Thanks John for lots of good feedback, and I realize I should clarify
some things... comments inline below...
On 2014-24-01 24:46, John Bollinger wrote:
On Wednesday, January 22, 2014 12:15:31 PM UTC-6, henrik lindberg wrote:
Recent Pull Requests to puppetlabs-stdlib has raised issues w.r.t
how we
should handle stdlib going forward. We have also had a discussion about
types and providers in core and if they should be moved out to modules
in a "tier2". That discussion also raises issues about
backwards compatibility, and configuration of modules.
I am posting this to trigger a discussion and to collect requirements.
* Is there content in stdlib that really belongs in core?
That begs a more fundamental question of policy on what kinds of things
belong in core in general. Also a question of whether there's a
distinction between "core" and a hypothetical "tier1" that isn't the
core product but is developed and maintained by PL and packaged with core.
With that said, there are many functions in stdlib that seem strangely
placed in an optional add-on module. Functions that I would definitely
put in that category include
empty()
flatten()
get_module_path()
has_key()
is_array()
is_hash()
is_numeric()
is_string()
join()
keys()
size()
values()
Other functions that I might suggest putting in that category include
abs()
any2array()
concat()
count()
delete()
delete_at()
delete_values()
delete_undef_values()
difference()
dirname()
floor()
fqdn_rotate()
hash()
intersection()
join_keys_to_values()
lstrip()
max()
member()
merge()
min()
pick()
prefix()
range()
reject()
reverse()
rstrip()
sort()
squeeze()
str2saltedsha512()
strip()
suffix()
type()
union()
unique()
values_at()
zip()
There are also some functions whose usefulness, I question, but which,
if indeed generally useful, probably should not be optional add-ons:
bool2num()
capitalize()
chomp()
chop()
downcase()
getvar()
grep()
is_bool()
is_float()
is_integer()
num2bool()
shuffle()
str2bool()
strftime()
swapcase()
time()
type()
upcase()
uriescape()
* Is there content in stdlib that should never have been included (it
should really be in a different module)?
Anything in my third list above might fall into this category. In
addition, I would definitely put any stdlib function not already listed
above into this category.
In particular, although I see the validate_*() functions serving a
useful role, I think don't see them as core, and moreover they would
hang together nicely in their own module.
Likewise, there is a group of functions centered on probing nodes'
network characteristics; these also don't seem quite "core", but do hang
together as their own group.
There are a few oddball functions that perhaps hang together loosely,
but that don't feel "core"-ish to me: base64(), loadyaml(), parsejson(),
parseyaml().
And then there is a handful of functions that should not exist: Those
certainly should not be considered "core", and the only reason I see
even for keeping them in stdlib is to avoid breaking third-party
modules: defined_with_params(), ensure_packages(), ensure_resource(),
getparam(), is_function_available(). Really, these would be better in a
"dangerous_hacks_you_should_not_use" module, just to make it clear.
Mostly agree - guess we have to arrange an "Puppet Stdlib Idol" where
people can phone in and vote or something. For now --- just noting
what everyone feels about what is there.
* How do we keep stdlib in sync with the Puppet version?
Is it necessary to do so? Few of its functions seem dependent on Puppet
internals, and none of those are among the ones that I think clearly
belong as part of the core product. Most of those dependent on Puppet
internals are in the group "dangerous_hacks" group. Yank those out, I
say, and make them somebody else's problem.
Well, there is one big problem that we would like to solve, and that is
how functions are called. The ambition is to deal with this in Puppet 4
timeframe. The problem with the current calling convention is (among
other things) that undef gets translated to an empty string - we would
like to stop transforming values that way. The idea is that a function
can opt in to the 4x calling convention.
There may not be any functions in stdlib that will benefit from the
calling convention change though (have not reviewed for that yet).
* How should module authors deal with their dependency on stdlib?
What sort of "dealing" are you asking about? Modules themselves can't
really do much "deal"ing; if they try to call functions that don't exist
then they will just break. If there were a reliable fallback then
that's what the module would (should) use in the first place.
The only other kind of dealing I can think of involves module metadata
and the puppet module tool, but it's not clear to me what kinds of
problems you suppose module authors need to deal with in that area.
* How should we handle future, breaking changes?
* A function is corrected/modified and is thus not backwards
compatible (it is not deprecated, just changed behavior).
Alternative 1: don't do that; create a new function instead. This is a
tried and true strategy.
Alternative 2: continue applying semantic versioning to stdlib, and
refer back to "How should module authors deal with their dependency on
stdlib?"
* A function changes signature (it is called with a different set
of arguments).
I am thinking about a combination of namespaced functions (their
identity is unique), but that they may have the same last part. A module
could then use unqualified function names. A mechanism of resolving the
module's dependencies would wire the module so it finds
the correct version of the function. This way, the puppet logic would
still contain a call to "foo(3)", and the function may come from any of
the referenced modules (say a "stdlib_compat_3" module).
I am also thinking about dependency ranges, and that I suspect that
module authors probably only use a lower version range, thus exposing
the module to potential future breakage.
What I really would like to see it work in the reverse - i.e. that
modules can *provide* an API as well as implement it, and that modules
that depend on other modules declare their dependency on those API
versions - not on the implementation of the API.
In order to achieve this, it may be required to provide modules that
are only there to specify a configuration of other modules. (This in
turn requires a lot more sophistication in the puppet module ecosystem).
In any case, what I want to avoid is that all modules have to be updated
in lock step sync and that module authors can adopt new functionality
faster without sacrificing also supporting the majority of users who are
several steps behind the bleeding edge.
See above.
* Should we have "backwards compatibility" as a separate module for
those that want to use older modules on a newer Puppet? (e.g.
stdlib-puppet3compat).
That would be a reasonable approach for functions removed from stdlib
and not otherwise moved anywhere else. It would be sure to cause a
tremendous mess if done for stdlib functions that were modified.
Yes, a mess, for sure :-) unless there is a way to "route" things to an
implementation that has the "old" / expected behavior.
* Do we have to namespace functions (to allow multiple versions
of the
same function for different modules?)
"Have to"? No. I think it's a good idea, however.
* Do we have to use a scheme such as adding a number after a
function/type
You mean when new behavior or signature is desired for an existing
function? Yes, I think the best approach is my alternative 1, which is
typically implemented by giving the new function a name derived from the
old one's.
* Do we need to implement module specific loading (allow multiple
versions of a function).
I think namespacing functions is a better strategy.
See comment above - I was thinking about a combination of namespace and
resolution of dependencies (to define visibility). Using a fully
qualified name could be allowed (it would be an absolute pointer), if
using only the last part, it would resolve to the visible version of
that function. (If ambiguous, user would have to use fully qualified name).
* What about types and providers? Since they all have to
co-exist in
the same catalog it is not really possible to support multiple
versions. How should we deal with types and providers?
I think the only significant issue there that is not analogous to the
situation with functions is third-party providers for existing types.
That's a thorny issue that I'm not prepared to address at the moment.
We can probably leave that out from the discussion around stdlib.
Regards
- henrik
--
You received this message because you are subscribed to the Google Groups "Puppet
Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/puppet-dev/52E1B465.3010606%40cloudsmith.com.
For more options, visit https://groups.google.com/groups/opt_out.