Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: (SIMP-9753) Add legacy/productmd treeinfo parser #166

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
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
87 changes: 87 additions & 0 deletions lib/simp/build/iso/tree_info_reader.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
require 'puppet'
require 'puppet/util/inifile'

module Simp; end
module Simp::Build; end
module Simp::Build::Iso
# Parses data from .treeinfo files. Supports pre-productmd and treeinfo 1.x.
class TreeInfoReader
PRE_PRODUCTMD_TREEINFO_VERSION = '0.0-pre-productmd'

def initialize(treeinfo_file, target_arch: 'x86_64')
File.exist?( treeinfo_file ) or fail("File does not exist: '#{treeinfo_file}'")

@target_arch = target_arch
@file = treeinfo_file
@ini = Puppet::Util::IniConfig::PhysicalFile.new(@file)
@ini.read
@treeinfo_version = treeinfo_version
@treeinfo_maj_version = treeinfo_version.split('.').first.to_i
end

# release version, for example: "21", "7.0", "2.1"
# @return [String]
def release_version
@treeinfo_maj_version > 0 ? section('release')['version'] : section('general')['version']
Copy link
Contributor

@lnemsick-simp lnemsick-simp Jun 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if section() returns nil? This code does not handle that error case in a fashion that an end-user would understand. In other words, the error message from operating on a nil object would be incomprehensible to the end user.

end

# release short name, for example: "Fedora", "RHEL", "CentOS"
def release_short_name
# @return [String]
@treeinfo_maj_version > 0 ? section('release')['short'] : section('general')['family']
end

# tree architecture, for example x86_64
# @return [String]
def tree_arch
@treeinfo_maj_version > 0 ? section('tree')['arch'] : section('general')['arch']
end

# @return [Hash] collection of section hashes (k = name, v = k/v pairs)
def sections
@ini.sections.map{|s| [s.name, section(s.name)] }.to_h
end

# @param [String] name of ini section to read
# @return [Hash] k/v pairs from ini [section] if it exists
# @return [nil] if ini [section] doesn't exist
def section(name)
s = @ini.get_section(name) || return
s.entries.grep(Array).to_h
end

# @return [Hash] data for all variants in [tree] section (treeinfo 1.x)
def variants
variant_uids = section('tree')['variants'].to_s.split(',')
variant_uids.map { |uid| section("variant-#{uid}") }
end

# Determine .treeinfo version string
# @return [String] if productmd format, treeinfo version
# @return [String] if pre-productmd, PRE_PRODUCTMD_TREEINFO_VERSION
# @raise [RuntimeError] if not in treeinfo format
# @raise [RuntimeError] if productmd treeinfo version is higher than 1.x
def treeinfo_version
version = ''
header = section('header')
if header
# productmd .treeinfo format (EL8+)
version = header['version']
unless version.to_s.split('.').first == '1'
fail "ERROR: Unsupported productmd .treeinfo version: '#{version}': '#{@file}'"
end
warn "Detected productmd .treeinfo, version '#{verison}'" if @verbose
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why does this code send debug messages to $stderr?

Copy link
Contributor

@lnemsick-simp lnemsick-simp Jun 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does @verbose get enabled?

else
# pre-productmd .treeinfo format (EL7)
unless section('general')
fail "ERROR: Cannot parse: Not a pre-prouct .treeinfo format: '#{@file}' !"
end
version = PRE_PRODUCTMD_TREEINFO_VERSION
warn 'Detected pre-productmd .treeinfo format (<= EL7)' if @verbose
end
version
end

end
end

21 changes: 21 additions & 0 deletions spec/lib/simp/build/iso/files/treeinfo.CentOS7.0.2009-x86_64.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[general]
name = CentOS-7
family = CentOS
timestamp = 1603729576.26
variant =
version = 7
packagedir =
arch = x86_64

[stage2]
mainimage = LiveOS/squashfs.img

[images-x86_64]
kernel = images/pxeboot/vmlinuz
initrd = images/pxeboot/initrd.img
boot.iso = images/boot.iso

[images-xen]
kernel = images/pxeboot/vmlinuz
initrd = images/pxeboot/initrd.img

67 changes: 67 additions & 0 deletions spec/lib/simp/build/iso/files/treeinfo.CentOS8.3.2011-x86_64.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
[checksums]
images/efiboot.img = sha256:3b400994d93956d1a3c59d3c7fbefe1a73e287b2b2b0dedea7d16ef5042cb3c9
images/install.img = sha256:60115a4c57495f4ae4fa2a8b169523267b07b47b8333c9189a4586f54a8cc29f
images/pxeboot/initrd.img = sha256:31cb34ff174707a7846483a81579a124c0beea4cc1030f1884103a9a0622de47
images/pxeboot/vmlinuz = sha256:40fa3404fa9686065d95b9dc2caa97a08680b7e8566baa2c3f09ff48fd660d48

[general]
; WARNING.0 = This section provides compatibility with pre-productmd treeinfos.
; WARNING.1 = Read productmd documentation for details about new format.
arch = x86_64
family = CentOS Linux
name = CentOS Linux 8
packagedir = AppStream/Packages
platforms = x86_64,xen
repository = AppStream
timestamp = 1605735523
variant = AppStream
variants = AppStream,BaseOS
version = 8

[header]
type = productmd.treeinfo
version = 1.2

