cheftacular 2.9.1 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0fe23950f4d89fd436f8f7123dc8c8f97a37142c
4
- data.tar.gz: b51e27e4ccfff017252831899bb337807cb880e5
3
+ metadata.gz: 8949fa37858773111202176ac29af437fcbb10b4
4
+ data.tar.gz: 672dfda5a31ed376cbd1f73ad486af1e3f9f1407
5
5
  SHA512:
6
- metadata.gz: 4b4e7adec32f861223b857e4854e4a31ed3bcfb0bd3ecd2a3f59f6e60891f7a83dfddbb7417764250bf87038622f825fdeffb9cbb2707ef3ebc0837b9e0eb758
7
- data.tar.gz: 58f52b6c9c6f1a551086e4cce607f6e673107f8d2582fc661c0978b1b40cf8e837b83c8279bf49ee1c2ba5c592a9343a73bef763694a9313ff8a8a28e4257634
6
+ metadata.gz: 983c929c9118974e86668048b1e4d67b5f53fc6903355e7abc668b6a69b46e7e34c35e2a74f76f5e28dcaedfa1cca12ab182b999321844344603e87778f5a8f8
7
+ data.tar.gz: c0aead1166459633e9fa03dbfd08f80ee2d23b65e78ea90a014474f34c1ae3db8c7d5af91ad4e0a96a0757ee8aab6744ea762ebbd90d361c7af7325cea8bfabb
@@ -35,7 +35,7 @@ class Cheftacular
35
35
  options, locs, ridley, logs_bag_hash, pass_bag_hash, bundle_command, cheftacular, passwords = @config['helper'].set_local_instance_vars
36
36
 
37
37
  #on is namespaced to SSHKit::Backend::Netssh.on
38
- on ( nodes.map { |n| @config['cheftacular']['deploy_user'] + "@" + n.public_ipaddress } ), in: :groups, limit: 10, wait: 5 do |host|
38
+ on ( nodes.map { |n| @config['cheftacular']['deploy_user'] + "@" + n.public_ipaddress } ), in: :groups, limit: 6, wait: 5 do |host|
39
39
  n = get_node_from_address(nodes, host.hostname)
40
40
 
41
41
  puts("Beginning chef client run for #{ n.name } (#{ n.public_ipaddress }) on role #{ options['role'] }") unless options['quiet']
@@ -54,13 +54,13 @@ class Cheftacular
54
54
  def migrate_wordpress nodes=[]
55
55
  puts "Method #{ __method__ } is not yet implemented"
56
56
 
57
- exit
57
+ return false
58
58
  end
59
59
 
60
60
  def migrate_nodejs nodes=[]
61
61
  puts "Method #{ __method__ } is not yet implemented"
62
62
 
63
- exit
63
+ return false
64
64
  end
65
65
 
66
66
  def migrate_all nodes=[]
@@ -9,19 +9,20 @@ class Cheftacular
9
9
  current_day = Time.now.strftime('%Y%m%d')
10
10
  current_time = Time.now.strftime('%H:%M')
11
11
 
12
+ audit_data = audit_run_as_hash
13
+
12
14
  @config[@options['env']]['audit_bag_hash']['audit_log'][current_day] ||= {}
13
15
  @config[@options['env']]['audit_bag_hash']['audit_log'][current_day][current_time] ||= []
14
- @config[@options['env']]['audit_bag_hash']['audit_log'][current_day][current_time] << read_audit_cache_file_to_hash
16
+ @config[@options['env']]['audit_bag_hash']['audit_log'][current_day][current_time] << audit_data
15
17
 
16
18
  @config['ChefDataBag'].save_audit_bag
17
- end
18
19
 
19
- def write_audit_cache_file
20
- File.open( @config['filesystem'].current_audit_file_path, "w") { |f| f.write( fetch_audit_data_hash ) }
20
+ audit_command_to_slack_queue(audit_data) unless @config['cheftacular']['slack']['notify_on_command_execute'].blank?
21
21
  end
22
22
 
