capistrano 2.8.0 → 3.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (239) hide show
  1. checksums.yaml +7 -0
  2. data/.docker/Dockerfile +7 -0
  3. data/.docker/ssh_key_rsa +49 -0
  4. data/.docker/ssh_key_rsa.pub +1 -0
  5. data/.docker/ubuntu_setup.sh +23 -0
  6. data/.github/issue_template.md +19 -0
  7. data/.github/pull_request_template.md +22 -0
  8. data/.github/release-drafter.yml +25 -0
  9. data/.github/workflows/ci.yml +80 -0
  10. data/.github/workflows/release-drafter.yml +18 -0
  11. data/.gitignore +23 -8
  12. data/.rubocop.yml +62 -0
  13. data/CHANGELOG.md +1 -0
  14. data/CONTRIBUTING.md +63 -0
  15. data/DEVELOPMENT.md +112 -0
  16. data/Gemfile +42 -9
  17. data/LICENSE.txt +21 -0
  18. data/README.md +221 -0
  19. data/RELEASING.md +17 -0
  20. data/Rakefile +17 -8
  21. data/UPGRADING-3.7.md +86 -0
  22. data/bin/cap +2 -3
  23. data/bin/capify +7 -89
  24. data/capistrano.gemspec +29 -43
  25. data/docker-compose.yml +8 -0
  26. data/features/configuration.feature +28 -0
  27. data/features/deploy.feature +92 -0
  28. data/features/deploy_failure.feature +17 -0
  29. data/features/doctor.feature +11 -0
  30. data/features/installation.feature +21 -0
  31. data/features/sshconnect.feature +11 -0
  32. data/features/stage_failure.feature +9 -0
  33. data/features/step_definitions/assertions.rb +162 -0
  34. data/features/step_definitions/cap_commands.rb +21 -0
  35. data/features/step_definitions/setup.rb +91 -0
  36. data/features/subdirectory.feature +9 -0
  37. data/features/support/docker_gateway.rb +53 -0
  38. data/features/support/env.rb +1 -0
  39. data/features/support/remote_command_helpers.rb +29 -0
  40. data/features/support/remote_ssh_helpers.rb +33 -0
  41. data/lib/Capfile +3 -0
  42. data/lib/capistrano/all.rb +17 -0
  43. data/lib/capistrano/application.rb +153 -0
  44. data/lib/capistrano/configuration/empty_filter.rb +9 -0
  45. data/lib/capistrano/configuration/filter.rb +26 -0
  46. data/lib/capistrano/configuration/host_filter.rb +29 -0
  47. data/lib/capistrano/configuration/null_filter.rb +9 -0
  48. data/lib/capistrano/configuration/plugin_installer.rb +51 -0
  49. data/lib/capistrano/configuration/question.rb +76 -0
  50. data/lib/capistrano/configuration/role_filter.rb +29 -0
  51. data/lib/capistrano/configuration/scm_resolver.rb +149 -0
  52. data/lib/capistrano/configuration/server.rb +137 -0
  53. data/lib/capistrano/configuration/servers.rb +56 -96
  54. data/lib/capistrano/configuration/validated_variables.rb +110 -0
  55. data/lib/capistrano/configuration/variables.rb +79 -94
  56. data/lib/capistrano/configuration.rb +178 -33
  57. data/lib/capistrano/console.rb +1 -0
  58. data/lib/capistrano/defaults.rb +36 -0
  59. data/lib/capistrano/deploy.rb +3 -0
  60. data/lib/capistrano/doctor/environment_doctor.rb +19 -0
  61. data/lib/capistrano/doctor/gems_doctor.rb +45 -0
  62. data/lib/capistrano/doctor/output_helpers.rb +79 -0
  63. data/lib/capistrano/doctor/servers_doctor.rb +105 -0
  64. data/lib/capistrano/doctor/variables_doctor.rb +74 -0
  65. data/lib/capistrano/doctor.rb +6 -0
  66. data/lib/capistrano/dotfile.rb +2 -0
  67. data/lib/capistrano/dsl/env.rb +43 -0
  68. data/lib/capistrano/dsl/paths.rb +89 -0
  69. data/lib/capistrano/dsl/stages.rb +31 -0
  70. data/lib/capistrano/dsl/task_enhancements.rb +61 -0
  71. data/lib/capistrano/dsl.rb +95 -0
  72. data/lib/capistrano/framework.rb +2 -0
  73. data/lib/capistrano/i18n.rb +46 -0
  74. data/lib/capistrano/immutable_task.rb +30 -0
  75. data/lib/capistrano/install.rb +1 -0
  76. data/lib/capistrano/plugin.rb +95 -0
  77. data/lib/capistrano/proc_helpers.rb +13 -0
  78. data/lib/capistrano/scm/git.rb +105 -0
  79. data/lib/capistrano/scm/hg.rb +55 -0
  80. data/lib/capistrano/scm/plugin.rb +13 -0
  81. data/lib/capistrano/scm/svn.rb +56 -0
  82. data/lib/capistrano/scm/tasks/git.rake +84 -0
  83. data/lib/capistrano/scm/tasks/hg.rake +53 -0
  84. data/lib/capistrano/scm/tasks/svn.rake +53 -0
  85. data/lib/capistrano/scm.rb +115 -0
  86. data/lib/capistrano/setup.rb +36 -0
  87. data/lib/capistrano/tasks/console.rake +25 -0
  88. data/lib/capistrano/tasks/deploy.rake +280 -0
  89. data/lib/capistrano/tasks/doctor.rake +24 -0
  90. data/lib/capistrano/tasks/framework.rake +67 -0
  91. data/lib/capistrano/tasks/install.rake +41 -0
  92. data/lib/capistrano/templates/Capfile +38 -0
  93. data/lib/capistrano/templates/deploy.rb.erb +39 -0
  94. data/lib/capistrano/templates/stage.rb.erb +61 -0
  95. data/lib/capistrano/upload_task.rb +9 -0
  96. data/lib/capistrano/version.rb +1 -14
  97. data/lib/capistrano/version_validator.rb +32 -0
  98. data/lib/capistrano.rb +0 -3
  99. data/spec/integration/dsl_spec.rb +632 -0
  100. data/spec/integration_spec_helper.rb +5 -0
  101. data/spec/lib/capistrano/application_spec.rb +60 -0
  102. data/spec/lib/capistrano/configuration/empty_filter_spec.rb +17 -0
  103. data/spec/lib/capistrano/configuration/filter_spec.rb +109 -0
  104. data/spec/lib/capistrano/configuration/host_filter_spec.rb +71 -0
  105. data/spec/lib/capistrano/configuration/null_filter_spec.rb +17 -0
  106. data/spec/lib/capistrano/configuration/plugin_installer_spec.rb +98 -0
  107. data/spec/lib/capistrano/configuration/question_spec.rb +92 -0
  108. data/spec/lib/capistrano/configuration/role_filter_spec.rb +80 -0
  109. data/spec/lib/capistrano/configuration/scm_resolver_spec.rb +56 -0
  110. data/spec/lib/capistrano/configuration/server_spec.rb +309 -0
  111. data/spec/lib/capistrano/configuration/servers_spec.rb +331 -0
  112. data/spec/lib/capistrano/configuration_spec.rb +357 -0
  113. data/spec/lib/capistrano/doctor/environment_doctor_spec.rb +44 -0
  114. data/spec/lib/capistrano/doctor/gems_doctor_spec.rb +67 -0
  115. data/spec/lib/capistrano/doctor/output_helpers_spec.rb +47 -0
  116. data/spec/lib/capistrano/doctor/servers_doctor_spec.rb +86 -0
  117. data/spec/lib/capistrano/doctor/variables_doctor_spec.rb +89 -0
  118. data/spec/lib/capistrano/dsl/paths_spec.rb +228 -0
  119. data/spec/lib/capistrano/dsl/task_enhancements_spec.rb +108 -0
  120. data/spec/lib/capistrano/dsl_spec.rb +125 -0
  121. data/spec/lib/capistrano/immutable_task_spec.rb +31 -0
  122. data/spec/lib/capistrano/plugin_spec.rb +84 -0
  123. data/spec/lib/capistrano/scm/git_spec.rb +194 -0
  124. data/spec/lib/capistrano/scm/hg_spec.rb +109 -0
  125. data/spec/lib/capistrano/scm/svn_spec.rb +137 -0
  126. data/spec/lib/capistrano/scm_spec.rb +103 -0
  127. data/spec/lib/capistrano/upload_task_spec.rb +19 -0
  128. data/spec/lib/capistrano/version_validator_spec.rb +118 -0
  129. data/spec/lib/capistrano_spec.rb +7 -0
  130. data/spec/spec_helper.rb +29 -0
  131. data/spec/support/matchers.rb +5 -0
  132. data/spec/support/tasks/database.rake +11 -0
  133. data/spec/support/tasks/fail.rake +8 -0
  134. data/spec/support/tasks/failed.rake +5 -0
  135. data/spec/support/tasks/plugin.rake +6 -0
  136. data/spec/support/tasks/root.rake +11 -0
  137. data/spec/support/test_app.rb +205 -0
  138. metadata +234 -208
  139. data/.rvmrc +0 -1
  140. data/CHANGELOG +0 -954
  141. data/README.mdown +0 -76
  142. data/lib/capistrano/callback.rb +0 -45
  143. data/lib/capistrano/cli/execute.rb +0 -85
  144. data/lib/capistrano/cli/help.rb +0 -125
  145. data/lib/capistrano/cli/help.txt +0 -81
  146. data/lib/capistrano/cli/options.rb +0 -243
  147. data/lib/capistrano/cli/ui.rb +0 -40
  148. data/lib/capistrano/cli.rb +0 -47
  149. data/lib/capistrano/command.rb +0 -286
  150. data/lib/capistrano/configuration/actions/file_transfer.rb +0 -51
  151. data/lib/capistrano/configuration/actions/inspect.rb +0 -46
  152. data/lib/capistrano/configuration/actions/invocation.rb +0 -298
  153. data/lib/capistrano/configuration/callbacks.rb +0 -148
  154. data/lib/capistrano/configuration/connections.rb +0 -230
  155. data/lib/capistrano/configuration/execution.rb +0 -143
  156. data/lib/capistrano/configuration/loading.rb +0 -197
  157. data/lib/capistrano/configuration/namespaces.rb +0 -197
  158. data/lib/capistrano/configuration/roles.rb +0 -73
  159. data/lib/capistrano/errors.rb +0 -19
  160. data/lib/capistrano/ext/string.rb +0 -5
  161. data/lib/capistrano/extensions.rb +0 -57
  162. data/lib/capistrano/logger.rb +0 -59
  163. data/lib/capistrano/processable.rb +0 -53
  164. data/lib/capistrano/recipes/compat.rb +0 -32
  165. data/lib/capistrano/recipes/deploy/assets.rb +0 -57
  166. data/lib/capistrano/recipes/deploy/dependencies.rb +0 -44
  167. data/lib/capistrano/recipes/deploy/local_dependency.rb +0 -54
  168. data/lib/capistrano/recipes/deploy/remote_dependency.rb +0 -111
  169. data/lib/capistrano/recipes/deploy/scm/accurev.rb +0 -169
  170. data/lib/capistrano/recipes/deploy/scm/base.rb +0 -196
  171. data/lib/capistrano/recipes/deploy/scm/bzr.rb +0 -86
  172. data/lib/capistrano/recipes/deploy/scm/cvs.rb +0 -153
  173. data/lib/capistrano/recipes/deploy/scm/darcs.rb +0 -96
  174. data/lib/capistrano/recipes/deploy/scm/git.rb +0 -282
  175. data/lib/capistrano/recipes/deploy/scm/mercurial.rb +0 -137
  176. data/lib/capistrano/recipes/deploy/scm/none.rb +0 -44
  177. data/lib/capistrano/recipes/deploy/scm/perforce.rb +0 -138
  178. data/lib/capistrano/recipes/deploy/scm/subversion.rb +0 -121
  179. data/lib/capistrano/recipes/deploy/scm.rb +0 -19
  180. data/lib/capistrano/recipes/deploy/strategy/base.rb +0 -88
  181. data/lib/capistrano/recipes/deploy/strategy/checkout.rb +0 -20
  182. data/lib/capistrano/recipes/deploy/strategy/copy.rb +0 -224
  183. data/lib/capistrano/recipes/deploy/strategy/export.rb +0 -20
  184. data/lib/capistrano/recipes/deploy/strategy/remote.rb +0 -52
  185. data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +0 -57
  186. data/lib/capistrano/recipes/deploy/strategy.rb +0 -19
  187. data/lib/capistrano/recipes/deploy/templates/maintenance.rhtml +0 -53
  188. data/lib/capistrano/recipes/deploy.rb +0 -568
  189. data/lib/capistrano/recipes/standard.rb +0 -37
  190. data/lib/capistrano/recipes/templates/maintenance.rhtml +0 -53
  191. data/lib/capistrano/role.rb +0 -102
  192. data/lib/capistrano/server_definition.rb +0 -56
  193. data/lib/capistrano/shell.rb +0 -260
  194. data/lib/capistrano/ssh.rb +0 -101
  195. data/lib/capistrano/task_definition.rb +0 -75
  196. data/lib/capistrano/transfer.rb +0 -216
  197. data/rvmrc.sample +0 -1
  198. data/test/cli/execute_test.rb +0 -132
  199. data/test/cli/help_test.rb +0 -165
  200. data/test/cli/options_test.rb +0 -329
  201. data/test/cli/ui_test.rb +0 -28
  202. data/test/cli_test.rb +0 -17
  203. data/test/command_test.rb +0 -289
  204. data/test/configuration/actions/file_transfer_test.rb +0 -61
  205. data/test/configuration/actions/inspect_test.rb +0 -65
  206. data/test/configuration/actions/invocation_test.rb +0 -247
  207. data/test/configuration/callbacks_test.rb +0 -220
  208. data/test/configuration/connections_test.rb +0 -420
  209. data/test/configuration/execution_test.rb +0 -175
  210. data/test/configuration/loading_test.rb +0 -132
  211. data/test/configuration/namespace_dsl_test.rb +0 -311
  212. data/test/configuration/roles_test.rb +0 -144
  213. data/test/configuration/servers_test.rb +0 -183
  214. data/test/configuration/variables_test.rb +0 -190
  215. data/test/configuration_test.rb +0 -88
  216. data/test/deploy/local_dependency_test.rb +0 -76
  217. data/test/deploy/remote_dependency_test.rb +0 -135
  218. data/test/deploy/scm/accurev_test.rb +0 -23
  219. data/test/deploy/scm/base_test.rb +0 -55
  220. data/test/deploy/scm/bzr_test.rb +0 -51
  221. data/test/deploy/scm/darcs_test.rb +0 -37
  222. data/test/deploy/scm/git_test.rb +0 -184
  223. data/test/deploy/scm/mercurial_test.rb +0 -134
  224. data/test/deploy/scm/none_test.rb +0 -35
  225. data/test/deploy/scm/subversion_test.rb +0 -32
  226. data/test/deploy/strategy/copy_test.rb +0 -321
  227. data/test/extensions_test.rb +0 -69
  228. data/test/fixtures/cli_integration.rb +0 -5
  229. data/test/fixtures/config.rb +0 -5
  230. data/test/fixtures/custom.rb +0 -3
  231. data/test/logger_test.rb +0 -123
  232. data/test/recipes_test.rb +0 -25
  233. data/test/role_test.rb +0 -11
  234. data/test/server_definition_test.rb +0 -121
  235. data/test/shell_test.rb +0 -90
  236. data/test/ssh_test.rb +0 -113
  237. data/test/task_definition_test.rb +0 -116
  238. data/test/transfer_test.rb +0 -160
  239. data/test/utils.rb +0 -37
