dust-deploy 0.1.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.
@@ -0,0 +1,17 @@
1
+ class Locale < Thor
2
+ desc 'locale:deploy', 'configures system locale'
3
+ def deploy node, locale, options
4
+ if node.uses_apt? true
5
+ ::Dust.print_msg "setting locale to '#{locale}'"
6
+ node.write '/etc/default/locale', "LANGUAGE=#{locale}\nLANG=#{locale}\nLC_ALL=#{locale}\nLC_CTYPE=#{locale}\n", true
7
+ ::Dust.print_ok
8
+ elsif node.uses_rpm? true
9
+ ::Dust.print_msg "setting locale to '#{locale}'"
10
+ node.write '/etc/sysconfig/i18n', "LANG=\"#{locale}\"\nLC_ALL=\"#{locale}\"\nSYSFONT=\"latarcyrheb-sun16\"\n", true
11
+ ::Dust.print_ok
12
+ else
13
+ ::Dust.print_failed 'os not supported'
14
+ end
15
+ end
16
+ end
17
+
@@ -0,0 +1,23 @@
1
+ class MemoryLimit < Thor
2
+ desc 'memory_limit:deploy', 'sets up system wide memory limit per process'
3
+ def deploy node, ingredients, options
4
+ template_path = "./templates/#{ File.basename(__FILE__).chomp( File.extname(__FILE__) ) }"
5
+
6
+ node.collect_facts
7
+
8
+ # get system memory (in kb)
9
+ system_mem = ::Dust.convert_size node['memorysize']
10
+
11
+ # don't allow a process to use more than 90% of the system memory
12
+ max_mem = (system_mem * 0.9).to_i
13
+
14
+ # if the remaining 10% are more than 512mb, use system_mem - 512mb as max instead
15
+ threshold = ::Dust.convert_size '512 MB'
16
+ max_mem = system_mem - threshold if max_mem > threshold
17
+
18
+ ::Dust.print_msg "setting max memory for a process to #{max_mem} kb"
19
+ node.write '/etc/security/limits.d/00-memory-limit', "* hard as #{max_mem}", true
20
+ ::Dust.print_ok
21
+
22
+ end
23
+ end
@@ -0,0 +1,12 @@
1
+ require 'erb'
2
+
3
+ class Motd < Thor
4
+ desc 'motd:deploy', 'creates message of the day'
5
+ def deploy node, ingredients, options
6
+ template_path = "./templates/#{ File.basename(__FILE__).chomp( File.extname(__FILE__) ) }"
7
+
8
+ # configure node using erb template
9
+ template = ERB.new File.read("#{template_path}/motd.erb"), nil, '%<>'
10
+ node.write '/etc/motd', template.result(binding)
11
+ end
12
+ end
@@ -0,0 +1,49 @@
1
+ require 'erb'
2
+
3
+ class Mysql < Thor
4
+ desc 'mysql:deploy', 'installs and configures mysql database'
5
+ def deploy node, config, options
6
+ template_path = "./templates/#{ File.basename(__FILE__).chomp( File.extname(__FILE__) ) }"
7
+
8
+ return unless node.uses_apt?
9
+ node.install_package 'mysql-server'
10
+
11
+ ::Dust.print_msg "configuring mysql\n"
12
+
13
+ # defaults
14
+ config['bind_address'] ||= '127.0.0.1'
15
+ config['port'] ||= 3306
16
+
17
+ ::Dust.print_ok "listen on #{config['bind_address']}:#{config['port']}", 2
18
+
19
+ config['innodb_file_per_table'] ||= 1
20
+ config['innodb_thread_concurrency'] ||= 0
21
+ config['innodb_flush_log_at_trx_commit'] ||= 1
22
+
23
+ # allocate 70% of the available ram to mysql
24
+ # but leave max 1gb to system
25
+ unless config['innodb_buffer_pool_size']
26
+ ::Dust.print_msg 'autoconfiguring innodb buffer size', 2
27
+ node.collect_facts true
28
+
29
+ # get system memory (in kb)
30
+ system_mem = ::Dust.convert_size node['memorysize']
31
+
32
+ # allocate 70% of the available ram to mysql
33
+ buffer_pool = (system_mem * 0.70).to_i / 1024
34
+
35
+ config['innodb_buffer_pool_size'] = "#{buffer_pool}M"
36
+ ::Dust.print_ok
37
+ end
38
+
39
+ ::Dust.print_ok "setting innodb buffer pool to '#{config['innodb_buffer_pool_size']}'", 2
40
+
41
+ template = ERB.new( File.read("#{template_path}/my.cnf.erb"), nil, '%<>')
42
+ node.write '/etc/mysql/my.cnf', template.result(binding)
43
+ node.chmod '644', '/etc/mysql/my.cnf'
44
+
45
+ node.service_restart 'mysql-server' if options.restart?
46
+ node.service_reload 'mysql-server' if options.reload?
47
+ end
48
+ end
49
+
@@ -0,0 +1,53 @@
1
+ require 'erb'
2
+
3
+ class Nginx < Thor
4
+ desc 'nginx:deploy', 'installs and configures nginx web server'
5
+ def deploy node, sites, options
6
+ template_path = "./templates/#{ File.basename(__FILE__).chomp( File.extname(__FILE__) ) }"
7
+
8
+ # abort if nginx cannot be installed
9
+ return unless node.install_package('nginx')
10
+
11
+ node.scp("#{template_path}/nginx.conf", '/etc/nginx/nginx.conf')
12
+
13
+ # remove old sites that may be present
14
+ ::Dust.print_msg 'deleting old sites in /etc/nginx/sites-*'
15
+ node.rm '/etc/nginx/sites-*/*', true
16
+ ::Dust.print_ok
17
+
18
+ sites.each do |state, site|
19
+ file = "#{template_path}/sites/#{site}"
20
+
21
+ # if this site is just a regular file, copy it to sites-available
22
+ if File.exists? file
23
+ node.scp file, "/etc/nginx/sites-available/#{site}"
24
+
25
+ # if this site is an erb template, render it and deploy
26
+ elsif File.exists? "#{file}.erb"
27
+ template = ERB.new( File.read("#{file}.erb"), nil, '%<>')
28
+ node.write "/etc/nginx/sites-available/#{site}", template.result(binding)
29
+
30
+ # skip to next site if template wasn't found
31
+ else
32
+ ::Dust.print_failed "couldn't find template for #{site}", 2
33
+ next
34
+ end
35
+
36
+ # symlink to sites-enabled if this is listed as an enabled site
37
+ if state == 'sites-enabled'
38
+ ::Dust.print_msg "enabling #{site}", 2
39
+ ::Dust.print_result( node.exec("cd /etc/nginx/sites-enabled && ln -s ../sites-available/#{site} #{site}")[:exit_code] )
40
+ end
41
+ end
42
+
43
+ # check configuration and restart nginx
44
+ ::Dust.print_msg 'checking nginx configuration'
45
+ if node.exec('/etc/init.d/nginx configtest')[:exit_code] == 0
46
+ ::Dust.print_ok
47
+ node.restart_service('nginx') if options.restart?
48
+ else
49
+ ::Dust.print_failed
50
+ end
51
+ end
52
+ end
53
+
@@ -0,0 +1,9 @@
1
+ class Packages < Thor
2
+ desc 'packages:deploy', 'installs packages'
3
+ def deploy node, packages, options
4
+ packages.each do |package|
5
+ node.install_package package
6
+ end
7
+ end
8
+ end
9
+
@@ -0,0 +1,119 @@
1
+ require 'erb'
2
+
3
+ class Postgres < Thor
4
+ desc 'postgres:deploy', 'installs and configures postgresql database'
5
+ def deploy node, config, options
6
+ template_path = "./templates/#{ File.basename(__FILE__).chomp( File.extname(__FILE__) ) }"
7
+
8
+ return ::Dust.print_failed 'no version specified' unless config['version']
9
+
10
+ if node.uses_emerge? true
11
+ return unless node.package_installed? 'postgresql-server'
12
+ config['data-dir'] ||= "/var/lib/postgresql/#{config['version']}/data"
13
+ config['conf-dir'] ||= "/etc/postgresql-#{config['version']}"
14
+ config['archive-dir'] ||= "/var/lib/postgresql/#{config['version']}/archive"
15
+ config['service-name'] ||= "postgresql-#{config['version']}"
16
+ elsif node.uses_apt? true
17
+ return unless node.package_installed? "postgresql-#{config['version']}"
18
+ config['data-dir'] ||= "/var/lib/postgresql/#{config['version']}/#{config['cluster']}"
19
+ config['conf-dir'] ||= "/etc/postgresql/#{config['version']}/#{config['cluster']}"
20
+ config['archive-dir'] ||= "/var/lib/postgresql/#{config['version']}/#{config['cluster']}-archive"
21
+ config['service-name'] ||= 'postgresql'
22
+ else
23
+ return 'os not supported'
24
+ end
25
+
26
+
27
+ deploy_file 'postgresql.conf', "#{config['conf-dir']}/postgresql.conf", binding
28
+ deploy_file 'pg_hba.conf', "#{config['conf-dir']}/pg_hba.conf", binding
29
+ deploy_file 'pg_ident.conf', "#{config['conf-dir']}/pg_ident.conf", binding
30
+
31
+ node.chmod '644', "#{config['conf-dir']}/postgresql.conf"
32
+ node.chmod '644', "#{config['conf-dir']}/pg_hba.conf"
33
+ node.chmod '644', "#{config['conf-dir']}/pg_ident.conf"
34
+
35
+ # deploy pacemaker script
36
+ if node.package_installed? 'pacemaker'
37
+ deploy_file 'pacemaker.sh', "#{config['conf-dir']}/pacemaker.sh", binding
38
+ node.chmod '755', "#{config['conf-dir']}/pacemaker.sh"
39
+ end
40
+
41
+ # copy recovery.conf to either recovery.conf or recovery.done
42
+ # depending on which file already exists.
43
+ if node.file_exists? "#{config['data-dir']}/recovery.conf", true
44
+ deploy_file 'recovery.conf', "#{config['data-dir']}/recovery.conf", binding
45
+ else
46
+ deploy_file 'recovery.conf', "#{config['data-dir']}/recovery.done", binding
47
+ end
48
+
49
+ # deploy certificates to data-dir
50
+ deploy_file 'server.crt', "#{config['data-dir']}/server.crt", binding
51
+ deploy_file 'server.key', "#{config['data-dir']}/server.key", binding
52
+
53
+ node.chown config['dbuser'], config['data-dir'] if config['dbuser']
54
+ node.chmod 'u+Xrw,g-rwx,o-rwx', config['data-dir']
55
+
56
+ # create archive dir
57
+ node.mkdir config['archive-dir']
58
+ node.chown config['dbuser'], config['archive-dir'] if config['dbuser']
59
+ node.chmod 'u+Xrw,g-rwx,o-rwx', config['archive-dir']
60
+
61
+
62
+ # increase shm memory
63
+ if node.uses_apt? true
64
+ ::Dust.print_msg "setting postgres sysctl keys\n"
65
+ node.collect_facts true
66
+
67
+ # use half of system memory for shmmax
68
+ shmmax = ::Dust.convert_size(node['memorysize']) * 1024 / 2
69
+ shmall = shmmax / 4096 # shmmax/pagesize (pagesize = 4096)
70
+
71
+ ::Dust.print_msg "setting shmmax to: #{shmmax}", 2
72
+ ::Dust.print_result node.exec("sysctl -w kernel.shmmax=#{shmmax}")[:exit_code]
73
+ ::Dust.print_msg "setting shmall to: #{shmall}", 2
74
+ ::Dust.print_result node.exec("sysctl -w kernel.shmall=#{shmall}")[:exit_code]
75
+ ::Dust.print_msg 'setting overcommit memory to 2', 2
76
+ ::Dust.print_result node.exec('sysctl -w vm.overcommit_memory=2')[:exit_code]
77
+ ::Dust.print_msg 'setting swappiness to 0', 2
78
+ ::Dust.print_result node.exec('sysctl -w vm.swappiness=0')[:exit_code]
79
+
80
+ file = ''
81
+ file += "kernel.shmmax=#{shmmax}\n"
82
+ file += "kernel.shmall=#{shmall}\n"
83
+ file += "vm.overcommit_memory=2\n" # don't allocate memory that's not there
84
+ file += "vm.swappiness=0\n" # rather shrink cache then use swap as filesystem cache
85
+
86
+ node.write "/etc/sysctl.d/30-postgresql-shm.conf", file
87
+ end
88
+
89
+ # reload/restart postgres if command line option is given
90
+ node.restart_service config['service-name'] if options.restart?
91
+ node.reload_service config['service-name'] if options.reload?
92
+ end
93
+
94
+ private
95
+ def deploy_file file, target, recipe_binding
96
+ template_path = "./templates/#{ File.basename(__FILE__).chomp( File.extname(__FILE__) ) }"
97
+
98
+ # get node and config from binding
99
+ node = eval 'node', recipe_binding
100
+ config = eval 'config', recipe_binding
101
+
102
+ # if file is just a regular file, copy it to sites-available
103
+ if File.exists? "#{template_path}/#{file}"
104
+ node.scp "#{template_path}/#{file}", target
105
+
106
+ # if file is an erb template, render it and deploy
107
+ elsif File.exists? "#{template_path}/#{file}.erb"
108
+ ::Dust.print_msg "adjusting and deploying #{file}"
109
+ template = ERB.new( File.read("#{template_path}/#{file}.erb"), nil, '%<>')
110
+ ::Dust.print_result node.write(target, template.result(binding), true)
111
+
112
+ # file was not found, return
113
+ else
114
+ return ::Dust.print_failed "file '#{template_path}/#{file}' not found."
115
+ end
116
+ end
117
+
118
+ end
119
+
@@ -0,0 +1,24 @@
1
+ class RcLocal < Thor
2
+ desc 'rc_local:deploy', 'configures custom startup script'
3
+ def deploy node, config, options
4
+
5
+ if node.uses_apt? true
6
+ ::Dust.print_msg "configuring custom startup script\n"
7
+
8
+ rc = ''
9
+ config.each do |cmd|
10
+ ::Dust.print_msg "adding command: #{cmd}", 2
11
+ rc += "#{cmd}\n"
12
+ ::Dust.print_ok
13
+ end
14
+ rc += "\nexit 0\n"
15
+
16
+ node.write '/etc/rc.local', rc
17
+ node.chown 'root:root', '/etc/rc.local'
18
+ node.chmod '755', '/etc/rc.local'
19
+ else
20
+ ::Dust.print_failed 'os not supported'
21
+ end
22
+ end
23
+ end
24
+
@@ -0,0 +1,88 @@
1
+ class Repositories < Thor
2
+ desc 'repositories:deploy', 'configures package management repositories (aptitude, yum)'
3
+ def deploy node, repos, options
4
+
5
+ if node.uses_apt?
6
+ :: Dust.print_msg 'deleting old repositories'
7
+ node.rm '/etc/apt/sources.list.d/*.list', true
8
+ ::Dust.print_ok
9
+
10
+ repos.each do |name, repo|
11
+ puts
12
+
13
+ # if repo is present but not a hash use defaults
14
+ repo = {} unless repo.class == Hash
15
+
16
+ # setting defaults
17
+ repo['url'] ||= 'http://ftp.debian.org/debian/' if node.is_debian? true
18
+ repo['url'] ||= 'http://archive.ubuntu.com/ubuntu/' if node.is_ubuntu? true
19
+
20
+ repo['release'] ||= node['lsbdistcodename']
21
+ repo['components'] ||= 'main'
22
+
23
+ # ||= doesn't work for booleans
24
+ repo['source'] = repo['source'].nil? ? true : repo['source']
25
+ repo['binary'] = repo['binary'].nil? ? true : repo['binary']
26
+
27
+ # the default repository in /etc/apt/sources.list (debian)
28
+ if name == 'default'
29
+ ::Dust.print_msg 'deploying default repository'
30
+
31
+ sources = ''
32
+ sources += "deb #{repo['url']} #{repo['release']} #{repo['components']}\n" +
33
+ "deb-src #{repo['url']} #{repo['release']} #{repo['components']}\n\n"
34
+
35
+ # security
36
+ if node.is_debian? true
37
+ sources += "deb http://security.debian.org/ #{repo['release']}/updates #{repo['components']}\n" +
38
+ "deb-src http://security.debian.org/ #{repo['release']}/updates #{repo['components']}\n\n"
39
+ elsif node.is_ubuntu? true
40
+ sources += "deb http://security.ubuntu.com/ubuntu/ #{repo['release']}-security #{repo['components']}\n" +
41
+ "deb-src http://security.ubuntu.com/ubuntu/ #{repo['release']}-security #{repo['components']}\n\n"
42
+ end
43
+
44
+ # updates
45
+ sources += "deb #{repo['url']} #{repo['release']}-updates #{repo['components']}\n" +
46
+ "deb-src #{repo['url']} #{repo['release']}-updates #{repo['components']}\n\n"
47
+
48
+ # proposed
49
+ if node.is_ubuntu? true
50
+ sources += "deb #{repo['url']} #{repo['release']}-proposed #{repo['components']}\n" +
51
+ "deb-src #{repo['url']} #{repo['release']}-proposed #{repo['components']}\n\n"
52
+ end
53
+
54
+ # backports is enabled per default in ubuntu oneiric
55
+ if node.is_ubuntu? true
56
+ sources += "deb #{repo['url']} #{repo['release']}-backports #{repo['components']}\n" +
57
+ "deb-src #{repo['url']} #{repo['release']}-backports #{repo['components']}\n\n"
58
+ end
59
+
60
+ ::Dust.print_result node.write('/etc/apt/sources.list', sources, true)
61
+ next
62
+
63
+ else
64
+ # add url to sources.list
65
+ sources = ''
66
+ sources += "deb #{repo['url']} #{repo['release']} #{repo['components']}\n" if repo['binary']
67
+ sources += "deb-src #{repo['url']} #{repo['release']} #{repo['components']}\n" if repo['source']
68
+
69
+ ::Dust.print_msg "adding repository '#{name}' to sources"
70
+ ::Dust.print_result node.write("/etc/apt/sources.list.d/#{name}.list", sources, true)
71
+
72
+ # add the repository key
73
+ if repo['key']
74
+ ::Dust.print_msg "adding #{name} repository key"
75
+ ::Dust.print_result node.exec("wget -O- '#{repo['key']}' | apt-key add -")[:exit_code]
76
+ end
77
+ end
78
+ end
79
+
80
+ elsif node.uses_rpm?
81
+ ::Dust.print_failed 'rpm not yet supported'
82
+
83
+ else
84
+ ::Dust.print_failed 'os not supported'
85
+ end
86
+ end
87
+ end
88
+
@@ -0,0 +1,42 @@
1
+ class ResolvConf < Thor
2
+ desc 'resolv_conf:deploy', 'configures /etc/resolv.conf'
3
+ def deploy node, config, options
4
+ ::Dust.print_msg "configuring resolv.conf\n"
5
+
6
+ # if config is just true, create empty hash and use defaults
7
+ config = {} unless config.class == Hash
8
+
9
+ # setting default config variables (unless already set)
10
+ config['nameservers'] ||= [ '208.67.222.222', '208.67.220.220' ] # opendns
11
+
12
+ config_file = ''
13
+
14
+ # configures whether daily reports are sent
15
+ if config['search']
16
+ ::Dust.print_msg "adding search #{config['search']}", 2
17
+ config_file += "search #{config['search']}\n"
18
+ ::Dust.print_ok
19
+ end
20
+
21
+ if config['domain']
22
+ ::Dust.print_msg "adding domain #{config['domain']}", 2
23
+ config_file += "domain #{config['domain']}\n"
24
+ ::Dust.print_ok
25
+ end
26
+
27
+ if config['options']
28
+ ::Dust.print_msg "adding options #{config['options']}", 2
29
+ config_file += "options #{config['options']}\n"
30
+ ::Dust.print_ok
31
+ end
32
+
33
+ config['nameservers'].each do |nameserver|
34
+ ::Dust.print_msg "adding nameserver #{nameserver}", 2
35
+ config_file += "nameserver #{nameserver}\n"
36
+ ::Dust.print_ok
37
+ end
38
+
39
+ node.write '/etc/resolv.conf', config_file
40
+ end
41
+ end
42
+