class Vanagon::Platform::Solaris10

Public Class Methods

new(name) click to toggle source

Constructor. Sets up some defaults for the solaris 10 platform and calls the parent constructor

@param name [String] name of the platform @return [Vanagon::Platform::Solaris] the solaris 10 derived platform with the given name

Calls superclass method Vanagon::Platform::new
# File lib/vanagon/platform/solaris_10.rb, line 183
def initialize(name)
  @name = name
  @make = "/opt/csw/bin/gmake"
  @tar = "/usr/sfw/bin/gtar"
  @patch = "/usr/bin/gpatch"
  @sed = "/opt/csw/bin/gsed"
  @shasum = "/opt/csw/bin/shasum"
  # solaris 10
  @num_cores = "/usr/bin/kstat cpu_info | awk '{print $$1}' | grep '^core_id$$' | wc -l"
  super(name)
  if @architecture == "sparc"
    @platform_triple = "sparc-sun-solaris2.#{@os_version}"
  elsif @architecture == "i386"
    @platform_triple = "i386-pc-solaris2.#{@os_version}"
  end
end

Public Instance Methods

add_group(user) click to toggle source

Generate the scripts required to add a group to the package generated. This will also update the group if it has changed.

@param user [Vanagon::Common::User] the user to reference for the group @return [String] the commands required to add a group to the system

# File lib/vanagon/platform/solaris_10.rb, line 97
      def add_group(user)
        # NB: system users aren't supported on solaris 10
        return <<-HERE.undent
          if ! getent group '#{user.group}' > /dev/null 2>&1; then
            /usr/sbin/groupadd '#{user.group}'
          fi
        HERE
      end
add_user(user) click to toggle source

Generate the scripts required to add a user to the package generated. This will also update the user if it has changed.

@param user [Vanagon::Common::User] the user to create @return [String] the commands required to add a user to the system

# File lib/vanagon/platform/solaris_10.rb, line 111
      def add_user(user)
        # NB: system users aren't supported on solaris 10
        # Solaris 10 also doesn't support long flags
        cmd_args = ["'#{user.name}'"]
        cmd_args.unshift "-g '#{user.group}'" if user.group
        cmd_args.unshift "-d '#{user.homedir}'" if user.homedir
        if user.shell
          cmd_args.unshift "-s '#{user.shell}'"
        elsif user.is_system
          # Even though system users aren't a thing, we can still disable the shell
          cmd_args.unshift "-s '/usr/bin/false'"
        end

        user_args = cmd_args.join("\s")

        return <<-HERE.undent
          if getent passwd '#{user.name}' > /dev/null 2>&1; then
            /usr/sbin/usermod #{user_args}
          else
            /usr/sbin/useradd #{user_args}
          fi
        HERE
      end
generate_package(project) click to toggle source

The specific bits used to generate a solaris package for a given project

@param project [Vanagon::Project] project to build a solaris package of @return [Array] list of commands required to build a solaris package for the given project from a tarball

