ood_packaging 0.0.1.r2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,143 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ood_packaging/utils'
4
+ require 'rake'
5
+ require 'rake/file_utils'
6
+
7
+ # Build the packaging build boxes
8
+ class OodPackaging::BuildBox
9
+ include OodPackaging::Utils
10
+ include FileUtils
11
+
12
+ BASE_IMAGES = {
13
+ 'el7' => 'centos:7',
14
+ 'el8' => 'rockylinux/rockylinux:8',
15
+ 'ubuntu-20.04' => 'ubuntu:20.04'
16
+ }.freeze
17
+
18
+ CODENAMES = {
19
+ 'ubuntu-20.04' => 'focal'
20
+ }.freeze
21
+
22
+ def initialize(config = {})
23
+ @config = config
24
+ raise ArgumentError, 'Must provide dist' if dist.nil?
25
+
26
+ # rubocop:disable Style/GuardClause
27
+ unless valid_dist?(dist)
28
+ raise ArgumentError, "Invalid dist selected: #{dist}. Valid choices are #{valid_dists.join(' ')}"
29
+ end
30
+ # rubocop:enable Style/GuardClause
31
+ end
32
+
33
+ def dist
34
+ @dist ||= ENV['OOD_PACKAGING_DIST'] || @config[:dist]
35
+ end
36
+
37
+ def rpm?
38
+ dist.start_with?('el')
39
+ end
40
+
41
+ def deb?
42
+ !rpm?
43
+ end
44
+
45
+ def dnf?
46
+ return false unless rpm?
47
+ return false if dist == 'el7'
48
+
49
+ true
50
+ end
51
+
52
+ def scl?
53
+ return true if dist == 'el7'
54
+
55
+ false
56
+ end
57
+
58
+ def package_manager
59
+ return 'apt' if deb?
60
+ return 'dnf' if dnf?
61
+
62
+ 'yum'
63
+ end
64
+
65
+ def valid_dist?(value)
66
+ BASE_IMAGES.key?(value)
67
+ end
68
+
69
+ def valid_dists
70
+ BASE_IMAGES.keys
71
+ end
72
+
73
+ def base_image
74
+ @base_image ||= BASE_IMAGES[dist]
75
+ end
76
+
77
+ def codename
78
+ @codename ||= CODENAMES[dist]
79
+ end
80
+
81
+ def build_dir
82
+ File.join(File.dirname(__FILE__), 'build_box/docker-image')
83
+ end
84
+
85
+ def image_registry
86
+ @config[:builx_box_registry] || ENV['OOD_PACKAGING_BUILD_BOX_REGISTRY'] || nil
87
+ end
88
+
89
+ def image_org
90
+ @config[:build_box_org] || ENV['OOD_PACKAGING_BUILX_BOX_ORG'] || 'ohiosupercomputer'
91
+ end
92
+
93
+ def image_name
94
+ @config[:builx_box_name] || ENV['OOD_PACKAGING_BUILD_BOX_NAME'] || 'ood-buildbox'
95
+ end
96
+
97
+ def image_version
98
+ (ENV['OOD_PACKAGING_BUILD_BOX_VERSION'] || OodPackaging::VERSION).gsub(/^v/, '')
99
+ end
100
+
101
+ def image_tag
102
+ [image_registry, image_org, "#{image_name}-#{dist}:#{image_version}"].compact.join('/')
103
+ end
104
+
105
+ def build_gem
106
+ gem = File.join(proj_root, 'pkg', "ood_packaging-#{OodPackaging::VERSION}.gem")
107
+ Rake::Task['build'].invoke
108
+ sh "rm -f #{build_dir}/*.gem"
109
+ sh "cp #{gem} #{build_dir}/"
110
+ end
111
+
112
+ def dockerfile
113
+ template_file('build_box/docker-image/Dockerfile.erb')
114
+ end
115
+
116
+ def scripts
117
+ template_file('build_box/docker-image/inituidgid.sh.erb')
118
+ template_file('build_box/docker-image/install.sh.erb')
119
+ end
120
+
121
+ def build!
122
+ scripts
123
+ cmd = [container_runtime, 'build']
124
+ cmd.concat ['--tag', image_tag]
125
+ cmd.concat [ENV['OOD_PACKAGING_BUILD_BOX_ARGS']] if ENV['OOD_PACKAGING_BUILD_BOX_ARGS']
126
+ cmd.concat ['-f', dockerfile]
127
+ cmd.concat [build_dir]
128
+ build_gem
129
+ sh cmd.join(' ')
130
+ end
131
+
132
+ def push!
133
+ sh [container_runtime, 'push', image_tag].join(' ')
134
+ end
135
+
136
+ def pull!
137
+ sh [container_runtime, 'pull', image_tag].join(' ')
138
+ end
139
+
140
+ def save!(path)
141
+ sh [container_runtime, 'save', image_tag, '| gzip >', path].join(' ')
142
+ end
143
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Handle options for OodPackaging
4
+ module OodPackaging
5
+ OPTIONS = [:package, :version, :dist, :work_dir, :clean_work_dir, :output_dir, :clean_output_dir, :tar,
6
+ :tar_only, :skip_download, :gpg_sign, :gpg_name, :gpg_pubkey, :gpg_private_key, :gpg_passphrase,
7
+ :debug, :attach].freeze
8
+ end
@@ -0,0 +1,326 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ood_packaging/build_box'
4
+ require 'ood_packaging/utils'
5
+ require 'ood_packaging/string_ext'
6
+ require 'English'
7
+ require 'pathname'
8
+ require 'ostruct'
9
+ require 'securerandom'
10
+ require 'rake'
11
+ require 'rake/file_utils'
12
+
13
+ # The interface to build packages using containers
14
+ class OodPackaging::Package
15
+ include OodPackaging::Utils
16
+ include FileUtils
17
+
18
+ attr_accessor :build_box
19
+
20
+ def initialize(config = {})
21
+ @config = config
22
+ @config[:dist] = 'el8' if tar_only?
23
+ @build_box = OodPackaging::BuildBox.new(config)
24
+ raise ArgumentError, 'Package is required' if package.nil?
25
+ raise ArgumentError, 'Version is required' if version.nil?
26
+ raise ArgumentError, "Package #{package} is not a directory" unless Dir.exist?(package)
27
+ raise ArgumentError, "Package #{package} is not an absolute path" unless (Pathname.new package).absolute?
28
+ end
29
+
30
+ def container_name
31
+ @container_name ||= SecureRandom.uuid
32
+ end
33
+
34
+ def debug?
35
+ return true if ENV['OOD_PACKAGING_DEBUG'] == 'true'
36
+
37
+ @config[:debug].nil? ? false : @config[:debug]
38
+ end
39
+
40
+ def cmd_suffix
41
+ return '' if debug?
42
+
43
+ ' 2>/dev/null 1>/dev/null'
44
+ end
45
+
46
+ def attach?
47
+ return true if ENV['OOD_PACKAGING_ATTACH'] == 'true'
48
+
49
+ @config[:attach].nil? ? false : @config[:attach]
50
+ end
51
+
52
+ def work_dir
53
+ @work_dir ||= File.expand_path(@config[:work_dir])
54
+ end
55
+
56
+ def clean_work_dir
57
+ return false if ENV['OOD_PACKAGING_CLEAN_WORK_DIR'] == 'false'
58
+
59
+ @config[:clean_work_dir].nil? ? true : @config[:clean_work_dir]
60
+ end
61
+
62
+ def output_dir
63
+ @output_dir ||= File.expand_path(@config[:output_dir])
64
+ end
65
+
66
+ def clean_output_dir
67
+ return false if ENV['OOD_PACKAGING_CLEAN_OUTPUT_DIR'] == 'false'
68
+
69
+ @config[:clean_output_dir].nil? ? true : @config[:clean_output_dir]
70
+ end
71
+
72
+ def package
73
+ @config[:package]
74
+ end
75
+
76
+ def version
77
+ @config[:version]
78
+ end
79
+
80
+ def tar_version
81
+ version.gsub(/^v/, '')
82
+ end
83
+
84
+ def tar?
85
+ @config[:tar].nil? ? build_box.deb? : @config[:tar]
86
+ end
87
+
88
+ def tar_only?
89
+ @config[:tar_only].nil? ? false : @config[:tar_only]
90
+ end
91
+
92
+ def package_name
93
+ name = File.basename(package)
94
+ case name
95
+ when /deb|rpm/
96
+ name = if File.basename(File.dirname(package)) == 'packages'
97
+ File.basename(File.dirname(File.dirname(package)))
98
+ else
99
+ File.basename(File.dirname(package))
100
+ end
101
+ when 'packaging'
102
+ name = File.basename(File.dirname(package))
103
+ end
104
+ name
105
+ end
106
+
107
+ def gpg_files
108
+ [
109
+ OpenStruct.new(private_key: @config[:gpg_private_key], passphrase: @config[:gpg_passphrase]),
110
+ OpenStruct.new(private_key: ENV['OOD_PACKAGING_GPG_PRIVATE_KEY'],
111
+ passphrase: ENV['OOD_PACKAGING_GPG_PASSPHRASE'])
112
+ ].each do |gpg|
113
+ next if gpg.private_key.nil? || gpg.passphrase.nil?
114
+ return gpg if File.exist?(gpg.private_key) && File.exist?(gpg.passphrase)
115
+ end
116
+ nil
117
+ end
118
+
119
+ def gpg_sign
120
+ return false if ENV['OOD_PACKAGING_GPG_SIGN'].to_s == 'false'
121
+ return false if @config[:gpg_sign] == false
122
+
123
+ !gpg_files.nil?
124
+ end
125
+
126
+ def default_gpg_name
127
+ 'OnDemand Release Signing Key'
128
+ end
129
+
130
+ def gpg_name
131
+ @config[:gpg_name].nil? ? default_gpg_name : @config[:gpg_name]
132
+ end
133
+
134
+ def container_init
135
+ '/sbin/init'
136
+ end
137
+
138
+ def tar_path
139
+ if build_box.deb?
140
+ path = File.join(package, 'deb')
141
+ return path if Dir.exist?(path)
142
+ end
143
+
144
+ package
145
+ end
146
+
147
+ def tar_name
148
+ version = if build_box.rpm?
149
+ rpm_version
150
+ else
151
+ deb_version
152
+ end
153
+ "#{package_name}-#{version}"
154
+ end
155
+
156
+ def rpm_tar_dest_dir
157
+ [
158
+ File.join(package, 'rpm'),
159
+ File.join(package, 'packaging/rpm'),
160
+ File.join(package, 'packaging')
161
+ ].each do |dir|
162
+ return dir if Dir.exist?(dir)
163
+ end
164
+ File.join(package, 'packaging/rpm')
165
+ end
166
+
167
+ def rpm_version
168
+ tar_version
169
+ end
170
+
171
+ def deb_tar_dest_dir
172
+ dir = File.join(package, 'deb')
173
+ return File.join(dir, 'build') if Dir.exist?(dir)
174
+
175
+ File.join(package, 'build')
176
+ end
177
+
178
+ def deb_version
179
+ tar_version.gsub('-', '.')
180
+ end
181
+
182
+ def exec_launchers
183
+ [
184
+ File.join(ctr_scripts_dir, 'inituidgid.sh'),
185
+ File.join(ctr_scripts_dir, 'setuser.rb'),
186
+ ctr_user
187
+ ]
188
+ end
189
+
190
+ def exec_rake
191
+ cmd = []
192
+ cmd.concat exec_launchers if docker_runtime?
193
+ cmd.concat ['scl', 'enable', scl_ruby, '--'] if podman_runtime? && build_box.scl?
194
+ cmd.concat [File.join(ctr_scripts_dir, 'rake')]
195
+ cmd.concat ['-q'] unless debug?
196
+ cmd.concat ['-f', File.join(ctr_scripts_dir, 'Rakefile'), 'ood_packaging:package:build']
197
+ cmd
198
+ end
199
+
200
+ def exec_attach
201
+ cmd = []
202
+ cmd.concat exec_launchers if docker_runtime?
203
+ cmd.concat ['/bin/bash']
204
+ cmd
205
+ end
206
+
207
+ def container_mounts
208
+ args = []
209
+ args.concat ['-v', "#{package}:/package:ro"]
210
+ args.concat ['-v', "#{@config[:gpg_pubkey]}:/gpg.pub:ro"] if @config[:gpg_pubkey]
211
+ args.concat ['-v', "#{work_dir}:/work"]
212
+ args.concat ['-v', "#{output_dir}:/output"]
213
+ if gpg_sign
214
+ args.concat ['-v', "#{gpg_files.private_key}:#{gpg_private_key}:ro"]
215
+ args.concat ['-v', "#{gpg_files.passphrase}:#{gpg_passphrase}:ro"]
216
+ end
217
+ args
218
+ end
219
+
220
+ def clean!
221
+ sh "rm -rf #{work_dir}", verbose: debug? if clean_work_dir
222
+ sh "rm -rf #{output_dir}", verbose: debug? if clean_output_dir
223
+ end
224
+
225
+ def bootstrap!
226
+ sh "mkdir -p #{work_dir}", verbose: debug?
227
+ sh "mkdir -p #{output_dir}", verbose: debug?
228
+ end
229
+
230
+ def tar!
231
+ cmd = ['git', 'ls-files', '.', '|', tar, '-c']
232
+ if build_box.rpm?
233
+ dir = rpm_tar_dest_dir
234
+ else
235
+ dir = deb_tar_dest_dir.tap { |p| sh "mkdir -p #{p}" }
236
+ cmd.concat ["--transform 'flags=r;s,packaging/deb,debian,'"]
237
+ end
238
+ tar_file = "#{dir}/#{tar_name}.tar.gz"
239
+ cmd.concat ["--transform 's,^,#{tar_name}/,'"]
240
+ cmd.concat ['-T', '-', '|', "gzip > #{tar_file}"]
241
+
242
+ sh "rm #{tar_file}" if File.exist?(tar_file)
243
+ puts "Create tar archive #{tar_file}".blue
244
+ Dir.chdir(tar_path) do
245
+ sh cmd.join(' '), verbose: debug?
246
+ end
247
+ end
248
+
249
+ def run!
250
+ if tar_only?
251
+ tar!
252
+ return
253
+ end
254
+ clean!
255
+ bootstrap!
256
+ tar! if tar?
257
+ container_start!
258
+ container_exec!(exec_rake)
259
+ puts "Build SUCCESS: package=#{package} dist=#{build_box.dist}".green
260
+ rescue RuntimeError
261
+ puts "Build FAILED package=#{package} dist=#{build_box.dist}".red
262
+ raise
263
+ ensure
264
+ container_exec!(exec_attach, ['-i', '-t']) if attach?
265
+ container_kill! if container_running? && !attach?
266
+ end
267
+
268
+ def container_running?
269
+ cmd = "#{container_runtime} inspect #{container_name} 2>/dev/null 1>/dev/null"
270
+ puts cmd if debug?
271
+ `#{cmd}`
272
+ $CHILD_STATUS.success?
273
+ end
274
+
275
+ def container_start!
276
+ cmd = [container_runtime, 'run', '--detach', '--rm']
277
+ cmd.concat ['--name', container_name]
278
+ cmd.concat rt_specific_flags
279
+ cmd.concat container_mounts
280
+ cmd.concat [build_box.image_tag]
281
+ cmd.concat [container_init]
282
+ cmd.concat ['1>/dev/null'] unless debug?
283
+ puts "Starting container #{container_name} using image #{build_box.image_tag}".blue
284
+ sh cmd.join(' '), verbose: debug?
285
+ end
286
+
287
+ def container_exec!(exec_cmd, extra_args = [])
288
+ cmd = [container_runtime, 'exec']
289
+ cmd.concat extra_args
290
+ container_env.each_pair do |k, v|
291
+ cmd.concat ['-e', "'#{k}=#{v}'"] unless v.nil?
292
+ end
293
+ cmd.concat [container_name]
294
+ cmd.concat exec_cmd
295
+ puts "Build STARTED: package=#{package} dist=#{build_box.dist} exec=#{exec_cmd[-1]}".blue
296
+ sh cmd.join(' '), verbose: debug?
297
+ true
298
+ rescue RuntimeError
299
+ container_kill! if container_running? && !attach?
300
+ raise
301
+ end
302
+
303
+ def container_kill!
304
+ puts "Killing container #{container_name}".blue
305
+ cmd = [container_runtime, 'kill', container_name]
306
+ cmd.concat [cmd_suffix] unless debug?
307
+ sh cmd.join(' '), verbose: debug?
308
+ end
309
+
310
+ def container_env
311
+ env = {
312
+ 'DIST' => build_box.dist,
313
+ 'PACKAGE' => package_name,
314
+ 'VERSION' => version,
315
+ 'TAR_NAME' => "#{tar_name}.tar.gz",
316
+ 'GPG_SIGN' => gpg_sign,
317
+ 'GPG_NAME' => gpg_name,
318
+ 'SKIP_DOWNLOAD' => @config[:skip_download],
319
+ 'OOD_UID' => Process.uid,
320
+ 'OOD_GID' => Process.gid,
321
+ 'DEBUG' => debug?
322
+ }
323
+ env['GPG_PUBKEY'] = '/gpg.pub' if @config[:gpg_pubkey]
324
+ env
325
+ end
326
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ood_packaging'
4
+ require 'rake'
5
+ require 'rake/tasklib'
6
+
7
+ # Define OodPackaging rake task library
8
+ class OodPackaging::RakeTask < ::Rake::TaskLib
9
+ include ::Rake::DSL if defined?(::Rake::DSL)
10
+ include OodPackaging::Utils
11
+
12
+ OodPackaging::OPTIONS.each do |o|
13
+ attr_accessor o.to_sym
14
+ end
15
+
16
+ def initialize(*args, &task_block)
17
+ super()
18
+ @name = args.shift || :package
19
+
20
+ define(args, &task_block)
21
+ end
22
+
23
+ def define(args, &task_block)
24
+ desc 'Build package' unless ::Rake.application.last_description
25
+
26
+ task @name, *args do |_, task_args|
27
+ task_block&.call(*[self, task_args].slice(0, task_block.arity))
28
+ config = {}
29
+ OodPackaging::OPTIONS.each do |o|
30
+ v = instance_variable_get("@#{o}")
31
+ config[o.to_sym] = v unless v.nil?
32
+ end
33
+ OodPackaging::Package.new(config).run!
34
+ end
35
+ end
36
+
37
+ def name
38
+ @name.to_s
39
+ end
40
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # https://stackoverflow.com/a/11482430
4
+ class String
5
+ def colorize(code)
6
+ "\e[#{code}m#{self}\e[0m"
7
+ end
8
+
9
+ def red
10
+ colorize(31)
11
+ end
12
+
13
+ def green
14
+ colorize(32)
15
+ end
16
+
17
+ def blue
18
+ colorize(34)
19
+ end
20
+ end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ood_packaging'
4
+ require 'ood_packaging/rake_task'
5
+ require 'ood_packaging/utils'
6
+
7
+ namespace :ood_packaging do
8
+ include OodPackaging::Utils
9
+
10
+ desc 'Set version'
11
+ task :version, [:version] do |_task, args|
12
+ version_file = File.join(proj_root, 'lib/ood_packaging/version.rb')
13
+ version = args[:version].gsub(/^v/, '')
14
+ sh "#{sed} -i -r \"s| VERSION =.*| VERSION = '#{version}'|g\" #{version_file}"
15
+ sh 'bundle install'
16
+ end
17
+
18
+ namespace :buildbox do
19
+ desc 'Build buildbox image'
20
+ task :build, [:dist] do |_task, args|
21
+ @build_box = OodPackaging::BuildBox.new(args)
22
+ @build_box.build!
23
+ end
24
+
25
+ desc 'Push buildbox image'
26
+ task :push, [:dist] do |_task, args|
27
+ @build_box = OodPackaging::BuildBox.new(args)
28
+ @build_box.push!
29
+ end
30
+
31
+ desc 'Pull buildbox image'
32
+ task :pull, [:dist] do |_task, args|
33
+ @build_box = OodPackaging::BuildBox.new(args)
34
+ @build_box.pull!
35
+ end
36
+
37
+ desc 'Save buildbox image'
38
+ task :save, [:dist, :path] do |_task, args|
39
+ @build_box = OodPackaging::BuildBox.new(args)
40
+ @build_box.save!(args[:path])
41
+ end
42
+ end
43
+
44
+ namespace :package do
45
+ desc 'Build a package (INSIDE CONTAINER ONLY)'
46
+ task :build do
47
+ OodPackaging::Build.new.run!
48
+ end
49
+
50
+ OodPackaging::RakeTask.new(:internal, [:package, :dist]) do |t, args|
51
+ name = args[:package].split(':').last
52
+ t.package = File.join(proj_root, 'packages', name)
53
+ dist = args[:dist] || ENV['OOD_PACKAGING_DIST']
54
+ t.dist = dist
55
+ t.version = OodPackaging.package_version(name, dist)
56
+ t.work_dir = File.join(proj_root, 'tmp/work')
57
+ t.output_dir = File.join(proj_root, 'tmp/output')
58
+ end
59
+
60
+ desc 'Package ondemand-release'
61
+ task :'ondemand-release', [:dist] do |t, args|
62
+ ENV['OOD_PACKAGING_GPG_SIGN'] = 'false'
63
+ Rake::Task['ood_packaging:package:internal'].invoke(t.name, args[:dist])
64
+ end
65
+
66
+ desc 'Package ondemand-release-latest'
67
+ task :'ondemand-release-latest', [:dist] do |t, args|
68
+ ENV['OOD_PACKAGING_GPG_SIGN'] = 'false'
69
+ Rake::Task['ood_packaging:package:internal'].invoke(t.name, args[:dist])
70
+ end
71
+
72
+ desc 'Package ondemand-release'
73
+ task :'ondemand-runtime', [:dist] do |t, args|
74
+ Rake::Task['ood_packaging:package:internal'].invoke(t.name, args[:dist])
75
+ end
76
+
77
+ desc 'Package passenger'
78
+ task :passenger, [:dist] do |t, args|
79
+ Rake::Task['ood_packaging:package:internal'].invoke(t.name, args[:dist])
80
+ end
81
+
82
+ desc 'Package cjose'
83
+ task :cjose, [:dist] do |t, args|
84
+ Rake::Task['ood_packaging:package:internal'].invoke(t.name, args[:dist])
85
+ end
86
+
87
+ desc 'Package mod_auth_openidc'
88
+ task :mod_auth_openidc, [:dist] do |t, args|
89
+ Rake::Task['ood_packaging:package:internal'].invoke(t.name, args[:dist])
90
+ end
91
+
92
+ desc 'Package sqlite'
93
+ task :sqlite, [:dist] do |t, args|
94
+ Rake::Task['ood_packaging:package:internal'].invoke(t.name, args[:dist])
95
+ end
96
+
97
+ desc 'Package ondemand_exporter'
98
+ task :ondemand_exporter, [:dist] do |t, args|
99
+ Rake::Task['ood_packaging:package:internal'].invoke(t.name, args[:dist])
100
+ end
101
+
102
+ desc 'Package ondemand-compute'
103
+ task :'ondemand-compute', [:dist] do |t, args|
104
+ Rake::Task['ood_packaging:package:internal'].invoke(t.name, args[:dist])
105
+ end
106
+
107
+ desc 'Package python-websockify'
108
+ task :'python-websockify', [:dist] do |t, args|
109
+ Rake::Task['ood_packaging:package:internal'].invoke(t.name, args[:dist])
110
+ end
111
+
112
+ desc 'Package turbovnc'
113
+ task :turbovnc, [:dist] do |t, args|
114
+ Rake::Task['ood_packaging:package:internal'].invoke(t.name, args[:dist])
115
+ end
116
+ end
117
+ end