vanagon 0.3.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +13 -0
  3. data/README.md +175 -0
  4. data/bin/build +33 -0
  5. data/bin/devkit +22 -0
  6. data/bin/repo +26 -0
  7. data/bin/ship +15 -0
  8. data/lib/vanagon.rb +8 -0
  9. data/lib/vanagon/common.rb +2 -0
  10. data/lib/vanagon/common/pathname.rb +87 -0
  11. data/lib/vanagon/common/user.rb +25 -0
  12. data/lib/vanagon/component.rb +157 -0
  13. data/lib/vanagon/component/dsl.rb +307 -0
  14. data/lib/vanagon/component/source.rb +66 -0
  15. data/lib/vanagon/component/source/git.rb +60 -0
  16. data/lib/vanagon/component/source/http.rb +158 -0
  17. data/lib/vanagon/driver.rb +112 -0
  18. data/lib/vanagon/engine/base.rb +82 -0
  19. data/lib/vanagon/engine/docker.rb +40 -0
  20. data/lib/vanagon/engine/local.rb +40 -0
  21. data/lib/vanagon/engine/pooler.rb +85 -0
  22. data/lib/vanagon/errors.rb +28 -0
  23. data/lib/vanagon/extensions/string.rb +11 -0
  24. data/lib/vanagon/optparse.rb +62 -0
  25. data/lib/vanagon/platform.rb +245 -0
  26. data/lib/vanagon/platform/deb.rb +71 -0
  27. data/lib/vanagon/platform/dsl.rb +293 -0
  28. data/lib/vanagon/platform/osx.rb +100 -0
  29. data/lib/vanagon/platform/rpm.rb +76 -0
  30. data/lib/vanagon/platform/rpm/wrl.rb +39 -0
  31. data/lib/vanagon/platform/solaris_10.rb +182 -0
  32. data/lib/vanagon/platform/solaris_11.rb +138 -0
  33. data/lib/vanagon/platform/swix.rb +35 -0
  34. data/lib/vanagon/project.rb +251 -0
  35. data/lib/vanagon/project/dsl.rb +218 -0
  36. data/lib/vanagon/utilities.rb +299 -0
  37. data/spec/fixures/component/invalid-test-fixture.json +3 -0
  38. data/spec/fixures/component/mcollective.service +1 -0
  39. data/spec/fixures/component/test-fixture.json +4 -0
  40. data/spec/lib/vanagon/common/pathname_spec.rb +103 -0
  41. data/spec/lib/vanagon/common/user_spec.rb +36 -0
  42. data/spec/lib/vanagon/component/dsl_spec.rb +443 -0
  43. data/spec/lib/vanagon/component/source/git_spec.rb +19 -0
  44. data/spec/lib/vanagon/component/source/http_spec.rb +43 -0
  45. data/spec/lib/vanagon/component/source_spec.rb +99 -0
  46. data/spec/lib/vanagon/component_spec.rb +22 -0
  47. data/spec/lib/vanagon/engine/base_spec.rb +40 -0
  48. data/spec/lib/vanagon/engine/docker_spec.rb +40 -0
  49. data/spec/lib/vanagon/engine/pooler_spec.rb +54 -0
  50. data/spec/lib/vanagon/platform/deb_spec.rb +60 -0
  51. data/spec/lib/vanagon/platform/dsl_spec.rb +128 -0
  52. data/spec/lib/vanagon/platform/rpm_spec.rb +41 -0
  53. data/spec/lib/vanagon/platform/solaris_11_spec.rb +44 -0
  54. data/spec/lib/vanagon/platform_spec.rb +53 -0
  55. data/spec/lib/vanagon/project/dsl_spec.rb +203 -0
  56. data/spec/lib/vanagon/project_spec.rb +44 -0
  57. data/spec/lib/vanagon/utilities_spec.rb +140 -0
  58. data/templates/Makefile.erb +116 -0
  59. data/templates/deb/changelog.erb +5 -0
  60. data/templates/deb/conffiles.erb +3 -0
  61. data/templates/deb/control.erb +21 -0
  62. data/templates/deb/dirs.erb +3 -0
  63. data/templates/deb/docs.erb +1 -0
  64. data/templates/deb/install.erb +3 -0
  65. data/templates/deb/postinst.erb +46 -0
  66. data/templates/deb/postrm.erb +15 -0
  67. data/templates/deb/prerm.erb +17 -0
  68. data/templates/deb/rules.erb +25 -0
  69. data/templates/osx/postinstall.erb +24 -0
  70. data/templates/osx/preinstall.erb +19 -0
  71. data/templates/osx/project-installer.xml.erb +19 -0
  72. data/templates/rpm/project.spec.erb +217 -0
  73. data/templates/solaris/10/depend.erb +3 -0
  74. data/templates/solaris/10/pkginfo.erb +13 -0
  75. data/templates/solaris/10/postinstall.erb +37 -0
  76. data/templates/solaris/10/preinstall.erb +7 -0
  77. data/templates/solaris/10/preremove.erb +6 -0
  78. data/templates/solaris/10/proto.erb +5 -0
  79. data/templates/solaris/11/p5m.erb +73 -0
  80. metadata +172 -0
