gitchefsync 0.6.1 → 0.6.2
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/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: {}
|