Commit 07400263 authored by Seth Chisamore's avatar Seth Chisamore

Slight refactor and test coverage for Solaris packager

parent 798a0074
......@@ -14,24 +14,27 @@
# limitations under the License.
#
require 'socket'
module Omnibus
class Packager::Solaris < Packager::Base
# @return [Hash]
SCRIPT_MAP = {
# Default Omnibus naming
postinst: 'postinstall',
postrm: 'postremove',
# Default Solaris naming
postinstall: 'postinstall',
postremove: 'postremove',
}.freeze
id :solaris
build do
shellout! "cd #{install_dirname} && find #{install_basename} -print > #{staging_dir_path('files')}"
write_prototype_content
write_pkginfo_content
copy_file("#{project.package_scripts_path}/postinst", staging_dir_path('postinstall'))
copy_file("#{project.package_scripts_path}/postrm", staging_dir_path('postremove'))
shellout! "pkgmk -o -r #{install_dirname} -d #{staging_dir} -f #{staging_dir_path('Prototype')}"
shellout! "pkgchk -vd #{staging_dir} #{project.package_name}"
shellout! "pkgtrans #{staging_dir} #{package_path} #{project.package_name}"
write_scripts
write_prototype_file
write_pkginfo_file
create_solaris_file
end
# @see Base#package_name
......@@ -50,24 +53,42 @@ module Omnibus
def install_basename
File.basename(project.install_dir)
end
def staging_dir_path(file_name)
File.join(staging_dir, file_name)
end
#
# Copy all scripts in {Project#package_scripts_path} to the control
# directory of this repo.
#
# @return [void]
#
def write_scripts
SCRIPT_MAP.each do |source, destination|
source_path = File.join(project.package_scripts_path, source.to_s)
if File.file?(source_path)
destination_path = staging_dir_path(destination)
log.debug(log_key) { "Adding script `#{source}' to `#{destination_path}'" }
copy_file(source_path, destination_path)
end
end
end
#
# Generate a Prototype file for solaris build
#
def write_prototype_content
prototype_content = <<-EOF.gsub(/^ {8}/, '')
i pkginfo
i postinstall
i postremove
EOF
def write_prototype_file
shellout! "cd #{install_dirname} && find #{install_basename} -print > #{staging_dir_path('files')}"
# generate list of control files
File.open staging_dir_path('Prototype'), 'w+' do |f|
f.write prototype_content
f.write <<-EOF.gsub(/^ {10}/, '')
i pkginfo
i postinstall
i postremove
EOF
end
# generate the prototype's file list
......@@ -80,7 +101,10 @@ module Omnibus
#
# Generate a pkginfo file for solaris build
#
def write_pkginfo_content
def write_pkginfo_file
hostname = Socket.gethostname
# http://docs.oracle.com/cd/E19683-01/816-0219/6m6njqbat/index.html
pkginfo_content = <<-EOF.gsub(/^ {8}/, '')
CLASSES=none
TZ=PST
......@@ -94,13 +118,24 @@ module Omnibus
DESC=#{project.description}
VENDOR=#{project.maintainer}
EMAIL=#{project.maintainer}
PSTAMP=#{`hostname`.chomp + Time.now.utc.iso8601}
PSTAMP=#{hostname}#{Time.now.utc.iso8601}
EOF
File.open staging_dir_path('pkginfo'), 'w+' do |f|
f.write pkginfo_content
end
end
#
# Generate the Solaris file using +pkg*+.
#
# @return [void]
#
def create_solaris_file
shellout! "pkgmk -o -r #{install_dirname} -d #{staging_dir} -f #{staging_dir_path('Prototype')}"
shellout! "pkgchk -vd #{staging_dir} #{project.package_name}"
shellout! "pkgtrans #{staging_dir} #{package_path} #{project.package_name}"
end
#
# The architecture for this Solaris package.
#
......
require 'spec_helper'
module Omnibus
describe Packager::Solaris do
let(:project) do
Project.new.tap do |project|
project.name('project')
project.homepage('https://example.com')
project.install_dir('/opt/project')
project.build_version('1.2.3')
project.build_iteration('1')
project.maintainer('Chef Software')
end
end
subject { described_class.new(project) }
let(:project_root) { File.join(tmp_path, 'project/root') }
let(:package_dir) { File.join(tmp_path, 'package/dir') }
let(:staging_dir) { File.join(tmp_path, 'staging/dir') }
let(:architecture) { 'i86pc' }
before do
# This is here to allow this unit test to run on windows.
allow(File).to receive(:expand_path).and_wrap_original do |m, *args|
m.call(*args).sub(/^[A-Za-z]:/, '')
end
Config.project_root(project_root)
Config.package_dir(package_dir)
allow(subject).to receive(:staging_dir).and_return(staging_dir)
create_directory(staging_dir)
stub_ohai(platform: 'solaris2', version: '5.11') do |data|
data['kernel']['machine'] = architecture
end
end
describe '#id' do
it 'is :solaris' do
expect(subject.id).to eq(:solaris)
end
end
describe '#package_name' do
it 'includes the name, version, iteration and architecture' do
expect(subject.package_name).to eq('project-1.2.3-1.i386.solaris')
end
end
describe '#pkgmk_version' do
it 'includes the version and iteration' do
expect(subject.pkgmk_version).to eq('1.2.3-1')
end
end
describe '#install_dirname' do
it 'returns the parent directory' do
expect(subject.install_dirname).to eq('/opt')
end
end
describe '#install_basename' do
it 'name of the install directory' do
expect(subject.install_basename).to eq('project')
end
end
describe '#write_scripts' do
context 'when scripts are given' do
let(:scripts) { %w( postinstall postremove ) }
before do
scripts.each do |script_name|
create_file("#{project_root}/package-scripts/project/#{script_name}") do
"Contents of #{script_name}"
end
end
end
it 'writes the scripts into scripts staging dir' do
subject.write_scripts
scripts.each do |script_name|
script_file = "#{staging_dir}/#{script_name}"
contents = File.read(script_file)
expect(contents).to include("Contents of #{script_name}")
end
end
end
context 'when scripts with default omnibus naming are given' do
let(:default_scripts) { %w( postinst postrm ) }
before do
default_scripts.each do |script_name|
create_file("#{project_root}/package-scripts/project/#{script_name}") do
"Contents of #{script_name}"
end
end
end
it 'writes the scripts into scripts staging dir' do
subject.write_scripts
default_scripts.each do |script_name|
mapped_name = Packager::Solaris::SCRIPT_MAP[script_name.to_sym]
script_file = "#{staging_dir}/#{mapped_name}"
contents = File.read(script_file)
expect(contents).to include("Contents of #{script_name}")
end
end
end
end
describe '#write_prototype_file' do
let(:prototype_file) { File.join(staging_dir, 'Prototype') }
before do
allow(subject).to receive(:shellout!)
end
it 'creates the prototype file' do
subject.write_prototype_file
contents = File.read(prototype_file)
expect(contents).to include(
<<-EOH.gsub(/^ {12}/, '')
i pkginfo
i postinstall
i postremove
EOH
)
end
it 'uses the correct commands' do
expect(subject).to receive(:shellout!)
.with("cd /opt && find project -print > #{File.join(staging_dir, 'files')}")
expect(subject).to receive(:shellout!)
.with("cd /opt && pkgproto < #{File.join(staging_dir, 'files')} > #{File.join(staging_dir, 'Prototype.files')}")
expect(subject).to receive(:shellout!)
.with("awk '{ $5 = \"root\"; $6 = \"root\"; print }' < #{File.join(staging_dir, 'Prototype.files')} >> #{File.join(staging_dir, 'Prototype')}")
subject.write_prototype_file
end
end
describe '#create_solaris_file' do
it 'uses the correct commands' do
expect(subject).to receive(:shellout!)
.with("pkgmk -o -r /opt -d #{staging_dir} -f #{File.join(staging_dir, 'Prototype')}")
expect(subject).to receive(:shellout!)
.with("pkgchk -vd #{staging_dir} project")
expect(subject).to receive(:shellout!)
.with("pkgtrans #{staging_dir} #{File.join(package_dir, 'project-1.2.3-1.i386.solaris')} project")
subject.create_solaris_file
end
end
describe '#write_pkginfo_file' do
let(:pkginfo_file) { File.join(staging_dir, 'pkginfo') }
let(:hostname) { Socket.gethostname }
let(:now) { Time.now }
it 'generates the file' do
subject.write_pkginfo_file
expect(pkginfo_file).to be_a_file
end
it 'has the correct content' do
allow(Time).to receive(:now).and_return(now)
subject.write_pkginfo_file
contents = File.read(pkginfo_file)
expect(contents).to include("CLASSES=none")
expect(contents).to include("TZ=PST")
expect(contents).to include("PATH=/sbin:/usr/sbin:/usr/bin:/usr/sadm/install/bin")
expect(contents).to include("BASEDIR=/opt")
expect(contents).to include("PKG=project")
expect(contents).to include("NAME=project")
expect(contents).to include("ARCH=i386")
expect(contents).to include("VERSION=1.2.3-1")
expect(contents).to include("CATEGORY=application")
expect(contents).to include("DESC=")
expect(contents).to include("VENDOR=Chef Software")
expect(contents).to include("EMAIL=Chef Software")
expect(contents).to include("PSTAMP=#{hostname}#{now.utc.iso8601}")
end
end
describe '#create_solaris_file' do
before do
allow(subject).to receive(:shellout!)
allow(Dir).to receive(:chdir) { |_, &b| b.call }
end
it 'uses the correct commands' do
expect(subject).to receive(:shellout!)
.with("pkgmk -o -r /opt -d #{staging_dir} -f #{File.join(staging_dir, 'Prototype')}")
expect(subject).to receive(:shellout!)
.with("pkgchk -vd #{staging_dir} project")
expect(subject).to receive(:shellout!)
.with("pkgtrans #{staging_dir} #{File.join(package_dir, 'project-1.2.3-1.i386.solaris')} project")
subject.create_solaris_file
end
end
describe '#safe_architecture' do
context 'the architecture is Intel-based' do
let(:architecture) { 'i86pc' }
it 'returns `i386`' do
expect(subject.safe_architecture).to eq('i386')
end
end
context 'the architecture is SPARC-based' do
let(:architecture) { 'sun4v' }
it 'returns `sparc`' do
expect(subject.safe_architecture).to eq('sparc')
end
end
context 'anything else' do
let(:architecture) { 'FOO' }
it 'returns the value from Ohai' do
expect(subject.safe_architecture).to eq('FOO')
end
end
end
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment