Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

machine_execute and machine_file fails with undefined method `[]' for nil:NilClass #94

Open
Ryuzavi opened this issue Nov 29, 2018 · 4 comments

Comments

@Ryuzavi
Copy link

Ryuzavi commented Nov 29, 2018

Versions:

  • Version of Chef-Provisioning: 2.7.2
  • Version of Chef-Provisioning-vSphere: 2.3.1

Platform Details

  • Version of vSphere/vCenter: 6.0.0
  • Version of ESXi: 6.0.0

Scenario:

When trying to run either the machine_execute or machine_file resources on vsphere they both fail with the generic error undefined method []' for nil:NilClass`

Steps to Reproduce:

Set up Chef Provisioning vSphere as normal and try to execute the machine_execute or machine_file resource, e.g.

machine_execute 'hostname' do
  machine 'test'
  live_stream true
end

Expected Result:

For the command to be run successfully on the box or the action performed on the file.

Actual Result:

Generic undefined method []' for nil:NilClass` error suggesting an attribute somewhere isn't being set correctly

    ================================================================================
    Error executing action `run` on resource 'machine_execute[hostname]'
    ================================================================================
    
    NoMethodError
    -------------
    undefined method `[]' for nil:NilClass
    
    Resource Declaration:
    ---------------------
    # In /root/.chef/local-mode-cache/cache/cookbooks/test/recipes/build.rb
    
     33:   machine_execute 'hostname' do
     34:     machine 'test'
     35:     live_stream true
     36:   end
     37: 
    
    Compiled Resource:
    ------------------
    # Declared in /root/.chef/local-mode-cache/cache/cookbooks/test/recipes/build.rb:33:in `from_file'
    
    machine_execute("hostname") do
      action [:run]
      default_guard_interpreter :default
      chef_server {:chef_server_url=>"chefzero://localhost:8889", :options=>{:client_name=>"****", :signing_key_filename=>nil, :api_version=>"0"}}
      declared_type :machine_execute
      cookbook_name "test"
      recipe_name "build"
      machine "test"
      live_stream true
      command "hostname"
    end
    
    System Info:
    ------------
    chef_version=14.7.17
    platform=ubuntu
    platform_version=18.04
    ruby=ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-linux]
    program_name=/opt/chefdk/bin/chef-client
@jjlimepoint
Copy link

jjlimepoint commented Nov 29, 2018

Can reproduce - issue seems to be machine_for is referencing machine_options[:bootstrap_options][:ssh] but bootstrap optionsa re not coming through :(

EDIT: whereas other drivers put the entire bootstrap options in machine_spec.reference, and use that, c-p-vsphere does not, and relies on "what is passed in" - so this can never have worked :).

@jjlimepoint
Copy link

Hilariously, you can work around this by putting a machine_options in your client.rb file that you use - it will merge this with the exsting config. This is obviously not ideal, but will get you running - so mine looks like this:

machine_options Hash({ :bootstrap_options => { :ssh => { :user => root, :password => 'redacted' }}})

The correct fix would be to hook up the correct hookups between these to pass in the machine_options from the resource, of course - chef-provisioning assumes that's all been persisted to machine_spec.reference, which goes into node attributes. but we probably don't want to store them in the node attributes, since they can contain passwords - which means hooking up something else to keep track of it during the run.... I played the whole "lookup the resource" game, which did kind of work for getting the machine options out, but again this is not the worlds simplest patch(tm) (for one, you can't just grab resource(machine[name]), due to machine_batch).

Indeed, the code is literally:

      machine_options = { :convergence_options => { :chef_server => chef_server } }
      machine_options = Cheffish::MergedConfig.new(config[:machine_options], machine_options) if config[:machine_options]
      driver.connect_to_machine(machine_spec, machine_options)

you'll note the lack of any refernce to our actual machine, or the contents of machien spec - which means it is always going to break unless the driver is keeping track internally of the credentials. whee! The right thing to do, would be for chef-provisioning to take that machine object as an input, and merge in the machine_options from the machine object, of course.

@Ryuzavi
Copy link
Author

Ryuzavi commented Nov 30, 2018

Interesting stuff indeed. I thought it might be something fundamental like that. Shame it doesn't appear to be straightforward to fix. I'll certainly give that client.rb workaround a try for now. I wonder how other drivers are handling this, like AWS?

@jjlimepoint
Copy link

AWS handles this by fundamentally being a much more complicated driver, and hence keeping track internally of what it did - my first impulse was/is to modify the vsphere drive to do the same, but I'm not inclined to add that level of complexity - I did get a quick fix working for machine rather than machine_batch by modifying chef-provisioning itself to go and fetch the machine_options from machine when looking them up, which appears to be how it was always "intended" to work for simpler drivers - but there is a bit of complexity around machine_batch that i haven't had a chance to look at yet (right now, i'm just using net::ssh in my own code here, but honsetly, i'm keen to cut that out!)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants