dust-deploy 0.4.1 → 0.4.2

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.
@@ -1,6 +1,13 @@
1
1
  Changelog
2
2
  =============
3
3
 
4
+ 0.4.2
5
+ ------------
6
+
7
+ adds hash_check recipe, which can check for weak hashes (according to provided list) in your /etc/shadow files.
8
+ can be used e.g. for making sure that none of your servers still has the template password.
9
+
10
+
4
11
  0.4.1
5
12
  ------------
6
13
 
@@ -1,6 +1,5 @@
1
1
  require 'dust/helper'
2
2
  require 'dust/print_status'
3
- require 'dust/convert_size'
4
3
  require 'dust/server'
5
4
  require 'dust/recipe'
6
5
 
@@ -0,0 +1,26 @@
1
+ root
2
+ toor
3
+ user
4
+ 123456
5
+ 12345
6
+ password
7
+ password1
8
+ 123456789
9
+ 12345678
10
+ 1234567890
11
+ abc123
12
+ computer
13
+ tigger
14
+ 1234
15
+ qwerty
16
+ money
17
+ carmen
18
+ mickey
19
+ secret
20
+ summer
21
+ internet
22
+ a1b2c3
23
+ 123
24
+ service
25
+ hello
26
+ 123abc
@@ -49,3 +49,24 @@ class String
49
49
  false
50
50
  end
51
51
  end
52
+
53
+
54
+ module Dust
55
+ # converts string to kilobytes (rounded)
56
+ def self.convert_size s
57
+ i, unit = s.split(' ')
58
+
59
+ case unit.downcase
60
+ when 'kb'
61
+ return i.to_i
62
+ when 'mb'
63
+ return (i.to_f * 1024).to_i
64
+ when 'gb'
65
+ return (i.to_f * 1024 * 1024).to_i
66
+ when 'tb'
67
+ return (i.to_f * 1024 * 1024 * 1024).to_i
68
+ else
69
+ return false
70
+ end
71
+ end
72
+ end
@@ -2,7 +2,8 @@ class Aliases < Recipe
2
2
  desc 'aliases:deploy', 'installs email aliases'
3
3
  def deploy
4
4
  return unless @node.package_installed? 'postfix'
5
- @node.scp "#{@template_path}/aliases", '/etc/aliases'
5
+
6
+ @node.deploy_file "#{@template_path}/aliases", '/etc/aliases', :binding => binding
6
7
 
7
8
  ::Dust.print_msg 'running newaliases'
8
9
  ::Dust.print_result @node.exec('newaliases')[:exit_code]
@@ -25,7 +25,7 @@ class BasicSetup < Recipe
25
25
  ::Dust.print_msg "deploying configuration files for root\n"
26
26
  Dir["#{@template_path}/.*"].each do |file|
27
27
  next unless File.file? file
28
- @node.scp file, "/root/#{File.basename file}", :indent => 2
28
+ @node.deploy_file file, "/root/#{File.basename file}", { :binding => binding, :indent => 2 }
29
29
  end
30
30
 
31
31
  end
@@ -1,5 +1,3 @@
1
- require 'erb'
2
-
3
1
  class Duplicity < Recipe
4
2
  desc 'duplicity:deploy', 'installs and configures duplicity backups'
5
3
  def deploy
@@ -46,11 +44,11 @@ class Duplicity < Recipe
46
44
  cronjob_path = "/etc/cron.#{config['interval']}/duplicity-#{scenario}"
47
45
 
48
46
  # adjust and upload cronjob
49
- template = ERB.new File.read("#{@template_path}/cronjob.erb"), nil, '%<>'
50
- ::Dust.print_msg "adjusting and deploying cronjob (scenario: #{scenario}, interval: #{config['interval']})\n"
47
+ ::Dust.print_msg "adjusting and deploying cronjob (scenario: #{scenario}, interval: #{config['interval']})\n"
51
48
  config['options'].each { |option| ::Dust.print_ok "adding option: #{option}", :indent => 2 }
52
- @node.write cronjob_path, template.result(binding)
53
-
49
+
50
+ @node.deploy_file "#{@template_path}/cronjob", cronjob_path, :binding => binding
51
+
54
52
  # making cronjob executeable
55
53
  @node.chmod '0700', cronjob_path
56
54
  puts
@@ -1,7 +1,7 @@
1
1
  class EtcHosts < Recipe
2
2
  desc 'etc_hosts:deploy', 'deploys /etc/hosts'
3
3
  def deploy
4
- @node.scp "#{@template_path}/hosts", '/etc/hosts'
4
+ @node.deploy_file "#{@template_path}/hosts", '/etc/hosts', :binding => binding
5
5
 
6
6
  # restart dns service
7
7
  if @options.restart? and @config.is_a? String
