Please review pull request #65: Updated doc to reflect actual changes for dynamic scoping opened by (zaphod42)

Description:

We are not removing dynamic scoping of resource defaults, so that
information is out. Instead the resource default information is
presented as a good practice.

Reworded the information about the new scope to mention how node scope
fits in.

Provided some examples to illustrate how things will work out.

  • Opened: Fri Apr 20 23:22:01 UTC 2012
  • Based on: puppetlabs:master (448da8618c77513feed7060cd05338d27558a904)
  • Requested merge: zaphod42:feature/master/13970-remove-dynamic-scoping (e889898bb6ac4d41d9ad571d24eb5c19102e8400)

Diff follows:

diff --git a/source/guides/scope_and_puppet.markdown b/source/guides/scope_and_puppet.markdown
index d9fe9fa..5634bba 100644
--- a/source/guides/scope_and_puppet.markdown
+++ b/source/guides/scope_and_puppet.markdown
@@ -6,21 +6,37 @@ title: Scope and Puppet
 Scope and Puppet as of 2.7
 ==========================
 
-Puppet 2.7 issues deprecation warnings for dynamic variable and resource defaults lookup. Find out why, and learn how to adapt your Puppet code for the future!
+Puppet 2.7 issues deprecation warnings for dynamic variable lookup. Find out why, and learn how to adapt your Puppet code for the future!
 
 * * * 
 
 What's Changing?
 ----------------
 
-Dynamic scope will be removed from the Puppet language in a future version. **This will be a major and backwards-incompatible change.** Currently, if an unqualified variable isn't defined in the local scope, Puppet looks it up along a chain of parent scopes, eventually ending at top scope; resource defaults (`File{ owner => root, }`, e.g.) travel in much the same way. In the future, Puppet will only examine the local scope and top scope when resolving an unqualified variable or a resource default; intervening scopes will be ignored. **In effect, all variables will be either strictly local or strictly global.** The one exception will be derived classes, which will continue to consult the scope of the base class they inherit from. 
+Dynamic scope will be removed from the Puppet language in a future version. **This will be a major and backwards-incompatible change.** Currently, if an unqualified variable isn't defined in the local scope, Puppet looks it up along a chain of parent scopes, eventually ending at top scope. In the future, Puppet will only examine the local, inherited, node, and top scopes and top scope when resolving an unqualified variable; intervening scopes will be ignored. **In effect, all variables will be either strictly local to a hierarchy or strictly global.**
 
 To ease the transition, Puppet 2.7 issues deprecation warnings whenever dynamic variable lookup occurs. You should strongly consider refactoring your code to eliminate these warnings. 
 
+### An example of dynamic lookup
+
+{% highlight ruby %}
+    include dynamic
+
+    class dynamic {
+      $var = "from dynamic"
+      include included
+    }
+
+    class included {
+      notify { $var: } # dynamic lookup will end up finding "from dynamic"
+                       # this will change to being undefined
+    }
+{% endhighlight %}
+
 Why?
 ----
 
-Dynamic scope is confusing and dangerous, and often causes unexpected behavior. There are already better methods for accomplishing everything dynamic scope currently does, but even if you're being good, it can step in to "help" at inopportune moments. Dynamic scope interacts really badly with class inheritance, and it makes the boundaries between classes a lot more porous than good programming practice demands. 
+Dynamic scope is confusing and dangerous, and often causes unexpected behavior. Although dynamic scoping allows many powerful features, even if you're being good, it can step in to "help" at inopportune moments. Dynamic scope interacts really badly with class inheritance, and it makes the boundaries between classes a lot more porous than good programming practice demands. It turns out that dynamic scoping is not needed since there are already better methods for accomplishing everything dynamic scope currently allows.
 
 Thus, it's time to bid it a fond farewell.
 
@@ -31,19 +47,62 @@ So you've installed Puppet 2.7 and are ready to start going after those deprecat
 
 ### Qualify Your Variables! 
 
