diff options
Diffstat (limited to 'lib/leap_cli')
| -rw-r--r-- | lib/leap_cli/cloud.rb | 3 | ||||
| -rw-r--r-- | lib/leap_cli/cloud/dependencies.rb | 47 | ||||
| -rw-r--r-- | lib/leap_cli/commands/cert.rb (renamed from lib/leap_cli/commands/ca.rb) | 68 | ||||
| -rw-r--r-- | lib/leap_cli/commands/compile.rb | 2 | ||||
| -rw-r--r-- | lib/leap_cli/commands/node.rb | 27 | ||||
| -rw-r--r-- | lib/leap_cli/commands/ping.rb | 58 | ||||
| -rw-r--r-- | lib/leap_cli/commands/run.rb | 53 | ||||
| -rw-r--r-- | lib/leap_cli/commands/test.rb | 2 | ||||
| -rw-r--r-- | lib/leap_cli/commands/user.rb | 37 | ||||
| -rw-r--r-- | lib/leap_cli/commands/vagrant.rb | 4 | ||||
| -rw-r--r-- | lib/leap_cli/commands/vm.rb | 5 | ||||
| -rw-r--r-- | lib/leap_cli/config/environment.rb | 30 | ||||
| -rw-r--r-- | lib/leap_cli/config/manager.rb | 15 | ||||
| -rw-r--r-- | lib/leap_cli/config/node.rb | 4 | ||||
| -rw-r--r-- | lib/leap_cli/config/object_list.rb | 4 | ||||
| -rw-r--r-- | lib/leap_cli/macros/haproxy.rb | 73 | ||||
| -rw-r--r-- | lib/leap_cli/macros/stunnel.rb | 14 | ||||
| -rw-r--r-- | lib/leap_cli/ssh/backend.rb | 2 | ||||
| -rw-r--r-- | lib/leap_cli/ssh/key.rb | 11 | 
19 files changed, 305 insertions, 154 deletions
| diff --git a/lib/leap_cli/cloud.rb b/lib/leap_cli/cloud.rb index 268cea38..b8e45b3b 100644 --- a/lib/leap_cli/cloud.rb +++ b/lib/leap_cli/cloud.rb @@ -1,4 +1,3 @@ - -require 'fog/aws' +require_relative 'cloud/dependencies.rb'  require_relative 'cloud/cloud.rb'  require_relative 'cloud/image.rb' diff --git a/lib/leap_cli/cloud/dependencies.rb b/lib/leap_cli/cloud/dependencies.rb index fd690e59..670d6134 100644 --- a/lib/leap_cli/cloud/dependencies.rb +++ b/lib/leap_cli/cloud/dependencies.rb @@ -1,40 +1,37 @@  # -# I am not sure this is a good idea, but it might be. Tricky, so disabled for now +# Ensure that the needed fog gems are installed  # - -=begin  module LeapCli    class Cloud -    def self.check_required_gems -      begin -        require "fog" -      rescue LoadError -        bail! do -          log :error, "The 'vm' command requires the gem 'fog-core'. Please run `gem install fog-core` and try again." -        end -      end +    SUPPORTED = { +      'aws' => {require: 'fog/aws', gem: 'fog-aws'} +    }.freeze -      fog_gems = @cloud.required_gems -      if !options[:mock] && fog_gems.empty? -        bail! do -          log :warning, "no vm providers are configured in cloud.json." -          log "You must have credentials for one of: #{@cloud.possible_apis.join(', ')}." +    def self.check_dependencies!(config) +      required_gem = map_api_to_gem(config['api']) +      if required_gem.nil? +        Util.bail! do +          Util.log :error, "The API '#{config['api']}' specified in cloud.json is not one that I know how to speak. Try one of #{supported_list}."          end        end -      fog_gems.each do |name, gem_name| -        begin -          require gem_name.sub('-','/') -        rescue LoadError -          bail! do -            log :error, "The 'vm' command requires the gem '#{gem_name}' (because of what is configured in cloud.json)." -            log "Please run `sudo gem install #{gem_name}` and try again." -          end +      begin +        require required_gem[:require] +      rescue LoadError +        Util.bail! do +          Util.log :error, "The 'vm' command requires the gem '#{required_gem[:gem]}'. Please run `gem install #{required_gem[:gem]}` and try again." +          Util.log "(make sure you install the gem in the ruby #{RUBY_VERSION} environment)"          end        end      end +    def self.supported_list +      SUPPORTED.keys.join(', ') +    end + +    def self.map_api_to_gem(api) +      SUPPORTED[api] +    end    end  end -=end
\ No newline at end of file diff --git a/lib/leap_cli/commands/ca.rb b/lib/leap_cli/commands/cert.rb index 3c5fc7d5..68fa9444 100644 --- a/lib/leap_cli/commands/ca.rb +++ b/lib/leap_cli/commands/cert.rb @@ -102,13 +102,13 @@ module LeapCli; module Commands    def generate_test_client_cert(prefix=nil)      require 'leap_cli/x509'      cert = CertificateAuthority::Certificate.new -    cert.serial_number.number = cert_serial_number(provider.domain) -    cert.subject.common_name = [prefix, random_common_name(provider.domain)].join +    cert.serial_number.number = X509.cert_serial_number(provider.domain) +    cert.subject.common_name = [prefix, X509.random_common_name(provider.domain)].join      cert.not_before = X509.yesterday      cert.not_after  = X509.yesterday.advance(:years => 1)      cert.key_material.generate_key(1024) # just for testing, remember! -    cert.parent = client_ca_root -    cert.sign! client_test_signing_profile +    cert.parent = X509.client_ca_root +    cert.sign! X509.client_test_signing_profile      yield cert.key_material.private_key.to_pem, cert.to_pem    end @@ -281,11 +281,13 @@ module LeapCli; module Commands      if status == 'valid'        log 'authorized!', color: :green, style: :bold      elsif status == 'error' -      bail! :error, message +      bail! :error, message.inspect      elsif status == 'unauthorized' -      bail!(:unauthorized, message, color: :yellow, style: :bold) do +      bail!(:unauthorized, message.inspect, color: :yellow, style: :bold) do          log 'You must first run `leap cert register` to register the account key with letsencrypt.org'        end +    else +      bail!(:error, "unrecognized status: #{status.inspect}, #{message.inspect}")      end      log :fetching, "new certificate from letsencrypt.org" @@ -335,31 +337,41 @@ module LeapCli; module Commands    # This method will bail if any checks fail.    #    def domain_ready_for_acme!(domain) -    begin -      uri = URI("https://#{domain}/.well-known/acme-challenge/ok") -      options = { -        use_ssl: true, -        open_timeout: 5, -        verify_mode: OpenSSL::SSL::VERIFY_NONE -      } -      Net::HTTP.start(uri.host, uri.port, options) do |http| -        http.request(Net::HTTP::Get.new(uri)) do |response| -          if !response.is_a?(Net::HTTPSuccess) -            bail!(:error, "Could not GET %s" % uri) do -              log "%s %s" % [response.code, response.message] -              log "You may need to run `leap deploy`" -            end +    uri = URI("https://#{domain}/.well-known/acme-challenge/ok") +    options = { +      use_ssl: true, +      open_timeout: 5, +      verify_mode: OpenSSL::SSL::VERIFY_NONE +    } +    http_get(uri, options) +  end + +  private + +  def http_get(uri, options, limit = 10) +    raise ArgumentError, "HTTP redirect too deep (#{uri})" if limit == 0 +    Net::HTTP.start(uri.host, uri.port, options) do |http| +      http.request(Net::HTTP::Get.new(uri)) do |response| +        case response +        when Net::HTTPSuccess then +          return response +        when Net::HTTPRedirection then +          return http_get(URI(response['location']), options, limit - 1) +        else +          bail!(:error, "Could not GET %s" % uri) do +            log "%s %s" % [response.code, response.message] +            log "You may need to run `leap deploy`"            end          end        end -    rescue Errno::ETIMEDOUT, Net::OpenTimeout -      bail! :error, "Connection attempt timed out: %s" % uri -    rescue Interrupt -      bail! -    rescue StandardError => exc -      bail!(:error, "Could not GET %s" % uri) do -        log exc.to_s -      end +    end +  rescue Errno::ETIMEDOUT, Net::OpenTimeout +    bail! :error, "Connection attempt timed out: %s" % uri +  rescue Interrupt +    bail! +  rescue StandardError => exc +    bail!(:error, "Could not GET %s" % uri) do +      log exc.to_s      end    end diff --git a/lib/leap_cli/commands/compile.rb b/lib/leap_cli/commands/compile.rb index 92c879d7..16dff3df 100644 --- a/lib/leap_cli/commands/compile.rb +++ b/lib/leap_cli/commands/compile.rb @@ -155,7 +155,7 @@ module LeapCli        buffer = StringIO.new        keys = Dir.glob(path([:user_ssh, '*']))        if keys.empty? -        bail! "You must have at least one public SSH user key configured in order to proceed. See `leap help add-user`." +        bail! "You must have at least one public SSH user key configured in order to proceed. See `leap help user add`."        end        if file_exists?(path(:monitor_pub_key))          keys << path(:monitor_pub_key) diff --git a/lib/leap_cli/commands/node.rb b/lib/leap_cli/commands/node.rb index 60540de9..9cde15bc 100644 --- a/lib/leap_cli/commands/node.rb +++ b/lib/leap_cli/commands/node.rb @@ -45,6 +45,23 @@ module LeapCli; module Commands          do_node_rm(global_options, options, args)        end      end + +    node.desc 'Mark a node as disabled.' +    node.arg_name 'NAME' +    node.command :disable do |cmd| +      cmd.action do |global_options,options,args| +        do_node_disable(global_options, options, args) +      end +    end + +    node.desc 'Mark a node as enabled.' +    node.arg_name 'NAME' +    node.command :enable do |cmd| +      cmd.action do |global_options,options,args| +        do_node_enable(global_options, options, args) +      end +    end +    end    ## @@ -126,4 +143,14 @@ module LeapCli; module Commands      remove_node_facts(node.name)    end +  def do_node_enable(global, options, args) +    node = get_node_from_args(args, include_disabled: true) +    node.update_json({}, remove: ["enabled"]) +  end + +  def do_node_disable(global, options, args) +    node = get_node_from_args(args, include_disabled: true) +    node.update_json("enabled" => false) +  end +  end; end diff --git a/lib/leap_cli/commands/ping.rb b/lib/leap_cli/commands/ping.rb new file mode 100644 index 00000000..4283d9b3 --- /dev/null +++ b/lib/leap_cli/commands/ping.rb @@ -0,0 +1,58 @@ +module LeapCli; module Commands + +  desc "Ping nodes to see if they are alive." +  long_desc "Attempts to ping each node in the FILTER set." +  arg_name "FILTER" +  command :ping do |c| +    c.flag 'timeout', :arg_name => "TIMEOUT", +      :default_value => 2, :desc => 'Wait at most TIMEOUT seconds.' +    c.flag 'count', :arg_name => "COUNT", +      :default_value => 2, :desc => 'Ping COUNT times.' +    c.action do |global, options, args| +      do_ping(global, options, args) +    end +  end + +  private + +  def do_ping(global, options, args) +    assert_bin!('ping') + +    timeout = [options[:timeout].to_i, 1].max +    count   = [options[:count].to_i, 1].max +    nodes   = nil + +    if args && args.any? +      node = manager.disabled_node(args.first) +      if node +        nodes = Config::ObjectList.new +        nodes.add(node.name, node) +      end +    end + +    nodes ||= manager.filter! args + +    threads = [] +    nodes.each_node do |node| +      threads << Thread.new do +        cmd = "ping -i 0.2 -n -q -W #{timeout} -c #{count} #{node.ip_address} 2>&1" +        log(2, cmd) +        output = `#{cmd}` +        if $?.success? +          last = output.split("\n").last +          times = last.split('=').last.strip +          min, avg, max, mdev = times.split('/') +          log("ping #{min} ms", host: node.name, color: :green) +        else +          log(:failed, "to ping #{node.ip_address}", host: node.name) +        end +      end +    end +    threads.map(&:join) + +    log("done") +  end + +end; end + + diff --git a/lib/leap_cli/commands/run.rb b/lib/leap_cli/commands/run.rb index cad9b7a0..9149d594 100644 --- a/lib/leap_cli/commands/run.rb +++ b/lib/leap_cli/commands/run.rb @@ -3,13 +3,27 @@ module LeapCli; module Commands    desc 'Run a shell command remotely'    long_desc "Runs the specified command COMMAND on each node in the FILTER set. " +              "For example, `leap run 'uname -a' webapp`" -  arg_name 'COMMAND FILTER'    command :run do |c|      c.switch 'stream', :default => false, :desc => 'If set, stream the output as it arrives. (default: --stream for a single node, --no-stream for multiple nodes)'      c.flag 'port', :arg_name => 'SSH_PORT', :desc => 'Override default SSH port used when trying to connect to the server.' -    c.action do |global, options, args| -      run_shell_command(global, options, args) + +    c.desc 'Run an arbitrary shell command.' +    c.arg_name 'FILTER', optional: true +    c.command :command do |command| +      command.action do |global, options, args| +        run_shell_command(global, options, args) +      end +    end + +    c.desc 'Generate one or more new invite codes.' +    c.arg_name '[COUNT] [ENVIRONMENT]' +    c.command :invite do |invite| +      invite.action do |global_options,options,args| +        run_new_invites(global_options, options, args) +      end      end + +    c.default_command :command    end    private @@ -27,6 +41,39 @@ module LeapCli; module Commands      end    end +  CMD_NEW_INVITES="cd /srv/leap/webapp; RAILS_ENV=production bundle exec rake \"generate_invites[NUM,USES]\"" + +  def run_new_invites(global, options, args) +    require 'leap_cli/ssh' +    count = 1 +    uses  = 1 +    env   = nil +    arg1  = args.shift +    arg2  = args.shift +    if arg1 && arg2 +      env   = manager.env(arg2) +      count = arg1 +    elsif arg1 +      env = manager.env(arg1) +    else +      env = manager.env(nil) +    end +    unless env +      bail! "Environment name you specified does not match one that is available. See `leap env ls` for the available names" +    end + +    env_name = env.name == 'default' ? nil : env.name +    webapp_nodes = env.nodes[:environment => env_name][:services => 'webapp'].first +    if webapp_nodes.empty? +      bail! "Could not find a webapp node for the specified environment" +    end +    stream_command( +      webapp_nodes, +      CMD_NEW_INVITES.sub('NUM', count.to_s).sub('USES', uses.to_s), +      options +    ) +  end +    def capture_command(nodes, cmd, options)      SSH.remote_command(nodes, options) do |ssh, host|        output = ssh.capture(cmd, :log_output => false) diff --git a/lib/leap_cli/commands/test.rb b/lib/leap_cli/commands/test.rb index 70eb00fd..e2815aae 100644 --- a/lib/leap_cli/commands/test.rb +++ b/lib/leap_cli/commands/test.rb @@ -35,7 +35,7 @@ module LeapCli; module Commands          SSH::remote_command(node, options) do |ssh, host|            ssh.stream(test_cmd(options), :raise_error => true, :log_wrap => true)          end -      rescue LeapCli::SSH::ExecuteError +      rescue LeapCli::SSH::TimeoutError, SSHKit::Runner::ExecuteError, SSHKit::Command::Failed          if options[:continue]            exit_status(1)          else diff --git a/lib/leap_cli/commands/user.rb b/lib/leap_cli/commands/user.rb index 1ca92719..7fd5f52d 100644 --- a/lib/leap_cli/commands/user.rb +++ b/lib/leap_cli/commands/user.rb @@ -113,14 +113,42 @@ module LeapCli      def do_list_users(global, options, args)        require 'leap_cli/ssh' +      ssh_keys = {} +      Dir.glob("#{ENV['HOME']}/.ssh/*.pub").each do |keyfile| +        key = SSH::Key.load(keyfile) +        ssh_keys[key.fingerprint] = key if key +      end + +      ssh_agent_keys = {} +      if !`which ssh-add`.empty? +        `ssh-add -L`.split("\n").each do |keystring| +          key = SSH::Key.load(keystring) +          ssh_agent_keys[key.fingerprint] = key if key +        end +      end +        Dir.glob(path([:user_ssh, '*'])).each do |keyfile|          username = File.basename(File.dirname(keyfile))          log username, :color => :cyan do            log Path.relative_path(keyfile)            key = SSH::Key.load(keyfile) -          log 'SSH MD5 fingerprint: ' + key.fingerprint(:digest => :md5, :type => :ssh, :encoding => :hex) -          log 'SSH SHA256 fingerprint: ' + key.fingerprint(:digest => :sha256, :type => :ssh, :encoding => :base64) -          log 'DER MD5 fingerprint: ' + key.fingerprint(:digest => :md5, :type => :der, :encoding => :hex) +          if key.nil? +            log :warning, "could not read ssh key #{keyfile}" do +              log "currently, only these ssh key types are supported: " + SSH::Key::SUPPORTED_TYPES.join(", ") +            end +          else +            log 'SSH MD5 fingerprint: ' + key.fingerprint(:digest => :md5, :type => :ssh, :encoding => :hex) +            log 'SSH SHA256 fingerprint: ' + key.fingerprint(:digest => :sha256, :type => :ssh, :encoding => :base64) +            log 'DER MD5 fingerprint: ' + key.fingerprint(:digest => :md5, :type => :der, :encoding => :hex) +            if ssh_keys[key.fingerprint] +              log 'Matches local key: ' + ssh_keys[key.fingerprint].filename, color: :green +              if ssh_agent_keys[key.fingerprint] +                log 'Matches ssh-agent key: ' + ssh_agent_keys[key.fingerprint].summary(encoding: :base64), color: :green +              else +                log :error, 'No matching key in the ssh-agent' +              end +            end +          end          end        end      end @@ -154,6 +182,9 @@ module LeapCli          end        else          key_index = 0 +        log "Picking the only compatible ssh key: "+ ssh_keys[key_index].filename do +          log ssh_keys[key_index].summary +        end        end        return ssh_keys[key_index] diff --git a/lib/leap_cli/commands/vagrant.rb b/lib/leap_cli/commands/vagrant.rb index f8a75b61..78b2fede 100644 --- a/lib/leap_cli/commands/vagrant.rb +++ b/lib/leap_cli/commands/vagrant.rb @@ -132,10 +132,10 @@ module LeapCli; module Commands          lines << %[    config.vm.provider "virtualbox" do |v|]          lines << %[      v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]]          lines << %[      v.name   = "#{node.name}"] -        lines << %[      v.memory = 1536] +        lines << %[      v.memory = 2048]          lines << %[    end]          lines << %[    config.vm.provider "libvirt" do |v|] -        lines << %[      v.memory = 1536] +        lines << %[      v.memory = 2048]          lines << %[    end]          lines << %[    #{leapfile.custom_vagrant_vm_line}] if leapfile.custom_vagrant_vm_line          lines << %[  end] diff --git a/lib/leap_cli/commands/vm.rb b/lib/leap_cli/commands/vm.rb index 790774f1..6f97dbce 100644 --- a/lib/leap_cli/commands/vm.rb +++ b/lib/leap_cli/commands/vm.rb @@ -415,7 +415,6 @@ module LeapCli; module Commands      config = manager.env.cloud      name = nil      if options[:mock] -      Fog.mock!        name = 'mock_aws'        config['mock_aws'] = {          "api" => "aws", @@ -451,6 +450,10 @@ module LeapCli; module Commands      assert! entry['api'] == 'aws', "cloud.json: currently, only 'aws' is supported for `api`."      assert! entry['vendor'] == 'aws', "cloud.json: currently, only 'aws' is supported for `vendor`." +    LeapCli::Cloud::check_dependencies!(entry) +    if options[:mock] +      Fog.mock! +    end      return LeapCli::Cloud.new(name, entry, node)    end diff --git a/lib/leap_cli/config/environment.rb b/lib/leap_cli/config/environment.rb index ce570839..0410ef5b 100644 --- a/lib/leap_cli/config/environment.rb +++ b/lib/leap_cli/config/environment.rb @@ -122,14 +122,25 @@ module LeapCli; module Config      end      # -    # Alters the node's json config file. Unfortunately, doing this will -    # strip out all the comments. +    # Alters the node's json config file. As a side effect, all comments get +    # moved to the top of the file.      # -    def update_node_json(node, new_values) +    # NOTE: This does a shallow merge! In other words, a call like this... +    # +    #     update_node_json(node, {"webapp" => {"domain" => "example.org"}) +    # +    # ...is probably not what you want, because it will entirely remove all +    # existing entries under "webapp". +    # +    def update_node_json(node, new_values, options=nil)        node_json_path = Path.named_path([:node_config, node.name]) +      comments       = read_comments(node_json_path)        old_data       = load_json(node_json_path, Config::Node) +      options && options[:remove] && options[:remove].each do |key| +        old_data.delete(key) +      end        new_data       = old_data.merge(new_values) -      new_contents   = JSON.sorted_generate(new_data) + "\n" +      new_contents   = [comments, JSON.sorted_generate(new_data), "\n"].join        Util::write_file! node_json_path, new_contents      end @@ -152,6 +163,17 @@ module LeapCli; module Config        results      end +    def read_comments(filename) +      buffer = StringIO.new +      File.open(filename, "rb", :encoding => 'UTF-8') do |f| +        while (line = f.gets) +          next unless line =~ /^\s*\/\// +          buffer << line +        end +      end +      return buffer.string.force_encoding('utf-8') +    end +      def load_json(filename, object_class, options={})        if !File.exist?(filename)          return object_class.new(self) diff --git a/lib/leap_cli/config/manager.rb b/lib/leap_cli/config/manager.rb index d69a5808..a9f1a85f 100644 --- a/lib/leap_cli/config/manager.rb +++ b/lib/leap_cli/config/manager.rb @@ -342,14 +342,25 @@ module LeapCli          if node.vagrant?            return self.env("local")          else -          environment = self.env(default_environment) +          environment = nil            if node['tags']              node['tags'].to_a.each do |tag|                if self.environment_names.include?(tag) -                environment = self.env(tag) +                if environment.nil? +                  environment = self.env(tag) +                else +                  LeapCli::Util.bail! do +                    LeapCli.log( +                      :error, +                      "The node '%s' is invalid, because it cannot have two environments ('%s' and '%s')." % +                      [node.name, environment.name, tag] +                    ) +                  end +                end                end              end            end +          environment ||= self.env(default_environment)            return environment          end        end diff --git a/lib/leap_cli/config/node.rb b/lib/leap_cli/config/node.rb index 23abdee3..a7c5c1e4 100644 --- a/lib/leap_cli/config/node.rb +++ b/lib/leap_cli/config/node.rb @@ -169,8 +169,8 @@ module LeapCli; module Config      #      # modifies the config file nodes/NAME.json for this node.      # -    def update_json(new_values) -      self.env.update_node_json(node, new_values) +    def update_json(new_values, options=nil) +      self.env.update_node_json(node, new_values, options)      end      # diff --git a/lib/leap_cli/config/object_list.rb b/lib/leap_cli/config/object_list.rb index 80f89d92..815864e4 100644 --- a/lib/leap_cli/config/object_list.rb +++ b/lib/leap_cli/config/object_list.rb @@ -49,6 +49,10 @@ module LeapCli          end        end +      def first +        ObjectList.new(self.values.first) +      end +        def exclude(node)          list = self.dup          list.delete(node.name) diff --git a/lib/leap_cli/macros/haproxy.rb b/lib/leap_cli/macros/haproxy.rb deleted file mode 100644 index 3fef24c4..00000000 --- a/lib/leap_cli/macros/haproxy.rb +++ /dev/null @@ -1,73 +0,0 @@ -# encoding: utf-8 - -## -## HAPROXY -## - -module LeapCli -  module Macro - -    # -    # creates a hash suitable for configuring haproxy. the key is the node name of the server we are proxying to. -    # -    # * node_list - a hash of nodes for the haproxy servers -    # * stunnel_client - contains the mappings to local ports for each server node. -    # * non_stunnel_port - in case self is included in node_list, the port to connect to. -    # -    # 1000 weight is used for nodes in the same location. -    # 100 otherwise. -    # -    def haproxy_servers(node_list, stunnel_clients, non_stunnel_port=nil) -      default_weight = 10 -      local_weight = 100 - -      # record the hosts_file -      hostnames(node_list) - -      # create a simple map for node name -> local stunnel accept port -      accept_ports = stunnel_clients.inject({}) do |hsh, stunnel_entry| -        name = stunnel_entry.first.sub(/_[0-9]+$/, '') -        hsh[name] = stunnel_entry.last['accept_port'] -        hsh -      end - -      # if one the nodes in the node list is ourself, then there will not be a stunnel to it, -      # but we need to include it anyway in the haproxy config. -      if node_list[self.name] && non_stunnel_port -        accept_ports[self.name] = non_stunnel_port -      end - -      # create the first pass of the servers hash -      servers = node_list.values.inject(Config::ObjectList.new) do |hsh, node| -        # make sure we have a port to talk to -        unless accept_ports[node.name] -          error "haproxy needs a local port to talk to when connecting to #{node.name}" -        end -        weight = default_weight -        try { -          weight = local_weight if self.location.name == node.location.name -        } -        hsh[node.name] = Config::Object[ -          'backup', false, -          'host', 'localhost', -          'port', accept_ports[node.name], -          'weight', weight -        ] -        if node.services.include?('couchdb') -          hsh[node.name]['writable'] = node.couch.mode != 'mirror' -        end -        hsh -      end - -      # if there are some local servers, make the others backup -      if servers.detect{|k,v| v.weight == local_weight} -        servers.each do |k,server| -          server['backup'] = server['weight'] == default_weight -        end -      end - -      return servers -    end - -  end -end diff --git a/lib/leap_cli/macros/stunnel.rb b/lib/leap_cli/macros/stunnel.rb index 821bda38..59a38fad 100644 --- a/lib/leap_cli/macros/stunnel.rb +++ b/lib/leap_cli/macros/stunnel.rb @@ -87,6 +87,18 @@ module LeapCli        }      end +    # +    # what it the port of the couchdb we should connect to. +    # host will always be localhost. +    # +    def couchdb_port +      if services.include?('couchdb') +        couch.port +      else +        stunnel.clients.couch_client.values.first.accept_port +      end +    end +      private      # @@ -103,4 +115,4 @@ module LeapCli      end    end -end
\ No newline at end of file +end diff --git a/lib/leap_cli/ssh/backend.rb b/lib/leap_cli/ssh/backend.rb index 3894d815..599fc9a0 100644 --- a/lib/leap_cli/ssh/backend.rb +++ b/lib/leap_cli/ssh/backend.rb @@ -178,7 +178,7 @@ module LeapCli        rescue StandardError => exc          if exc.is_a?(SSHKit::Command::Failed) || exc.is_a?(SSHKit::Runner::ExecuteError)            if @options[:raise_error] -            raise LeapCli::SSH::ExecuteError, exc.to_s +            raise exc            elsif @options[:fail_msg]              @logger.log(@options[:fail_msg], host: @host.hostname, :color => :red)            else diff --git a/lib/leap_cli/ssh/key.rb b/lib/leap_cli/ssh/key.rb index 76223b7e..108b6137 100644 --- a/lib/leap_cli/ssh/key.rb +++ b/lib/leap_cli/ssh/key.rb @@ -254,9 +254,9 @@ module LeapCli          end          if digest == "MD5" && encoding == :hex -          return fp.scan(/../).join(':') +          return fp.strip.scan(/../).join(':')          else -          return fp +          return fp.strip          end        end @@ -267,11 +267,12 @@ module LeapCli          Net::SSH::Buffer.from(:key, @key).to_s.split("\001\000").last.size * 8        end -      def summary +      def summary(type: :ssh, digest: :sha256, encoding: :hex) +        fp = digest.to_s.upcase + ":" + self.fingerprint(type: type, digest: digest, encoding: encoding)          if self.filename -          "%s %s %s (%s)" % [self.type, self.bits, self.fingerprint, File.basename(self.filename)] +          "%s %s %s (%s)" % [self.type, self.bits, fp, File.basename(self.filename)]          else -          "%s %s %s" % [self.type, self.bits, self.fingerprint] +          "%s %s %s" % [self.type, self.bits, fp]          end        end | 