23
- def read_audit_cache_file_to_hash ret_hash={}, options_to_ignore=[]
24
- ret_hash = Hash.class_eval( File.read( @config['filesystem'].current_audit_file_path ))
23
+ def audit_run_as_hash ret_hash={}, options_to_ignore=[]
24
+ ret_hash['hostname'] = Socket.gethostname
25
+ ret_hash['directory'] = @config['locs']['root']
25
26
  ret_hash['command'] = @options['command']
26
27
 
27
28
  options_to_ignore << :preferred_cloud if @options['preferred_cloud'] == @config['cheftacular']['preferred_cloud']
@@ -29,6 +30,8 @@ class Cheftacular
29
30
  options_to_ignore << :preferred_cloud_region if @options['preferred_cloud_region'] == @config['cheftacular']['preferred_cloud_region']
30
31
  options_to_ignore << :virtualization_mode if @options['virtualization_mode'] == @config['cheftacular']['virtualization_mode']
31
32
  options_to_ignore << :route_dns_changes_via if @options['route_dns_changes_via'] == @config['cheftacular']['route_dns_changes_via']
33
+ options_to_ignore << :sub_env
34
+ options_to_ignore << :command
32
35
 
33
36
  ret_hash['options'] = @options.dup.delete_if { |key, value| options_to_ignore.include?(key.to_sym) }
34
37
 
@@ -37,14 +40,24 @@ class Cheftacular
37
40
  ret_hash
38
41
  end
39
42
 
40
- def fetch_audit_data_hash ret_hash={}, ip=""
41
- ret_hash['hostname'] = Socket.gethostname
43
+ def compile_audit_hash_entry_as_array audit_hash, entry_number=0, ret_array=[]
44
+ ret_array << "#{ (entry_number.to_s + '. ') unless entry_number == 0 }#{ audit_hash['command'] }"
45
+ ret_array << " Hostname: #{ audit_hash['hostname'] }"
46
+ ret_array << " Directory: #{ audit_hash['directory'] }" if audit_hash.has_key?('directory')
47
+ ret_array << " Arguments: #{ audit_hash['arguments'] }" if !audit_hash['arguments'].nil? && !audit_hash['arguments'].empty?
48
+ ret_array << " Options: #{ audit_hash['options'].to_hash }" unless audit_hash['options'].empty?
49
+
50
+ ret_array = ret_array.map { |entry| entry.prepend(' ')} unless entry_number == 0
42
51
 
43
- ret_hash
44
- rescue StandardError => exception
45
- @config['filesystem'].cleanup_file_caches('current-audit-only')
52
+ ret_array
53
+ end
54
+
55
+ private
56
+
57
+ def audit_command_to_slack_queue audit_hash, msg=''
58
+ msg << compile_audit_hash_entry_as_array(audit_hash).join("\n")
46
59
 
47
- @config['error'].exception_output "Unable to finish parsing auditing hash", exception
60
+ @config['slack_queue'] << { message: msg.prepend('```').insert(-1, '```'), channel: @config['cheftacular']['slack']['notify_on_command_execute'] }
48
61
  end
49
62
  end
50
63
  end
@@ -39,8 +39,6 @@ class Cheftacular
39
39
  if @config['helper'].is_initialization_command?(ARGV[0])
40
40
  @options['command'] = ARGV[0] #this is normally set by parse_context but that is not run for initialization commands
41
41
  else
42
- #@config['stateless_action'].cheftacular_config('sync') unless @config['helper'].running_on_chef_node?
43
-
44
42
  @config['stateless_action'].initialize_data_bag_contents(@options['env']) #ensure basic structure are always maintained before each run
45
43
 
46
44
  @config['parser'].parse_application_context if @config['helper'].running_in_mode?('application')
@@ -50,6 +48,8 @@ class Cheftacular
50
48
  puts("Preparing to run command \"#{ @options['command'] }\"...") if @options['verbose']
51
49
 
52
50
  @config['auditor'].audit_run if @config['cheftacular']['auditing']
51
+
52
+ @config['queue_master'].work_off_slack_queue #this occurs twice so commands that don't "end" can be queued
53
53
  end
54
54
 
55
55
  @config['stateless_action'].check_cheftacular_yml_keys unless @config['helper'].is_initialization_command?(ARGV[0])
@@ -177,7 +177,7 @@ class Cheftacular
177
177
  chef_repo_cookbooks
178
178
  end
179
179
 
180
- def parse_version_from_berkshelf_cookbook berkshelf_cookbook
180
+ def parse_version_from_berkshelf_cookbook berkshelf_cookbook
181
181
  if File.exists?(File.expand_path("#{ @config['locs']['berks'] }/#{ berkshelf_cookbook }/metadata.rb"))
182
182
  File.read(File.expand_path("#{ @config['locs']['berks'] }/#{ berkshelf_cookbook }/metadata.rb")).gsub('"',"'").gsub(/^version[\s]*('\d[.\d]+')/).peek[/('\d[.\d]+')/].gsub("'",'')
183
183
  else
@@ -185,6 +185,10 @@ class Cheftacular
185
185
  end
186
186
  end
187
187
 
188
+ def parse_gemfile_gem_version gem_name
189
+ File.read(File.expand_path("#{ @config['locs']['root'] }/Gemfile"))[/#{ gem_name }.*([\d\.]+)/][/([\d\.]+)/]
190
+ end
191
+
188
192
  private
189
193
  def current_file_path file_name, use_timestamp=true
190
194
  File.join( @config['locs']['app-root'], 'tmp', @config['helper'].declassify, ( use_timestamp ? "#{ Time.now.strftime("%Y%m%d") }-#{ file_name }" : file_name ))
@@ -48,7 +48,7 @@ class Cheftacular
48
48
  def fetch_remote_version
49
49
  puts "Checking remote #{ declassify } version..."
50
50
 
51
- `gem list #{ declassify } --remote`[/(\d+\.\d+\.\d+)/]
51
+ `gem list #{ declassify } --remote`[/([\d\.]+)/]
52
52
  end
53
53
 
54
54
  def completion_rate? percent, mode
@@ -274,7 +274,7 @@ class Cheftacular
274
274
  next unless key.include?(method.to_s)
275
275
 
276
276
  if hash['exit_status'] && hash['exit_status'] == 1
277
- @config['stateless_action'].slack(hash['text'].prepend('```').insert(-1, '```'))
277
+ @config['slack_queue'] << { message: hash['text'].prepend('```').insert(-1, '```') }
278
278
 
279
279
  @config['error'].exception_output(on_failing_exit_status_message) if !on_failing_exit_status_message.blank?
280
280
  end
@@ -285,9 +285,22 @@ class Cheftacular
285
285
  def slack_current_deploy_arguments
286
286
  msg = "#{ Socket.gethostname } just set for the repository #{ @config['getter'].get_repository_from_role_name(@options['role']) }:\n"
287
287
  msg << "the organization to #{ @options['deploy_organization'] }\n" if @options['deploy_organization']
288
- msg << "the revision to #{ @options['target_revision'] }" if @options['target_revision']
288
+ msg << "the revision to #{ @options['target_revision'] }\n" if @options['target_revision']
289
+ msg << "In the environment: #{ @options['env'] }"
289
290
 
290
- @config['stateless_action'].slack(msg.prepend('```').insert(-1, '```'), @config['cheftacular']['slack']['notify_on_deployment_args'])
291
+ @config['slack_queue'] << { message: msg.prepend('```').insert(-1, '```'), channel: @config['cheftacular']['slack']['notify_on_deployment_args'] }
292
+ end
293
+
294
+ def display_currently_installed_version
295
+ puts "The current version of cheftacular is #{ Cheftacular::VERSION }"
296
+ end
297
+
298
+ def set_detected_cheftacular_version
299
+ @config['detected_cheftacular_version'] ||= if File.exists?( @config['filesystem'].current_version_file_path )
300
+ File.read( @config['filesystem'].current_version_file_path )
301
+ else
302
+ @config['helper'].fetch_remote_version
303
+ end
291
304
  end
292
305
  end
293
306
  end
@@ -55,9 +55,7 @@ class Cheftacular
55
55
 
56
56
  @config['helper'].completion_rate? 100, 'initializer'
57
57
 
58
- initialize_version_check if @config['cheftacular']['strict_version_checks']
59
-
60
- initialize_auditing_checks if @config['cheftacular']['auditing']
58
+ initialize_version_check if @config['cheftacular']['strict_version_checks']
61
59
 
62
60
  initialize_chef_repo_up_to_date if @config['cheftacular']['keep_chef_repo_cheftacular_yml_up_to_date']
63
61
  end
@@ -133,6 +131,12 @@ class Cheftacular
133
131
  @options['verbose'] = true
134
132
  end
135
133
 
134
+ opts.on('-V', '--version', "Displays the current version of cheftacular") do
135
+ @config['helper'].display_currently_installed_version
136
+
137
+ exit
138
+ end
139
+
136
140
  opts.on('--no-logs', "Do not make logs for any command") do
137
141
  @options['no_logs'] = true
138
142
  end
@@ -426,38 +430,30 @@ class Cheftacular
426
430
  end
427
431
  end
428
432
 
429
- def initialize_version_check detected_version=""
433
+ def initialize_version_check
430
434
  current_version = Cheftacular::VERSION
431
435
 
432
- detected_version = File.exists?( @config['filesystem'].current_version_file_path ) ? File.read( @config['filesystem'].current_version_file_path ) : @config['helper'].fetch_remote_version
436
+ @config['helper'].set_detected_cheftacular_version
433
437
 
434
- if @config['helper'].is_higher_version? detected_version, current_version
435
- puts "\n Your Cheftacular is out of date. Currently #{ current_version } and remote version is #{ detected_version }.\n"
438
+ if @config['helper'].is_higher_version? @config['detected_cheftacular_version'], current_version
439
+ puts "\n Your Cheftacular is out of date. Currently #{ current_version } and remote version is #{ @config['detected_cheftacular_version'] }.\n"
436
440
 
437
441
  if @config['internal_ruby_config'].include?('@global')
438
442
  puts "Please run rvm #{ @config['internal_ruby_config'] } do gem update cheftacular to update to the latest version"
439
443
  else
440
- puts "Please update the gemfile to #{ detected_version }, bundle install and then restart this process.\n"
444
+ @config['stateless_action'].update_cheftacular
441
445
  end
442
446
 
443
447
  exit
444
448
  else
445
449
  unless File.exists?( @config['filesystem'].current_version_file_path )
446
- puts "Creating file cache for #{ Time.now.strftime("%Y%m%d") } (#{ detected_version }). No new version detected."
450
+ puts "Creating file cache for #{ Time.now.strftime("%Y%m%d") } (#{ @config['detected_cheftacular_version'] }). No new version detected."
447
451
 
448
- @config['filesystem'].write_version_file detected_version
452
+ @config['filesystem'].write_version_file @config['detected_cheftacular_version']
449
453
  end
450
454
  end
451
455
  end
452
456
 
453
- def initialize_auditing_checks
454
- unless File.exists? @config['filesystem'].current_audit_file_path
455
- puts "Creating file cache for #{ Time.now.strftime("%Y%m%d") } audit data..."
456
-
457
- @config['auditor'].write_audit_cache_file
458
- end
459
- end
460
-
461
457
  def initialize_classes
462
458
  @config['auditor'] = Cheftacular::Auditor.new(@options, @config)
463
459
  @config['parser'] = Cheftacular::Parser.new(@options, @config)
@@ -8,9 +8,11 @@ class Cheftacular
8
8
  def work_off_slack_queue
9
9
  return true if @config['slack_queue'].empty?
10
10
 
11
- @config['slack_queue'].each do |message|
12
- @config['stateless_action'].slack(message)
11
+ @config['slack_queue'].each do |slack_hash|
12
+ @config['stateless_action'].slack(slack_hash[:message], slack_hash[:channel])
13
13
  end
14
+
15
+ @config['slack_queue'] = []
14
16
  end
15
17
  end
16
18
  end
@@ -72,5 +72,7 @@ class Cheftacular
72
72
 
73
73
  puts @config['documentation']['arguments']
74
74
  end
75
+
76
+ alias_method :flags, :arguments
75
77
  end
76
78
  end
@@ -16,13 +16,32 @@ class Cheftacular
16
16
  def check_cheftacular_yml_keys out=[], exit_on_missing=false, warn_on_missing=false
17
17
  base_message = "Your cheftacular.yml is missing the key KEY, its default value is being set to DEFAULT for this run."
18
18
 
19
+ #############################2.10.0################################################
20
+
21
+ unless @config['cheftacular'].has_key?('self_update_repository')
22
+ puts base_message.gsub('KEY', 'self_update_repository').gsub('DEFAULT', 'blank')
23
+
24
+ @config['cheftacular']['self_update_repository'] = ''
25
+
26
+ warn_on_missing = true
27
+ end
28
+
29
+ #############################2.9.2################################################
30
+
31
+ unless @config['cheftacular']['slack'].has_key?('notify_on_command_execute')
32
+ puts base_message.gsub('KEY', 'slack:notify_on_command_execute').gsub('DEFAULT', 'blank')
33
+
34
+ @config['cheftacular']['slack']['notify_command_execute'] = ''
35
+
36
+ warn_on_missing = true
37
+ end
38
+
19
39
  #############################2.9.0################################################
20
40
 
21
41
  unless @config['cheftacular']['slack'].has_key?('notify_on_deployment_args')
22
- #backup_config:global_backup_role_name
23
- base_message.gsub('KEY', 'notify_on_deployment_args').gsub('DEFAULT', 'false')
42
+ puts base_message.gsub('KEY', 'slack:notify_on_deployment_args').gsub('DEFAULT', 'blank')
24
43
 
25
- @config['cheftacular']['slack']['notify_on_deployment_args'] = false
44
+ @config['cheftacular']['slack']['notify_on_deployment_args'] = ''
26
45
 
27
46
  warn_on_missing = true
28
47
  end
@@ -30,8 +49,7 @@ class Cheftacular
30
49
  #############################2.7.0################################################
31
50
 
32
51
  unless @config['cheftacular'].has_key?('backup_config')
33
- #backup_config:global_backup_role_name
34
- base_message.gsub('KEY', 'backup_config').gsub('DEFAULT', 'nil')
52
+ puts base_message.gsub('KEY', 'backup_config').gsub('DEFAULT', 'nil')
35
53
 
36
54
  warn_on_missing = true
37
55
  end
@@ -4,7 +4,7 @@ class Cheftacular
4
4
  def cheftacular_config
5
5
  @config['documentation']['stateless_action'][__method__] ||= {}
6
6
  @config['documentation']['stateless_action'][__method__]['long_description'] = [
7
- "`cft cheftacular_config [display|sync|overwrite]` this command " +
7
+ "`cft cheftacular_config [diff|display|sync|overwrite]` this command " +
8
8
  "Allows you to interact with your complete cheftacular configuration, the union of all repository's cheftacular.ymls. ",
9
9
 
10
10
  [
@@ -27,7 +27,7 @@ class Cheftacular
27
27
  def cheftacular_config command=''
28
28
  command = ARGV[1] if command.blank?
29
29
 
30
- raise "Unsupported command (#{ command }) for cft cheftacular_config" unless command =~ /display|sync|overwrite/
30
+ raise "Unsupported command (#{ command }) for cft cheftacular_config" unless command =~ /diff|display|sync|overwrite/
31
31
 
32
32
  self.send("cheftacular_config_#{ command }")
33
33
  end
@@ -42,11 +42,7 @@ class Cheftacular
42
42
 
43
43
  compiled_audit_hash[day][time].each do |log_arr|
44
44
  log_arr.each do |log_hash|
45
- out << " #{ log_array_entry_count }. #{ log_hash['command'] }"
46
- out << " 1. Hostname: #{ log_hash['hostname'] }"
47
- out << " 3. Arguments: #{ log_hash['arguments'] }"
48
- out << " 4. Options: #{ log_hash['options'].to_hash }"
49
- out << ""
45
+ out << @config['auditor'].compile_audit_hash_entry_as_array(log_hash, log_array_entry_count)
50
46
 
51
47
  log_array_entry_count += 1
52
48
  end
@@ -56,7 +52,7 @@ class Cheftacular
56
52
  end
57
53
  end
58
54
 
59
- File.open("#{ @config['locs']['chef-log'] }/audit-log-#{ Time.now.strftime("%Y%m%d%H%M%S") }.md", "w") { |f| f.write(out.join("\n")) }
55
+ File.open("#{ @config['locs']['chef-log'] }/audit-log-#{ Time.now.strftime("%Y%m%d%H%M%S") }.md", "w") { |f| f.write(out.flatten.join("\n")) }
60
56
  end
61
57
  end
62
58
  end
@@ -20,10 +20,12 @@ class Cheftacular
20
20
 
21
21
  class StatelessAction
22
22
  def slack message='', channel=''
23
+ return false if @config['cheftacular']['slack']['webhook'].nil?
24
+
23
25
  @slack_notifier ||= Slack::Notifier.new @config['cheftacular']['slack']['webhook'], username: 'Cheftacular'
24
26
 
25
- message = ARGV[1] if message.blank?
26
- channel = ARGV[2] if channel.blank?
27
+ message = ARGV[1] if !message.nil? && message.blank?
28
+ channel = ARGV[2] if !channel.nil? && channel.blank?
27
29
 
28
30
  @slack_notifier.channel = channel.nil? ? @config['cheftacular']['slack']['default_channel'] : channel
29
31
  @slack_notifier.ping message
@@ -0,0 +1,85 @@
1
+
2
+ class Cheftacular
3
+ class StatelessActionDocumentation
4
+ def update_cheftacular
5
+ @config['documentation']['stateless_action'][__method__] ||= {}
6
+ @config['documentation']['stateless_action'][__method__]['long_description'] = [
7
+ "`cft #{ __method__ }` this command attempts to update cheftacular to the latest version."
8
+ ]
9
+
10
+ @config['documentation']['stateless_action'][__method__]['short_description'] = 'Update cheftacular to the latest version'
11
+
12
+ @config['documentation']['application'][__method__] = @config['documentation']['stateless_action'][__method__]
13
+ end
14
+ end
15
+
16
+ class StatelessAction
17
+ def update_cheftacular status_hash={}
18
+ update_cheftacular_not_configured_to_update if @config['cheftacular']['self_update_repository'] != @config['locs']['root']
19
+
20
+ @config['helper'].set_detected_cheftacular_version
21
+
22
+ puts "Attempting to update cheftacular from #{ Cheftacular::VERSION } to #{ @config['detected_cheftacular_version'] }..."
23
+
24
+ status_hash['gemfile_is_latest_version'] = update_cheftacular_from_git
25
+ status_hash['gemfile_is_latest_version'] = update_cheftacular_gemfile unless status_hash['gemfile_is_latest_version']
26
+ status_hash['bundled_latest_version'] = update_cheftacular_bundle if status_hash['gemfile_is_latest_version']
27
+
28
+ if !status_hash['gemfile_is_latest_version'] || !status_hash['bundled_latest_version']
29
+ puts(
30
+ "Issues occured in automatically updating your cheftacular " +
31
+ "to #{ @config['detected_cheftacular_version'] }, please send " +
32
+ "the output of this command to your DevOps administrator or add " +
33
+ "it as an issue at this gem's github page."
34
+ )
35
+ else
36
+ puts "Successfully installed version #{ @config['detected_cheftacular_version'] }, please re-run your command."
37
+ end
38
+ end
39
+
40
+ private
41
+ def update_cheftacular_from_git out=[]
42
+ out << `git reset --hard origin/master && git pull origin master`
43
+
44
+ parsed_gemfile_version = @config['filesystem'].parse_gemfile_gem_version('cheftacular')
45
+
46
+ puts "After git update, Gemfile lists version #{ parsed_gemfile_version } versus latest version: #{ @config['detected_cheftacular_version'] }"
47
+
48
+ return parsed_gemfile_version == @config['detected_cheftacular_version']
49
+ end
50
+
51
+ def update_cheftacular_gemfile
52
+ puts "Forcing gemfile update to the latest version of cheftacular..."
53
+
54
+ gemfile_path = File.expand_path("#{ @config['locs']['root'] }/Gemfile")
55
+ parsed_gemfile_version = @config['filesystem'].parse_gemfile_gem_version('cheftacular')
56
+ new_file_content = File.read(gemfile_path).gsub(parsed_gemfile_version, @config['detected_cheftacular_version'])
57
+
58
+ File.open( gemfile_path, "w") { |f| f.write(new_file_content) }
59
+
60
+ new_parsed_gemfile_version = @config['filesystem'].parse_gemfile_gem_version('cheftacular')
61
+
62
+ puts "After forced gemfile update, Gemfile lists version #{ new_parsed_gemfile_version } versus latest version: #{ @config['detected_cheftacular_version'] }"
63
+
64
+ return new_parsed_gemfile_version == @config['detected_cheftacular_version']
65
+ end
66
+
67
+ def update_cheftacular_bundle out=[]
68
+ puts "Running bundle install..."
69
+
70
+ out << `bundle install`
71
+
72
+ cheftacular_bundle_version = out.first[/cheftacular.*([\d\.]+)/][/([\d\.]+)/]
73
+
74
+ puts "After bundle install, version is #{ cheftacular_bundle_version } versus latest version: #{ @config['detected_cheftacular_version'] }"
75
+
76
+ return cheftacular_bundle_version == @config['detected_cheftacular_version']
77
+ end
78
+
79
+ def update_cheftacular_not_configured_to_update
80
+ puts "Please update the gemfile to #{ @config['detected_cheftacular_version'] }, bundle install and then restart this process.\n"
81
+
82
+ exit
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,27 @@
1
+
2
+ class Cheftacular
3
+ class StatelessActionDocumentation
4
+ def version
5
+ @config['documentation']['stateless_action'][__method__] ||= {}
6
+ @config['documentation']['stateless_action'][__method__]['long_description'] = [
7
+ "`cft version` this command prints out the current version of cheftacular.",
8
+ ]
9
+
10
+ @config['documentation']['stateless_action'][__method__]['short_description'] = 'Displays the current version of cheftacular'
11
+
12
+ @config['documentation']['application'][__method__] = @config['documentation']['stateless_action'][__method__]
13
+ end
14
+ end
15
+
16
+ class InitializationAction
17
+ def version
18
+
19
+ end
20
+ end
21
+
22
+ class StatelessAction
23
+ def version
24
+ @config['helper'].display_currently_installed_version
25
+ end
26
+ end
27
+ end
@@ -1,5 +1,5 @@
1
1
  class Cheftacular
2
2
  #major_version.minor_version.bugfixes
3
- VERSION = "2.9.1"
3
+ VERSION = "2.10.0"
4
4
  RUBY_VERSION = "2.2.2"
5
5
  end
@@ -36,11 +36,13 @@ module SSHKit
36
36
  end
37
37
 
38
38
  def get_true_environment run_list, chef_env_roles, default_env
39
- chef_env_roles.each_pair do |role, env|
40
- if run_list.include?("role[#{ role }]")
41
- default_env = env
39
+ unless chef_env_roles.nil?
40
+ chef_env_roles.each_pair do |role, env|
41
+ if run_list.include?("role[#{ role }]")
42
+ default_env = env
42
43
 
43
- break
44
+ break
45
+ end
44
46
  end
45
47
  end
46
48
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cheftacular
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.9.1
4
+ version: 2.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Louis Alridge
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-06 00:00:00.000000000 Z
11
+ date: 2015-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hashie
@@ -303,12 +303,14 @@ files:
303
303
  - lib/cheftacular/stateless_actions/slack.rb
304
304
  - lib/cheftacular/stateless_actions/test_env.rb
305
305
  - lib/cheftacular/stateless_actions/update_chef_client.rb
306
+ - lib/cheftacular/stateless_actions/update_cheftacular.rb
306
307
  - lib/cheftacular/stateless_actions/update_cloudflare_dns_from_cloud.rb
307
308
  - lib/cheftacular/stateless_actions/update_split_branches.rb
308
309
  - lib/cheftacular/stateless_actions/update_thecheftacularcookbook.rb
309
310
  - lib/cheftacular/stateless_actions/update_tld.rb
310
311
  - lib/cheftacular/stateless_actions/upload_nodes.rb
311
312
  - lib/cheftacular/stateless_actions/upload_roles.rb
313
+ - lib/cheftacular/stateless_actions/version.rb
312
314
  - lib/cheftacular/version.rb
313
315
  - lib/cloud_interactor/authentication.rb
314
316
  - lib/cloud_interactor/cloud_interactor.rb