solutious-rudy 0.4.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,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
+