Allow 'ask' to be run at "compile" time
For semi-automated runbooks, it is useful to be able to collect all the necessary information that is needed by a runbook up-front, before the steps start executing. In the simple case, you can just ask all your questions in the first step, but if you're aggregating multiple sections or runbooks together into one mega runbook o' doom, and each of the components has questions of its own, you end up having to come back to the run all the time to answer more questions. If I could answer all the questions at once, and then wander off to get a cuppa while the runbook does its thing, I would be a much happier (and well-caffeinated) person.
I like this idea, but have struggled to find a good implementation. If you can think of a good way to accomplish this, I would be interested. A couple of thoughts:
- Typically for gathering input at compile time, I suggest relying on environment variables.
Runbook.book "Bootstrap Servers" do
step "Setup" do
ruby_command do
@rails_env ||= ENV["RAILS_ENV"]
ask "Environment?", into: :rails_env, default: "staging" unless @rails_env
end
end
end
$ RAILS_ENV=production bundle exec runbook exec my_runbook.rb
Alternatively, TTY::Prompt is a dependency of Runbook, so it could be used to collect user input before the runbook is evaluated. The main concern with this is it prevents a transition to full autonomy for the runbook. If this is unlikely to be necessary for your particular use case, then this approach may be a good route to go. Another downside of this is that you will be re-prompted every time you execute the runbook, even if you encounter an error. It also will not remember previous inputs.
- Switching to some OOP might be useful. You could do something like the following:
# runbooks/restart_cluster.rb
require 'rotate_leader_runbook'
require 'restart_node_runbook'
Runbook.book "Restart Cluster" do
section "setup" do
add RotateLeaderRunbook.input_step
add RestartLeaderRunbook.input_step
end
add RotateLeaderRunbook.rotate_leader_section
add RotateLeaderRunbook.restart_node_section
end
# lib/runbook/rotate_leader_runbook.rb
module RotateLeaderRunbook
def self.input_step
Runbook.step do
ask "Server?", into: server
ask "Timeout?", into: timeout
end
end
def self.rotate_leader_section
Runbook.section "Rotate Leader" do
# ...
end
end
end
This way, you could coalesce inputs to all execute at the beginning of the runbook.
I'm also going to mention that I am planning to include this feature in the next version of Runbook: https://github.com/braintree/runbook/blob/master/TODO.md#always-executed-setup-section. This may not directly address your issue, but may be useful for your mega runbook o' doom.