1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
module LeapCli; module Commands
extend self
extend LeapCli::Util
def path(name)
Path.named_path(name)
end
#
# keeps prompting the user for a numbered choice, until they pick a good one or bail out.
#
# block is yielded and is responsible for rendering the choices.
#
def numbered_choice_menu(msg, items, &block)
while true
say("\n" + msg + ':')
items.each_with_index &block
say("q. quit")
index = ask("number 1-#{items.length}> ")
if index.empty?
next
elsif index =~ /q/
bail!
else
i = index.to_i - 1
if i < 0 || i >= items.length
bail!
else
return i
end
end
end
end
#
#
#
# FYI
# Capistrano::Logger::IMPORTANT = 0
# Capistrano::Logger::INFO = 1
# Capistrano::Logger::DEBUG = 2
# Capistrano::Logger::TRACE = 3
#
def ssh_connect(nodes, options={}, &block)
node_list = parse_node_list(nodes)
cap = new_capistrano
cap.logger.level = LeapCli.log_level
user = options[:user] || 'root'
cap.set :user, user
cap.set :ssh_options, ssh_options
cap.set :use_sudo, false # we may want to change this in the future
# # supply drop options
# cap.set :puppet_source, [Path.platform, 'puppet'].join('/')
# cap.set :puppet_destination, '/root/leap'
# #cap.set :puppet_command, 'puppet apply'
# cap.set :puppet_lib, "puppet/modules"
# cap.set :puppet_parameters, '--confdir=puppet puppet/manifests/site.pp'
# #cap.set :puppet_stream_output, false
# #puppet apply --confdir=puppet puppet/manifests/site.pp | grep -v 'warning:.*is deprecated'
# #puppet_cmd = "cd #{puppet_destination} && #{sudo_cmd} #{puppet_command} --modulepath=#{puppet_lib} #{puppet_parameters}"
#
# allow password authentication when we are bootstraping a single node.
#
if options[:bootstrap] && node_list.size == 1
hostname = node_list.values.first.name
# the 'password' block is only called if key auth fails
if options[:echo]
cap.set(:password) { ask "Root SSH password for #{user}@#{hostname}> " }
else
cap.set(:password) { Capistrano::CLI.password_prompt " * Typed password will be hidden (use --echo to make it visible)\nRoot SSH password for #{user}@#{hostname}> " }
end
end
node_list.each do |name, node|
cap.server node.name, :dummy_arg, node_options(node)
end
yield cap
end
private
#
# For available options, see http://net-ssh.github.com/net-ssh/classes/Net/SSH.html#method-c-start
#
def ssh_options
{
:config => false,
:user_known_hosts_file => path(:known_hosts),
:paranoid => true
}
end
#
# For notes on advanced ways to set server-specific options, see
# http://railsware.com/blog/2011/11/02/advanced-server-definitions-in-capistrano/
#
def node_options(node)
#password_proc = Proc.new {Capistrano::CLI.password_prompt "Root SSH password for #{node.name}"} # only called if needed
{
#:password => password_proc,
:ssh_options => {
:host_key_alias => node.name,
:host_name => node.ip_address,
:port => node.ssh.port
}
}
end
def new_capistrano
# load once the library files
@capistrano_enabled ||= begin
require 'capistrano'
require 'capistrano/cli'
require 'leap_cli/remote/plugin'
Capistrano.plugin :leap, LeapCli::Remote::Plugin
true
end
# create capistrano instance
cap = Capistrano::Configuration.new
# add tasks to capistrano instance
cap.load File.dirname(__FILE__) + '/../remote/tasks.rb'
return cap
end
def parse_node_list(nodes)
if nodes.is_a? Config::Object
Config::ObjectList.new(nodes)
elsif nodes.is_a? Config::ObjectList
nodes
elsif nodes.is_a? String
manager.filter!(nodes)
else
bail! "argument error"
end
end
end; end
|