virtualmonkey 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (178) hide show
  1. data/.document +5 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +77 -0
  4. data/Rakefile +51 -0
  5. data/VERSION +1 -0
  6. data/bin/grinder +102 -0
  7. data/bin/mcicp +46 -0
  8. data/bin/monkey +12 -0
  9. data/bin/vary_instance_types +59 -0
  10. data/config/cloud_variables/all_clouds.json +30 -0
  11. data/config/cloud_variables/east.json +9 -0
  12. data/config/cloud_variables/rackspace.json +7 -0
  13. data/config/cloud_variables/west.json +9 -0
  14. data/config/common_inputs/apache_haproxy.json +27 -0
  15. data/config/common_inputs/base.json +5 -0
  16. data/config/common_inputs/ebs_toolbox.json +10 -0
  17. data/config/common_inputs/haproxy.json +15 -0
  18. data/config/common_inputs/lamp.json +30 -0
  19. data/config/common_inputs/mysql.json +24 -0
  20. data/config/common_inputs/none.json +4 -0
  21. data/config/common_inputs/php.json +25 -0
  22. data/config/common_inputs/php_aio_trial_chef_alpha.json +3 -0
  23. data/config/common_inputs/php_app_fe_chef.json +12 -0
  24. data/config/common_inputs/php_elb.json +12 -0
  25. data/config/common_inputs/qstart.json +5 -0
  26. data/config/common_inputs/rails.json +31 -0
  27. data/config/common_inputs/rails_aio_demo_chef_alpha.json +3 -0
  28. data/config/common_inputs/rails_aio_developer_chef_alpha.json +10 -0
  29. data/config/common_inputs/rsgrid.json +10 -0
  30. data/config/common_inputs/tomcat.json +15 -0
  31. data/config/common_inputs/windows_blog_engine.json +3 -0
  32. data/config/common_inputs/windows_net_aio.json +14 -0
  33. data/config/troop/11H1/backup/base.json +10 -0
  34. data/config/troop/11H1/backup/lamp_mysql_50.json +10 -0
  35. data/config/troop/11H1/backup/lamp_mysql_51.json +10 -0
  36. data/config/troop/11H1/backup/loadbalancer-php.json +13 -0
  37. data/config/troop/11H1/backup/loadbalancer.json +14 -0
  38. data/config/troop/11H1/backup/loadbalancer_rails.json +13 -0
  39. data/config/troop/11H1/backup/loadbalancer_tomcat6.json +13 -0
  40. data/config/troop/11H1/backup/mysql50.json +11 -0
  41. data/config/troop/11H1/backup/mysql50_toolbox.json +12 -0
  42. data/config/troop/11H1/backup/mysql51.json +11 -0
  43. data/config/troop/11H1/backup/mysql51_toolbox.json +12 -0
  44. data/config/troop/11H1/backup/php_elb.json +11 -0
  45. data/config/troop/11H1/base.json +10 -0
  46. data/config/troop/11H1/ebs_toolbox.json +12 -0
  47. data/config/troop/11H1/lamp_mysql_50.json +10 -0
  48. data/config/troop/11H1/lamp_mysql_51.json +10 -0
  49. data/config/troop/11H1/loadbalancer-php.json +13 -0
  50. data/config/troop/11H1/loadbalancer.json +17 -0
  51. data/config/troop/11H1/loadbalancer_rails.json +13 -0
  52. data/config/troop/11H1/loadbalancer_tomcat6.json +13 -0
  53. data/config/troop/11H1/mysql50.json +11 -0
  54. data/config/troop/11H1/mysql50_toolbox.json +12 -0
  55. data/config/troop/11H1/mysql51.json +11 -0
  56. data/config/troop/11H1/mysql51_awsdns.json +11 -0
  57. data/config/troop/11H1/mysql51_debug.json +11 -0
  58. data/config/troop/11H1/mysql51_toolbox.json +12 -0
  59. data/config/troop/11H1/php.json +13 -0
  60. data/config/troop/11H1/php_elb.json +11 -0
  61. data/config/troop/11H1/rails.json +13 -0
  62. data/config/troop/11H1/tomcat6.json +13 -0
  63. data/config/troop/chef_quickstart.json +10 -0
  64. data/config/troop/just_elb +10 -0
  65. data/config/troop/lamp_v4.json +10 -0
  66. data/config/troop/patch_test.json +10 -0
  67. data/config/troop/rightlink.json +10 -0
  68. data/config/troop/simple_fail.json +11 -0
  69. data/config/troop/simple_pass.json +11 -0
  70. data/config/troop/windows_blog_engine.json +10 -0
  71. data/config/troop/windows_net_aio.json +10 -0
  72. data/config/troop/windows_quick_start.json +10 -0
  73. data/features/base.rb +31 -0
  74. data/features/db_toolbox.rb +59 -0
  75. data/features/ebs_toolbox.rb +62 -0
  76. data/features/lamp.rb +33 -0
  77. data/features/lb-apache-haproxy.rb +49 -0
  78. data/features/mysql_5.x_v2_v4_from_scratch.rb +71 -0
  79. data/features/mysql_5.x_v2_v4_from_scratch_awsdns.rb +71 -0
  80. data/features/mysql_5.x_v2_v4_from_scratch_dyndns.rb +71 -0
  81. data/features/mysql_v1_upgrade_v2.rb +54 -0
  82. data/features/old_cuke_features/Rakefile +121 -0
  83. data/features/old_cuke_features/Steps-TODO +31 -0
  84. data/features/old_cuke_features/app_state.feature +25 -0
  85. data/features/old_cuke_features/app_test.feature +24 -0
  86. data/features/old_cuke_features/base.feature +16 -0
  87. data/features/old_cuke_features/chef_quickstart.feature +11 -0
  88. data/features/old_cuke_features/db_toolbox.feature +38 -0
  89. data/features/old_cuke_features/ebs_toolbox.feature +39 -0
  90. data/features/old_cuke_features/elb_create_delete.feature +41 -0
  91. data/features/old_cuke_features/elb_generic.feature +27 -0
  92. data/features/old_cuke_features/fe_app_checks.feature +21 -0
  93. data/features/old_cuke_features/just-start.feature +13 -0
  94. data/features/old_cuke_features/lamp.feature +15 -0
  95. data/features/old_cuke_features/lb-apache-haproxy.feature +27 -0
  96. data/features/old_cuke_features/mysql_5.x_v2_v4_from_scratch.feature +33 -0
  97. data/features/old_cuke_features/mysql_5.x_v2_v4_from_scratch_awsdns.feature +33 -0
  98. data/features/old_cuke_features/mysql_5.x_v2_v4_from_scratch_dyndns.feature +33 -0
  99. data/features/old_cuke_features/mysql_chef_premium.feature +27 -0
  100. data/features/old_cuke_features/mysql_chef_premium_from_scratch.feature +37 -0
  101. data/features/old_cuke_features/mysql_v1_upgrade_v2.feature +42 -0
  102. data/features/old_cuke_features/php.feature +27 -0
  103. data/features/old_cuke_features/php_aio_trial_chef_alpha.feature +11 -0
  104. data/features/old_cuke_features/php_chef.feature +21 -0
  105. data/features/old_cuke_features/php_elb.feature +41 -0
  106. data/features/old_cuke_features/rails.feature +26 -0
  107. data/features/old_cuke_features/rails_aio_developer_chef.feature +17 -0
  108. data/features/old_cuke_features/reboot.feature +23 -0
  109. data/features/old_cuke_features/rightlink.feature +19 -0
  110. data/features/old_cuke_features/rsgrid.feature +19 -0
  111. data/features/old_cuke_features/simple.feature +8 -0
  112. data/features/old_cuke_features/simple_fail.feature +9 -0
  113. data/features/old_cuke_features/start-stop.feature +13 -0
  114. data/features/old_cuke_features/step_definitions/app.rb +21 -0
  115. data/features/old_cuke_features/step_definitions/deployment_steps.rb +112 -0
  116. data/features/old_cuke_features/step_definitions/ebs.rb +36 -0
  117. data/features/old_cuke_features/step_definitions/elb.rb +35 -0
  118. data/features/old_cuke_features/step_definitions/lb.rb +22 -0
  119. data/features/old_cuke_features/step_definitions/mysql_steps.rb +84 -0
  120. data/features/old_cuke_features/terminate.feature +7 -0
  121. data/features/old_cuke_features/tomcat6-tests-TODO +29 -0
  122. data/features/old_cuke_features/tomcat6.feature +27 -0
  123. data/features/patch_test.rb +33 -0
  124. data/features/php.rb +54 -0
  125. data/features/php_elb.rb +78 -0
  126. data/features/rails.rb +54 -0
  127. data/features/start_only.rb +26 -0
  128. data/features/tomcat6.rb +54 -0
  129. data/lib/virtualmonkey.rb +28 -0
  130. data/lib/virtualmonkey/application.rb +75 -0
  131. data/lib/virtualmonkey/application_frontend.rb +42 -0
  132. data/lib/virtualmonkey/command.rb +39 -0
  133. data/lib/virtualmonkey/command/clone.rb +50 -0
  134. data/lib/virtualmonkey/command/create.rb +21 -0
  135. data/lib/virtualmonkey/command/destroy.rb +51 -0
  136. data/lib/virtualmonkey/command/list.rb +10 -0
  137. data/lib/virtualmonkey/command/run.rb +76 -0
  138. data/lib/virtualmonkey/command/troop.rb +146 -0
  139. data/lib/virtualmonkey/cuke_monk.rb +184 -0
  140. data/lib/virtualmonkey/deployment_monk.rb +132 -0
  141. data/lib/virtualmonkey/deployment_runner.rb +333 -0
  142. data/lib/virtualmonkey/ebs.rb +161 -0
  143. data/lib/virtualmonkey/ebs_runner.rb +59 -0
  144. data/lib/virtualmonkey/elb_runner.rb +194 -0
  145. data/lib/virtualmonkey/fe_app_runner.rb +7 -0
  146. data/lib/virtualmonkey/file_locations.rb +7 -0
  147. data/lib/virtualmonkey/frontend.rb +124 -0
  148. data/lib/virtualmonkey/http_checks.rb +33 -0
  149. data/lib/virtualmonkey/index.html.erb +109 -0
  150. data/lib/virtualmonkey/lamp_runner.rb +29 -0
  151. data/lib/virtualmonkey/mysql.rb +172 -0
  152. data/lib/virtualmonkey/mysql_runner.rb +108 -0
  153. data/lib/virtualmonkey/mysql_toolbox_runner.rb +51 -0
  154. data/lib/virtualmonkey/patch_runner.rb +46 -0
  155. data/lib/virtualmonkey/php_aio_trial_chef_runner.rb +6 -0
  156. data/lib/virtualmonkey/php_chef_runner.rb +69 -0
  157. data/lib/virtualmonkey/rails_aio_developer_chef_runner.rb +8 -0
  158. data/lib/virtualmonkey/shared_dns.rb +67 -0
  159. data/lib/virtualmonkey/simple.rb +5 -0
  160. data/lib/virtualmonkey/simple_runner.rb +6 -0
  161. data/lib/virtualmonkey/test_case_interface.rb +151 -0
  162. data/lib/virtualmonkey/unified_application.rb +40 -0
  163. data/spec/bug3518.rb +16 -0
  164. data/spec/concurrent_writes_spec.rb +26 -0
  165. data/spec/cuke_job_spec.rb +26 -0
  166. data/spec/ek.rb +28 -0
  167. data/spec/little_ruby.rb +20 -0
  168. data/spec/mini.rb +25 -0
  169. data/spec/monitoring.rb +13 -0
  170. data/spec/release_aws_dns.rb +5 -0
  171. data/spec/release_dns.rb +5 -0
  172. data/spec/release_dyndns.rb +5 -0
  173. data/spec/shared_resources_spec.rb +25 -0
  174. data/spec/spec.opts +1 -0
  175. data/spec/spec_helper.rb +11 -0
  176. data/spec/virtualmonkey_spec.rb +7 -0
  177. data/virtualmonkey.gemspec +265 -0
  178. metadata +428 -0
