Issue #6780 has been updated by Daniel Pittman.

Assignee set to Daniel Pittman

After some investigation I have identified that we need to build this in two 
parts:

In part one we need a Ruby API level type checking and, possibly, coercion 
mechanism for the inputs.  Ideally this should be as low-effort as possible for 
the user, which suggests that we desire (but do not absolutely require):

 * when passed a basic class, use the obvious transformations. (eg: `String`, 
`Integer`)
 * when passed a richer class, introspect and add `from_yaml`, `from_pson`, 
`from_hash`, and related transformations automatically.
 * we should have some more effective mechanism for `from_s` than 
`Foo.new("whatever")`, since that is uncomfortable in Ruby if we have a rich 
initializer.
 * when we support multiple input types for the `foo` argument we should 
generate a `foo-type` option, taking a set of options matching the 
transformations.
 * the automatically generated type option should take precedence over existing 
options; it should *not* be possible to eliminate the generated parameter.

The Ruby API should automatically do this type checking and raise; while this 
isn't strictly the Ruby way, it makes sense in an API: we write the code to 
have strong typing where it matters, and avoid the cost everywhere behind the 
API.  This has the programmer-facing benefit that they don't need to think 
about type checking.

Where we support it, the Ruby API should coerce automatically, to make it 
easier for Ruby level invokers and front-end authors to interact with the 
system without having to duplicate the existing logic around coercion; if we 
know how to do it, why make them repeat themselves?


In part two we need to wire up some front ends, especially the CLI, and 
identify what changes are needed to that core to support that transformation.  
Ideally we should be able to sensibly avoid excess type checking when we talk 
to OptParse, so it isn't necessary to register classes there to get sane 
behaviour.  They should be able to delegate pretty much blind to the back-end 
and just work™.

Ideally, we should wire up an HTTP-based (strings, mostly) and MCollective / 
JSON-deserialized-data-structure input, which exercises all the parts of the 
system that should be used.


Still outstanding?  We want to have this rich typing and coercion for 
positional parameters in the Ruby API, but can't introspect the names of those 
parameters without nasty tricks (eg: read the source file at runtime) under 
Ruby 1.8.  We can solve that a few ways:

 * we can play nasty tricks, using `caller` and reading Ruby source code at 
runtime to introspect the parameter names.  Not really desired, because it is 
nasty, fragile, and doesn't support coercion unless we actually rewrite the 
source code at require time, and I am so not going there.
 * We can simply discard type checking and conversion for these arguments.  
Which pretty much bites, because this is a highly desired mechanism for 
supporting both users, and our front-ends sitting on the network and CLI.  
Also, these are likely to be a very common form of parameter, probably more so 
than regular options.
 * We can require extra metadata about the action, which is the desired option; 
there are a few ways to do that:

    action :foo, [String, Hash, Puppet::Resource::Catalog] do
        # => looks kind of C-like, not very rich.  Can't document those 
parameters or anything though, or make them optional, or anything.
        # we could use a hash, but that (A) loses order, which hurts, and (B) 
means our single line method definition gets to be twenty lines long…
    end

    action :bar do
        # => alas, the type signature is moved away from the name of the 
action, but…
        option "--foo FOO", String
        option "--bar [BAR]", Hash
        # => we declare the options just like anywhere else, then…
        parameters :foo, :bar
        # => …we declare which options you pass as named parameters to this 
action, and…
        when_invoked do |foo, bar, options|
            # => …just treat them as positional and all.  On the plus side, 
this is a pleasant API for Ruby users, it gives us the ability to use nothing 
but named arguments (which other mechanisms might like), and is fully 
compatible with convention.  It costs a bit in verbosity and spreads this 
information 
        end
    end

NB: I have held off on creating subtasks to encourage any discussion in this 
ticket before we commit to the mechanism.
----------------------------------------
Feature #6780: Implement type checking/coercion for action args 
https://projects.puppetlabs.com/issues/6780

Author: Pieter van de Bruggen
Status: Accepted
Priority: Normal
Assignee: Daniel Pittman
Category: interfaces
Target version: 2.6.x
Affected Puppet version: 
Keywords: 
Branch: 


The expectation is that actions should be able to transparently have 
typechecked signatures, and that automatic coercions will happen for certain 
argument types.

Consider:

    option "--foo FOO", String
    # => option requires a string; should it automatically to_s on an array?  I 
suspect not...

    option "--foo FOO", Puppet::Resource::Catalog
    # => option requires a catalog, and should automatically convert.
    # also, it should have "--foo-type TYPE", [:yaml, :pson, :string, :hash] 
added...

This makes interfacing the rich type system of Ruby with the command line's 
simple String-based interface simple.


-- 
You have received this notification because you have either subscribed to it, 
or are involved in it.
To change your notification preferences, please click here: 
http://projects.puppetlabs.com/my/account

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Bugs" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/puppet-bugs?hl=en.

Reply via email to