# File lib/vanagon/platform/solaris_10.rb, line 8
def generate_package(project) # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
  target_dir = project.repo ? output_dir(project.repo) : output_dir
  name_and_version = "#{project.name}-#{project.version}"
  pkg_name = package_name(project)

  # Generate list of dirs in the package and create an exlplicit search
  # string for AWK to use in order to explicitly define which directories
  # to put in to the prototype file. Note that the Regexp object was avoided
  # because the output from Regexp would create failures from AWK as the conversion
  # from a Regexp obj to a string is formatted in a sub-optimal way that would have
  # required more string manipulation anyway. the string should be formatted like so:
  #         && ($$3 ~ /directory\/regex.*/ || $$3 ~ /another\/directory\/regex.*/)
  # for as many iterations as there are directries in the package
  pkgdirs = project.get_root_directories.map { |dir| "#{dir.sub(/^\//, '').gsub(/([\/.])+/, '\\\\\1')}.*" }
  explicit_search_string = pkgdirs.map do |dir_regex|
    " $$3 ~ /#{dir_regex}/ "
  end.join("||")

  # Here we maintain backward compatibility with older vanagon versions
  # that did this by default.  This shim should get removed at some point
  # in favor of just letting the makefile deliver the bill-of-materials
  # to the correct directory. This shouldn't be required at all then.
  if project.bill_of_materials.nil?
    bom_install = [
      # Move bill-of-materials into a docdir
      "mkdir -p $(tempdir)/#{name_and_version}/usr/share/doc/#{project.name}",
      "mv $(tempdir)/#{name_and_version}/bill-of-materials $(tempdir)/#{name_and_version}/usr/share/doc/#{project.name}/bill-of-materials",
    ]
  else
    bom_install = []
  end

  [
    # Set up our needed directories
    "mkdir -p $(tempdir)/#{name_and_version}",
    "mkdir -p $(tempdir)/pkg",
    "mkdir -p output/#{target_dir}",

    # Unpack the project and stage the packaging artifacts
    "gunzip -c #{name_and_version}.tar.gz | '#{@tar}' -C '$(tempdir)' -xf -",

    bom_install,

    "cp -r packaging $(tempdir)/",

    # Here we are tweaking file/dir ownership and perms in the following ways
    # - All directories default to 0755 and root:sys
    # - All files default to root:sys
    # - The bin directory and all bin files are owned by root:bin instead of root:sys
    # - All files under lib are owned by root:bin instead of root:sys
    # - All .so files are owned by root:bin instead of root:sys
    # - Explicity only include directories in the package contents
    #   (this should exclude things like root/bin root/var and such)
    %((cd $(tempdir)/#{name_and_version}; pkgproto . | sort | awk ' \
      $$1 ~ /^d$$/ && (#{explicit_search_string}) {print "d",$$2,$$3,"0755 root sys";} \
      $$1 ~ /^s$$/ {print;} \
      $$1 ~ /^f$$/ {print "f",$$2,$$3,$$4,"root sys";} \
      $$1 !~ /^[dfs]$$/ {print;} ' | #{sed} \
         -e '/^[fd] [^ ]\\+ .*[/]s\\?bin[^ ]\\+/ {s/root sys$$/root bin/}' \
         -e '/^[fd] [^ ]\\+ .*[/]lib[/][^ ]\\+/ {s/root sys$$/root bin/}' \
         -e '/^[fd] [^ ]\\+ .*[/][^ ]\\+[.]so/ {s/root sys$$/root bin/}' >> ../packaging/proto)),
    %((cd $(tempdir); #{project.get_directories.map { |dir| "/opt/csw/bin/ggrep -q 'd none #{dir.path.sub(/^\//, '')}' packaging/proto || echo 'd none #{dir.path.sub(/^\//, '')} #{dir.mode || '0755'} #{dir.owner || 'root'} #{dir.group || 'sys'}' >> packaging/proto" }.join('; ')})),

    # Actually build the package
    "pkgmk -f $(tempdir)/packaging/proto -b $(tempdir)/#{name_and_version} -o -d $(tempdir)/pkg/",
    "pkgtrans -s $(tempdir)/pkg/ $(tempdir)/pkg/#{pkg_name.gsub(/\.gz$/, '')} #{project.name}",
    "gzip -c $(tempdir)/pkg/#{pkg_name.gsub(/\.gz$/, '')} > output/#{target_dir}/#{pkg_name}",
  ].flatten.compact
end
generate_packaging_artifacts(workdir, name, binding, project) click to toggle source

Method to generate the files required to build a solaris package for the project

@param workdir [String] working directory to stage the evaluated templates in @param name [String] name of the project @param binding [Binding] binding to use in evaluating the packaging templates @param project [Vanagon::Project] Vanagon::Project we are building for

# File lib/vanagon/platform/solaris_10.rb, line 84
def generate_packaging_artifacts(workdir, name, binding, project)
  ["pkginfo", "depend", "preinstall", "preremove", "postinstall", "proto"].each do |template|
    target_dir = File.join(workdir, 'packaging')
    FileUtils.mkdir_p(target_dir)
    erb_file(File.join(VANAGON_ROOT, "resources/solaris/10/#{template}.erb"), File.join(target_dir, template), false, { :binding => binding })
  end
end
install_build_dependencies(build_dependencies) click to toggle source

Because solaris has multiple terrible ways to install packages, we have this method which generates a shell script to be executed on the system which will install all of the build dependencies

@param build_dependencies [Array] list of all build dependencies to install @return [String] a command to install all of the build dependencies

# File lib/vanagon/platform/solaris_10.rb, line 149
def install_build_dependencies(build_dependencies) # rubocop:disable Metrics/AbcSize
  http = []
  pkgutil = []
  noasks = ["instance=overwrite", "partial=nocheck", "runlevel=nocheck", "idepend=nocheck", "rdepend=nocheck", "space=nocheck", "setuid=nocheck", "conflict=nocheck", "action=nocheck", "basedir=default"]
  noask_command = noasks.map { |noask| "echo '#{noask}' >> /var/tmp/noask" }.join('; ')

  build_dependencies.each do |build_dependency|
    if build_dependency =~ /^http.*\.gz/
      # Fetch, unpack, install...this assumes curl is present.
      package = build_dependency.sub(/^http.*\//, '')
      http << "tmpdir=$(#{mktemp}); (cd ${tmpdir} && curl --silent --show-error --fail -O #{build_dependency} && gunzip -c #{package} | pkgadd -d /dev/stdin -a /var/tmp/noask all)"
    else
      # Opencsw dependencies. At this point we assume that pkgutil is installed.
      pkgutil << build_dependency
    end
  end

  command = ''
  unless pkgutil.empty?
    command << "/opt/csw/bin/pkgutil -y -i #{pkgutil.join("\s")}; "
  end

  unless http.empty?
    command << "echo -n > /var/tmp/noask; #{noask_command}; "
    command << http.join('; ')
  end

  command
end
package_name(project) click to toggle source

Method to derive the package name for the project

@param project [Vanagon::Project] project to name @return [String] name of the solaris package for this project

# File lib/vanagon/platform/solaris_10.rb, line 139
def package_name(project)
  "#{project.name}-#{project.version}-#{project.release}.#{@architecture}.pkg.gz"
end