@@ -0,0 +1,44 @@
1
+ class HashCheck < Recipe
2
+
3
+ desc 'hash_check:deploy', 'checks /etc/shadow for weak hashes'
4
+ def deploy
5
+ # mkpasswd is in the package 'whois' resp. 'expect'
6
+ @node.install_package 'whois' if @node.uses_apt?
7
+ @node.install_package 'expect' if @node.uses_rpm?
8
+
9
+ # those keys indicate that no password is set, or login is disabled
10
+ keys = [ '*', '!', '!!', '', 'LK', 'NP' ]
11
+
12
+ # mapping the magic numbers to the actual hash algorithms
13
+ algorithms = { '1' => 'md5', '2' => 'blowfish', '5' => 'sha-256', '6' => 'sha-512' }
14
+
15
+ weak_passwords = File.open "#{@template_path}/weak_passwords", 'r'
16
+ shadow = @node.exec('cat /etc/shadow')[:stdout]
17
+
18
+ ::Dust.print_msg "checking for weak password hashes\n"
19
+
20
+ found_weak = false
21
+
22
+ shadow.each do |line|
23
+ user, hash = line.split(':')[0..1]
24
+ next if keys.include? hash
25
+ method, salt = hash.split('$')[1..2]
26
+
27
+ weak_passwords.each_line do |password|
28
+ password.chomp!
29
+
30
+ # generate the hash for this password, according to salt and method
31
+ weak_hash = @node.exec("mkpasswd -m #{algorithms[method.to_s]} -S '#{salt}' '#{password}'")[:stdout]
32
+ weak_hash.chomp!
33
+
34
+ if weak_hash == hash
35
+ ::Dust.print_failed "user #{user} has a weak password! (#{password})", :indent => 2
36
+ found_weak= true
37
+ end
38
+ end
39
+ end
40
+
41
+ weak_passwords.close
42
+ ::Dust.print_ok 'none found.', :indent => 2 unless found_weak
43
+ end
44
+ end
@@ -1,10 +1,6 @@
1
- require 'erb'
2
-
3
1
  class Motd < Recipe
4
2
  desc 'motd:deploy', 'creates message of the day'
5
- def deploy
6
- # configure node using erb template
7
- template = ERB.new File.read("#{@template_path}/motd.erb"), nil, '%<>'
8
- @node.write '/etc/motd', template.result(binding)
3
+ def deploy
4
+ @node.deploy_file "#{@template_path}/motd", '/etc/motd', :binding => binding
9
5
  end
10
6
  end
@@ -1,5 +1,3 @@
1
- require 'erb'
2
-
3
1
  class Mysql < Recipe
4
2
  desc 'mysql:deploy', 'installs and configures mysql database'
5
3
  def deploy
@@ -36,8 +34,7 @@ class Mysql < Recipe
36
34
 
37
35
  ::Dust.print_ok "setting innodb buffer pool to '#{@config['innodb_buffer_pool_size']}'", :indent => 2
38
36
 
39
- template = ERB.new( File.read("#{@template_path}/my.cnf.erb"), nil, '%<>')
40
- @node.write '/etc/mysql/my.cnf', template.result(binding)
37
+ @node.deploy_file "#{@template_path}/my.cnf", '/etc/mysql/my.cnf', :binding => binding
41
38
  @node.chmod '644', '/etc/mysql/my.cnf'
42
39
 
43
40
  @node.restart_service 'mysql-server' if options.restart?
@@ -4,8 +4,10 @@ class Newrelic < Recipe
4
4
  return Dust.print_failed 'no key specified' unless @config
5
5
  return unless @node.uses_apt? :quiet=>false
6
6
 
7
- ::Dust.print_msg 'updating repositories'
8
- ::Dust.print_result @node.exec('aptitude update')[:exit_code]
7
+ if @options.restart? or @options.reload?
8
+ ::Dust.print_msg 'updating repositories'
9
+ ::Dust.print_result @node.exec('aptitude update')[:exit_code]
10
+ end
9
11
 
10
12
  unless @node.install_package 'newrelic-sysmond'
11
13
  ::Dust.print_failed 'installing newrelic monitoring daemon failed, did you setup the newrelic repositories?'
@@ -1,5 +1,3 @@
1
- require 'erb'
2
-
3
1
  class Nginx < Recipe
4
2
  desc 'nginx:deploy', 'installs and configures nginx web server'
5
3
  def deploy
@@ -14,27 +12,13 @@ class Nginx < Recipe
14
12
  ::Dust.print_ok
15
13
 
16
14
  @config.each do |state, site|