@@ -0,0 +1,146 @@
1
+ module VirtualMonkey
2
+ module Command
3
+ # This command does all the steps create/run/conditionaly destroy
4
+ def self.troop
5
+ options = Trollop::options do
6
+ text "This command performs all the operations of the monkey in one execution. Create/Run/Destroy"
7
+ opt :file, "troop config, see config/troop/*sample.json for example format", :type => :string, :required => true
8
+ opt :no_spot, "do not use spot instances"
9
+ opt :step, "use the troop config file to do either: create, run, or destroy", :type => :string
10
+ opt :tag, "add an additional tag to the deployments", :type => :string
11
+ opt :create, "interactive mode: create troop config"
12
+ opt :mci_override, "list of mcis to use instead of the ones from the server template. expects full hrefs.", :type => :string, :multi => true, :required => false
13
+ opt :no_delete, "only terminate, no deletion.", :short => "-d"
14
+ end
15
+
16
+ # PATHs SETUP
17
+ features_dir = File.join(File.dirname(__FILE__), "..", "..", "..", "features")
18
+ features_glob = Dir.glob(File.join(features_dir, "**"))
19
+ features_glob = features_glob.collect { |c| File.basename(c) }
20
+
21
+ config_dir = File.join(File.dirname(__FILE__), "..", "..", "..", "config")
22
+ cloud_variables_glob = Dir.glob(File.join(config_dir, "cloud_variables", "**"))
23
+ cloud_variables_glob = cloud_variables_glob.collect { |c| File.basename(c) }
24
+ common_inputs_glob = Dir.glob(File.join(config_dir, "common_inputs", "**"))
25
+ common_inputs_glob = common_inputs_glob.collect { |c| File.basename(c) }
26
+ global_state_dir = File.join(File.dirname(__FILE__), "..", "..", "..", "test_states")
27
+ options[:tag] += "-" if options[:tag]
28
+ options[:tag] = "" unless options[:tag]
29
+
30
+ # CREATE NEW CONFIG
31
+ if options[:create]
32
+ troop_config = {}
33
+ troop_config[:tag] = ask("What tag to use for creating the deployments?")
34
+ troop_config[:server_template_ids] = ask("What Server Template ids would you like to use to create the deployments (comma delimited)?").split(",")
35
+ troop_config[:server_template_ids].each {|st| st.strip!}
36
+
37
+ troop_config[:runner] =
38
+ choose do |menu|
39
+ menu.prompt = "What kind of deployment is this (runner type)?"
40
+ menu.choice("MysqlToolboxRunner")
41
+ menu.choice("MysqlRunner")
42
+ menu.choice("SimpleRunner")
43
+ end
44
+
45
+ troop_config[:cloud_variables] =
46
+ choose do |menu|
47
+ menu.prompt = "Which cloud_variables config file?"
48
+ menu.index = :number
49
+ menu.choices(*cloud_variables_glob)
50
+ end
51
+
52
+ troop_config[:common_inputs] =
53
+ choose do |menu|
54
+ menu.prompt = "Which common_inputs config file?"
55
+ menu.index = :number
56
+ menu.choices(*common_inputs_glob)
57
+ end
58
+
59
+ troop_config[:feature] =
60
+ choose do |menu|
61
+ menu.prompt = "Which feature file?"
62
+ menu.index = :number
63
+ menu.choices(*features_glob)
64
+ end
65
+
66
+ write_out = troop_config.to_json( :indent => " ",
67
+ :object_nl => "\n",
68
+ :array_nl => "\n" )
69
+ File.open(options[:file], "w") { |f| f.write(write_out) }
70
+ say("created config file #{options[:file]}")
71
+ say("Done.")
72
+ else
73
+ # Execute Main
74
+ config = JSON::parse(IO.read(options[:file]))
75
+ options[:step] = "all" unless options[:step]
76
+ tag = options[:tag] + config['tag']
77
+
78
+ # CREATE PHASE
79
+ if options[:step] =~ /((all)|(create))/
80
+ @dm = DeploymentMonk.new(tag, config['server_template_ids'])
81
+ @dm.variables_for_cloud = JSON::parse(IO.read(File.join(config_dir, "cloud_variables", config['cloud_variables'])))
82
+ config['common_inputs'].each do |cipath|
83
+ @dm.load_common_inputs(File.join(config_dir, "common_inputs", cipath))
84
+ end
85
+ @dm.generate_variations(options)
86
+ end
87
+
88
+ # RUN PHASE
89
+ if options[:step] =~ /((all)|(run))/
90
+ @dm = DeploymentMonk.new(tag) if options[:step] =~ /run/
91
+ EM.run {
92
+ @cm = CukeMonk.new
93
+ @cm.options = {}
94
+ remaining_jobs = @cm.jobs.dup
95
+ @dm.deployments.each do |deploy|
96
+ @cm.run_test(deploy, File.join(features_dir, config['feature']))
97
+ end
98
+
99
+ watch = EM.add_periodic_timer(10) {
100
+ @cm.watch_and_report
101
+ if @cm.all_done?
102
+ watch.cancel
103
+ end
104
+ remaining_jobs.each do |job|
105
+ # destroy on success only (keep failed deploys)
106
+ if job.status == 0 and options[:step] =~ /all/
107
+ runner = eval("VirtualMonkey::#{config['runner']}.new(job.deployment.nickname)")
108
+ puts "destroying successful deployment: #{runner.deployment.nickname}"
109
+ runner.behavior(:stop_all, false)
110
+ runner.deployment.destroy unless options[:no_delete]
111
+ remaining_jobs.delete(job)
112
+ if runner.respond_to?(:release_dns) and not options[:no_delete]
113
+ runner.behavior(:release_dns)
114
+ end
115
+ end
116
+ end
117
+ }
118
+ }
119
+ end
120
+
121
+ if options[:step] =~ /destroy/
122
+ @dm = DeploymentMonk.new(tag)
123
+ @dm.deployments.each do |deploy|
124
+ runner = eval("VirtualMonkey::#{config['runner']}.new(deploy.nickname)")
125
+ runner.behavior(:stop_all, false)
126
+ state_dir = File.join(global_state_dir, deploy.nickname)
127
+ if File.directory?(state_dir)
128
+ puts "Deleting state files for #{deploy.nickname}..."
129
+ Dir.new(state_dir).each do |state_file|
130
+ if File.extname(state_file) =~ /((rb)|(feature))/
131
+ File.delete(File.join(state_dir, state_file))
132
+ end
133
+ end
134
+ Dir.rmdir(state_dir)
135
+ end
136
+ if runner.respond_to?(:release_dns) and not options[:no_delete]
137
+ runner.behavior(:release_dns)
138
+ end
139
+ end
140
+ @dm.destroy_all unless options[:no_delete]
141
+ end
142
+ end
143
+ puts "Troop done."
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,184 @@
1
+ require 'rubygems'
2
+ require 'erb'
3
+ require 'fog'
4
+ require 'eventmachine'
5
+ require 'right_popen'
6
+
7
+ class CukeJob
8
+ attr_accessor :status, :output, :logfile, :deployment, :rest_log, :no_resume
9
+
10
+ def link_to_rightscale
11
+ i = deployment.href.split(/\//).last
12
+ d = deployment.href.split(/\./).first.split(/\//).last
13
+ "https://#{d}.rightscale.com/deployments/#{i}#auditentries"
14
+ end
15
+
16
+ def on_read_stdout(data)
17
+ # @output ||= ""
18
+ # @output << data
19
+ File.open(@logfile, "a") { |f| f.write(data) }
20
+ end
21
+
22
+ def on_read_stderr(data)
23
+ # @output ||= ""
24
+ # @output << data
25
+ File.open(@logfile, "a") { |f| f.write(data) }
26
+ end
27
+
28
+ def receive_data data
29
+ # @output += data
30
+ File.open(@logfile, "a") { |f| f.write(data) }
31
+ end
32
+
33
+ def unbind
34
+ @status = get_status.exitstatus
35
+ end
36
+
37
+ def on_exit(status)
38
+ @status = status.exitstatus
39
+ # File.open(@logfile, "a") { |f| f.write(@output) }
40
+ end
41
+
42
+ def run(deployment, cmd)
43
+ RightScale.popen3(:command => cmd,
44
+ :target => self,
45
+ :environment => {"DEPLOYMENT" => deployment.nickname,
46
+ "AWS_ACCESS_KEY_ID" => Fog.credentials[:aws_access_key_id],
47
+ "AWS_SECRET_ACCESS_KEY" => Fog.credentials[:aws_secret_access_key],
48
+ "REST_CONNECTION_LOG" => @rest_log,
49
+ "MONKEY_NO_RESUME" => "#{@no_resume}",
50
+ "MONKEY_NO_DEBUG" => "true"},
51
+ :stdout_handler => :on_read_stdout,
52
+ :stderr_handler => :on_read_stderr,
53
+ :exit_handler => :on_exit)
54
+ end
55
+ end
56
+
57
+ class CukeMonk
58
+ attr_accessor :jobs
59
+ attr_accessor :options
60
+ # Runs a cucumber test on a single Deployment
61
+ # * deployment<~String> the nickname of the deployment
62
+ # * feature<~String> the feature filename
63
+ def run_test(deployment, feature, break_point = 1000000)
64
+ new_job = CukeJob.new
65
+ new_job.logfile = File.join(@log_dir, "#{deployment.nickname}.log")
66
+ new_job.rest_log = "#{@log_dir}/#{deployment.nickname}.rest_connection.log"
67
+ new_job.deployment = deployment
68
+ new_job.no_resume = "true" if @options[:no_resume]
69
+ break_point = @options[:breakpoint] if @options[:breakpoint]
70
+ cmd = "bin/grinder #{feature} #{break_point}"
71
+ @jobs << new_job
72
+ puts "running #{cmd}"
73
+ new_job.run(deployment, cmd)
74
+ end
75
+
76
+ def initialize()
77
+ @jobs = []
78
+ @passed = []
79
+ @failed = []
80
+ @running = []
81
+ dirname = Time.now.strftime("%Y/%m/%d/%H-%M-%S")
82
+ @log_dir = File.join("log", dirname)
83
+ @log_started = dirname
84
+ FileUtils.mkdir_p(@log_dir)
85
+ @feature_dir = File.join(File.dirname(__FILE__), '..', '..', 'features')
86
+ end
87
+
88
+ # runs a feature on an array of deployments
89
+ # * deployments<~Array> array of strings containing the nicknames of the deployments
90
+ # * feature_name<~String> the feature filename
91
+ def run_tests(deployments,cmd)
92
+ deployments.each { |d| run_test(d,cmd) }
93
+ end
94
+
95
+ def watch_and_report
96
+ old_passed = @passed
97
+ old_failed = @failed
98
+ old_running = @running
99
+ old_sum = old_passed.size + old_failed.size + old_running.size
100
+ @passed = @jobs.select { |s| s.status == 0 }
101
+ @failed = @jobs.select { |s| s.status == 1 }
102
+ @running = @jobs.select { |s| s.status == nil }
103
+ new_sum = @passed.size + @failed.size + @running.size
104
+ puts "#{@passed.size} features passed. #{@failed.size} features failed. #{@running.size} features running."
105
+ if new_sum < old_sum and new_sum < @jobs.size
106
+ puts "WARNING: Jobs Lost! Finding..."
107
+ report_lost_deployments({ :old_passed => old_passed, :passed => @passed,
108
+ :old_failed => old_failed, :failed => @failed,
109
+ :old_running => old_running, :running => @running })
110
+ end
111
+ if old_passed != @passed || old_failed != @failed
112
+ status_change_hook
113
+ end
114
+ end
115
+
116
+ def status_change_hook
117
+ generate_reports
118
+ if all_done?
119
+ puts "monkey done."
120
+ EM.stop
121
+ end
122
+ end
123
+
124
+ def all_done?
125
+ running = @jobs.select { |s| s.status == nil }
126
+ running.size == 0 && @jobs.size > 0
127
+ end
128
+
129
+ def generate_reports
130
+ passed = @jobs.select { |s| s.status == 0 }
131
+ failed = @jobs.select { |s| s.status == 1 }
132
+ running = @jobs.select { |s| s.status == nil }
133
+ report_on = @jobs.select { |s| s.status == 0 || s.status == 1 }
134
+ index = ERB.new File.read(File.dirname(__FILE__)+"/index.html.erb")
135
+ bucket_name = "virtual_monkey"
136
+
137
+ ## upload to s3
138
+ # setup credentials in ~/.fog
139
+ s3 = Fog::AWS::Storage.new(:aws_access_key_id => Fog.credentials[:aws_access_key_id_test], :aws_secret_access_key => Fog.credentials[:aws_secret_access_key_test])
140
+ if directory = s3.directories.detect { |d| d.key == bucket_name }
141
+ puts "found directory, re-using"
142
+ else
143
+ directory = s3.directories.create(:key => bucket_name)
144
+ end
145
+ raise 'could not create directory' unless directory
146
+ s3.put_object(bucket_name, "#{@log_started}/index.html", index.result(binding), 'x-amz-acl' => 'public-read', 'Content-Type' => 'text/html')
147
+
148
+ report_on.each do |j|
149
+ begin
150
+ done = 0
151
+ s3.put_object(bucket_name, "#{@log_started}/#{File.basename(j.logfile)}", IO.read(j.logfile), 'Content-Type' => 'text/plain', 'x-amz-acl' => 'public-read')
152
+ s3.put_object(bucket_name, "#{@log_started}/#{File.basename(j.rest_log)}", IO.read(j.rest_log), 'Content-Type' => 'text/plain', 'x-amz-acl' => 'public-read')
153
+ done = 1
154
+ rescue Exception => e
155
+ unless e.message =~ /Bad file descriptor/i
156
+ raise e
157
+ end
158
+ sleep 1
159
+ end while not done
160
+ end
161
+
162
+ msg = <<END_OF_MESSAGE
163
+ new results avilable at http://s3.amazonaws.com/#{bucket_name}/#{@log_started}/index.html\n-OR-\nin #{@log_dir}/index.html"
164
+ END_OF_MESSAGE
165
+ puts msg
166
+ end
167
+
168
+ def report_lost_deployments(jobs = {})
169
+ running_change = jobs[:old_running] - jobs[:running]
170
+ passed_change = jobs[:passed] - jobs[:old_passed]
171
+ failed_change = jobs[:failed] - jobs[:old_failed]
172
+ lost_jobs = running_change - passed_change - failed_change
173
+ lost_jobs.each do |j|
174
+ puts "LOST JOB---------------------------------"
175
+ puts "Deployment Name: #{j.deployment.nickname}"
176
+ puts "Status Code: #{j.status}"
177
+ puts "Audit Entries: #{j.link_to_rightscale}"
178
+ puts "Log File: #{j.logfile}"
179
+ puts "Rest_Connection Log File: #{j.rest_log}"
180
+ puts "-----------------------------------------"
181
+ end
182
+ end
183
+ end
184
+
@@ -0,0 +1,132 @@
1
+ require 'rubygems'
2
+ require 'rest_connection'
3
+
4
+ class DeploymentMonk
5
+ attr_accessor :common_inputs
6
+ attr_accessor :variables_for_cloud
7
+ attr_accessor :deployments
8
+ attr_reader :tag
9
+
10
+ def from_tag
11
+ variations = Deployment.find_by(:nickname) {|n| n =~ /^#{@tag}/ }
12
+ puts "loading #{variations.size} deployments matching your tag"
13
+ return variations
14
+ end
15
+
16
+ def initialize(tag, server_templates = [], extra_images = [])
17
+ @clouds = ["1","2","3","4", "232"]
18
+ @cloud_names = { "1" => "ec2-east", "2" => "ec2-eu", "3" => "ec2-west", "4" => "ec2-ap", "232" => "rackspace"}
19
+ @tag = tag
20
+ @deployments = from_tag
21
+ @server_templates = []
22
+ @common_inputs = {}
23
+ @variables_for_cloud = {}
24
+ raise "Need either populated deployments or passed in server_template ids" if server_templates.empty? && @deployments.empty?
25
+ if server_templates.empty?
26
+ puts "loading server templates from servers in the first deployment"
27
+ @deployments.first.servers.each do |s|
28
+ server_templates << s.server_template_href.split(/\//).last.to_i
29
+ end
30
+ end
31
+ server_templates.each do |st|
32
+ @server_templates << ServerTemplate.find(st.to_i)
33
+ end
34
+
35
+ @image_count = 0
36
+ @server_templates.each do |st|
37
+ new_st = ServerTemplateInternal.new(:href => st.href)
38
+ st.multi_cloud_images = new_st.multi_cloud_images
39
+ @image_count = st.multi_cloud_images.size if st.multi_cloud_images.size > @image_count
40
+ end
41
+ end
42
+
43
+ def generate_variations(options = {})
44
+ if options[:mci_override] && !options[:mci_override].empty?
45
+ @image_count = options[:mci_override].size
46
+ end
47
+ @image_count.times do |index|
48
+ @clouds.each do |cloud|
49
+ if @variables_for_cloud[cloud] == nil
50
+ puts "variables not found for cloud #{cloud} skipping.."
51
+ next
52
+ end
53
+ dep_tempname = "#{@tag}-#{@cloud_names[cloud]}-#{rand(1000000)}-"
54
+ dep_image_list = []
55
+ new_deploy = Deployment.create(:nickname => dep_tempname)
56
+ @deployments << new_deploy
57
+ @server_templates.each do |st|
58
+ server_params = { :nickname => "tempserver-#{rand(1000000)}-#{st.nickname}",
59
+ :deployment_href => new_deploy.href,
60
+ :server_template_href => st.href,
61
+ :cloud_id => cloud
62
+ #:ec2_image_href => image['image_href'],
63
+ #:instance_type => image['aws_instance_type']
64
+ }
65
+
66
+ server = Server.create(server_params.merge(@variables_for_cloud[cloud]))
67
+ # since the create call does not set the parameters, we need to set them separate
68
+ if server.respond_to?(:set_inputs)
69
+ server.set_inputs(@variables_for_cloud[cloud]['parameters'])
70
+ else
71
+ @variables_for_cloud[cloud]['parameters'].each do |key,val|
72
+ server.set_input(key,val)
73
+ end
74
+ end
75
+
76
+ # uses a special internal call for setting the MCI on the server
77
+ if options[:mci_override] && !options[:mci_override].empty?
78
+ use_this_image = options[:mci_override][index]
79
+ dep_image_list << MultiCloudImage.find(options[:mci_override][index]).name.gsub(/ /,'_')
80
+ elsif st.multi_cloud_images[index]
81
+ dep_image_list << st.multi_cloud_images[index]['name'].gsub(/ /,'_')
82
+ use_this_image = st.multi_cloud_images[index]['href']
83
+ else
84
+ use_this_image = st.multi_cloud_images[0]['href']
85
+ end
86
+ #RsInternal.set_server_multi_cloud_image(server.href, use_this_image)
87
+ sint = ServerInternal.new(:href => server.href)
88
+ sint.set_multi_cloud_image(use_this_image)
89
+
90
+ # finally, set the spot price
91
+ unless options[:no_spot]
92
+ server.reload
93
+ server.settings
94
+ if server.ec2_instance_type =~ /small/
95
+ server.max_spot_price = "0.085"
96
+ elsif server.ec2_instance_type =~ /large/
97
+ server.max_spot_price = "0.38"
98
+ end
99
+ server.pricing = "spot"
100
+ server.parameters = {}
101
+ server.save
102
+ end
103
+ end
104
+ new_deploy.nickname = dep_tempname + dep_image_list.uniq.join("_AND_")
105
+ new_deploy.save
106
+ @common_inputs.each do |key,val|
107
+ new_deploy.set_input(key,val)
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ def load_common_inputs(file)
114
+ @common_inputs.merge! JSON.parse(IO.read(file))
115
+ end
116
+
117
+ def destroy_all
118
+ @deployments.each do |v|
119
+ v.reload
120
+ v.servers.each { |s| s.stop }
121
+ end
122
+ @deployments.each { |v| v.destroy }
123
+ @deployments = []
124
+ end
125
+
126
+ def get_deployments
127
+ deployments = []
128
+ @deployments.each { |v| deployments << v.nickname }
129
+ deployments
130
+ end
131
+
132
+ end