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 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: {}