How to access a variable from parent define[d type]?

386 views
Skip to first unread message

Jakov Sosic

unread,
Oct 29, 2015, 2:05:16 AM10/29/15
to Puppet Users
Hi guys.

I have an issue with scope changes, and I am wondering how to proceed.


This is what I've got:

define first (
$somevar,
) {
$name_array = split($title, '/')
$developer = $name_array[0]
$instance = $name_array[1]

::second { "${developer}_${instance}":
template => 'my/custom/file.erb',
}

}


define second (
$template,
) {
notify { "${developer}": }
}

first { 'j/test': somevar => 'test' }


Accessing $developer was working before updating to puppet4, but after
updating, it's not working any more. ERBs that are inside 'second' are
depending on these variables being available to evaluate correctly.

I know a clean way to fix this would be to pass a variable $developer as
a parameter to second defined type. BUT, I would like to try and avoid
that because 'second' is a defined type provided by 3rd party module.


Is there anything else I can do?

jcbollinger

unread,
Oct 29, 2015, 9:24:07 AM10/29/15
to Puppet Users


On Thursday, October 29, 2015 at 1:05:16 AM UTC-5, Jakov Sosic wrote:
Hi guys.

I have an issue with scope changes, and I am wondering how to proceed.


This is what I've got:

define first (
   $somevar,
) {
   $name_array = split($title, '/')
   $developer = $name_array[0]
   $instance  = $name_array[1]

   ::second { "${developer}_${instance}":
     template => 'my/custom/file.erb',
   }

}


define second (
   $template,
) {
   notify { "${developer}": }
}

first { 'j/test': somevar => 'test' }


Accessing $developer was working before updating to puppet4, but after
updating, it's not working any more. ERBs that are inside 'second' are
depending on these variables being available to evaluate correctly.


What you describe should not have worked in Puppet 3, either.  Class inheritance is the only mechanism Puppet 3 scoping rules provide for variables declared in a local scope, such as is established by the body of a class or a defined type, to be visible in any other scope.  Defined types are not subject to class inheritance.  I'm reasonably confident that the example you provided would create a Notify with an empty message in Puppet 3, but since you mention templates, there was a bug in Puppet 3 in which templates were able to access variables via dynamic scope (PUP-1220).  That would explain the template behavior you describe.

As far as I know or can tell, scoping rules are unchanged in Puppet 4.  The fix for PUP-1220 was initially rolled out in Puppet 3.5.0, but only in the future parser.  In Puppet 4, the erstwhile future parser is the only parser.

 

I know a clean way to fix this would be to pass a variable $developer as
a parameter to second defined type. BUT, I would like to try and avoid
that because 'second' is a defined type provided by 3rd party module.


Is there anything else I can do?


There is nothing you can do to cause a variable declared in one defined type's local scope to be visible in a different defined type.  You can pass its value if you modify the second defined type, but you say you don't want to do that.  The only other avenues I see would involve modifying the template, or using a different means to specify the target file's content, or taking a step back and performing a broader redesign.  I'm afraid I can't suggest any details, however, because you've completely abstracted away what you're actually trying to achieve.


John

Chad Huneycutt

unread,
Oct 29, 2015, 1:20:27 PM10/29/15
to puppet...@googlegroups.com
Can you see the name of the defined type in the template? How about
just deriving $developer from that?

- Chad
> --
> You received this message because you are subscribed to the Google Groups
> "Puppet Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to puppet-users...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/puppet-users/7c0adc47-4dcc-4932-8494-5c6f39a6599e%40googlegroups.com.
>
> For more options, visit https://groups.google.com/d/optout.



--
Chad M. Huneycutt

Jakov Sosic

unread,
Oct 30, 2015, 1:45:50 AM10/30/15
to puppet...@googlegroups.com
On 10/29/2015 02:24 PM, jcbollinger wrote:

> What you describe should not have worked in Puppet 3, either. Class
> inheritance is the only mechanism Puppet 3 scoping rules
> <https://docs.puppetlabs.com/puppet/3/reference/lang_scope.html> provide
> for variables declared in a local scope, such as is established by the
> body of a class or a defined type, to be visible in any other scope.
> Defined types are not subject to class inheritance. I'm reasonably
> confident that the example you provided would create a Notify with an
> empty message in Puppet 3, but since you mention templates, there was a
> bug in Puppet 3 in which templates were able to access variables via
> dynamic scope (PUP-1220)
> <https://tickets.puppetlabs.com/browse/PUP-1220>. That would explain
> the template behavior you describe.
>
> As far as I know or can tell, scoping rules are unchanged in Puppet 4.
> The fix for PUP-1220 was initially rolled out in Puppet 3.5.0, but only
> in the future parser. In Puppet 4, the erstwhile future parser is the
> only parser.

Damn, that's it then...


> There is nothing you can do to cause a variable declared in one defined
> type's local scope to be visible in a different defined type. You can
> pass its /value/ if you modify the second defined type, but you say you
> don't want to do that. The only other avenues I see would involve
> modifying the template, or using a different means to specify the target
> file's content, or taking a step back and performing a broader
> redesign. I'm afraid I can't suggest any details, however, because
> you've completely abstracted away what you're actually trying to achieve.

Thanks jcbollinger - you truly are a Puppet hero :)

I seem to have no choice but to merge 2nd level defines into 1st level
define (move templates and all the logic).



Since you really helped, I'll do my best to try and explain what am I
doing here:

1) custom fact detects PHP project working copies in user directories
2) puppet uses custom fact to create defined resources (myclass::mydefined)
3) since each working copy of PHP project needs to generate couple of
apache vhosts, myclass::mydefined would just use apache::vhost define to
create those 3 vhosts per detected working copy


So, only viable solution is obviously to stop using apache::vhost, and
define file {} with templates directly in mclass::mydefined.

Thanks.



jcbollinger

unread,
Oct 30, 2015, 9:31:55 AM10/30/15
to Puppet Users


On Friday, October 30, 2015 at 12:45:50 AM UTC-5, Jakov Sosic wrote:


Since you really helped, I'll do my best to try and explain what am I
doing here:

1) custom fact detects PHP project working copies in user directories
2) puppet uses custom fact to create defined resources (myclass::mydefined)
3) since each working copy of PHP project needs to generate couple of
apache vhosts, myclass::mydefined would just use apache::vhost define to
create those 3 vhosts per detected working copy


So, only viable solution is obviously to stop using apache::vhost, and
define file {} with templates directly in mclass::mydefined.



I'm confused. Supposing you're using a recent version of puppetlabs-apache, where does a custom template even come into the picture for you?  apache::vhost does make extensive use of templates, but it doesn't provide any means for the user to give their own alternative templates.

Are you then modifying the module's own templates?  If so, why?  Does apache::vhost's dizzying array of parameters fail to cover all your needs?  If so, then that would be worth a bug report.

And if you're modifying the module's templates then you've already crossed the line into customizing your copy of the module.  I don't see why modifying its defined types would be qualitatively different.

You will of course approach the problem as you think best, but I'm doubtful that merging apache::vhost's functionality into your own defined types is necessary.


John

Reply all
Reply to author
Forward
0 new messages