solutious-rudy 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,85 @@
1
+ #
2
+ #
3
+ #
4
+ #
5
+ #
6
+ #
7
+ #
8
+ #
9
+ #
10
+ #
11
+ #
12
+
13
+ module Rudy
14
+ module Command
15
+ class Instances < Rudy::Command::Base
16
+
17
+ def restart_instances_valid?
18
+ raise "No instance ID provided" if @argv.filter.nil?
19
+ raise "No EC2 .pem keys provided" unless has_pem_keys?
20
+ raise "No SSH key provided for #{@global.user}!" unless has_keypair?
21
+ raise "No SSH key provided for root!" unless has_keypair?(:root)
22
+
23
+
24
+ @list = @ec2.instances.list(machine_group)
25
+ raise "#{@argv.filter} is not in the current machine group" unless @list.has_key?(@argv.filter)
26
+
27
+ raise "I will not help you destroy production!" if @global.environment == "prod" # TODO: use_caution?, locked?
28
+
29
+ exit unless are_you_sure?(5)
30
+ true
31
+ end
32
+ def restart_instances
33
+ puts "Restarting #{@argv.filter}!"
34
+ @ec2.instances.restart @argv.filter
35
+ end
36
+
37
+ def instances
38
+ filter = @argv.first
39
+ filter = machine_group if filter.nil? && !@option.all
40
+ if instance_id?(filter)
41
+ inst = @ec2.instances.get(filter)
42
+ raise "The instance #{filter} does not exist" if inst.empty?
43
+ list = {inst[:aws_instance_id] => inst}
44
+ else
45
+ raise "The security group #{filter} does not exist" if filter && !@ec2.groups.exists?(filter)
46
+ list = @ec2.instances.list(filter)
47
+ if list.empty?
48
+ msg = "There are no instances running"
49
+ msg << " in the group #{filter}" if filter
50
+ raise msg
51
+ end
52
+ end
53
+
54
+ list.each_pair do |id, inst|
55
+ print_instance inst
56
+ end
57
+
58
+ end
59
+
60
+ def destroy_instances_valid?
61
+ filter = argv.first
62
+ raise "No instance ID provided" if filter.nil?
63
+ raise "I will not help you destroy production!" if @global.environment == "prod" || filter =~ /^prod/
64
+ exit unless are_you_sure?
65
+ true
66
+ end
67
+
68
+ def destroy_instances
69
+ filter = argv.first
70
+
71
+ if @ec2.groups.exists?(filter)
72
+ list = @ec2.instances.list(filter)
73
+ raise "The group #{filter} has no running instances" if list.empty?
74
+ instance = list.keys.first
75
+ else
76
+ instance = filter
77
+ end
78
+ puts "Destroying #{instance}!"
79
+ @ec2.instances.destroy instance
80
+ end
81
+
82
+ end
83
+ end
84
+ end
85
+
@@ -0,0 +1,170 @@
1
+
2
+
3
+ module Rudy
4
+ module Command
5
+ class Machines < Rudy::Command::Base
6
+
7
+
8
+ def shutdown_valid?
9
+ raise "No EC2 .pem keys provided" unless has_pem_keys?
10
+ raise "No SSH key provided for #{@global.user}!" unless has_keypair?
11
+ raise "No SSH key provided for root!" unless has_keypair?(:root)
12
+
13
+ @list = @ec2.instances.list(machine_group)
14
+ raise "No machines running in #{machine_group}" unless @list && !@list.empty?
15
+
16
+ raise "I will not help you ruin production!" if @global.environment == "prod" # TODO: use_caution?, locked?
17
+
18
+ true
19
+ end
20
+
21
+
22
+ def shutdown
23
+ puts "Shutting down #{machine_group}: #{@list.keys.join(', ')}".att(:bright)
24
+ switch_user("root")
25
+ puts "This command also affects the volumes attached to the instances! (according to your routines config)"
26
+ exit unless are_you_sure?(5)
27
+
28
+ execute_routines(@list.values, :shutdown, :before)
29
+
30
+ execute_disk_routines(@list.values, :shutdown)
31
+
32
+
33
+ puts $/, "Terminating instances...".att(:bright), $/
34
+
35
+ @ec2.instances.destroy @list.keys
36
+ sleep 5
37
+
38
+ execute_routines(@list.values, :shutdown, :after)
39
+
40
+ puts "Done!"
41
+ end
42
+
43
+ def startup_valid?
44
+ rig = @ec2.instances.list(machine_group)
45
+ raise "There is already an instance running in #{machine_group}" if rig && !rig.empty?
46
+ raise "No SSH key provided for #{keypairname}!" unless has_keypair?
47
+ true
48
+ end
49
+ def startup
50
+ puts "Starting a machine in #{machine_group}".att(:bright)
51
+ switch_user("root")
52
+ exit unless are_you_sure?(3)
53
+
54
+ #execute_routines([], :startup, :before_local)
55
+
56
+ @option.image ||= machine_image
57
+
58
+ puts "using AMI: #{@option.image}"
59
+
60
+ instances = @ec2.instances.create(@option.image, machine_group.to_s, File.basename(keypairpath), machine_data.to_yaml, @global.zone)
61
+ inst = instances.first
62
+
63
+ if @option.address ||= machine_address
64
+ puts "Associating #{@option.address} to #{inst[:aws_instance_id]}"
65
+ @ec2.addresses.associate(inst[:aws_instance_id], @option.address)
66
+ end
67
+
68
+ wait_for_machine(inst[:aws_instance_id])
69
+ inst = @ec2.instances.get(inst[:aws_instance_id])
70
+
71
+ #inst = @ec2.instances.list(machine_group).values
72
+
73
+ execute_disk_routines(inst, :startup)
74
+ execute_routines(inst, :startup, :after)
75
+
76
+ puts "Done!"
77
+ end
78
+
79
+ def restart_valid?
80
+ shutdown_valid?
81
+ end
82
+ def restart
83
+ puts "Restarting #{machine_group}: #{@list.keys.join(', ')}".att(:bright)
84
+ switch_user("root")
85
+ exit unless are_you_sure?(5)
86
+
87
+ @list.each do |id, inst|
88
+ execute_routines(@list.values, :restart, :before)
89
+ end
90
+
91
+ puts "Restarting instances: #{@list.keys.join(', ')}".att(:bright)
92
+ @ec2.instances.restart @list.keys
93
+ sleep 10 # Wait for state to change and SSH to shutdown
94
+
95
+ @list.keys.each do |id|
96
+ wait_for_machine(id)
97
+ end
98
+
99
+ execute_disk_routines(@list.values, :restart)
100
+
101
+ @list.each do |id, inst|
102
+ execute_routines(@list.values, :restart, :after)
103
+ end
104
+
105
+ puts "Done!"
106
+ end
107
+
108
+
109
+ def status_valid?
110
+ raise "No EC2 .pem keys provided" unless has_pem_keys?
111
+ raise "No SSH key provided for #{@global.user}!" unless has_keypair?
112
+ raise "No SSH key provided for root!" unless has_keypair?(:root)
113
+
114
+ @list = @ec2.instances.list(machine_group)
115
+ raise "No machines running in #{machine_group}" unless @list
116
+ true
117
+ end
118
+ def status
119
+ puts "There are no machines running in #{machine_group}" if @list.empty?
120
+ @list.each_pair do |id, inst|
121
+ print_instance inst
122
+ end
123
+ end
124
+
125
+
126
+ def update_valid?
127
+ raise "No EC2 .pem keys provided" unless has_pem_keys?
128
+ raise "No SSH key provided for #{@global.user}!" unless has_keypair?
129
+ raise "No SSH key provided for root!" unless has_keypair?(:root)
130
+
131
+ @scripts = %w[rudy-ec2-startup update-ec2-ami-tools randomize-root-password]
132
+ @scripts.collect! {|script| File.join(RUDY_HOME, 'support', script) }
133
+ @scripts.each do |script|
134
+ raise "Cannot find #{script}" unless File.exists?(script)
135
+ end
136
+
137
+ true
138
+ end
139
+
140
+
141
+ def update
142
+ puts "Updating Rudy "
143
+ switch_user("root")
144
+
145
+ exit unless are_you_sure?
146
+ scp do |scp|
147
+ @scripts.each do |script|
148
+ puts "Uploading #{File.basename(script)}"
149
+ scp.upload!(script, "/etc/init.d/")
150
+ end
151
+ end
152
+
153
+ ssh do |session|
154
+ @scripts.each do |script|
155
+ session.exec!("chmod 700 /etc/init.d/#{File.basename(script)}")
156
+ end
157
+
158
+ puts "Installing Rudy (#{Rudy::VERSION})"
159
+ session.exec!("mkdir -p /etc/ec2")
160
+ session.exec!("gem sources -a http://gems.github.com")
161
+ puts session.exec!("gem install --no-ri --no-rdoc rudy -v #{Rudy::VERSION}")
162
+ end
163
+ end
164
+
165
+
166
+ end
167
+ end
168
+ end
169
+
170
+
@@ -0,0 +1,41 @@
1
+
2
+
3
+ module Rudy
4
+ module Command
5
+ class Metadata < Rudy::Command::Base
6
+
7
+
8
+ # Print Rudy's metadata to STDOUT
9
+ def metadata
10
+ group_metadata.each_pair do |n,h|
11
+ puts n.att(:bright)
12
+ puts h.inspect, ""
13
+ end
14
+ end
15
+
16
+ def destroy_metadata_valid?
17
+ false
18
+ end
19
+
20
+ def destroy_metadata
21
+ @sdb.domains.destroy(RUDY_DOMAIN)
22
+ end
23
+
24
+
25
+
26
+ def info
27
+ domains = @sdb.domains.list[:domains]
28
+ puts "Domains: #{domains.join(", ")}"
29
+ end
30
+
31
+ private
32
+ def check_environment
33
+ raise "No Amazon keys provided!" unless has_keys?
34
+ raise "No SSH keypairs provided!" unless has_keypair?
35
+ true
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+
@@ -0,0 +1,174 @@
1
+
2
+
3
+ module Rudy
4
+ module Command
5
+ class Release < Rudy::Command::Base
6
+
7
+
8
+
9
+
10
+ def release_valid?
11
+
12
+ relroutine = @config.routines.find_deferred(@global.environment, @global.role, :release)
13
+ raise "No release routines defined for #{machine_group}" if relroutine.nil?
14
+
15
+ raise "No EC2 .pem keys provided" unless has_pem_keys?
16
+ raise "No SSH key provided for #{@global.user} in #{machine_group}!" unless has_keypair?
17
+ raise "No SSH key provided for root in #{machine_group}!" unless has_keypair?(:root)
18
+
19
+ @list = @ec2.instances.list(machine_group)
20
+ unless @list.empty?
21
+ msg = "#{machine_group} is in use, probably with another release. #{$/}"
22
+ msg << 'Sort it out and run "rudy shutdown" before continuing.'
23
+ raise msg
24
+ end
25
+
26
+ @scm, @scm_params = find_scm(:release)
27
+
28
+ raise "No SCM defined for release routine" unless @scm
29
+ raise "#{Dir.pwd} is not a working copy" unless @scm.working_copy?(Dir.pwd)
30
+ raise "There are local changes. Please revert or check them in." unless @scm.everything_checked_in?
31
+ raise "Invalid base URI (#{@scm_params[:base]})." unless @scm.valid_uri?(@scm_params[:base])
32
+
33
+ true
34
+ end
35
+
36
+
37
+
38
+ def rerelease_valid?
39
+ relroutine = @config.routines.find_deferred(@global.environment, @global.role, :rerelease)
40
+ raise "No rerelease routines defined for #{machine_group}" if relroutine.nil?
41
+
42
+ raise "No EC2 .pem keys provided" unless has_pem_keys?
43
+ raise "No SSH key provided for #{@global.user} in #{machine_group}!" unless has_keypair?
44
+ raise "No SSH key provided for root in #{machine_group}!" unless has_keypair?(:root)
45
+
46
+ @list = @ec2.instances.list(machine_group)
47
+ if @list.empty?
48
+ msg = "There are no machines running in #{machine_group}. #{$/}"
49
+ msg << 'You must run "rudy release" before you can rerelease.'
50
+ raise msg
51
+ end
52
+
53
+ @scm, @scm_params = find_scm(:rerelease)
54
+
55
+ raise "No SCM defined for release routine" unless @scm
56
+ raise "#{Dir.pwd} is not a working copy" unless @scm.working_copy?(Dir.pwd)
57
+ raise "There are local changes. Please revert or check them in." unless @scm.everything_checked_in?
58
+ raise "Invalid base URI (#{@scm_params[:base]})." unless @scm.valid_uri?(@scm_params[:base])
59
+
60
+ true
61
+ end
62
+
63
+ def rerelease
64
+ puts "Updating release from working copy".att(:bright)
65
+
66
+ tag, revision = @scm.local_info
67
+ puts "tag: #{tag}"
68
+ puts "rev: #{revision}"
69
+
70
+ execute_disk_routines(@list.values, :rerelease)
71
+
72
+ if @scm
73
+
74
+ puts "Running SCM command".att(:bright)
75
+ ssh do |session|
76
+ cmd = "svn #{@scm_params[:command]}"
77
+ puts "#{cmd}"
78
+ session.exec!("cd #{@scm_params[:path]}")
79
+ session.exec!(cmd)
80
+ puts "#{@scm_params[:command]} complete"
81
+ end
82
+
83
+ end
84
+
85
+ execute_routines(@list.values, :rerelease, :after)
86
+
87
+ end
88
+
89
+ # <li>Creates a release tag based on the working copy on your machine</li>
90
+ # <li>Starts a new stage instance</li>
91
+ # <li>Executes release routines</li>
92
+ def release
93
+ # TODO: store metadata about release with local username and hostname
94
+ puts "Creating release from working copy".att(:bright)
95
+
96
+ exit unless are_you_sure?
97
+
98
+ tag = @scm.create_release(@global.local_user, @option.msg)
99
+ puts "Done! (#{tag})"
100
+
101
+ if @option.switch
102
+ puts "Switching working copy to new tag".att(:bright)
103
+ @scm.switch_working_copy(tag)
104
+ end
105
+
106
+ @option.image ||= machine_image
107
+
108
+ switch_user("root")
109
+
110
+ puts "Starting #{machine_group}".att(:bright)
111
+
112
+ instances = @ec2.instances.create(@option.image, machine_group.to_s, File.basename(keypairpath), machine_data.to_yaml, @global.zone)
113
+ inst = instances.first
114
+
115
+ if @option.address ||= machine_address
116
+ puts "Associating #{@option.address} to #{inst[:aws_instance_id]}".att(:bright)
117
+ @ec2.addresses.associate(inst[:aws_instance_id], @option.address)
118
+ end
119
+
120
+ wait_for_machine(inst[:aws_instance_id])
121
+ inst = @ec2.instances.get(inst[:aws_instance_id])
122
+
123
+ #inst = @ec2.instances.list(machine_group).values
124
+
125
+
126
+ execute_disk_routines(inst, :release)
127
+
128
+ if @scm
129
+
130
+ puts "Running SCM command".att(:bright)
131
+ ssh do |session|
132
+ cmd = "svn #{@scm_params[:command]} #{tag} #{@scm_params[:path]}"
133
+ puts "#{cmd}"
134
+ session.exec!(cmd)
135
+ puts "#{@scm_params[:command]} complete"
136
+ end
137
+
138
+ end
139
+
140
+ execute_routines(inst, :release, :after)
141
+
142
+ print_instance inst
143
+
144
+ puts "Done!"
145
+ end
146
+
147
+
148
+ def find_scm(routine)
149
+ env, rol, att = @global.environment, @global.role
150
+
151
+ # Look for the source control engine, checking all known scm values.
152
+ # The available one will look like [environment][role][release][svn]
153
+ params = nil
154
+ scm_name = nil
155
+ SUPPORTED_SCM_NAMES.each do |v|
156
+ scm_name = v
157
+ params = @config.routines.find(env, rol, routine, scm_name)
158
+ break if params
159
+ end
160
+
161
+ if params
162
+ klass = eval "Rudy::SCM::#{scm_name.to_s.upcase}"
163
+ scm = klass.new(:base => params[:base])
164
+ end
165
+
166
+ [scm, params]
167
+
168
+ end
169
+ private :find_scm
170
+
171
+ end
172
+ end
173
+ end
174
+