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.