gitchefsync 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/gitchefsync.gemspec +17 -1
- data/lib/gitchefsync.rb +82 -19
- data/lib/gitchefsync/audit.rb +122 -16
- data/lib/gitchefsync/common.rb +22 -0
- data/lib/gitchefsync/config.rb +18 -0
- data/lib/gitchefsync/env_sync.rb +84 -36
- data/lib/gitchefsync/errors.rb +17 -0
- data/lib/gitchefsync/git_util.rb +16 -0
- data/lib/gitchefsync/io_util.rb +16 -0
- data/lib/gitchefsync/knife_util.rb +16 -0
- data/lib/gitchefsync/log.rb +16 -0
- data/lib/gitchefsync/notify.rb +69 -13
- data/lib/gitchefsync/opts.rb +16 -0
- data/lib/gitchefsync/schedule.rb +17 -1
- data/lib/gitchefsync/version.rb +17 -1
- data/spec/gitchefsync_spec.rb +16 -0
- data/spec/integration.rb +16 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a57596b84302167acc4a08933a924eded9d26f57
|
4
|
+
data.tar.gz: f672d7e712813563a212cab7aa5118de2b840c31
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ae21d609ac0004a3825f44a6b12278abe40b1feabb739152aabb532ae4bade6e9d3ee29561dd44bedfaa37145ca11f7cd40696e54fe831ef3b2b896f91550957
|
7
|
+
data.tar.gz: 94da27966929e77ac27cd6ade202776801d9c0110f86fb1ff523f2a778df42c7338e764d800202d1f19a480318618140ff03bef742ecd346cbf54795d746b7ec
|
data/gitchefsync.gemspec
CHANGED
@@ -1,4 +1,20 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
# Gitchefsync - git to chef sync toolset
|
3
|
+
#
|
4
|
+
# Copyright 2014, BlackBerry, Inc.
|
5
|
+
#
|
6
|
+
#Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
#you may not use this file except in compliance with the License.
|
8
|
+
#You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
#Unless required by applicable law or agreed to in writing, software
|
13
|
+
#distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
#See the License for the specific language governing permissions and
|
16
|
+
#limitations under the License.
|
17
|
+
|
2
18
|
lib = File.expand_path('../lib', __FILE__)
|
3
19
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
20
|
require 'gitchefsync/version'
|
@@ -23,7 +39,7 @@ Gem::Specification.new do |spec|
|
|
23
39
|
spec.add_runtime_dependency "gitlab", '~> 3.0.0'
|
24
40
|
spec.add_development_dependency "bundler", "~> 1.6"
|
25
41
|
spec.add_development_dependency "rake"
|
26
|
-
spec.homepage = "https://gitlab.rim.net/
|
42
|
+
spec.homepage = "https://gitlab.rim.net/chef/gitchefsync/tree/master"
|
27
43
|
|
28
44
|
|
29
45
|
end
|
data/lib/gitchefsync.rb
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
# Gitchefsync - git to chef sync toolset
|
2
|
+
#
|
3
|
+
# Copyright 2014, BlackBerry, Inc.
|
4
|
+
#
|
5
|
+
#Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
#you may not use this file except in compliance with the License.
|
7
|
+
#You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
#Unless required by applicable law or agreed to in writing, software
|
12
|
+
#distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
#See the License for the specific language governing permissions and
|
15
|
+
#limitations under the License.
|
16
|
+
|
1
17
|
require 'optparse'
|
2
18
|
require 'gitlab'
|
3
19
|
require 'json'
|
@@ -36,10 +52,10 @@ module Gitchefsync
|
|
36
52
|
#number of files
|
37
53
|
def self.trimAudit
|
38
54
|
logger.debug("event_id=trim_audit_files:keep=#{@audit_keep_trim}")
|
39
|
-
audit = Audit.new(@
|
55
|
+
audit = Audit.new(@audit_dir, 'env' )
|
40
56
|
audit.trim(@audit_keep_trim)
|
41
57
|
|
42
|
-
audit = Audit.new(@
|
58
|
+
audit = Audit.new(@audit_dir, 'cb' )
|
43
59
|
audit.trim(@audit_keep_trim)
|
44
60
|
|
45
61
|
end
|
@@ -48,8 +64,8 @@ module Gitchefsync
|
|
48
64
|
|
49
65
|
notification = Notification.new(@config['smtp_server'])
|
50
66
|
|
51
|
-
notification.
|
52
|
-
notification.singleNotifyFromAudit(@
|
67
|
+
notification.singleNotifyFromAudit(@audit_dir, 'cb',@config['default_notify_email'] )
|
68
|
+
notification.singleNotifyFromAudit(@audit_dir,'env',@config['default_notify_email'])
|
53
69
|
|
54
70
|
notification.close
|
55
71
|
end
|
@@ -70,6 +86,7 @@ module Gitchefsync
|
|
70
86
|
|
71
87
|
|
72
88
|
FS.knifeReady(@options[:git_local], @options[:knife_config])
|
89
|
+
@knife_ready = true
|
73
90
|
|
74
91
|
if !@config['sync_local']
|
75
92
|
|
@@ -163,18 +180,19 @@ module Gitchefsync
|
|
163
180
|
include FS,Git
|
164
181
|
|
165
182
|
logger.info "event_id=stage_cookbooks:git_local=#{@git_local}"
|
166
|
-
FS.knifeReady(@options[:git_local], @options[:knife_config])
|
183
|
+
FS.knifeReady(@options[:git_local], @options[:knife_config]) unless @knife_ready
|
167
184
|
ret_status = Hash.new
|
168
185
|
|
169
186
|
|
170
187
|
#not sure if this should be globally governed?
|
171
|
-
audit = Audit.new(@
|
188
|
+
audit = Audit.new(@audit_dir, 'cb')
|
172
189
|
|
173
190
|
|
174
191
|
knifeUtil = KnifeUtil.new(@knife, @git_local)
|
175
192
|
#Have a delta point: interact with the chef server to identify delta
|
176
193
|
listCB = knifeUtil.listCookbooks
|
177
|
-
|
194
|
+
#list of cookbooks processed
|
195
|
+
list_processed = Array.new
|
178
196
|
cookbook_dirs = Dir.entries(@git_local).reject! {|item| item.start_with?(".") }
|
179
197
|
cookbook_dirs.each do |dir|
|
180
198
|
|
@@ -192,7 +210,9 @@ module Gitchefsync
|
|
192
210
|
logger.debug "event_id=git_checkout:path=#{path}:tag=#{tag}"
|
193
211
|
Git.cmd "cd #{path} && #{@git_bin} checkout #{tag}"
|
194
212
|
|
195
|
-
self.processCookbook(path,audit)
|
213
|
+
cb = self.processCookbook(path,audit)
|
214
|
+
list_processed << @stage_dir + "/" + cb.berksTar() unless cb.nil?
|
215
|
+
|
196
216
|
rescue NoMetaDataError => e
|
197
217
|
#No audit written on failure to parse metadata
|
198
218
|
logger.info "event_id=nometadata:dir=#{dir}"
|
@@ -216,7 +236,17 @@ module Gitchefsync
|
|
216
236
|
end
|
217
237
|
end
|
218
238
|
|
219
|
-
|
239
|
+
#compared list_processed with what is in stage
|
240
|
+
#and delete the tars
|
241
|
+
stage = @stage_dir + "/*tar.gz"
|
242
|
+
existing = Dir.glob(stage)
|
243
|
+
to_del = existing - list_processed
|
244
|
+
logger.info "event_id=list_tar_delta:del+list=#{to_del}"
|
245
|
+
to_del.each do |file|
|
246
|
+
File.delete(file)
|
247
|
+
end
|
248
|
+
#reconcile method will actually delete the cookbooks from server
|
249
|
+
|
220
250
|
#write out the audit file
|
221
251
|
audit.write
|
222
252
|
#clean the audit files
|
@@ -232,34 +262,44 @@ module Gitchefsync
|
|
232
262
|
cookbook = knifeUtil.parseMetaData(path)
|
233
263
|
logger.debug "event_id=processing:cookbook=#{cookbook}"
|
234
264
|
|
265
|
+
|
235
266
|
if cookbook != nil
|
236
267
|
stage_tar = @config['stage_dir'] +"/" + cookbook.berksTar()
|
237
268
|
tar_exists = File.exists?(stage_tar)
|
238
269
|
end
|
239
270
|
|
240
271
|
begin
|
272
|
+
|
273
|
+
#get some git historical info
|
274
|
+
extra = Hash.new
|
275
|
+
extra['sha'] = (Git.cmd "cd #{path} && git log -1 --pretty=%H").chomp
|
276
|
+
extra['author_email'] = (Git.cmd "cd #{path} && git log -1 --pretty=%ce").chomp
|
277
|
+
extra['date'] = (Git.cmd "cd #{path} && git log -1 --pretty=%cd").chomp
|
278
|
+
extra['subject'] = (Git.cmd "cd #{path} && git log -1 --pretty=%s").chomp
|
279
|
+
|
241
280
|
if (cookbook !=nil && (!knifeUtil.isCBinList(cookbook, self.serverCookbooks()) || !tar_exists ))
|
242
281
|
berks_tar = self.stageBerks(path , @config['stage_dir'])
|
243
282
|
#upload cookbooks still puts a Berksfile, will refactor this method
|
244
283
|
self.uploadBerks(path)
|
245
284
|
logger.debug("event_id=staging:cookbook=#{cookbook}:berks_tar=#{berks_tar}")
|
246
285
|
self.stageCBUpload(berks_tar, @stage_cb_dir, knifeUtil, self.serverCookbooks())
|
247
|
-
audit.addCookbook(cookbook) if berks_tar.nil?
|
286
|
+
audit.addCookbook(cookbook,"UPDATE",nil,extra) if berks_tar.nil?
|
248
287
|
logger.info "event_id=cookbook_staged:cookbook=#{cookbook}"
|
249
288
|
|
250
289
|
elsif cookbook !=nil && @config['force_package']
|
251
290
|
logger.info "event_id=cookbook_force_package:cookbook=#{cookbook}"
|
252
291
|
self.stageBerks(path, @config['stage_dir'])
|
253
|
-
|
254
|
-
audit.addCookbook(cookbook, "EXISTING")
|
292
|
+
elsif cookbook != nil
|
293
|
+
audit.addCookbook(cookbook, "EXISTING",nil,extra)
|
255
294
|
logger.info "event_id=cookbook_untouched:cookbook=#{cookbook}"
|
256
295
|
end
|
257
296
|
rescue BerksError => e
|
258
297
|
logger.error "event_id=berks_package_failure:msg=#{e.message}:trace=#{e.backtrace}"
|
259
|
-
audit.addCookbook(cookbook, "ERROR", e)
|
298
|
+
audit.addCookbook(cookbook, "ERROR", e, extra)
|
260
299
|
end
|
261
300
|
|
262
301
|
Git.cmd "cd #{path} && git clean -xdf"
|
302
|
+
return cookbook
|
263
303
|
end
|
264
304
|
|
265
305
|
#do a berks upload of the path
|
@@ -307,7 +347,11 @@ module Gitchefsync
|
|
307
347
|
#returns the path to the berks tar file
|
308
348
|
def self.stageBerks(path, stage_dir)
|
309
349
|
include FS
|
350
|
+
|
310
351
|
begin
|
352
|
+
if File.exists?(File.join(path,"Berfile.lock"))
|
353
|
+
raise BerksLockError, "Berks lock file found"
|
354
|
+
end
|
311
355
|
if File.exists?(File.join(path, "Berksfile"))
|
312
356
|
logger.debug "event_id=Stage_cookbook:path=#{path}"
|
313
357
|
|
@@ -345,7 +389,8 @@ module Gitchefsync
|
|
345
389
|
else
|
346
390
|
raise NoBerksError, "Unable to locate Berks file for #{path}"
|
347
391
|
end
|
348
|
-
|
392
|
+
|
393
|
+
rescue NoBerksError,BerksLockError => e
|
349
394
|
raise e
|
350
395
|
rescue Exception => e
|
351
396
|
raise BerksError.new(e.message)
|
@@ -366,7 +411,7 @@ module Gitchefsync
|
|
366
411
|
|
367
412
|
|
368
413
|
#read in the latest audit - fail on non-null exceptions
|
369
|
-
audit = Audit.new(@
|
414
|
+
audit = Audit.new(@audit_dir,'cb' )
|
370
415
|
|
371
416
|
json = audit.parseLatest
|
372
417
|
if json != nil && audit.hasError(json)
|
@@ -409,13 +454,31 @@ module Gitchefsync
|
|
409
454
|
raise InvalidTar, "Invalid tar name #{file}"
|
410
455
|
end
|
411
456
|
|
412
|
-
logger.debug "In chef server? #{knifeUtil.inList(match[1],match[2],listCB)}"
|
457
|
+
#logger.debug "In chef server? #{knifeUtil.inList(match[1],match[2],listCB)}"
|
413
458
|
|
459
|
+
|
414
460
|
if !knifeUtil.inList(match[1],match[2],listCB) || forceUpload
|
415
461
|
logger.info "event_id=stage_upload:cookbook=#{match[1]}:ver=#{match[2]}:dir=#{cookbook_dir}"
|
416
462
|
FS.cmd "tar -xf #{file} -C #{cookbook_dir}"
|
417
|
-
|
418
|
-
|
463
|
+
new_cb_list = Array.new
|
464
|
+
cb_dir = Dir.entries(cookbook_dir + "/cookbooks")
|
465
|
+
cb_dir.each do |dir|
|
466
|
+
|
467
|
+
begin
|
468
|
+
cb_info = knifeUtil.parseMetaData(cookbook_dir + "/cookbooks/" + dir)
|
469
|
+
if knifeUtil.inList(cb_info.name(),cb_info.version,listCB)
|
470
|
+
logger.debug "event_id=del_cb_in_server:name=#{cb_info}"
|
471
|
+
FS.cmdNoError "rm -fr #{cookbook_dir}/cookbooks/#{cb_info.name}"
|
472
|
+
else
|
473
|
+
#TODO: add this as a concat method in knife_util class
|
474
|
+
new_cb_list << cb_info
|
475
|
+
end
|
476
|
+
rescue NoMetaDataError => e
|
477
|
+
logger.debug "no metadata on #{dir}"
|
478
|
+
end
|
479
|
+
end
|
480
|
+
out = FS.cmd "cd #{cookbook_dir} && #{@knife} cookbook upload -a --cookbook-path=#{cookbook_dir}/cookbooks"
|
481
|
+
listCB.concat(new_cb_list)
|
419
482
|
logger.debug "event_id=stage_upload_output=\n#{out}"
|
420
483
|
else
|
421
484
|
logger.info"event_id=stage_no_upload:cookbook=#{match[1]}:ver=#{match[2]}"
|
@@ -453,7 +516,7 @@ module Gitchefsync
|
|
453
516
|
def self.reconcile
|
454
517
|
|
455
518
|
#Validation
|
456
|
-
if Audit.new(@
|
519
|
+
if Audit.new(@audit_dir, 'cb').latest == nil
|
457
520
|
logger.warn "event_id=reconcile_no_audit_detected"
|
458
521
|
return
|
459
522
|
end
|
data/lib/gitchefsync/audit.rb
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
# Gitchefsync - git to chef sync toolset
|
2
|
+
#
|
3
|
+
# Copyright 2014, BlackBerry, Inc.
|
4
|
+
#
|
5
|
+
#Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
#you may not use this file except in compliance with the License.
|
7
|
+
#You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
#Unless required by applicable law or agreed to in writing, software
|
12
|
+
#distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
#See the License for the specific language governing permissions and
|
15
|
+
#limitations under the License.
|
16
|
+
|
1
17
|
require 'json'
|
2
18
|
require 'gitchefsync/config'
|
3
19
|
require 'gitchefsync/io_util'
|
@@ -15,7 +31,7 @@ module Gitchefsync
|
|
15
31
|
|
16
32
|
#adds an audit item
|
17
33
|
def add ( item )
|
18
|
-
@list << item
|
34
|
+
@list << item
|
19
35
|
end
|
20
36
|
|
21
37
|
def addItem(name, version)
|
@@ -23,16 +39,16 @@ module Gitchefsync
|
|
23
39
|
add(item)
|
24
40
|
end
|
25
41
|
|
26
|
-
def addCookbook(cookbook,action="UPDATE",exception=nil)
|
27
|
-
item = AuditItem.new(cookbook.name,cookbook.version,exception,action)
|
42
|
+
def addCookbook(cookbook,action="UPDATE",exception=nil, extra_info = nil)
|
43
|
+
item = AuditItem.new(cookbook.name,cookbook.version,exception,action,extra_info)
|
28
44
|
item.setCookbook(cookbook)
|
29
45
|
add(item)
|
30
46
|
end
|
31
47
|
|
32
48
|
#This gives enough information
|
33
|
-
def addEnv(name,action='UPDATE',exception=nil)
|
49
|
+
def addEnv(name,action='UPDATE',exception=nil, extra_info=nil)
|
34
50
|
cb = Cookbook.new(name,'','mandolin','mandolin@blackberry.com')
|
35
|
-
addCookbook(cb,action,exception)
|
51
|
+
addCookbook(cb,action,exception,extra_info)
|
36
52
|
end
|
37
53
|
|
38
54
|
#writes the audit out
|
@@ -40,12 +56,26 @@ module Gitchefsync
|
|
40
56
|
#and an audit-type-timestamp.json
|
41
57
|
def write
|
42
58
|
begin
|
59
|
+
unless File.exists? @fileLocation
|
60
|
+
FS.cmd "mkdir -p #{@fileLocation}"
|
61
|
+
end
|
43
62
|
fileLoc = @fileLocation + "/audit-" +@type+ @ts.to_s + ".json"
|
44
63
|
#fileCurrent = @fileLocation + "/audit-" +@type+ "-current" + ".json"
|
45
64
|
if @list.length > 0
|
46
65
|
Gitchefsync.logger.debug "event_id=write_audit:file_loc=#{fileLoc}"
|
47
66
|
file = File.open(fileLoc, "w")
|
48
|
-
|
67
|
+
list_hash = Array.new
|
68
|
+
@list.each do |item|
|
69
|
+
list_hash << item.to_hash
|
70
|
+
end
|
71
|
+
audit_hash = Hash.new
|
72
|
+
audit_hash['host_source'] = FS.cmd "hostname"
|
73
|
+
audit_hash['date'] = Time.now
|
74
|
+
#time taken from time of start of audit process -construction, until it's writing (now)
|
75
|
+
audit_hash['audit_written_secs'] = Time.now.to_i - @ts
|
76
|
+
audit_hash['num_items'] = list_hash.length()
|
77
|
+
audit_hash['items'] = list_hash
|
78
|
+
json = JSON.generate(audit_hash)
|
49
79
|
file.write(json)
|
50
80
|
#create sym link to this file
|
51
81
|
latest = @fileLocation+ "/audit_" + @type + "_latest.json"
|
@@ -65,11 +95,24 @@ module Gitchefsync
|
|
65
95
|
|
66
96
|
#returns the latest audit file
|
67
97
|
def latest
|
98
|
+
latest = @fileLocation+ "/audit_" + @type + "_latest.json"
|
99
|
+
if File.exists? latest
|
100
|
+
return latest
|
101
|
+
end
|
102
|
+
file = fileFrom(-1)
|
103
|
+
file
|
104
|
+
end
|
105
|
+
|
106
|
+
#returns the file from the latest:-1, next:-2 and so on
|
107
|
+
#returning nil if nothing found
|
108
|
+
def fileFrom(index)
|
68
109
|
entries = Dir.glob(@fileLocation + "/audit-#{@type}*")
|
69
110
|
file = nil
|
70
|
-
|
71
|
-
|
111
|
+
|
112
|
+
if entries != nil && (entries.length >= -index)
|
113
|
+
file = entries.sort[entries.length + index]
|
72
114
|
end
|
115
|
+
|
73
116
|
file
|
74
117
|
end
|
75
118
|
|
@@ -131,23 +174,74 @@ module Gitchefsync
|
|
131
174
|
end
|
132
175
|
json
|
133
176
|
end
|
134
|
-
|
135
|
-
|
136
|
-
|
177
|
+
|
178
|
+
#get audit hash from the
|
179
|
+
#
|
180
|
+
def auditItems(index)
|
181
|
+
file = fileFrom(index)
|
182
|
+
audit_list = Array.new
|
183
|
+
|
184
|
+
if !file.nil?
|
185
|
+
json = JSON.parse(File.read(file))
|
186
|
+
end
|
137
187
|
if json.nil?
|
138
|
-
|
188
|
+
return nil
|
139
189
|
end
|
140
190
|
audit_list = Array.new
|
141
|
-
|
191
|
+
#keep backward compatibility
|
192
|
+
if json.kind_of?(Array)
|
193
|
+
items = json
|
194
|
+
else
|
195
|
+
items = json['items']
|
196
|
+
end
|
197
|
+
items.each do |audit_item|
|
142
198
|
audit_list << AuditItem.new(nil,nil).from_hash(audit_item)
|
143
199
|
end
|
144
200
|
audit_list
|
201
|
+
|
202
|
+
end
|
203
|
+
|
204
|
+
def latestAuditItems
|
205
|
+
auditItems(-1)
|
206
|
+
end
|
207
|
+
|
208
|
+
#finds the audit item by audit item name - to be used with a
|
209
|
+
#method latestAuditItems (above)
|
210
|
+
#@param name - the name of the item
|
211
|
+
#@param audit - an array of audit items
|
212
|
+
def itemByName(name, audit)
|
213
|
+
ret = nil
|
214
|
+
audit.each do |item|
|
215
|
+
|
216
|
+
if item.name.eql? name
|
217
|
+
ret = item
|
218
|
+
break
|
219
|
+
end
|
220
|
+
end
|
221
|
+
ret
|
222
|
+
end
|
223
|
+
def itemByNameVersion(name,version, audit)
|
224
|
+
ret = nil
|
225
|
+
audit.each do |item|
|
226
|
+
|
227
|
+
if item.name.eql?(name) && item.version.eql?(version)
|
228
|
+
ret = item
|
229
|
+
break
|
230
|
+
end
|
231
|
+
end
|
232
|
+
ret
|
145
233
|
end
|
146
|
-
|
147
234
|
#if the json has exceptions
|
148
235
|
def hasError (json_obj)
|
149
236
|
ret = false
|
150
|
-
|
237
|
+
#keep backward compatibility
|
238
|
+
if json_obj.kind_of?(Array)
|
239
|
+
items = json_obj
|
240
|
+
else
|
241
|
+
items = json_obj['items']
|
242
|
+
end
|
243
|
+
|
244
|
+
items.each do |item|
|
151
245
|
if item['exception'] != nil then ret = true end
|
152
246
|
end
|
153
247
|
ret
|
@@ -158,17 +252,21 @@ module Gitchefsync
|
|
158
252
|
#TODO: just reference Cookbook clas in knife_util
|
159
253
|
class AuditItem
|
160
254
|
|
161
|
-
def initialize(name, version, exception = nil, action = 'UPDATE', ts = Time.now)
|
255
|
+
def initialize(name, version, exception = nil, action = 'UPDATE', extra_info = nil, ts = Time.now)
|
162
256
|
@name = name
|
163
257
|
@version = version
|
164
258
|
@ts = ts.to_i
|
165
259
|
@exception = exception
|
166
260
|
@action = action
|
261
|
+
@extra_info = extra_info
|
167
262
|
end
|
168
263
|
|
169
264
|
def name
|
170
265
|
@name
|
171
266
|
end
|
267
|
+
def version
|
268
|
+
@version
|
269
|
+
end
|
172
270
|
def ex
|
173
271
|
@exception
|
174
272
|
end
|
@@ -187,6 +285,12 @@ module Gitchefsync
|
|
187
285
|
@action = action
|
188
286
|
end
|
189
287
|
|
288
|
+
def extra_info
|
289
|
+
@extra_info
|
290
|
+
end
|
291
|
+
def set_extra_info hash
|
292
|
+
@extra_info = hash
|
293
|
+
end
|
190
294
|
#this method doesn't work when called when exception is created from json (from_hash)
|
191
295
|
def to_hash
|
192
296
|
h = Hash.new
|
@@ -202,6 +306,7 @@ module Gitchefsync
|
|
202
306
|
h[:action] = @action unless @action == nil
|
203
307
|
h[:maintainer] = @cookbook.maintainer unless @cookbook == nil
|
204
308
|
h[:maintainer_email] = @cookbook.maintainer_email unless @cookbook == nil
|
309
|
+
h[:extra_info] = @extra_info unless @extra_info == nil
|
205
310
|
h
|
206
311
|
end
|
207
312
|
|
@@ -213,6 +318,7 @@ module Gitchefsync
|
|
213
318
|
@type = h['type']
|
214
319
|
@action = h['action']
|
215
320
|
@cookbook = Cookbook.new(@name,@version,h['maintainer'],h['maintainer_email'])
|
321
|
+
@extra_info = h['extra_info']
|
216
322
|
return self
|
217
323
|
end
|
218
324
|
end
|
data/lib/gitchefsync/common.rb
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
# Gitchefsync - git to chef sync toolset
|
2
|
+
#
|
3
|
+
# Copyright 2014, BlackBerry, Inc.
|
4
|
+
#
|
5
|
+
#Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
#you may not use this file except in compliance with the License.
|
7
|
+
#You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
#Unless required by applicable law or agreed to in writing, software
|
12
|
+
#distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
#See the License for the specific language governing permissions and
|
15
|
+
#limitations under the License.
|
16
|
+
|
17
|
+
|
1
18
|
module Gitchefsync
|
2
19
|
|
3
20
|
extend Gitchefsync::Configuration
|
@@ -43,6 +60,11 @@ module Gitchefsync
|
|
43
60
|
|
44
61
|
#@param project - Gitlab project object
|
45
62
|
def self.pullProject(project, verify_yml=false)
|
63
|
+
|
64
|
+
#MAND-791 skip private repositories
|
65
|
+
if !project['public']
|
66
|
+
logger.warn "event_id=private_project_detected:project=#{project['path_with_namespace']}"
|
67
|
+
end
|
46
68
|
p_name = project['path_with_namespace'].split('/').join('_')
|
47
69
|
project_path = File.join(@git_local, p_name)
|
48
70
|
|
data/lib/gitchefsync/config.rb
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
# Gitchefsync - git to chef sync toolset
|
2
|
+
#
|
3
|
+
# Copyright 2014, BlackBerry, Inc.
|
4
|
+
#
|
5
|
+
#Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
#you may not use this file except in compliance with the License.
|
7
|
+
#You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
#Unless required by applicable law or agreed to in writing, software
|
12
|
+
#distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
#See the License for the specific language governing permissions and
|
15
|
+
#limitations under the License.
|
16
|
+
|
1
17
|
require 'gitchefsync/opts'
|
2
18
|
require 'logger'
|
3
19
|
#Not available till ruby 2.0
|
@@ -27,6 +43,8 @@ module Gitchefsync
|
|
27
43
|
@git_local = options[:git_local]
|
28
44
|
@token = options[:private_token]
|
29
45
|
@stage_dir = config['stage_dir']
|
46
|
+
@audit_dir = config['stage_dir'] + "/audit"
|
47
|
+
config['audit_dir'] = @audit_dir
|
30
48
|
@rel_branch = config['release_branch']
|
31
49
|
@rel_branch ||= 'master'
|
32
50
|
@stage_cb_dir = options[:stage_cookbook_dir]
|
data/lib/gitchefsync/env_sync.rb
CHANGED
@@ -1,9 +1,26 @@
|
|
1
|
+
# Gitchefsync - git to chef sync toolset
|
2
|
+
#
|
3
|
+
# Copyright 2014, BlackBerry, Inc.
|
4
|
+
#
|
5
|
+
#Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
#you may not use this file except in compliance with the License.
|
7
|
+
#You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
#Unless required by applicable law or agreed to in writing, software
|
12
|
+
#distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
#See the License for the specific language governing permissions and
|
15
|
+
#limitations under the License.
|
16
|
+
|
1
17
|
require 'gitchefsync/git_util'
|
2
18
|
require 'gitchefsync/errors'
|
3
19
|
require 'gitchefsync/io_util'
|
4
20
|
require 'gitchefsync/audit'
|
5
21
|
require 'gitchefsync/config'
|
6
22
|
require 'gitchefsync/common'
|
23
|
+
require 'digest'
|
7
24
|
|
8
25
|
module Gitchefsync
|
9
26
|
|
@@ -84,7 +101,9 @@ module Gitchefsync
|
|
84
101
|
@stage_filepath = config['stage_dir']
|
85
102
|
@force_upload = config['force_upload']
|
86
103
|
@repo_list = repo_list
|
87
|
-
|
104
|
+
#this is a bit of a hack to determine if we're writing audit
|
105
|
+
@sous = config['sync_local']
|
106
|
+
@audit = Audit.new(config['audit_dir'], 'env' )
|
88
107
|
@audit_keep_trim = config['audit_keep_trim']
|
89
108
|
@audit_keep_trim ||= 20
|
90
109
|
@env_file_list = Array.new()
|
@@ -92,13 +111,13 @@ module Gitchefsync
|
|
92
111
|
@role_file_list = Array.new()
|
93
112
|
end
|
94
113
|
|
95
|
-
def reject_json
|
114
|
+
def reject_json content
|
96
115
|
file_json = nil
|
97
116
|
begin
|
98
|
-
|
99
|
-
file_json = JSON.parse
|
117
|
+
|
118
|
+
file_json = JSON.parse content
|
100
119
|
rescue Exception => e
|
101
|
-
Gitchefsync.logger.error "event_id=
|
120
|
+
Gitchefsync.logger.error "event_id=env_json_parse_error:file=#{file}"
|
102
121
|
@audit.addEnv(file,'UPDATE', e )
|
103
122
|
end
|
104
123
|
file_json
|
@@ -117,23 +136,23 @@ module Gitchefsync
|
|
117
136
|
Gitchefsync.logger.debug "event_id=json_is_valid:iden=#{iden}:basename=#{f['basename']}"
|
118
137
|
end
|
119
138
|
|
120
|
-
def upload_env(f,
|
121
|
-
Gitchefsync.logger.debug "event_id=upload_env:filepath=#{f['fullpath']}"
|
139
|
+
def upload_env(f, delta)
|
140
|
+
Gitchefsync.logger.debug "event_id=upload_env:filepath=#{f['fullpath']}:delta=#{delta}"
|
122
141
|
begin
|
123
142
|
validate_json(f, 'name')
|
124
143
|
@env_file_list << f['json']['name']
|
125
|
-
|
126
|
-
if
|
144
|
+
|
145
|
+
if delta || @force_upload
|
127
146
|
FS.cmd "#{@knife} environment from file #{f['fullpath']} --yes"
|
128
147
|
Gitchefsync.logger.info "event_id=environment_uploaded:file_json_name=#{f['json']['name']}:file=#{f['fullpath']}"
|
129
|
-
@audit.addEnv(f['fullpath'],'UPDATE' )
|
148
|
+
@audit.addEnv(f['fullpath'],'UPDATE',nil,f['extra_info'] )
|
130
149
|
else
|
131
150
|
Gitchefsync.logger.debug "event_id=environment_not_uploaded:file_json_name=#{f['json']['name']}:file=#{f['fullpath']}"
|
132
|
-
@audit.addEnv(f['fullpath'],'EXISTING' )
|
151
|
+
@audit.addEnv(f['fullpath'],'EXISTING',nil,f['extra_info'] )
|
133
152
|
end
|
134
153
|
rescue ValidationError => e
|
135
154
|
Gitchefsync.logger.error("event_id=validation_error:msg=#{e.message}")
|
136
|
-
@audit.addEnv(f['fullpath'],'UPDATE', e )
|
155
|
+
@audit.addEnv(f['fullpath'],'UPDATE', e ,f['extra_info'])
|
137
156
|
end
|
138
157
|
end
|
139
158
|
|
@@ -147,45 +166,45 @@ module Gitchefsync
|
|
147
166
|
raise ValidationError, "event_id=invalid_path_to_data_bag_json:path=#{fullpath}"
|
148
167
|
end
|
149
168
|
|
150
|
-
def upload_db(f,
|
151
|
-
Gitchefsync.logger.debug "event_id=upload_data_bag:filepath=#{f['fullpath']}"
|
169
|
+
def upload_db(f, delta)
|
170
|
+
Gitchefsync.logger.debug "event_id=upload_data_bag:filepath=#{f['fullpath']}:delta=#{delta}"
|
152
171
|
db_iden = data_bag_iden(f['fullpath'])
|
153
172
|
begin
|
154
173
|
validate_json(f, 'id')
|
155
174
|
@db_file_list << [db_iden, f['json']['id']]
|
156
|
-
show_out = FS.cmdNoError "#{@knife} data bag show #{db_iden} #{f['json']['id']}"
|
157
|
-
if
|
175
|
+
#show_out = FS.cmdNoError "#{@knife} data bag show #{db_iden} #{f['json']['id']}"
|
176
|
+
if delta || @force_upload
|
158
177
|
FS.cmd "#{@knife} data bag create #{db_iden}"
|
159
178
|
FS.cmd "#{@knife} data bag from file #{db_iden} #{f['fullpath']}"
|
160
179
|
Gitchefsync.logger.info "event_id=databag_uploaded:file_json_name=#{f['json']['id']}:file=#{f['fullpath']}"
|
161
|
-
@audit.addEnv(f['fullpath'],'UPDATE' )
|
180
|
+
@audit.addEnv(f['fullpath'],'UPDATE', nil, f['extra_info'] )
|
162
181
|
else
|
163
182
|
Gitchefsync.logger.debug "event_id=data_bag_not_uploaded:file_json_name=#{f['json']['id']}:file=#{f['fullpath']}"
|
164
|
-
@audit.addEnv(f['fullpath'],'EXISTING')
|
183
|
+
@audit.addEnv(f['fullpath'],'EXISTING', nil, f['extra_info'])
|
165
184
|
end
|
166
185
|
rescue ValidationError => e
|
167
186
|
Gitchefsync.logger.error("event_id=validation_error:msg=#{e.message}")
|
168
|
-
@audit.addEnv(f['fullpath'],'UPDATE', e )
|
187
|
+
@audit.addEnv(f['fullpath'],'UPDATE', e , f['extra_info'])
|
169
188
|
end
|
170
189
|
end
|
171
190
|
|
172
|
-
def upload_role(f,
|
173
|
-
Gitchefsync.logger.debug "event_id=upload_role:fullpath=#{f['fullpath']}"
|
191
|
+
def upload_role(f, delta)
|
192
|
+
Gitchefsync.logger.debug "event_id=upload_role:fullpath=#{f['fullpath']}:delta=#{delta}"
|
174
193
|
begin
|
175
194
|
validate_json(f, 'name')
|
176
195
|
@role_file_list << f['json']['name']
|
177
|
-
|
178
|
-
if
|
196
|
+
|
197
|
+
if delta || @force_upload
|
179
198
|
FS.cmd "#{@knife} role from file #{f['fullpath']} --yes"
|
180
199
|
Gitchefsync.logger.info "event_id=role_uploaded:file_json_name=#{f['json']['name']}:file=#{f['fullpath']}"
|
181
|
-
@audit.addEnv(f['fullpath'],'UPDATE' )
|
200
|
+
@audit.addEnv(f['fullpath'],'UPDATE',nil, f['extra_info'] )
|
182
201
|
else
|
183
202
|
Gitchefsync.logger.debug "event_id=role_not_uploaded:file_json_name=#{f['json']['name']}:file=#{f['fullpath']}"
|
184
|
-
@audit.addEnv(f['fullpath'],'EXISTING' )
|
203
|
+
@audit.addEnv(f['fullpath'],'EXISTING', nil, f['extra_info'] )
|
185
204
|
end
|
186
205
|
rescue ValidationError => e
|
187
206
|
Gitchefsync.logger.error("event_id=validation_error:msg=#{e.message}")
|
188
|
-
@audit.addEnv(f['fullpath'],'UPDATE', e )
|
207
|
+
@audit.addEnv(f['fullpath'],'UPDATE', e , f['extra_info'])
|
189
208
|
end
|
190
209
|
end
|
191
210
|
|
@@ -244,13 +263,15 @@ module Gitchefsync
|
|
244
263
|
@audit.add(a)
|
245
264
|
end
|
246
265
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
266
|
+
|
267
|
+
if !@sous
|
268
|
+
@audit.write
|
269
|
+
#trim the audit file
|
270
|
+
@audit.trim(@audit_keep_trim)
|
271
|
+
end
|
252
272
|
end
|
253
273
|
|
274
|
+
|
254
275
|
def update_json_files
|
255
276
|
Gitchefsync.logger.info "event_id=update_json_files"
|
256
277
|
@env_file_list.clear
|
@@ -258,25 +279,52 @@ module Gitchefsync
|
|
258
279
|
@db_file_list.clear
|
259
280
|
@role_file_list.clear
|
260
281
|
|
282
|
+
#latest audit info for delta purposes
|
283
|
+
begin
|
284
|
+
latest_audit = @audit.latestAuditItems
|
285
|
+
latest_audit ||= Array.new
|
286
|
+
Gitchefsync.logger.info "event_id=audit_file_found:length=#{latest_audit.length}"
|
287
|
+
rescue AuditError => e
|
288
|
+
Gitchefsync.logger.warn "event_id=no_audit_file_found"
|
289
|
+
latest_audit = Array.new
|
290
|
+
end
|
291
|
+
|
292
|
+
|
261
293
|
@repo_list.each do |repo|
|
262
294
|
env_dir = repo.chef_path + "/**/*json"
|
263
295
|
|
264
296
|
Dir.glob(env_dir).each do |file|
|
265
297
|
|
266
298
|
file_attr = Hash.new()
|
267
|
-
|
299
|
+
content = File.read(file)
|
300
|
+
|
301
|
+
file_attr['json'] = reject_json(content)
|
268
302
|
next if file_attr['json'].nil?
|
269
303
|
file_attr['type'] = json_type(file)
|
270
304
|
file_attr['filename'] = File.basename(file)
|
271
305
|
file_attr['basename'] = File.basename(file).chomp(".json")
|
272
306
|
file_attr['fullpath'] = file
|
273
|
-
|
307
|
+
file_attr['extra_info'] = Hash.new
|
308
|
+
#To do comparison we'll hash current
|
309
|
+
file_attr['extra_info']['digest'] = Digest::SHA256.hexdigest content
|
310
|
+
#and compare hash to last audit
|
311
|
+
item = @audit.itemByName(file,latest_audit)
|
312
|
+
delta = true
|
313
|
+
if !item.nil?
|
314
|
+
Gitchefsync.logger.debug "event_id=audit_item_found:name=#{file}:digest=#{file_attr['extra_info']['digest']}"
|
315
|
+
if item.extra_info != nil && file_attr['extra_info']['digest'].eql?(item.extra_info['digest'])
|
316
|
+
Gitchefsync.logger.debug "file_digest=#{item.extra_info['digest']}"
|
317
|
+
delta = false
|
318
|
+
end
|
319
|
+
else
|
320
|
+
Gitchefsync.logger.warn "event_id=no_audit_item_found:name=#{file}"
|
321
|
+
end
|
274
322
|
if file_attr['type'].eql? "env"
|
275
|
-
upload_env(file_attr,
|
323
|
+
upload_env(file_attr, delta)
|
276
324
|
elsif file_attr['type'].eql? "db"
|
277
|
-
upload_db(file_attr,
|
325
|
+
upload_db(file_attr, delta)
|
278
326
|
elsif file_attr['type'].eql? "role"
|
279
|
-
upload_role(file_attr,
|
327
|
+
upload_role(file_attr, delta)
|
280
328
|
end
|
281
329
|
end
|
282
330
|
end
|
data/lib/gitchefsync/errors.rb
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
# Gitchefsync - git to chef sync toolset
|
2
|
+
#
|
3
|
+
# Copyright 2014, BlackBerry, Inc.
|
4
|
+
#
|
5
|
+
#Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
#you may not use this file except in compliance with the License.
|
7
|
+
#You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
#Unless required by applicable law or agreed to in writing, software
|
12
|
+
#distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
#See the License for the specific language governing permissions and
|
15
|
+
#limitations under the License.
|
1
16
|
|
2
17
|
#Define custom exception classes here
|
3
18
|
module Gitchefsync
|
@@ -18,6 +33,8 @@ module Gitchefsync
|
|
18
33
|
class BerksError < CmdError; end
|
19
34
|
|
20
35
|
class NoBerksError < BerksError; end
|
36
|
+
|
37
|
+
class BerksLockError < BerksError; end
|
21
38
|
|
22
39
|
class KnifeError < CmdError; end
|
23
40
|
|
data/lib/gitchefsync/git_util.rb
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
# Gitchefsync - git to chef sync toolset
|
2
|
+
#
|
3
|
+
# Copyright 2014, BlackBerry, Inc.
|
4
|
+
#
|
5
|
+
#Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
#you may not use this file except in compliance with the License.
|
7
|
+
#You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
#Unless required by applicable law or agreed to in writing, software
|
12
|
+
#distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
#See the License for the specific language governing permissions and
|
15
|
+
#limitations under the License.
|
16
|
+
|
1
17
|
require 'gitchefsync/config'
|
2
18
|
require 'gitlab'
|
3
19
|
#Git helper module
|
data/lib/gitchefsync/io_util.rb
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
# Gitchefsync - git to chef sync toolset
|
2
|
+
#
|
3
|
+
# Copyright 2014, BlackBerry, Inc.
|
4
|
+
#
|
5
|
+
#Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
#you may not use this file except in compliance with the License.
|
7
|
+
#You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
#Unless required by applicable law or agreed to in writing, software
|
12
|
+
#distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
#See the License for the specific language governing permissions and
|
15
|
+
#limitations under the License.
|
16
|
+
|
1
17
|
require 'open3'
|
2
18
|
require 'gitchefsync/errors'
|
3
19
|
# raise an excetpion here
|
@@ -1,3 +1,19 @@
|
|
1
|
+
# Gitchefsync - git to chef sync toolset
|
2
|
+
#
|
3
|
+
# Copyright 2014, BlackBerry, Inc.
|
4
|
+
#
|
5
|
+
#Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
#you may not use this file except in compliance with the License.
|
7
|
+
#You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
#Unless required by applicable law or agreed to in writing, software
|
12
|
+
#distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
#See the License for the specific language governing permissions and
|
15
|
+
#limitations under the License.
|
16
|
+
|
1
17
|
#helper file for parsing knife commands
|
2
18
|
#this may get refactored
|
3
19
|
|
data/lib/gitchefsync/log.rb
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
# Gitchefsync - git to chef sync toolset
|
2
|
+
#
|
3
|
+
# Copyright 2014, BlackBerry, Inc.
|
4
|
+
#
|
5
|
+
#Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
#you may not use this file except in compliance with the License.
|
7
|
+
#You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
#Unless required by applicable law or agreed to in writing, software
|
12
|
+
#distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
#See the License for the specific language governing permissions and
|
15
|
+
#limitations under the License.
|
16
|
+
|
1
17
|
module Gitchefsync
|
2
18
|
module Log
|
3
19
|
#Wrapped sys log Logger
|
data/lib/gitchefsync/notify.rb
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
# Gitchefsync - git to chef sync toolset
|
2
|
+
#
|
3
|
+
# Copyright 2014, BlackBerry, Inc.
|
4
|
+
#
|
5
|
+
#Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
#you may not use this file except in compliance with the License.
|
7
|
+
#You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
#Unless required by applicable law or agreed to in writing, software
|
12
|
+
#distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
#See the License for the specific language governing permissions and
|
15
|
+
#limitations under the License.
|
16
|
+
|
1
17
|
require 'gitchefsync/audit'
|
2
18
|
require 'gitchefsync/io_util'
|
3
19
|
require 'net/smtp'
|
@@ -36,27 +52,67 @@ module Gitchefsync
|
|
36
52
|
Gitchefsync.logger.info("event_id=notification_complete:audit_type=#{audit_type}")
|
37
53
|
end
|
38
54
|
|
55
|
+
def hasDelta(item1,item2)
|
56
|
+
|
57
|
+
if item1.nil? || item2.nil?
|
58
|
+
return true
|
59
|
+
end
|
60
|
+
i1 = item1.to_hash
|
61
|
+
i2 = item2.to_hash
|
62
|
+
|
63
|
+
if !i1[:extra_info].nil? && !i2[:extra_info].nil?
|
64
|
+
|
65
|
+
if !i1[:extra_info]['digest'].nil? && !i1[:extra_info]['digest'].eql?(i2[:extra_info]['digest']) then return true end
|
66
|
+
if !i1[:extra_info]['sha'].nil? && !i1[:extra_info]['sha'].eql?(i2[:extra_info]['sha']) then return true end
|
67
|
+
|
68
|
+
end
|
69
|
+
return false
|
70
|
+
end
|
39
71
|
#Aggregates a single email to the "to" email parameter
|
40
72
|
def singleNotifyFromAudit(audit_dir,audit_type,to)
|
41
73
|
audit = Audit.new(audit_dir,audit_type)
|
42
74
|
audit_list = audit.latestAuditItems
|
43
|
-
|
44
|
-
|
75
|
+
prev_audit = audit.auditItems(-2)
|
76
|
+
|
77
|
+
if audit_list.nil?
|
78
|
+
Gitchefsync.logger.warn "event_id=unable_to_notify:msg=audit_list_isnull:type=#{audit_type}"
|
79
|
+
return
|
80
|
+
end
|
81
|
+
empty = true
|
82
|
+
msg = "From: gitchefsync <mandolin@blackberry.com>\nTo: #{to}\nSubject: gitchefsync failure: summary\n\n"
|
83
|
+
msg << "Alert from Hostname: #{@hostname}\n"
|
84
|
+
type = "Environment"
|
85
|
+
if audit_type.eql?("cb")
|
86
|
+
type = "Cookbooks"
|
87
|
+
end
|
88
|
+
|
89
|
+
msg << "Notification Type: #{type}\n\n"
|
45
90
|
audit_list.each do |audit_item|
|
46
91
|
h = audit_item.to_hash
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
92
|
+
Gitchefsync.logger.debug "processing item: #{h} ex=#{h[:exception]} #{!h[:exception].nil? && !h[:exception].empty?}"
|
93
|
+
|
94
|
+
if !h[:exception].nil? && !h[:exception].empty?
|
95
|
+
|
96
|
+
if !prev_audit.nil? && hasDelta(audit_item,audit.itemByNameVersion(h[:name],h[:version],prev_audit))
|
97
|
+
Gitchefsync.logger.debug "item_has_exception=#{h}"
|
98
|
+
msg << "item: #{h[:name]}:#{h[:version]} was NOT processed with status #{h[:action]}\n"
|
99
|
+
msg << "audit_json= #{h}"
|
100
|
+
msg << "ERROR #{h[:exception]}\n\n"
|
101
|
+
empty = false
|
102
|
+
|
103
|
+
end
|
104
|
+
|
56
105
|
end
|
57
|
-
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
if !empty
|
110
|
+
Gitchefsync.logger.debug "sending msg=#{msg}"
|
111
|
+
sendTo(to,msg)
|
112
|
+
else
|
113
|
+
Gitchefsync.logger.info "event_id=no_message_sent"
|
58
114
|
end
|
59
|
-
|
115
|
+
|
60
116
|
end
|
61
117
|
|
62
118
|
def send(body)
|
data/lib/gitchefsync/opts.rb
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
# Gitchefsync - git to chef sync toolset
|
2
|
+
#
|
3
|
+
# Copyright 2014, BlackBerry, Inc.
|
4
|
+
#
|
5
|
+
#Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
#you may not use this file except in compliance with the License.
|
7
|
+
#You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
#Unless required by applicable law or agreed to in writing, software
|
12
|
+
#distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
#See the License for the specific language governing permissions and
|
15
|
+
#limitations under the License.
|
16
|
+
|
1
17
|
require 'gitlab'
|
2
18
|
require 'gitchefsync/errors'
|
3
19
|
module Gitchefsync
|
data/lib/gitchefsync/schedule.rb
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
# Gitchefsync - git to chef sync toolset
|
2
|
+
#
|
3
|
+
# Copyright 2014, BlackBerry, Inc.
|
4
|
+
#
|
5
|
+
#Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
#you may not use this file except in compliance with the License.
|
7
|
+
#You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
#Unless required by applicable law or agreed to in writing, software
|
12
|
+
#distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
#See the License for the specific language governing permissions and
|
15
|
+
#limitations under the License.
|
1
16
|
require 'timeout'
|
2
17
|
|
3
18
|
module Gitchefsync
|
@@ -57,7 +72,8 @@ module Gitchefsync
|
|
57
72
|
Gitchefsync.reconcile
|
58
73
|
cleanTmp()
|
59
74
|
Gitchefsync.logger.info "event_id=master_sync_completed"
|
60
|
-
|
75
|
+
#notification
|
76
|
+
Gitchefsync.notifyFromAudit()
|
61
77
|
# MAND-615 - This file will signal its ok for this directory to be sous sync target
|
62
78
|
File.write(File.join(@sous_rsync_src, "master_sync_completed"), "")
|
63
79
|
end
|
data/lib/gitchefsync/version.rb
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
# Gitchefsync - git to chef sync toolset
|
2
|
+
#
|
3
|
+
# Copyright 2014, BlackBerry, Inc.
|
4
|
+
#
|
5
|
+
#Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
#you may not use this file except in compliance with the License.
|
7
|
+
#You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
#Unless required by applicable law or agreed to in writing, software
|
12
|
+
#distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
#See the License for the specific language governing permissions and
|
15
|
+
#limitations under the License.
|
16
|
+
|
1
17
|
module Gitchefsync
|
2
|
-
VERSION = "0.6.
|
18
|
+
VERSION = "0.6.2"
|
3
19
|
end
|
data/spec/gitchefsync_spec.rb
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
# Gitchefsync - git to chef sync toolset
|
2
|
+
#
|
3
|
+
# Copyright 2014, BlackBerry, Inc.
|
4
|
+
#
|
5
|
+
#Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
#you may not use this file except in compliance with the License.
|
7
|
+
#You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
#Unless required by applicable law or agreed to in writing, software
|
12
|
+
#distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
#See the License for the specific language governing permissions and
|
15
|
+
#limitations under the License.
|
16
|
+
|
1
17
|
require 'rspec'
|
2
18
|
require 'gitchefsync'
|
3
19
|
require 'gitchefsync/opts'
|
data/spec/integration.rb
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
# Gitchefsync - git to chef sync toolset
|
2
|
+
#
|
3
|
+
# Copyright 2014, BlackBerry, Inc.
|
4
|
+
#
|
5
|
+
#Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
#you may not use this file except in compliance with the License.
|
7
|
+
#You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
#Unless required by applicable law or agreed to in writing, software
|
12
|
+
#distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
#See the License for the specific language governing permissions and
|
15
|
+
#limitations under the License.
|
16
|
+
|
1
17
|
require 'gitchefsync'
|
2
18
|
require 'gitlab'
|
3
19
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gitchefsync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marcus Simonsen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gitlab
|
@@ -87,7 +87,7 @@ files:
|
|
87
87
|
- spec/gitchefsync_spec.rb
|
88
88
|
- spec/integration.rb
|
89
89
|
- spec/sync-config.json
|
90
|
-
homepage: https://gitlab.rim.net/
|
90
|
+
homepage: https://gitlab.rim.net/chef/gitchefsync/tree/master
|
91
91
|
licenses:
|
92
92
|
- MIT
|
93
93
|
metadata: {}
|