engineyard-serverside 1.2.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.
Files changed (220) hide show
  1. data/LICENSE +19 -0
  2. data/bin/engineyard-serverside +10 -0
  3. data/lib/engineyard-serverside.rb +49 -0
  4. data/lib/engineyard-serverside/bundle_installer.rb +4 -0
  5. data/lib/engineyard-serverside/cli.rb +146 -0
  6. data/lib/engineyard-serverside/configuration.rb +130 -0
  7. data/lib/engineyard-serverside/default_maintenance_page.html +29 -0
  8. data/lib/engineyard-serverside/deploy.rb +321 -0
  9. data/lib/engineyard-serverside/deploy_hook.rb +80 -0
  10. data/lib/engineyard-serverside/lockfile_parser.rb +55 -0
  11. data/lib/engineyard-serverside/logged_output.rb +78 -0
  12. data/lib/engineyard-serverside/server.rb +70 -0
  13. data/lib/engineyard-serverside/strategies/git.rb +136 -0
  14. data/lib/engineyard-serverside/task.rb +62 -0
  15. data/lib/engineyard-serverside/version.rb +3 -0
  16. data/lib/vendor/dataflow/HISTORY +52 -0
  17. data/lib/vendor/dataflow/LICENSE +19 -0
  18. data/lib/vendor/dataflow/README.textile +290 -0
  19. data/lib/vendor/dataflow/Rakefile +36 -0
  20. data/lib/vendor/dataflow/dataflow.rb +120 -0
  21. data/lib/vendor/dataflow/dataflow/actor.rb +22 -0
  22. data/lib/vendor/dataflow/dataflow/equality.rb +28 -0
  23. data/lib/vendor/dataflow/dataflow/future_queue.rb +24 -0
  24. data/lib/vendor/dataflow/dataflow/port.rb +54 -0
  25. data/lib/vendor/dataflow/examples/barrier.rb +9 -0
  26. data/lib/vendor/dataflow/examples/data_driven.rb +17 -0
  27. data/lib/vendor/dataflow/examples/dataflow_http_gets.rb +13 -0
  28. data/lib/vendor/dataflow/examples/flow.rb +20 -0
  29. data/lib/vendor/dataflow/examples/future_http_gets.rb +12 -0
  30. data/lib/vendor/dataflow/examples/future_queue.rb +11 -0
  31. data/lib/vendor/dataflow/examples/instance_variables.rb +15 -0
  32. data/lib/vendor/dataflow/examples/laziness.rb +9 -0
  33. data/lib/vendor/dataflow/examples/local_variables.rb +11 -0
  34. data/lib/vendor/dataflow/examples/messages.rb +26 -0
  35. data/lib/vendor/dataflow/examples/port_http_gets.rb +13 -0
  36. data/lib/vendor/dataflow/examples/port_send.rb +10 -0
  37. data/lib/vendor/dataflow/examples/ring.rb +21 -0
  38. data/lib/vendor/dataflow/spec/actor_spec.rb +28 -0
  39. data/lib/vendor/dataflow/spec/anonymous_variables_spec.rb +21 -0
  40. data/lib/vendor/dataflow/spec/barrier_spec.rb +25 -0
  41. data/lib/vendor/dataflow/spec/by_need_spec.rb +55 -0
  42. data/lib/vendor/dataflow/spec/dataflow_spec.rb +151 -0
  43. data/lib/vendor/dataflow/spec/equality_spec.rb +40 -0
  44. data/lib/vendor/dataflow/spec/flow_spec.rb +25 -0
  45. data/lib/vendor/dataflow/spec/forker_spec.rb +28 -0
  46. data/lib/vendor/dataflow/spec/future_queue_spec.rb +31 -0
  47. data/lib/vendor/dataflow/spec/inspect_spec.rb +19 -0
  48. data/lib/vendor/dataflow/spec/need_later_spec.rb +12 -0
  49. data/lib/vendor/dataflow/spec/port_spec.rb +26 -0
  50. data/lib/vendor/dataflow/spec/spec.opts +1 -0
  51. data/lib/vendor/dataflow/spec/spec_helper.rb +10 -0
  52. data/lib/vendor/escape/Readme +21 -0
  53. data/lib/vendor/escape/doc_include/template/qualitysmith.rb +631 -0
  54. data/lib/vendor/escape/lib/escape.rb +247 -0
  55. data/lib/vendor/json_pure/CHANGES +166 -0
  56. data/lib/vendor/json_pure/COPYING +58 -0
  57. data/lib/vendor/json_pure/GPL +340 -0
  58. data/lib/vendor/json_pure/README +358 -0
  59. data/lib/vendor/json_pure/Rakefile +292 -0
  60. data/lib/vendor/json_pure/TODO +1 -0
  61. data/lib/vendor/json_pure/VERSION +1 -0
  62. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkComparison.log +52 -0
  63. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast-autocorrelation.dat +1000 -0
  64. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast.dat +1001 -0
  65. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty-autocorrelation.dat +900 -0
  66. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty.dat +901 -0
  67. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe-autocorrelation.dat +1000 -0
  68. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe.dat +1001 -0
  69. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt.log +261 -0
  70. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast-autocorrelation.dat +1000 -0
  71. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast.dat +1001 -0
  72. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty-autocorrelation.dat +1000 -0
  73. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty.dat +1001 -0
  74. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe-autocorrelation.dat +1000 -0
  75. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe.dat +1001 -0
  76. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure.log +262 -0
  77. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator-autocorrelation.dat +1000 -0
  78. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator.dat +1001 -0
  79. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails.log +82 -0
  80. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkComparison.log +34 -0
  81. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser-autocorrelation.dat +900 -0
  82. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser.dat +901 -0
  83. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt.log +81 -0
  84. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser-autocorrelation.dat +1000 -0
  85. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser.dat +1001 -0
  86. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure.log +82 -0
  87. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser-autocorrelation.dat +1000 -0
  88. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser.dat +1001 -0
  89. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails.log +82 -0
  90. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser-autocorrelation.dat +1000 -0
  91. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser.dat +1001 -0
  92. data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML.log +82 -0
  93. data/lib/vendor/json_pure/benchmarks/generator2_benchmark.rb +222 -0
  94. data/lib/vendor/json_pure/benchmarks/generator_benchmark.rb +224 -0
  95. data/lib/vendor/json_pure/benchmarks/ohai.json +1216 -0
  96. data/lib/vendor/json_pure/benchmarks/ohai.ruby +1 -0
  97. data/lib/vendor/json_pure/benchmarks/parser2_benchmark.rb +251 -0
  98. data/lib/vendor/json_pure/benchmarks/parser_benchmark.rb +259 -0
  99. data/lib/vendor/json_pure/bin/edit_json.rb +9 -0
  100. data/lib/vendor/json_pure/bin/prettify_json.rb +75 -0
  101. data/lib/vendor/json_pure/data/example.json +1 -0
  102. data/lib/vendor/json_pure/data/index.html +38 -0
  103. data/lib/vendor/json_pure/data/prototype.js +4184 -0
  104. data/lib/vendor/json_pure/ext/json/ext/generator/extconf.rb +16 -0
  105. data/lib/vendor/json_pure/ext/json/ext/generator/generator.c +1323 -0
  106. data/lib/vendor/json_pure/ext/json/ext/generator/generator.h +170 -0
  107. data/lib/vendor/json_pure/ext/json/ext/parser/extconf.rb +15 -0
  108. data/lib/vendor/json_pure/ext/json/ext/parser/parser.c +1935 -0
  109. data/lib/vendor/json_pure/ext/json/ext/parser/parser.h +71 -0
  110. data/lib/vendor/json_pure/ext/json/ext/parser/parser.rl +792 -0
  111. data/lib/vendor/json_pure/install.rb +26 -0
  112. data/lib/vendor/json_pure/lib/json.rb +10 -0
  113. data/lib/vendor/json_pure/lib/json/Array.xpm +21 -0
  114. data/lib/vendor/json_pure/lib/json/FalseClass.xpm +21 -0
  115. data/lib/vendor/json_pure/lib/json/Hash.xpm +21 -0
  116. data/lib/vendor/json_pure/lib/json/Key.xpm +73 -0
  117. data/lib/vendor/json_pure/lib/json/NilClass.xpm +21 -0
  118. data/lib/vendor/json_pure/lib/json/Numeric.xpm +28 -0
  119. data/lib/vendor/json_pure/lib/json/String.xpm +96 -0
  120. data/lib/vendor/json_pure/lib/json/TrueClass.xpm +21 -0
  121. data/lib/vendor/json_pure/lib/json/add/core.rb +148 -0
  122. data/lib/vendor/json_pure/lib/json/add/rails.rb +58 -0
  123. data/lib/vendor/json_pure/lib/json/common.rb +397 -0
  124. data/lib/vendor/json_pure/lib/json/editor.rb +1371 -0
  125. data/lib/vendor/json_pure/lib/json/ext.rb +15 -0
  126. data/lib/vendor/json_pure/lib/json/json.xpm +1499 -0
  127. data/lib/vendor/json_pure/lib/json/pure.rb +77 -0
  128. data/lib/vendor/json_pure/lib/json/pure/generator.rb +452 -0
  129. data/lib/vendor/json_pure/lib/json/pure/parser.rb +307 -0
  130. data/lib/vendor/json_pure/lib/json/version.rb +8 -0
  131. data/lib/vendor/json_pure/tests/fixtures/fail1.json +1 -0
  132. data/lib/vendor/json_pure/tests/fixtures/fail10.json +1 -0
  133. data/lib/vendor/json_pure/tests/fixtures/fail11.json +1 -0
  134. data/lib/vendor/json_pure/tests/fixtures/fail12.json +1 -0
  135. data/lib/vendor/json_pure/tests/fixtures/fail13.json +1 -0
  136. data/lib/vendor/json_pure/tests/fixtures/fail14.json +1 -0
  137. data/lib/vendor/json_pure/tests/fixtures/fail18.json +1 -0
  138. data/lib/vendor/json_pure/tests/fixtures/fail19.json +1 -0
  139. data/lib/vendor/json_pure/tests/fixtures/fail2.json +1 -0
  140. data/lib/vendor/json_pure/tests/fixtures/fail20.json +1 -0
  141. data/lib/vendor/json_pure/tests/fixtures/fail21.json +1 -0
  142. data/lib/vendor/json_pure/tests/fixtures/fail22.json +1 -0
  143. data/lib/vendor/json_pure/tests/fixtures/fail23.json +1 -0
  144. data/lib/vendor/json_pure/tests/fixtures/fail24.json +1 -0
  145. data/lib/vendor/json_pure/tests/fixtures/fail25.json +1 -0
  146. data/lib/vendor/json_pure/tests/fixtures/fail27.json +2 -0
  147. data/lib/vendor/json_pure/tests/fixtures/fail28.json +2 -0
  148. data/lib/vendor/json_pure/tests/fixtures/fail3.json +1 -0
  149. data/lib/vendor/json_pure/tests/fixtures/fail4.json +1 -0
  150. data/lib/vendor/json_pure/tests/fixtures/fail5.json +1 -0
  151. data/lib/vendor/json_pure/tests/fixtures/fail6.json +1 -0
  152. data/lib/vendor/json_pure/tests/fixtures/fail7.json +1 -0
  153. data/lib/vendor/json_pure/tests/fixtures/fail8.json +1 -0
  154. data/lib/vendor/json_pure/tests/fixtures/fail9.json +1 -0
  155. data/lib/vendor/json_pure/tests/fixtures/pass1.json +56 -0
  156. data/lib/vendor/json_pure/tests/fixtures/pass15.json +1 -0
  157. data/lib/vendor/json_pure/tests/fixtures/pass16.json +1 -0
  158. data/lib/vendor/json_pure/tests/fixtures/pass17.json +1 -0
  159. data/lib/vendor/json_pure/tests/fixtures/pass2.json +1 -0
  160. data/lib/vendor/json_pure/tests/fixtures/pass26.json +1 -0
  161. data/lib/vendor/json_pure/tests/fixtures/pass3.json +6 -0
  162. data/lib/vendor/json_pure/tests/test_json.rb +361 -0
  163. data/lib/vendor/json_pure/tests/test_json_addition.rb +162 -0
  164. data/lib/vendor/json_pure/tests/test_json_encoding.rb +68 -0
  165. data/lib/vendor/json_pure/tests/test_json_fixtures.rb +34 -0
  166. data/lib/vendor/json_pure/tests/test_json_generate.rb +122 -0
  167. data/lib/vendor/json_pure/tests/test_json_rails.rb +144 -0
  168. data/lib/vendor/json_pure/tests/test_json_unicode.rb +76 -0
  169. data/lib/vendor/json_pure/tools/fuzz.rb +139 -0
  170. data/lib/vendor/json_pure/tools/server.rb +61 -0
  171. data/lib/vendor/open4/lib/open4.rb +403 -0
  172. data/lib/vendor/thor/CHANGELOG.rdoc +89 -0
  173. data/lib/vendor/thor/LICENSE +20 -0
  174. data/lib/vendor/thor/README.rdoc +297 -0
  175. data/lib/vendor/thor/Thorfile +69 -0
  176. data/lib/vendor/thor/bin/rake2thor +86 -0
  177. data/lib/vendor/thor/bin/thor +6 -0
  178. data/lib/vendor/thor/lib/thor.rb +244 -0
  179. data/lib/vendor/thor/lib/thor/actions.rb +275 -0
  180. data/lib/vendor/thor/lib/thor/actions/create_file.rb +103 -0
  181. data/lib/vendor/thor/lib/thor/actions/directory.rb +91 -0
  182. data/lib/vendor/thor/lib/thor/actions/empty_directory.rb +134 -0
  183. data/lib/vendor/thor/lib/thor/actions/file_manipulation.rb +223 -0
  184. data/lib/vendor/thor/lib/thor/actions/inject_into_file.rb +104 -0
  185. data/lib/vendor/thor/lib/thor/base.rb +540 -0
  186. data/lib/vendor/thor/lib/thor/core_ext/file_binary_read.rb +9 -0
  187. data/lib/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +75 -0
  188. data/lib/vendor/thor/lib/thor/core_ext/ordered_hash.rb +100 -0
  189. data/lib/vendor/thor/lib/thor/error.rb +30 -0
  190. data/lib/vendor/thor/lib/thor/group.rb +271 -0
  191. data/lib/vendor/thor/lib/thor/invocation.rb +180 -0
  192. data/lib/vendor/thor/lib/thor/parser.rb +4 -0
  193. data/lib/vendor/thor/lib/thor/parser/argument.rb +67 -0
  194. data/lib/vendor/thor/lib/thor/parser/arguments.rb +150 -0
  195. data/lib/vendor/thor/lib/thor/parser/option.rb +128 -0
  196. data/lib/vendor/thor/lib/thor/parser/options.rb +169 -0
  197. data/lib/vendor/thor/lib/thor/rake_compat.rb +66 -0
  198. data/lib/vendor/thor/lib/thor/runner.rb +314 -0
  199. data/lib/vendor/thor/lib/thor/shell.rb +83 -0
  200. data/lib/vendor/thor/lib/thor/shell/basic.rb +239 -0
  201. data/lib/vendor/thor/lib/thor/shell/color.rb +108 -0
  202. data/lib/vendor/thor/lib/thor/task.rb +102 -0
  203. data/lib/vendor/thor/lib/thor/util.rb +230 -0
  204. data/lib/vendor/thor/lib/thor/version.rb +3 -0
  205. data/lib/vendor/thor/thor.gemspec +120 -0
  206. data/spec/custom_deploy_spec.rb +95 -0
  207. data/spec/deploy_hook_spec.rb +211 -0
  208. data/spec/fixtures/gitrepo.tar.gz +0 -0
  209. data/spec/fixtures/gitrepo/foo +0 -0
  210. data/spec/fixtures/invalid_hook.rb +1 -0
  211. data/spec/fixtures/valid_hook.rb +1 -0
  212. data/spec/git_strategy_spec.rb +22 -0
  213. data/spec/lockfile_parser_spec.rb +30 -0
  214. data/spec/spec_helper.rb +37 -0
  215. data/spec/support/lockfiles/0.9-no-bundler +111 -0
  216. data/spec/support/lockfiles/0.9-with-bundler +117 -0
  217. data/spec/support/lockfiles/1.0-no-bundler +54 -0
  218. data/spec/support/lockfiles/1.0.0.rc.1-with-bundler +162 -0
  219. data/spec/support/lockfiles/not-a-lockfile +10 -0
  220. metadata +279 -0
@@ -0,0 +1,80 @@
1
+ module EY
2
+ class DeployHook < Task
3
+ def initialize(options)
4
+ super(EY::Deploy::Configuration.new(options))
5
+ end
6
+
7
+ def callback_context
8
+ @context ||= CallbackContext.new(config)
9
+ end
10
+
11
+ def run(hook)
12
+ hook_path = "#{c.release_path}/deploy/#{hook}.rb"
13
+ if File.exist?(hook_path)
14
+ Dir.chdir(c.release_path) do
15
+ puts "~> running deploy hook: deploy/#{hook}.rb"
16
+ if desc = syntax_error(hook_path)
17
+ hook_name = File.basename(hook_path)
18
+ abort "*** [Error] Invalid Ruby syntax in hook: #{hook_name} ***\n*** #{desc.chomp} ***"
19
+ else
20
+ callback_context.instance_eval(IO.read(hook_path))
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ def syntax_error(file)
27
+ valid = Kernel.system("ruby -c #{file} 2>/tmp/ey_invalid_deploy_hook | grep 'Syntax OK' --quiet")
28
+ File.new("/tmp/ey_invalid_deploy_hook").gets unless valid
29
+ end
30
+
31
+ class CallbackContext
32
+ def initialize(config)
33
+ @configuration = config
34
+ @node = node
35
+ end
36
+
37
+ def method_missing(meth, *args, &blk)
38
+ if @configuration.respond_to?(meth)
39
+ @configuration.send(meth, *args, &blk)
40
+ else
41
+ super
42
+ end
43
+ end
44
+
45
+ def respond_to?(meth, include_private=false)
46
+ @configuration.respond_to?(meth, include_private) || super
47
+ end
48
+
49
+ def run(cmd)
50
+ system(Escape.shell_command(["sh", "-l", "-c", cmd]))
51
+ end
52
+
53
+ def sudo(cmd)
54
+ system(Escape.shell_command(["sudo", "sh", "-l", "-c", cmd]))
55
+ end
56
+
57
+ # convenience functions for running on certain instance types
58
+ def on_app_master(&blk) on_roles(%w[solo app_master], &blk) end
59
+ def on_app_servers(&blk) on_roles(%w[solo app_master app], &blk) end
60
+ def on_db_master(&blk) on_roles(%w[solo db_master], &blk) end
61
+ def on_db_slaves(&blk) on_roles(%w[db_slave], &blk) end
62
+ def on_db_servers(&blk) on_roles(%w[solo db_master db_slave], &blk) end
63
+ def on_app_servers_and_utilities(&blk) on_roles(%w[solo app_master app util], &blk) end
64
+
65
+ def on_utilities(*names, &blk)
66
+ names.flatten!
67
+ on_roles(%w[util]) do
68
+ blk.call if names.empty? || names.include?(current_name)
69
+ end
70
+ end
71
+
72
+ private
73
+ def on_roles(desired_roles)
74
+ yield if desired_roles.include?(current_role.to_s)
75
+ end
76
+
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,55 @@
1
+ require 'yaml'
2
+ module EY
3
+ class LockfileParser
4
+
5
+ attr_reader :bundler_version, :lockfile_version
6
+
7
+ def initialize(lockfile_contents)
8
+ @contents = lockfile_contents
9
+ @lockfile_version, @bundler_version = parse
10
+ end
11
+
12
+ private
13
+ def parse
14
+ from_yaml = safe_yaml_load(@contents)
15
+ if from_yaml # 0.9
16
+ bundler_version = from_yaml['specs'].map do |spec|
17
+ # spec is a one-element hash: the key is the gem name, and
18
+ # the value is {"version" => the-version}.
19
+ if spec.keys.first == "bundler"
20
+ spec.values.first["version"]
21
+ end
22
+ end.compact.first
23
+ [:bundler09, bundler_version]
24
+ else # 1.0 or bust
25
+ dep_section = ""
26
+ in_dependencies_section = false
27
+ @contents.each_line do |line|
28
+ if line =~ /^DEPENDENCIES/
29
+ in_dependencies_section = true
30
+ elsif line =~ /^\S/
31
+ in_dependencies_section = false
32
+ elsif in_dependencies_section
33
+ dep_section << line
34
+ end
35
+ end
36
+
37
+ unless dep_section.length > 0
38
+ raise "Couldn't parse #{lockfile}; exiting"
39
+ exit(1)
40
+ end
41
+
42
+ result = dep_section.scan(/^\s*bundler\s*\(=\s*([^\)]+)\)/).first
43
+ bundler_version = result ? result.first : nil
44
+ [:bundler10, bundler_version]
45
+ end
46
+ end
47
+
48
+ def safe_yaml_load(loadable)
49
+ YAML.load(loadable)
50
+ rescue ArgumentError # not yaml
51
+ nil
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,78 @@
1
+ require 'open4'
2
+
3
+ module EY
4
+ module LoggedOutput
5
+
6
+ class Tee
7
+ def initialize(*streams)
8
+ @streams = streams.flatten
9
+ end
10
+
11
+ def <<(output)
12
+ @streams.each do |s|
13
+ s << output
14
+ s.flush
15
+ end
16
+ self
17
+ end
18
+ end # Tee
19
+
20
+ @@logfile = File.join(ENV['HOME'], 'ey.log')
21
+ def self.logfile=(filename)
22
+ File.unlink filename if File.exist?(filename) # start fresh
23
+ @@logfile = filename
24
+ end
25
+
26
+ def self.logfile
27
+ @@logfile
28
+ end
29
+
30
+ @@verbose = false
31
+ def self.verbose=(v)
32
+ @@verbose = !!v
33
+ end
34
+
35
+ def self.verbose?
36
+ @@verbose
37
+ end
38
+
39
+ def verbose?
40
+ EY::LoggedOutput.verbose?
41
+ end
42
+
43
+ def info(msg)
44
+ with_logfile do |log|
45
+ Tee.new($stdout, log) << (msg + "\n")
46
+ end
47
+ end
48
+
49
+ def debug(msg)
50
+ with_logfile do |log|
51
+ log << "#{msg}\n"
52
+ end
53
+ end
54
+
55
+ def logged_system(cmd)
56
+ with_logfile do |log|
57
+ out = verbose? ? Tee.new($stdout, log) : log
58
+ err = Tee.new($stderr, log) # we always want to see errors
59
+
60
+ out << ":: running #{cmd}\n"
61
+
62
+ # :quiet means don't raise an error on nonzero exit status
63
+ status = Open4.spawn cmd, 0 => '', 1 => out, 2 => err, :quiet => true
64
+ status.exitstatus == 0
65
+ end
66
+ end
67
+
68
+ private
69
+ def with_logfile
70
+ File.open(logfile, 'a') {|f| yield f }
71
+ end
72
+
73
+ def logfile
74
+ EY::LoggedOutput.logfile
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,70 @@
1
+ require 'open-uri'
2
+ require 'engineyard-serverside/logged_output'
3
+
4
+ module EY
5
+ class Server < Struct.new(:hostname, :role, :name)
6
+ include LoggedOutput
7
+
8
+ def initialize(*fields)
9
+ super
10
+ self.role = self.role.to_sym
11
+ end
12
+
13
+ def self.config=(config)
14
+ @@config = config
15
+ end
16
+
17
+ def config
18
+ @@config
19
+ end
20
+
21
+ attr_writer :default_task
22
+
23
+ def self.from_roles(*roles)
24
+ roles = roles.flatten.compact
25
+ return all if !roles || roles.include?(:all) || roles.empty?
26
+
27
+ all.select do |s|
28
+ roles.include?(s.role) || roles.include?(s.name)
29
+ end
30
+ end
31
+
32
+ def self.from_hash(h)
33
+ new(h[:hostname], h[:role], h[:name])
34
+ end
35
+
36
+ def self.all
37
+ @all
38
+ end
39
+
40
+ def self.all=(server_hashes)
41
+ @all = server_hashes.map { |s| from_hash(s) }
42
+ end
43
+
44
+ def self.current
45
+ all.find {|s| s.local? }
46
+ end
47
+
48
+ def local?
49
+ [:app_master, :solo].include?(role)
50
+ end
51
+
52
+ def push_code
53
+ return if local?
54
+ run "mkdir -p #{config.repository_cache}"
55
+ logged_system(%|rsync --delete -aq -e "#{ssh_command}" #{config.repository_cache}/ #{config.user}@#{hostname}:#{config.repository_cache}|)
56
+ end
57
+
58
+ def run(command)
59
+ if local?
60
+ logged_system(command)
61
+ else
62
+ logged_system(ssh_command + " " + Escape.shell_command(["#{config.user}@#{hostname}", command]))
63
+ end
64
+ end
65
+
66
+ def ssh_command
67
+ "ssh -i #{ENV['HOME']}/.ssh/internal -o StrictHostKeyChecking=no -o PasswordAuthentication=no"
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,136 @@
1
+ require 'engineyard-serverside/logged_output'
2
+
3
+ module EY
4
+ module Strategies
5
+ class Git
6
+ module Helpers
7
+ def update_repository_cache
8
+ strategy.fetch
9
+ unless strategy.checkout
10
+ abort "*** [Error] Git could not checkout (#{strategy.to_checkout}) ***"
11
+ end
12
+ end
13
+
14
+ def create_revision_file_command
15
+ strategy.create_revision_file_command(c.release_path)
16
+ end
17
+
18
+ def short_log_message(revision)
19
+ strategy.short_log_message(revision)
20
+ end
21
+
22
+ def strategy
23
+ klass = Module.nesting[1]
24
+ # Use [] to access attributes instead of calling methods so
25
+ # that we get nils instead of NoMethodError.
26
+ #
27
+ # Rollback doesn't know about the repository location (nor
28
+ # should it need to), but it would like to use #short_log_message.
29
+ klass.new(
30
+ :repository_cache => c[:repository_cache],
31
+ :app => c[:app],
32
+ :repo => c[:repo],
33
+ :ref => c[:branch]
34
+ )
35
+ end
36
+ end
37
+
38
+ include LoggedOutput
39
+
40
+ attr_reader :opts
41
+
42
+ def initialize(opts)
43
+ @opts = opts
44
+ set_up_git_ssh(@opts[:app])
45
+ end
46
+
47
+ def usable_repository?
48
+ File.directory?(opts[:repository_cache]) && `#{git} remote -v | grep origin`[opts[:repo]]
49
+ end
50
+
51
+ def fetch
52
+ if usable_repository?
53
+ logged_system("#{git} fetch -q origin 2>&1")
54
+ else
55
+ FileUtils.rm_rf(opts[:repository_cache])
56
+ logged_system("git clone -q #{opts[:repo]} #{opts[:repository_cache]} 2>&1")
57
+ end
58
+ end
59
+
60
+ def checkout
61
+ info "~> Deploying revision #{short_log_message(to_checkout)}"
62
+ in_git_work_tree do
63
+ (logged_system("git checkout -q '#{to_checkout}'") ||
64
+ logged_system("git reset -q --hard '#{to_checkout}'")) &&
65
+ logged_system("git submodule update --init") &&
66
+ logged_system("git clean -dfq")
67
+ end
68
+ end
69
+
70
+ def to_checkout
71
+ return @to_checkout if @opts_ref == opts[:ref]
72
+ @opts_ref = opts[:ref]
73
+ @to_checkout = if branch?(opts[:ref])
74
+ "origin/#{opts[:ref]}"
75
+ else
76
+ opts[:ref]
77
+ end
78
+ end
79
+
80
+ def create_revision_file_command(dir)
81
+ %Q{#{git} show --pretty=format:"%H" | head -1 > "#{dir}/REVISION"}
82
+ end
83
+
84
+ def short_log_message(rev)
85
+ `#{git} log --pretty=oneline --abbrev-commit '#{rev}^..#{rev}'`.strip
86
+ end
87
+
88
+ private
89
+ def in_git_work_tree
90
+ Dir.chdir(git_work_tree) { yield }
91
+ end
92
+
93
+ def git_work_tree
94
+ opts[:repository_cache]
95
+ end
96
+
97
+ def git
98
+ "git --git-dir #{git_work_tree}/.git --work-tree #{git_work_tree}"
99
+ end
100
+
101
+ def branch?(ref)
102
+ `#{git} branch -r`.map { |x| x.strip }.include?("origin/#{ref}")
103
+ end
104
+
105
+ def set_up_git_ssh(app)
106
+ # hold references to the tempfiles so they don't get finalized
107
+ # unexpectedly; tempfile finalization unlinks the files
108
+ @git_ssh = Tempfile.open("git-ssh")
109
+ @config = Tempfile.open("git-ssh-config")
110
+
111
+ @config.write "StrictHostKeyChecking no\n"
112
+ @config.write "CheckHostIP no\n"
113
+ @config.write "PasswordAuthentication no\n"
114
+ @config.write "LogLevel DEBUG\n"
115
+ @config.write "IdentityFile ~/.ssh/#{app}-deploy-key\n"
116
+ @config.chmod(0600)
117
+ @config.close
118
+
119
+ @git_ssh.write "#!/bin/sh\n"
120
+ @git_ssh.write "unset SSH_AUTH_SOCK\n"
121
+ @git_ssh.write "ssh -F \"#{@config.path}\" $*\n"
122
+ @git_ssh.chmod(0700)
123
+ # NB: this file _must_ be closed before git looks at it.
124
+ #
125
+ # Linux won't let you execve a file that's open for writing,
126
+ # so if this file stays open, then git will complain about
127
+ # being unable to exec it and will exit with a message like
128
+ #
129
+ # fatal: exec /tmp/git-ssh20100417-21417-d040rm-0 failed.
130
+ @git_ssh.close
131
+
132
+ ENV['GIT_SSH'] = @git_ssh.path
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,62 @@
1
+ module EY
2
+ class Task
3
+ include Dataflow
4
+
5
+ attr_reader :config
6
+ alias :c :config
7
+
8
+ def initialize(conf)
9
+ @config = conf
10
+ @roles = :all
11
+ end
12
+
13
+ def require_custom_tasks
14
+ deploy_file = ["config/eydeploy.rb", "eydeploy.rb"].map do |short_file|
15
+ File.join(c.repository_cache, short_file)
16
+ end.detect do |file|
17
+ File.exist?(file)
18
+ end
19
+
20
+ if deploy_file
21
+ puts "~> Loading deployment task overrides from #{deploy_file}"
22
+ instance_eval(File.read(deploy_file))
23
+ true
24
+ else
25
+ false
26
+ end
27
+ end
28
+
29
+ def roles(*task_roles)
30
+ raise "Roles must be passed a block" unless block_given?
31
+
32
+ begin
33
+ @roles = task_roles
34
+ yield
35
+ ensure
36
+ @roles = :all
37
+ end
38
+ end
39
+
40
+ def run(cmd, &blk)
41
+ run_on_roles(cmd, &blk)
42
+ end
43
+
44
+ def sudo(cmd, &blk)
45
+ run_on_roles(cmd, %w[sudo sh -l -c], &blk)
46
+ end
47
+
48
+ private
49
+
50
+ def run_on_roles(cmd, wrapper=%w[sh -l -c])
51
+ results = EY::Server.from_roles(@roles).map do |server|
52
+ to_run = block_given? ? yield(server, cmd.dup) : cmd
53
+ need_later { server.run(Escape.shell_command(wrapper + [to_run])) }
54
+ end
55
+ barrier *results
56
+ # MRI's truthiness check is an internal C thing that does not call
57
+ # any methods... so Dataflow cannot proxy it & we must "x == true"
58
+ # Rubinius, wherefore art thou!?
59
+ results.all?{|x| x == true } || raise(EY::RemoteFailure)
60
+ end
61
+ end
62
+ end