puppetlabs / puppet-resource_api

This library provides a simple way to write new native resources for https://puppet.com.
Apache License 2.0
27 stars 41 forks source link

How to execute local commands in a provider #216

Open DavidS opened 4 years ago

DavidS commented 4 years ago

Use Case

Local providers need to execute commands to inspect and manage local resources.

Describe the Solution You Would Like

There was a Commands API in early versions of the Resource API, which ticked a number of boxes around ease-of-use, safety, platform-awareness, and integration with Resource API patterns. That iteration was built on the childprocess gem which - due to its dependency on FFI - was not acceptable to ship in the puppet agent.

Having a dedicated Resource API layer would also enable us to do advanced checks like verifying noop-correctness (see PDK-565 for examples).

Describe Alternatives You've Considered

Additional Context

Originally filed as https://tickets.puppetlabs.com/browse/PDK-847 .

@kreeuwijk said

As someone who has only just started to [dip my toes|https://github.com/kreeuwijk/puppet-patch_mgmt/blob/master/lib/puppet/provider/patch_win/patch_win.rb] into the types & providers development space, let me give you an outside perspective to what the experience is today for a starting Puppet developer:

TLDR: The learning curve is still very, very steep if you're not a skilled Ruby developer. The Resource API needs to do more to make provider development easier.

While the PDK has helped in creating the skeleton for new types & providers, the main aspect of executing actions is still mostly left to the knowledge of the developer:

  • Running external processes (bash, powerhshell) and doing error handling & output capture
  • Transforming external process output into consumable puppet resources
  • Interacting with external APIs

I've spent all day yesterday researching a useable way to execute some Powershell code in a custom provider, after I learned that the Puppet::ResourceApi:Command is no longer part of the Resource API (even though the apt-key2 example that the Resource API documentation points to, still has it in its code). I've tried to use Open3 but found it too difficult and cumbersome, and finally gave up and used exec() to at least get something working.

The Resource API should take care of this basic need for me. It should provide a generalized way to execute external code (bash, batch, powershell, etc) and provide core capabilities like error handling, context awareness and output capturing. Right now I don't even know how to preserve context awareness since I can't use Puppet::ResourceApi:Command.

I would like to see clearer guidance on how to execute commands/processes with the Resource API in the state that it's in today, and how to handle context awareness in relationship to that. Then hopefully this guidance can be updated later when we do have a generalized & easier way to deal with this challenge.

DavidS commented 4 years ago

We're about to ship FFI in all agent platforms again, so this might be easier in the near future.

nmaludy commented 4 years ago

+1

isaiahfrantz commented 3 years ago

Anything happening with this issue? Its pretty crazy that such an important wrapper from the low level api was not implemented in the new-and improved simplified api. I have been searching high and low for examples that run local command but every example I saw used net::http to call a web api, not a single one that ran a local binary!!

DavidS commented 3 years ago

https://puppetcommunity.slack.com/archives/C0W1X7ZAL/p1616535689004600

stschulte commented 4 months ago

Is there any update? I am maintaining a puppet module that I wrote quite a while ago (for puppet 3) and I was thinking about porting my type/provider to the resource API as I thought the old interface was discouraged (supported by the fact that pdk new provider provides a skeleton for the resource API)

Right now the documentation of the resource API explains the concept on two examples yum and apt and they both don't show how running local commands are implemented. The APT example simply shows a single function call

@apt_key_cmd.run(context, action, key_id)

without showing where @apt_key_cmd.run comes from nor what the function signature actually is.

If this is not possible right now is it fair to assume that the Resource API is targeted against devices (which are managed through transports), not local providers?