dust-deploy 0.15.2 → 0.16.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/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
|