danarchy_deploy 0.1.2 → 0.2.1

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.
Files changed (39) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/Gemfile.lock +9 -20
  4. data/README.md +10 -9
  5. data/Rakefile +0 -4
  6. data/bin/danarchy_deploy +24 -10
  7. data/danarchy_deploy.gemspec +4 -3
  8. data/lib/danarchy_deploy.rb +186 -55
  9. data/lib/danarchy_deploy/applicator.rb +39 -0
  10. data/lib/danarchy_deploy/applicator/nginx.rb +86 -0
  11. data/lib/danarchy_deploy/applicator/phpfpm.rb +84 -0
  12. data/lib/danarchy_deploy/applicator/redmine.rb +40 -0
  13. data/lib/danarchy_deploy/applicator/ssl.rb +14 -0
  14. data/lib/danarchy_deploy/applicator/wordpress.rb +146 -0
  15. data/lib/danarchy_deploy/applicator/wordpress/wpcli.rb +67 -0
  16. data/lib/danarchy_deploy/applicator/wordpress/wpcli_install.sh +36 -0
  17. data/lib/danarchy_deploy/applicator/wordpress/wpconfig.rb +49 -0
  18. data/lib/danarchy_deploy/archiver.rb +9 -7
  19. data/lib/danarchy_deploy/archiver/svn.rb +17 -0
  20. data/lib/danarchy_deploy/hash_deep_merge.rb +9 -0
  21. data/lib/danarchy_deploy/helpers.rb +42 -10
  22. data/lib/danarchy_deploy/installer.rb +2 -2
  23. data/lib/danarchy_deploy/services.rb +12 -25
  24. data/lib/danarchy_deploy/services/init.rb +52 -0
  25. data/lib/danarchy_deploy/services/init/openrc.rb +72 -0
  26. data/lib/danarchy_deploy/services/init/systemd.rb +69 -0
  27. data/lib/danarchy_deploy/services/mongodb.rb +162 -0
  28. data/lib/danarchy_deploy/services/mysql.rb +58 -0
  29. data/lib/danarchy_deploy/services/mysql/new_server.rb +72 -0
  30. data/lib/danarchy_deploy/services/mysql/privileges.rb +35 -0
  31. data/lib/danarchy_deploy/system.rb +86 -0
  32. data/lib/danarchy_deploy/system/centos.rb +17 -0
  33. data/lib/danarchy_deploy/system/debian.rb +61 -0
  34. data/lib/danarchy_deploy/system/gentoo.rb +66 -0
  35. data/lib/danarchy_deploy/system/opensuse.rb +22 -0
  36. data/lib/danarchy_deploy/templater.rb +53 -13
  37. data/lib/danarchy_deploy/users.rb +29 -19
  38. data/lib/danarchy_deploy/version.rb +1 -1
  39. metadata +34 -12