17
- file = "#{@template_path}/sites/#{site}"
18
-
19
- # if this site is just a regular file, copy it to sites-available
20
- if File.exists? file
21
- @node.scp file, "/etc/nginx/sites-available/#{site}"
22
-
23
- # if this site is an erb template, render it and deploy
24
- elsif File.exists? "#{file}.erb"
25
- template = ERB.new( File.read("#{file}.erb"), nil, '%<>')
26
- @node.write "/etc/nginx/sites-available/#{site}", template.result(binding)
27
-
28
- # skip to next site if template wasn't found
29
- else
30
- ::Dust.print_failed "couldn't find template for #{site}", :indent => 2
31
- next
32
- end
33
-
15
+
16
+ @node.deploy_file "#{@template_path}/sites/#{site}", "/etc/nginx/sites-available/#{site}", :binding => binding
17
+
34
18
  # symlink to sites-enabled if this is listed as an enabled site
35
19
  if state == 'sites-enabled'
36
20
  ::Dust.print_msg "enabling #{site}", :indent => 2
37
- ::Dust.print_result( @node.exec("cd /etc/nginx/sites-enabled && ln -s ../sites-available/#{site} #{site}")[:exit_code] )
21
+ ::Dust.print_result @node.exec("cd /etc/nginx/sites-enabled && ln -s ../sites-available/#{site} #{site}")[:exit_code]
38
22
  end
39
23
  end
40
24
 
@@ -1,5 +1,3 @@
1
- require 'erb'
2
-
3
1
  class Postgres < Recipe
4
2
  desc 'postgres:deploy', 'installs and configures postgresql database'
5
3
  def deploy
@@ -24,9 +22,9 @@ class Postgres < Recipe
24
22
  end
25
23
 
26
24
 
27
- deploy_file 'postgresql.conf', "#{@config['conf-dir']}/postgresql.conf"
28
- deploy_file 'pg_hba.conf', "#{@config['conf-dir']}/pg_hba.conf"
29
- deploy_file 'pg_ident.conf', "#{@config['conf-dir']}/pg_ident.conf"
25
+ @node.deploy_file "#{@template_path}/postgresql.conf", "#{@config['conf-dir']}/postgresql.conf", :binding => binding
26
+ @node.deploy_file "#{@template_path}/pg_hba.conf", "#{@config['conf-dir']}/pg_hba.conf", :binding => binding
27
+ @node.deploy_file "#{@template_path}/pg_ident.conf", "#{@config['conf-dir']}/pg_ident.conf", :binding => binding
30
28
 
31
29
  @node.chmod '644', "#{@config['conf-dir']}/postgresql.conf"
32
30
  @node.chmod '644', "#{@config['conf-dir']}/pg_hba.conf"
@@ -34,21 +32,21 @@ class Postgres < Recipe
34
32
 
35
33
  # deploy pacemaker script
36
34
  if @node.package_installed? 'pacemaker'
37
- deploy_file 'pacemaker.sh', "#{@config['conf-dir']}/pacemaker.sh"
35
+ @node.deploy_file "#{@template_path}/pacemaker.sh", "#{@config['conf-dir']}/pacemaker.sh", :binding => binding
38
36
  @node.chmod '755', "#{@config['conf-dir']}/pacemaker.sh"
39
37
  end
40
38
 
41
39
  # copy recovery.conf to either recovery.conf or recovery.done
42
40
  # depending on which file already exists.
43
41
  if @node.file_exists? "#{@config['data-dir']}/recovery.conf", :quiet => true
44
- deploy_file 'recovery.conf', "#{@config['data-dir']}/recovery.conf"
42
+ @node.deploy_file "#{@template_path}/recovery.conf", "#{@config['data-dir']}/recovery.conf", :binding => binding
45
43
  else
46
- deploy_file 'recovery.conf', "#{@config['data-dir']}/recovery.done"
44
+ @node.deploy_file "#{@template_path}/recovery.conf", "#{@config['data-dir']}/recovery.done", :binding => binding
47
45
  end
48
46
 
49
47
  # deploy certificates to data-dir
50
- deploy_file 'server.crt', "#{@config['data-dir']}/server.crt"
51
- deploy_file 'server.key', "#{@config['data-dir']}/server.key"
48
+ @node.deploy_file "#{@template_path}/server.crt", "#{@config['data-dir']}/server.crt", :binding => binding
49
+ @node.deploy_file "#{@template_path}/server.key", "#{@config['data-dir']}/server.key", :binding => binding
52
50
 
53
51
  @node.chown @config['dbuser'], @config['data-dir'] if @config['dbuser']
54
52
  @node.chmod 'u+Xrw,g-rwx,o-rwx', @config['data-dir']
@@ -91,23 +89,5 @@ class Postgres < Recipe
91
89
  @node.reload_service @config['service-name'] if options.reload?
92
90
  end
93
91
 
