Jira (PUP-6964) Puppet 4.x functions should be available to all modules not just those that declare the containing module as a dependency

3 views
Skip to first unread message

Nick Walker (JIRA)

unread,
Dec 1, 2016, 4:48:03 PM12/1/16
to puppe...@googlegroups.com
Nick Walker created an issue
 
Puppet / Improvement PUP-6964
Puppet 4.x functions should be available to all modules not just those that declare the containing module as a dependency
Issue Type: Improvement Improvement
Assignee: Unassigned
Created: 2016/12/01 1:47 PM
Labels: tcse
Priority: Normal Normal
Reporter: Nick Walker

The Problem

See

PUP-6952 and PUP-6953 for backgound but essentially, puppet can't find puppet 4.x functions in other modules unless they are declared as a dependency of the module trying to use the function.

OR if the module just doesn't declare any dependencies.

The Change

The behavior of finding functions should not be dependent on the modules dependencies as defined in metadata.json for the module.

We should search the entire modulepath for a function and not just in the declared dependencies.

We can retain some of the optimization by searching in declared dependencies first and then if not found extend the search to all modules. This makes the optimization opt-in and not required.

Add Comment Add Comment
 
This message was sent by Atlassian JIRA (v6.4.14#64029-sha1:ae256fe)
Atlassian logo

Henrik Lindberg (JIRA)

unread,
Dec 1, 2016, 5:36:06 PM12/1/16
to puppe...@googlegroups.com
Henrik Lindberg commented on Improvement PUP-6964
 
Re: Puppet 4.x functions should be available to all modules not just those that declare the containing module as a dependency

The behavior is there to keep everyone honest. What is the point of having metadata if it not enforced? You can lie as much as you like without any consequences. Where should a user be looking for the functions and possibly other constructs named in the global namespace?
If strict module namespacing was enforced it would never be a problem.

The case I am thinking about is the user that consumes a module. That module makes use of a function foo(). Where did it come from?
At least with having to declare module dependencies the list of modules to explore is greatly reduced.

Also, the author of a module should be very much aware of making the module depend on another. It is a conscious design and maintenance decision.

The current design of allowing no dependencies in metadata.json to mean "look everywhere" is because we interpret that as the module author saying "I did not bother helping you - go fish". I think that is bad.

Henrik Lindberg (JIRA)

unread,
Dec 1, 2016, 5:47:05 PM12/1/16
to puppe...@googlegroups.com

I am ambivalent though since right now it is only 4.x functions (ruby or puppet) that requires the dependencies. I also fear that the decision to allow no-dependencies to mean "all/any" has the effect that people remove rather than correct the list of dependencies.

I would however like us to move in the opposite more strict direction and rather evolve the metadata.json capabilities with things like optional dependencies.
But maybe the route there is to take a step back first, and increase the strictness in sync with better capabilities in metadata.json. Here I am not sure what the right balance between strictness/quality and usability is. Ping Eric Sorenson (in response to your 0.02$ on PUP-6953).

Also note - as long as we allow any module to contain top scope named definitions (functions as well as other) there is always the issue of potential clashes. Strictly using metadata.json gives modules a chance to tell which thing they actually want rather than having to rely on the undefined (somewhat random) order to search modules that is obtained by stepping through modulepath. The current implementation is deterministic because it searches in the order the dependencies are listed.

Maggie Dreyer (JIRA)

unread,
May 16, 2017, 3:10:05 PM5/16/17
to puppe...@googlegroups.com

Moses Mendoza (JIRA)

unread,
May 18, 2017, 1:55:03 PM5/18/17
to puppe...@googlegroups.com

Nate McCurdy (JIRA)

unread,
Oct 18, 2017, 2:11:03 PM10/18/17
to puppe...@googlegroups.com
Nate McCurdy commented on Improvement PUP-6964
 
Re: Puppet 4.x functions should be available to all modules not just those that declare the containing module as a dependency

I'd like to point out that this affects custom types from a module as well. For example, Stdlib::Absolutepath from the stdlib module.

This was entirely unexpected behavior and a breaking change that affected many nodes.

The fix (removing the empty array of dependencies in metadata.json) was very much not-obvious to find.

Henrik Lindberg (JIRA)

unread,
Oct 19, 2017, 7:51:03 AM10/19/17
to puppe...@googlegroups.com
Henrik Lindberg updated an issue
 

Added this to PUP-8072 epic "ScriptMerge" as we there want to break out the bolt functions from puppet to bolt and it will be unfriendly to then require that every module with plans need to make a dependency on the bolt supplied "special internal" module.

Eric Sorenson (JIRA)

unread,
Oct 19, 2017, 3:26:02 PM10/19/17
to puppe...@googlegroups.com
Eric Sorenson commented on Improvement PUP-6964
 
Re: Puppet 4.x functions should be available to all modules not just those that declare the containing module as a dependency

Yes, that would be completely insane. The current behavior w/ normal 4.x functions is also insane, and if we can fix both at once so much the better.

Henrik Lindberg (JIRA)

unread,
Oct 20, 2017, 11:21:03 AM10/20/17
to puppe...@googlegroups.com
Henrik Lindberg assigned an issue to Thomas Hallgren
 
Change By: Henrik Lindberg
Assignee: Thomas Hallgren
Release Notes Summary: It is no longer required to have a dependency listed in a module's metadata.json on another module (b) in order to use functions or data types from module b.
Sprint: Tasks Kanban
Release Notes: New Feature
Fix Version/s: PUP 5.4.0

John Duarte (JIRA)

unread,
Oct 23, 2017, 11:18:05 AM10/23/17
to puppe...@googlegroups.com

Thomas Hallgren (JIRA)

unread,
Oct 24, 2017, 9:49:03 AM10/24/17
to puppe...@googlegroups.com

Thomas Hallgren (JIRA)

unread,
Oct 24, 2017, 9:49:03 AM10/24/17
to puppe...@googlegroups.com

Henrik Lindberg (JIRA)

unread,
Oct 24, 2017, 10:41:03 AM10/24/17
to puppe...@googlegroups.com

Craig Gomes (JIRA)

unread,
Feb 5, 2018, 2:17:07 PM2/5/18
to puppe...@googlegroups.com
Craig Gomes updated an issue
 
Change By: Craig Gomes
Priority: Normal Blocker
This message was sent by Atlassian JIRA (v7.5.1#75006-sha1:7df2574)
Atlassian logo

Craig Gomes (JIRA)

unread,
Feb 5, 2018, 2:18:03 PM2/5/18
to puppe...@googlegroups.com
Craig Gomes commented on Improvement PUP-6964
 
Re: Puppet 4.x functions should be available to all modules not just those that declare the containing module as a dependency

This ticket has been linked to PE-23417 - performance regression

See Patrick's comments here

Kenn Hussey (JIRA)

unread,
Feb 5, 2018, 2:25:05 PM2/5/18
to puppe...@googlegroups.com

Josh Cooper (JIRA)

unread,
Feb 6, 2018, 11:10:06 PM2/6/18
to puppe...@googlegroups.com

Josh Cooper (JIRA)

unread,
Feb 6, 2018, 11:10:07 PM2/6/18
to puppe...@googlegroups.com

Josh Cooper (JIRA)

unread,
Feb 6, 2018, 11:10:08 PM2/6/18
to puppe...@googlegroups.com

Henrik Lindberg (JIRA)

unread,
Feb 7, 2018, 9:12:04 AM2/7/18
to puppe...@googlegroups.com
Henrik Lindberg commented on Improvement PUP-6964
 
Re: Puppet 4.x functions should be available to all modules not just those that declare the containing module as a dependency

I have a new PR up for this that places the modules from a module's dependencies first in the loaders to search. That means that it should in theory have the same performance as before except that it would reach "not found" in slightly longer time. It would be great to get a gatling run on that PR - possibly getting the feature in (even if it is the 11th hour to making it for 5.4.0).

Henrik Lindberg (JIRA)

unread,
Feb 26, 2018, 4:01:04 PM2/26/18
to puppe...@googlegroups.com

Henrik Lindberg (JIRA)

unread,
Feb 26, 2018, 4:01:06 PM2/26/18
to puppe...@googlegroups.com

Josh Cooper (JIRA)

unread,
Feb 26, 2018, 4:39:04 PM2/26/18
to puppe...@googlegroups.com

Christopher Wood (JIRA)

unread,
Mar 6, 2018, 10:21:03 AM3/6/18
to puppe...@googlegroups.com
Christopher Wood commented on Improvement PUP-6964
 
Re: Puppet 4.x functions should be available to all modules not just those that declare the containing module as a dependency

I found this ticket after running face-first into this issue yesterday.

A component of the behaviour in puppet 5.4.0 is that when I copied the function-using code from a component module class into a profile module class, puppet was then able to find my function.

Of course the control repo lacks a metadata.json, and now that I've added my module dependency everything works, so not chasing too hard on whether function lookup works for component modules without metadata.json.

(Also interested in whether the eventual error message will provide a list of places searched for functions, as that would have shed some light at my level of puppet skill.)

This message was sent by Atlassian JIRA (v7.7.1#77002-sha1:e75ca93)
Atlassian logo

Reid Vandewiele (JIRA)

unread,
Mar 6, 2018, 11:27:04 AM3/6/18
to puppe...@googlegroups.com

Christopher Wood makes an excellent point about visibility. If, upon not finding a function, Puppet made how function loading works naturally discoverable, this wouldn't be nearly as painful a problem.

Henrik Lindberg (JIRA)

unread,
Mar 8, 2018, 11:16:04 AM3/8/18
to puppe...@googlegroups.com

Henrik Lindberg (JIRA)

unread,
Mar 8, 2018, 11:20:02 AM3/8/18
to puppe...@googlegroups.com
Henrik Lindberg commented on Improvement PUP-6964
 
Re: Puppet 4.x functions should be available to all modules not just those that declare the containing module as a dependency

I pulled this from the PUP 5.5.0 release as we are not quite there yet with the implementation as there are concerns about performance that we can only speculate about. Seems a bit risky to merge based on speculation alone.

We are also still debating what the a more optimal solution would be - if the individual caches per module are positive (trading memory for speed) or if they are negative (takes both memory and unnecessary cycles). We may also have to look at 3.x function loading since the current behavior is try 4.x load first, if that fails try 3.x. That happens on every call to a 3.x function (with the 4.x lookup being optimized/cached).

Eric Sorenson (JIRA)

unread,
Mar 8, 2018, 6:58:03 PM3/8/18
to puppe...@googlegroups.com
Eric Sorenson commented on Improvement PUP-6964

This needs to get fixed in the 5.5.x series, or no one will be able to reasonably use 4.x functions in modules.

Josh Cooper (JIRA)

unread,
Mar 14, 2018, 8:34:04 PM3/14/18
to puppe...@googlegroups.com
Josh Cooper commented on Improvement PUP-6964

The most recent PR was rejected as it would have introduced a perf regression. I moved this back to ready for engineering to reflect reality. /cc Eric Sorenson

Josh Cooper (JIRA)

unread,
Mar 14, 2018, 8:34:04 PM3/14/18
to puppe...@googlegroups.com

Josh Cooper (JIRA)

unread,
Mar 19, 2018, 6:59:03 PM3/19/18
to puppe...@googlegroups.com
Josh Cooper commented on Improvement PUP-6964
 
Re: Puppet 4.x functions should be available to all modules not just those that declare the containing module as a dependency

Henrik Lindberg We will also need this functionality in order to unvendor types and providers from puppet, as previously modules didn't need to declare "module" dependencies on core T&P in puppet, or the loaders need to special case what were previously builtin types?

Henrik Lindberg (JIRA)

unread,
Mar 20, 2018, 7:45:03 AM3/20/18
to puppe...@googlegroups.com

Josh Cooper Types and providers are loaded using the 3.x autoloader - it does not have any restrictions on module visibility.

Josh Cooper (JIRA)

unread,
Mar 20, 2018, 12:19:04 PM3/20/18
to puppe...@googlegroups.com

Charlie Sharpsteen (JIRA)

unread,
Apr 10, 2018, 11:12:06 AM4/10/18
to puppe...@googlegroups.com

Owen Rodabaugh (JIRA)

unread,
Apr 10, 2018, 11:32:03 AM4/10/18
to puppe...@googlegroups.com
Owen Rodabaugh updated an issue
Change By: Owen Rodabaugh
CS Priority: Needs Priority Normal
CS Impact: Users writing modules can run into this and end up thrashing around trying to understand why it's not working. Anything that makes writing modules more accessible/less confusing to users is a good thing.

Given that the initial attempts at this included a significant performance impact, perhaps there is a middle ground of having a flag that tells puppet whether to rely on the dependencies entry in metadata.json or instead go for "slow mode", perhaps as a new metadata.json entry, where it scans the environment for functions.
CS Severity: 3 - Serious
CS Business Value: 4 - $$$$$
CS Frequency: 3 - 25-50% of Customers

Nick Walker (JIRA)

unread,
Aug 7, 2018, 6:40:03 PM8/7/18
to puppe...@googlegroups.com

Adam Bottchen (JIRA)

unread,
Aug 16, 2018, 7:36:03 PM8/16/18
to puppe...@googlegroups.com

Eric Sorenson (JIRA)

unread,
Aug 23, 2018, 12:25:04 PM8/23/18
to puppe...@googlegroups.com
Eric Sorenson updated an issue
Change By: Eric Sorenson
Fix Version/s: PUP 5.y
Fix Version/s: PUP 6.0.0
Fix Version/s: PUP 5.5.7

Henrik Lindberg (JIRA)

unread,
Aug 25, 2018, 6:40:04 AM8/25/18
to puppe...@googlegroups.com
Henrik Lindberg commented on Improvement PUP-6964
 
Re: Puppet 4.x functions should be available to all modules not just those that declare the containing module as a dependency

I continued the work on this and got some good results. I integrated 3.x function loading into the 4.x loaders such that the loaders will find and load 3x functions with lower precedence than 4.x functions as before, but now per module only - thus a module with both 3.x and 4.x can no longer have its 3x functions overridden by 4.x functions in modules coming after it on the module path.

With the new approach the 3.x functions are still loaded the old way to allow code that calls scope.function_xxx to work as before. (The actual 3x loading code is unchanged to reduce risk). Instead, the 4.x loader creates a wrapper 4.x function that delegates the call using the scope.function_xxx calling convention (again to reduce risk).

I also included the rewrite of returned values from 3.x functions to remove the problem of returning 4.x runtime incompatible :undef instead of nil (this is a separate ticket as well). Needed to do this in the new wrapper since the calling side does not know this needs to be done.

First run of benchmarking this (10 iterations on my machine) showed promising results as the baseline was 16.05s before the change and 15.64s after (both single runs, but still indicative of a possible wash in terms of performance).

There may be an opportunity to shave a little more off since a 3.x function is actually two methods; one dispatcher (the function_xxx method) that checks the argument constraints and raises errors, and the actual function (the real_function_xxx method). Since the 4x function wrapper also checks arguments it may be possible to short circuit one level of indirection per call. Impact of this is probably small in this particular benchmark.

Work remains to write tests for this before putting up a PR.

Henrik Lindberg (JIRA)

unread,
Aug 26, 2018, 4:12:06 PM8/26/18
to puppe...@googlegroups.com

Henrik Lindberg (JIRA)

unread,
Aug 26, 2018, 5:47:04 PM8/26/18
to puppe...@googlegroups.com
 
Re: Puppet 4.x functions should be available to all modules not just those that declare the containing module as a dependency

After running the existing tests, I found that they already covered the altered behavior because the test suite found problems in the implementation (that I subsequently fixed). I think this is now good to merge. See PR with benchmark figures from running the benchmark on my machine. The new code seems to be slightly faster than the old way of loading (I measured aprox 10%).

Kenn Hussey (JIRA)

unread,
Sep 11, 2018, 2:33:04 PM9/11/18
to puppe...@googlegroups.com

Kris Bosland (JIRA)

unread,
Sep 11, 2018, 3:00:13 PM9/11/18
to puppe...@googlegroups.com

Kenn Hussey (JIRA)

unread,
Sep 12, 2018, 9:17:05 AM9/12/18
to puppe...@googlegroups.com

Henrik Lindberg (JIRA)

unread,
Oct 26, 2018, 9:19:09 AM10/26/18
to puppe...@googlegroups.com
Henrik Lindberg commented on Improvement PUP-6964
 
Re: Puppet 4.x functions should be available to all modules not just those that declare the containing module as a dependency

The work in this ticket is the cause for the problem reported in PUP-9268. A 3.x (legacy API) function that has illegal method definitions in its body will fail as those methods are no longer available where they used to be.

Henrik Lindberg (JIRA)

unread,
Oct 30, 2018, 12:32:33 PM10/30/18
to puppe...@googlegroups.com

Austin Boyd (JIRA)

unread,
Oct 22, 2019, 5:56:04 AM10/22/19
to puppe...@googlegroups.com

Austin Boyd (JIRA)

unread,
Oct 22, 2019, 6:06:06 AM10/22/19
to puppe...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages