chake 0.21.2 → 0.80

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.ackrc +1 -0
  3. data/.gitignore +22 -0
  4. data/.gitlab-ci.yml +24 -0
  5. data/.manifest +63 -0
  6. data/.rubocop.yml +53 -0
  7. data/.rubocop_todo.yml +40 -0
  8. data/ChangeLog.md +15 -0
  9. data/README.chef.md +70 -0
  10. data/README.itamae.md +58 -0
  11. data/README.md +110 -85
  12. data/README.shell.md +30 -0
  13. data/Rakefile +34 -10
  14. data/bin/chake +2 -2
  15. data/chake.gemspec +16 -16
  16. data/examples/test/.ssh_config +4 -0
  17. data/examples/test/Rakefile +1 -1
  18. data/examples/test/Vagrantfile +6 -0
  19. data/examples/test/config.rb +4 -4
  20. data/examples/test/cookbooks/basics/recipes/default.rb +1 -0
  21. data/examples/test/cookbooks/example/files/default/test +1 -0
  22. data/examples/test/cookbooks/example/files/{host-homer → host-lemur}/test.asc +0 -0
  23. data/lib/chake.rb +86 -153
  24. data/lib/chake/bootstrap/{01_debian.sh → chef/01_debian.sh} +0 -0
  25. data/lib/chake/bootstrap/{99_unsupported.sh → chef/99_unsupported.sh} +0 -0
  26. data/lib/chake/config.rb +2 -7
  27. data/lib/chake/config_manager.rb +93 -0
  28. data/lib/chake/config_manager/chef.rb +35 -0
  29. data/lib/chake/config_manager/itamae.rb +58 -0
  30. data/lib/chake/config_manager/shell.rb +34 -0
  31. data/lib/chake/config_manager/skel/chef/Rakefile +1 -0
  32. data/lib/chake/config_manager/skel/chef/config.rb +4 -0
  33. data/lib/chake/config_manager/skel/chef/cookbooks/basics/recipes/default.rb +1 -0
  34. data/lib/chake/config_manager/skel/chef/nodes.yaml +3 -0
  35. data/lib/chake/config_manager/skel/itamae/Rakefile +1 -0
  36. data/lib/chake/config_manager/skel/itamae/cookbooks/basics/default.rb +1 -0
  37. data/lib/chake/config_manager/skel/itamae/nodes.yaml +3 -0
  38. data/lib/chake/config_manager/skel/itamae/roles/basic.rb +1 -0
  39. data/lib/chake/config_manager/skel/shell/Rakefile +1 -0
  40. data/lib/chake/config_manager/skel/shell/nodes.yaml +3 -0
  41. data/lib/chake/connection.rb +83 -0
  42. data/lib/chake/{backend → connection}/local.rb +2 -8
  43. data/lib/chake/{backend → connection}/ssh.rb +6 -14
  44. data/lib/chake/node.rb +49 -29
  45. data/lib/chake/readline.rb +6 -10
  46. data/lib/chake/version.rb +1 -1
  47. data/man/.gitignore +2 -0
  48. data/man/Rakefile +27 -14
  49. data/man/readme2man.sed +5 -5
  50. data/spec/chake/backend/local_spec.rb +5 -6
  51. data/spec/chake/backend/ssh_spec.rb +8 -10
  52. data/spec/chake/backend_spec.rb +1 -2
  53. data/spec/chake/config_manager/chef_spec.rb +38 -0
  54. data/spec/chake/config_manager/itamae_spec.rb +69 -0
  55. data/spec/chake/config_manager/shell_spec.rb +54 -0
  56. data/spec/chake/config_manager_spec.rb +24 -0
  57. data/spec/chake/node_spec.rb +38 -15
  58. data/spec/spec_helper.rb +20 -18
  59. metadata +63 -43
  60. data/coverage/assets/0.11.0/application.css +0 -809
  61. data/coverage/assets/0.11.0/application.js +0 -43679
  62. data/coverage/assets/0.11.0/colorbox/border.png +0 -0
  63. data/coverage/assets/0.11.0/colorbox/controls.png +0 -0
  64. data/coverage/assets/0.11.0/colorbox/loading.gif +0 -0
  65. data/coverage/assets/0.11.0/colorbox/loading_background.png +0 -0
  66. data/coverage/assets/0.11.0/favicon_green.png +0 -0
  67. data/coverage/assets/0.11.0/favicon_red.png +0 -0
  68. data/coverage/assets/0.11.0/favicon_yellow.png +0 -0
  69. data/coverage/assets/0.11.0/loading.gif +0 -0
  70. data/coverage/assets/0.11.0/magnify.png +0 -0
  71. data/coverage/assets/0.11.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  72. data/coverage/assets/0.11.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  73. data/coverage/assets/0.11.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  74. data/coverage/assets/0.11.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  75. data/coverage/assets/0.11.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  76. data/coverage/assets/0.11.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  77. data/coverage/assets/0.11.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  78. data/coverage/assets/0.11.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  79. data/coverage/assets/0.11.0/smoothness/images/ui-icons_222222_256x240.png +0 -0
  80. data/coverage/assets/0.11.0/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  81. data/coverage/assets/0.11.0/smoothness/images/ui-icons_454545_256x240.png +0 -0
  82. data/coverage/assets/0.11.0/smoothness/images/ui-icons_888888_256x240.png +0 -0
  83. data/coverage/assets/0.11.0/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  84. data/coverage/index.html +0 -4158
  85. data/examples/test/nodes.yaml +0 -7
  86. data/examples/test/tmp/chake/test.local.bootstrap +0 -21
  87. data/examples/test/tmp/chake/test.local.json +0 -7
  88. data/examples/test/tmp/chake/test.local.plain.sha1sum +0 -9
  89. data/lib/chake/backend.rb +0 -80
  90. data/tags +0 -103
