dust-deploy 0.15.2 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- data/changelog.md +30 -0
- data/lib/dust/messaging.rb +3 -0
- data/lib/dust/recipes/cjdroute.rb +18 -28
- data/lib/dust/recipes/motd.rb +46 -4
- data/lib/dust/recipes/postgres.rb +37 -30
- data/lib/dust/recipes/sudoers.rb +8 -3
- data/lib/dust/recipes/sysctl.rb +34 -12
- data/lib/dust/recipes/users.rb +16 -3
- data/lib/dust/runner.rb +2 -2
- data/lib/dust/server.rb +53 -13
- data/lib/dust/version.rb +1 -1
- metadata +2 -2
data/changelog.md
CHANGED
@@ -1,6 +1,36 @@
|
|
1
1
|
Changelog
|
2
2
|
=============
|
3
3
|
|
4
|
+
0.16.0
|
5
|
+
------------
|
6
|
+
|
7
|
+
- fixes an issue where the user was set to the sudo user when using node.scp, now defaults to root:root
|
8
|
+
- updates and fixes for cjdroute recipe
|
9
|
+
- adds node.selinuxenabled? and node.chcon
|
10
|
+
- users recipe now changes selinux content of home and ssh dirs
|
11
|
+
- improves motd recipe, now supports update-motd as well. there are three possible ways of maintaining the motd now:
|
12
|
+
using a motd string in the config file, and static file or a ERB template file. for more information see:
|
13
|
+
https://github.com/kechagia/dust-deploy/wiki/motd
|
14
|
+
|
15
|
+
- introduces node.get_gid()
|
16
|
+
- users recipe now chowns to primary gid
|
17
|
+
- users recipe now checks if public_keys.yaml and the requested user is actually present
|
18
|
+
- removes the leading 10- from sysctl.d files, so they can be set individually if needed
|
19
|
+
- sysctl recipe only applies rules directly if --restart is given
|
20
|
+
- also enables support for multiple files, please migrate
|
21
|
+
|
22
|
+
recipes:
|
23
|
+
# old (deprecated)
|
24
|
+
sysctl:
|
25
|
+
key: value
|
26
|
+
|
27
|
+
sysctl:
|
28
|
+
# new
|
29
|
+
name:
|
30
|
+
key: value
|
31
|
+
othername: { key: value }
|
32
|
+
|
33
|
+
|
4
34
|
0.15.2
|
5
35
|
------------
|
6
36
|
|
data/lib/dust/messaging.rb
CHANGED
@@ -9,10 +9,6 @@ class Cjdroute< Recipe
|
|
9
9
|
return unless install_dependencies
|
10
10
|
return unless get_latest_version
|
11
11
|
|
12
|
-
# clean up building directory, if --restart is given
|
13
|
-
# using --restart, since there's no --cleanup
|
14
|
-
# return unless make_clean if @options.restart?
|
15
|
-
|
16
12
|
# compiling action
|
17
13
|
return unless run_make
|
18
14
|
|
@@ -23,8 +19,8 @@ class Cjdroute< Recipe
|
|
23
19
|
stop_cjdroute
|
24
20
|
|
25
21
|
# copy binary
|
26
|
-
return unless @node.mkdir
|
27
|
-
return unless @node.cp
|
22
|
+
return unless @node.mkdir(@config['bin_dir'])
|
23
|
+
return unless @node.cp("#{@config['build_dir']}/cjdroute", "#{@config['bin_dir']}/cjdroute")
|
28
24
|
|
29
25
|
start_cjdroute
|
30
26
|
end
|
@@ -103,23 +99,23 @@ class Cjdroute< Recipe
|
|
103
99
|
def install_dependencies
|
104
100
|
@node.messages.add("installing build dependencies\n")
|
105
101
|
|
106
|
-
return false unless @node.install_package
|
102
|
+
return false unless @node.install_package('cmake', :indent => 2)
|
107
103
|
|
108
104
|
# check cmake version
|
109
|
-
ret = @node.exec
|
105
|
+
ret = @node.exec('cmake --version')
|
110
106
|
ver = ret[:stdout].match(/2.[0-9]/)[0].to_f
|
111
107
|
return @node.messages.add('cjdroute requires cmake 2.8 or higher').failed if ver < 2.8
|
112
108
|
|
113
109
|
|
114
110
|
if @node.uses_apt?
|
115
|
-
return false unless @node.install_package
|
116
|
-
return false unless @node.install_package
|
117
|
-
return false unless @node.install_package
|
118
|
-
return false unless @node.install_package
|
111
|
+
return false unless @node.install_package('git-core', :indent => 2)
|
112
|
+
return false unless @node.install_package('build-essential', :indent => 2)
|
113
|
+
return false unless @node.install_package('psmisc', :indent => 2)
|
114
|
+
return false unless @node.install_package('coreutils', :indent => 2)
|
119
115
|
else
|
120
|
-
return false unless @node.install_package
|
121
|
-
return false unless @node.install_package
|
122
|
-
return false unless @node.install_package
|
116
|
+
return false unless @node.install_package('git', :indent => 2)
|
117
|
+
return false unless @node.install_package('gcc', :indent => 2)
|
118
|
+
return false unless @node.install_package('make', :indent => 2)
|
123
119
|
end
|
124
120
|
|
125
121
|
true
|
@@ -127,10 +123,10 @@ class Cjdroute< Recipe
|
|
127
123
|
|
128
124
|
# gets/updates latest version from cjdns git repository
|
129
125
|
def get_latest_version
|
130
|
-
if @node.dir_exists?
|
126
|
+
if @node.dir_exists?(@config['build_dir'], :quiet => true)
|
131
127
|
|
132
128
|
# check if build directory is maintained by git
|
133
|
-
unless @node.dir_exists?
|
129
|
+
unless @node.dir_exists?("#{@config['build_dir']}/.git", :quiet => true)
|
134
130
|
return @node.messages.add("#{@config['build_dir']} doesn't appear to be a git repository").failed
|
135
131
|
end
|
136
132
|
|
@@ -145,7 +141,7 @@ class Cjdroute< Recipe
|
|
145
141
|
|
146
142
|
else
|
147
143
|
# create build directory
|
148
|
-
unless @node.mkdir
|
144
|
+
unless @node.mkdir(@config['build_dir'])
|
149
145
|
return @node.messages.add("couldn't create build directory #{@config['build_dir']}").failed
|
150
146
|
end
|
151
147
|
|
@@ -164,12 +160,6 @@ class Cjdroute< Recipe
|
|
164
160
|
true
|
165
161
|
end
|
166
162
|
|
167
|
-
# remove and recreate building directory
|
168
|
-
def make_clean
|
169
|
-
msg = @node.messages.add('cleaning up')
|
170
|
-
msg.parse_result(@node.exec("rm -rf #{@config['build_dir']}/build")[:exit_code])
|
171
|
-
end
|
172
|
-
|
173
163
|
def run_make
|
174
164
|
msg = @node.messages.add('compiling cjdns')
|
175
165
|
msg.parse_result(@node.exec("export Log_LEVEL=#{@config['loglevel']}; cd #{@config['build_dir']}; ./do", :live => true)[:exit_code])
|
@@ -183,11 +173,11 @@ class Cjdroute< Recipe
|
|
183
173
|
end
|
184
174
|
|
185
175
|
msg = @node.messages.add('generating config file')
|
186
|
-
ret = @node.exec("#{@config['
|
176
|
+
ret = @node.exec("#{@config['build_dir']}/cjdroute --genconf")
|
187
177
|
return false unless msg.parse_result(ret[:exit_code])
|
188
178
|
|
189
179
|
# parse generated json
|
190
|
-
cjdroute_conf = JSON.parse
|
180
|
+
cjdroute_conf = JSON.parse(ret[:stdout])
|
191
181
|
|
192
182
|
# add some public peers, so we can get started directly
|
193
183
|
msg = @node.messages.add('adding public peers', :indent => 2)
|
@@ -197,8 +187,8 @@ class Cjdroute< Recipe
|
|
197
187
|
# exchange tun0 with configured tun device
|
198
188
|
cjdroute_conf['router']['interface']['tunDevice'] = @config['tun']
|
199
189
|
|
200
|
-
return false unless @node.mkdir
|
201
|
-
return @node.write
|
190
|
+
return false unless @node.mkdir(@config['etc_dir'])
|
191
|
+
return @node.write("#{@config['etc_dir']}/cjdroute.conf", JSON.pretty_generate(cjdroute_conf))
|
202
192
|
end
|
203
193
|
|
204
194
|
# kill any cjdroute processes that might be running
|
data/lib/dust/recipes/motd.rb
CHANGED
@@ -1,7 +1,41 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
1
3
|
class Motd < Recipe
|
2
4
|
desc 'motd:deploy', 'creates message of the day'
|
3
|
-
def deploy
|
4
|
-
@node.
|
5
|
+
def deploy
|
6
|
+
return @node.messages.add('no motd or motd template given') unless @config.is_a? String
|
7
|
+
|
8
|
+
file = "#{@template_path}/#{@config}"
|
9
|
+
|
10
|
+
# use the file, or file.erb if present
|
11
|
+
# if not, use the given string
|
12
|
+
if File.exists?(file)
|
13
|
+
@node.messages.add("found static motd file '#{File.basename(file)}'").ok
|
14
|
+
message = File.read(file)
|
15
|
+
elsif File.exists?(file + '.erb')
|
16
|
+
@node.messages.add("found template motd file '#{File.basename(file)}.erb'").ok
|
17
|
+
message = ERB.new(File.read(file + '.erb'), nil, '%<>').result(binding)
|
18
|
+
else
|
19
|
+
@node.messages.add("found motd string in config file").ok
|
20
|
+
message = ERB.new(@config, nil, '%<>').result(binding)
|
21
|
+
end
|
22
|
+
|
23
|
+
# check if /etc/update-motd.d is present
|
24
|
+
if @node.dir_exists?('/etc/update-motd.d', :quiet => true)
|
25
|
+
file = '/etc/update-motd.d/50-dust'
|
26
|
+
msg = @node.messages.add("update-motd was found, deploying motd to #{file}")
|
27
|
+
|
28
|
+
# create a simple shellscript that echos the motd, and deploy it
|
29
|
+
msg.parse_result(@node.write(file, shellscriptify(message), :quiet => true))
|
30
|
+
|
31
|
+
# since we've deployed a shellscript, make it executeable
|
32
|
+
@node.chmod('0755', file)
|
33
|
+
|
34
|
+
# not using update-motd, simply modify /etc/motd
|
35
|
+
else
|
36
|
+
msg = @node.messages.add('deploying message of the day directly to /etc/motd')
|
37
|
+
msg.parse_result(@node.write('/etc/motd', message, :quiet => true))
|
38
|
+
end
|
5
39
|
end
|
6
40
|
|
7
41
|
desc 'motd:status', 'shows current message of the day'
|
@@ -9,6 +43,14 @@ class Motd < Recipe
|
|
9
43
|
msg = @node.messages.add('getting /etc/motd')
|
10
44
|
ret = @node.exec 'cat /etc/motd'
|
11
45
|
msg.parse_result(ret[:exit_code])
|
12
|
-
msg.
|
13
|
-
end
|
46
|
+
msg.parse_output(ret)
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# creates a shellscript echoing string
|
53
|
+
def shellscriptify(string)
|
54
|
+
"#!/bin/sh\n\ncat <<EOF\n#{string}\nEOF\n"
|
55
|
+
end
|
14
56
|
end
|
@@ -20,25 +20,25 @@ class Postgres < Recipe
|
|
20
20
|
set_permissions
|
21
21
|
|
22
22
|
# configure pacemaker profile
|
23
|
-
if @config['profile'].to_array.include?
|
24
|
-
deploy_pacemaker_script if @node.package_installed?
|
23
|
+
if @config['profile'].to_array.include?('pacemaker')
|
24
|
+
deploy_pacemaker_script if @node.package_installed?('pacemaker')
|
25
25
|
end
|
26
26
|
|
27
27
|
# configure zabbix profile
|
28
|
-
if @config['profile'].to_array.include?
|
28
|
+
if @config['profile'].to_array.include?('zabbix')
|
29
29
|
configure_for_zabbix if zabbix_installed?
|
30
30
|
end
|
31
31
|
|
32
32
|
# reload/restart postgres if command line option is given
|
33
|
-
@node.restart_service
|
34
|
-
@node.reload_service
|
33
|
+
@node.restart_service(@config['service_name']) if options.restart?
|
34
|
+
@node.reload_service(@config['service_name']) if options.reload?
|
35
35
|
end
|
36
36
|
|
37
37
|
desc 'postgres:status', 'displays status of postgres cluster'
|
38
38
|
def status
|
39
|
-
return unless @node.package_installed?
|
39
|
+
return unless @node.package_installed?([ 'postgresql-server', "postgresql-#{@config['version']}" ])
|
40
40
|
set_default_directories
|
41
|
-
@node.print_service_status
|
41
|
+
@node.print_service_status(@config['service_name'])
|
42
42
|
end
|
43
43
|
|
44
44
|
|
@@ -55,7 +55,7 @@ class Postgres < Recipe
|
|
55
55
|
return @node.messages.add('os not supported, please specify "package: <package name>" in your config').failed
|
56
56
|
end
|
57
57
|
|
58
|
-
@node.install_package
|
58
|
+
@node.install_package(package)
|
59
59
|
end
|
60
60
|
|
61
61
|
# set conf-dir and data-dir as well as service-name
|
@@ -85,25 +85,30 @@ class Postgres < Recipe
|
|
85
85
|
|
86
86
|
# deploy postgresql.conf, pg_hba.conf and pg_ident.conf
|
87
87
|
def deploy_config
|
88
|
-
@node.write
|
89
|
-
@node.write
|
90
|
-
@node.write "#{@config['conf_directory']}/pg_ident.conf", generate_pg_ident_conf
|
88
|
+
@node.write("#{@config['conf_directory']}/postgresql.conf", generate_postgresql_conf)
|
89
|
+
@node.write("#{@config['conf_directory']}/pg_hba.conf", generate_pg_hba_conf)
|
90
|
+
@node.write( "#{@config['conf_directory']}/pg_ident.conf", generate_pg_ident_conf)
|
91
91
|
end
|
92
92
|
|
93
93
|
# copy recovery.conf to either recovery.conf or recovery.done
|
94
94
|
# depending on which file already exists.
|
95
95
|
def deploy_recovery
|
96
|
-
if @node.file_exists?
|
97
|
-
@node.write
|
96
|
+
if @node.file_exists?("#{@config['postgresql.conf']['data_directory']}/recovery.conf", :quiet => true)
|
97
|
+
@node.write("#{@config['postgresql.conf']['data_directory']}/recovery.conf", generate_recovery_conf)
|
98
98
|
else
|
99
|
-
@node.write
|
99
|
+
@node.write("#{@config['postgresql.conf']['data_directory']}/recovery.done", generate_recovery_conf)
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
103
|
# deploy certificates to data-dir
|
104
104
|
def deploy_certificates
|
105
|
-
@node.deploy_file
|
106
|
-
|
105
|
+
@node.deploy_file("#{@template_path}/#{@config['server.crt']}",
|
106
|
+
"#{@config['postgresql.conf']['data_directory']}/server.crt",
|
107
|
+
:binding => binding)
|
108
|
+
|
109
|
+
@node.deploy_file("#{@template_path}/#{@config['server.key']}",
|
110
|
+
"#{@config['postgresql.conf']['data_directory']}/server.key",
|
111
|
+
:binding => binding)
|
107
112
|
end
|
108
113
|
|
109
114
|
# default settings for postgresql.conf
|
@@ -122,10 +127,10 @@ class Postgres < Recipe
|
|
122
127
|
|
123
128
|
def generate_postgresql_conf
|
124
129
|
@config['postgresql.conf'] ||= {}
|
125
|
-
@config['postgresql.conf'] = default_postgres_conf.merge
|
130
|
+
@config['postgresql.conf'] = default_postgres_conf.merge(@config['postgresql.conf'])
|
126
131
|
|
127
132
|
# calculate values if dedicated profile is given
|
128
|
-
profile_dedicated if @config['profile'].to_array.include?
|
133
|
+
profile_dedicated if @config['profile'].to_array.include?('dedicated')
|
129
134
|
|
130
135
|
postgresql_conf = ''
|
131
136
|
@config['postgresql.conf'].each do |key, value|
|
@@ -150,18 +155,18 @@ class Postgres < Recipe
|
|
150
155
|
|
151
156
|
def generate_pg_hba_conf
|
152
157
|
@config['pg_hba.conf'] ||= [ 'local all postgres trust' ]
|
153
|
-
@config['pg_hba.conf'].join
|
158
|
+
@config['pg_hba.conf'].join("\n")
|
154
159
|
end
|
155
160
|
|
156
161
|
def generate_pg_ident_conf
|
157
162
|
@config['pg_ident.conf'] ||= []
|
158
|
-
@config['pg_ident.conf'].join
|
163
|
+
@config['pg_ident.conf'].join("\n")
|
159
164
|
end
|
160
165
|
|
161
166
|
# try to find good values (but don't overwrite if set in config file) for
|
162
167
|
# shared_buffers, work_mem and maintenance_work_mem, effective_cache_size and wal_buffers
|
163
168
|
def profile_dedicated
|
164
|
-
@node.collect_facts
|
169
|
+
@node.collect_facts(:quiet => true)
|
165
170
|
system_mem = ::Dust.convert_size(@node['memorysize']).to_f
|
166
171
|
|
167
172
|
msg = @node.messages.add("calculating recommended settings for a dedicated databse server with #{kb2mb system_mem} ram\n")
|
@@ -198,22 +203,24 @@ class Postgres < Recipe
|
|
198
203
|
|
199
204
|
# give the configured dbuser the data_directory
|
200
205
|
def set_permissions
|
201
|
-
|
202
|
-
|
206
|
+
if @config['dbuser']
|
207
|
+
@node.chown("#{@config['dbuser']}:#{@node.get_gid(@config['dbuser'])}", @config['postgresql.conf']['data_directory'])
|
208
|
+
end
|
209
|
+
@node.chmod('u+Xrw,g-rwx,o-rwx', @config['postgresql.conf']['data_directory'])
|
203
210
|
end
|
204
211
|
|
205
212
|
# deploy the pacemaker script
|
206
213
|
def deploy_pacemaker_script
|
207
|
-
@node.deploy_file
|
208
|
-
@node.chmod
|
214
|
+
@node.deploy_file("#{@template_path}/pacemaker.sh", "#{@config['conf_directory']}/pacemaker.sh", :binding => binding)
|
215
|
+
@node.chmod('755', "#{@config['conf_directory']}/pacemaker.sh")
|
209
216
|
end
|
210
217
|
|
211
218
|
# check if zabbix is installed
|
212
219
|
def zabbix_installed?
|
213
220
|
if @node.uses_emerge?
|
214
|
-
return @node.package_installed?
|
221
|
+
return @node.package_installed?('zabbix', :quiet => true)
|
215
222
|
else
|
216
|
-
return @node.package_installed?
|
223
|
+
return @node.package_installed?('zabbix-agent', :quiet => true)
|
217
224
|
end
|
218
225
|
end
|
219
226
|
|
@@ -225,7 +232,7 @@ class Postgres < Recipe
|
|
225
232
|
msg = @node.messages.add('adding zabbix user to postgres group', :indent => 2)
|
226
233
|
msg.parse_result(@node.exec('usermod -a -G postgres zabbix')[:exit_code])
|
227
234
|
|
228
|
-
if is_master?
|
235
|
+
if is_master?(:indent => 2)
|
229
236
|
msg = @node.messages.add('checking if zabbix user exists in postgres', :indent => 3)
|
230
237
|
ret = msg.parse_result(@node.exec('psql -U postgres -c ' +
|
231
238
|
' "SELECT usename FROM pg_user WHERE usename = \'zabbix\'"' +
|
@@ -243,9 +250,9 @@ class Postgres < Recipe
|
|
243
250
|
end
|
244
251
|
|
245
252
|
# checks if this server is a postgres master
|
246
|
-
def is_master?
|
253
|
+
def is_master?(options = {})
|
247
254
|
msg = @node.messages.add('checking if this host is the postgres master: ', options)
|
248
|
-
if @node.file_exists?
|
255
|
+
if @node.file_exists?("#{@config['postgresql.conf']['data_directory']}/recovery.done", :quiet => true)
|
249
256
|
msg.ok('yes')
|
250
257
|
return true
|
251
258
|
else
|
data/lib/dust/recipes/sudoers.rb
CHANGED
@@ -33,17 +33,22 @@ class Sudoers < Recipe
|
|
33
33
|
private
|
34
34
|
|
35
35
|
def remove_other_rules
|
36
|
-
@node.messages.add("
|
36
|
+
msg = @node.messages.add("removing non-dust rules\n")
|
37
37
|
ret = @node.exec('ls /etc/sudoers.d/* |cat')
|
38
38
|
if ret[:exit_code] != 0
|
39
39
|
return @node.messages.add('couldn\'t get installed rule list, skipping deletion of old rules').warning
|
40
40
|
end
|
41
41
|
|
42
|
-
#
|
42
|
+
# get unmaintained rules
|
43
|
+
old_rules = []
|
43
44
|
ret[:stdout].each_line do |file|
|
44
45
|
file.chomp!
|
45
|
-
|
46
|
+
old_rules << file unless @config.keys.include?(File.basename(file))
|
46
47
|
end
|
48
|
+
|
49
|
+
# delete old rules, or display message that none were found
|
50
|
+
old_rules.each { |file| @node.rm(file, :indent => 2) }
|
51
|
+
@node.messages.add('none found', :indent => 2).ok if old_rules.empty?
|
47
52
|
end
|
48
53
|
|
49
54
|
def deploy_rule(name, file)
|
data/lib/dust/recipes/sysctl.rb
CHANGED
@@ -2,13 +2,13 @@ class Sysctl < Recipe
|
|
2
2
|
desc 'sysctl:deploy', 'configures sysctl'
|
3
3
|
def deploy
|
4
4
|
# we need support for /etc/sysctl.d/
|
5
|
-
unless @node.dir_exists?
|
5
|
+
unless @node.dir_exists?('/etc/sysctl.d/')
|
6
6
|
return @node.messages.add('sysctl configuration not supported for your linux distribution').warning
|
7
7
|
end
|
8
8
|
|
9
9
|
# seperate templates from sysctls
|
10
10
|
sysctls = @config.clone
|
11
|
-
templates = sysctls.delete
|
11
|
+
templates = sysctls.delete('templates')
|
12
12
|
|
13
13
|
# apply template sysctls
|
14
14
|
if templates
|
@@ -18,24 +18,46 @@ class Sysctl < Recipe
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
# apply
|
22
|
-
|
23
|
-
|
21
|
+
# apply sysctls
|
22
|
+
sysctls.each do |name, keys|
|
23
|
+
@node.messages.add("configuring sysctls (#{name})\n")
|
24
|
+
apply(name, keys)
|
25
|
+
end
|
26
|
+
|
27
|
+
# don't remove other rules for now
|
28
|
+
# remove_other_rules(sysctls.keys)
|
24
29
|
end
|
25
30
|
|
26
31
|
|
27
32
|
private
|
28
33
|
|
29
|
-
def apply
|
34
|
+
def apply(name, sysctl)
|
30
35
|
sysctl_conf = ''
|
31
36
|
sysctl.each do |key, value|
|
32
|
-
|
33
|
-
|
37
|
+
if options.restart?
|
38
|
+
msg = @node.messages.add("setting #{key} = #{value}", :indent => 2)
|
39
|
+
msg.parse_result(@node.exec("sysctl -w #{key}=#{value}")[:exit_code])
|
40
|
+
end
|
34
41
|
sysctl_conf << "#{key} = #{value}\n"
|
35
42
|
end
|
36
43
|
|
37
|
-
msg = @node.messages.add("saving settings to /etc/sysctl.d
|
38
|
-
msg.parse_result(@node.write("/etc/sysctl.d
|
44
|
+
msg = @node.messages.add("saving settings to /etc/sysctl.d/#{name}.conf", :indent => 2)
|
45
|
+
msg.parse_result(@node.write("/etc/sysctl.d/#{name}.conf", sysctl_conf, :quiet => true))
|
46
|
+
end
|
47
|
+
|
48
|
+
# removes rules from /etc/sysctl.d/ that are not present in "names"
|
49
|
+
def remove_other(names)
|
50
|
+
@node.messages.add("deleting old rules\n")
|
51
|
+
ret = @node.exec('ls /etc/sysctl.d/* |cat')
|
52
|
+
if ret[:exit_code] != 0
|
53
|
+
return @node.messages.add('couldn\'t get list of files in /etc/sysctl.d, skipping deletion of old rules').warning
|
54
|
+
end
|
55
|
+
|
56
|
+
# delete file if not in config
|
57
|
+
ret[:stdout].each_line do |file|
|
58
|
+
file.chomp!
|
59
|
+
@node.rm(file, :indent => 2) unless names.include?(File.basename(file))
|
60
|
+
end
|
39
61
|
end
|
40
62
|
|
41
63
|
|
@@ -43,7 +65,7 @@ class Sysctl < Recipe
|
|
43
65
|
|
44
66
|
# disable allocation of more ram than actually there for postgres
|
45
67
|
def postgres
|
46
|
-
database.merge
|
68
|
+
database.merge('vm.overcommit_memory' => 2)
|
47
69
|
end
|
48
70
|
|
49
71
|
# redis complains if vm.overcommit_memory != 1
|
@@ -58,7 +80,7 @@ class Sysctl < Recipe
|
|
58
80
|
# use half of the system memory for shmmax
|
59
81
|
# and set shmall according to pagesize
|
60
82
|
def database
|
61
|
-
@node.collect_facts
|
83
|
+
@node.collect_facts(:quiet => true)
|
62
84
|
|
63
85
|
# get pagesize
|
64
86
|
pagesize = @node.exec('getconf PAGESIZE')[:stdout].to_i || 4096
|
data/lib/dust/recipes/users.rb
CHANGED
@@ -26,7 +26,7 @@ class Users < Recipe
|
|
26
26
|
Dir["#{@template_path}/#{key_dir}/*"].each do |file|
|
27
27
|
destination = "#{ssh_dir}/#{File.basename(file)}"
|
28
28
|
@node.scp(file, destination, :indent => 2)
|
29
|
-
@node.chown("#{user}:#{user}", destination)
|
29
|
+
@node.chown("#{user}:#{@node.get_gid(user)}", destination)
|
30
30
|
|
31
31
|
# chmod private key
|
32
32
|
if File.basename(file) =~ /^(id_rsa|id_dsa|id_ecdsa)$/
|
@@ -40,25 +40,38 @@ class Users < Recipe
|
|
40
40
|
def deploy_authorized_keys(user, ssh_users)
|
41
41
|
@node.messages.add("generating authorized_keys for #{user}\n")
|
42
42
|
ssh_dir = create_ssh_dir(user)
|
43
|
+
|
43
44
|
authorized_keys = generate_authorized_keys(ssh_users)
|
45
|
+
return false unless authorized_keys
|
46
|
+
|
44
47
|
@node.write("#{ssh_dir}/authorized_keys", authorized_keys)
|
45
|
-
@node.chown("#{user}:#{user}", "#{ssh_dir}/authorized_keys")
|
48
|
+
@node.chown("#{user}:#{@node.get_gid(user)}", "#{ssh_dir}/authorized_keys")
|
49
|
+
@node.chcon({ 'type' => 'ssh_home_t' }, "#{ssh_dir}/authorized_keys")
|
46
50
|
end
|
47
51
|
|
48
52
|
def create_ssh_dir(user)
|
49
53
|
ssh_dir = @node.get_home(user) + '/.ssh'
|
50
54
|
@node.mkdir(ssh_dir)
|
51
|
-
@node.chown("#{user}:#{user}", ssh_dir)
|
55
|
+
@node.chown("#{user}:#{@node.get_gid(user)}", ssh_dir)
|
56
|
+
@node.chcon({ 'type' => 'ssh_home_t' }, ssh_dir)
|
52
57
|
ssh_dir
|
53
58
|
end
|
54
59
|
|
55
60
|
def generate_authorized_keys(ssh_users)
|
56
61
|
# load users and their ssh keys from yaml file
|
62
|
+
unless File.exists?("#{@template_path}/public_keys.yaml")
|
63
|
+
return @node.messages.add("#{@template_path}/public_keys.yaml not present").failed
|
64
|
+
end
|
65
|
+
|
57
66
|
users = YAML.load_file("#{@template_path}/public_keys.yaml")
|
58
67
|
authorized_keys = ''
|
59
68
|
|
60
69
|
# create the authorized_keys hash for this user
|
61
70
|
ssh_users.to_array.each do |ssh_user|
|
71
|
+
unless users[ssh_user]
|
72
|
+
return @node.messages.add("#{ssh_user} cannot be found in #{@template_path}/public_keys.yaml").failed
|
73
|
+
end
|
74
|
+
|
62
75
|
users[ssh_user]['name'] ||= ssh_user
|
63
76
|
msg = @node.messages.add("adding user #{users[ssh_user]['name']}", :indent => 2)
|
64
77
|
users[ssh_user]['keys'].each do |key|
|
data/lib/dust/runner.rb
CHANGED
@@ -337,9 +337,9 @@ module Dust
|
|
337
337
|
inherited = {}
|
338
338
|
node.delete('inherits').each do |file|
|
339
339
|
template = YAML.load ERB.new( File.read("./nodes/#{file}.yaml"), nil, '%<>').result
|
340
|
-
inherited.deep_merge!
|
340
|
+
inherited.deep_merge!(template)
|
341
341
|
end
|
342
|
-
node = inherited.deep_merge
|
342
|
+
node = inherited.deep_merge(node)
|
343
343
|
end
|
344
344
|
|
345
345
|
# if more than one hostname is specified, create a node
|
data/lib/dust/server.rb
CHANGED
@@ -164,6 +164,8 @@ module Dust
|
|
164
164
|
else
|
165
165
|
# files = 644, dirs = 755
|
166
166
|
permissions = 'ug-x,o-wx,u=rwX,g=rX,o=rX'
|
167
|
+
user = 'root'
|
168
|
+
group = 'root'
|
167
169
|
end
|
168
170
|
|
169
171
|
# if in sudo mode, copy file to temporary place, then move using sudo
|
@@ -232,6 +234,28 @@ module Dust
|
|
232
234
|
msg.parse_result(exec("chown -R #{user} #{file}")[:exit_code])
|
233
235
|
end
|
234
236
|
|
237
|
+
def chcon(permissions, file, options = {})
|
238
|
+
options = default_options.merge(options)
|
239
|
+
|
240
|
+
# just return if selinux is not enabled
|
241
|
+
return true unless selinuxenabled?
|
242
|
+
|
243
|
+
args = ""
|
244
|
+
args << " --type #{permissions['type']}" if permissions['type']
|
245
|
+
args << " --recursive #{permissions['recursive']}" if permissions['recursive']
|
246
|
+
args << " --user #{permissions['user']}" if permissions['user']
|
247
|
+
args << " --range #{permissions['range']}" if permissions['range']
|
248
|
+
args << " --role #{permissions['role']}" if permissions['role']
|
249
|
+
|
250
|
+
msg = messages.add("setting selinux permissions of #{File.basename file}", options)
|
251
|
+
msg.parse_result(exec("chcon #{args} #{file}")[:exit_code])
|
252
|
+
end
|
253
|
+
|
254
|
+
def selinuxenabled?
|
255
|
+
return true if exec('selinuxenabled')[:exit_code] == 0
|
256
|
+
false
|
257
|
+
end
|
258
|
+
|
235
259
|
def rm file, options = {}
|
236
260
|
options = default_options.merge options
|
237
261
|
|
@@ -275,12 +299,11 @@ module Dust
|
|
275
299
|
def restorecon path, options = {}
|
276
300
|
options = default_options.merge options
|
277
301
|
|
278
|
-
# if
|
279
|
-
|
280
|
-
return true unless ret[:exit_code] == 0
|
302
|
+
# if selinux is not enabled, just return
|
303
|
+
return true unless selinuxenabled?
|
281
304
|
|
282
305
|
msg = messages.add("restoring selinux labels for #{path}", options)
|
283
|
-
msg.parse_result(exec("
|
306
|
+
msg.parse_result(exec("restorecon -R #{path}")[:exit_code])
|
284
307
|
end
|
285
308
|
|
286
309
|
def get_system_users options = {}
|
@@ -738,10 +761,10 @@ module Dust
|
|
738
761
|
args << " --append --groups #{Array(options['groups']).join(',')}" if options['groups']
|
739
762
|
|
740
763
|
if args.empty?
|
741
|
-
|
764
|
+
ret = messages.add("user #{user} already set up correctly", options).ok
|
742
765
|
else
|
743
766
|
msg = messages.add("modifying user #{user}", { :indent => options[:indent] }.merge(options))
|
744
|
-
|
767
|
+
ret = msg.parse_result(exec("usermod #{args} #{user}")[:exit_code])
|
745
768
|
end
|
746
769
|
|
747
770
|
else
|
@@ -755,16 +778,20 @@ module Dust
|
|
755
778
|
args << " --groups #{Array(options['groups']).join(',')}" if options['groups']
|
756
779
|
|
757
780
|
msg = messages.add("creating user #{user}", { :indent => options[:indent] }.merge(options))
|
758
|
-
|
781
|
+
ret = msg.parse_result(exec("useradd #{user} #{args}")[:exit_code])
|
759
782
|
end
|
783
|
+
|
784
|
+
# set selinux permissions
|
785
|
+
chcon({ 'type' => 'user_home_dir_t' }, get_home(user), options)
|
786
|
+
return ret
|
760
787
|
end
|
761
788
|
|
762
789
|
# returns the home directory of this user
|
763
|
-
def get_home
|
764
|
-
options = default_options(:quiet => true).merge
|
790
|
+
def get_home(user, options = {})
|
791
|
+
options = default_options(:quiet => true).merge(options)
|
765
792
|
|
766
793
|
msg = messages.add("getting home directory of #{user}", options)
|
767
|
-
ret = exec
|
794
|
+
ret = exec("getent passwd |cut -d':' -f1,6 |grep '^#{user}' |head -n1 |cut -d: -f2")
|
768
795
|
if msg.parse_result(ret[:exit_code])
|
769
796
|
return ret[:stdout].chomp
|
770
797
|
else
|
@@ -773,11 +800,24 @@ module Dust
|
|
773
800
|
end
|
774
801
|
|
775
802
|
# returns shell of this user
|
776
|
-
def get_shell
|
777
|
-
options = default_options(:quiet => true).merge
|
803
|
+
def get_shell(user, options = {})
|
804
|
+
options = default_options(:quiet => true).merge(options)
|
778
805
|
|
779
806
|
msg = messages.add("getting shell of #{user}", options)
|
780
|
-
ret = exec
|
807
|
+
ret = exec("getent passwd |cut -d':' -f1,7 |grep '^#{user}' |head -n1 |cut -d: -f2")
|
808
|
+
if msg.parse_result(ret[:exit_code])
|
809
|
+
return ret[:stdout].chomp
|
810
|
+
else
|
811
|
+
return false
|
812
|
+
end
|
813
|
+
end
|
814
|
+
|
815
|
+
# returns primary group id of this user
|
816
|
+
def get_gid(user, options = {})
|
817
|
+
options = default_options(:quiet => true).merge(options)
|
818
|
+
|
819
|
+
msg = messages.add("getting primary gid of #{user}", options)
|
820
|
+
ret = exec("getent passwd |cut -d':' -f1,4 |grep '^#{user}' |head -n1 |cut -d: -f2")
|
781
821
|
if msg.parse_result(ret[:exit_code])
|
782
822
|
return ret[:stdout].chomp
|
783
823
|
else
|
data/lib/dust/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dust-deploy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-08-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|