https://www.puppet.com/community logo
Join Slack
Powered by
# puppet
  • h

    helindbe

    05/06/2025, 8:25 PM
    Classes are evaluated as they are included, think of them as functions - if one class includes another it will evaluate that class before continuing in the calling class. Defines, when “declared” to be included will be queued and evaluated after classes, if a class is included during evaluation of a define the class will be fully evaluated before the define is. When a class is evaluated it first evaluates its parameters. Does that help?
  • h

    helindbe

    05/06/2025, 8:28 PM
    See https://puppet-on-the-edge.blogspot.com/2014/04/getting-your-puppet-ducks-in-row.html for more on this topic
  • j

    jms1

    05/06/2025, 8:29 PM
    so ... the first time the compiler encounters
    include xyz
    , it gets the class's parameters from (enc, hiera, etc.) and adds those to an internal "hash of variable values" somewhere, and adds the class's name to a list of classes to be "executed" later on in the compilation process ... then each successive
    include xyz
    notices that the class is already on the list and doesn't do anything else ... yes? (the last time i dealt with compiler design was around 1993)
  • h

    helindbe

    05/06/2025, 8:32 PM
    almost, it makes a record of class being called/included and evaluates its params and then its body. it is never queued.
  • h

    helindbe

    05/06/2025, 8:33 PM
    if included again it is a noop
  • h

    helindbe

    05/06/2025, 8:33 PM
    if included with param values it cannot be included again with param values
  • j

    jms1

    05/06/2025, 8:34 PM
    ah ... so it sounds like when it gets `include`'d the first time it makes an early pass through the code to find other
    include
    statements, and then later it actually "runs" the code to generate the resource declarations for the catalog
  • h

    helindbe

    05/06/2025, 8:34 PM
    no, no extra pass, it just goes statement by statement
  • j

    jms1

    05/06/2025, 8:35 PM
    so ... when it processes the first
    include
    , it actually "runs" the code of the "included" class and adds things to the catalog?
  • h

    helindbe

    05/06/2025, 8:35 PM
    any resources declared will be pushed on a queue though, but included classes are evaluated directly
  • j

    jms1

    05/06/2025, 8:35 PM
    i thought that's the one thing it didn't do
  • h

    helindbe

    05/06/2025, 8:36 PM
    when a class is included it is evaluated (I suppose that is “run” in your vocabulary)
  • j

    jms1

    05/06/2025, 8:36 PM
    okay ... and this "resources pushed on a queue" ends up becoming the
    resources
    array in the catalog that gets sent back to the agent?
  • h

    helindbe

    05/06/2025, 8:38 PM
    Not directly, think of them as function calls that are pushed on a queue instead of being directly called. After all class bodies have been evaluated it will start actually calling the queued defines
  • h

    helindbe

    05/06/2025, 8:38 PM
    the result of those end up in the catalog.
  • j

    jms1

    05/06/2025, 8:39 PM
    ah ... so when you said "any resources declared will be pushed on a queue", you were referring to instances of defined types being pushed on to a queue, as opposed to classes?
  • h

    helindbe

    05/06/2025, 8:41 PM
    yes
  • h

    helindbe

    05/06/2025, 8:41 PM
    Read my blog post, it will make it clearer
  • j

    jms1

    05/06/2025, 8:43 PM
    okay ... i think i understand that much of it. i already had the article open in another tab, now i'm gonna go read through and see if i can grok it
    👍 1
  • a

    Adrian Parreiras Horta

    05/06/2025, 8:44 PM
    You could try adding an explicit
    lookup()
    as a class parameter to the class you want to access the other class' parameters from. The linter will warn you about it, but we found it to be occasionally useful
  • a

    Adrian Parreiras Horta

    05/06/2025, 8:46 PM
    Like if the params from one class are tightly coupled with another. Probably not the best practice, but for example https://github.com/puppetlabs/puppet_operational_dashboards/blob/bf8a5dea0e1c0e1e133d4db3e4cad442dcae89a7/manifests/init.pp#L46-L48
  • j

    jms1

    05/06/2025, 8:46 PM
    i tried that several years ago, what i found was that code in "class_a" cannot
    lookup( "class_b::xxx" )
    . maybe this has changed since then, but i'm still using PE 2016.2 aka "puppet 4.5.2" (although there is a light at the end of the tunnel, i just hope it isn't an oncoming train)
  • n

    natemccurdy

    05/06/2025, 8:48 PM
    lookup()
    is for looking up data from Hiera. It does not lookup variables from classes or class parameters.
    👍 1
    ☝️ 1
  • a

    Adrian Parreiras Horta

    05/06/2025, 8:48 PM
    If it isn't actually defined in hiera, you probably need to add a default to the lookup that defaults to the other class parameter. Which yeah, isn't the best
  • j

    jms1

    05/06/2025, 8:49 PM
    i know what he was trying to say ... in my case it could be useful, as all of our parameter values are stored in hiera (we don't use the ENC, other than the node groups that the PE installer creates by default)
  • j

    jms1

    05/06/2025, 9:27 PM
    @helindbe you are right, the blog post helped A LOT, thanks for that ... so it sounds like
    include
    will actually "run" the other class the first time, and if i need to access a parameter value or a variable from another class, i just need to be sure to
    include
    that other class before trying to access it.
  • j

    jms1

    05/06/2025, 9:28 PM
    the weird thing is, i remember trying this before, finding that it didn't work, and remembering "that doesn't work" ever since ... but i'll be honest, it's been years so i don't remember the details. i wonder if it didn't work back then because i typo'd, or forgot, the
    include other_class
    line before trying to access its variables?
  • n

    natemccurdy

    05/06/2025, 9:29 PM
    I would assume that it didn't work because the class wasn't included. It's always been the case that a class must be evaluated before its parameters or variables can be referenced. And the standard way to evaluate a class is to
    include
    it (or
    contain
    ,
    require
    , or declare it like a resource).
  • j

    jms1

    05/06/2025, 9:44 PM
    given how long ago it was (and the fact that my first five years with puppet were spent "learning while doing"), that's entirely possible
  • c

    csharpsteen

    05/06/2025, 10:05 PM
    Yup. Classes are special and get evaluated at the point where they are included. So, if you try to reference variables from another class without first including, containing, or otherwise declaring it, then you have no guarantee that the class has been evaluated yet. It may work out without a declaration, but that's because the compiler order is just lining up nicely for you that day.