Module: Jamf::Composer
- Defined in:
- lib/jamf/composer.rb
Overview
This module provides two methods for building very simple Casper-happy .pkg and .dmg packages for deployment.
Unlike Composer.app from JAMF, this module currently doesn’t offer a way to do a before/after disk scan and use the differences to build the root folder from which the package is built. Nor does the module support editing the pre/post install scripts in .pkgs.
The ‘root folder’, a folder representing the root filesystem of the target machine where the package will be installed, must already exist and be fully populated and with correct permissions.
Constant Summary collapse
- PKG_UTIL =
the apple pkgutil tool
Pathname.new '/usr/sbin/pkgutil'
- PKGBUILD =
The location of the cli tool for making .pkgs
Pathname.new '/usr/bin/pkgbuild'
- PKG_BUNDLE_ID_PFX =
the default bundle identifier prefix for pkgs
'ruby-jss-composer'.freeze
- HDI_UTIL =
Apple’s hdiutil for making dmgs
'/usr/bin/hdiutil'.freeze
- DEFAULT_OUT_DIR =
Where to save the output ?
Pathname.new '/Users/Shared'
Class Method Summary collapse
-
.mk_dmg(name, root, out_dir = DEFAULT_OUT_DIR) ⇒ Pathname
Make a casper-happy .dmg out of a root folder, permissions are assumed to be correct.
-
.mk_pkg(name, version, root, **opts) ⇒ Pathname
Make a casper-happy .pkg out of a root folder, permissions are assumed to be correct.
Class Method Details
.mk_dmg(name, root, out_dir = DEFAULT_OUT_DIR) ⇒ Pathname
Make a casper-happy .dmg out of a root folder, permissions are assumed to be correct.
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/jamf/composer.rb', line 172 def self.mk_dmg(name, root, out_dir = DEFAULT_OUT_DIR) dmg_filename = "#{name}.dmg" dmg_vol = name dmg_out = Pathname.new "#{out_dir}/#{dmg_filename}" if dmg_out.exist? mv_to = dmg_out.dirname + "#{dmg_out.basename}.#{Time.now.strftime('%Y%m%d%H%M%S')}" dmg_out.rename mv_to end # if dmg out exist ### TODO - this may need to be sudo'd to handle proper internal permissions. system "#{HDI_UTIL} create -volname '#{dmg_vol}' -scrub -srcfolder '#{root}' '#{dmg_out}'" raise 'There was an error building the .dmg' unless $?.exitstatus.zero? Pathname.new dmg_out end |
.mk_pkg(name, version, root, **opts) ⇒ Pathname
Make a casper-happy .pkg out of a root folder, permissions are assumed to be correct.
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/jamf/composer.rb', line 95 def self.mk_pkg(name, version, root, **opts) raise NoSuchItemError, "Missing pkgbuild tool. Please make sure you're running 10.8 or later." unless PKGBUILD.executable? opts[:out_dir] ||= DEFAULT_OUT_DIR opts[:bundle_id_prefix] ||= PKG_BUNDLE_ID_PFX pkg_filename = name.end_with?('.pkg') ? name : name + '.pkg' pkg_id = opts[:pkg_id] pkg_id ||= opts[:bundle_id_prefix] + '.' + name pkg_out = "#{opts[:out_dir]}/#{pkg_filename}" pkg_ownership = opts[:preserve_ownership] ? 'preserve' : 'recommended' if opts[:signing_identity] signing = "--sign '#{opts[:signing_identity]}'" signing << " #{opts[:signing_options]}" if opts[:signing_options] else signing = '' end # if opts[:signing_identity] ### first, run 'analyze' to get a 'component plist' in which we can change some settings ### for any bundles in the root (bundles like .apps, frameworks, plugins, etc..) ### ### we edit the settings thus: ### BundleOverwriteAction = upgrade, totally replace any version current on disk ### BundleIsVersionChecked = false, allow us to install regardless of what version is currently installed ### BundleIsRelocatable = false, if there's a version of this in some other location, Do Not move this one there after installation ### BundleHasStrictIdentifier = false, don't care if there's something at the install path with a different bundle id. ### ### In other words, just install the thing! ### (see 'man pkgbuild' for more info) ### ### comp_plist_out = Pathname.new "/tmp/#{PKG_BUNDLE_ID_PFX}-#{pkg_filename}.plist" system "#{PKGBUILD} --analyze --root '#{root}' '#{comp_plist_out}'" comp_plist = JSS.parse_plist comp_plist_out ### if the plist is empty, there are no bundles in the pkg if comp_plist[0].nil? comp_plist_arg = '' else ### otherwise, edit the bundle dictionaries comp_plist.each do |bndl| bndl.delete 'ChildBundles' if bndl['ChildBundles'] bndl['BundleOverwriteAction'] = 'upgrade' bndl['BundleIsVersionChecked'] = false bndl['BundleIsRelocatable'] = false bndl['BundleHasStrictIdentifier'] = false end ### write out the edits comp_plist_out.open('w') { |f| f.write JSS.xml_plist_from(comp_plist) } comp_plist_arg = "--component-plist '#{comp_plist_out}'" end ### now build the pkg begin it_built = system "#{PKGBUILD} --identifier '#{pkg_id}' --version '#{version}' --ownership #{pkg_ownership} --install-location / --root '#{root}' #{signing} #{comp_plist_arg} '#{pkg_out}'" raise 'There was an error building the .pkg' unless it_built ensure comp_plist_out.delete if comp_plist_out.exist? end Pathname.new pkg_out end |