[images-x86_64]
efiboot.img = images/efiboot.img
initrd = images/pxeboot/initrd.img
kernel = images/pxeboot/vmlinuz

[images-xen]
initrd = images/pxeboot/initrd.img
kernel = images/pxeboot/vmlinuz

[media]
discnum = 1
totaldiscs = 1

[release]
name = CentOS Linux
short = CentOS
version = 8

[stage2]
mainimage = images/install.img

[tree]
arch = x86_64
build_timestamp = 1605735523
platforms = x86_64,xen
variants = AppStream,BaseOS

[variant-AppStream]
id = AppStream
name = AppStream
packages = AppStream/Packages
repository = AppStream
type = variant
uid = AppStream

[variant-BaseOS]
id = BaseOS
name = BaseOS
packages = BaseOS/Packages
repository = BaseOS
type = variant
uid = BaseOS

56 changes: 56 additions & 0 deletions spec/lib/simp/build/iso/files/treeinfo.Fedora-Server-21-x86_64.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
[checksums]
images/boot.iso = sha256:56af126a50c227d779a200b414f68ea7bcf58e21c8035500cd21ba164f85b9b4
images/efiboot.img = sha256:de48c8b25f03861c00c355ccf78108159f1f2aa63d0d63f92815146c24f60164
images/macboot.img = sha256:da76ff5490b4ae7e123f19b8f4b36efd6b7c435073551978d50c5181852a87f5
images/product.img = sha256:ffce14a7a95be20b36f302cb0698be8c19fda798807d3d63a491d6f7c1b23b5b
images/pxeboot/initrd.img = sha256:aadebd07c4c0f19304f0df7535a8f4218e5141602f95adec08ad1e22ff1e2d43
images/pxeboot/upgrade.img = sha256:224d098fb3903583b491692c5e0e1d20ea840d51f4da671ced97d422402bbf1c
images/pxeboot/vmlinuz = sha256:81c28a439f1d23786057d3b57db66e00b2b1a39b64d54de1a90cf2617e53c986
repodata/repomd.xml = sha256:3af1609aa27949bf1e02e9204a7d4da7efee470063dadbc3ea0be3ef7f1f4d14

[general]
arch = x86_64
family = Fedora
name = Fedora 21
packagedir = Packages
platforms = x86_64,xen
repository = .
timestamp = 1417653911
variant = Server
version = 21

[header]
version = 1.0

[images-x86_64]
boot.iso = images/boot.iso
initrd = images/pxeboot/initrd.img
kernel = images/pxeboot/vmlinuz
upgrade = images/pxeboot/upgrade.img

[images-xen]
initrd = images/pxeboot/initrd.img
kernel = images/pxeboot/vmlinuz
upgrade = images/pxeboot/upgrade.img

[release]
name = Fedora
short = Fedora
version = 21

[stage2]
mainimage = LiveOS/squashfs.img

[tree]
arch = x86_64
build_timestamp = 1417653911
platforms = x86_64,xen
variants = Server

[variant-Server]
id = Server
name = Server
packages = Packages
repository = .
type = variant
uid = Server
65 changes: 65 additions & 0 deletions spec/lib/simp/build/iso/tree_info_reader_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
require 'simp/build/iso/tree_info_reader'
require 'spec_helper'

TREEINFO_FIXTURE_FILES_DIR = File.join(__dir__, 'files')

TREEINFO_EXPECTATIONS = {
'treeinfo.CentOS7.0.2009-x86_64.ini' => {
'short' => 'CentOS',
'version' => '7',
'arch' => 'x86_64',
},
'treeinfo.CentOS8.3.2011-x86_64.ini' => {
'short' => 'CentOS',
'version' => '8',
'arch' => 'x86_64',
},
'treeinfo.Fedora-Server-21-x86_64.ini' => {
'short' => 'Fedora',
'version' => '21',
'arch' => 'x86_64',
},

}

FIXTURE_FILES = TREEINFO_EXPECTATIONS.map do |k,v|
File.join( TREEINFO_FIXTURE_FILES_DIR, k )
end

describe Simp::Build::Iso::TreeInfoReader do
let(:files_dir) { TREEINFO_FIXTURE_FILES_DIR }

FIXTURE_FILES.each do |treeinfo_file|
context "using .treeinfo data from '#{File.basename(treeinfo_file)}'" do
let(:ini_file){ treeinfo_file }
subject(:tree_info_reader){ Simp::Build::Iso::TreeInfoReader.new(ini_file) }

describe '#initialize' do
it 'succeeds with a valid .treeinfo file' do
expect{ tree_info_reader }.to_not raise_error
end
end

describe '#release_short_name' do
let(:expected_value){ TREEINFO_EXPECTATIONS[File.basename(ini_file)]['short'] }
it 'returns the expected name' do
expect( tree_info_reader.release_short_name ).to eq expected_value
end
end

describe '#release_version' do
let(:expected_value){ TREEINFO_EXPECTATIONS[File.basename(ini_file)]['version'] }
it 'returns the expected version' do
expect( tree_info_reader.release_version ).to eq expected_value
end
end

describe '#tree_arch' do
let(:expected_value){ TREEINFO_EXPECTATIONS[File.basename(ini_file)]['arch'] }
it 'returns the expected arch' do
expect( tree_info_reader.tree_arch ).to eq expected_value
end
end
end
end
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where are the tests for the error cases (e.g., invalid or unsupported treeinfo version)?