chake 0.21 → 0.81.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ackrc +2 -0
- data/.gitignore +22 -0
- data/.gitlab-ci.yml +24 -0
- data/.manifest +65 -0
- data/.rubocop.yml +55 -0
- data/.rubocop_todo.yml +40 -0
- data/ChangeLog.md +37 -0
- data/README.chef.md +70 -0
- data/README.itamae.md +58 -0
- data/README.md +118 -85
- data/README.shell.md +30 -0
- data/Rakefile +36 -10
- data/bin/chake +2 -2
- data/chake.gemspec +16 -16
- data/examples/test/.ssh_config +4 -0
- data/examples/test/Rakefile +1 -1
- data/examples/test/Vagrantfile +6 -0
- data/examples/test/config.rb +4 -4
- data/examples/test/cookbooks/basics/recipes/default.rb +1 -0
- data/examples/test/cookbooks/example/files/default/test +1 -0
- data/examples/test/cookbooks/example/files/{host-homer → host-lemur}/test.asc +0 -0
- data/lib/chake.rb +111 -153
- data/lib/chake/bootstrap/chef/01_installed.sh +4 -0
- data/lib/chake/bootstrap/{01_debian.sh → chef/02_debian.sh} +0 -0
- data/lib/chake/bootstrap/{99_unsupported.sh → chef/99_unsupported.sh} +0 -0
- data/lib/chake/config.rb +2 -7
- data/lib/chake/config_manager.rb +89 -0
- data/lib/chake/config_manager/chef.rb +35 -0
- data/lib/chake/config_manager/itamae.rb +57 -0
- data/lib/chake/config_manager/shell.rb +34 -0
- data/lib/chake/config_manager/skel/chef/Rakefile +1 -0
- data/lib/chake/config_manager/skel/chef/config.rb +4 -0
- data/lib/chake/config_manager/skel/chef/cookbooks/basics/recipes/default.rb +1 -0
- data/lib/chake/config_manager/skel/chef/nodes.yaml +3 -0
- data/lib/chake/config_manager/skel/itamae/Rakefile +1 -0
- data/lib/chake/config_manager/skel/itamae/cookbooks/basics/default.rb +1 -0
- data/lib/chake/config_manager/skel/itamae/nodes.yaml +3 -0
- data/lib/chake/config_manager/skel/itamae/roles/basic.rb +1 -0
- data/lib/chake/config_manager/skel/shell/Rakefile +1 -0
- data/lib/chake/config_manager/skel/shell/nodes.yaml +3 -0
- data/lib/chake/connection.rb +83 -0
- data/lib/chake/{backend → connection}/local.rb +2 -8
- data/lib/chake/{backend → connection}/ssh.rb +6 -14
- data/lib/chake/node.rb +49 -29
- data/lib/chake/readline.rb +6 -10
- data/lib/chake/version.rb +1 -1
- data/lib/chake/wipe.rb +18 -0
- data/man/.gitignore +2 -0
- data/man/Rakefile +28 -14
- data/man/readme2man.sed +5 -5
- data/spec/chake/backend/local_spec.rb +5 -6
- data/spec/chake/backend/ssh_spec.rb +8 -10
- data/spec/chake/backend_spec.rb +1 -2
- data/spec/chake/config_manager/chef_spec.rb +38 -0
- data/spec/chake/config_manager/itamae_spec.rb +87 -0
- data/spec/chake/config_manager/shell_spec.rb +54 -0
- data/spec/chake/config_manager_spec.rb +23 -0
- data/spec/chake/node_spec.rb +38 -15
- data/spec/spec_helper.rb +37 -17
- metadata +65 -39
- data/coverage/assets/0.11.0/application.css +0 -809
- data/coverage/assets/0.11.0/application.js +0 -43679
- data/coverage/assets/0.11.0/colorbox/border.png +0 -0
- data/coverage/assets/0.11.0/colorbox/controls.png +0 -0
- data/coverage/assets/0.11.0/colorbox/loading.gif +0 -0
- data/coverage/assets/0.11.0/colorbox/loading_background.png +0 -0
- data/coverage/assets/0.11.0/favicon_green.png +0 -0
- data/coverage/assets/0.11.0/favicon_red.png +0 -0
- data/coverage/assets/0.11.0/favicon_yellow.png +0 -0
- data/coverage/assets/0.11.0/loading.gif +0 -0
- data/coverage/assets/0.11.0/magnify.png +0 -0
- data/coverage/assets/0.11.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/coverage/assets/0.11.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/coverage/assets/0.11.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/coverage/assets/0.11.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/coverage/assets/0.11.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/coverage/assets/0.11.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/coverage/assets/0.11.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/coverage/assets/0.11.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/coverage/assets/0.11.0/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/coverage/assets/0.11.0/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/coverage/assets/0.11.0/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/coverage/assets/0.11.0/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/coverage/assets/0.11.0/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/coverage/index.html +0 -4158
- data/lib/chake/backend.rb +0 -80
- data/tags +0 -72
File without changes
|
File without changes
|
data/lib/chake/config.rb
CHANGED
@@ -2,20 +2,15 @@ require 'chake/node'
|
|
2
2
|
|
3
3
|
module Chake
|
4
4
|
class << self
|
5
|
-
attr_accessor :chef_config
|
6
5
|
attr_accessor :nodes
|
7
|
-
attr_accessor :tmpdir
|
8
6
|
end
|
9
7
|
end
|
10
8
|
|
11
|
-
chef_config = ENV['CHAKE_CHEF_CONFIG'] || 'config.rb'
|
12
9
|
nodes_file = ENV['CHAKE_NODES'] || 'nodes.yaml'
|
13
10
|
nodes_directory = ENV['CHAKE_NODES_D'] || 'nodes.d'
|
14
|
-
node_data = File.
|
11
|
+
node_data = File.exist?(nodes_file) && YAML.load_file(nodes_file) || {}
|
15
12
|
Dir.glob(File.join(nodes_directory, '*.yaml')).sort.each do |f|
|
16
13
|
node_data.merge!(YAML.load_file(f))
|
17
14
|
end
|
18
15
|
|
19
|
-
Chake.
|
20
|
-
Chake.nodes = node_data.map { |node,data| Chake::Node.new(node, data) }.reject(&:skip?).uniq(&:hostname)
|
21
|
-
Chake.tmpdir = Chake.tmpdir
|
16
|
+
Chake.nodes = node_data.map { |node, data| Chake::Node.new(node, data) }.reject(&:skip?).uniq(&:hostname)
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module Chake
|
4
|
+
class ConfigManager
|
5
|
+
attr_reader :node
|
6
|
+
|
7
|
+
def initialize(node)
|
8
|
+
@node = node
|
9
|
+
end
|
10
|
+
|
11
|
+
def converge; end
|
12
|
+
|
13
|
+
def apply(config); end
|
14
|
+
|
15
|
+
def path
|
16
|
+
"/var/tmp/#{name}.#{node.username}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def name
|
20
|
+
self.class.short_name
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
name
|
25
|
+
end
|
26
|
+
|
27
|
+
def bootstrap_steps
|
28
|
+
base = File.join(File.absolute_path(File.dirname(__FILE__)), 'bootstrap')
|
29
|
+
steps = Dir[File.join(base, '*.sh')] + Dir[File.join(base, name, '*.sh')]
|
30
|
+
steps.sort_by { |f| File.basename(f) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def needs_upload?
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.short_name
|
38
|
+
name.split('::').last.downcase
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.priority(new_prioriry = nil)
|
42
|
+
@priority ||= new_prioriry || 50
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.inherited(klass)
|
46
|
+
super
|
47
|
+
@subclasses ||= []
|
48
|
+
@subclasses << klass
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.get(node)
|
52
|
+
available = @subclasses.sort_by(&:priority)
|
53
|
+
manager = available.find { |c| c.short_name == node.data['config_manager'] }
|
54
|
+
manager ||= available.find { |c| c.accept?(node) }
|
55
|
+
raise ArgumentError, "Can't find configuration manager class for node #{node.hostname}. Available: #{available}.join(', ')}" unless manager
|
56
|
+
|
57
|
+
manager.new(node)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.accept?(_node)
|
61
|
+
false
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.all
|
65
|
+
@subclasses
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.init
|
69
|
+
skel = Pathname(__FILE__).parent / 'config_manager' / 'skel' / short_name
|
70
|
+
skel.glob('**/*').each do |source|
|
71
|
+
target = source.relative_path_from(skel)
|
72
|
+
if target.exist?
|
73
|
+
puts "exists: #{target}"
|
74
|
+
else
|
75
|
+
if source.directory?
|
76
|
+
FileUtils.mkdir_p target
|
77
|
+
else
|
78
|
+
FileUtils.cp source, target
|
79
|
+
end
|
80
|
+
puts "create: #{target}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
Dir["#{File.dirname(__FILE__)}/config_manager/*.rb"].sort.each do |f|
|
88
|
+
require f
|
89
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'chake/config'
|
2
|
+
require 'chake/tmpdir'
|
3
|
+
|
4
|
+
module Chake
|
5
|
+
class ConfigManager
|
6
|
+
class Chef < ConfigManager
|
7
|
+
CONFIG = ENV['CHAKE_CHEF_CONFIG'] || 'config.rb'
|
8
|
+
|
9
|
+
def converge
|
10
|
+
node.run_as_root "sh -c 'rm -f #{node.path}/nodes/*.json && chef-solo -c #{node.path}/#{CONFIG} #{logging} -j #{json_config}'"
|
11
|
+
end
|
12
|
+
|
13
|
+
def apply(config)
|
14
|
+
node.run_as_root "sh -c 'rm -f #{node.path}/nodes/*.json && chef-solo -c #{node.path}/#{CONFIG} #{logging} -j #{json_config} --override-runlist recipe[#{config}]'"
|
15
|
+
end
|
16
|
+
|
17
|
+
priority 99
|
18
|
+
|
19
|
+
def self.accept?(_node)
|
20
|
+
true # this is the default, but after everything else
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def json_config
|
26
|
+
parts = [node.path, Chake.tmpdir, "#{node.hostname}.json"].compact
|
27
|
+
File.join(parts)
|
28
|
+
end
|
29
|
+
|
30
|
+
def logging
|
31
|
+
node.silent && '-l fatal' || ''
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
require 'chake/config'
|
3
|
+
require 'chake/tmpdir'
|
4
|
+
|
5
|
+
module Chake
|
6
|
+
class ConfigManager
|
7
|
+
class Itamae < ConfigManager
|
8
|
+
def converge
|
9
|
+
run_itamae(*node.data['itamae'])
|
10
|
+
end
|
11
|
+
|
12
|
+
def apply(config)
|
13
|
+
run_itamae(config)
|
14
|
+
end
|
15
|
+
|
16
|
+
def needs_upload?
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.accept?(node)
|
21
|
+
node.data.key?('itamae')
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def run_itamae(*recipes)
|
27
|
+
cmd = ['itamae']
|
28
|
+
case node.connection
|
29
|
+
when Chake::Connection::Ssh
|
30
|
+
cmd << 'ssh' << "--user=#{node.username}" << "--host=#{node.hostname}"
|
31
|
+
cmd += ssh_config
|
32
|
+
when Chake::Connection::Local
|
33
|
+
cmd << 'local'
|
34
|
+
else
|
35
|
+
raise NotImplementedError, "Connection type #{node.connection.class} not supported for itamee"
|
36
|
+
end
|
37
|
+
cmd << "--node-json=#{json_config}"
|
38
|
+
if node.silent
|
39
|
+
cmd << '--log-level=warn'
|
40
|
+
end
|
41
|
+
cmd += recipes
|
42
|
+
node.log("$ #{cmd.join(' ')}")
|
43
|
+
io = IO.popen(cmd, 'r', err: %i[child out])
|
44
|
+
node.connection.read_output(io)
|
45
|
+
end
|
46
|
+
|
47
|
+
def json_config
|
48
|
+
File.join(Chake.tmpdir, "#{node.hostname}.json")
|
49
|
+
end
|
50
|
+
|
51
|
+
def ssh_config
|
52
|
+
ssh_config = node.connection.send(:ssh_config_file) # FIXME
|
53
|
+
File.exist?(ssh_config) ? ["--ssh-config=#{ssh_config}"] : []
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
require 'chake/config'
|
3
|
+
|
4
|
+
module Chake
|
5
|
+
class ConfigManager
|
6
|
+
class Shell < ConfigManager
|
7
|
+
def converge
|
8
|
+
commands = node.data['shell'].join(' && ')
|
9
|
+
node.run_as_root sh(commands)
|
10
|
+
end
|
11
|
+
|
12
|
+
def apply(config)
|
13
|
+
node.run_as_root sh(config)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.accept?(node)
|
17
|
+
node.data.key?('shell')
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def sh(command)
|
23
|
+
if node.path
|
24
|
+
command = "cd #{node.path} && " + command
|
25
|
+
end
|
26
|
+
if node.silent
|
27
|
+
"sh -ec '#{command}' >/dev/null"
|
28
|
+
else
|
29
|
+
"sh -xec '#{command}'"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'chake'
|
@@ -0,0 +1 @@
|
|
1
|
+
package 'openssh-server'
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'chake'
|
@@ -0,0 +1 @@
|
|
1
|
+
package 'openssh-server'
|
@@ -0,0 +1 @@
|
|
1
|
+
include_recipe '../cookbooks/basics'
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'chake'
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Chake
|
2
|
+
Connection = Struct.new(:node) do
|
3
|
+
class CommandFailed < RuntimeError
|
4
|
+
end
|
5
|
+
|
6
|
+
def scp
|
7
|
+
['scp']
|
8
|
+
end
|
9
|
+
|
10
|
+
def scp_dest
|
11
|
+
''
|
12
|
+
end
|
13
|
+
|
14
|
+
def rsync
|
15
|
+
['rsync']
|
16
|
+
end
|
17
|
+
|
18
|
+
def rsync_dest
|
19
|
+
"#{node.path}/"
|
20
|
+
end
|
21
|
+
|
22
|
+
def run(cmd)
|
23
|
+
node.log('$ %<command>s' % { command: cmd })
|
24
|
+
io = IO.popen(command_runner + ['/bin/sh'], 'w+', err: %i[child out])
|
25
|
+
io.write(cmd)
|
26
|
+
io.close_write
|
27
|
+
read_output(io)
|
28
|
+
end
|
29
|
+
|
30
|
+
def read_output(io)
|
31
|
+
io.each_line do |line|
|
32
|
+
node.log(line.gsub(/\s*$/, ''))
|
33
|
+
end
|
34
|
+
io.close
|
35
|
+
if $CHILD_STATUS
|
36
|
+
status = $CHILD_STATUS.exitstatus
|
37
|
+
if status != 0
|
38
|
+
raise CommandFailed, [node.hostname, 'FAILED with exit status %<status>d' % { status: status }].join(': ')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def run_shell
|
44
|
+
system(*shell_command)
|
45
|
+
end
|
46
|
+
|
47
|
+
def run_as_root(cmd)
|
48
|
+
if node.remote_username == 'root'
|
49
|
+
run(cmd)
|
50
|
+
else
|
51
|
+
run("sudo #{cmd}")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_s
|
56
|
+
self.class.connection_name
|
57
|
+
end
|
58
|
+
|
59
|
+
def skip?
|
60
|
+
false
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.connection_name
|
64
|
+
name.split('::').last.downcase
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.inherited(subclass)
|
68
|
+
super
|
69
|
+
@connections ||= []
|
70
|
+
@connections << subclass
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.get(name)
|
74
|
+
connection = @connections.find { |b| b.connection_name == name }
|
75
|
+
raise ArgumentError, "Invalid connection name: #{name}" unless connection
|
76
|
+
|
77
|
+
connection
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
require 'chake/connection/ssh'
|
83
|
+
require 'chake/connection/local'
|
@@ -1,11 +1,8 @@
|
|
1
1
|
require 'socket'
|
2
2
|
|
3
3
|
module Chake
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
class Local < Backend
|
8
|
-
|
4
|
+
class Connection
|
5
|
+
class Local < Connection
|
9
6
|
def command_runner
|
10
7
|
['sh', '-c']
|
11
8
|
end
|
@@ -17,9 +14,6 @@ module Chake
|
|
17
14
|
def skip?
|
18
15
|
node.hostname != Socket.gethostname
|
19
16
|
end
|
20
|
-
|
21
17
|
end
|
22
|
-
|
23
18
|
end
|
24
|
-
|
25
19
|
end
|
@@ -1,15 +1,12 @@
|
|
1
1
|
module Chake
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
class Ssh < Backend
|
6
|
-
|
2
|
+
class Connection
|
3
|
+
class Ssh < Connection
|
7
4
|
def scp
|
8
5
|
['scp', ssh_config, scp_options].flatten.compact
|
9
6
|
end
|
10
7
|
|
11
8
|
def scp_dest
|
12
|
-
ssh_target
|
9
|
+
"#{ssh_target}:"
|
13
10
|
end
|
14
11
|
|
15
12
|
def rsync
|
@@ -17,7 +14,7 @@ module Chake
|
|
17
14
|
end
|
18
15
|
|
19
16
|
def rsync_dest
|
20
|
-
[ssh_target, node.path
|
17
|
+
[ssh_target, "#{node.path}/"].join(':')
|
21
18
|
end
|
22
19
|
|
23
20
|
def command_runner
|
@@ -35,11 +32,9 @@ module Chake
|
|
35
32
|
begin
|
36
33
|
ssh_command = 'ssh'
|
37
34
|
if File.exist?(ssh_config_file)
|
38
|
-
ssh_command +=
|
39
|
-
end
|
40
|
-
if node.port
|
41
|
-
ssh_command += ' -p ' + node.port.to_s
|
35
|
+
ssh_command += " -F #{ssh_config_file}"
|
42
36
|
end
|
37
|
+
ssh_command += " -p #{node.port}" if node.port
|
43
38
|
if ssh_command == 'ssh'
|
44
39
|
[]
|
45
40
|
else
|
@@ -71,9 +66,6 @@ module Chake
|
|
71
66
|
def scp_options
|
72
67
|
node.port && ['-P', node.port.to_s] || []
|
73
68
|
end
|
74
|
-
|
75
69
|
end
|
76
|
-
|
77
70
|
end
|
78
|
-
|
79
71
|
end
|