Class: Vanagon::Platform::Solaris10

Inherits:
Vanagon::Platform show all
Defined in:
lib/vanagon/platform/solaris_10.rb

Constant Summary

Constants inherited from Vanagon::Platform

PLATFORM_REGEX, VERSION_REGEX

Instance Attribute Summary

Attributes inherited from Vanagon::Platform

#abs_resource_name, #architecture, #aws_ami, #aws_instance_type, #aws_key, #aws_key_name, #aws_region, #aws_shutdown_behavior, #aws_subnet_id, #aws_user_data, #aws_vpc_id, #brew, #build_dependencies, #build_hosts, #cflags, #codename, #copy, #cross_compiled, #defaultdir, #dist, #docker_image, #docker_run_args, #environment, #find, #install, #ldflags, #make, #mktemp, #name, #num_cores, #os_name, #os_version, #output_dir, #package_type, #patch, #platform_triple, #provisioning, #rpmbuild, #sed, #servicedir, #servicetype, #servicetypes, #settings, #shasum, #shell, #sort, #source_output_dir, #ssh_port, #tar, #target_user, #use_docker_exec, #valid_operators, #vmpooler_template

Instance Method Summary collapse

Methods inherited from Vanagon::Platform

#[], #add_build_repository, #generate_compiled_archive, #get_service_dir, #get_service_types, #is_aix?, #is_amazon?, #is_cisco_wrlinux?, #is_cross_compiled?, #is_cross_compiled_linux?, #is_deb?, #is_debian?, #is_el8?, #is_el?, #is_eos?, #is_fedora?, #is_fips?, #is_huaweios?, #is_linux?, #is_macos?, #is_osx?, #is_rpm?, #is_sles?, #is_solaris?, #is_ubuntu?, #is_unix?, #is_windows?, load_platform, #package_override, #provision_with, #validate_operator, #version_munger

Methods included from HashableAttributes

#to_hash, #to_json

Methods included from Utilities

#erb_file, #erb_string, #ex, #find_program_on_path, #get_md5sum, #get_sum, #http_request, #http_request_code, #http_request_generic, #local_command, #remote_ssh_command, #retry_with_timeout, #rsync_from, #rsync_to, #ssh_command

Constructor Details

#initialize(name) ⇒ Vanagon::Platform::Solaris

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

Parameters:

  • name (String)

    name of the platform



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# 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

Instance Method Details

#add_group(user) ⇒ String

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

Parameters:

Returns:

  • (String)

    the commands required to add a group to the system



97
98
99
100
101
102
103
104
# 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) ⇒ String

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

Parameters:

Returns:

  • (String)

    the commands required to add a user to the system



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# 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) ⇒ Array

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

Parameters:

Returns:

  • (Array)

    list of commands required to build a solaris package for the given project from a tarball



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# 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) ⇒ Object

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

Parameters:

  • workdir (String)

    working directory to stage the evaluated templates in

  • name (String)

    name of the project

  • binding (Binding)

    binding to use in evaluating the packaging templates

  • project (Vanagon::Project)

    Vanagon::Project we are building for



84
85
86
87
88
89
90
# 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) ⇒ String

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

Parameters:

  • build_dependencies (Array)

    list of all build dependencies to install

Returns:

  • (String)

    a command to install all of the build dependencies



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# 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) ⇒ String

Method to derive the package name for the project

Parameters:

Returns:

  • (String)

    name of the solaris package for this project



139
140
141
# File 'lib/vanagon/platform/solaris_10.rb', line 139

def package_name(project)
  "#{project.name}-#{project.version}-#{project.release}.#{@architecture}.pkg.gz"
end