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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7d42fe53a3355fac66554627bcc30fedc5a28d9a
4
- data.tar.gz: 6a277f678f793afdf12308510e8be5466711068a
3
+ metadata.gz: a57596b84302167acc4a08933a924eded9d26f57
4
+ data.tar.gz: f672d7e712813563a212cab7aa5118de2b840c31
5
5
  SHA512:
6
- metadata.gz: c6c0d391f1033f08f0e919c38be05033e057b1195d6db064d2033abae366eaf1c1c62156f6a0873f9b8e15509c443c2354e0d39a46dba7e9fcc6969e1b8cd590
7
- data.tar.gz: b1f724fa77ee87ab65efa1bd48234fa34bacc96026222e96a25deced9cebee57469ee0207eaa0321295885651bab3018874bb3c35e73f59f0d46750831676486
6
+ metadata.gz: ae21d609ac0004a3825f44a6b12278abe40b1feabb739152aabb532ae4bade6e9d3ee29561dd44bedfaa37145ca11f7cd40696e54fe831ef3b2b896f91550957
7
+ data.tar.gz: 94da27966929e77ac27cd6ade202776801d9c0110f86fb1ff523f2a778df42c7338e764d800202d1f19a480318618140ff03bef742ecd346cbf54795d746b7ec
@@ -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/mandolin/gitchefsync/tree/master"
42
+ spec.homepage = "https://gitlab.rim.net/chef/gitchefsync/tree/master"
27
43
 
28
44
 
29
45
  end
@@ -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(@config['stage_dir'], 'env' )
55
+ audit = Audit.new(@audit_dir, 'env' )
40
56
  audit.trim(@audit_keep_trim)
41
57
 
42
- audit = Audit.new(@config['stage_dir'], 'cb' )
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.notifyFromAudit(@config['stage_dir'], 'cb' )
52
- notification.singleNotifyFromAudit(@config['stage_dir'],'env',@config['default_notify_email'])
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(@config['stage_dir'], 'cb')
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
- else
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
- rescue NoBerksError => e
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(@config['stage_dir'],'cb' )
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
- out = FS.cmd "cd #{cookbook_dir} && #{@knife} cookbook upload -a --force --cookbook-path=#{cookbook_dir}/cookbooks"
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(@config['stage_dir'], 'cb').latest == nil
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
@@ -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.to_hash
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
- json = JSON.generate(@list)
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
- if entries != nil
71
- file = entries.sort[entries.length-1]
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
- def latestAuditItems
136
- json = parseLatest
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
- raise AuditError, "No json available"
188
+ return nil
139
189
  end
140
190
  audit_list = Array.new
141
- json.each do |audit_item|
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
- json_obj.each do |item|
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
@@ -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
 
@@ -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]
@@ -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
- @audit = Audit.new(config['stage_dir'], 'env' )
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 file
114
+ def reject_json content
96
115
  file_json = nil
97
116
  begin
98
- json = File.read file
99
- file_json = JSON.parse json
117
+
118
+ file_json = JSON.parse content
100
119
  rescue Exception => e
101
- Gitchefsync.logger.error "event_id=env_parse_error:file=#{file}"
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, git_delta)
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
- show_out = FS.cmdNoError "#{@knife} environment show #{f['json']['name']}"
126
- if show_out.match("ERROR:") || git_delta || @force_upload
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, git_delta)
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 show_out.match("ERROR:") || git_delta || @force_upload
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, git_delta)
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
- show_out = FS.cmdNoError "#{@knife} role show #{f['json']['name']}"
178
- if show_out.match("ERROR:") || git_delta || @force_upload
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
- #TODO: must create audit for removal
248
-
249
- @audit.write
250
- #trim the audit file
251
- @audit.trim(@audit_keep_trim)
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
- file_attr['json'] = reject_json(file)
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, repo.git_delta)
323
+ upload_env(file_attr, delta)
276
324
  elsif file_attr['type'].eql? "db"
277
- upload_db(file_attr, repo.git_delta)
325
+ upload_db(file_attr, delta)
278
326
  elsif file_attr['type'].eql? "role"
279
- upload_role(file_attr, repo.git_delta)
327
+ upload_role(file_attr, delta)
280
328
  end
281
329
  end
282
330
  end
@@ -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
 
@@ -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
@@ -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
 
@@ -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
@@ -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
- msg = "From: gichefsync <mandolin@blackberry.com>\nTo: #{to}\nSubject: gitchefsync failure: summary\n\n"
44
- msg << "Alert from Hostname: #{@hostname}\n\n"
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
- if h[:exception] != nil
49
- ver = ""
50
- if !h[:version].empty? then ver = ":" + h[:version] end
51
-
52
- msg << "item: #{h[:name]}#{ver} was NOT processed with status #{h[:action]} "
53
- msg << "\nERROR #{h[:exception]}"
54
- else
55
- msg << "item: #{h[:name]} was NOT processed with status #{h[:action]} "
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
- msg << "\n\n"
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
- sendTo(to,msg)
115
+
60
116
  end
61
117
 
62
118
  def send(body)
@@ -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
@@ -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
@@ -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.1"
18
+ VERSION = "0.6.2"
3
19
  end
@@ -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'
@@ -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.1
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-14 00:00:00.000000000 Z
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/mandolin/gitchefsync/tree/master
90
+ homepage: https://gitlab.rim.net/chef/gitchefsync/tree/master
91
91
  licenses:
92
92
  - MIT
93
93
  metadata: {}