94
- private
95
- def deploy_file file, target
96
- # if file is just a regular file, copy it to sites-available
97
- if File.exists? "#{@template_path}/#{file}"
98
- @node.scp "#{@template_path}/#{file}", target
99
-
100
- # if file is an erb template, render it and deploy
101
- elsif File.exists? "#{@template_path}/#{file}.erb"
102
- ::Dust.print_msg "adjusting and deploying #{file}"
103
- template = ERB.new( File.read("#{@template_path}/#{file}.erb"), nil, '%<>')
104
- ::Dust.print_result @node.write(target, template.result(binding), :quiet => true)
105
-
106
- # file was not found, return
107
- else
108
- return ::Dust.print_failed "file '#{@template_path}/#{file}' not found."
109
- end
110
- end
111
-
112
92
  end
113
93
 
@@ -1,24 +1,16 @@
1
- require 'erb'
2
-
3
1
  class ZabbixAgent < Recipe
4
2
  desc 'zabbix_agent:deploy', 'installs and configures zabbix agent'
5
3
  def deploy
6
4
  return unless install_zabbix
7
5
 
8
- # configure @node using erb template
9
- template = ERB.new File.read("#{@template_path}/zabbix_agentd.conf.erb"), nil, '%<>'
10
- ::Dust.print_msg 'adjusting and deploying zabbix_agentd.conf'
11
- @node.write '/etc/zabbix/zabbix_agentd.conf', template.result(binding), :quiet => true
12
- ::Dust.print_ok
13
-
6
+ @node.deploy_file "#{@template_path}/zabbix_agentd.conf", '/etc/zabbix/zabbix_agentd.conf', :binding => binding
7
+
8
+ # set daemon name, according zu distribution
9
+ daemon = @node.uses_emerge? ? 'zabbix-agentd' : 'zabbix-agent'
10
+
14
11
  # restart using new configuration
15
- if @node.uses_emerge? :quiet => true
16
- @node.autostart_service 'zabbix-agentd'
17
- @node.restart_service 'zabbix-agentd' if options.restart?
18
- else
19
- @node.autostart_service 'zabbix-agent'
20
- @node.restart_service 'zabbix-agent' if options.restart?
21
- end
12
+ @node.autostart_service daemon
13
+ @node.restart_service daemon if options.restart?
22
14
  end
23
15
 
24
16
  private
@@ -26,15 +18,13 @@ class ZabbixAgent < Recipe
26
18
  def install_zabbix
27
19
 
28
20
  if @node.uses_apt?
21
+ # debsecan is needed for zabbix checks (security updates)
29
22
  return false unless @node.install_package 'zabbix-agent'
30
-
31
- # debsecan is needed for zabbix checks (security updates)
32
23
  return false unless @node.install_package 'debsecan'
33
24
 
34
25
  elsif @node.uses_emerge?
26
+ # glsa-check (part of gentoolkit) is needed for zabbix checks (security updates)
35
27
  return false unless @node.install_package 'zabbix', :env => 'USE=agent'
36
-
37
- # glsa-check (part of gentoolkit) is needed for zabbix checks (security updates)
38
28
  return false unless @node.install_package 'gentoolkit'
39
29
 
40
30
  elsif @node.uses_rpm?
@@ -49,6 +39,9 @@ class ZabbixAgent < Recipe
49
39
  true
50
40
  end
51
41
 
42
+
43
+ # below this line is unfinished code, not in use yet
44
+
52
45
  # TODO (not yet finished)
53
46
  desc 'zabbix_agent:postgres', 'configure postgres database for zabbix monitoring'
54
47
  def postgres
@@ -69,7 +62,7 @@ class ZabbixAgent < Recipe
69
62
  ::Dust.print_result( @node.exec('createuser -U postgres zabbix -RSD')[:exit_code] )
70
63
  end
71
64
 
72
- # TODO: only GRANT is this is a master
65
+ # TODO: only GRANT is this is a master
73
66
  ::Dust.print_msg 'GRANT zabbix user access to postgres database'
74
67
  ::Dust.print_result( @node.exec('psql -U postgres -c "GRANT SELECT ON pg_stat_database TO zabbix" postgres')[:exit_code] )
75
68
 
@@ -2,37 +2,41 @@ require 'rubygems'
2
2
  require 'net/ssh'
3
3
  require 'net/scp'
4
4
  require 'net/ssh/proxy/socks5'
5
+ require 'erb'
5
6
 
6
7
  module Dust
7
8
  class Server
8
9
  attr_reader :ssh
9
10
 
10
- def initialize attr
11
- @attr = attr
12
-
13
- @attr['user'] ||= 'root'
14
- @attr['port'] ||= 22
15
- @attr['password'] ||= ''
11
+ def default_options options = {}
12
+ { :quiet => false, :indent => 1 }.merge options
13
+ end
14
+
15
+ def initialize node
16
+ @node = node
17
+ @node['user'] ||= 'root'
18
+ @node['port'] ||= 22
19
+ @node['password'] ||= ''
16
20
  end
17
21
 
18
22
  def connect