@@ -0,0 +1,162 @@
1
+ require 'mongo'
2
+
3
+ module DanarchyDeploy
4
+ module Services
5
+ class MongoDB
6
+ def self.new(os, mongodb, options)
7
+ @mongodb = mongodb
8
+ @options = options
9
+ puts "\n" + self.name
10
+ puts "\n > Configuring MongoDB service."
11
+
12
+ DanarchyDeploy::Services::Init.init_manager(os, 'mongodb', 'start', options) if ! options[:pretend]
13
+ Mongo::Logger.logger.level = Logger::FATAL
14
+ mongodb_conf, updated_conf = self.load_mongodb_conf
15
+ host_port = mongodb_conf['net']['bindIp'].split(',').first + ':' + mongodb_conf['net']['port'].to_s
16
+ admin_user, new_admin = self.load_admin_user
17
+
18
+ if new_admin == true
19
+ client = Mongo::Client.new(['127.0.0.1'], database: 'admin')
20
+ self.ensure_user(client.database, admin_user)
21
+ end
22
+
23
+ if ! options[:pretend] && updated_conf == true || new_admin == true
24
+ puts 'Stopping MongoDB'
25
+ DanarchyDeploy::Services::Init.init_manager(os, 'mongodb', 'stop', options)
26
+ self.save_mongodb_conf(mongodb_conf)
27
+ puts 'Starting MongoDB'
28
+ DanarchyDeploy::Services::Init.init_manager(os, 'mongodb', 'start', options)
29
+ end
30
+
31
+ client = Mongo::Client.new([host_port], database: 'admin',
32
+ user: admin_user[:user], password: Base64.decode64(admin_user[:password]))
33
+ self.ensure_user(client.database, admin_user)
34
+
35
+ if databases = @mongodb[:databases]
36
+ databases.each do |database, params|
37
+ print "\n |+ Fake Run: " if options[:pretend]
38
+ puts "\n Reviewing database: #{database}"
39
+ db = client.use(database).database
40
+ params[:users].each do |user|
41
+ puts " > Checking user: #{user[:user]}"
42
+ self.ensure_user(db, user)
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ private
49
+ def self.load_mongodb_conf
50
+ updated_conf = false
51
+ @mongodb[:mongodb_conf] = @mongodb[:mongodb_conf] ?
52
+ @mongodb[:mongodb_conf] :
53
+ '/etc/mongodb.conf'
54
+ mongodb_conf = File.exist?(@mongodb[:mongodb_conf]) ? YAML.load_file(@mongodb[:mongodb_conf]) : Hash.new
55
+
56
+ generated_mongodb_conf = self.generate_mongodb_conf
57
+ updated_conf = mongodb_conf != generated_mongodb_conf
58
+ [generated_mongodb_conf, updated_conf]
59
+ end
60
+
61
+ def self.generate_mongodb_conf
62
+ if ! File.readlines('/etc/security/limits.conf').grep(/mongodb/)
63
+ entry = 'mongodb soft nofile 32000'
64
+ entry += 'mongodb hard nofile 64000'
65
+ File.open('/etc/security/limits.conf', 'a+') do |f|
66
+ f.write entry
67
+ end
68
+ end
69
+
70
+ mongodb_conf = {
71
+ 'net' => { 'port' => 27017, 'bindIp' => '127.0.0.1' },
72
+ 'storage' => { 'dbPath' => '/var/lib/mongodb' },
73
+ 'systemLog' => { 'destination' => 'file',
74
+ 'path' => '/var/log/mongodb/mongodb.log',
75
+ 'quiet' => true,
76
+ 'logAppend' => true }
77
+ }
78
+
79
+ if @mongodb[:config]
80
+ mdb_conf = DanarchyDeploy::Helpers.hash_symbols_to_strings(@mongodb[:config])
81
+ mongodb_conf = mongodb_conf.deep_merge(mdb_conf)
82
+ end
83
+
84
+ mongodb_conf
85
+ end
86
+
87
+ def self.save_mongodb_conf(mongodb_conf)
88
+ if @options[:pretend]
89
+ puts "\n |+ Fake run: Saving MongoDB Configuration"
90
+ else
91
+ puts 'Saving MongoDB Configuration'
92
+ File.write(@mongodb[:mongodb_conf], mongodb_conf.to_yaml)
93
+ end
94
+ end
95
+
96
+ # def self.ensure_admin_user(host_port, admin_user)
97
+ # begin
98
+ # client = Mongo::Client.new([host_port], database: 'admin',
99
+ # username: admin_user[:user], password: admin_user[:password])
100
+ # database = client.database
101
+ # database.users.info(admin_user[:user])
102
+ # rescue Mongo::Auth::Unauthorized, Mongo::Error => e
103
+ # puts e.message
104
+
105
+ # if @options[:pretend]
106
+ # puts " |+ Fake Run: Creating admin user #{admin_user[:user]}"
107
+ # else
108
+ # client = Mongo::Client.new([host_port], database: 'admin')
109
+ # db = client.database
110
+ # self.ensure_user(db, admin_user)
111
+ # end
112
+ # end
113
+ # end
114
+
115
+ def self.generate_admin_user
116
+ password = @mongodb[:admin_password] ?
117
+ @mongodb[:admin_password].chomp :
118
+ Base64.encode64(SecureRandom.base64(14)).chomp
119
+
120
+ { user: "admin",
121
+ password: password,
122
+ roles: [{ role: "root", db: "admin" },
123
+ { role: "userAdminAnyDatabase", db: "admin" },
124
+ { role: "dbAdminAnyDatabase", db: "admin" },
125
+ { role: "readWriteAnyDatabase", db: "admin" }] }
126
+ end
127
+
128
+ def self.load_admin_user
129
+ admin_user = nil
130
+ new_user = false
131
+
132
+ if File.exist?('/root/.mdb_admin_user.json')
133
+ admin_user = JSON.parse(File.read('/root/.mdb_admin_user.json'), symbolize_names: true)
134
+ else
135
+ admin_user = self.generate_admin_user
136
+ self.save_admin_user(admin_user) if ! @options[:pretend]
137
+ new_user = true
138
+ end
139
+
140
+ [admin_user, new_user]
141
+ end
142
+
143
+ def self.save_admin_user(admin_user)
144
+ File.write('/root/.mdb_admin_user.json', JSON.pretty_generate(admin_user))
145
+ end
146
+
147
+ def self.ensure_user(db, user)
148
+ puts user if @options[:vars_verbose]
149
+ password = Base64.decode64(user[:password]).chomp
150
+ if @options[:pretend]
151
+ puts "\n |+ Fake Run: Creating/Updating user: #{user[:user]}"
152
+ elsif db.users.info(user[:user]).empty?
153
+ puts "\n |+ Creating user: #{user[:user]}"
154
+ db.users.create(user[:user], password: password, roles: user[:roles])
155
+ else
156
+ puts "\n |+ Updating user: #{user[:user]}"
157
+ db.users.update(user[:user], password: password, roles: user[:roles])
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,58 @@
1
+ require_relative 'mysql/new_server'
2
+ require_relative 'mysql/privileges'
3
+
4
+ module DanarchyDeploy
5
+ module Services
6
+ class MySQL
7
+ def self.new(os, mysql, options)
8
+ puts "\n" + self.name
9
+ puts "\n > Configuring MySQL service."
10
+
11
+ mysql = self.set_parameters(mysql)
12
+ self.generate_my_cnf(mysql, options)
13
+
14
+ if File.exist?(mysql[:my_cnf]) && Dir.exist?(mysql[:datadir] + '/mysql')
15
+ puts " |+ Using existing MySQL service."
16
+ else
17
+ MySQL::NewServer.new(os, mysql, options)
18
+ end
19
+
20
+ if mysql[:privileges]
21
+ puts "\n > Configuring MySQL Privileges"
22
+ MySQL::Privileges.new(mysql, options)
23
+ end
24
+ end
25
+
26
+ def self.set_parameters(mysql)
27
+ mysql[:default_file] = mysql[:default_file] ?
28
+ mysql[:default_file] :
29
+ '/root/.my.cnf'
30
+ mysql[:my_cnf] = mysql[:my_cnf] ?
31
+ mysql[:my_cnf] :
32
+ '/etc/mysql/my.cnf'
33
+ mysql[:datadir] = mysql[:datadir] ?
34
+ mysql[:datadir] :
35
+ '/var/lib/mysql'
36
+ mysql[:bind_address] = mysql[:bind_address] ?
37
+ mysql[:bind_address] :
38
+ '127.0.0.1'
39
+
40
+ mysql
41
+ end
42
+
43
+ def self.generate_my_cnf(mysql, options)
44
+ source = options[:deploy_dir] +
45
+ '/templates/services/mysql/my.cnf.erb'
46
+
47
+ templates = [{ target: mysql[:my_cnf],
48
+ source: source,
49
+ variables: {
50
+ datadir: mysql[:datadir],
51
+ bind_address: mysql[:bind_address] }
52
+ }]
53
+
54
+ DanarchyDeploy::Templater.new(templates, options)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,72 @@
1
+
2
+ module DanarchyDeploy
3
+ module Services
4
+ class MySQL
5
+ class NewServer
6
+ def self.new(os, mysql, options)
7
+ self.generate_root_mycnf(mysql, options)
8
+
9
+ if os == 'gentoo'
10
+ self.gentoo_new_mysql(mysql, options)
11
+ elsif os == 'opensuse'
12
+ self.opensuse_new_mysql(mysql, options)
13
+ elsif %w[debian ubuntu].include?(os)
14
+ self.debian_new_mysql(mysql, options)
15
+ elsif %w[centos redhat].include?(os)
16
+ self.centos_new_mysql(mysql, options)
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def self.gentoo_new_mysql(mysql, options)
23
+ puts "\n > Performing first time MySQL configuration."
24
+ cmd = 'emerge --config mariadb'
25
+ config_result = DanarchyDeploy::Helpers.run_command(cmd, options)
26
+
27
+ if config_result[:stderr]
28
+ abort(' |! ERROR: Failed to configure MySQL')
29
+ else config_result[:stdout]
30
+ puts " |+ MySQL configured successfully"
31
+ puts config_result[:stdout]
32
+ end
33
+
34
+ puts "\n > Starting MySQL."
35
+ DanarchyDeploy::Services::Init.init_manager('gentoo', 'mysql', 'start', options)
36
+ end
37
+
38
+ def self.debian_new_mysql(mysql, options)
39
+ puts " ! Debian/Ubuntu MySQL configuration not yet implemented!"
40
+ end
41
+
42
+ def self.centos_new_mysql(mysql, options)
43
+ puts " ! CentOS/Redhat MySQL configuration not yet implemented!"
44
+
45
+ end
46
+
47
+ def self.opensuse_new_mysql(mysql, options)
48
+ puts " ! OpenSUSE MySQL configuration not yet implemented!"
49
+ end
50
+
51
+ def self.generate_root_mycnf(mysql, options)
52
+ return if File.exist?(mysql[:default_file])
53
+ puts " |+ Generating #{mysql[:default_file]} file."
54
+ password = SecureRandom.base64(14)
55
+ source = options[:deploy_dir] +
56
+ '/templates/services/mysql/root_my.cnf.erb'
57
+
58
+ templates = [{ target: mysql[:default_file],
59
+ source: source,
60
+ variables: {
61
+ host: 'localhost',
62
+ user: 'root',
63
+ pass: password,
64
+ port: '3306' }
65
+ }]
66
+
67
+ DanarchyDeploy::Templater.new(templates, options)
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,35 @@
1
+ # require 'mysql2'
2
+ # Need to run with CLI rather than Ruby gem to reduce dependencies when this isn't used.
3
+
4
+ module DanarchyDeploy
5
+ module Services
6
+ class MySQL
7
+ class Privileges
8
+ def self.new(mysql, options)
9
+ sql_grants = sql_template(mysql, options)
10
+ run_sql_grants(mysql, sql_grants, options)
11
+ end
12
+
13
+ def self.sql_template(mysql, options)
14
+ sql_grants = '/root/.user_grants.sql'
15
+ source = options[:deploy_dir] +
16
+ '/templates/services/mysql/user_db_grants.sql.erb'
17
+ templates = [{ target: sql_grants,
18
+ source: source,
19
+ variables: mysql[:privileges] }]
20
+
21
+ DanarchyDeploy::Templater.new(templates, options)
22
+ sql_grants
23
+ end
24
+
25
+ def self.run_sql_grants(mysql, sql_grants, options)
26
+ # Using CLI commands for now;
27
+ # mysql2 requires mysql client be installed even if we won't be using it.
28
+ # client = Mysql2::Client.new(:default_file => default_file)
29
+ cmd = "mysql --defaults-file=#{mysql[:default_file]} -v < #{sql_grants}"
30
+ DanarchyDeploy::Helpers.run_command(cmd, options)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,86 @@
1
+ require_relative 'system/centos'
2
+ require_relative 'system/debian'
3
+ require_relative 'system/gentoo'
4
+ require_relative 'system/opensuse'
5
+
6
+ module DanarchyDeploy
7
+ module System
8
+ def self.new(deployment, options)
9
+ abort('Operating System not defined! Exiting!') if !deployment[:os]
10
+ puts "\n" + self.name
11
+
12
+ installer, updater, cleaner = prep_operating_system(deployment, options)
13
+ install_result = nil
14
+ if deployment[:packages] && !deployment[:packages].empty?
15
+ packages = deployment[:packages].join(' ')
16
+ puts "\nInstalling packages..."
17
+ install_result = DanarchyDeploy::Helpers.run_command("#{installer} #{packages}", options)
18
+ puts install_result[:stdout] if install_result[:stdout]
19
+ else
20
+ puts "\nNo packages to install."
21
+ end
22
+
23
+ if !options[:pretend]
24
+ puts "\nRunning system updates..."
25
+ updater_result = DanarchyDeploy::Helpers.run_command(updater, options)
26
+ puts updater_result[:stdout] if updater_result[:stdout]
27
+ puts "\nCleaning up unused packages..."
28
+ cleanup_result = DanarchyDeploy::Helpers.run_command(cleaner, options)
29
+ puts cleanup_result[:stdout] if cleanup_result[:stdout]
30
+ end
31
+
32
+ deployment
33
+ end
34
+
35
+ private
36
+ def self.prep_operating_system(deployment, options)
37
+ (installer, updater, cleaner) = nil
38
+ os = deployment[:os]
39
+
40
+ if deployment[:system]
41
+ if deployment[:system][:archives]
42
+ puts " > Deploying system archives"
43
+ DanarchyDeploy::Archiver.new(deployment[:system][:archives], options)
44
+ end
45
+
46
+ if deployment[:system][:templates]
47
+ puts "\n > Configuring system templates for #{deployment[:os]}"
48
+ DanarchyDeploy::Templater.new(deployment[:system][:templates], options)
49
+
50
+ # Add deployment[:system][:dmcrypt], deployment[:system][:lvm], and deployment[:system][:fstab] here
51
+ deployment[:system][:templates].each do |t|
52
+ if t[:target] == '/etc/fstab'
53
+ t[:variables].each do |v|
54
+ if !Dir.exist?(v[:mountpoint])
55
+ puts "Creating mountpoint: #{v[:mountpoint]}"
56
+ FileUtils.mkdir_p(v[:mountpoint]) if !options[:pretend]
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ end
63
+ end
64
+
65
+ puts "\n > Mounting Filesystems"
66
+ if !options[:pretend]
67
+ mount_result = DanarchyDeploy::Helpers.run_command('mount -a', options)
68
+ abort(' |! Failed to mount filesystems!') if mount_result[:stderr]
69
+ end
70
+
71
+ if os.downcase == 'gentoo'
72
+ (installer, updater, cleaner) = DanarchyDeploy::System::Gentoo.new(deployment, options)
73
+ elsif %w[debian ubuntu].include?(os.downcase)
74
+ (installer, updater, cleaner) = DanarchyDeploy::System::Debian.new(deployment, options)
75
+ elsif os.downcase == 'opensuse'
76
+ puts 'OpenSUSE is not fully supported yet!'
77
+ (installer, updater, cleaner) = DanarchyDeploy::System::OpenSUSE.new(deployment, options)
78
+ elsif %w[centos redhat].include?(os.downcase)
79
+ puts 'CentOS/RedHat is not fully supported yet!'
80
+ (installer, updater, cleaner) = DanarchyDeploy::System::CentOS.new(deployment, options)
81
+ end
82
+
83
+ [installer, updater, cleaner]
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,17 @@
1
+
2
+ module DanarchyDeploy
3
+ module System
4
+ class CentOS
5
+ def self.new(deployment, options)
6
+ puts "\n" + self.name
7
+ puts "#{deployment[:os].capitalize} detected! Using yum."
8
+ # needs more testing
9
+ installer = 'yum install -y '
10
+ updater = 'yum upgrade -y'
11
+ cleaner = 'yum clean all'
12
+
13
+ [installer, updater, cleaner]
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,61 @@
1
+ require 'net/http'
2
+
3
+ module DanarchyDeploy
4
+ module System
5
+ class Debian
6
+ def self.new(deployment, options)
7
+ puts "\n" + self.name
8
+ puts "#{deployment[:os].capitalize} detected! Using apt."
9
+
10
+ if deployment[:apt]
11
+ if deployment[:apt][:templates]
12
+ puts "\nChecking Apt configs."
13
+ DanarchyDeploy::Templater.new(deployment[:apt][:templates], options)
14
+ end
15
+
16
+ if deployment[:apt][:gpgkeys]
17
+ puts "\nInstalling Apt GPG Keys."
18
+ install_gpgkeys(deployment[:apt][:gpgkeys], options)
19
+ end
20
+ end
21
+
22
+ nonint = 'export DEBIAN_FRONTEND=noninteractive ; '
23
+ installer = nonint + 'apt-get install -y '
24
+ installer += '--dry-run ' if options[:pretend]
25
+ updater = nonint + 'apt-get upgrade -y '
26
+ cleaner = nonint + 'apt-get autoclean -y '
27
+
28
+ puts "\nUpdating Apt repos..."
29
+ DanarchyDeploy::Helpers.run_command(nonint + 'apt-get update', options)
30
+
31
+ [installer, updater, cleaner]
32
+ end
33
+
34
+ private
35
+ def self.install_gpgkeys(gpgkeys, options)
36
+ gpgkeys.each do |url|
37
+ puts "\n > Acquiring GPG key from: #{url}"
38
+ tmpfile = '/var/tmp/' + `date +%s`.chomp + '.gpgkey.tmp'
39
+ gpgkey = Net::HTTP.get(URI(url))
40
+ if ! gpgkey
41
+ abort(' ! GPG key download failed!')
42
+ else
43
+ puts " |+ GPG key successfully downloaded!"
44
+ File.write(tmpfile, gpgkey)
45
+ abort(" ! Failed to write tmpfile for url: #{url} => #{tmpfile}") if ! File.exist?(tmpfile)
46
+
47
+ # Silence noise about non-TTY terminal thanks to apt-key
48
+ gpgcmd = "export APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=false; apt-key add -qq #{tmpfile}"
49
+ gpg_result = DanarchyDeploy::Helpers.run_command(gpgcmd, { quiet: true })
50
+
51
+ if gpg_result[:stderr]
52
+ abort(" ! Failed to write key for: #{url}")
53
+ elsif gpg_result[:stdout]
54
+ puts " |+ GPG Key saved!"
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end