@@ -0,0 +1,30 @@
1
+ chake-shell(7) -- configure chake nodes with shell
2
+ ==================================================
3
+
4
+ ## Description
5
+
6
+ This configuration manager is a simpler wrapper for running a list of shell
7
+ commands on the nodes.
8
+
9
+ ## Configuration
10
+
11
+ The _shell_ configuration manager requires one key called `shell`, and the
12
+ value must be a list of strings representing the list of commands to run on the
13
+ node when converging.
14
+
15
+ ```yaml
16
+ host1.mycompany.com:
17
+ shell:
18
+ - echo "HELLO WORLD"
19
+ ```
20
+
21
+ ## Bootstrapping
22
+
23
+ Very little bootstrapping is required for this configuration manager, as we
24
+ hope every node you could possibly want to manage with it already has a POSIX
25
+ shell as `/bin/sh`. During bootstrapping, only the node hostname will be set
26
+ according to your chake configuration.
27
+
28
+ ## See also
29
+
30
+ * **chake(1)**
data/Rakefile CHANGED
@@ -1,5 +1,5 @@
1
1
  namespace :bundler do
2
- require "bundler/gem_tasks"
2
+ require 'bundler/gem_tasks'
3
3
  end
4
4
 
5
5
  task :test do
@@ -8,6 +8,8 @@ end
8
8
 
9
9
  pkg = Gem::Specification.load('chake.gemspec')
10
10
 
11
+ task 'bundler:build' => :manifest
12
+
11
13
  task 'build:tarball' => 'bundler:build' do
12
14
  chdir 'pkg' do
13
15
  sh 'gem2tgz', "#{pkg.name}-#{pkg.version}.gem"
@@ -17,7 +19,7 @@ end
17
19
  desc 'Create Debian source package'
18
20
  task 'build:debsrc' => ['bundler:clobber', 'build:tarball'] do
19
21
  dirname = "#{pkg.name}-#{pkg.version}"
20
- v = `git describe`.strip.gsub('-', '.').sub(/^v/, '')
22
+ v = `git describe`.strip.tr('-', '.').sub(/^v/, '')
21
23
  chdir 'pkg' do
22
24
  sh 'gem2deb', '--no-wnpp-check', '-s', '-p', pkg.name, "#{dirname}.tar.gz"
23
25
  sh "rename s/#{pkg.version}/#{v}/ *.orig.tar.gz"
@@ -31,7 +33,7 @@ task 'build:debsrc' => ['bundler:clobber', 'build:tarball'] do
31
33
  end
32
34
 
33
35
  desc 'Builds and installs Debian package'
34
- task 'deb:install' => 'build:debsrc'do
36
+ task 'deb:install' => 'build:debsrc' do
35
37
  chdir "pkg/#{pkg.name}-#{pkg.version}" do
36
38
  sh 'dpkg-buildpackage --diff-ignore=version.rb -us -uc'
