ridoku 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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