pupistry 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +13 -1
- data/{bin → exe}/pupistry +45 -76
- data/lib/pupistry.rb +1 -1
- data/lib/pupistry/agent.rb +40 -60
- data/lib/pupistry/artifact.rb +136 -172
- data/lib/pupistry/bootstrap.rb +30 -35
- data/lib/pupistry/config.rb +59 -31
- data/lib/pupistry/gpg.rb +71 -102
- data/lib/pupistry/storage_aws.rb +56 -61
- data/lib/pupistry/version.rb +3 -0
- data/resources/aws/cfn_pupistry_bucket_and_iam.template +11 -1
- data/resources/packer/amazon_linux.json +17 -0
- data/resources/packer/test_user_data.txt +33 -0
- metadata +92 -5
data/lib/pupistry/artifact.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# rubocop:disable Style/Documentation, Style/GlobalVars
|
1
2
|
require 'rubygems'
|
2
3
|
require 'yaml'
|
4
|
+
require 'safe_yaml'
|
3
5
|
require 'time'
|
4
6
|
require 'digest'
|
5
7
|
require 'fileutils'
|
@@ -12,13 +14,12 @@ module Pupistry
|
|
12
14
|
# All the functions needed for manipulating the artifats
|
13
15
|
attr_accessor :checksum
|
14
16
|
|
15
|
-
|
16
17
|
def fetch_r10k
|
17
|
-
$logger.info
|
18
|
+
$logger.info 'Using r10k utility to fetch the latest Puppet code'
|
18
19
|
|
19
|
-
unless defined? $config[
|
20
|
-
$logger.fatal
|
21
|
-
|
20
|
+
unless defined? $config['build']['puppetcode']
|
21
|
+
$logger.fatal 'You must configure the build:puppetcode config option in settings.yaml'
|
22
|
+
fail 'Invalid Configuration'
|
22
23
|
end
|
23
24
|
|
24
25
|
# https://github.com/puppetlabs/r10k
|
@@ -33,53 +34,50 @@ module Pupistry
|
|
33
34
|
# doable and much more polished approach. For now the MVP is to just run
|
34
35
|
# it via system, pull requests/patches to fix very welcome!
|
35
36
|
|
36
|
-
|
37
37
|
# Build the r10k config to instruct it to use our cache path for storing
|
38
38
|
# it's data and exporting the finished result.
|
39
|
-
$logger.debug
|
39
|
+
$logger.debug 'Generating an r10k configuration file...'
|
40
40
|
r10k_config = {
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
'cachedir' => "#{$config['general']['app_cache']}/r10kcache",
|
42
|
+
'sources' => {
|
43
|
+
'puppet' => {
|
44
|
+
'remote' => $config['build']['puppetcode'],
|
45
|
+
'basedir' => $config['general']['app_cache'] + '/puppetcode'
|
46
46
|
}
|
47
47
|
}
|
48
48
|
}
|
49
49
|
|
50
50
|
begin
|
51
|
-
File.open("#{$config[
|
52
|
-
fh.write YAML
|
51
|
+
File.open("#{$config['general']['app_cache']}/r10kconfig.yaml", 'w') do |fh|
|
52
|
+
fh.write YAML.dump(r10k_config)
|
53
53
|
end
|
54
|
-
rescue
|
55
|
-
$logger.fatal
|
54
|
+
rescue StandardError => e
|
55
|
+
$logger.fatal 'Unexpected error when trying to write the r10k configuration file'
|
56
56
|
raise e
|
57
57
|
end
|
58
58
|
|
59
|
-
|
60
59
|
# Execute R10k with the provided configuration
|
61
|
-
$logger.debug
|
60
|
+
$logger.debug 'Executing r10k'
|
62
61
|
|
63
|
-
if system "r10k deploy environment -c #{$config[
|
64
|
-
$logger.info
|
62
|
+
if system "r10k deploy environment -c #{$config['general']['app_cache']}/r10kconfig.yaml -pv debug"
|
63
|
+
$logger.info 'r10k run completed'
|
65
64
|
else
|
66
|
-
$logger.error
|
67
|
-
|
65
|
+
$logger.error 'r10k run failed, unable to generate artifact'
|
66
|
+
fail 'r10k run did not complete, unable to generate artifact'
|
68
67
|
end
|
69
|
-
|
70
68
|
end
|
71
69
|
|
72
70
|
def fetch_latest
|
73
71
|
# Fetch the latest S3 YAML file and check the version metadata without writing
|
74
72
|
# it to disk. Returns the version. Useful for quickly checking for updates :-)
|
75
73
|
|
76
|
-
$logger.debug
|
74
|
+
$logger.debug 'Checking latest artifact version...'
|
77
75
|
|
78
|
-
s3 = Pupistry::
|
76
|
+
s3 = Pupistry::StorageAWS.new 'agent'
|
79
77
|
contents = s3.download 'manifest.latest.yaml'
|
80
78
|
|
81
79
|
if contents
|
82
|
-
manifest = YAML
|
80
|
+
manifest = YAML.load(contents, safe: true, raise_on_unknown_tag: true)
|
83
81
|
|
84
82
|
if defined? manifest['version']
|
85
83
|
# We have a manifest version supplied, however since the manifest
|
@@ -93,8 +91,8 @@ module Pupistry
|
|
93
91
|
if /^[A-Za-z0-9]{32}$/.match(manifest['version'])
|
94
92
|
return manifest['version']
|
95
93
|
else
|
96
|
-
$logger.error
|
97
|
-
$logger.error
|
94
|
+
$logger.error 'Manifest version returned from S3 manifest.latest.yaml did not match expected regex of MD5.'
|
95
|
+
$logger.error 'Possible bug or security incident, investigate with care!'
|
98
96
|
$logger.error "Returned version string was: \"#{manifest['version']}\""
|
99
97
|
exit 0
|
100
98
|
end
|
@@ -106,50 +104,44 @@ module Pupistry
|
|
106
104
|
# download did not work
|
107
105
|
return false
|
108
106
|
end
|
109
|
-
|
110
|
-
|
111
107
|
end
|
112
108
|
|
113
|
-
|
114
109
|
def fetch_current
|
115
110
|
# Fetch the latest on-disk YAML file and check the version metadata, used
|
116
111
|
# to determine the latest artifact that has not yet been pushed to S3.
|
117
112
|
# Returns the version.
|
118
113
|
|
119
114
|
# Read the symlink information to get the latest version
|
120
|
-
if File.
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
115
|
+
if File.exist?($config['general']['app_cache'] + '/artifacts/manifest.latest.yaml')
|
116
|
+
manifest = YAML.load(File.open($config['general']['app_cache'] + '/artifacts/manifest.latest.yaml'), safe: true, raise_on_unknown_tag: true)
|
117
|
+
@checksum = manifest['version']
|
118
|
+
else
|
119
|
+
$logger.error 'No artifact has been built yet. You need to run pupistry build first?'
|
120
|
+
return false
|
121
|
+
end
|
127
122
|
end
|
128
123
|
|
129
|
-
|
130
124
|
def fetch_installed
|
131
125
|
# Fetch the current version that is installed.
|
132
|
-
|
126
|
+
|
133
127
|
# Make sure the Puppetcode install directory exists
|
134
|
-
unless Dir.
|
135
|
-
$logger.warn "The destination path of #{$config[
|
128
|
+
unless Dir.exist?($config['agent']['puppetcode'])
|
129
|
+
$logger.warn "The destination path of #{$config['agent']['puppetcode']} does not appear to exist or is not readable"
|
136
130
|
return false
|
137
131
|
end
|
138
132
|
|
139
133
|
# Look for a manifest file in the directory and read the version from it.
|
140
|
-
if File.
|
141
|
-
manifest = YAML
|
134
|
+
if File.exist?($config['agent']['puppetcode'] + '/manifest.pupistry.yaml')
|
135
|
+
manifest = YAML.load(File.open($config['agent']['puppetcode'] + '/manifest.pupistry.yaml'), safe: true, raise_on_unknown_tag: true)
|
142
136
|
|
143
137
|
return manifest['version']
|
144
138
|
else
|
145
|
-
$logger.warn
|
139
|
+
$logger.warn 'No current version installed'
|
146
140
|
return false
|
147
141
|
end
|
148
142
|
end
|
149
143
|
|
150
|
-
|
151
144
|
def fetch_artifact
|
152
|
-
|
153
145
|
# Figure out which version to fetch (if not explicitly defined)
|
154
146
|
if defined? @checksum
|
155
147
|
$logger.debug "Downloading artifact version #{@checksum}"
|
@@ -159,37 +151,32 @@ module Pupistry
|
|
159
151
|
if defined? @checksum
|
160
152
|
$logger.debug "Downloading latest artifact (#{@checksum})"
|
161
153
|
else
|
162
|
-
$logger.error
|
154
|
+
$logger.error 'There is not current artifact that can be fetched'
|
163
155
|
return false
|
164
156
|
end
|
165
157
|
|
166
158
|
end
|
167
159
|
|
168
160
|
# Make sure the download dir/cache exists
|
169
|
-
unless Dir.
|
170
|
-
FileUtils.mkdir_p $config["general"]["app_cache"] + "/artifacts/"
|
171
|
-
end
|
161
|
+
FileUtils.mkdir_p $config['general']['app_cache'] + '/artifacts/' unless Dir.exist?($config['general']['app_cache'] + '/artifacts/')
|
172
162
|
|
173
163
|
# Download files if they don't already exist
|
174
|
-
if File.
|
175
|
-
|
164
|
+
if File.exist?($config['general']['app_cache'] + "/artifacts/manifest.#{@checksum}.yaml") &&
|
165
|
+
File.exist?($config['general']['app_cache'] + "/artifacts/artifact.#{@checksum}.tar.gz")
|
166
|
+
$logger.debug 'This artifact is already present, no download required.'
|
176
167
|
else
|
177
|
-
s3 = Pupistry::
|
178
|
-
s3.download "manifest.#{@checksum}.yaml", $config[
|
179
|
-
s3.download "artifact.#{@checksum}.tar.gz", $config[
|
168
|
+
s3 = Pupistry::StorageAWS.new 'agent'
|
169
|
+
s3.download "manifest.#{@checksum}.yaml", $config['general']['app_cache'] + "/artifacts/manifest.#{@checksum}.yaml"
|
170
|
+
s3.download "artifact.#{@checksum}.tar.gz", $config['general']['app_cache'] + "/artifacts/artifact.#{@checksum}.tar.gz"
|
180
171
|
end
|
181
|
-
|
182
172
|
end
|
183
173
|
|
184
|
-
|
185
|
-
|
186
174
|
def push_artifact
|
187
175
|
# The push step involves 2 steps:
|
188
176
|
# 1. GPG sign the artifact and write it into the manifest file
|
189
177
|
# 2. Upload the manifest and archive files to S3.
|
190
178
|
# 3. Upload a copy as the "latest" manifest file which will be hit by clients.
|
191
179
|
|
192
|
-
|
193
180
|
# Determine which version we are uploading. Either one specifically
|
194
181
|
# selected, otherwise find the latest one to push
|
195
182
|
|
@@ -206,65 +193,60 @@ module Pupistry
|
|
206
193
|
end
|
207
194
|
end
|
208
195
|
|
209
|
-
|
210
196
|
# Do we even need to upload? If nothing has changed....
|
211
197
|
if @checksum == fetch_latest
|
212
198
|
$logger.error "You've already pushed this artifact version, nothing to do."
|
213
199
|
exit 0
|
214
200
|
end
|
215
201
|
|
216
|
-
|
217
202
|
# Make sure the files actually exist...
|
218
|
-
unless File.
|
203
|
+
unless File.exist?($config['general']['app_cache'] + "/artifacts/manifest.#{@checksum}.yaml")
|
219
204
|
$logger.error "The files expected for #{@checksum} do not appear to exist or are not readable"
|
220
|
-
|
205
|
+
fail 'Fatal unexpected error'
|
221
206
|
end
|
222
207
|
|
223
|
-
unless File.
|
208
|
+
unless File.exist?($config['general']['app_cache'] + "/artifacts/artifact.#{@checksum}.tar.gz")
|
224
209
|
$logger.error "The files expected for #{@checksum} do not appear to exist or are not readable"
|
225
|
-
|
210
|
+
fail 'Fatal unexpected error'
|
226
211
|
end
|
227
212
|
|
228
|
-
|
229
213
|
# GPG sign the files
|
230
|
-
if $config[
|
231
|
-
$logger.warn
|
232
|
-
$logger.warn
|
214
|
+
if $config['general']['gpg_disable'] == true
|
215
|
+
$logger.warn 'You have GPG signing *disabled*, whilst not critical it does weaken your security.'
|
216
|
+
$logger.warn 'Skipping signing step...'
|
233
217
|
else
|
234
218
|
|
235
219
|
gpgsig = Pupistry::GPG.new @checksum
|
236
220
|
|
237
221
|
# Sign the artifact
|
238
222
|
unless gpgsig.artifact_sign
|
239
|
-
$logger.fatal
|
223
|
+
$logger.fatal 'Unable to proceed with an unsigned artifact'
|
240
224
|
exit 0
|
241
225
|
end
|
242
226
|
|
243
227
|
# Verify the signature - we want to make sure what we've just signed
|
244
228
|
# can actually be validated properly :-)
|
245
229
|
unless gpgsig.artifact_verify
|
246
|
-
$logger.fatal
|
230
|
+
$logger.fatal 'Whilst a signature was generated, it was unable to be validated. This would suggest a bug of some kind.'
|
247
231
|
exit 0
|
248
232
|
end
|
249
233
|
|
250
234
|
# Save the signature to the manifest
|
251
235
|
unless gpgsig.signature_save
|
252
|
-
$logger.fatal
|
236
|
+
$logger.fatal 'Unable to write the signature into the manifest file for the artifact.'
|
253
237
|
exit 0
|
254
238
|
end
|
255
239
|
|
256
240
|
end
|
257
241
|
|
258
|
-
|
259
|
-
# Upload the artifact & manifests to S3. We also make an additional copy
|
242
|
+
# Upload the artifact & manifests to S3. We also make an additional copy
|
260
243
|
# as the "latest" file which will be downloaded by all the agents checking
|
261
244
|
# for new updates.
|
262
245
|
|
263
|
-
s3 = Pupistry::
|
264
|
-
s3.upload $config[
|
265
|
-
s3.upload $config[
|
266
|
-
s3.upload $config[
|
267
|
-
|
246
|
+
s3 = Pupistry::StorageAWS.new 'build'
|
247
|
+
s3.upload $config['general']['app_cache'] + "/artifacts/artifact.#{@checksum}.tar.gz", "artifact.#{@checksum}.tar.gz"
|
248
|
+
s3.upload $config['general']['app_cache'] + "/artifacts/manifest.#{@checksum}.yaml", "manifest.#{@checksum}.yaml"
|
249
|
+
s3.upload $config['general']['app_cache'] + "/artifacts/manifest.#{@checksum}.yaml", 'manifest.latest.yaml'
|
268
250
|
|
269
251
|
# Test a read of the manifest, we do this to make sure the S3 ACLs setup
|
270
252
|
# allow downloading of the uploaded files - helps avoid user headaches if
|
@@ -273,7 +255,7 @@ module Pupistry
|
|
273
255
|
# Only worth doing this step if they've explicitly set their AWS IAM credentials
|
274
256
|
# for the agent, which should be everyone except for IAM role users.
|
275
257
|
|
276
|
-
if $config[
|
258
|
+
if $config['agent']['access_key_id']
|
277
259
|
fetch_artifact
|
278
260
|
else
|
279
261
|
$logger.warn "The agent's AWS credentials are unset on this machine, unable to do download test to check permissions for you."
|
@@ -282,7 +264,6 @@ module Pupistry
|
|
282
264
|
|
283
265
|
$logger.info "Upload of artifact version #{@checksum} completed and is now latest"
|
284
266
|
end
|
285
|
-
|
286
267
|
|
287
268
|
def build_artifact
|
288
269
|
# r10k has done all the heavy lifting for us, we just need to generate a
|
@@ -292,10 +273,9 @@ module Pupistry
|
|
292
273
|
# the file. Like r10k, if you want to convert to a nicely polished native
|
293
274
|
# Ruby solution, patches welcome.
|
294
275
|
|
295
|
-
$logger.info
|
296
|
-
|
297
|
-
Dir.chdir($config["general"]["app_cache"]) do
|
276
|
+
$logger.info 'Creating artifact...'
|
298
277
|
|
278
|
+
Dir.chdir($config['general']['app_cache']) do
|
299
279
|
# Make sure there is a directory to write artifacts into
|
300
280
|
FileUtils.mkdir_p('artifacts')
|
301
281
|
|
@@ -303,94 +283,93 @@ module Pupistry
|
|
303
283
|
# so that we can grab the checksum, since checksum will always differ
|
304
284
|
# post-compression.
|
305
285
|
unless system "tar -c --exclude '.git' -f artifacts/artifact.temp.tar puppetcode/*"
|
306
|
-
$logger.error
|
307
|
-
|
286
|
+
$logger.error 'Unable to create tarball'
|
287
|
+
fail 'An unexpected error occured when executing tar'
|
308
288
|
end
|
309
289
|
|
310
290
|
# The checksum is important, we use it as our version for each artifact
|
311
291
|
# so we can tell them apart in a unique way.
|
312
|
-
@checksum = Digest::MD5.file($config[
|
292
|
+
@checksum = Digest::MD5.file($config['general']['app_cache'] + '/artifacts/artifact.temp.tar').hexdigest
|
313
293
|
|
314
294
|
# Now we have the checksum, check if it's the same as any existing
|
315
295
|
# artifacts. If so, drop out here, good to give feedback to the user
|
316
296
|
# if nothing has changed since it's easy to forget to git push a single
|
317
297
|
# module/change.
|
318
298
|
|
319
|
-
if File.
|
299
|
+
if File.exist?($config['general']['app_cache'] + "/artifacts/manifest.#{@checksum}.yaml")
|
320
300
|
$logger.error "This artifact version (#{@checksum}) has already been built, nothing todo."
|
321
301
|
$logger.error "Did you remember to \"git push\" your module changes?"
|
322
302
|
|
323
303
|
# Cleanup temp file
|
324
|
-
FileUtils.rm($config[
|
304
|
+
FileUtils.rm($config['general']['app_cache'] + '/artifacts/artifact.temp.tar')
|
325
305
|
exit 0
|
326
306
|
end
|
327
307
|
|
328
308
|
# Compress the artifact now that we have taken it's checksum
|
329
|
-
$logger.info
|
309
|
+
$logger.info 'Compressing artifact...'
|
330
310
|
|
331
|
-
if system
|
311
|
+
if system 'gzip artifacts/artifact.temp.tar'
|
332
312
|
else
|
333
|
-
$logger.error
|
334
|
-
|
313
|
+
$logger.error 'An unexpected error occured during compression of the artifact'
|
314
|
+
fail 'An unexpected error occured during compression of the artifact'
|
335
315
|
end
|
336
316
|
end
|
337
317
|
|
338
|
-
|
339
318
|
# We have the checksum, so we can now rename the artifact file
|
340
|
-
FileUtils.mv($config[
|
319
|
+
FileUtils.mv($config['general']['app_cache'] + '/artifacts/artifact.temp.tar.gz',
|
320
|
+
$config['general']['app_cache'] + "/artifacts/artifact.#{@checksum}.tar.gz")
|
341
321
|
|
342
|
-
|
343
|
-
$logger.info "Building manifest information for artifact..."
|
322
|
+
$logger.info 'Building manifest information for artifact...'
|
344
323
|
|
345
324
|
# Create the manifest file, this is used by clients for pulling details about
|
346
325
|
# the latest artifacts. We don't GPG sign here, but we do put in a placeholder.
|
347
326
|
manifest = {
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
327
|
+
'version' => @checksum,
|
328
|
+
'date' => Time.new.inspect,
|
329
|
+
'builduser' => ENV['USER'] || 'unlabled',
|
330
|
+
'gpgsig' => 'unsigned'
|
352
331
|
}
|
353
332
|
|
354
333
|
begin
|
355
|
-
File.open("#{$config[
|
356
|
-
fh.write YAML
|
334
|
+
File.open("#{$config['general']['app_cache']}/artifacts/manifest.#{@checksum}.yaml", 'w') do |fh|
|
335
|
+
fh.write YAML.dump(manifest)
|
357
336
|
end
|
358
|
-
rescue
|
359
|
-
$logger.fatal
|
337
|
+
rescue StandardError => e
|
338
|
+
$logger.fatal 'Unexpected error when trying to write the manifest file'
|
360
339
|
raise e
|
361
340
|
end
|
362
341
|
|
363
342
|
# This is the latest artifact, create some symlinks pointing the latest to it
|
364
343
|
begin
|
365
|
-
FileUtils.ln_s("manifest.#{@checksum}.yaml",
|
366
|
-
|
367
|
-
|
368
|
-
|
344
|
+
FileUtils.ln_s("manifest.#{@checksum}.yaml",
|
345
|
+
"#{$config['general']['app_cache']}/artifacts/manifest.latest.yaml",
|
346
|
+
force: true)
|
347
|
+
FileUtils.ln_s("artifact.#{@checksum}.tar.gz",
|
348
|
+
"#{$config['general']['app_cache']}/artifacts/artifact.latest.tar.gz",
|
349
|
+
force: true)
|
350
|
+
rescue StandardError => e
|
351
|
+
$logger.fatal 'Something weird went really wrong trying to symlink the latest artifacts'
|
369
352
|
raise e
|
370
353
|
end
|
371
354
|
|
372
|
-
|
373
355
|
$logger.info "New artifact version #{@checksum} ready for pushing"
|
374
356
|
end
|
375
357
|
|
376
|
-
|
377
358
|
def unpack
|
378
359
|
# Unpack the currently selected artifact to the archives directory.
|
379
|
-
|
360
|
+
|
380
361
|
# An application version must be specified
|
381
|
-
unless defined? @checksum
|
382
|
-
raise "Application bug, trying to unpack no artifact"
|
383
|
-
end
|
362
|
+
fail 'Application bug, trying to unpack no artifact' unless defined? @checksum
|
384
363
|
|
385
364
|
# Make sure the files actually exist...
|
386
|
-
unless File.
|
365
|
+
unless File.exist?($config['general']['app_cache'] + "/artifacts/manifest.#{@checksum}.yaml")
|
387
366
|
$logger.error "The files expected for #{@checksum} do not appear to exist or are not readable"
|
388
|
-
|
367
|
+
fail 'Fatal unexpected error'
|
389
368
|
end
|
390
369
|
|
391
|
-
unless File.
|
370
|
+
unless File.exist?($config['general']['app_cache'] + "/artifacts/artifact.#{@checksum}.tar.gz")
|
392
371
|
$logger.error "The files expected for #{@checksum} do not appear to exist or are not readable"
|
393
|
-
|
372
|
+
fail 'Fatal unexpected error'
|
394
373
|
end
|
395
374
|
|
396
375
|
# Clean up an existing unpacked copy - in *theory* it should be same, but
|
@@ -399,73 +378,64 @@ module Pupistry
|
|
399
378
|
clean_unpack
|
400
379
|
|
401
380
|
# Unpack the archive file
|
402
|
-
FileUtils.mkdir_p($config[
|
403
|
-
Dir.chdir($config[
|
404
|
-
|
405
|
-
unless system "tar -xf ../artifact.#{@checksum}.tar.gz"
|
406
|
-
$logger.error "Unable to unpack artifact files to #{Dir.pwd}"
|
407
|
-
raise "An unexpected error occured when executing tar"
|
408
|
-
else
|
381
|
+
FileUtils.mkdir_p($config['general']['app_cache'] + "/artifacts/unpacked.#{@checksum}")
|
382
|
+
Dir.chdir($config['general']['app_cache'] + "/artifacts/unpacked.#{@checksum}") do
|
383
|
+
if system "tar -xf ../artifact.#{@checksum}.tar.gz"
|
409
384
|
$logger.debug "Successfully unpacked artifact #{@checksum}"
|
385
|
+
else
|
386
|
+
$logger.error "Unable to unpack artifact files to #{Dir.pwd}"
|
387
|
+
fail 'An unexpected error occured when executing tar'
|
410
388
|
end
|
411
389
|
end
|
412
|
-
|
413
390
|
end
|
414
391
|
|
415
|
-
|
416
392
|
def install
|
417
393
|
# Copy the unpacked artifact into the agent's configured location. Generally all the
|
418
394
|
# heavy lifting is done by fetch_latest and unpack methods.
|
419
395
|
|
420
396
|
# An application version must be specified
|
421
|
-
unless defined? @checksum
|
422
|
-
raise "Application bug, trying to install no artifact"
|
423
|
-
end
|
397
|
+
fail 'Application bug, trying to install no artifact' unless defined? @checksum
|
424
398
|
|
425
399
|
# Validate the artifact if GPG is enabled.
|
426
|
-
if $config[
|
427
|
-
$logger.warn
|
428
|
-
$logger.warn
|
400
|
+
if $config['general']['gpg_disable'] == true
|
401
|
+
$logger.warn 'You have GPG validation *disabled*, whilst not critical it does weaken your security.'
|
402
|
+
$logger.warn 'Skipping validation step...'
|
429
403
|
else
|
430
404
|
|
431
405
|
gpgsig = Pupistry::GPG.new @checksum
|
432
406
|
|
433
407
|
unless gpgsig.artifact_verify
|
434
|
-
$logger.fatal
|
435
|
-
|
408
|
+
$logger.fatal 'The GPG signature could not be validated for the artifact. This could be a bug, a file corruption or a POSSIBLE SECURITY ISSUE such as maliciously modified content.'
|
409
|
+
fail 'Fatal unexpected error'
|
436
410
|
end
|
437
411
|
|
438
412
|
end
|
439
413
|
|
440
|
-
|
441
414
|
# Make sure the artifact has been unpacked
|
442
|
-
unless Dir.
|
415
|
+
unless Dir.exist?($config['general']['app_cache'] + "/artifacts/unpacked.#{@checksum}")
|
443
416
|
$logger.error "The unpacked directory expected for #{@checksum} does not appear to exist or is not readable"
|
444
|
-
|
417
|
+
fail 'Fatal unexpected error'
|
445
418
|
end
|
446
419
|
|
447
420
|
# Purge any currently installed files in the directory. See clean_install
|
448
|
-
# TODO notes for how this could be improved.
|
449
|
-
unless clean_install
|
450
|
-
$logger.error "Installation not proceeduing due to issues cleaning/prepping destination dir"
|
451
|
-
end
|
421
|
+
# TODO: notes for how this could be improved.
|
422
|
+
$logger.error 'Installation not proceeding due to issues cleaning/prepping destination dir' unless clean_install
|
452
423
|
|
453
424
|
# Make sure the destination directory exists
|
454
|
-
unless Dir.
|
455
|
-
$logger.error "The destination path of #{$config[
|
456
|
-
|
425
|
+
unless Dir.exist?($config['agent']['puppetcode'])
|
426
|
+
$logger.error "The destination path of #{$config['agent']['puppetcode']} does not appear to exist or is not readable"
|
427
|
+
fail 'Fatal unexpected error'
|
457
428
|
end
|
458
|
-
|
429
|
+
|
459
430
|
# Clone unpacked contents to the installation directory
|
460
431
|
begin
|
461
|
-
FileUtils.cp_r $config[
|
462
|
-
FileUtils.cp
|
432
|
+
FileUtils.cp_r $config['general']['app_cache'] + "/artifacts/unpacked.#{@checksum}/puppetcode/.", $config['agent']['puppetcode']
|
433
|
+
FileUtils.cp $config['general']['app_cache'] + "/artifacts/manifest.#{@checksum}.yaml", $config['agent']['puppetcode'] + '/manifest.pupistry.yaml'
|
463
434
|
return true
|
464
435
|
rescue
|
465
|
-
$logger.fatal "An unexpected error occured when copying the unpacked artifact to #{$config[
|
436
|
+
$logger.fatal "An unexpected error occured when copying the unpacked artifact to #{$config['agent']['puppetcode']}"
|
466
437
|
raise e
|
467
438
|
end
|
468
|
-
|
469
439
|
end
|
470
440
|
|
471
441
|
def clean_install
|
@@ -476,49 +446,43 @@ module Pupistry
|
|
476
446
|
# TODO: Do this smarter, we should track what files we drop in, and then remove
|
477
447
|
# any that weren't touched. Need to avoid rsync and stick with native to make
|
478
448
|
# support easier for weird/minimilistic distributions.
|
479
|
-
|
480
|
-
if defined? $config[
|
481
|
-
if $config[
|
449
|
+
|
450
|
+
if defined? $config['agent']['puppetcode'] # rubocop:disable Style/GuardClause
|
451
|
+
if $config['agent']['puppetcode'].empty?
|
482
452
|
$logger.error "You must configure a location for the agent's Puppet code to be deployed to"
|
483
453
|
return false
|
484
454
|
else
|
485
|
-
$logger.debug "Cleaning up #{$config[
|
455
|
+
$logger.debug "Cleaning up #{$config['agent']['puppetcode']} directory"
|
486
456
|
|
487
|
-
if Dir.
|
488
|
-
FileUtils.rm_r Dir.glob($config[
|
457
|
+
if Dir.exist?($config['agent']['puppetcode'])
|
458
|
+
FileUtils.rm_r Dir.glob($config['agent']['puppetcode'] + '/*'), secure: true
|
489
459
|
else
|
490
|
-
FileUtils.mkdir_p $config[
|
491
|
-
FileUtils.chmod(0700, $config[
|
460
|
+
FileUtils.mkdir_p $config['agent']['puppetcode']
|
461
|
+
FileUtils.chmod(0700, $config['agent']['puppetcode'])
|
492
462
|
end
|
493
463
|
|
494
464
|
return true
|
495
465
|
end
|
496
466
|
end
|
497
|
-
|
498
467
|
end
|
499
468
|
|
500
|
-
|
501
469
|
def clean_unpack
|
502
470
|
# Cleanup/remove any unpacked archive directories. Requires that the
|
503
471
|
# checksum be set to the version to be purged.
|
504
472
|
|
505
|
-
unless defined? @checksum
|
506
|
-
raise "Application bug, trying to unpack no artifact"
|
507
|
-
end
|
473
|
+
fail 'Application bug, trying to unpack no artifact' unless defined? @checksum
|
508
474
|
|
509
|
-
if Dir.
|
510
|
-
$logger.debug "Cleaning up #{$config[
|
511
|
-
FileUtils.rm_r $config[
|
475
|
+
if Dir.exist?($config['general']['app_cache'] + "/artifacts/unpacked.#{@checksum}/")
|
476
|
+
$logger.debug "Cleaning up #{$config['general']['app_cache']}/artifacts/unpacked.#{@checksum}..."
|
477
|
+
FileUtils.rm_r $config['general']['app_cache'] + "/artifacts/unpacked.#{@checksum}", secure: true
|
512
478
|
return true
|
513
479
|
else
|
514
|
-
$logger.debug
|
480
|
+
$logger.debug 'Nothing to cleanup (selected artifact is not currently unpacked)'
|
515
481
|
return true
|
516
482
|
end
|
517
483
|
|
518
|
-
|
519
|
-
|
484
|
+
false
|
520
485
|
end
|
521
|
-
|
522
486
|
end
|
523
487
|
end
|
524
488
|
|