ridoku 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,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