ridoku 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/AUTHORS +3 -0
- data/Gemfile +24 -0
- data/Gemfile.lock +45 -0
- data/LICENSE.txt +23 -0
- data/README.md +271 -0
- data/Rakefile +1 -0
- data/bin/rid +3 -0
- data/bin/ridoku +350 -0
- data/lib/helpers.rb +13 -0
- data/lib/io-colorize.rb +35 -0
- data/lib/options.rb +142 -0
- data/lib/ridoku.rb +11 -0
- data/lib/ridoku/backup.rb +393 -0
- data/lib/ridoku/base.rb +717 -0
- data/lib/ridoku/config_wizard.rb +195 -0
- data/lib/ridoku/cook.rb +103 -0
- data/lib/ridoku/create.rb +101 -0
- data/lib/ridoku/cron.rb +227 -0
- data/lib/ridoku/db.rb +235 -0
- data/lib/ridoku/defaults.rb +68 -0
- data/lib/ridoku/deploy.rb +157 -0
- data/lib/ridoku/domain.rb +124 -0
- data/lib/ridoku/dump.rb +132 -0
- data/lib/ridoku/env.rb +118 -0
- data/lib/ridoku/list.rb +168 -0
- data/lib/ridoku/log.rb +77 -0
- data/lib/ridoku/maintenance.rb +76 -0
- data/lib/ridoku/packages.rb +93 -0
- data/lib/ridoku/rails_defaults.rb +160 -0
- data/lib/ridoku/run.rb +137 -0
- data/lib/ridoku/service.rb +158 -0
- data/lib/ridoku/services/postgres.rb +77 -0
- data/lib/ridoku/services/rabbitmq.rb +48 -0
- data/lib/ridoku/version.rb +5 -0
- data/lib/ridoku/workers.rb +138 -0
- data/ridoku.gemspec +32 -0
- metadata +211 -0
data/lib/ridoku/log.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
#
|
2
|
+
# Command: log
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'ridoku/base'
|
6
|
+
|
7
|
+
module Ridoku
|
8
|
+
register :log
|
9
|
+
|
10
|
+
class Log < Base
|
11
|
+
attr_accessor :environment
|
12
|
+
|
13
|
+
def run
|
14
|
+
command = Base.config[:command]
|
15
|
+
sub_command = (command.length > 0 && command[1]) || nil
|
16
|
+
|
17
|
+
case sub_command
|
18
|
+
when 'unicorn', nil
|
19
|
+
unicorn_log
|
20
|
+
when 'nginx'
|
21
|
+
nginx_log
|
22
|
+
when 'all'
|
23
|
+
all_logs
|
24
|
+
else
|
25
|
+
print_log_help
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def unicorn_log_command
|
32
|
+
Base.fetch_app
|
33
|
+
|
34
|
+
lines = "#{Base.config[:lines] || 250}"
|
35
|
+
dir = "/srv/www/#{Base.app[:shortname]}/shared/log"
|
36
|
+
"for f in #{dir}/*.log; do echo "\
|
37
|
+
"#{$stdout.colorize("Log #{lines}: $f; "\
|
38
|
+
"echo #{'=' * 80}", [:bold])};"\
|
39
|
+
"tail -#{lines} $f; echo; done"
|
40
|
+
end
|
41
|
+
|
42
|
+
def line_break(title)
|
43
|
+
"#{'=' * 80}\n==== #{title}\n#{'=' * 80}\n"
|
44
|
+
end
|
45
|
+
|
46
|
+
def unicorn_log
|
47
|
+
$stdout.puts $stdout.colorize(line_break('Unicorn Logs'), [:bold, :green])
|
48
|
+
system(Ridoku::Run.command(unicorn_log_command, false))
|
49
|
+
end
|
50
|
+
|
51
|
+
def nginx_log
|
52
|
+
$stdout.puts $stdout.colorize(line_break('Nginx Logs'), [:bold, :green])
|
53
|
+
system(Ridoku::Run.command('tail -1000 /var/log/nginx/error.log'))
|
54
|
+
end
|
55
|
+
|
56
|
+
def all_logs
|
57
|
+
nginx_log
|
58
|
+
unicorn_log
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def print_log_help
|
63
|
+
$stderr.puts <<-EOF
|
64
|
+
Command: log
|
65
|
+
|
66
|
+
Log the specified command on an instance:
|
67
|
+
log[:unicorn] print unicorn logs for the specified app and instance
|
68
|
+
log:nginx print nginx logs for the specified app and instance
|
69
|
+
log:all print all logs for specified instance and app to commandline
|
70
|
+
|
71
|
+
examples:
|
72
|
+
$ ridoku log --mukujara
|
73
|
+
|
74
|
+
EOF
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#
|
2
|
+
# Command: maintenance
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'ridoku/base'
|
6
|
+
|
7
|
+
module Ridoku
|
8
|
+
register :maintenance
|
9
|
+
|
10
|
+
class Maintenance < Base
|
11
|
+
attr_accessor :app
|
12
|
+
|
13
|
+
def run
|
14
|
+
clist = Base.config[:command]
|
15
|
+
command = clist.shift
|
16
|
+
sub_command = clist.shift
|
17
|
+
|
18
|
+
case sub_command
|
19
|
+
when 'on'
|
20
|
+
maintenance(true)
|
21
|
+
when 'off'
|
22
|
+
maintenance(false)
|
23
|
+
when 'status', nil
|
24
|
+
status
|
25
|
+
else
|
26
|
+
print_maintenance_help
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def maintenance(maint)
|
33
|
+
Base.fetch_stack
|
34
|
+
Base.fetch_app
|
35
|
+
|
36
|
+
Base.custom_json['deploy'][Base.app[:shortname]]['maintenance'] = maint
|
37
|
+
Base.save_stack
|
38
|
+
|
39
|
+
Ridoku::Cook.cook_recipe_on_layers('deploy::maintenance', ['rails-app'],
|
40
|
+
deploy: {
|
41
|
+
Base.app[:shortname] => {
|
42
|
+
application_type: 'rails'
|
43
|
+
}
|
44
|
+
}
|
45
|
+
)
|
46
|
+
status
|
47
|
+
end
|
48
|
+
|
49
|
+
def status
|
50
|
+
Base.fetch_stack
|
51
|
+
Base.fetch_app
|
52
|
+
|
53
|
+
$stdout.print 'Maintenance: '
|
54
|
+
|
55
|
+
app_json = Base.custom_json['deploy'][Base.app[:shortname]]
|
56
|
+
|
57
|
+
if app_json.key?('maintenance')
|
58
|
+
maint = (app_json['maintenance'] == true)
|
59
|
+
$stdout.puts $stdout.colorize((maint ? 'on' : 'off'),
|
60
|
+
[:bold, (maint ? :red : :green)])
|
61
|
+
else
|
62
|
+
$stdout.puts $stdout.colorize('off', :green)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def print_maintenance_help
|
67
|
+
$stderr.puts <<-EOF
|
68
|
+
Command: maintenance
|
69
|
+
|
70
|
+
Set maintenance mode on the specific applications:
|
71
|
+
maintenance:on Turn on maintenance mode for all application instances.
|
72
|
+
maintenance:off Turn off maintenance mode for all application instances.
|
73
|
+
EOF
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
#
|
2
|
+
# Command: packages
|
3
|
+
# Description: List/Modify the current apps configuration.
|
4
|
+
# packages - lists the key value pairs
|
5
|
+
# packages:add PACKAGE [...]
|
6
|
+
# packages:delete KEY
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'ridoku/base'
|
10
|
+
|
11
|
+
module Ridoku
|
12
|
+
register :packages
|
13
|
+
|
14
|
+
class Packages < Base
|
15
|
+
|
16
|
+
def run
|
17
|
+
command = Base.config[:command]
|
18
|
+
sub_command = (command.length > 0 && command[1]) || nil
|
19
|
+
|
20
|
+
case sub_command
|
21
|
+
when 'list', nil
|
22
|
+
list
|
23
|
+
when 'set', 'add'
|
24
|
+
set
|
25
|
+
when 'delete', 'remove', 'rm'
|
26
|
+
delete
|
27
|
+
else
|
28
|
+
print_package_help
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
def print_package_help
|
35
|
+
$stderr.puts <<-EOF
|
36
|
+
Command: packages
|
37
|
+
|
38
|
+
List/Modify the current layer's package dependencies.
|
39
|
+
packages lists the key value pairs
|
40
|
+
packages:set PACKAGE [...]
|
41
|
+
packages:delete PACKAGE [...]
|
42
|
+
|
43
|
+
#{$stderr.colorize('Warning:', [:bold, :red])} Currently, this is limited by Opsworks to 10 packages.
|
44
|
+
EOF
|
45
|
+
end
|
46
|
+
|
47
|
+
def list
|
48
|
+
Base.fetch_layer(Base.config[:layer] || 'rails-app')
|
49
|
+
|
50
|
+
if Base.layers.length == 0
|
51
|
+
$stdout.puts 'No Layers Selected!'
|
52
|
+
|
53
|
+
else
|
54
|
+
max = 0
|
55
|
+
Base.layers.each do |layer|
|
56
|
+
short = $stdout.colorize(layer[:shortname], :bold)
|
57
|
+
max = short.length if max < short.length
|
58
|
+
end
|
59
|
+
|
60
|
+
Base.layers.each do |layer|
|
61
|
+
fmt = "%#{max}s"
|
62
|
+
shortname = sprintf(fmt, $stdout.colorize(layer[:shortname], :bold))
|
63
|
+
$stdout.puts "[#{shortname}] #{layer[:name]}: " +
|
64
|
+
"#{$stdout.colorize('No Packages Selected', :red) if
|
65
|
+
layer[:packages].length == 0}"
|
66
|
+
layer[:packages].each do |pack|
|
67
|
+
$stdout.puts " #{$stdout.colorize(pack, :green)}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def set
|
74
|
+
Base.fetch_layer(Base.config[:layer] || 'rails-app')
|
75
|
+
|
76
|
+
ARGV.each do |package|
|
77
|
+
# $stdout.puts "#{update && 'Updating' || 'Adding'}: #{key} as '#{value}'"
|
78
|
+
end
|
79
|
+
|
80
|
+
# Base.save_layer(layer, :packages)
|
81
|
+
end
|
82
|
+
|
83
|
+
def delete
|
84
|
+
Base.fetch_layer(Base.config[:layer] || 'rails-app')
|
85
|
+
|
86
|
+
ARGV.each do |package|
|
87
|
+
# $stdout.puts "Deleting key: #{key}, '#{value}'"
|
88
|
+
end
|
89
|
+
|
90
|
+
# Base.save_layer(layer, :packages)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
|
2
|
+
require 'ridoku/defaults'
|
3
|
+
|
4
|
+
module Ridoku
|
5
|
+
class RailsDefaults < ClassProperties
|
6
|
+
def initialize
|
7
|
+
super
|
8
|
+
|
9
|
+
self.warnings = {}.tap do |warn|
|
10
|
+
warn[:app_source] = <<-EOA
|
11
|
+
The App Source is the repository which you wish to pull your application
|
12
|
+
from. 'Type' should be 'git','subversion', etc. 'Url' should be the
|
13
|
+
'git@github:user/repo' url (or appropriate repository URL). 'SSH Key'
|
14
|
+
should be a Private key associated with the repository you pull from.
|
15
|
+
EOA
|
16
|
+
|
17
|
+
warn[:domains] = <<-EOB
|
18
|
+
Domains this server should respond to (used for the HTTP server config).
|
19
|
+
Separate each domain with a ':' or '|'.
|
20
|
+
EOB
|
21
|
+
end
|
22
|
+
|
23
|
+
self.required = {
|
24
|
+
stack: {
|
25
|
+
service_role_arn: :string,
|
26
|
+
default_instance_profile_arn: :string,
|
27
|
+
# attributes: Color: ?,
|
28
|
+
custom_cookbooks_source: { ssh_key: :optional }
|
29
|
+
},
|
30
|
+
layer: {
|
31
|
+
loadbalance: {
|
32
|
+
attributes: {
|
33
|
+
haproxy_stats_password: :string,
|
34
|
+
haproxy_stats_user: :string
|
35
|
+
}
|
36
|
+
},
|
37
|
+
application: {},
|
38
|
+
database: {}
|
39
|
+
},
|
40
|
+
app: {
|
41
|
+
name: :string,
|
42
|
+
shortname: :string,
|
43
|
+
type: :string,
|
44
|
+
app_source: {
|
45
|
+
type: :string,
|
46
|
+
url: :string,
|
47
|
+
ssh_key: :optional
|
48
|
+
},
|
49
|
+
domains: :array,
|
50
|
+
attributes: {
|
51
|
+
rails_env: :string
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
self.default = {
|
57
|
+
stack: {
|
58
|
+
name: 'Ridoku-Rails',
|
59
|
+
region: 'us-west-1',
|
60
|
+
default_os: 'Ubuntu 12.04 LTS',
|
61
|
+
hostname_theme: 'Legendary_creatures_from_Japan',
|
62
|
+
default_availability_zone: 'us-west-1a',
|
63
|
+
custom_json: '',
|
64
|
+
configuration_manager: {
|
65
|
+
name: 'Chef',
|
66
|
+
version: '11.4'
|
67
|
+
},
|
68
|
+
use_custom_cookbooks:true,
|
69
|
+
custom_cookbooks_source: {
|
70
|
+
type: 'git',
|
71
|
+
url: 'git@github.com:zv1n/ridoku-cookbooks.git',
|
72
|
+
revision: 'stable'
|
73
|
+
},
|
74
|
+
default_root_device_type: 'instance-store'
|
75
|
+
},
|
76
|
+
|
77
|
+
layer: [
|
78
|
+
loadbalance: {
|
79
|
+
standard: true,
|
80
|
+
updates: true,
|
81
|
+
type:'lb',
|
82
|
+
attributes: {
|
83
|
+
enable_haproxy_stats: 'true',
|
84
|
+
haproxy_health_check_method: 'OPTIONS',
|
85
|
+
haproxy_health_check_url: '/',
|
86
|
+
haproxy_stats_url: '/haproxy?stats',
|
87
|
+
},
|
88
|
+
auto_assign_elastic_ips: true,
|
89
|
+
auto_assign_public_ips: true
|
90
|
+
},
|
91
|
+
application: {
|
92
|
+
standard: true,
|
93
|
+
updates: true,
|
94
|
+
type:'rails-app',
|
95
|
+
attributes: {
|
96
|
+
bundler_version: '1.3.5',
|
97
|
+
manage_bundler: 'true',
|
98
|
+
rails_stack: 'nginx_unicorn',
|
99
|
+
ruby_version:'1.9.3',
|
100
|
+
rubygems_version:'2.1.5'
|
101
|
+
},
|
102
|
+
packages: [
|
103
|
+
'imagemagick',
|
104
|
+
'libmagickwand-dev',
|
105
|
+
'nodejs',
|
106
|
+
'postgresql-common',
|
107
|
+
'libpgsql-ruby'
|
108
|
+
],
|
109
|
+
auto_assign_elastic_ips: false,
|
110
|
+
auto_assign_public_ips: true,
|
111
|
+
custom_recipes:{
|
112
|
+
configure: ['postgresql::ruby']
|
113
|
+
}
|
114
|
+
},
|
115
|
+
database: {
|
116
|
+
type: 'custom',
|
117
|
+
name: 'Ridoku-Postgres',
|
118
|
+
shortname: 'ridoku-postgres',
|
119
|
+
attributes: {
|
120
|
+
},
|
121
|
+
auto_assign_elastic_ips: true,
|
122
|
+
auto_assign_public_ips: true,
|
123
|
+
custom_security_group_ids: ['Ridoku-PostgreSQL-Server'],
|
124
|
+
custom_recipes:{
|
125
|
+
setup: ['postgresql::ec2_server'],
|
126
|
+
configure: [],
|
127
|
+
deploy: [],
|
128
|
+
undeploy: [],
|
129
|
+
shutdown: []
|
130
|
+
},
|
131
|
+
instance: {
|
132
|
+
root_device_type: 'ebs-backed'
|
133
|
+
}
|
134
|
+
}
|
135
|
+
],
|
136
|
+
|
137
|
+
app: {
|
138
|
+
app_source: {
|
139
|
+
type: 'git',
|
140
|
+
revision: 'master'
|
141
|
+
},
|
142
|
+
enable_ssl: false,
|
143
|
+
attributes:{
|
144
|
+
auto_bundle_on_deploy: true,
|
145
|
+
document_root: 'public'
|
146
|
+
},
|
147
|
+
},
|
148
|
+
|
149
|
+
instance: {
|
150
|
+
instance_type: 'm1.small',
|
151
|
+
os: 'Ubuntu 12.04 LTS',
|
152
|
+
availability_zone: 'us-west-1a',
|
153
|
+
architecture: 'x86_64',
|
154
|
+
root_device_type: 'instance-store',
|
155
|
+
install_updates_on_boot: true
|
156
|
+
}
|
157
|
+
}
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
data/lib/ridoku/run.rb
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
#
|
2
|
+
# Command: run
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'ridoku/base'
|
6
|
+
|
7
|
+
module Ridoku
|
8
|
+
register :run
|
9
|
+
|
10
|
+
class Run < Base
|
11
|
+
attr_accessor :environment
|
12
|
+
|
13
|
+
def run
|
14
|
+
command = Base.config[:command]
|
15
|
+
sub_command = (command.length > 0 && command[1]) || nil
|
16
|
+
|
17
|
+
case sub_command
|
18
|
+
when 'command', nil
|
19
|
+
run_command
|
20
|
+
when 'shell'
|
21
|
+
shell
|
22
|
+
else
|
23
|
+
print_run_help
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
class << self
|
30
|
+
def create_ssh_path(instance = nil)
|
31
|
+
Base.fetch_instance
|
32
|
+
Base.fetch_account
|
33
|
+
|
34
|
+
instance ||= Base.select_instances(Base.config[:instances]).first
|
35
|
+
|
36
|
+
unless instance
|
37
|
+
$stderr.puts 'Unable to find a valid instance.'
|
38
|
+
print_run_help
|
39
|
+
exit 1
|
40
|
+
end
|
41
|
+
|
42
|
+
username = Base.account[:user][:user_name].gsub(/[.]/, '')
|
43
|
+
"#{username}@#{instance[:elastic_ip] || instance[:public_ip]}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def command(command = nil, relative_command = true)
|
47
|
+
Base.fetch_app
|
48
|
+
Base.fetch_permissions
|
49
|
+
|
50
|
+
Base.fetch_stack
|
51
|
+
|
52
|
+
# stupid fucking escaping bullshit
|
53
|
+
# So, ruby escapes, so does bash, so does ssh
|
54
|
+
# (all interpreter layers)
|
55
|
+
# Sooo, we have to have an OMFG ridiculous number of backslashes...
|
56
|
+
# to escape one mother fucking value.
|
57
|
+
|
58
|
+
# TODO: The entire 'run' system is fucked. Rethink it.
|
59
|
+
command.gsub!(/\$/, '\\'*14 + '$') if command
|
60
|
+
|
61
|
+
environment =
|
62
|
+
Base.custom_json['deploy'][Base.app[:shortname]]['app_env']
|
63
|
+
|
64
|
+
fail Ridoku::NoSshAccess.new unless
|
65
|
+
Base.permissions[:permissions].first[:allow_ssh]
|
66
|
+
|
67
|
+
if Base.permissions[:permissions].first[:allow_sudo]
|
68
|
+
prefix = "sudo su #{Base.config[:shell_user] || 'root'} -c "
|
69
|
+
else
|
70
|
+
prefix = ''
|
71
|
+
end
|
72
|
+
|
73
|
+
environ = environment.map do |key, val|
|
74
|
+
"#{key}='#{val}'"
|
75
|
+
end.join(' ')
|
76
|
+
|
77
|
+
dir = "/srv/www/#{Base.app[:shortname]}/current"
|
78
|
+
chdir = "cd #{dir}"
|
79
|
+
path = "PATH=/usr/local/bin:#{dir}/script/:${PATH}"
|
80
|
+
network_path = create_ssh_path
|
81
|
+
|
82
|
+
relative = relative_command ? '/usr/bin/env' : ''
|
83
|
+
|
84
|
+
bash_command = (command && "-c \\\\\\\"#{chdir} && #{relative} #{command}\\\\\\\"") || ''
|
85
|
+
|
86
|
+
ssh_command = [
|
87
|
+
"-t #{network_path}",
|
88
|
+
%Q("#{prefix} \\"#{environ} #{path} bash #{bash_command}\\"")
|
89
|
+
]
|
90
|
+
|
91
|
+
ssh_command.unshift("-i #{Base.config[:ssh_key]}") if
|
92
|
+
Base.config[:ssh_key]
|
93
|
+
|
94
|
+
ssh_command.unshift("/usr/bin/env ssh").join(' ')
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def shell
|
99
|
+
command = Ridoku::Run.command
|
100
|
+
|
101
|
+
Base.if_debug? do
|
102
|
+
$stdout.puts 'Running shell with command:'
|
103
|
+
$stdout.puts command
|
104
|
+
end
|
105
|
+
|
106
|
+
exec command
|
107
|
+
end
|
108
|
+
|
109
|
+
def run_command
|
110
|
+
command = Ridoku::Run.command(ARGV.join(' '))
|
111
|
+
|
112
|
+
Base.if_debug? do
|
113
|
+
$stdout.puts 'Running command:'
|
114
|
+
$stdout.puts command
|
115
|
+
end
|
116
|
+
|
117
|
+
exec command
|
118
|
+
end
|
119
|
+
|
120
|
+
def print_run_help
|
121
|
+
$stderr.puts <<-EOF
|
122
|
+
Command: run
|
123
|
+
|
124
|
+
Run the specified command on an instance:
|
125
|
+
run[:command] run a command (over ssh) in the release directory
|
126
|
+
run:shell ssh to the specified instance
|
127
|
+
--instance specify the instance (max: 1)
|
128
|
+
--user ssh as user (default: root; optionally: <AWS Username>,
|
129
|
+
or deploy)
|
130
|
+
|
131
|
+
examples:
|
132
|
+
$ run:shell
|
133
|
+
mukujara$
|
134
|
+
EOF
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|