Module: LeapCli::Remote::LeapPlugin
- Defined in:
- lib/leap_cli/remote/leap_plugin.rb
Instance Method Summary collapse
-
#assert_initialized ⇒ Object
echos “ok” if the node has been initialized and the required packages are installed, bails out otherwise.
-
#capture(cmd, &block) ⇒ Object
like stream, but capture all the output before returning.
-
#check_for_no_deploy ⇒ Object
bails out the deploy if the file /etc/leap/no-deploy exists.
-
#debug ⇒ Object
dumps debugging information #.
-
#history(lines) ⇒ Object
dumps the recent deploy history to the console.
- #log(*args, &block) ⇒ Object
-
#mkdirs(*dirs) ⇒ Object
creates directories that are owned by root and 700 permissions.
- #required_packages ⇒ Object
-
#run_with_progress(cmd, &block) ⇒ Object
Run a command, with a nice status report and progress indicator.
-
#stream(cmd, &block) ⇒ Object
similar to run(cmd, &block), but with:.
-
#with_task(name) ⇒ Object
This is a hairy ugly hack, exactly the kind of stuff that makes ruby dangerous and too much fun for its own good.
Instance Method Details
#assert_initialized ⇒ Object
echos “ok” if the node has been initialized and the required packages are installed, bails out otherwise.
27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/leap_cli/remote/leap_plugin.rb', line 27 def assert_initialized begin test_initialized_file = "test -f #{Leap::Platform.init_path}" check_required_packages = "! dpkg-query -W --showformat='${Status}\n' #{required_packages} 2>&1 | grep -q -E '(deinstall|no packages)'" run "#{test_initialized_file} && #{check_required_packages} && echo ok" rescue Capistrano::CommandError => exc LeapCli::Util.bail! do exc.hosts.each do |host| node = host.to_s.split('.').first LeapCli::Util.log :error, "running deploy: node not initialized. Run 'leap node init #{node}'", :host => host end end end end |
#capture(cmd, &block) ⇒ Object
like stream, but capture all the output before returning
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/leap_cli/remote/leap_plugin.rb', line 123 def capture(cmd, &block) command = '%s 2>&1; echo "exitcode=$?" 2>&1;' % cmd host_data = {} run(command) do |channel, stream, data| host_data[channel[:host]] ||= "" if data =~ /exitcode=(\d+)\n/ exitcode = $1.to_i data.sub!(/exitcode=(\d+)\n/,'') host_data[channel[:host]] += data yield({:host => channel[:host], :data => host_data[channel[:host]], :exitcode => exitcode}) else host_data[channel[:host]] += data end end end |
#check_for_no_deploy ⇒ Object
bails out the deploy if the file /etc/leap/no-deploy exists. This kind of sucks, because it would be better to skip over nodes that have no-deploy set instead halting the entire deploy. As far as I know, with capistrano, there is no way to close one of the ssh connections in the pool and make sure it gets no further commands.
48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/leap_cli/remote/leap_plugin.rb', line 48 def check_for_no_deploy begin run "test ! -f /etc/leap/no-deploy" rescue Capistrano::CommandError => exc LeapCli::Util.bail! do exc.hosts.each do |host| LeapCli::Util.log "Can't continue because file /etc/leap/no-deploy exists", :host => host end end end end |
#debug ⇒ Object
dumps debugging information #
63 64 65 |
# File 'lib/leap_cli/remote/leap_plugin.rb', line 63 def debug run "#{Leap::Platform.leap_dir}/bin/debug.sh" end |
#history(lines) ⇒ Object
dumps the recent deploy history to the console
70 71 72 73 |
# File 'lib/leap_cli/remote/leap_plugin.rb', line 70 def history(lines) command = "(test -s /var/log/leap/deploy-summary.log && tail -n #{lines} /var/log/leap/deploy-summary.log) || (test -s /var/log/leap/deploy-summary.log.1 && tail -n #{lines} /var/log/leap/deploy-summary.log.1) || (echo 'no history')" run command end |
#log(*args, &block) ⇒ Object
12 13 14 |
# File 'lib/leap_cli/remote/leap_plugin.rb', line 12 def log(*args, &block) LeapCli::Util::log(*args, &block) end |
#mkdirs(*dirs) ⇒ Object
creates directories that are owned by root and 700 permissions
19 20 21 22 |
# File 'lib/leap_cli/remote/leap_plugin.rb', line 19 def mkdirs(*dirs) raise ArgumentError.new('illegal dir name') if dirs.grep(/[\' ]/).any? run dirs.collect{|dir| "mkdir -m 700 -p #{dir}; "}.join end |
#required_packages ⇒ Object
8 9 10 |
# File 'lib/leap_cli/remote/leap_plugin.rb', line 8 def required_packages "puppet rsync lsb-release locales" end |
#run_with_progress(cmd, &block) ⇒ Object
Run a command, with a nice status report and progress indicator. Only successful results are returned, errors are printed.
For each successful run on each host, block is yielded with a hash like so:
=> ‘bluejay’, :exitcode => 0, :data => ‘shell output’
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/leap_cli/remote/leap_plugin.rb', line 147 def run_with_progress(cmd, &block) ssh_failures = [] exitcode_failures = [] succeeded = [] task = LeapCli.log_level > 1 ? :standard_task : :skip_errors_task with_task(task) do log :querying, 'facts' do progress " " call_on_failure do |host| ssh_failures << host progress 'F' end capture(cmd) do |response| if response[:exitcode] == 0 progress '.' yield response else exitcode_failures << response progress 'F' end end end end puts "done" if ssh_failures.any? log :failed, 'to connect to nodes: ' + ssh_failures.join(' ') end if exitcode_failures.any? log :failed, 'to run successfully:' do exitcode_failures.each do |response| log "[%s] exit %s - %s" % [response[:host], response[:exitcode], response[:data].strip] end end end rescue Capistrano::RemoteError => err log :error, err.to_s end |
#stream(cmd, &block) ⇒ Object
similar to run(cmd, &block), but with:
-
exit codes
-
stdout and stderr are combined
108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/leap_cli/remote/leap_plugin.rb', line 108 def stream(cmd, &block) command = '%s 2>&1; echo "exitcode=$?"' % cmd run(command) do |channel, stream, data| exitcode = nil if data =~ /exitcode=(\d+)\n/ exitcode = $1.to_i data.sub!(/exitcode=(\d+)\n/,'') end yield({:host => channel[:host], :data => data, :exitcode => exitcode}) end end |
#with_task(name) ⇒ Object
This is a hairy ugly hack, exactly the kind of stuff that makes ruby dangerous and too much fun for its own good.
In most places, we run remote ssh without a current ‘task’. This works fine, except that in a few places, the behavior of capistrano ssh is controlled by the options of the current task.
We don’t want to create an actual current task, because tasks are no fun and can’t take arguments or return values. So, when we need to configure things that can only be configured in a task, we use this handy hack to fake the current task.
This is NOT thread safe, but could be made to be so with some extra work.
90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/leap_cli/remote/leap_plugin.rb', line 90 def with_task(name) task = @config.tasks[name] @config.class.send(:alias_method, :original_current_task, :current_task) @config.class.send(:define_method, :current_task, Proc.new(){ task }) begin yield ensure @config.class.send(:remove_method, :current_task) @config.class.send(:alias_method, :current_task, :original_current_task) end end |