19
- Dust.print_hostname @attr['hostname']
23
+ Dust.print_hostname @node['hostname']
20
24
  begin
21
25
  # connect to proxy if given
22
- if @attr['proxy']
23
- host, port = @attr['proxy'].split ':'
26
+ if @node['proxy']
27
+ host, port = @node['proxy'].split ':'
24
28
  proxy = Net::SSH::Proxy::SOCKS5.new host, port
25
29
  else
26
30
  proxy = nil
27
31
  end
28
32
 
29
- @ssh = Net::SSH.start @attr['fqdn'], @attr['user'],
30
- { :password => @attr['password'],
31
- :port => @attr['port'],
33
+ @ssh = Net::SSH.start @node['fqdn'], @node['user'],
34
+ { :password => @node['password'],
35
+ :port => @node['port'],
32
36
  :proxy => proxy }
33
37
  rescue Exception
34
- error_message = "coudln't connect to #{@attr['fqdn']}"
35
- error_message += " (via socks5 proxy #{@attr['proxy']})" if proxy
38
+ error_message = "coudln't connect to #{@node['fqdn']}"
39
+ error_message += " (via socks5 proxy #{@node['proxy']})" if proxy
36
40
  Dust.print_failed error_message
37
41
  return false
38
42
  end
@@ -66,7 +70,9 @@ module Dust
66
70
  end
67
71
 
68
72
 
69
- def write target, text, options={:quiet => false, :indent => 1}
73
+ def write target, text, options = {}
74
+ options = default_options.merge options
75
+
70
76
  Dust.print_msg "deploying #{File.basename target}", options
71
77
 
72
78
  # escape $ signs and \ at the end of line
@@ -84,40 +90,54 @@ module Dust
84
90
  restorecon target, options # restore SELinux labels
85
91
  end
86
92
 
87
- def append target, text, options={:quiet => false, :indent => 1}
93
+ def append target, text, options = {}
94
+ options = default_options.merge options
95
+
88
96
  Dust.print_msg "appending to #{File.basename target}", options
89
97
  Dust.print_result exec("cat << EOF >> #{target}\n#{text}\nEOF")[:exit_code], options
90
98
  end
91
99
 
92
- def scp source, destination, options={:quiet => false, :indent => 1}
100
+ def scp source, destination, options = {}
101
+ options = default_options.merge options
102
+
93
103
  Dust.print_msg "deploying #{File.basename(source)}", options
94
104
  @ssh.scp.upload! source, destination
95
105
  Dust.print_ok '', options
96
106
  restorecon destination, options # restore SELinux labels
97
107
  end
98
108
 
99
- def symlink source, destination, options={:quiet => false, :indent => 1}
109
+ def symlink source, destination, options = {}
110
+ options = default_options.merge options
111
+
100
112
  Dust.print_msg "symlinking #{File.basename(source)} to '#{destination}'", options
101
113
  Dust.print_result exec("ln -s #{source} #{destination}")[:exit_code], options
102
114
  restorecon destination, options # restore SELinux labels
103
115
  end
104
116
 
105
- def chmod mode, file, options={:quiet => false, :indent => 1}
117
+ def chmod mode, file, options = {}
118
+ options = default_options.merge options
119
+
106
120
  Dust.print_msg "setting mode of #{File.basename(file)} to #{mode}", options
107
121
  Dust.print_result exec("chmod -R #{mode} #{file}")[:exit_code], options
108
122
  end
109
123
 
110
- def chown user, file, options={:quiet => false, :indent => 1}
124
+ def chown user, file, options = {}
125
+ options = default_options.merge options
126
+
111
127
  Dust.print_msg "setting owner of #{File.basename(file)} to #{user}", options
112
128
  Dust.print_result exec("chown -R #{user} #{file}")[:exit_code], options
113
129
  end
114
130
 
115
- def rm file, options={:quiet => false, :indent => 1}
131
+ def rm file, options = {}
132
+ options = default_options.merge options
133
+
116
134
  Dust.print_msg "deleting #{file}", options
117
135
  Dust.print_result exec("rm -rf #{file}")[:exit_code], options
118
136
  end
119
137
 
120
- def mkdir dir, options={:quiet => false, :indent => 1}
138
+ def mkdir dir, options = {}
139
+ options = default_options.merge options
140
+
121
141
  return true if dir_exists? dir, :quiet => true
122
142
 
123
143
  Dust.print_msg "creating directory #{dir}", options
@@ -127,7 +147,9 @@ module Dust
127
147
 
128
148
  # check if restorecon (selinux) is available
129
149
  # if so, run it on "path" recursively
130
- def restorecon path, options={:quiet => false, :indent => 1}
150
+ def restorecon path, options = {}
151
+ options = default_options.merge options
152
+
131
153
 
132
154
  # if restorecon is not installed, just return true
133
155
  ret = exec 'which restorecon'
@@ -137,7 +159,9 @@ module Dust
137
159
  Dust.print_result exec("#{ret[:stdout].chomp} -R #{path}")[:exit_code], options
138
160
  end
139
161
 
140
- def get_system_users options={:quiet => false, :indent => 1}
162
+ def get_system_users options = {}
163
+ options = default_options.merge options
164
+
141
165
  Dust.print_msg "getting all system users", options
142
166
  ret = exec 'getent passwd |cut -d: -f1'
143
167
  Dust.print_result ret[:exit_code], options
@@ -150,7 +174,9 @@ module Dust
150
174
  end
151
175
 
152
176
  # checks if one of the packages is installed
153
- def package_installed? packages, options={:quiet => false, :indent => 1}
177
+ def package_installed? packages, options = {}
178
+ options = default_options.merge options
179
+
154
180
  packages = [ packages ] if packages.is_a? String
155
181
 
156
182
  Dust.print_msg "checking if #{packages.join(' or ')} is installed", options
@@ -168,10 +194,16 @@ module Dust
168
194
  Dust.print_failed '', options
169
195
  end
170
196
 
171
- def install_package package, options={:quiet => false, :indent => 1, :env => ''}
172
- return true if package_installed? package, options
197
+ def install_package package, options = {}
198
+ options = default_options.merge options
199
+ options[:env] ||= ''
200
+
201
+ if package_installed? package, :quiet=>true
202
+ return Dust.print_ok "package #{package} already installed"
203
+ end
204
+
205
+ Dust.print_msg "installing #{package}", :indent => options[:indent] + 1
173
206
 
174
- Dust.print_msg "installing #{package}", {:quiet => options[:quiet], :indent => options[:indent] + 1}
175
207
  if uses_apt?
176
208
  exec "DEBIAN_FRONTEND=noninteractive aptitude install -y #{package}"
177
209
  elsif uses_emerge?
@@ -186,7 +218,9 @@ module Dust
186
218
  Dust.print_result package_installed? package, :quiet => true
187
219
  end
188
220
 
189
- def remove_package package, options={:quiet => false, :indent => 1}
221
+ def remove_package package, options = {}
222
+ options = default_options.merge options
223
+
190
224
  unless package_installed? package, :quiet => true
191
225
  return Dust.print_ok "package #{package} not installed", options
192
226
  end
@@ -203,7 +237,9 @@ module Dust
203
237
  end
204
238
  end
205
239
 
206
- def update_repos options={:quiet => false, :indent => 1}
240
+ def update_repos options = {}
241
+ options = default_options.merge options
242
+
207
243
  Dust.print_msg 'updating system repositories', options
208
244
 
209
245
  if uses_apt?
@@ -217,7 +253,9 @@ module Dust
217
253
  end
218
254
  end
219
255
 
220
- def system_update options={:quiet => false, :indent => 1}
256
+ def system_update options = {}
257
+ options = default_options.merge options
258
+
221
259
  Dust.print_msg 'installing system updates', options
222
260
 
223
261
  if uses_apt?
@@ -241,27 +279,35 @@ module Dust
241
279
 
242
280
  # determining the system packet manager has to be done without facter
243
281
  # because it's used to find out whether facter is installed / install facter
244
- def uses_apt? options={:quiet => true, :indent => 1}
282
+ def uses_apt? options = {}
283
+ options = default_options(:quiet => true).merge options
284
+
245
285
  Dust.print_msg 'determining whether node uses apt', options
246
286
  Dust.print_result exec('test -e /etc/debian_version')[:exit_code], options
247
287
  end
248
288
 
249
- def uses_rpm? options={:quiet => true, :indent => 1}
289
+ def uses_rpm? options = {}
290
+ options = default_options(:quiet => true).merge options
291
+
250
292
  Dust.print_msg 'determining whether node uses rpm', options
251
293
  Dust.print_result exec('test -e /etc/redhat-release')[:exit_code], options
252
294
  end
253
295
 
254
- def uses_emerge? options={:quiet => true, :indent => 1}
296
+ def uses_emerge? options = {}
297
+ options = default_options(:quiet => true).merge options
298
+
255
299
  Dust.print_msg 'determining whether node uses emerge', options
256
300
  Dust.print_result exec('test -e /etc/gentoo-release')[:exit_code], options
257
301
  end
258
302
 
259
- def is_os? os_list, options={:quiet => true, :indent => 1}
303
+ def is_os? os_list, options = {}
304
+ options = default_options(:quiet => true).merge options
305
+
260
306
  Dust.print_msg "checking if this machine runs #{os_list.join(' or ')}", options
261
- collect_facts options unless @attr['operatingsystem']
307
+ collect_facts options unless @node['operatingsystem']
262
308
 
263
309
  os_list.each do |os|
264
- if @attr['operatingsystem'].downcase == os.downcase
310
+ if @node['operatingsystem'].downcase == os.downcase
265
311
  return Dust.print_ok '', options
266
312
  end
267
313
  end
@@ -270,46 +316,66 @@ module Dust
270
316
  false
271
317
  end
272
318
 
273
- def is_debian? options={:quiet => true, :indent => 1}
319
+ def is_debian? options = {}
320
+ options = default_options(:quiet => true).merge options
321
+
274
322
  is_os? ['debian'], options
275
323
  end
276
324
 
277
- def is_ubuntu? options={:quiet => true, :indent => 1}
325
+ def is_ubuntu? options = {}
326
+ options = default_options(:quiet => true).merge options
327
+
278
328
  is_os? ['ubuntu'], options
279
329
  end
280
330
 
281
- def is_gentoo? options={:quiet => true, :indent => 1}
331
+ def is_gentoo? options = {}
332
+ options = default_options(:quiet => true).merge options
333
+
282
334
  is_os? ['gentoo'], options
283
335
  end
284
336
 
285
- def is_centos? options={:quiet => true, :indent => 1}
337
+ def is_centos? options = {}
338
+ options = default_options(:quiet => true).merge options
339
+
286
340
  is_os? ['centos'], options
287
341
  end
288
342
 
289
- def is_scientific? options={:quiet => true, :indent => 1}
343
+ def is_scientific? options = {}
344
+ options = default_options(:quiet => true).merge options
345
+
290
346
  is_os? ['scientific'], options
291
347
  end
292
348
 
293
- def is_fedora? options={:quiet => true, :indent => 1}
349
+ def is_fedora? options = {}
350
+ options = default_options(:quiet => true).merge options
351
+
294
352
  is_os? ['fedora'], options
295
353
  end
296
354
 
297
- def is_executable? file, options={:quiet => false, :indent => 1}
355
+ def is_executable? file, options = {}
356
+ options = default_options.merge options
357
+
298
358
  Dust.print_msg "checking if file #{file} exists and is executeable", options
299
359
  Dust.print_result exec("test -x $(which #{file})")[:exit_code], options
300
360
  end
301
361
 
302
- def file_exists? file, options={:quiet => false, :indent => 1}
362
+ def file_exists? file, options = {}
363
+ options = default_options.merge options
364
+
303
365
  Dust.print_msg "checking if file #{file} exists", options
304
366
  Dust.print_result exec("test -e #{file}")[:exit_code], options
305
367
  end
306
368
 
307
- def dir_exists? dir, options={:quiet => false, :indent => 1}
369
+ def dir_exists? dir, options = {}
370
+ options = default_options.merge options
371
+
308
372
  Dust.print_msg "checking if directory #{dir} exists", options
309
373
  Dust.print_result exec("test -d #{dir}")[:exit_code], options
310
374
  end
311
375
 
312
- def autostart_service service, options={:quiet => false, :indent => 1}
376
+ def autostart_service service, options = {}
377
+ options = default_options.merge options
378
+
313
379
  Dust.print_msg "autostart #{service} on boot", options
314
380
  if uses_rpm?
315
381
  Dust.print_result exec("chkconfig #{service} on")[:exit_code], options
@@ -320,27 +386,37 @@ module Dust
320
386
  end
321
387
  end
322
388
 
323
- def restart_service service, options={:quiet => false, :indent => 1}
389
+ def restart_service service, options = {}
390
+ options = default_options.merge options
391
+
324
392
  Dust.print_msg "restarting #{service}", options
325
393
  Dust.print_result exec("/etc/init.d/#{service} restart")[:exit_code], options
326
394
  end
327
395
 
328
- def reload_service service, options={:quiet => false, :indent => 1}
396
+ def reload_service service, options = {}
397
+ options = default_options.merge options
398
+
329
399
  Dust.print_msg "reloading #{service}", options
330
400
  Dust.print_result exec("/etc/init.d/#{service} reload")[:exit_code], options
331
401
  end
332
402
 
333
403
  # check whether a user exists on this node
334
- def user_exists? user, options={:quiet => false, :indent => 1}
404
+ def user_exists? user, options = {}
405
+ options = default_options.merge options
406
+
335
407
  Dust.print_msg "checking if user #{user} exists", options
336
408
  Dust.print_result exec("id #{user}")[:exit_code], options
337
409
  end
338
410
 
339
411
  # create a user
340
- def create_user user, options={:home => nil, :shell => nil, :quiet => false, :indent => 1}
412
+ def create_user user, options = {}
413
+ options = default_options.merge options
414
+ options[:home] ||= nil
415
+ options[:shell] ||= nil
416
+
341
417
  return true if user_exists? user, options
342
418
 
343
- Dust.print_msg "creating user #{user}", {:quiet => options[:quiet], :indent => options[:indent] + 1}
419
+ Dust.print_msg "creating user #{user}", :indent => options[:indent]
344
420
  cmd = "useradd #{user} -m"
345
421
  cmd += " -d #{options[:home]}" if options[:home]
346
422
  cmd += " -s #{options[:shell]}" if options[:shell]
@@ -348,7 +424,9 @@ module Dust
348
424
  end
349
425
 
350
426
  # collect additional system facts using puppets facter
351
- def collect_facts options={:quiet => false, :indent => 1}
427
+ def collect_facts options = {}
428
+ options = default_options.merge options
429
+
352
430
 
353
431
  # check if lsb-release (on apt systems) and facter are installed
354
432
  # and install them if not
@@ -362,23 +440,41 @@ module Dust
362
440
 
363
441
  Dust.print_msg "collecting additional system facts (using facter)", options
364
442
 
365
- # run facter with -y for yaml output, and merge results into @attr
443
+ # run facter with -y for yaml output, and merge results into @node
366
444
  ret = exec 'facter -y'
367
- @attr.merge! YAML.load ret[:stdout]
445
+ @node.merge! YAML.load ret[:stdout]
368
446
 
369
447
  Dust.print_result ret[:exit_code], options
370
448
  end
371
449
 
450
+ # if file is a regular file, copy it using scp
451
+ # if it's an file.erb exists, render template and push to server
452
+ def deploy_file file, destination, options = {}
453
+ options = default_options(:binding => binding).merge options
454
+
455
+ if File.exists? file
456
+ scp file, destination, options
457
+
458
+ elsif File.exists? "#{file}.erb"
459
+ template = ERB.new( File.read("#{file}.erb"), nil, '%<>')
460
+ write destination, template.result(options[:binding]), options
461
+
462
+ else
463
+ ::Dust.print_failed "'#{file}' was not found."
464
+ end
465
+ end
466
+
467
+
372
468
  private
373
469
 
374
470
  def method_missing method, *args, &block
375
- # make server attributes accessible via server.attribute
376
- if @attr[method.to_s]
377
- @attr[method.to_s]
471
+ # make server nodeibutes accessible via server.nodeibute
472
+ if @node[method.to_s]
473
+ @node[method.to_s]
378
474
 
379
- # and as server['attribute']
380
- elsif @attr[args.first]
381
- @attr[args.first]
475
+ # and as server['nodeibute']
476
+ elsif @node[args.first]
477
+ @node[args.first]
382
478
 
383
479
  # default to super
384
480
  else
@@ -1,3 +1,3 @@
1
1
  module Dust
2
- VERSION = "0.4.1"
2
+ VERSION = "0.4.2"
3
3
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 4
8
- - 1
9
- version: 0.4.1
8
+ - 2
9
+ version: 0.4.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - kris kechagia
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2012-01-15 00:00:00 +01:00
17
+ date: 2012-01-17 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -96,7 +96,6 @@ files:
96
96
  - changelog.md
97
97
  - dust.gemspec
98
98
  - lib/dust.rb
99
- - lib/dust/convert_size.rb
100
99
  - lib/dust/examples/nodes/_debian.yaml
101
100
  - lib/dust/examples/nodes/_default.yaml
102
101
  - lib/dust/examples/nodes/_newrelic.yaml
@@ -111,6 +110,7 @@ files:
111
110
  - lib/dust/examples/templates/basic_setup/.your-vimrc
112
111
  - lib/dust/examples/templates/duplicity/cronjob.erb
113
112
  - lib/dust/examples/templates/etc_hosts/hosts
113
+ - lib/dust/examples/templates/hash_check/weak_passwords
114
114
  - lib/dust/examples/templates/motd/motd.erb
115
115
  - lib/dust/examples/templates/nginx/nginx.conf
116
116
  - lib/dust/examples/templates/nginx/sites/othersite.erb
@@ -130,6 +130,7 @@ files:
130
130
  - lib/dust/recipes/debsecan.rb
131
131
  - lib/dust/recipes/duplicity.rb
132
132
  - lib/dust/recipes/etc_hosts.rb
133
+ - lib/dust/recipes/hash_check.rb
133
134
  - lib/dust/recipes/iptables.rb
134
135
  - lib/dust/recipes/locale.rb
135
136
  - lib/dust/recipes/memory_limit.rb
@@ -1,21 +0,0 @@
1
- module Dust
2
-
3
- # converts string to kilobytes (rounded)
4
- def self.convert_size s
5
- i, unit = s.split(' ')
6
-
7
- case unit.downcase
8
- when 'kb'
9
- return i.to_i
10
- when 'mb'
11
- return (i.to_f * 1024).to_i
12
- when 'gb'
13
- return (i.to_f * 1024 * 1024).to_i
14
- when 'tb'
15
- return (i.to_f * 1024 * 1024 * 1024).to_i
16
- else
17
- return false
18
- end
19
- end
20
-
21
- end