@@ -1,102 +0,0 @@
1
- module Capistrano
2
- class Role
3
- include Enumerable
4
-
5
- def initialize(*list)
6
- @static_servers = []
7
- @dynamic_servers = []
8
- push(*list)
9
- end
10
-
11
- def each(&block)
12
- servers.each &block
13
- end
14
-
15
- def push(*list)
16
- options = list.last.is_a?(Hash) ? list.pop : {}
17
- list.each do |item|
18
- if item.respond_to?(:call)
19
- @dynamic_servers << DynamicServerList.new(item, options)
20
- else
21
- @static_servers << self.class.wrap_server(item, options)
22
- end
23
- end
24
- end
25
- alias_method :<<, :push
26
-
27
- def servers
28
- @static_servers + dynamic_servers
29
- end
30
- alias_method :to_ary, :servers
31
-
32
- def empty?
33
- servers.empty?
34
- end
35
-
36
- def clear
37
- @dynamic_servers.clear
38
- @static_servers.clear
39
- end
40
-
41
- def include?(server)
42
- servers.include?(server)
43
- end
44
-
45
- protected
46
-
47
- # This is the combination of a block, a hash of options, and a cached value.
48
- class DynamicServerList
49
- def initialize (block, options)
50
- @block = block
51
- @options = options
52
- @cached = []
53
- @is_cached = false
54
- end
55
-
56
- # Convert to a list of ServerDefinitions
57
- def to_ary
58
- unless @is_cached
59
- @cached = Role::wrap_list(@block.call(@options), @options)
60
- @is_cached = true
61
- end
62
- @cached
63
- end
64
-
65
- # Clear the cached value
66
- def reset!
67
- @cached.clear
68
- @is_cached = false
69
- end
70
- end
71
-
72
- # Attribute reader for the cached results of executing the blocks in turn
73
- def dynamic_servers
74
- @dynamic_servers.inject([]) { |list, item| list.concat item }
75
- end
76
-
77
- # Wraps a string in a ServerDefinition, if it isn't already.
78
- # This and wrap_list should probably go in ServerDefinition in some form.
79
- def self.wrap_server (item, options)
80
- item.is_a?(ServerDefinition) ? item : ServerDefinition.new(item, options)
81
- end
82
-
83
- # Turns a list, or something resembling a list, into a properly-formatted
84
- # ServerDefinition list. Keep an eye on this one -- it's entirely too
85
- # magical for its own good. In particular, if ServerDefinition ever inherits
86
- # from Array, this will break.
87
- def self.wrap_list (*list)
88
- options = list.last.is_a?(Hash) ? list.pop : {}
89
- if list.length == 1
90
- if list.first.nil?
91
- return []
92
- elsif list.first.is_a?(Array)
93
- list = list.first
94
- end
95
- end
96
- options.merge! list.pop if list.last.is_a?(Hash)
97
- list.map do |item|
98
- self.wrap_server item, options
99
- end
100
- end
101
- end
102
- end
@@ -1,56 +0,0 @@
1
- module Capistrano
2
- class ServerDefinition
3
- include Comparable
4
-
5
- attr_reader :host
6
- attr_reader :user
7
- attr_reader :port
8
- attr_reader :options
9
-
10
- # The default user name to use when a user name is not explicitly provided
11
- def self.default_user
12
- ENV['USER'] || ENV['USERNAME'] || "not-specified"
13
- end
14
-
15
- def initialize(string, options={})
16
- @user, @host, @port = string.match(/^(?:([^;,:=]+)@|)(.*?)(?::(\d+)|)$/)[1,3]
17
-
18
- @options = options.dup
19
- user_opt, port_opt = @options.delete(:user), @options.delete(:port)
20
-
21
- @user ||= user_opt
22
- @port ||= port_opt
23
-
24
- @port = @port.to_i if @port
25
- end
26
-
27
- def <=>(server)
28
- [host, port, user] <=> [server.host, server.port, server.user]
29
- end
30
-
31
- # Redefined, so that Array#uniq will work to remove duplicate server
32
- # definitions, based solely on their host names.
33
- def eql?(server)
34
- host == server.host &&
35
- user == server.user &&
36
- port == server.port
37
- end
38
-
39
- alias :== :eql?
40
-
41
- # Redefined, so that Array#uniq will work to remove duplicate server
42
- # definitions, based on their connection information.
43
- def hash
44
- @hash ||= [host, user, port].hash
45
- end
46
-
47
- def to_s
48
- @to_s ||= begin
49
- s = host
50
- s = "#{user}@#{s}" if user
51
- s = "#{s}:#{port}" if port && port != 22
52
- s
53
- end
54
- end
55
- end
56
- end
@@ -1,260 +0,0 @@
1
- require 'thread'
2
- require 'capistrano/processable'
3
-
4
- module Capistrano
5
- # The Capistrano::Shell class is the guts of the "shell" task. It implements
6
- # an interactive REPL interface that users can employ to execute tasks and
7
- # commands. It makes for a GREAT way to monitor systems, and perform quick
8
- # maintenance on one or more machines.
9
- class Shell
10
- include Processable
11
-
12
- # A Readline replacement for platforms where readline is either
13
- # unavailable, or has not been installed.
14
- class ReadlineFallback #:nodoc:
15
- HISTORY = []
16
-
17
- def self.readline(prompt)
18
- STDOUT.print(prompt)
19
- STDOUT.flush
20
- STDIN.gets
21
- end
22
- end
23
-
24
- # The configuration instance employed by this shell
25
- attr_reader :configuration
26
-
27
- # Instantiate a new shell and begin executing it immediately.
28
- def self.run(config)
29
- new(config).run!
30
- end
31
-
32
- # Instantiate a new shell
33
- def initialize(config)
34
- @configuration = config
35
- end
36
-
37
- # Start the shell running. This method will block until the shell
38
- # terminates.
39
- def run!
40
- setup
41
-
42
- puts <<-INTRO
43
- ====================================================================
44
- Welcome to the interactive Capistrano shell! This is an experimental
45
- feature, and is liable to change in future releases. Type 'help' for
46
- a summary of how to use the shell.
47
- --------------------------------------------------------------------
48
- INTRO
49
-
50
- loop do
51
- break if !read_and_execute
52
- end
53
-
54
- @bgthread.kill
55
- end
56
-
57
- def read_and_execute
58
- command = read_line
59
-
60
- case command
61
- when "?", "help" then help
62
- when "quit", "exit" then
63
- puts "exiting"
64
- return false
65
- when /^set -(\w)\s*(\S+)/
66
- set_option($1, $2)
67
- when /^(?:(with|on)\s*(\S+))?\s*(\S.*)?/i
68
- process_command($1, $2, $3)
69
- else
70
- raise "eh?"
71
- end
72
-
73
- return true
74
- end
75
-
76
- private
77
-
78
- # Present the prompt and read a single line from the console. It also
79
- # detects ^D and returns "exit" in that case. Adds the input to the
80
- # history, unless the input is empty. Loops repeatedly until a non-empty
81
- # line is input.
82
- def read_line
83
- loop do
84
- command = reader.readline("cap> ")
85
-
86
- if command.nil?
87
- command = "exit"
88
- puts(command)
89
- else
90
- command.strip!
91
- end
92
-
93
- unless command.empty?
94
- reader::HISTORY << command
95
- return command
96
- end
97
- end
98
- end
99
-
100
- # Display a verbose help message.
101
- def help
102
- puts <<-HELP
103
- --- HELP! ---------------------------------------------------
104
- "Get me out of this thing. I just want to quit."
105
- -> Easy enough. Just type "exit", or "quit". Or press ctrl-D.
106
-
107
- "I want to execute a command on all servers."
108
- -> Just type the command, and press enter. It will be passed,
109
- verbatim, to all defined servers.
110
-
111
- "What if I only want it to execute on a subset of them?"
112
- -> No problem, just specify the list of servers, separated by
113
- commas, before the command, with the `on' keyword:
114
-
115
- cap> on app1.foo.com,app2.foo.com echo ping
116
-
117
- "Nice, but can I specify the servers by role?"
118
- -> You sure can. Just use the `with' keyword, followed by the
119
- comma-delimited list of role names:
120
-
121
- cap> with app,db echo ping
122
-
123
- "Can I execute a Capistrano task from within this shell?"
124
- -> Yup. Just prefix the task with an exclamation mark:
125
-
126
- cap> !deploy
127
- HELP
128
- end
129
-
130
- # Determine which servers the given task requires a connection to, and
131
- # establish connections to them if necessary. Return the list of
132
- # servers (names).
133
- def connect(task)
134
- servers = configuration.find_servers_for_task(task)
135
- needing_connections = servers - configuration.sessions.keys
136
- unless needing_connections.empty?
137
- puts "[establishing connection(s) to #{needing_connections.join(', ')}]"
138
- configuration.establish_connections_to(needing_connections)
139
- end
140
- servers
141
- end
142
-
143
- # Execute the given command. If the command is prefixed by an exclamation
144
- # mark, it is assumed to refer to another capistrano task, which will
145
- # be invoked. Otherwise, it is executed as a command on all associated
146
- # servers.
147
- def exec(command)
148
- @mutex.synchronize do
149
- if command[0] == ?!
150
- exec_tasks(command[1..-1].split)
151
- else
152
- servers = connect(configuration.current_task)
153
- exec_command(command, servers)
154
- end
155
- end
156
- ensure
157
- STDOUT.flush
158
- end
159
-
160
- # Given an array of task names, invoke them in sequence.
161
- def exec_tasks(list)
162
- list.each do |task_name|
163
- task = configuration.find_task(task_name)
164
- raise Capistrano::NoSuchTaskError, "no such task `#{task_name}'" unless task
165
- connect(task)
166
- configuration.execute_task(task)
167
- end
168
- rescue Capistrano::NoMatchingServersError, Capistrano::NoSuchTaskError => error
169
- warn "error: #{error.message}"
170
- end
171
-
172
- # Execute a command on the given list of servers.
173
- def exec_command(command, servers)
174
- command = command.gsub(/\bsudo\b/, "sudo -p '#{configuration.sudo_prompt}'")
175
- processor = configuration.sudo_behavior_callback(Configuration.default_io_proc)
176
- sessions = servers.map { |server| configuration.sessions[server] }
177
- options = configuration.add_default_command_options({})
178
- cmd = Command.new(command, sessions, options.merge(:logger => configuration.logger), &processor)
179
- previous = trap("INT") { cmd.stop! }
180
- cmd.process!
181
- rescue Capistrano::Error => error
182
- warn "error: #{error.message}"
183
- ensure
184
- trap("INT", previous)
185
- end
186
-
187
- # Return the object that will be used to query input from the console.
188
- # The returned object will quack (more or less) like Readline.
189
- def reader
190
- @reader ||= begin
191
- require 'readline'
192
- Readline
193
- rescue LoadError
194
- ReadlineFallback
195
- end
196
- end
197
-
198
- # Prepare every little thing for the shell. Starts the background
199
- # thread and generally gets things ready for the REPL.
200
- def setup
201
- configuration.logger.level = Capistrano::Logger::INFO
202
-
203
- @mutex = Mutex.new
204
- @bgthread = Thread.new do
205
- loop do
206
- @mutex.synchronize { process_iteration(0.1) }
207
- end
208
- end
209
- end
210
-
211
- # Set the given option to +value+.
212
- def set_option(opt, value)
213
- case opt
214
- when "v" then
215
- puts "setting log verbosity to #{value.to_i}"
216
- configuration.logger.level = value.to_i
217
- when "o" then
218
- case value
219
- when "vi" then
220
- puts "using vi edit mode"
221
- reader.vi_editing_mode
222
- when "emacs" then
223
- puts "using emacs edit mode"
224
- reader.emacs_editing_mode
225
- else
226
- puts "unknown -o option #{value.inspect}"
227
- end
228
- else
229
- puts "unknown setting #{opt.inspect}"
230
- end
231
- end
232
-
233
- # Process a command. Interprets the scope_type (must be nil, "with", or
234
- # "on") and the command. If no command is given, then the scope is made
235
- # effective for all subsequent commands. If the scope value is "all",
236
- # then the scope is unrestricted.
237
- def process_command(scope_type, scope_value, command)
238
- env_var = case scope_type
239
- when "with" then "ROLES"
240
- when "on" then "HOSTS"
241
- end
242
-
243
- old_var, ENV[env_var] = ENV[env_var], (scope_value == "all" ? nil : scope_value) if env_var
244
- if command
245
- begin
246
- exec(command)
247
- ensure
248
- ENV[env_var] = old_var if env_var
249
- end
250
- else
251
- puts "scoping #{scope_type} #{scope_value}"
252
- end
253
- end
254
- end
255
-
256
- # All open sessions, needed to satisfy the Command::Processable include
257
- def sessions
258
- configuration.sessions.values
259
- end
260
- end
@@ -1,101 +0,0 @@
1
- begin
2
- require 'rubygems'
3
- gem 'net-ssh', ">= 2.0.10"
4
- rescue LoadError, NameError
5
- end
6
-
7
- require 'net/ssh'
8
-
9
- module Capistrano
10
- # A helper class for dealing with SSH connections.
11
- class SSH
12
- # Patch an accessor onto an SSH connection so that we can record the server
13
- # definition object that defines the connection. This is useful because
14
- # the gateway returns connections whose "host" is 127.0.0.1, instead of
15
- # the host on the other side of the tunnel.
16
- module Server #:nodoc:
17
- def self.apply_to(connection, server)
18
- connection.extend(Server)
19
- connection.xserver = server
20
- connection
21
- end
22
-
23
- attr_accessor :xserver
24
- end
25
-
26
- # An abstraction to make it possible to connect to the server via public key
27
- # without prompting for the password. If the public key authentication fails
28
- # this will fall back to password authentication.
29
- #
30
- # +server+ must be an instance of ServerDefinition.
31
- #
32
- # If a block is given, the new session is yielded to it, otherwise the new
33
- # session is returned.
34
- #
35
- # If an :ssh_options key exists in +options+, it is passed to the Net::SSH
36
- # constructor. Values in +options+ are then merged into it, and any
37
- # connection information in +server+ is added last, so that +server+ info
38
- # takes precedence over +options+, which takes precendence over ssh_options.
39
- def self.connect(server, options={})
40
- connection_strategy(server, options) do |host, user, connection_options|
41
- connection = Net::SSH.start(host, user, connection_options)
42
- Server.apply_to(connection, server)
43
- end
44
- end
45
-
46
- # Abstracts the logic for establishing an SSH connection (which includes
47
- # testing for connection failures and retrying with a password, and so forth,
48
- # mostly made complicated because of the fact that some of these variables
49
- # might be lazily evaluated and try to do something like prompt the user,
50
- # which should only happen when absolutely necessary.
51
- #
52
- # This will yield the hostname, username, and a hash of connection options
53
- # to the given block, which should return a new connection.
54
- def self.connection_strategy(server, options={}, &block)
55
- methods = [ %w(publickey hostbased), %w(password keyboard-interactive) ]
56
- password_value = nil
57
-
58
- # construct the hash of ssh options that should be passed more-or-less
59
- # directly to Net::SSH. This will be the general ssh options, merged with
60
- # the server-specific ssh-options.
61
- ssh_options = (options[:ssh_options] || {}).merge(server.options[:ssh_options] || {})
62
-
63
- # load any SSH configuration files that were specified in the SSH options. This
64
- # will load from ~/.ssh/config and /etc/ssh_config by default (see Net::SSH
65
- # for details). Merge the explicitly given ssh_options over the top of the info
66
- # from the config file.
67
- ssh_options = Net::SSH.configuration_for(server.host, ssh_options.fetch(:config, true)).merge(ssh_options)
68
-
69
- # Once we've loaded the config, we don't need Net::SSH to do it again.
70
- ssh_options[:config] = false
71
-
72
- ssh_options[:verbose] = :debug if options[:verbose] && options[:verbose] > 0
73
-
74
- user = server.user || options[:user] || ssh_options[:username] ||
75
- ssh_options[:user] || ServerDefinition.default_user
76
- port = server.port || options[:port] || ssh_options[:port]
77
-
78
- # the .ssh/config file might have changed the host-name on us
79
- host = ssh_options.fetch(:host_name, server.host)
80
-
81
- ssh_options[:port] = port if port
82
-
83
- # delete these, since we've determined which username to use by this point
84
- ssh_options.delete(:username)
85
- ssh_options.delete(:user)
86
-
87
- begin
88
- connection_options = ssh_options.merge(
89
- :password => password_value,
90
- :auth_methods => ssh_options[:auth_methods] || methods.shift
91
- )
92
-
93
- yield host, user, connection_options
94
- rescue Net::SSH::AuthenticationFailed
95
- raise if methods.empty? || ssh_options[:auth_methods]
96
- password_value = options[:password]
97
- retry
98
- end
99
- end
100
- end
101
- end
@@ -1,75 +0,0 @@
1
- require 'capistrano/server_definition'
2
-
3
- module Capistrano
4
- # Represents the definition of a single task.
5
- class TaskDefinition
6
- attr_reader :name, :namespace, :options, :body, :desc, :on_error, :max_hosts
7
-
8
- def initialize(name, namespace, options={}, &block)
9
-
10
- if name.to_s =~ /^(?:before_|after_)/
11
- Kernel.warn("[Deprecation Warning] Naming tasks with before_ and after_ is deprecated, please see the new before() and after() methods. (Offending task name was #{name})")
12
- end
13
-
14
- @name, @namespace, @options = name, namespace, options
15
- @desc = @options.delete(:desc)
16
- @on_error = options.delete(:on_error)
17
- @max_hosts = options[:max_hosts] && options[:max_hosts].to_i
18
- @body = block or raise ArgumentError, "a task requires a block"
19
- @servers = nil
20
- end
21
-
22
- # Returns the task's fully-qualified name, including the namespace
23
- def fully_qualified_name
24
- @fully_qualified_name ||= begin
25
- if namespace.default_task == self
26
- namespace.fully_qualified_name
27
- else
28
- [namespace.fully_qualified_name, name].compact.join(":")
29
- end
30
- end
31
- end
32
-
33
- # Returns the description for this task, with newlines collapsed and
34
- # whitespace stripped. Returns the empty string if there is no
35
- # description for this task.
36
- def description(rebuild=false)
37
- @description = nil if rebuild
38
- @description ||= begin
39
- description = @desc || ""
40
-
41
- indentation = description[/\A\s+/]
42
- if indentation
43
- reformatted_description = ""
44
- description.strip.each_line do |line|
45
- line = line.chomp.sub(/^#{indentation}/, "")
46
- line = line.gsub(/#{indentation}\s*/, " ") if line[/^\S/]
47
- reformatted_description << line << "\n"
48
- end
49
- description = reformatted_description
50
- end
51
-
52
- description.strip.gsub(/\r\n/, "\n")
53
- end
54
- end
55
-
56
- # Returns the first sentence of the full description. If +max_length+ is
57
- # given, the result will be truncated if it is longer than +max_length+,
58
- # and an ellipsis appended.
59
- def brief_description(max_length=nil)
60
- brief = description[/^.*?\.(?=\s|$)/] || description
61
-
62
- if max_length && brief.length > max_length
63
- brief = brief[0,max_length-3] + "..."
64
- end
65
-
66
- brief
67
- end
68
-
69
- # Indicates whether the task wants to continue, even if a server has failed
70
- # previously
71
- def continue_on_error?
72
- @on_error == :continue
73
- end
74
- end
75
- end