37
39
  sh 'debi'
@@ -48,7 +50,7 @@ end
48
50
  file 'pkg/chake.spec' => ['chake.spec.erb', 'lib/chake/version.rb'] do |t|
49
51
  require 'erb'
50
52
  pkg = Gem::Specification.load('chake.gemspec')
51
- template = ERB.new(File.read('chake.spec.erb'))
53
+ template = ERB.new(File.read('chake.spec.erb'))
52
54
  File.open(t.name, 'w') do |f|
53
55
  f.puts(template.result(binding))
54
56
  end
@@ -60,27 +62,49 @@ task 'build:all' => ['build:debsrc', 'build:rpmsrc']
60
62
  desc 'lists changes since last release'
61
63
  task :changelog do
62
64
  last_tag = `git tag | sort -V`.split.last
63
- sh 'git', 'shortlog', last_tag + '..'
65
+ sh 'git', 'shortlog', "#{last_tag}.."
64
66
  end
65
67
 
66
68
  task :check_tag do
67
69
  last_tag = `git tag | sort -V`.split.last
68
70
  if last_tag == "v#{pkg.version}"
69
- fail "Version #{pkg.version} was already released!"
71
+ raise "Version #{pkg.version} was already released!"
70
72
  end
71
73
  end
72
74
 
73
75
  desc 'checks if the latest release is properly documented in ChangeLog.md'
74
76
  task :check_changelog do
75
77
  begin
76
- sh 'grep', '^#\s*' + pkg.version.to_s, 'ChangeLog.md'
77
- rescue
78
+ sh 'grep', "^#\\s*#{pkg.version}", 'ChangeLog.md'
79
+ rescue StandardError
78
80
  puts "Version #{pkg.version} not documented in ChangeLog.md!"
79
81
  raise
80
82
  end
81
83
  end
82
84
 
85
+ desc 'Updates manifest file'
86
+ task :manifest do
87
+ manifest = File.read('.manifest')
88
+ git = `git ls-files`
89
+ if manifest != git
90
+ File.open('.manifest', 'w') { |f| f.write(git) }
91
+ sh 'git commit .manifest -m "Update manifest"'
92
+ end
93
+ end
94
+
83
95
  desc 'Makes a release'
84
- task :release => [:check_tag, :check_changelog, :test, 'bundler:release']
96
+ task release: [:check_tag, :check_changelog, :test, 'bundler:release']
97
+
98
+ desc 'Check coding style'
99
+ task :style do
100
+ sh 'rubocop'
101
+ end
102
+
103
+ desc 'Check spelling in the source code'
104
+ task :codespell do
105
+ sh 'codespell', '--skip=.git', '--skip=coverage', '--skip=*.asc', '--skip=*.swp'
106
+ end
107
+
108
+ task default: [:test, :style, :codespell]
85
109
 
86
- task :default => :test
110
+ load './man/Rakefile'
data/bin/chake CHANGED
@@ -4,7 +4,7 @@ require 'rake'
4
4
 
5
5
  rakefiles = %w[rakefile Rakefile rakefile.rb Rakefile.rb]
6
6
 
7
- if (!rakefiles.any? { |f| File.exist?(f) }) && !ARGV.include?('-f') && !ARGV.include?('--rakefile')
7
+ if rakefiles.none? { |f| File.exist?(f) } && !ARGV.include?('-f') && !ARGV.include?('--rakefile')
8
8
  require 'tmpdir'
9
9
  require 'fileutils'
10
10
 
@@ -24,7 +24,7 @@ end
24
24
 
25
25
  class Rake::Application
26
26
  alias orig_thread_pool thread_pool
27
- def thread_pool # :nodoc:
27
+ def thread_pool # :nodoc:
28
28
  if Chake.respond_to?(:nodes)
29
29
  @thread_pool ||= Rake::ThreadPool.new(Chake.nodes.size + 1)
30
30
  else
@@ -1,27 +1,27 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require 'chake/version'
5
4
 
6
5
  Gem::Specification.new do |spec|
7
- spec.name = "chake"
6
+ spec.name = 'chake'
8
7
  spec.version = Chake::VERSION
