dust-deploy 0.4.4 → 0.4.5

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,16 @@
1
1
  Changelog
2
2
  =============
3
3
 
4
+ 0.4.5
5
+ ------------
6
+
7
+ - node.write and node.append now not using echo for writing files on the server anymore.
8
+ this solves problems with binary files and files including backticks (`)
9
+ - adds pacemaker recipe, for basic setup and configuration of corosync/pacemaker
10
+ - adds sudoers recipe for maintaining your sudoers rules
11
+ - postgres recipe now checks if zabbix is installed, and if so configures the node for monitoring
12
+
13
+
4
14
  0.4.4
5
15
  ------------
6
16
 
@@ -34,9 +34,9 @@ class Duplicity < Recipe
34
34
  # add hostkey to known_hosts
35
35
  if config['hostkey']
36
36
  ::Dust.print_msg 'checking if ssh key is in known_hosts'
37
- unless ::Dust.print_result @node.exec("grep -q '#{config['hostkey']}' ~/.ssh/known_hosts")[:exit_code] == 0
38
- @node.mkdir '~/.ssh', :indent => 2
39
- @node.append '~/.ssh/known_hosts', config['hostkey'], :indent => 2
37
+ unless ::Dust.print_result @node.exec("grep -q '#{config['hostkey']}' /root/.ssh/known_hosts")[:exit_code] == 0
38
+ @node.mkdir '/root/.ssh', :indent => 2
39
+ @node.append '/root/.ssh/known_hosts', config['hostkey'], :indent => 2
40
40
  end
41
41
  end
42
42
 
@@ -0,0 +1,35 @@
1
+ require 'base64'
2
+
3
+ class Pacemaker < Recipe
4
+
5
+ desc 'pacemaker:deploy', 'installs and configures corosync/pacemaker'
6
+ def deploy
7
+ # this recipe is only tested with ubuntu
8
+ return unless @node.uses_apt?
9
+ return unless @node.install_package 'pacemaker'
10
+
11
+ # return if no authkey is given
12
+ unless @config['authkey']
13
+ return ::Dust.print_failed 'no authkey given. generate it using "corosync-keygen" ' +
14
+ 'and convert it to base64 using "base64 -w0 /etc/corosync/authkey"'
15
+ end
16
+
17
+ @node.collect_facts
18
+
19
+ # set defaults
20
+ @config['interface'] ||= 'eth0'
21
+ @config['mcastaddr'] ||= '226.13.37.1'
22
+ @config['mcastport'] ||= 5405
23
+
24
+ # set bindnetaddr to the ip address of @config['interface']
25
+ # unless it is specified manually in node config
26
+ @config['bindnetaddr'] ||= @node["ipaddress_#{@config['interface']}"]
27
+
28
+ # decode base64 authkey
29
+ @node.write '/etc/corosync/authkey', Base64.decode64(@config['authkey'])
30
+ @node.deploy_file "#{@template_path}/corosync.conf", '/etc/corosync/corosync.conf', :binding => binding
31
+
32
+ # not restarting automatically, because it provokes switching of ha services
33
+ #@node.restart_service 'corosync' if @options.restart
34
+ end
35
+ end
@@ -2,7 +2,26 @@ class Postgres < Recipe
2
2
  desc 'postgres:deploy', 'installs and configures postgresql database'
3
3
  def deploy
4
4
  return ::Dust.print_failed 'no version specified' unless @config['version']
5
-
5
+ return ::Dust.print_failed 'os not supported' unless default_config
6
+
7
+ deploy_config
8
+ deploy_recovery
9
+ deploy_certificates
10
+ configure_sysctl
11
+
12
+ deploy_pacemaker_script if @node.package_installed? 'pacemaker'
13
+ configure_for_zabbix if zabbix_installed?
14
+
15
+ # reload/restart postgres if command line option is given
16
+ @node.restart_service @config['service-name'] if options.restart?
17
+ @node.reload_service @config['service-name'] if options.reload?
18
+ end
19
+
20
+
21
+ private
22
+
23
+ # set default variables and make sure postgres is installed
24
+ def default_config
6
25
  if @node.uses_emerge?
7
26
  return unless @node.package_installed? 'postgresql-server'
8
27
  @config['data-dir'] ||= "/var/lib/postgresql/#{@config['version']}/data"
@@ -18,10 +37,12 @@ class Postgres < Recipe
18
37
  @config['service-name'] ||= 'postgresql'
19
38
 
20
39
  else
21
- return 'os not supported'
40
+ return ::Dust.print_failed 'os not supported yet'
22
41
  end
42
+ end
23
43
 
24
-
44
+ # deploy standard postgres config
45
+ def deploy_config
25
46
  @node.deploy_file "#{@template_path}/postgresql.conf", "#{@config['conf-dir']}/postgresql.conf", :binding => binding
26
47
  @node.deploy_file "#{@template_path}/pg_hba.conf", "#{@config['conf-dir']}/pg_hba.conf", :binding => binding
27
48
  @node.deploy_file "#{@template_path}/pg_ident.conf", "#{@config['conf-dir']}/pg_ident.conf", :binding => binding
@@ -29,22 +50,20 @@ class Postgres < Recipe
29
50
  @node.chmod '644', "#{@config['conf-dir']}/postgresql.conf"
30
51
  @node.chmod '644', "#{@config['conf-dir']}/pg_hba.conf"
31
52
  @node.chmod '644', "#{@config['conf-dir']}/pg_ident.conf"
32
-
33
- # deploy pacemaker script
34
- if @node.package_installed? 'pacemaker'
35
- @node.deploy_file "#{@template_path}/pacemaker.sh", "#{@config['conf-dir']}/pacemaker.sh", :binding => binding
36
- @node.chmod '755', "#{@config['conf-dir']}/pacemaker.sh"
37
- end
38
-
39
- # copy recovery.conf to either recovery.conf or recovery.done
40
- # depending on which file already exists.
53
+ end
54
+
55
+ # copy recovery.conf to either recovery.conf or recovery.done
56
+ # depending on which file already exists.
57
+ def deploy_recovery
41
58
  if @node.file_exists? "#{@config['data-dir']}/recovery.conf", :quiet => true
42
59
  @node.deploy_file "#{@template_path}/recovery.conf", "#{@config['data-dir']}/recovery.conf", :binding => binding
43
60
  else
44
61
  @node.deploy_file "#{@template_path}/recovery.conf", "#{@config['data-dir']}/recovery.done", :binding => binding
45
62
  end
46
-
47
- # deploy certificates to data-dir
63
+ end
64
+
65
+ # deploy certificates to data-dir
66
+ def deploy_certificates
48
67
  @node.deploy_file "#{@template_path}/server.crt", "#{@config['data-dir']}/server.crt", :binding => binding
49
68
  @node.deploy_file "#{@template_path}/server.key", "#{@config['data-dir']}/server.key", :binding => binding
50
69
 
@@ -55,9 +74,11 @@ class Postgres < Recipe
55
74
  @node.mkdir @config['archive-dir']
56
75
  @node.chown @config['dbuser'], @config['archive-dir'] if @config['dbuser']
57
76
  @node.chmod 'u+Xrw,g-rwx,o-rwx', @config['archive-dir']
77
+ end
58
78
 
59
-
60
- # increase shm memory
79
+ # increase shm memory
80
+ def configure_sysctl
81
+
61
82
  if @node.uses_apt?
62
83
  ::Dust.print_msg "setting postgres sysctl keys\n"
63
84
  @node.collect_facts :quiet => true
@@ -83,11 +104,56 @@ class Postgres < Recipe
83
104
 
84
105
  @node.write "/etc/sysctl.d/30-postgresql-shm.conf", file
85
106
  end
86
-
87
- # reload/restart postgres if command line option is given
88
- @node.restart_service @config['service-name'] if options.restart?
89
- @node.reload_service @config['service-name'] if options.reload?
90
107
  end
91
108
 
109
+ def deploy_pacemaker_script
110
+ @node.deploy_file "#{@template_path}/pacemaker.sh", "#{@config['conf-dir']}/pacemaker.sh", :binding => binding
111
+ @node.chmod '755', "#{@config['conf-dir']}/pacemaker.sh"
112
+ end
113
+
114
+ # below this line is unfinished code, not in use yet
115
+ def zabbix_installed?
116
+ if @node.uses_emerge?
117
+ return @node.package_installed? 'zabbix', :quiet => true
118
+ else
119
+ return @node.package_installed? 'zabbix-agent', :quiet => true
120
+ end
121
+ end
122
+
123
+ # adds zabbix user to postgres group
124
+ # creates zabbix user in postgres and grant access to postgres database
125
+ def configure_for_zabbix
126
+ ::Dust.print_msg "configuring postgres for zabbix monitoring\n"
127
+ ::Dust.print_msg 'adding zabbix user to postgres group', :indent => 2
128
+ ::Dust.print_result @node.exec('usermod -a -G postgres zabbix')[:exit_code]
129
+
130
+ if is_master? :indent => 2
131
+ ::Dust.print_msg 'checking if zabbix user exists in postgres', :indent => 3
132
+ ret = ::Dust.print_result @node.exec('psql -U postgres -c ' +
133
+ ' "SELECT usename FROM pg_user WHERE usename = \'zabbix\'"' +
134
+ ' postgres |grep -q zabbix')[:exit_code]
135
+
136
+ # if user was not found, create him
137
+ unless ret
138
+ ::Dust.print_msg 'create zabbix user in postgres', :indent => 4
139
+ ::Dust.print_result @node.exec('createuser -U postgres zabbix -RSD')[:exit_code]
140
+ end
141
+
142
+ ::Dust.print_msg 'GRANT zabbix user access to postgres database', :indent => 3
143
+ ::Dust.print_result( @node.exec('psql -U postgres -c "GRANT SELECT ON pg_stat_database TO zabbix" postgres')[:exit_code] )
144
+ end
145
+ end
146
+
147
+ # checks if this server is a postgres master
148
+ def is_master? options = {}
149
+ ::Dust.print_msg 'checking if this host is the postgres master: ', options
150
+ if @node.file_exists? "#{@config['data-dir']}/recovery.done", :quiet => true
151
+ ::Dust.print_ok 'yes', :indent => 0
152
+ return true
153
+ else
154
+ ::Dust.print_ok 'no', :indent => 0
155
+ return false
156
+ end
157
+ end
92
158
  end
93
159
 
@@ -0,0 +1,46 @@
1
+ class Sudoers < Recipe
2
+ desc 'sudoers:deploy', 'installs email aliases'
3
+ def deploy
4
+ return unless @node.install_package 'sudo'
5
+
6
+ remove_rules
7
+
8
+ @config.each do |name, rule|
9
+ ::Dust.print_msg "deploying sudo rules '#{name}'\n"
10
+
11
+ # rulename: 'myrule'
12
+ if rule.is_a? String
13
+ file = "#{rule}\n"
14
+
15
+ # rulename: { user: [ user1, user2 ], command: [ cmd1, cmd2 ] }
16
+ else
17
+ unless rule['user'] and rule['command']
18
+ ::Dust.print_failed 'user or command missing', :indent => 2
19
+ next
20
+ end
21
+
22
+ file = ''
23
+ rule['user'].each do |u|
24
+ rule['command'].each { |c| file.concat "#{u} #{c}\n" }
25
+ end
26
+ end
27
+
28
+ deploy_rule name, file
29
+ end
30
+
31
+ end
32
+
33
+
34
+ private
35
+
36
+ def remove_rules
37
+ @node.rm '/etc/sudoers.d/*'
38
+ end
39
+
40
+ def deploy_rule name, file
41
+ @node.write "/etc/sudoers.d/#{name}", file, :indent => 2
42
+ @node.chmod '0440', "/etc/sudoers.d/#{name}", :indent => 2
43
+ @node.chown 'root:root', "/etc/sudoers.d/#{name}", :indent => 2
44
+ end
45
+ end
46
+
@@ -38,38 +38,4 @@ class ZabbixAgent < Recipe
38
38
 
39
39
  true
40
40
  end
41
-
42
-
43
- # below this line is unfinished code, not in use yet
44
-
45
- # TODO (not yet finished)
46
- desc 'zabbix_agent:postgres', 'configure postgres database for zabbix monitoring'
47
- def postgres
48
- next unless @node.uses_emerge? :quiet=>false
49
- next unless @node.package_installed?('postgresql-@node')
50
-
51
- ::Dust.print_msg 'add zabbix system user to postgres group'
52
- ::Dust.print_result( @node.exec('usermod -a -G postgres zabbix')[:exit_code] )
53
-
54
- ::Dust.print_msg 'checking if zabbix user exists in postgres'
55
- ret = ::Dust.print_result( @node.exec('psql -U postgres -c ' +
56
- ' "SELECT usename FROM pg_user WHERE usename = \'zabbix\'"' +
57
- ' postgres |grep -q zabbix')[:exit_code] )
58
-
59
- # if user was not found, create him
60
- unless ret
61
- ::Dust.print_msg 'create zabbix user in postgres', :indent => 2
62
- ::Dust.print_result( @node.exec('createuser -U postgres zabbix -RSD')[:exit_code] )
63
- end
64
-
65
- # TODO: only GRANT is this is a master
66
- ::Dust.print_msg 'GRANT zabbix user access to postgres database'
67
- ::Dust.print_result( @node.exec('psql -U postgres -c "GRANT SELECT ON pg_stat_database TO zabbix" postgres')[:exit_code] )
68
-
69
- # reload postgresql
70
- @node.reload_service('postgresql-9.0')
71
-
72
- @node.disconnect
73
- puts
74
- end
75
41
  end
@@ -3,7 +3,8 @@ require 'net/ssh'
3
3
  require 'net/scp'
4
4
  require 'net/ssh/proxy/socks5'
5
5
  require 'erb'
6
-
6
+ require 'tempfile'
7
+
7
8
  module Dust
8
9
  class Server
9
10
  attr_reader :ssh
@@ -70,37 +71,34 @@ module Dust
70
71
  end
71
72
 
72
73
 
73
- def write target, text, options = {}
74
+ def write destination, content, options = {}
74
75
  options = default_options.merge options
75
-
76
- Dust.print_msg "deploying #{File.basename target}", options
77
-
78
- # escape $ signs and \ at the end of line
79
- text.gsub! '$','\$'
80
- text.gsub! /\\$/, '\\\\\\'
81
-
82
- # note: ` (backticks) somehow cannot be escaped.. don't use them
83
- # in bash, use $(cmd) instead of `cmd` as a workaround
84
- if exec("cat << EOF > #{target}\n#{text}\nEOF")[:exit_code] != 0
85
- Dust.print_failed '', options
86
- return false
87
- end
88
-
89
- Dust.print_ok '', options
90
- restorecon target, options # restore SELinux labels
76
+
77
+ Dust.print_msg "deploying #{File.basename destination}", options
78
+
79
+ f = Tempfile.new 'dust-write'
80
+ f.print content
81
+ f.close
82
+
83
+ Dust.print_result scp(f.path, destination, :quiet => true), options
84
+ f.unlink
91
85
  end
92
86
 
93
- def append target, text, options = {}
87
+ def append destination, newcontent, options = {}
94
88
  options = default_options.merge options
95
-
96
- Dust.print_msg "appending to #{File.basename target}", options
97
- Dust.print_result exec("cat << EOF >> #{target}\n#{text}\nEOF")[:exit_code], options
89
+
90
+ Dust.print_msg "appending to #{File.basename destination}", options
91
+
92
+ content = exec("cat #{destination}")[:stdout]
93
+ content.concat newcontent
94
+
95
+ Dust.print_result write(destination, content, :quiet => true), options
98
96
  end
99
97
 
100
98
  def scp source, destination, options = {}
101
99
  options = default_options.merge options
102
100
 
103
- Dust.print_msg "deploying #{File.basename(source)}", options
101
+ Dust.print_msg "deploying #{File.basename source}", options
104
102
  @ssh.scp.upload! source, destination
105
103
  Dust.print_ok '', options
106
104
  restorecon destination, options # restore SELinux labels
@@ -109,7 +107,7 @@ module Dust
109
107
  def symlink source, destination, options = {}
110
108
  options = default_options.merge options
111
109
 
112
- Dust.print_msg "symlinking #{File.basename(source)} to '#{destination}'", options
110
+ Dust.print_msg "symlinking #{File.basename source} to '#{destination}'", options
113
111
  Dust.print_result exec("ln -s #{source} #{destination}")[:exit_code], options
114
112
  restorecon destination, options # restore SELinux labels
115
113
  end
@@ -117,14 +115,14 @@ module Dust
117
115
  def chmod mode, file, options = {}
118
116
  options = default_options.merge options
119
117
 
120
- Dust.print_msg "setting mode of #{File.basename(file)} to #{mode}", options
118
+ Dust.print_msg "setting mode of #{File.basename file} to #{mode}", options
121
119
  Dust.print_result exec("chmod -R #{mode} #{file}")[:exit_code], options
122
120
  end
123
121
 
124
122
  def chown user, file, options = {}
125
123
  options = default_options.merge options
126
124
 
127
- Dust.print_msg "setting owner of #{File.basename(file)} to #{user}", options
125
+ Dust.print_msg "setting owner of #{File.basename file} to #{user}", options
128
126
  Dust.print_result exec("chown -R #{user} #{file}")[:exit_code], options
129
127
  end
130
128
 
@@ -150,7 +148,6 @@ module Dust
150
148
  def restorecon path, options = {}
151
149
  options = default_options.merge options
152
150
 
153
-
154
151
  # if restorecon is not installed, just return true
155
152
  ret = exec 'which restorecon'
156
153
  return true unless ret[:exit_code] == 0
@@ -1,3 +1,3 @@
1
1
  module Dust
2
- VERSION = "0.4.4"
2
+ VERSION = "0.4.5"
3
3
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 4
8
- - 4
9
- version: 0.4.4
8
+ - 5
9
+ version: 0.4.5
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-20 00:00:00 +01:00
17
+ date: 2012-01-23 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -138,6 +138,7 @@ files:
138
138
  - lib/dust/recipes/mysql.rb
139
139
  - lib/dust/recipes/newrelic.rb
140
140
  - lib/dust/recipes/nginx.rb
141
+ - lib/dust/recipes/pacemaker.rb
141
142
  - lib/dust/recipes/packages.rb
142
143
  - lib/dust/recipes/postgres.rb
143
144
  - lib/dust/recipes/rc_local.rb
@@ -146,6 +147,7 @@ files:
146
147
  - lib/dust/recipes/resolv_conf.rb
147
148
  - lib/dust/recipes/ssh_authorized_keys.rb
148
149
  - lib/dust/recipes/sshd.rb
150
+ - lib/dust/recipes/sudoers.rb
149
151
  - lib/dust/recipes/unattended_upgrades.rb
150
152
  - lib/dust/recipes/zabbix_agent.rb
151
153
  - lib/dust/server.rb