source_install 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +9 -0
- data/lib/source_install.rb +342 -0
- metadata +102 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 509f4694c4ffef87fcc75fad945512bbab934a03b28c0323cf45347b6663429c
|
4
|
+
data.tar.gz: 39105c8b6b84325af2291529f7b3958858a12ce84f75ee9bc617573ff94bf17b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 94093d88f44e85b269f9798ebaa4850fc3ad4c37ea495494497775e691907985f90f60ea3b019cd02e6c4dac4ac4d4d4342a7d04e3d0f0eae146809a9917b48d
|
7
|
+
data.tar.gz: a8efdbde9087a6c6d636e39430a4580aaea916fa9fd05948ab3301ebe062d7865eb3f1da58132f2654ea834099f458e313de390bec2a5ad56db83b5e954cd5c6
|
data/LICENSE
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2017-present The University of Alaska
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
6
|
+
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
8
|
+
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,342 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This module implements helpers that are used for resources
|
4
|
+
module Source
|
5
|
+
# This module implements helpers that are used for resources
|
6
|
+
module Install
|
7
|
+
VERSION = '0.0.0'
|
8
|
+
|
9
|
+
# Hooks for install
|
10
|
+
|
11
|
+
def base_name(_new_resource)
|
12
|
+
raise NotImplementedError('Client must define base application name e.g. "Python". \
|
13
|
+
This is frequently used to build e.g. archive file name and will be used to define default directories.')
|
14
|
+
end
|
15
|
+
|
16
|
+
def default_version(_new_resource)
|
17
|
+
raise NotImplementedError('Client must provide a default version string e.g. "1.1.4".')
|
18
|
+
end
|
19
|
+
|
20
|
+
def archive_file_name(_new_resource)
|
21
|
+
# noinspection RubyExpressionInStringInspection
|
22
|
+
raise NotImplementedError('Client must indicate the filename of the what the archive file \
|
23
|
+
that will be downloaded, e.g. "#{base_name(new_resource)}-#{new_resource.version}.tar.gz"')
|
24
|
+
end
|
25
|
+
|
26
|
+
def download_base_url(_new_resource)
|
27
|
+
raise NotImplementedError('Client must indicate the URL at which the archive file is located, \
|
28
|
+
e.g. "https://www.oss-project.org/source"')
|
29
|
+
end
|
30
|
+
|
31
|
+
def archive_root_directory(_new_resource)
|
32
|
+
# noinspection RubyExpressionInStringInspection
|
33
|
+
raise NotImplementedError('Client must indicate the directory created by extraction, \
|
34
|
+
e.g. "#{base_name(new_resource)}-#{new_resource.version}". This will be used as the build directory.')
|
35
|
+
end
|
36
|
+
|
37
|
+
def extract_creates_file(_new_resource)
|
38
|
+
raise NotImplementedError('Client must indicate a relative path to a file that is created by extraction, \
|
39
|
+
e.g. "README.md"')
|
40
|
+
end
|
41
|
+
|
42
|
+
def configuration_command(_new_resource)
|
43
|
+
raise NotImplementedError('Client must define the configuration command to be run before build, \
|
44
|
+
e.g. "./config shared --prefix..."')
|
45
|
+
end
|
46
|
+
|
47
|
+
def install_creates_file(_new_resource)
|
48
|
+
raise NotImplementedError('Client must indicate a relative path to a file that is created by installation, \
|
49
|
+
e.g. "bin/my_app"')
|
50
|
+
end
|
51
|
+
|
52
|
+
def install_command(_new_resource)
|
53
|
+
raise NotImplementedError('Client must define the command for installation, e.g. "make install"')
|
54
|
+
end
|
55
|
+
|
56
|
+
def post_install_logic(_new_resource)
|
57
|
+
raise NotImplementedError('Client must define logic to run after installation, for example to creating symlinks')
|
58
|
+
end
|
59
|
+
|
60
|
+
# Common install code
|
61
|
+
|
62
|
+
def ensure_version(new_resource)
|
63
|
+
return if new_resource.version
|
64
|
+
|
65
|
+
new_resource.version = default_version(new_resource)
|
66
|
+
end
|
67
|
+
|
68
|
+
def download_url(new_resource)
|
69
|
+
url = download_base_url(new_resource)
|
70
|
+
url += '/' unless url.match?(%r{/$})
|
71
|
+
url += archive_file_name(new_resource)
|
72
|
+
return url
|
73
|
+
end
|
74
|
+
|
75
|
+
def create_default_directories
|
76
|
+
directory '/var/chef' do
|
77
|
+
mode 0o755
|
78
|
+
owner 'root'
|
79
|
+
group 'root'
|
80
|
+
end
|
81
|
+
directory '/var/chef/cache' do
|
82
|
+
mode 0o755
|
83
|
+
owner 'root'
|
84
|
+
group 'root'
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def path_to_download_directory(new_resource)
|
89
|
+
return new_resource.download_directory if new_resource.download_directory
|
90
|
+
|
91
|
+
create_default_directories
|
92
|
+
return '/var/chef/cache'
|
93
|
+
end
|
94
|
+
|
95
|
+
def path_to_download_file(new_resource)
|
96
|
+
directory = path_to_download_directory(new_resource)
|
97
|
+
file = File.join(directory, archive_file_name(new_resource))
|
98
|
+
return file
|
99
|
+
end
|
100
|
+
|
101
|
+
def download_archive(new_resource)
|
102
|
+
download_file = path_to_download_file(new_resource)
|
103
|
+
url = download_url(new_resource)
|
104
|
+
remote_file download_file do
|
105
|
+
source url
|
106
|
+
owner new_resource.owner
|
107
|
+
group new_resource.group
|
108
|
+
end
|
109
|
+
return download_file
|
110
|
+
end
|
111
|
+
|
112
|
+
def path_to_build_directory(new_resource)
|
113
|
+
base = archive_root_directory(new_resource)
|
114
|
+
return File.join(new_resource.build_directory, base) if new_resource.build_directory
|
115
|
+
|
116
|
+
create_default_directories
|
117
|
+
return File.join('/var/chef/cache', base)
|
118
|
+
end
|
119
|
+
|
120
|
+
def clear_source_directory(build_directory, new_resource)
|
121
|
+
dir = build_directory
|
122
|
+
bash 'Clear Archive' do
|
123
|
+
code "rm -rf #{dir}\nmkdir #{dir}\nchown #{new_resource.owner}:#{new_resource.group} #{dir}"
|
124
|
+
# Run as root so we blow it away if the owner changes
|
125
|
+
action :nothing
|
126
|
+
subscribes :run, 'checksum_file[Download Checksum]', :immediate
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def manage_source_directory(download_file, build_directory, new_resource)
|
131
|
+
checksum_file 'Download Checksum' do
|
132
|
+
source_path download_file
|
133
|
+
target_path "/var/chef/cache/#{base_name(new_resource).downcase}-#{new_resource.version}-dl-checksum"
|
134
|
+
end
|
135
|
+
clear_source_directory(build_directory, new_resource)
|
136
|
+
end
|
137
|
+
|
138
|
+
def extract_command(filename)
|
139
|
+
return 'unzip -q' if filename.match?(/\.zip/)
|
140
|
+
|
141
|
+
return 'tar xzf' if filename.match?(/\.(:?tar\.gz|tgz)/)
|
142
|
+
|
143
|
+
raise "Archive not supported: #{filename}"
|
144
|
+
end
|
145
|
+
|
146
|
+
def code_for_extraction(download_file, build_directory, new_resource)
|
147
|
+
code = <<~CODE
|
148
|
+
#{extract_command(download_file)} #{download_file}
|
149
|
+
chown -R #{new_resource.owner}:#{new_resource.group} #{build_directory}
|
150
|
+
CODE
|
151
|
+
return code
|
152
|
+
end
|
153
|
+
|
154
|
+
def extract_download(download_file, build_directory, new_resource)
|
155
|
+
# Built-in archive_file requires Chef 15 and poise_archive is failing to exhibit idempotence on zip files
|
156
|
+
parent = File.dirname(build_directory)
|
157
|
+
code = code_for_extraction(download_file, build_directory, new_resource)
|
158
|
+
bash 'Extract Archive' do
|
159
|
+
code code
|
160
|
+
cwd parent
|
161
|
+
# Run as root in case it is installing in directory without write access
|
162
|
+
creates File.join(build_directory, extract_creates_file(new_resource))
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def extract_archive(build_directory, new_resource)
|
167
|
+
download_file = download_archive(new_resource)
|
168
|
+
manage_source_directory(download_file, build_directory, new_resource)
|
169
|
+
extract_download(download_file, build_directory, new_resource)
|
170
|
+
end
|
171
|
+
|
172
|
+
def default_install_directory(new_resource)
|
173
|
+
return "/opt/#{base_name(new_resource).downcase}/#{new_resource.version}"
|
174
|
+
end
|
175
|
+
|
176
|
+
def create_opt_directories(new_resource)
|
177
|
+
directory "/opt/#{base_name(new_resource).downcase}" do
|
178
|
+
mode 0o755
|
179
|
+
owner 'root'
|
180
|
+
group 'root'
|
181
|
+
end
|
182
|
+
directory default_install_directory(new_resource) do
|
183
|
+
mode 0o755
|
184
|
+
owner 'root'
|
185
|
+
group 'root'
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def ensure_install_directory(new_resource)
|
190
|
+
return if new_resource.install_directory
|
191
|
+
|
192
|
+
create_opt_directories(new_resource)
|
193
|
+
new_resource.install_directory = default_install_directory(new_resource)
|
194
|
+
end
|
195
|
+
|
196
|
+
def save_config(code, new_resource)
|
197
|
+
file 'Config File' do
|
198
|
+
path "/var/chef/cache/#{base_name(new_resource).downcase}-#{new_resource.version}-config"
|
199
|
+
content code
|
200
|
+
mode 0o644
|
201
|
+
owner 'root'
|
202
|
+
group 'root'
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def manage_make_file(build_directory, code, new_resource)
|
207
|
+
save_config(code, new_resource)
|
208
|
+
makefile = File.join(build_directory, 'Makefile')
|
209
|
+
file makefile do
|
210
|
+
action :nothing
|
211
|
+
subscribes :delete, 'file[Config File]', :immediate
|
212
|
+
end
|
213
|
+
return makefile
|
214
|
+
end
|
215
|
+
|
216
|
+
def configure_build(build_directory, new_resource)
|
217
|
+
code = configuration_command(new_resource)
|
218
|
+
makefile = manage_make_file(build_directory, code, new_resource)
|
219
|
+
bash 'Configure Build' do
|
220
|
+
code code
|
221
|
+
cwd build_directory
|
222
|
+
user new_resource.owner
|
223
|
+
group new_resource.group
|
224
|
+
creates makefile
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def check_build_directory(build_directory, new_resource)
|
229
|
+
checksum_file 'Source Checksum' do
|
230
|
+
source_path build_directory
|
231
|
+
target_path "/var/chef/cache/#{base_name(new_resource).downcase}-#{new_resource.version}-src-checksum"
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def manage_bin_file(bin_file)
|
236
|
+
file bin_file do
|
237
|
+
action :nothing
|
238
|
+
manage_symlink_source false
|
239
|
+
subscribes :delete, 'checksum_file[Source Checksum]', :immediate
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def execute_build(build_directory, bin_file, new_resource)
|
244
|
+
bash 'Compile' do
|
245
|
+
code 'make'
|
246
|
+
cwd build_directory
|
247
|
+
user new_resource.owner
|
248
|
+
group new_resource.group
|
249
|
+
creates bin_file
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def execute_install(build_directory, bin_file, new_resource)
|
254
|
+
bash 'Install' do
|
255
|
+
code install_command(new_resource)
|
256
|
+
cwd build_directory
|
257
|
+
# Run as root in case it is installing in directory without write access
|
258
|
+
creates bin_file
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def recurse_command(path)
|
263
|
+
return ' -R' if File.directory?(path)
|
264
|
+
|
265
|
+
return ''
|
266
|
+
end
|
267
|
+
|
268
|
+
def command_for_file(filename, new_resource)
|
269
|
+
path = File.join(new_resource.install_directory, filename)
|
270
|
+
recurse = recurse_command(path)
|
271
|
+
return "\nchown#{recurse} #{new_resource.owner}:#{new_resource.group} #{path}"
|
272
|
+
end
|
273
|
+
|
274
|
+
def iterate_install_directory(new_resource)
|
275
|
+
command = ''
|
276
|
+
Dir.foreach(new_resource.install_directory) do |filename|
|
277
|
+
next if ['.', '..'].include?(filename)
|
278
|
+
|
279
|
+
command += command_for_file(filename, new_resource)
|
280
|
+
end
|
281
|
+
return command
|
282
|
+
end
|
283
|
+
|
284
|
+
def build_permission_command(new_resource)
|
285
|
+
ruby_block 'Build Children' do
|
286
|
+
block do
|
287
|
+
files = iterate_install_directory(new_resource)
|
288
|
+
node.run_state['build_permission_command'] = files
|
289
|
+
end
|
290
|
+
action :nothing
|
291
|
+
subscribes :run, 'bash[Install]', :immediate
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
# Some install scripts create artifacts in the source directory
|
296
|
+
def set_src_permissions(build_directory, new_resource)
|
297
|
+
bash 'Set Config Permissions' do
|
298
|
+
code "chown -R #{new_resource.owner}:#{new_resource.group} #{build_directory}"
|
299
|
+
action :nothing
|
300
|
+
subscribes :run, 'bash[Install]', :immediate
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
def set_install_permissions(build_directory, new_resource)
|
305
|
+
build_permission_command(new_resource)
|
306
|
+
bash 'Change Install Permissions' do
|
307
|
+
code(lazy { node.run_state['build_permission_command'] })
|
308
|
+
cwd new_resource.install_directory
|
309
|
+
action :nothing
|
310
|
+
subscribes :run, 'bash[Install]', :immediate
|
311
|
+
end
|
312
|
+
set_src_permissions(build_directory, new_resource)
|
313
|
+
end
|
314
|
+
|
315
|
+
def make_build(build_directory, bin_file, new_resource)
|
316
|
+
execute_build(build_directory, bin_file, new_resource)
|
317
|
+
execute_install(build_directory, bin_file, new_resource)
|
318
|
+
set_install_permissions(build_directory, new_resource)
|
319
|
+
end
|
320
|
+
|
321
|
+
def compile_and_install(build_directory, new_resource)
|
322
|
+
check_build_directory(build_directory, new_resource)
|
323
|
+
bin_file = File.join(new_resource.install_directory, install_creates_file(new_resource))
|
324
|
+
manage_bin_file(bin_file)
|
325
|
+
make_build(build_directory, bin_file, new_resource)
|
326
|
+
end
|
327
|
+
|
328
|
+
def build_binary(build_directory, new_resource)
|
329
|
+
ensure_install_directory(new_resource)
|
330
|
+
configure_build(build_directory, new_resource)
|
331
|
+
compile_and_install(build_directory, new_resource)
|
332
|
+
post_install_logic(new_resource)
|
333
|
+
end
|
334
|
+
|
335
|
+
def create_install(new_resource)
|
336
|
+
ensure_version(new_resource)
|
337
|
+
build_directory = path_to_build_directory(new_resource)
|
338
|
+
extract_archive(build_directory, new_resource)
|
339
|
+
build_binary(build_directory, new_resource)
|
340
|
+
end
|
341
|
+
end
|
342
|
+
end
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: source_install
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- UA OIT Systems Engineering
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-08-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: chefspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: kitchen-vagrant
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: test-kitchen
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Logic for downloading, configuring, compiling, and installing packages
|
70
|
+
from source
|
71
|
+
email:
|
72
|
+
- ua-oit-se@alaska.edu
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- LICENSE
|
78
|
+
- lib/source_install.rb
|
79
|
+
homepage: https://github.com/ualaska-it/source_install
|
80
|
+
licenses:
|
81
|
+
- MIT
|
82
|
+
metadata: {}
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: 2.4.0
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
requirements: []
|
98
|
+
rubygems_version: 3.0.3
|
99
|
+
signing_key:
|
100
|
+
specification_version: 4
|
101
|
+
summary: A gem for common installer logic
|
102
|
+
test_files: []
|