-Whenever you need to refer to a variable in another class, give the variable an explicit namespace: instead of simply referring to `$packagelist`, use `$git::core::packagelist`. This is a win in readability --- any casual observer can tell exactly where the variable is being set, without having to model your code in their head --- and it saves you from accidentally getting the value of some completely unrelated `$packagelist` variable.
+Whenever you need to refer to a variable in another class, give the variable an explicit namespace: instead of simply referring to `$packagelist`, use `$git::core::packagelist`. This is a win in readability --- any casual observer can tell exactly where the variable is being set, without having to model your code in their head --- and it saves you from accidentally getting the value of some completely unrelated `$packagelist` variable. For complete clarity and consistency you will probably want to do this even when it isn't absolutely neccessary.
+
+{% highlight ruby %}
+    include parent::child
+
+    class parent {
+      $var = "from parent"
+    }
+
+    class parent::child inherits parent {
+      $local_var = "from parent::child"
+      notify { $parent::var: }  # will be "from parent".
+      notify { $var: }          # will be "from parent", as well. Avoid using this form.
+      notify { $local_var: }    # will be "from parent::child". The unqualified form is fine here.
+    }
+{% endhighlight %}
+
+When referring to a variable in another class that is not a parent of the current class, then you will always need to fully qualify the variable name.
+
+{% highlight ruby %}
+    class other {
+      $var = "from other"
+    }
+
+    class example {
+      include other
+      notify { $other::var: } # will be "from other"
+    }
+{% endhighlight %}
 
 If you're referring explicitly to a top-scope variable, use the empty namespace (e.g. `$::packagelist`) for extra clarity. 
 
+{% highlight ruby %}
+    $var = "from topscope"
+    node default {
+      $var = "from node"
+      include lookup_example
+    }
+
+    class lookup_example {
+      notify { $var: }   # will be "from node"
+      notify { $::var: } # will be "from topscope"
+    }
+{% endhighlight %}
+
 ### Declare Resource Defaults Per-File!
 
-If you're using dynamic scope to share resource defaults, there's no way around it: you'll have to repeat yourself in each file that the defaults apply to. 
+Although resource defaults are not being changed, they will still by affected by dynamic scope, for consistency and clarity you'll want to follow these rules for them, as well.
+
+Using your resource defaults without dynamic scope means one thing: you'll have to repeat yourself in each file that the defaults apply to. 
 
 But this is not a bad thing! Resource defaults are really just code compression, and were designed to make a single file of Puppet code more concise. By making sure your defaults are always on the same page as the resources they apply to, you'll make your code vastly more legible and predictable. 
 
 If you need to apply resource defaults more broadly, you can still set them at top scope in your primary site manifest. If you need the resource defaults in a class to change depending on where the class is being declared, you need parameterized classes. 
 
-All told, it's more likely that defaults have been traveling through scopes without your knowledge, and the eventual elimination of dynamic scope will just make them act like you thought they were acting. 
+All told, it's more likely that defaults have been traveling through scopes without your knowledge, and following these guidelines will just make them act like you thought they were acting. 
 
 ### Use Parameterized Classes!
 
@@ -65,6 +124,7 @@ Appendix: How Scope Works in Puppet ≤ 2.7.x
 
 These rules seem simple enough, so an example is in order:
 
+{% highlight ruby %}
     # manifests/site.pp
     $nodetype = "base"
     
@@ -99,6 +159,7 @@ These rules seem simple enough, so an example is in order:
          }
     
     } 
+{% endhighlight %}
 
 When nodes www01 through www10 connect to the puppet master, `$nodetype` will always be set to "base" and main.cf will always be served from files/base/. This is because `postfix::custom`'s chain of parent scopes is `postfix::custom < postfix < base < top-scope`; the combination of inheritance and dynamic scope causes lookup of the `$nodetype` variable to bypass `node 01-10` entirely. 
 

    

--
You received this message because you are subscribed to the Google Groups "Puppet Developers" 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-dev?hl=en.

Reply via email to