9
- spec.authors = ["Antonio Terceiro"]
10
- spec.email = ["terceiro@softwarelivre.org"]
11
- spec.summary = %q{serverless configuration management tool for chef}
12
- spec.description = %q{chake allows one to manage a number of hosts via SSH by combining chef (solo) and rake. It doesn't require a chef server; all you need is a workstation from where you can SSH into all your hosts. chake automates copying the configuration management repository to the target host (including managing encrypted files), running chef on them, and running arbitrary commands on the hosts.}
13
- spec.homepage = "https://gitlab.com/terceiro/chake"
14
- spec.license = "MIT"
8
+ spec.authors = ['Antonio Terceiro']
9
+ spec.email = ['terceiro@softwarelivre.org']
10
+ spec.summary = 'serverless configuration management tool for chef'
11
+ spec.description = "chake allows one to manage a number of hosts via SSH by combining chef (solo) and rake. It doesn't require a chef server; all you need is a workstation from where you can SSH into all your hosts. chake automates copying the configuration management repository to the target host (including managing encrypted files), running chef on them, and running arbitrary commands on the hosts."
12
+ spec.homepage = 'https://gitlab.com/terceiro/chake'
13
+ spec.license = 'MIT'
15
14
 
16
- spec.files = Dir['**/*'] - Dir['pkg/**/*']
15
+ spec.files = File.read('.manifest').split("\n") + ['.manifest']
17
16
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
18
+ spec.require_paths = ['lib']
20
19
 
21
- spec.add_development_dependency "bundler", "~> 1.5"
22
- spec.add_development_dependency "rspec"
23
- spec.add_development_dependency "simplecov"
24
- spec.add_development_dependency "asciidoctor", '>= 1.5.5'
20
+ spec.add_development_dependency 'bundler', '~> 1.5'
21
+ spec.add_development_dependency 'ronn-ng'
22
+ spec.add_development_dependency 'rspec'
23
+ spec.add_development_dependency 'rubocop'
24
+ spec.add_development_dependency 'simplecov'
25
25
 
26
- spec.add_dependency "rake"
26
+ spec.add_dependency 'rake'
27
27
  end
@@ -0,0 +1,4 @@
1
+ Host test.local
2
+ IdentityFile .vagrant/machines/default/libvirt/private_key
3
+
4
+ # vim: ft=sshconfig
@@ -1,4 +1,4 @@
1
- $:.unshift '../../lib' # this shouldn't be needed when you have chake installed
1
+ $LOAD_PATH.unshift '../../lib' # this shouldn't be needed when you have chake installed
2
2
  require 'chake'
3
3
 
4
4
  manifest = %w[
@@ -0,0 +1,6 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ Vagrant.configure('2') do |config|
5
+ config.vm.box = 'debian/buster64'
6
+ end
@@ -1,4 +1,4 @@
1
- root = File.expand_path(File.dirname(__FILE__))
2
- file_cache_path root + '/cache'
3
- cookbook_path root + '/cookbooks'
4
- role_path root + '/config/roles'
1
+ root = __dir__
2
+ file_cache_path "#{root}/cache"
3
+ cookbook_path "#{root}/cookbooks"
4
+ role_path "#{root}/config/roles"
@@ -0,0 +1 @@
1
+ package 'openssh-server'
@@ -1,5 +1,3 @@
1
- # encoding: UTF-8
2
-
3
1
  require 'yaml'
4
2
  require 'json'
5
3
  require 'tmpdir'
@@ -7,159 +5,96 @@ require 'tmpdir'
7
5
  require 'chake/config'
8
6
  require 'chake/version'
9
7
  require 'chake/readline'
10
- require 'chake/tmpdir'
11
-
12
-
13
- desc "Initializes current directory with sample structure"
14
- task :init do
15
- if File.exists?('nodes.yaml')
16
- puts '[exists] nodes.yaml'
17
- else
18
- File.open('nodes.yaml', 'w') do |f|
19
- sample_nodes = <<EOF
20
- host1.mycompany.com:
21
- run_list:
22
- - recipe[basics]
23
- EOF
24
- f.write(sample_nodes)
25
- puts "[create] nodes.yaml"
26
- end
27
- end
28
-
29
- if File.exist?('nodes.d')
30
- puts '[exists] nodes.d/'
31
- else
32
- FileUtils.mkdir_p 'nodes.d'
33
- puts '[ mkdir] nodes.d/'
34
- end
35
-
36
-
37
- if File.exists?('config.rb')
38
- puts '[exists] config.rb'
39
- else
40
- File.open('config.rb', 'w') do |f|
41
- f.puts "root = File.expand_path(File.dirname(__FILE__))"
42
- f.puts "file_cache_path root + '/cache'"
43
- f.puts "cookbook_path root + '/cookbooks'"
44
- f.puts "role_path root + '/config/roles'"
45
- end
46
- puts "[create] config.rb"
47
- end
48
8
 
49
- if !File.exist?('config/roles')
50
- FileUtils.mkdir_p 'config/roles'
51
- puts '[ mkdir] config/roles'
52
- end
53
- if !File.exist?('cookbooks/basics/recipes')
54
- FileUtils.mkdir_p 'cookbooks/basics/recipes/'
55
- puts '[ mkdir] cookbooks/basics/recipes/'
56
- end
57
- recipe = 'cookbooks/basics/recipes/default.rb'
58
- if File.exists?(recipe)
59
- puts "[exists] #{recipe}"
60
- else
61
- File.open(recipe, 'w') do |f|
62
- f.puts "package 'openssh-server'"
63
- end
64
- puts "[create] #{recipe}"
65
- end
66
- if File.exists?('Rakefile')
67
- puts '[exists] Rakefile'
68
- else
69
- File.open('Rakefile', 'w') do |f|
70
- f.puts 'require "chake"'
71
- puts '[create] Rakefile'
72
- end
9
+ desc 'Initializes current directory with sample structure'
10
+ task init: 'init:itamae'
11
+ Chake::ConfigManager.all.map do |cfgmgr|
12
+ desc "Initializes current directory for #{cfgmgr.short_name}"
13
+ task "init:#{cfgmgr.short_name}" do
14
+ cfgmgr.init
73
15
  end
74
16
  end
75
17
 
76
18
  desc 'list nodes'
77
19
  task :nodes do
78
- Chake.nodes.each do |node|
79
- puts "%-40s %-5s\n" % [node.hostname, node.backend]
20
+ fields = %i[hostname connection config_manager]
21
+ IO.popen(['column', '-t'], mode: 'w') do |table|
22
+ table.puts(fields.join(' '))
23
+ table.puts(fields.map { |f| '-' * f.length }.join(' '))
24
+ Chake.nodes.each do |node|
25
+ table.puts fields.map { |f| node.send(f) }.join(' ')
26
+ end
80
27
  end
81
28
  end
82
29
 
83
30
  def encrypted_for(node)
84
- encrypted_files = Dir.glob("**/files/{default,host-#{node}}/*.{asc,gpg}") + Dir.glob("**/files/*.{asc,gpg}")
85
- encrypted_files.inject({}) do |hash, key|
31
+ encrypted_files = Dir.glob("**/files/{default,host-#{node}}/*.{asc,gpg}") + Dir.glob('**/files/*.{asc,gpg}')
32
+ encrypted_files.each_with_object({}) do |key, hash|
86
33
  hash[key] = key.sub(/\.(asc|gpg)$/, '')
87
- hash
88
34
  end
89
35
  end
90
36
 
91
37
  def if_files_changed(node, group_name, files)
92
- if files.empty?
93
- return
94
- end
95
- hash_io = IO.popen(['xargs', 'sha1sum'], 'w+')
38
+ return if files.empty?
39
+
40
+ hash_io = IO.popen(%w[xargs sha1sum], 'w+')
96
41
  files.sort.each { |f| hash_io.puts(f) }
97
42
  hash_io.close_write
98
43
  current_hash = hash_io.read
99
44
 
100
- hash_file = File.join(Chake.tmpdir, node + '.' + group_name + '.sha1sum')
45
+ hash_file = File.join(Chake.tmpdir, "#{node}.#{group_name}.sha1sum")
101
46
  hash_on_disk = nil
102
- if File.exists?(hash_file)
103
- hash_on_disk = File.read(hash_file)
104
- end
47
+ hash_on_disk = File.read(hash_file) if File.exist?(hash_file)
105
48
 
106
- if current_hash != hash_on_disk
107
- yield
108
- end
49
+ yield if current_hash != hash_on_disk
109
50
  FileUtils.mkdir_p(File.dirname(hash_file))
110
51
  File.open(hash_file, 'w') do |f|
111
52
  f.write(current_hash)
112
53
  end
113
54
  end
114
55
 
115
-
116
56
  def write_json_file(file, data)
117
- File.chmod(0600, file) if File.exists?(file)
118
- File.open(file, 'w', 0600) do |f|
57
+ File.chmod(0o600, file) if File.exist?(file)
58
+ File.open(file, 'w', 0o600) do |f|
119
59
  f.write(JSON.pretty_generate(data))
120
60
  f.write("\n")
121
61
  end
122
62
  end
123
63
 
124
- bootstrap_steps = Dir.glob(File.expand_path('chake/bootstrap/*.sh', File.dirname(__FILE__))).sort
125
-
126
64
  desc 'Executed before bootstrapping'
127
- task :bootstrap_common => :connect_common
65
+ task bootstrap_common: :connect_common
128
66
 
129
67
  desc 'Executed before uploading'
130
- task :upload_common => :connect_common
68
+ task upload_common: :connect_common
131
69
 
132
70
  desc 'Executed before uploading'
133
- task :converge_common => :connect_common
71
+ task converge_common: :connect_common
134
72
 
135
73
  desc 'Executed before connecting to any host'
136
74
  task :connect_common
137
75
 
138
76
  Chake.nodes.each do |node|
77
+ node.silent = Rake.application.options.silent
139
78
 
140
79
  hostname = node.hostname
141
- bootstrap_script = File.join(Chake.tmpdir, 'bootstrap-' + hostname)
142
-
143
- file bootstrap_script => bootstrap_steps do |t|
144
- mkdir_p(File.dirname(bootstrap_script))
145
- File.open(t.name, 'w') do |f|
146
- f.puts '#!/bin/sh'
147
- f.puts 'set -eu'
148
- bootstrap_steps.each do |platform|
149
- f.puts(File.read(platform))
150
- end
151
- end
152
- chmod 0755, t.name
153
- end
80
+
81
+ bootstrap_script = File.join(Chake.tmpdir, "#{hostname}.bootstrap")
82
+
83
+ bootstrap_steps = node.bootstrap_steps
84
+
85
+ bootstrap_code = (["#!/bin/sh\n", "set -eu\n"] + bootstrap_steps.map { |f| File.read(f) }).join
154
86
 
155
87
  desc "bootstrap #{hostname}"
156
- task "bootstrap:#{hostname}" => [:bootstrap_common, bootstrap_script] do
157
- config = File.join(Chake.tmpdir, hostname + '.json')
88
+ task "bootstrap:#{hostname}" => :bootstrap_common do
89
+ mkdir_p Chake.tmpdir unless File.directory?(Chake.tmpdir)
90
+ if node.needs_bootstrap? && (!File.exist?(bootstrap_script) || File.read(bootstrap_script) != bootstrap_code)
91
+
92
+ # create bootstrap script
93
+ File.open(bootstrap_script, 'w') do |f|
94
+ f.write(bootstrap_code)
95
+ end
96
+ chmod 0o755, bootstrap_script
158
97
 
159
- if File.exists?(config)
160
- # already bootstrapped, just overwrite
161
- write_json_file(config, node.data)
162
- else
163
98
  # copy bootstrap script over
164
99
  scp = node.scp
165
100
  target = "/tmp/.chake-bootstrap.#{Etc.getpwuid.name}"
@@ -167,28 +102,29 @@ Chake.nodes.each do |node|
167
102
 
168
103
  # run bootstrap script
169
104
  node.run_as_root("#{target} #{hostname}")
170
-
171
- # overwrite config with current contents
172
- mkdir_p File.dirname(config)
173
- write_json_file(config, node.data)
174
105
  end
175
106
 
107
+ # overwrite config with current contents
108
+ config = File.join(Chake.tmpdir, "#{hostname}.json")
109
+ write_json_file(config, node.data)
176
110
  end
177
111
 
178
112
  desc "upload data to #{hostname}"
179
113
  task "upload:#{hostname}" => :upload_common do
114
+ next unless node.needs_upload?
115
+
180
116
  encrypted = encrypted_for(hostname)
181
- rsync_excludes = (encrypted.values + encrypted.keys).map { |f| ["--exclude", f] }.flatten
182
- rsync_excludes << "--exclude" << ".git/"
183
- rsync_excludes << "--exclude" << "cache/"
184
- rsync_excludes << "--exclude" << "nodes/"
185
- rsync_excludes << "--exclude" << "local-mode-cache/"
117
+ rsync_excludes = (encrypted.values + encrypted.keys).map { |f| ['--exclude', f] }.flatten
118
+ rsync_excludes << '--exclude' << '.git/'
119
+ rsync_excludes << '--exclude' << 'cache/'
120
+ rsync_excludes << '--exclude' << 'nodes/'
121
+ rsync_excludes << '--exclude' << 'local-mode-cache/'
186
122
 
187
- rsync = node.rsync + ["-avp"] + ENV.fetch('CHAKE_RSYNC_OPTIONS', '').split
123
+ rsync = node.rsync + ['-avp'] + ENV.fetch('CHAKE_RSYNC_OPTIONS', '').split
188
124
  rsync_logging = Rake.application.options.silent && '--quiet' || '--verbose'
189
125
 
190
126
  hash_files = Dir.glob(File.join(Chake.tmpdir, '*.sha1sum'))
191
- files = Dir.glob("**/*").select { |f| !File.directory?(f) } - encrypted.keys - encrypted.values - hash_files
127
+ files = Dir.glob('**/*').reject { |f| File.directory?(f) } - encrypted.keys - encrypted.values - hash_files
192
128
  if_files_changed(hostname, 'plain', files) do
193
129
  sh *rsync, '--delete', rsync_logging, *rsync_excludes, './', node.rsync_dest
194
130
  end
@@ -199,14 +135,14 @@ Chake.nodes.each do |node|
199
135
  target = File.join(tmpdir, target_file)
200
136
  mkdir_p(File.dirname(target))
201
137
  rm_f target
202
- File.open(target, 'w', 0400) do |output|
138
+ File.open(target, 'w', 0o400) do |output|
203
139
  IO.popen(['gpg', '--quiet', '--batch', '--use-agent', '--decrypt', encrypted_file]) do |data|
204
140
  output.write(data.read)
205
141
  end
206
142
  end
207
143
  puts "#{target} (decrypted)"
208
144
  end
209
- sh *rsync, rsync_logging, tmpdir + '/', node.rsync_dest
145
+ sh *rsync, rsync_logging, "#{tmpdir}/", node.rsync_dest
210
146
  end
211
147
  end
212
148
  end
@@ -215,19 +151,17 @@ Chake.nodes.each do |node|
215
151
 
216
152
  desc "converge #{hostname}"
217
153
  task "converge:#{hostname}" => converge_dependencies do
218
- chef_logging = Rake.application.options.silent && '-l fatal' || ''
219
- node.run_as_root "sh -c 'rm -f #{node.path}/nodes/*.json && chef-solo -c #{node.path}/#{Chake.chef_config} #{chef_logging} -j #{node.path}/#{Chake.tmpdir}/#{hostname}.json'"
154
+ node.converge
220
155
  end
221
156
 
222
157
  desc 'apply <recipe> on #{hostname}'
223
- task "apply:#{hostname}", [:recipe] => [:recipe_input, :connect_common] do |task, args|
224
- chef_logging = Rake.application.options.silent && '-l fatal' || ''
225
- node.run_as_root "sh -c 'rm -f #{node.path}/nodes/*.json && chef-solo -c #{node.path}/#{Chake.chef_config} #{chef_logging} -j #{node.path}/#{Chake.tmpdir}/#{hostname}.json --override-runlist recipe[#{$recipe_to_apply}]'"
158
+ task "apply:#{hostname}", [:recipe] => %i[recipe_input connect_common] do |_task, _args|
159
+ node.apply($recipe_to_apply)
226
160
  end
227
161
  task "apply:#{hostname}" => converge_dependencies
228
162
 
229
163
  desc "run a command on #{hostname}"
230
- task "run:#{hostname}", [:command] => [:run_input, :connect_common] do
164
+ task "run:#{hostname}", [:command] => %i[run_input connect_common] do
231
165
  node.run($cmd_to_run)
232
166
  end
233
167
 
@@ -240,32 +174,31 @@ Chake.nodes.each do |node|
240
174
  task "check:#{hostname}" => :connect_common do
241
175
  node.run('sudo echo OK')
242
176
  end
243
-
244
177
  end
245
178
 
246
- task :run_input, :command do |task,args|
179
+ task :run_input, :command do |_task, args|
247
180
  $cmd_to_run = args[:command]
248
- if !$cmd_to_run
249
- puts "# Enter command to run (use arrow keys for history):"
181
+ unless $cmd_to_run
182
+ puts '# Enter command to run (use arrow keys for history):'
250
183
  $cmd_to_run = Chake::Readline::Commands.readline
251
184
  end
252
185
  if !$cmd_to_run || $cmd_to_run.strip == ''
253
186
  puts
254
- puts "I: no command provided, operation aborted."
187
+ puts 'I: no command provided, operation aborted.'
255
188
  exit(1)
256
189
  end
257
190
  end
258
191
 
259
- task :recipe_input, :recipe do |task,args|
192
+ task :recipe_input, :recipe do |_task, args|
260
193
  $recipe_to_apply = args[:recipe]
261
194
 
262
- if !$recipe_to_apply
195
+ unless $recipe_to_apply
263
196
  recipes = Dir['**/*/recipes/*.rb'].map do |f|
264
197
  f =~ %r{(.*/)?(.*)/recipes/(.*).rb$}
265
- cookbook = $2
266
- recipe = $3
198
+ cookbook = Regexp.last_match(2)
199
+ recipe = Regexp.last_match(3)
267
200
  recipe = nil if recipe == 'default'
268
- [cookbook,recipe].compact.join('::')
201
+ [cookbook, recipe].compact.join('::')
269
202
  end.sort
270
203
  puts 'Available recipes:'
271
204
 
@@ -276,43 +209,43 @@ task :recipe_input, :recipe do |task,args|
276
209
  $recipe_to_apply = Chake::Readline::Recipes.readline
277
210
  if !$recipe_to_apply || $recipe_to_apply.empty?
278
211
  puts
279
- puts "I: no recipe provided, operation aborted."
212
+ puts 'I: no recipe provided, operation aborted.'
280
213
  exit(1)
281
214
  end
282
- if !recipes.include?($recipe_to_apply)
215
+ unless recipes.include?($recipe_to_apply)
283
216
  abort "E: no such recipe: #{$recipe_to_apply}"
284
217
  end
285
218
  end
286
219
  end
287
220
 
288
- desc "upload to all nodes"
289
- multitask :upload => Chake.nodes.map { |node| "upload:#{node.hostname}" }
221
+ desc 'upload to all nodes'
222
+ multitask upload: Chake.nodes.map { |node| "upload:#{node.hostname}" }
290
223
 
291
- desc "bootstrap all nodes"
292
- multitask :bootstrap => Chake.nodes.map { |node| "bootstrap:#{node.hostname}" }
224
+ desc 'bootstrap all nodes'
225
+ multitask bootstrap: Chake.nodes.map { |node| "bootstrap:#{node.hostname}" }
293
226
 
294
- desc "converge all nodes (default)"
295
- multitask "converge" => Chake.nodes.map { |node| "converge:#{node.hostname}" }
227
+ desc 'converge all nodes (default)'
228
+ multitask 'converge' => Chake.nodes.map { |node| "converge:#{node.hostname}" }
296
229
 
297
- desc "Apply <recipe> on all nodes"
298
- multitask "apply", [:recipe] => Chake.nodes.map { |node| "apply:#{node.hostname}" }
230
+ desc 'Apply <recipe> on all nodes'
231
+ multitask 'apply', [:recipe] => Chake.nodes.map { |node| "apply:#{node.hostname}" }
299
232
 
300
- desc "run <command> on all nodes"
233
+ desc 'run <command> on all nodes'
301
234
  multitask :run, [:command] => Chake.nodes.map { |node| "run:#{node.hostname}" }
302
235
 
303
- task :default => :converge
236
+ task default: :converge
304
237
 
305
238
  desc 'checks connectivity and setup on all nodes'
306
- multitask :check => (Chake.nodes.map { |node| "check:#{node.hostname}" }) do
307
- puts "✓ all hosts OK"
308
- puts " - ssh connection works"
309
- puts " - password-less sudo works"
239
+ multitask check: (Chake.nodes.map { |node| "check:#{node.hostname}" }) do
240
+ puts '✓ all hosts OK'
241
+ puts ' - ssh connection works'
242
+ puts ' - password-less sudo works'
310
243
  end
311
244
 
312
245
  desc 'runs a Ruby console in the chake environment'
313
246
  task :console do
314
247
  require 'irb'
315
- IRB.setup(eval("__FILE__"), argv: [])
248
+ IRB.setup('__FILE__', argv: [])
316
249
  workspace = IRB::WorkSpace.new(self)
317
250
 
318
251
  puts 'chake - interactive console'