chef-boneyard/chef-dk

Issue Invoking Knife SSH from Ruby script

gmacgregor1 opened this issue · 7 comments

Description

I am unable to invoke knife::ssh from a ruby script after specifying all the required config information. Basically trying to location a directory on a large group of servers using ruby scripting instead of knife commands, and I upgraded chefDK to 3.1.0 from 2.(something) and now I am getting the following error:

#<Thread:0x0000000003cf14a0@/home/gmacgregor1/.chefdk/gem/ruby/2.5.0/gems/net-ssh-multi-1.2.1/lib/net/ssh/multi/session.rb:554 run> terminated with exception (report_on_exception is true):
Traceback (most recent call last):
        4: from /home/gmacgregor1/.chefdk/gem/ruby/2.5.0/gems/net-ssh-multi-1.2.1/lib/net/ssh/multi/session.rb:555:in `block (2 levels) in realize_pending_connections!'
        3: from /home/gmacgregor1/.chefdk/gem/ruby/2.5.0/gems/net-ssh-multi-1.2.1/lib/net/ssh/multi/pending_connection.rb:60:in `replace_with'
        2: from /home/gmacgregor1/.chefdk/gem/ruby/2.5.0/gems/net-ssh-multi-1.2.1/lib/net/ssh/multi/pending_connection.rb:60:in `each'
        1: from /home/gmacgregor1/.chefdk/gem/ruby/2.5.0/gems/net-ssh-multi-1.2.1/lib/net/ssh/multi/pending_connection.rb:60:in `block in replace_with'
/home/gmacgregor1/.chefdk/gem/ruby/2.5.0/gems/net-ssh-multi-1.2.1/lib/net/ssh/multi/pending_connection.rb:29:in `replay_on': undefined method `open_channel' for nil:NilClass (NoMethodError)

ChefDK Version

Chef Development Kit Version: 3.1.0
chef-client version: 14.2.0
delivery version: master (6862f27aba89109a9630f0b6c6798efec56b4efe)
berks version: 7.0.4
kitchen version: 1.22.0
inspec version: 2.1.72

Platform Version

centos-release-7-5.1804.el7.centos.2.x86_64

Replication Case

I pass all the values in via a json config file, and parse them using OpenStruct.

def knife_ssh (env, concurrency, chef_path, identity_file, chef_api_key, chef_api_user, name_args, stage)
  ssh_user = 'root'
  config_file = File.join("#{chef_path}", 'knife', "#{env}", 'knife.rb')

  knife = Chef::Knife::Ssh.new
  knife.name_args = name_args

  knife.config[:ssh_user] = ssh_user
  knife.config[:concurrency] = concurrency
  knife.config[:config_file] = config_file
  knife.config[:ssh_identity_file] = identity_file
  knife.config[:client_key] = chef_api_key
  knife.config[:api_key] = chef_api_key
  knife.config[:api_client_user] = chef_api_user

  stdout = StringIO.new
  stderr = StringIO.new
  knife.ui = Chef::Knife::UI.new(stdout, stderr, STDIN, {})
  knife.configure_chef
  puts "Running Knife on #{env}! Please Wait...."
  knife.run
  Chef::Knife::Ssh.reset_config_loader!
end

Omitted some specific output, but I can include that if it is required.

/home/gmacgregor1/.chefdk/gem/ruby/2.5.0/gems/net-ssh-multi-1.2.1 indicates that this is failing in a custom gem that the user has installed, I'd try nuking that gem as if it's using that codepath then it's not ChefDK code that is breaking.

Knife isn't really meant to be used as a library and I'm curious why you're not just using net-ssh directly.

Knife is a CLI tool, not a library. We do not support this kind of usage. Use net-ssh and friends directly instead.

@coderanger Hmm, if its only a CLI tool, why does this exist https://www.rubydoc.info/github/opscode/chef/Chef/Knife/Ssh...

from https://docs.chef.io/plugin_knife_custom.html

def knife_ssh
  ssh = Chef::Knife::Ssh.new
  ssh.ui = ui
  ssh.name_args = [ server_name, ssh_command ]
  ssh.config[:ssh_user] = Chef::Config[:knife][:ssh_user] || config[:ssh_user]
  ssh.config[:ssh_password] = config[:ssh_password]
  ssh.config[:ssh_port] = Chef::Config[:knife][:ssh_port] || config[:ssh_port]
  ssh.config[:ssh_gateway] = Chef::Config[:knife][:ssh_gateway] || config[:ssh_gateway]
  ssh.config[:identity_file] = Chef::Config[:knife][:identity_file] || config[:identity_file]
  ssh.config[:manual] = true
  ssh.config[:host_key_verify] = Chef::Config[:knife][:host_key_verify] || config[:host_key_verify]
  ssh.config[:on_error] = :raise
  ssh
end

Also this was working in chefdk 2.(something) and worked very well, when I upgraded to the newer version I figured I wouldn't have much issues.

And I am not using net-ssh directly as I would like to use the knife search function to go through the list of nodes, instead of bashing-out.

That reference is merely an example of how knife ssh checks config values internally, nothing more. The fact that RubyDocs exists is a side effect of this being a gem, no implied contract or support.

Moreover, as I pointed out the source of your issue is gems you specifically installed to the DK that aren't the built-in gems.

@cheeseplus net-ssh-multi was installed by the chefdk rpm I initially installed it. I haven't installed any gems within ~/.chefdk manually.

same error on a fresh install of centos and chefdk

#<Thread:0x00007fd46c137cc8@/opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/net-ssh-multi-1.2.1/lib/net/ssh/multi/session.rb:554 run> terminated with exception (report_on_exception is true):
Traceback (most recent call last):
        4: from /opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/net-ssh-multi-1.2.1/lib/net/ssh/multi/session.rb:555:in `block (2 levels) in realize_pending_connections!'
        3: from /opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/net-ssh-multi-1.2.1/lib/net/ssh/multi/pending_connection.rb:60:in `replace_with'
        2: from /opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/net-ssh-multi-1.2.1/lib/net/ssh/multi/pending_connection.rb:60:in `each'
        1: from /opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/net-ssh-multi-1.2.1/lib/net/ssh/multi/pending_connection.rb:60:in `block in replace_with'
/opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/net-ssh-multi-1.2.1/lib/net/ssh/multi/pending_connection.rb:29:in `replay_on': undefined method `open_channel' for nil:NilClass (NoMethodError)

I think i have a way around it, but this gem is in-fact used by Knife to do concurrent sessions.

lock commented

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.