dust-deploy 0.9.2 → 0.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.
- data/bin/dust +3 -2
- data/changelog.md +36 -0
- data/dust.gemspec +2 -3
- data/lib/dust/print_status.rb +1 -1
- data/lib/dust/recipes/apt.rb +74 -0
- data/lib/dust/recipes/debsecan.rb +4 -4
- data/lib/dust/recipes/duplicity.rb +1 -1
- data/lib/dust/recipes/iptables.rb +9 -9
- data/lib/dust/recipes/logrotate.rb +4 -5
- data/lib/dust/recipes/mysql.rb +4 -5
- data/lib/dust/recipes/postgres.rb +10 -7
- data/lib/dust/recipes/rc_local.rb +2 -2
- data/lib/dust/recipes/redis.rb +4 -4
- data/lib/dust/recipes/repositories.rb +15 -15
- data/lib/dust/recipes/resolv_conf.rb +4 -4
- data/lib/dust/recipes/ruby_rvm.rb +20 -0
- data/lib/dust/recipes/ssh_authorized_keys.rb +4 -5
- data/lib/dust/recipes/sshd.rb +1 -1
- data/lib/dust/recipes/sudoers.rb +1 -1
- data/lib/dust/recipes/sysctl.rb +1 -1
- data/lib/dust/recipes/zabbix_agent.rb +5 -3
- data/lib/dust/server.rb +23 -6
- data/lib/dust/version.rb +1 -1
- metadata +104 -73
- data/lib/dust/recipes/unattended_upgrades.rb +0 -27
data/bin/dust
CHANGED
@@ -4,6 +4,7 @@ require 'rubygems'
|
|
4
4
|
require 'thor/runner'
|
5
5
|
require 'thor/util'
|
6
6
|
require 'yaml'
|
7
|
+
require 'erb'
|
7
8
|
require 'fileutils'
|
8
9
|
require 'ipaddress'
|
9
10
|
require 'dust'
|
@@ -186,7 +187,7 @@ module Dust
|
|
186
187
|
end
|
187
188
|
|
188
189
|
yaml_files.to_array.each do |file|
|
189
|
-
node = YAML.
|
190
|
+
node = YAML.load ERB.new( File.read(file), nil, '%<>').result
|
190
191
|
|
191
192
|
# if the file is empty, just skip it
|
192
193
|
next unless node
|
@@ -200,7 +201,7 @@ module Dust
|
|
200
201
|
if node['inherits']
|
201
202
|
inherited = {}
|
202
203
|
node.delete('inherits').each do |file|
|
203
|
-
template = YAML.
|
204
|
+
template = YAML.load ERB.new( File.read("./nodes/#{file}.yaml"), nil, '%<>').result
|
204
205
|
inherited.deep_merge! template
|
205
206
|
end
|
206
207
|
node = inherited.deep_merge node
|
data/changelog.md
CHANGED
@@ -1,6 +1,42 @@
|
|
1
1
|
Changelog
|
2
2
|
=============
|
3
3
|
|
4
|
+
0.10.0
|
5
|
+
------------
|
6
|
+
|
7
|
+
- it is now possible to use ERB codes in your yaml configuration files.
|
8
|
+
|
9
|
+
<% user = john %>
|
10
|
+
|
11
|
+
hostname: <%= user %>-notebook
|
12
|
+
|
13
|
+
recipes:
|
14
|
+
ssh_authorized_keys:
|
15
|
+
<%= user %>: admin
|
16
|
+
|
17
|
+
- unattended upgrade recipe was removed in favor of the new apt recipe
|
18
|
+
- postgres recipe: now adds a log_line_prefix as default
|
19
|
+
also accepts empty postgresql.conf in yaml configuration
|
20
|
+
- apt recipe now looks for present proxy configurations and comments them out before applying new config
|
21
|
+
- adds apt recipe to configure apt systems (unattended upgrades, proxy configuration, etc)
|
22
|
+
you have to migrate your existing unattended_upgrade recipe from:
|
23
|
+
|
24
|
+
recipes:
|
25
|
+
unattended_upgrades: true
|
26
|
+
|
27
|
+
to:
|
28
|
+
|
29
|
+
recipes:
|
30
|
+
apt:
|
31
|
+
unattended_upgrades:
|
32
|
+
enabled: 1
|
33
|
+
|
34
|
+
or simply, in case you do not need other apt options (as enabling unattended_upgrades is the default):
|
35
|
+
|
36
|
+
recipes:
|
37
|
+
apt: enabled
|
38
|
+
|
39
|
+
|
4
40
|
0.9.2
|
5
41
|
------------
|
6
42
|
|
data/dust.gemspec
CHANGED
@@ -18,9 +18,8 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
-
# specify any dependencies here
|
22
|
-
|
23
|
-
# s.add_runtime_dependency "rest-client"
|
21
|
+
# specify any dependencies here
|
22
|
+
s.add_runtime_dependency 'json'
|
24
23
|
s.add_runtime_dependency 'net-ssh'
|
25
24
|
s.add_runtime_dependency 'net-scp'
|
26
25
|
s.add_runtime_dependency 'net-sftp'
|
data/lib/dust/print_status.rb
CHANGED
@@ -0,0 +1,74 @@
|
|
1
|
+
class Apt < Recipe
|
2
|
+
desc 'apt:deploy', 'configures apt/aptitude'
|
3
|
+
def deploy
|
4
|
+
return unless @node.uses_apt?
|
5
|
+
|
6
|
+
@config = default_config.merge @config
|
7
|
+
|
8
|
+
unattended_upgrades @config.delete('unattended_upgrades')
|
9
|
+
proxy @config.delete('proxy')
|
10
|
+
|
11
|
+
@config.each do |name, settings|
|
12
|
+
::Dust.print_msg "deploying apt settings #{name}\n"
|
13
|
+
conf = ''
|
14
|
+
settings.to_array.each do |setting|
|
15
|
+
conf << "#{setting}\n"
|
16
|
+
end
|
17
|
+
|
18
|
+
@node.write "/etc/apt/apt.conf.d/#{name}", conf, :indent => 2
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
private
|
24
|
+
def default_config
|
25
|
+
{
|
26
|
+
'unattended_upgrades' => {
|
27
|
+
'enable' => 1,
|
28
|
+
'update-package-lists' => 1,
|
29
|
+
'unattended-upgrade' => 1,
|
30
|
+
'autocleaninterval' => 1,
|
31
|
+
'verbose' => 0
|
32
|
+
},
|
33
|
+
|
34
|
+
'proxy' => 'disabled'
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def unattended_upgrades config
|
39
|
+
return if config.is_a? FalseClass or config == 'disabled'
|
40
|
+
|
41
|
+
@node.install_package 'unattended-upgrades'
|
42
|
+
|
43
|
+
::Dust.print_msg "deploying unattended upgrades configuration\n"
|
44
|
+
periodic = ''
|
45
|
+
periodic << "APT::Periodic::Enable \"#{config['enable']}\";\n"
|
46
|
+
periodic << "APT::Periodic::Update-Package-Lists \"#{config['update-package-lists']}\";\n"
|
47
|
+
periodic << "APT::Periodic::Unattended-Upgrade \"#{config['unattended-upgrade']}\";\n"
|
48
|
+
periodic << "APT::Periodic::AutocleanInterval \"#{config['autocleaninterval']}\";\n"
|
49
|
+
periodic << "APT::Periodic::Verbose \"#{config['verbose']}\";\n"
|
50
|
+
|
51
|
+
@node.write '/etc/apt/apt.conf.d/02periodic', periodic, :indent => 2
|
52
|
+
end
|
53
|
+
|
54
|
+
def proxy config
|
55
|
+
# look for already configured proxy and delete
|
56
|
+
files = @node.exec("grep -v '^#' /etc/apt/ -R |grep -i 'acquire::http::proxy' |cut -d: -f1")[:stdout]
|
57
|
+
files.each_line do |file|
|
58
|
+
file.chomp!
|
59
|
+
|
60
|
+
# skip 02proxy, because we're going to overwrite it anyways
|
61
|
+
next if file == '/etc/apt/apt.conf.d/02proxy'
|
62
|
+
|
63
|
+
::Dust.print_warning "found proxy configuration in file #{file}, commenting out"
|
64
|
+
@node.exec "sed -i 's/^\\(acquire::http::proxy.*\\)/#\\1/i' #{file}"
|
65
|
+
end
|
66
|
+
|
67
|
+
return if config.is_a? FalseClass or config == 'disabled'
|
68
|
+
|
69
|
+
::Dust.print_msg "deploying proxy configuration\n"
|
70
|
+
proxy = "Acquire::http::Proxy \"#{config}\";\n"
|
71
|
+
|
72
|
+
@node.write '/etc/apt/apt.conf.d/02proxy', proxy, :indent => 2
|
73
|
+
end
|
74
|
+
end
|
@@ -19,20 +19,20 @@ class Debsecan < Recipe
|
|
19
19
|
config_file = ''
|
20
20
|
|
21
21
|
# configures whether daily reports are sent
|
22
|
-
config_file
|
22
|
+
config_file << "# If true, enable daily reports, sent by email.\n" +
|
23
23
|
"REPORT=#{config['report'].to_s}\n\n"
|
24
24
|
|
25
25
|
# configures the suite
|
26
|
-
config_file
|
26
|
+
config_file << "# For better reporting, specify the correct suite here, using the code\n" +
|
27
27
|
"# name (that is, \"sid\" instead of \"unstable\").\n" +
|
28
28
|
"SUITE=#{@node['lsbdistcodename']}\n\n"
|
29
29
|
|
30
30
|
# which user gets the reports?
|
31
|
-
config_file
|
31
|
+
config_file << "# Mail address to which reports are sent.\n" +
|
32
32
|
"MAILTO=#{config['mailto']}\n\n"
|
33
33
|
|
34
34
|
# set vulnerability source
|
35
|
-
config_file
|
35
|
+
config_file << "# The URL from which vulnerability data is downloaded. Empty for the\n" +
|
36
36
|
"# built-in default.\n" +
|
37
37
|
"SOURCE=#{config['source']}\n\n"
|
38
38
|
|
@@ -77,7 +77,7 @@ class Duplicity < Recipe
|
|
77
77
|
"--archive-dir #{config['archive']} " +
|
78
78
|
"#{File.join(config['backend'], config['directory'])}"
|
79
79
|
|
80
|
-
cmd
|
80
|
+
cmd << " |tail -n3 |head -n1" unless options.long?
|
81
81
|
|
82
82
|
ret = @node.exec cmd
|
83
83
|
|
@@ -61,10 +61,10 @@ class Iptables < Recipe
|
|
61
61
|
|
62
62
|
@tables['ipv' + @ip_version.to_s].keys.each do |table|
|
63
63
|
# clear all rules
|
64
|
-
@script
|
64
|
+
@script << "--flush --table #{table}\n"
|
65
65
|
|
66
66
|
# delete all custom chains
|
67
|
-
@script
|
67
|
+
@script << "--delete-chain --table #{table}\n" unless @node.uses_rpm?
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
@@ -87,7 +87,7 @@ class Iptables < Recipe
|
|
87
87
|
# generates all iptables rules
|
88
88
|
def generate_all_rules
|
89
89
|
@tables['ipv' + @ip_version.to_s].each do |table, chains|
|
90
|
-
@script
|
90
|
+
@script << "*#{table}\n" if @node.uses_rpm?
|
91
91
|
set_chain_policies table
|
92
92
|
generate_rules_for_table table
|
93
93
|
end
|
@@ -103,9 +103,9 @@ class Iptables < Recipe
|
|
103
103
|
policy = get_chain_policy table, chain
|
104
104
|
|
105
105
|
if @node.uses_rpm?
|
106
|
-
@script
|
106
|
+
@script << ":#{chain.upcase} #{policy} [0:0]\n"
|
107
107
|
else
|
108
|
-
@script
|
108
|
+
@script << "--table #{table} --policy #{chain.upcase} #{policy}\n"
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
@@ -125,9 +125,9 @@ class Iptables < Recipe
|
|
125
125
|
next unless chain_used_in_table
|
126
126
|
|
127
127
|
if @node.uses_rpm?
|
128
|
-
@script
|
128
|
+
@script << ":#{chain.upcase} - [0:0]\n"
|
129
129
|
else
|
130
|
-
@script
|
130
|
+
@script << "--table #{table} --new-chain #{chain.upcase}\n"
|
131
131
|
end
|
132
132
|
end
|
133
133
|
end
|
@@ -162,7 +162,7 @@ class Iptables < Recipe
|
|
162
162
|
::Dust.print_ok
|
163
163
|
end
|
164
164
|
end
|
165
|
-
@script
|
165
|
+
@script << "COMMIT\n" if @node.uses_rpm?
|
166
166
|
end
|
167
167
|
|
168
168
|
def get_rules_for_table rules, table
|
@@ -188,7 +188,7 @@ class Iptables < Recipe
|
|
188
188
|
def generate_iptables_string chain, rule
|
189
189
|
parse_rule(rule).each do |r|
|
190
190
|
#::Dust.print_msg "#{::Dust.grey}#{r.join ' '}#{::Dust.none}\n", :indent => 5
|
191
|
-
@script
|
191
|
+
@script << "--append #{chain.upcase} #{r.join ' '}\n"
|
192
192
|
end
|
193
193
|
end
|
194
194
|
|
@@ -14,15 +14,15 @@ class Logrotate < Recipe
|
|
14
14
|
file = "#{rule['path']} {\n"
|
15
15
|
|
16
16
|
rule['args'] ||= default_args
|
17
|
-
rule['args'].each { |arg| file
|
17
|
+
rule['args'].each { |arg| file << " #{arg}\n" }
|
18
18
|
|
19
19
|
rule['scripts'] ||= {}
|
20
20
|
rule['scripts'].each do |script, commands|
|
21
|
-
file
|
22
|
-
commands.each { |cmd| file
|
21
|
+
file << " #{script}\n"
|
22
|
+
commands.each { |cmd| file << " #{cmd}\n" }
|
23
23
|
end
|
24
24
|
|
25
|
-
file
|
25
|
+
file << "}\n"
|
26
26
|
deploy_rule name, file
|
27
27
|
end
|
28
28
|
|
@@ -46,7 +46,6 @@ class Logrotate < Recipe
|
|
46
46
|
|
47
47
|
def deploy_rule name, file
|
48
48
|
@node.write "/etc/logrotate.d/#{name}", file, :indent => 2
|
49
|
-
@node.chmod '0644', "/etc/logrotate.d/#{name}", :indent => 2
|
50
49
|
@node.chown 'root:root', "/etc/logrotate.d/#{name}", :indent => 2
|
51
50
|
end
|
52
51
|
|
data/lib/dust/recipes/mysql.rb
CHANGED
@@ -13,7 +13,6 @@ class Mysql < Recipe
|
|
13
13
|
::Dust.print_ok "set innodb buffer pool to '#{@config['mysqld']['innodb_buffer_pool_size']}'", :indent => 2
|
14
14
|
|
15
15
|
@node.write '/etc/mysql/my.cnf', generate_my_cnf
|
16
|
-
@node.chmod '644', '/etc/mysql/my.cnf'
|
17
16
|
|
18
17
|
@node.restart_service 'mysql' if options.restart?
|
19
18
|
@node.reload_service 'mysql' if options.reload?
|
@@ -96,13 +95,13 @@ class Mysql < Recipe
|
|
96
95
|
def generate_my_cnf
|
97
96
|
my_cnf = ''
|
98
97
|
@config.each do |category, config|
|
99
|
-
my_cnf
|
100
|
-
config.each { |key, value| my_cnf
|
101
|
-
my_cnf
|
98
|
+
my_cnf << "[#{category}]\n"
|
99
|
+
config.each { |key, value| my_cnf << "#{key} = #{value}\n" }
|
100
|
+
my_cnf << "\n"
|
102
101
|
end
|
103
102
|
|
104
103
|
# add includedir
|
105
|
-
my_cnf
|
104
|
+
my_cnf << "!includedir /etc/mysql/conf.d/\n"
|
106
105
|
my_cnf
|
107
106
|
end
|
108
107
|
end
|
@@ -4,6 +4,8 @@ class Postgres < Recipe
|
|
4
4
|
return ::Dust.print_failed 'no version specified' unless @config['version']
|
5
5
|
return unless install_postgres
|
6
6
|
|
7
|
+
@config['postgresql.conf'] ||= {}
|
8
|
+
|
7
9
|
# default cluster on debian-like systems is 'main'
|
8
10
|
@config['cluster'] ||= 'main' if @node.uses_apt?
|
9
11
|
|
@@ -71,9 +73,6 @@ class Postgres < Recipe
|
|
71
73
|
@node.write "#{@config['conf_directory']}/postgresql.conf", generate_postgresql_conf
|
72
74
|
@node.write "#{@config['conf_directory']}/pg_hba.conf", generate_pg_hba_conf
|
73
75
|
@node.write "#{@config['conf_directory']}/pg_ident.conf", generate_pg_ident_conf
|
74
|
-
@node.chmod '644', "#{@config['conf_directory']}/postgresql.conf"
|
75
|
-
@node.chmod '644', "#{@config['conf_directory']}/pg_hba.conf"
|
76
|
-
@node.chmod '644', "#{@config['conf_directory']}/pg_ident.conf"
|
77
76
|
end
|
78
77
|
|
79
78
|
# copy recovery.conf to either recovery.conf or recovery.done
|
@@ -94,16 +93,20 @@ class Postgres < Recipe
|
|
94
93
|
|
95
94
|
# default settings for postgresql.conf
|
96
95
|
def default_postgres_conf
|
97
|
-
{
|
96
|
+
{
|
97
|
+
'max_connections' => 100,
|
98
98
|
'datestyle' => 'iso, mdy',
|
99
99
|
'lc_messages' => 'en_US.UTF-8',
|
100
100
|
'lc_monetary' => 'en_US.UTF-8',
|
101
101
|
'lc_numeric' => 'en_US.UTF-8',
|
102
102
|
'lc_time' => 'en_US.UTF-8',
|
103
|
-
'default_text_search_config' => 'pg_catalog.english'
|
103
|
+
'default_text_search_config' => 'pg_catalog.english',
|
104
|
+
'log_line_prefix' => '%t [%p] %u@%d '
|
105
|
+
}
|
104
106
|
end
|
105
107
|
|
106
108
|
def generate_postgresql_conf
|
109
|
+
@config['postgresql.conf'] ||= {}
|
107
110
|
@config['postgresql.conf'] = default_postgres_conf.merge @config['postgresql.conf']
|
108
111
|
|
109
112
|
calculate_values
|
@@ -111,7 +114,7 @@ class Postgres < Recipe
|
|
111
114
|
postgresql_conf = ''
|
112
115
|
@config['postgresql.conf'].each do |key, value|
|
113
116
|
value = "'#{value}'" if value.is_a? String # enclose strings in ''
|
114
|
-
postgresql_conf
|
117
|
+
postgresql_conf << "#{key} = #{value}\n"
|
115
118
|
end
|
116
119
|
|
117
120
|
postgresql_conf
|
@@ -123,7 +126,7 @@ class Postgres < Recipe
|
|
123
126
|
recovery_conf = ''
|
124
127
|
@config['recovery.conf'].each do |key, value|
|
125
128
|
value = "'#{value}'" if value.is_a? String # enclose strings in ''
|
126
|
-
recovery_conf
|
129
|
+
recovery_conf << "#{key} = #{value}\n"
|
127
130
|
end
|
128
131
|
|
129
132
|
recovery_conf
|
@@ -8,10 +8,10 @@ class RcLocal < Recipe
|
|
8
8
|
rc = ''
|
9
9
|
@config.to_array.each do |cmd|
|
10
10
|
::Dust.print_msg "adding command: #{cmd}", :indent => 2
|
11
|
-
rc
|
11
|
+
rc << "#{cmd}\n"
|
12
12
|
::Dust.print_ok
|
13
13
|
end
|
14
|
-
rc
|
14
|
+
rc << "\nexit 0\n"
|
15
15
|
|
16
16
|
@node.write '/etc/rc.local', rc
|
17
17
|
@node.chown 'root:root', '/etc/rc.local'
|
data/lib/dust/recipes/redis.rb
CHANGED
@@ -63,9 +63,9 @@ class Redis < Recipe
|
|
63
63
|
redis_conf = ''
|
64
64
|
@config.each do |key, value|
|
65
65
|
if value.is_a? Array
|
66
|
-
value.each { |v| redis_conf
|
66
|
+
value.each { |v| redis_conf << "#{key} #{v}\n" }
|
67
67
|
else
|
68
|
-
redis_conf
|
68
|
+
redis_conf << "#{key} #{value}\n"
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
@@ -83,8 +83,8 @@ class Redis < Recipe
|
|
83
83
|
::Dust.print_result @node.exec('sysctl -w vm.swappiness=0')[:exit_code]
|
84
84
|
|
85
85
|
file = ''
|
86
|
-
file
|
87
|
-
file
|
86
|
+
file << "vm.overcommit_memory=1\n"
|
87
|
+
file << "vm.swappiness=0\n"
|
88
88
|
|
89
89
|
@node.write "/etc/sysctl.d/30-redis.conf", file
|
90
90
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class Repositories < Recipe
|
2
2
|
desc 'repositories:deploy', 'configures package management repositories (aptitude, yum)'
|
3
3
|
def deploy
|
4
|
-
@node.collect_facts
|
4
|
+
return unless @node.collect_facts
|
5
5
|
|
6
6
|
delete_old_repositories
|
7
7
|
deploy_repositories
|
@@ -59,32 +59,32 @@ class Repositories < Recipe
|
|
59
59
|
|
60
60
|
def generate_default_repo repo
|
61
61
|
sources = ''
|
62
|
-
sources
|
63
|
-
sources
|
62
|
+
sources << "deb #{repo['url']} #{repo['release']} #{repo['components']}\n"
|
63
|
+
sources << "deb-src #{repo['url']} #{repo['release']} #{repo['components']}\n\n"
|
64
64
|
|
65
65
|
# security
|
66
66
|
if @node.is_debian?
|
67
|
-
sources
|
68
|
-
sources
|
67
|
+
sources << "deb http://security.debian.org/ #{repo['release']}/updates #{repo['components']}\n"
|
68
|
+
sources << "deb-src http://security.debian.org/ #{repo['release']}/updates #{repo['components']}\n\n"
|
69
69
|
elsif @node.is_ubuntu?
|
70
|
-
sources
|
71
|
-
sources
|
70
|
+
sources << "deb http://security.ubuntu.com/ubuntu/ #{repo['release']}-security #{repo['components']}\n"
|
71
|
+
sources << "deb-src http://security.ubuntu.com/ubuntu/ #{repo['release']}-security #{repo['components']}\n\n"
|
72
72
|
end
|
73
73
|
|
74
74
|
# updates
|
75
|
-
sources
|
76
|
-
sources
|
75
|
+
sources << "deb #{repo['url']} #{repo['release']}-updates #{repo['components']}\n"
|
76
|
+
sources << "deb-src #{repo['url']} #{repo['release']}-updates #{repo['components']}\n\n"
|
77
77
|
|
78
78
|
# proposed
|
79
79
|
if @node.is_ubuntu?
|
80
|
-
sources
|
81
|
-
sources
|
80
|
+
sources << "deb #{repo['url']} #{repo['release']}-proposed #{repo['components']}\n"
|
81
|
+
sources << "deb-src #{repo['url']} #{repo['release']}-proposed #{repo['components']}\n\n"
|
82
82
|
end
|
83
83
|
|
84
84
|
# backports is enabled per default in ubuntu oneiric
|
85
85
|
if @node.is_ubuntu?
|
86
|
-
sources
|
87
|
-
sources
|
86
|
+
sources << "deb #{repo['url']} #{repo['release']}-backports #{repo['components']}\n"
|
87
|
+
sources << "deb-src #{repo['url']} #{repo['release']}-backports #{repo['components']}\n\n"
|
88
88
|
end
|
89
89
|
|
90
90
|
sources
|
@@ -93,8 +93,8 @@ class Repositories < Recipe
|
|
93
93
|
def generate_repo repo
|
94
94
|
# add url to sources.list
|
95
95
|
sources = ''
|
96
|
-
sources
|
97
|
-
sources
|
96
|
+
sources << "deb #{repo['url']} #{repo['release']} #{repo['components']}\n" if repo['binary']
|
97
|
+
sources << "deb-src #{repo['url']} #{repo['release']} #{repo['components']}\n" if repo['source']
|
98
98
|
sources
|
99
99
|
end
|
100
100
|
|
@@ -14,25 +14,25 @@ class ResolvConf < Recipe
|
|
14
14
|
# configures whether daily reports are sent
|
15
15
|
if @config['search']
|
16
16
|
::Dust.print_msg "adding search #{@config['search']}", :indent => 2
|
17
|
-
config_file
|
17
|
+
config_file << "search #{@config['search']}\n"
|
18
18
|
::Dust.print_ok
|
19
19
|
end
|
20
20
|
|
21
21
|
if @config['domain']
|
22
22
|
::Dust.print_msg "adding domain #{@config['domain']}", :indent => 2
|
23
|
-
config_file
|
23
|
+
config_file << "domain #{@config['domain']}\n"
|
24
24
|
::Dust.print_ok
|
25
25
|
end
|
26
26
|
|
27
27
|
if @config['options']
|
28
28
|
::Dust.print_msg "adding options #{@config['options']}", :indent => 2
|
29
|
-
config_file
|
29
|
+
config_file << "options #{@config['options']}\n"
|
30
30
|
::Dust.print_ok
|
31
31
|
end
|
32
32
|
|
33
33
|
@config['nameservers'].each do |nameserver|
|
34
34
|
::Dust.print_msg "adding nameserver #{nameserver}", :indent => 2
|
35
|
-
config_file
|
35
|
+
config_file << "nameserver #{nameserver}\n"
|
36
36
|
::Dust.print_ok
|
37
37
|
end
|
38
38
|
|
@@ -34,6 +34,8 @@ class RubyRvm < Recipe
|
|
34
34
|
next
|
35
35
|
end
|
36
36
|
|
37
|
+
return unless change_shell user
|
38
|
+
return unless create_homedir user
|
37
39
|
return unless install_rvm user
|
38
40
|
return unless install_ruby user, version
|
39
41
|
return unless set_default user, version
|
@@ -84,4 +86,22 @@ class RubyRvm < Recipe
|
|
84
86
|
end
|
85
87
|
false
|
86
88
|
end
|
89
|
+
|
90
|
+
# rvm only supports bash and zsh
|
91
|
+
def change_shell user
|
92
|
+
shell = @node.get_shell user
|
93
|
+
return true if shell == '/bin/zsh' or shell == '/bin/bash'
|
94
|
+
|
95
|
+
::Dust.print_msg "changing shell for #{user} to /bin/bash"
|
96
|
+
::Dust.print_result@node.exec("chsh -s /bin/bash #{user}")[:exit_code]
|
97
|
+
end
|
98
|
+
|
99
|
+
def create_homedir user
|
100
|
+
dir = @node.get_home user
|
101
|
+
unless @node.dir_exists? dir, :quiet => true
|
102
|
+
return false unless @node.mkdir dir
|
103
|
+
return false unless @node.chown user, dir
|
104
|
+
end
|
105
|
+
true
|
106
|
+
end
|
87
107
|
end
|
@@ -25,10 +25,10 @@ class SshAuthorizedKeys < Recipe
|
|
25
25
|
users[ssh_user]['name'] ||= ssh_user
|
26
26
|
::Dust.print_msg "adding user #{users[ssh_user]['name']}", :indent => 2
|
27
27
|
users[ssh_user]['keys'].each do |key|
|
28
|
-
authorized_keys
|
29
|
-
authorized_keys
|
30
|
-
authorized_keys
|
31
|
-
authorized_keys
|
28
|
+
authorized_keys << "#{key}"
|
29
|
+
authorized_keys << " #{users[ssh_user]['name']}" if users[ssh_user]['name']
|
30
|
+
authorized_keys << " <#{users[ssh_user]['email']}>" if users[ssh_user]['email']
|
31
|
+
authorized_keys << "\n"
|
32
32
|
end
|
33
33
|
::Dust.print_ok
|
34
34
|
end
|
@@ -51,7 +51,6 @@ class SshAuthorizedKeys < Recipe
|
|
51
51
|
|
52
52
|
# check permissions
|
53
53
|
@node.chown "#{user}:#{user}", "#{home}/.ssh"
|
54
|
-
@node.chmod '0644', "#{home}/.ssh/authorized_keys"
|
55
54
|
end
|
56
55
|
|
57
56
|
# remove authorized_keys files for all other users
|
data/lib/dust/recipes/sshd.rb
CHANGED
data/lib/dust/recipes/sudoers.rb
CHANGED
data/lib/dust/recipes/sysctl.rb
CHANGED
@@ -30,7 +30,7 @@ class Sysctl < Recipe
|
|
30
30
|
sysctl.each do |key, value|
|
31
31
|
::Dust.print_msg "setting #{key} = #{value}", :indent => 2
|
32
32
|
::Dust.print_result @node.exec("sysctl -w #{key}=#{value}")[:exit_code]
|
33
|
-
sysctl_conf
|
33
|
+
sysctl_conf << "#{key} = #{value}\n"
|
34
34
|
end
|
35
35
|
|
36
36
|
::Dust.print_msg "saving settings to /etc/sysctl.d/10-#{name}.conf", :indent => 2
|
@@ -50,7 +50,9 @@ class ZabbixAgent < Recipe
|
|
50
50
|
# generate zabbix_agentd.conf
|
51
51
|
def generate_zabbix_agentd_conf
|
52
52
|
@config = default_config.merge @config
|
53
|
-
|
53
|
+
|
54
|
+
@config['UserParameter'] = Array @config['UserParameter']
|
55
|
+
|
54
56
|
# system updates
|
55
57
|
@config['UserParameter'] |= enable_apt if @node.uses_apt?
|
56
58
|
@config['UserParameter'] |= enable_rpm if @node.uses_rpm?
|
@@ -65,12 +67,12 @@ class ZabbixAgent < Recipe
|
|
65
67
|
# add normal configuration variables
|
66
68
|
@config.each do |key, value|
|
67
69
|
next if key == 'UserParameter'
|
68
|
-
zabbix_agentd_conf
|
70
|
+
zabbix_agentd_conf << "#{key}=#{value}\n"
|
69
71
|
end
|
70
72
|
|
71
73
|
# add user parameters
|
72
74
|
@config['UserParameter'].each do |user_parameter|
|
73
|
-
zabbix_agentd_conf
|
75
|
+
zabbix_agentd_conf << "UserParameter=#{user_parameter}\n"
|
74
76
|
end
|
75
77
|
|
76
78
|
zabbix_agentd_conf
|
data/lib/dust/server.rb
CHANGED
@@ -108,16 +108,20 @@ module Dust
|
|
108
108
|
|
109
109
|
def write destination, content, options = {}
|
110
110
|
options = default_options.merge options
|
111
|
-
|
111
|
+
|
112
112
|
Dust.print_msg "deploying #{File.basename destination}", options
|
113
|
-
|
113
|
+
|
114
114
|
f = Tempfile.new 'dust-write'
|
115
115
|
f.print content
|
116
116
|
f.close
|
117
|
-
|
117
|
+
|
118
|
+
file_existed = file_exists? destination, :quiet => true
|
119
|
+
|
118
120
|
ret = Dust.print_result scp(f.path, destination, :quiet => true), options
|
119
121
|
f.unlink
|
120
|
-
|
122
|
+
|
123
|
+
# default to 644 unless file existed before
|
124
|
+
chmod '0644', destination, options unless file_existed
|
121
125
|
ret
|
122
126
|
end
|
123
127
|
|
@@ -575,9 +579,22 @@ module Dust
|
|
575
579
|
def get_home user, options = {}
|
576
580
|
options = default_options(:quiet => true).merge options
|
577
581
|
|
578
|
-
Dust.print_msg "getting home directory of #{user}"
|
582
|
+
Dust.print_msg "getting home directory of #{user}", options
|
579
583
|
ret = exec "getent passwd |cut -d':' -f1,6 |grep '^#{user}' |head -n1 |cut -d: -f2"
|
580
|
-
if Dust.print_result ret[:exit_code]
|
584
|
+
if Dust.print_result ret[:exit_code], options
|
585
|
+
return ret[:stdout].chomp
|
586
|
+
else
|
587
|
+
return false
|
588
|
+
end
|
589
|
+
end
|
590
|
+
|
591
|
+
# returns shell of this user
|
592
|
+
def get_shell user, options = {}
|
593
|
+
options = default_options(:quiet => true).merge options
|
594
|
+
|
595
|
+
Dust.print_msg "getting shell of #{user}", options
|
596
|
+
ret = exec "getent passwd |cut -d':' -f1,7 |grep '^#{user}' |head -n1 |cut -d: -f2"
|
597
|
+
if Dust.print_result ret[:exit_code], options
|
581
598
|
return ret[:stdout].chomp
|
582
599
|
else
|
583
600
|
return false
|
data/lib/dust/version.rb
CHANGED
metadata
CHANGED
@@ -1,80 +1,104 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: dust-deploy
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 10
|
8
|
+
- 0
|
9
|
+
version: 0.10.0
|
6
10
|
platform: ruby
|
7
|
-
authors:
|
11
|
+
authors:
|
8
12
|
- kris kechagia
|
9
13
|
autorequire:
|
10
14
|
bindir: bin
|
11
15
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
16
|
+
|
17
|
+
date: 2012-04-03 00:00:00 +02:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: json
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
22
30
|
type: :runtime
|
31
|
+
version_requirements: *id001
|
32
|
+
- !ruby/object:Gem::Dependency
|
33
|
+
name: net-ssh
|
23
34
|
prerelease: false
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '0'
|
35
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
segments:
|
40
|
+
- 0
|
41
|
+
version: "0"
|
33
42
|
type: :runtime
|
43
|
+
version_requirements: *id002
|
44
|
+
- !ruby/object:Gem::Dependency
|
45
|
+
name: net-scp
|
34
46
|
prerelease: false
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: '0'
|
47
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
44
54
|
type: :runtime
|
55
|
+
version_requirements: *id003
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: net-sftp
|
45
58
|
prerelease: false
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
59
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
55
66
|
type: :runtime
|
67
|
+
version_requirements: *id004
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: thor
|
56
70
|
prerelease: false
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
- !ruby/object:Gem::Version
|
65
|
-
version: '0'
|
71
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
version: "0"
|
66
78
|
type: :runtime
|
79
|
+
version_requirements: *id005
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: ipaddress
|
67
82
|
prerelease: false
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
83
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
segments:
|
88
|
+
- 0
|
89
|
+
version: "0"
|
90
|
+
type: :runtime
|
91
|
+
version_requirements: *id006
|
92
|
+
description: when puppet and chef suck because you want to be in control and sprinkle just cannot do enough for you
|
93
|
+
email:
|
72
94
|
- kk@rndsec.net
|
73
|
-
executables:
|
95
|
+
executables:
|
74
96
|
- dust
|
75
97
|
extensions: []
|
98
|
+
|
76
99
|
extra_rdoc_files: []
|
77
|
-
|
100
|
+
|
101
|
+
files:
|
78
102
|
- .gitignore
|
79
103
|
- Gemfile
|
80
104
|
- LICENSE
|
@@ -110,6 +134,7 @@ files:
|
|
110
134
|
- lib/dust/print_status.rb
|
111
135
|
- lib/dust/recipe.rb
|
112
136
|
- lib/dust/recipes/aliases.rb
|
137
|
+
- lib/dust/recipes/apt.rb
|
113
138
|
- lib/dust/recipes/basic_setup.rb
|
114
139
|
- lib/dust/recipes/cjdroute.rb
|
115
140
|
- lib/dust/recipes/cups_client.rb
|
@@ -138,32 +163,38 @@ files:
|
|
138
163
|
- lib/dust/recipes/sshd.rb
|
139
164
|
- lib/dust/recipes/sudoers.rb
|
140
165
|
- lib/dust/recipes/sysctl.rb
|
141
|
-
- lib/dust/recipes/unattended_upgrades.rb
|
142
166
|
- lib/dust/recipes/zabbix_agent.rb
|
143
167
|
- lib/dust/server.rb
|
144
168
|
- lib/dust/version.rb
|
145
|
-
|
169
|
+
has_rdoc: true
|
170
|
+
homepage: ""
|
146
171
|
licenses: []
|
172
|
+
|
147
173
|
post_install_message:
|
148
174
|
rdoc_options: []
|
149
|
-
|
175
|
+
|
176
|
+
require_paths:
|
150
177
|
- lib
|
151
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
requirements:
|
160
|
-
- -
|
161
|
-
- !ruby/object:Gem::Version
|
162
|
-
|
178
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
179
|
+
requirements:
|
180
|
+
- - ">="
|
181
|
+
- !ruby/object:Gem::Version
|
182
|
+
segments:
|
183
|
+
- 0
|
184
|
+
version: "0"
|
185
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
186
|
+
requirements:
|
187
|
+
- - ">="
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
segments:
|
190
|
+
- 0
|
191
|
+
version: "0"
|
163
192
|
requirements: []
|
193
|
+
|
164
194
|
rubyforge_project: dust-deploy
|
165
|
-
rubygems_version: 1.
|
195
|
+
rubygems_version: 1.3.6
|
166
196
|
signing_key:
|
167
197
|
specification_version: 3
|
168
198
|
summary: small server deployment tool for complex environments
|
169
199
|
test_files: []
|
200
|
+
|
@@ -1,27 +0,0 @@
|
|
1
|
-
class UnattendedUpgrades < Recipe
|
2
|
-
desc 'unattended_upgrades:deploy', 'installs and configures automatic system updates for debian and ubuntu'
|
3
|
-
def deploy
|
4
|
-
return unless @node.uses_apt?
|
5
|
-
@node.install_package 'unattended-upgrades'
|
6
|
-
|
7
|
-
@config = {} unless @config.is_a? Hash
|
8
|
-
|
9
|
-
# set defaults for non-set config
|
10
|
-
@config['enable'] ||= 1
|
11
|
-
@config['update-package-lists'] ||= 1
|
12
|
-
@config['unattended-upgrade'] ||= 1
|
13
|
-
@config['autocleaninterval'] ||= 1
|
14
|
-
@config['verbose'] ||= 0
|
15
|
-
|
16
|
-
# generate configuration file
|
17
|
-
periodic = ''
|
18
|
-
periodic += "APT::Periodic::Enable \"#{@config['enable']}\";\n"
|
19
|
-
periodic += "APT::Periodic::Update-Package-Lists \"#{@config['update-package-lists']}\";\n"
|
20
|
-
periodic += "APT::Periodic::Unattended-Upgrade \"#{@config['unattended-upgrade']}\";\n"
|
21
|
-
periodic += "APT::Periodic::AutocleanInterval \"#{@config['autocleaninterval']}\";\n"
|
22
|
-
periodic += "APT::Periodic::Verbose \"#{@config['verbose']}\";\n"
|
23
|
-
|
24
|
-
@node.write '/etc/apt/apt.conf.d/02periodic', periodic
|
25
|
-
@node.chmod '644', '/etc/apt/apt.conf.d/02periodic'
|
26
|
-
end
|
27
|
-
end
|