@@ -0,0 +1,100 @@
1
+ class Vanagon
2
+ class Platform
3
+ class OSX < Vanagon::Platform
4
+ # The specific bits used to generate a osx package for a given project
5
+ #
6
+ # @param project [Vanagon::Project] project to build a osx package of
7
+ # @return [Array] list of commands required to build a osx package for the given project from a tarball
8
+ def generate_package(project)
9
+ target_dir = project.repo ? output_dir(project.repo) : output_dir
10
+ # Setup build directories
11
+ ["bash -c 'mkdir -p $(tempdir)/osx/build/{dmg,pkg,scripts,resources,root,payload,plugins}'",
12
+ "mkdir -p $(tempdir)/osx/build/root/#{project.name}-#{project.version}",
13
+ # Grab distribution xml, scripts and other external resources
14
+ "cp #{project.name}-installer.xml $(tempdir)/osx/build/",
15
+ "cp scripts/* $(tempdir)/osx/build/scripts/",
16
+ "if [ -d resources/osx/productbuild ] ; then cp -r resources/osx/productbuild/* $(tempdir)/osx/build/; fi",
17
+ # Unpack the project
18
+ "gunzip -c #{project.name}-#{project.version}.tar.gz | '#{@tar}' -C '$(tempdir)/osx/build/root/#{project.name}-#{project.version}' --strip-components 1 -xf -",
19
+
20
+ # Move bill-of-materials into a docdir
21
+ "mkdir -p $(tempdir)/osx/build/root/#{project.name}-#{project.version}/usr/local/share/doc/#{project.name}",
22
+ "mv $(tempdir)/osx/build/root/#{project.name}-#{project.version}/bill-of-materials $(tempdir)/osx/build/root/#{project.name}-#{project.version}/usr/local/share/doc/#{project.name}/bill-of-materials",
23
+
24
+ # Package the project
25
+ "(cd $(tempdir)/osx/build/; #{@pkgbuild} --root root/#{project.name}-#{project.version} \
26
+ --scripts $(tempdir)/osx/build/scripts \
27
+ --identifier #{project.identifier}.#{project.name} \
28
+ --version #{project.version} \
29
+ --install-location / \
30
+ payload/#{project.name}-#{project.version}-#{project.release}.pkg)",
31
+ # Create a custom installer using the pkg above
32
+ "(cd $(tempdir)/osx/build/; #{@productbuild} --distribution #{project.name}-installer.xml \
33
+ --identifier #{project.identifier}.#{project.name}-installer \
34
+ --package-path payload/ \
35
+ --resources $(tempdir)/osx/build/resources \
36
+ --plugins $(tempdir)/osx/build/plugins \
37
+ pkg/#{project.name}-#{project.version}-#{project.release}-installer.pkg)",
38
+ # Create a dmg and ship it to the output dir
39
+ "(cd $(tempdir)/osx/build/; #{@hdiutil} create -volname #{project.name}-#{project.version} \
40
+ -srcfolder pkg/ dmg/#{project.package_name})",
41
+ "mkdir -p output/#{target_dir}",
42
+ "cp $(tempdir)/osx/build/dmg/#{project.package_name} ./output/#{target_dir}"]
43
+ end
44
+
45
+ # Method to generate the files required to build a osx package for the project
46
+ #
47
+ # @param workdir [String] working directory to stage the evaluated templates in
48
+ # @param name [String] name of the project
49
+ # @param binding [Binding] binding to use in evaluating the packaging templates
50
+ def generate_packaging_artifacts(workdir, name, binding)
51
+ resources_dir = File.join(workdir, "resources", "osx")
52
+ FileUtils.mkdir_p(resources_dir)
53
+ script_dir = File.join(workdir, "scripts")
54
+ FileUtils.mkdir_p(script_dir)
55
+
56
+ erb_file(File.join(VANAGON_ROOT, "templates/osx/project-installer.xml.erb"), File.join(workdir, "#{name}-installer.xml"), false, { :binding => binding })
57
+
58
+ ["postinstall", "preinstall"].each do |script_file|
59
+ erb_file(File.join(VANAGON_ROOT, "templates/osx/#{script_file}.erb"), File.join(script_dir, script_file), false, { :binding => binding })
60
+ FileUtils.chmod 0755, File.join(script_dir, script_file)
61
+ end
62
+
63
+ # Probably a better way to do this, but OSX tends to need some extra stuff
64
+ FileUtils.cp_r("resources/osx/.", resources_dir) if File.exist?("resources/osx/")
65
+ end
66
+
67
+ # Method to derive the package name for the project
68
+ #
69
+ # @param project [Vanagon::Project] project to name
70
+ # @return [String] name of the osx package for this project
71
+ def package_name(project)
72
+ "#{project.name}-#{project.version}-#{project.release}.#{@os_name}#{@os_version}.dmg"
73
+ end
74
+
75
+ # Get the expected output dir for the osx packages. This allows us to
76
+ # use some standard tools to ship internally.
77
+ #
78
+ # @return [String] relative path to where osx packages should be staged
79
+ def output_dir(target_repo = "")
80
+ File.join("apple", @os_version, target_repo, @architecture)
81
+ end
82
+
83
+ # Constructor. Sets up some defaults for the osx platform and calls the parent constructor
84
+ #
85
+ # @param name [String] name of the platform
86
+ # @return [Vanagon::Platform::OSX] the osx derived platform with the given name
87
+ def initialize(name)
88
+ @name = name
89
+ @make = "/usr/bin/make"
90
+ @tar = "tar"
91
+ @pkgbuild = "/usr/bin/pkgbuild"
92
+ @productbuild = "/usr/bin/productbuild"
93
+ @hdiutil = "/usr/bin/hdiutil"
94
+ @patch = "/usr/bin/patch"
95
+ @num_cores = "/usr/sbin/sysctl -n hw.physicalcpu"
96
+ super(name)
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,76 @@
1
+ require 'vanagon/utilities'
2
+ include Vanagon::Utilities
3
+
4
+ class Vanagon
5
+ class Platform
6
+ class RPM < Vanagon::Platform
7
+ # The specific bits used to generate an rpm package for a given project
8
+ #
9
+ # @param project [Vanagon::Project] project to build an rpm package of
10
+ # @return [Array] list of commands required to build an rpm package for the given project from a tarball
11
+ def generate_package(project)
12
+ target_dir = project.repo ? output_dir(project.repo) : output_dir
13
+ ["bash -c 'mkdir -p $(tempdir)/rpmbuild/{SOURCES,SPECS,BUILD,RPMS,SRPMS}'",
14
+ "cp #{project.name}-#{project.version}.tar.gz $(tempdir)/rpmbuild/SOURCES",
15
+ "cp file-list-for-rpm $(tempdir)/rpmbuild/SOURCES",
16
+ "cp #{project.name}.spec $(tempdir)/rpmbuild/SPECS",
17
+ "PATH=/opt/freeware/bin:$$PATH #{@rpmbuild} -bb --target #{@architecture} #{rpm_defines} $(tempdir)/rpmbuild/SPECS/#{project.name}.spec",
18
+ "mkdir -p output/#{target_dir}",
19
+ "cp $(tempdir)/rpmbuild/*RPMS/**/*.rpm ./output/#{target_dir}"]
20
+ end
21
+
22
+ # Method to generate the files required to build an rpm package for the project
23
+ #
24
+ # @param workdir [String] working directory to stage the evaluated templates in
25
+ # @param name [String] name of the project
26
+ # @param binding [Binding] binding to use in evaluating the packaging templates
27
+ def generate_packaging_artifacts(workdir, name, binding)
28
+ erb_file(File.join(VANAGON_ROOT, "templates/rpm/project.spec.erb"), File.join(workdir, "#{name}.spec"), false, { :binding => binding })
29
+ end
30
+
31
+ # Method to derive the package name for the project
32
+ #
33
+ # @param project [Vanagon::Project] project to name
34
+ # @return [String] name of the rpm package for this project
35
+ def package_name(project)
36
+ "#{project.name}-#{project.version}-#{project.release}.#{project.noarch ? 'noarch' : @architecture}.rpm"
37
+ end
38
+
39
+ # Get the expected output dir for the rpm packages. This allows us to
40
+ # use some standard tools to ship internally.
41
+ #
42
+ # @return [String] relative path to where rpm packages should be staged
43
+ def output_dir(target_repo = "products")
44
+ File.join(@os_name, @os_version, target_repo, @architecture)
45
+ end
46
+
47
+ def rpm_defines
48
+ defines = %(--define '_topdir $(tempdir)/rpmbuild' )
49
+ # RPM doesn't allow dashes in the os_name. This was added to
50
+ # convert cisco-wrlinux to cisco_wrlinux
51
+ unless is_aix?
52
+ defines << %(--define 'dist .#{@os_name.gsub('-', '_')}#{@os_version}' )
53
+ end
54
+ defines
55
+ end
56
+
57
+ # Constructor. Sets up some defaults for the rpm platform and calls the parent constructor
58
+ #
59
+ # @param name [String] name of the platform
60
+ # @return [Vanagon::Platform::RPM] the rpm derived platform with the given name
61
+ def initialize(name)
62
+ @name = name
63
+ @make = "/usr/bin/make"
64
+ @tar = "tar"
65
+ @patch = "/usr/bin/patch"
66
+ @num_cores = "/bin/grep -c 'processor' /proc/cpuinfo"
67
+ if is_aix?
68
+ @num_cores = "lsdev -Cc processor |wc -l"
69
+ @install = "/opt/freeware/bin/install"
70
+ end
71
+ @rpmbuild = "/usr/bin/rpmbuild"
72
+ super(name)
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,39 @@
1
+ # This platform definition was created to account for oddities with
2
+ # the RPM available on WindRiver Linux based systems. WRL uses RPMv5
3
+ # and some of the WRL-based OS platforms we support (e.g, HuaweiOS)
4
+ # do not have package repo systems or support for installing remote
5
+ # RPMs via urls
6
+ class Vanagon
7
+ class Platform
8
+ class RPM
9
+ class WRL < Vanagon::Platform::RPM
10
+ # Some WRL RPM platforms (e.g, HuaweiOS) don't allow you to
11
+ # install remote packages via url, so we'll do a dance to
12
+ # download them via curl and then perform the installs locally.
13
+ # This method generates a shell script to be executed on the
14
+ # system to do this.
15
+ #
16
+ # @param build_dependencies [Array] list of all build dependencies to install
17
+ # @return [String] a command to install all of the build dependencies
18
+ def install_build_dependencies(build_dependencies)
19
+ commands = []
20
+ unless build_dependencies.empty?
21
+ commands << "tmpdir=$(mktemp -p /var/tmp -d)"
22
+ commands << "cd ${tmpdir}"
23
+ build_dependencies.each do |build_dependency|
24
+ if build_dependency.match(/^http.*\.rpm$/)
25
+ # We're downloading each package individually so
26
+ # failures are easier to troubleshoot
27
+ commands << %(curl --remote-name --location --fail --silent #{build_dependency} && echo "Successfully downloaded #{build_dependency}")
28
+ end
29
+ end
30
+ # Install the downloaded packages
31
+ commands << "rpm -Uvh --nodeps --replacepkgs ${tmpdir}/*.rpm"
32
+ end
33
+
34
+ commands.join(' && ')
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,182 @@
1
+ class Vanagon
2
+ class Platform
3
+ class Solaris10 < Vanagon::Platform
4
+ # The specific bits used to generate a solaris package for a given project
5
+ #
6
+ # @param project [Vanagon::Project] project to build a solaris package of
7
+ # @return [Array] list of commands required to build a solaris package for the given project from a tarball
8
+ def generate_package(project)
9
+ target_dir = project.repo ? output_dir(project.repo) : output_dir
10
+ name_and_version = "#{project.name}-#{project.version}"
11
+ pkg_name = package_name(project)
12
+
13
+ [
14
+ # Set up our needed directories
15
+ "mkdir -p $(tempdir)/#{name_and_version}",
16
+ "mkdir -p $(tempdir)/pkg",
17
+ "mkdir -p output/#{target_dir}",
18
+
19
+ # Unpack the project and stage the packaging artifacts
20
+ "gunzip -c #{name_and_version}.tar.gz | '#{@tar}' -C '$(tempdir)' -xf -",
21
+
22
+ # Move bill-of-materials into a docdir
23
+ "mkdir -p $(tempdir)/#{name_and_version}/usr/share/doc/#{project.name}",
24
+ "mv $(tempdir)/#{name_and_version}/bill-of-materials $(tempdir)/#{name_and_version}/usr/share/doc/#{project.name}/bill-of-materials",
25
+
26
+ "rm #{name_and_version}.tar.gz",
27
+ "cp -r packaging $(tempdir)/",
28
+
29
+ # Here we are tweaking file/dir ownership and perms in the following ways
30
+ # - All directories default to 0755 and root:sys
31
+ # - All files default to root:sys
32
+ # - The bin directory and all bin files are owned by root:bin instead of root:sys
33
+ # - All files under lib are owned by root:bin instead of root:sys
34
+ # - All .so files are owned by root:bin instead of root:sys
35
+ %((cd $(tempdir)/#{name_and_version}; pkgproto . | sort | awk ' \
36
+ $$1 ~ /^d$$/ {print "d",$$2,$$3,"0755 root sys";} \
37
+ $$1 ~ /^s$$/ {print;} \
38
+ $$1 ~ /^f$$/ {print "f",$$2,$$3,$$4,"root sys";} \
39
+ $$1 !~ /^[dfs]$$/ {print;} ' | /opt/csw/bin/gsed \
40
+ -e '/^[fd] [^ ]\\+ .*[/]s\\?bin/ {s/root sys$$/root bin/}' \
41
+ -e '/^[fd] [^ ]\\+ .*[/]lib[/][^/ ]\\+ / {s/root sys$$/root bin/}' \
42
+ -e '/^[fd] [^ ]\\+ .*[/][^ ]\\+[.]so / {s/root sys$$/root bin/}' >> ../packaging/proto) ),
43
+ %((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('; ')})),
44
+
45
+ # Actually build the package
46
+ "pkgmk -f $(tempdir)/packaging/proto -b $(tempdir)/#{name_and_version} -o -d $(tempdir)/pkg/",
47
+ "pkgtrans -s $(tempdir)/pkg/ $(tempdir)/pkg/#{pkg_name.gsub(/\.gz$/, '')} #{project.name}",
48
+ "gzip -c $(tempdir)/pkg/#{pkg_name.gsub(/\.gz$/, '')} > output/#{target_dir}/#{pkg_name}",
49
+ ]
50
+ end
51
+
52
+ # Method to generate the files required to build a solaris package for the project
53
+ #
54
+ # @param workdir [String] working directory to stage the evaluated templates in
55
+ # @param name [String] name of the project
56
+ # @param binding [Binding] binding to use in evaluating the packaging templates
57
+ def generate_packaging_artifacts(workdir, name, binding)
58
+ ["pkginfo", "depend", "preinstall", "preremove", "postinstall", "proto"].each do |template|
59
+ target_dir = File.join(workdir, 'packaging')
60
+ FileUtils.mkdir_p(target_dir)
61
+ erb_file(File.join(VANAGON_ROOT, "templates/solaris/10/#{template}.erb"), File.join(target_dir, template), false, { :binding => binding })
62
+ end
63
+ end
64
+
65
+ # Generate the scripts required to add a group to the package generated.
66
+ # This will also update the group if it has changed.
67
+ #
68
+ # @param user [Vanagon::Common::User] the user to reference for the group
69
+ # @return [String] the commands required to add a group to the system
70
+ def add_group(user)
71
+ # NB: system users aren't supported on solaris 10
72
+ return <<-HERE.undent
73
+ if ! getent group '#{user.group}' > /dev/null 2>&1; then
74
+ /usr/sbin/groupadd '#{user.group}'
75
+ fi
76
+ HERE
77
+ end
78
+
79
+ # Generate the scripts required to add a user to the package generated.
80
+ # This will also update the user if it has changed.
81
+ #
82
+ # @param user [Vanagon::Common::User] the user to create
83
+ # @return [String] the commands required to add a user to the system
84
+ def add_user(user)
85
+ # NB: system users aren't supported on solaris 10
86
+ # Solaris 10 also doesn't support long flags
87
+ cmd_args = ["'#{user.name}'"]
88
+ cmd_args.unshift "-g '#{user.group}'" if user.group
89
+ cmd_args.unshift "-d '#{user.homedir}'" if user.homedir
90
+ if user.shell
91
+ cmd_args.unshift "-s '#{user.shell}'"
92
+ elsif user.is_system
93
+ # Even though system users aren't a thing, we can still disable the shell
94
+ cmd_args.unshift "-s '/usr/bin/false'"
95
+ end
96
+
97
+ user_args = cmd_args.join("\s")
98
+
99
+ return <<-HERE.undent
100
+ if getent passwd '#{user.name}' > /dev/null 2>&1; then
101
+ /usr/sbin/usermod #{user_args}
102
+ else
103
+ /usr/sbin/useradd #{user_args}
104
+ fi
105
+ HERE
106
+ end
107
+
108
+ # Method to derive the package name for the project
109
+ #
110
+ # @param project [Vanagon::Project] project to name
111
+ # @return [String] name of the solaris package for this project
112
+ def package_name(project)
113
+ "#{project.name}-#{project.version}-#{project.release}.#{@architecture}.pkg.gz"
114
+ end
115
+
116
+ # Get the expected output dir for the solaris 10 packages. This allows us to
117
+ # use some standard tools to ship internally.
118
+ #
119
+ # @return [String] relative path to where solaris 10 packages should be staged
120
+ def output_dir(target_repo = "")
121
+ File.join("solaris", @os_version, target_repo)
122
+ end
123
+
124
+ # Because solaris has multiple terrible ways to install packages, we have
125
+ # this method which generates a shell script to be executed on the system
126
+ # which will install all of the build dependencies
127
+ #
128
+ # @param build_dependencies [Array] list of all build dependencies to install
129
+ # @return [String] a command to install all of the build dependencies
130
+ def install_build_dependencies(build_dependencies)
131
+ http = []
132
+ pkgutil = []
133
+ noasks = ["instance=overwrite", "partial=nocheck", "runlevel=nocheck", "idepend=nocheck", "rdepend=nocheck", "space=nocheck", "setuid=nocheck", "conflict=nocheck", "action=nocheck", "basedir=default"]
134
+ noask_command = noasks.map { |noask| "echo '#{noask}' >> /var/tmp/noask" }.join('; ')
135
+
136
+ build_dependencies.each do |build_dependency|
137
+ if build_dependency.match(/^http.*\.gz/)
138
+ # Fetch, unpack, install...this assumes curl is present.
139
+ package = build_dependency.sub(/^http.*\//, '')
140
+ http << "tmpdir=$(mktemp -p /var/tmp -d); (cd ${tmpdir} && curl -O #{build_dependency} && gunzip -c #{package} | pkgadd -d /dev/stdin -a /var/tmp/noask all)"
141
+ else
142
+ # Opencsw dependencies. At this point we assume that pkgutil is installed.
143
+ pkgutil << build_dependency
144
+ end
145
+ end
146
+
147
+ command = ''
148
+ unless pkgutil.empty?
149
+ command << "/opt/csw/bin/pkgutil -y -i #{pkgutil.join("\s")}; "
150
+ end
151
+
152
+ unless http.empty?
153
+ command << "echo -n > /var/tmp/noask; #{noask_command}; "
154
+ command << http.join('; ')
155
+ end
156
+
157
+ command
158
+ end
159
+
160
+ # Constructor. Sets up some defaults for the solaris 10 platform and calls the parent constructor
161
+ #
162
+ # @param name [String] name of the platform
163
+ # @return [Vanagon::Platform::Solaris] the solaris 10 derived platform with the given name
164
+ def initialize(name)
165
+ @name = name
166
+ @make = "/opt/csw/bin/gmake"
167
+ @tar = "/usr/sfw/bin/gtar"
168
+ @patch = "/usr/bin/gpatch"
169
+ # solaris 10
170
+ @num_cores = "/usr/bin/kstat cpu_info | awk '{print $$1}' | grep '^core_id$$' | wc -l"
171
+ super(name)
172
+ if @architecture == "sparc"
173
+ @platform_triple = "sparc-sun-solaris2.#{@os_version}"
174
+ elsif @architecture == "i386"
175
+ @platform_triple = "i386-pc-solaris2.#{@os_version}"
176
+ end
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+
@@ -0,0 +1,138 @@
1
+ class Vanagon
2
+ class Platform
3
+ class Solaris11 < Vanagon::Platform
4
+ # The specific bits used to generate a solaris package for a given project
5
+ #
6
+ # @param project [Vanagon::Project] project to build a solaris package of
7
+ # @return [Array] list of commands required to build a solaris package for the given project from a tarball
8
+ def generate_package(project)
9
+ target_dir = project.repo ? output_dir(project.repo) : output_dir
10
+ name_and_version = "#{project.name}-#{project.version}"
11
+ pkg_name = package_name(project)
12
+
13
+ [
14
+ # Set up our needed directories
15
+ "mkdir -p $(tempdir)/#{name_and_version}",
16
+ "mkdir -p $(tempdir)/pkg",
17
+ "mkdir -p output/#{target_dir}",
18
+
19
+ # Unpack the project and stage the packaging artifacts
20
+ "gunzip -c #{name_and_version}.tar.gz | '#{@tar}' -C '$(tempdir)' -xf -",
21
+ "cp -r packaging $(tempdir)/",
22
+ "pkgrepo create $(tempdir)/repo",
23
+ "pkgrepo set -s $(tempdir)/repo publisher/prefix=#{project.identifier}",
24
+
25
+ "(cd $(tempdir); pkgsend generate #{name_and_version} | pkgfmt >> packaging/#{project.name}.p5m.1)",
26
+
27
+ # Actually build the package
28
+ "(cd $(tempdir)/packaging; pkgmogrify -DARCH=`uname -p` #{project.name}.p5m.1 #{project.name}.p5m | pkgfmt > #{project.name}.p5m.2)",
29
+ "pkglint $(tempdir)/packaging/#{project.name}.p5m.2",
30
+ "pkgsend -s 'file://$(tempdir)/repo' publish -d '$(tempdir)/#{name_and_version}' --fmri-in-manifest '$(tempdir)/packaging/#{project.name}.p5m.2'",
31
+ "pkgrecv -s 'file://$(tempdir)/repo' -a -d 'output/#{target_dir}/#{pkg_name}' '#{project.name}@#{ips_version(project.version, project.release)}'",
32
+
33
+ # Now make sure the package we built isn't totally broken (but not when cross-compiling)
34
+ %(if [ "#{@architecture}" = `uname -p` ]; then pkg install -nv -g 'output/#{target_dir}/#{pkg_name}' '#{project.name}@#{ips_version(project.version, project.release)}'; fi),
35
+ ]
36
+ end
37
+
38
+ # Method to generate the files required to build a solaris package for the project
39
+ #
40
+ # @param workdir [String] working directory to stage the evaluated templates in
41
+ # @param name [String] name of the project
42
+ # @param binding [Binding] binding to use in evaluating the packaging templates
43
+ def generate_packaging_artifacts(workdir, name, binding)
44
+ target_dir = File.join(workdir, 'packaging')
45
+ FileUtils.mkdir_p(target_dir)
46
+ erb_file(File.join(VANAGON_ROOT, "templates/solaris/11/p5m.erb"), File.join(target_dir, "#{name}.p5m"), false, { :binding => binding })
47
+ end
48
+
49
+ # Generate the scripts required to add a group to the package generated.
50
+ # This will also update the group if it has changed.
51
+ #
52
+ # @param user [Vanagon::Common::User] the user to reference for the group
53
+ # @return [String] the commands required to add a group to the system
54
+ def add_group(user)
55
+ "group groupname=#{user.group}"
56
+ end
57
+
58
+ # Helper to setup an IPS build repo on a target system
59
+ # http://docs.oracle.com/cd/E36784_01/html/E36802/gkkek.html
60
+ #
61
+ # @param uri [String] uri of the repository to add
62
+ # @param origin [String] origin of the repository
63
+ # @return [String] the command required to add an ips build repository
64
+ def add_repository(uri, origin)
65
+ "pkg set-publisher -G '*' -g #{uri} #{origin}"
66
+ end
67
+
68
+ # Generate the scripts required to add a user to the package generated.
69
+ # This will also update the user if it has changed.
70
+ #
71
+ # @param user [Vanagon::Common::User] the user to create
72
+ # @return [String] the commands required to add a user to the system
73
+ def add_user(user)
74
+ command = "user username=#{user.name}"
75
+ command << " group=#{user.group}" if user.group
76
+ command << " home-dir=#{user.homedir}" if user.homedir
77
+ if user.shell
78
+ command << " login-shell=#{user.shell}"
79
+ elsif user.is_system
80
+ command << " login-shell=/usr/bin/false"
81
+ end
82
+
83
+ command
84
+ end
85
+
86
+ # Method to derive the package name for the project
87
+ #
88
+ # @param project [Vanagon::Project] project to name
89
+ # @return [String] name of the solaris package for this project
90
+ def package_name(project)
91
+ "#{project.name}@#{ips_version(project.version, project.release)}.#{@architecture}.p5p"
92
+ end
93
+
94
+ # Method to transform a standard version into the format expected by IPS
95
+ # packages
96
+ #
97
+ # @param version [String] Standard package version
98
+ # @param release [String] Standard package release
99
+ # @return [String] version in IPS format
100
+ def ips_version(version, release)
101
+ version.gsub!(/[a-zA-Z]/, '')
102
+ version.gsub!(/(^-)|(-$)/, '')
103
+
104
+ # Here we strip leading 0 from version components but leave singular 0 on their own.
105
+ version = version.split('.').map(&:to_i).join('.')
106
+ "#{version},5.11-#{release}"
107
+ end
108
+
109
+ # Get the expected output dir for the solaris 11 packages. This allows us to
110
+ # use some standard tools to ship internally.
111
+ #
112
+ # @return [String] relative path to where solaris 11 packages should be staged
113
+ def output_dir(target_repo = "")
114
+ File.join("solaris", @os_version, target_repo)
115
+ end
116
+
117
+ # Constructor. Sets up some defaults for the solaris 11 platform and calls the parent constructor
118
+ #
119
+ # @param name [String] name of the platform
120
+ # @return [Vanagon::Platform::Solaris] the solaris 11 derived platform with the given name
121
+ def initialize(name)
122
+ @name = name
123
+ @make = "/usr/bin/gmake"
124
+ @tar = "/usr/bin/gtar"
125
+ @patch = "/usr/bin/gpatch"
126
+ @num_cores = "/usr/bin/kstat cpu_info | /usr/bin/ggrep -E '[[:space:]]+core_id[[:space:]]' | wc -l"
127
+ super(name)
128
+ if @architecture == "sparc"
129
+ @platform_triple = "sparc-sun-solaris2.#{@os_version}"
130
+ elsif @architecture == "i386"
131
+ @platform_triple = "i386-pc-solaris2.#{@os_version}"
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+