Please review and discuss,
Brice
Original commit msg:
The following manifest doesn't work:
$foo = undef
case $foo {
undef: { notice("undef") }
default: { notice("defined") }
}
This is because "undef" scope variable are returned as an empty
string.
This patch introduces a subtile behavior change which might produce
some issues in existing manifests.
Note, unassigned variable usage still returns an empty string "" as
before (which is I think what people would expect), so:
case $bar {
undef: { notice("undef") }
default: { notice("defined") }
}
won't print "undef".
Signed-off-by: Brice Figureau <brice-...@daysofwonder.com>
---
lib/puppet/parser/ast/leaf.rb | 5 ++++-
spec/unit/parser/ast/comparison_operator.rb | 4 ++--
spec/unit/parser/ast/leaf.rb | 17 +++++++++++++++++
3 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/lib/puppet/parser/ast/leaf.rb b/lib/puppet/parser/ast/leaf.rb
index 153120a..e1157e8 100644
--- a/lib/puppet/parser/ast/leaf.rb
+++ b/lib/puppet/parser/ast/leaf.rb
@@ -147,7 +147,10 @@ class Puppet::Parser::AST
# not include syntactical constructs, like '$' and '{}').
def evaluate(scope)
parsewrap do
- return scope.lookupvar(@value)
+ if (var = scope.lookupvar(@value, false)) == :undefined
+ var = ""
+ end
+ var
end
end
end
diff --git a/spec/unit/parser/ast/comparison_operator.rb b/spec/unit/parser/ast/comparison_operator.rb
index 2631179..9740243 100755
--- a/spec/unit/parser/ast/comparison_operator.rb
+++ b/spec/unit/parser/ast/comparison_operator.rb
@@ -71,8 +71,8 @@ describe Puppet::Parser::AST::ComparisonOperator do
one = Puppet::Parser::AST::Variable.new( :value => "one" )
two = Puppet::Parser::AST::Variable.new( :value => "two" )
- @scope.expects(:lookupvar).with("one").returns(1)
- @scope.expects(:lookupvar).with("two").returns(2)
+ @scope.expects(:lookupvar).with("one", false).returns(1)
+ @scope.expects(:lookupvar).with("two", false).returns(2)
operator = Puppet::Parser::AST::ComparisonOperator.new :lval => one, :operator => "<", :rval => two
operator.evaluate(@scope).should == true
diff --git a/spec/unit/parser/ast/leaf.rb b/spec/unit/parser/ast/leaf.rb
index e968150..1d002d6 100755
--- a/spec/unit/parser/ast/leaf.rb
+++ b/spec/unit/parser/ast/leaf.rb
@@ -149,6 +149,23 @@ describe Puppet::Parser::AST::Regex do
end
end
+describe Puppet::Parser::AST::Variable do
+ before :each do
+ @scope = stub 'scope'
+ @var = Puppet::Parser::AST::Variable.new(:value => "myvar")
+ end
+
+ it "should lookup the variable in scope" do
+ @scope.expects(:lookupvar).with("myvar", false).returns(:myvalue)
+ @var.safeevaluate(@scope).should == :myvalue
+ end
+
+ it "should return an empty string if the variable wasn't set" do
+ @scope.expects(:lookupvar).with("myvar", false).returns(:undefined)
+ @var.safeevaluate(@scope).should == ""
+ end
+end
+
describe Puppet::Parser::AST::HostName do
before :each do
@scope = stub 'scope'
--
1.6.5.2
before (which is I think what people would expect), so:
case $bar {
undef: { notice("undef") }
default: { notice("defined") }
}
won't print "undef".
Please consider that this will be a behavior change, which should be
announced in the release notes etc.
We currently do a lot of checks on "" to check wether a variable have
been set or not:
case $sshd_tcp_forwarding {
'': { $sshd_tcp_forwarding = 'no' }
}
I assume that after this patch this won't work anymore and we have to
add everywhere a check on undef. This isn't really a problem, but the
break in the behavior should be noted and communicated.
cheers pete
That was the whole point of this patch: discuss it and see if we adopt
the behavior change or not.
> We currently do a lot of checks on "" to check wether a variable have
> been set or not:
>
> case $sshd_tcp_forwarding {
> '': { $sshd_tcp_forwarding = 'no' }
> }
>
> For example:
> http://git.puppet.immerda.ch/?p=module-sshd.git;a=blob;f=manifests/init.pp;h=8489a6a6b1a9047379aac942601f10596066522e;hb=7c73e1de97f872ba4c6651b9fa38599a9090311c
>
> I assume that after this patch this won't work anymore and we have to
> add everywhere a check on undef. This isn't really a problem, but the
> break in the behavior should be noted and communicated.
Sure. If the patch get approved it will be part of Rowlf so we have to
make sure it is noted in the "incompatible changes" section of the
release notes.
--
Brice Figureau
My Blog: http://www.masterzen.fr/
In fact I was wrong.
The current patch has the following:
* non-assigned variable when accessed *still* returns ''
* undef assigned variable when accessed returns undef instead of ''
Currently your manifests would still work.
Markus objected that both cases should return undef, which is what I had
implemented first, but since it was a behavior change, I made sure we
return '' on un-assigned variable.
Obviously the thing that this patch fixes is only a tiny part of the
story (I'm not even sure people assigns undef to variable in real
manifests).
So I want to start a discussion about this behavior change...
actually I think it's more intuitive to return undef than an empty
string. I mean undef is somehow the nil of puppet ;) not?
cheers pete
I've been thinking the same thing in the thread - that we should s/
undef/nil/g, and formally define what it means in the language.
'undef' was originally meant to be very minimal, but the 'nil' concept
is more useful than just undefining attributes.
--
Every great advance in natural knowledge has involved the absolute
rejection of authority. --Thomas H. Huxley
---------------------------------------------------------------------
Luke Kanies | http://reductivelabs.com | http://madstop.com
I agree that these should be equal.
As already mentioned, there are some significant backward
compatibility concerns, but it's probably worth making the change.
We could also have undef be considered equal to an empty string, like
perl essentially does, which would mitigate most of the issues, I think.
--
It's a small world, but I wouldn't want to paint it.
-- Stephen Wright
> Obviously the thing that this patch fixes is only a tiny part of the
> story (I'm not even sure people assigns undef to variable in real
> manifests).
Since it doesn't really *work* to set a variable to undef, of course
we don't... But yes, I would like that to work properly.
My immediate use case is that I want to do something like this:
case $mode {
"normal": { $stopped = stopped; $running = running }
"chroot": { $stopped = undef; $running = undef }
}
...
service {
"whatever-1": enable => true, ensure => $running;
"whatever-2": enable => false, ensure => $stopped;
}
When I run in a chroot environment, either in %post in kickstart
or when I run Puppet on a complete OS image that I'm going to deploy
on new machines using System Imager, I don't want to manage the
processes what processes are running. (The $mode variable I would
set using a facter environment variable.)
Another use case is in definitions, where I want to provide a default
behaviour for some parameter, but that behaviour may depend on some
other parameters, so it wouldn't be proper to have a fixed default
value for that parameter. Currently I solve that by giving it a
default value that is very unlikely to be used as a real value, but
it would be much nicer to actually be able to check for undef.
/Bellman
This seems like a good solution.
> Hmm. Order dependency in case statements seems counter to the
> spirit of puppet--is it? It could be removed by saying:
>
> * Undefined variables, variables set to undef, (and possibly
> unassigned hash elements) return undef.
> * In case expressions, undef is treated as "".
> * In interpolation, undef produces "".
Order-dependent case statements are counter, but with regexes, they're
here now, so the cat's essentially out of the bag.
> But then are there any contexts where it makes sense (or would even
> be possible) to distinguish "" and undef?
I can't imagine any in the compiler, and undef values don't make it
out of the compiler.
--
Don't hit at all if it is honorably possible to avoid hitting; but
never hit soft! -- Theodore Roosevelt
I was looking at my assigned patches, and it seems this one had never
been reviewed (it's the v2).
If someone can have a look, and (even) try it, that'd be great :-)
thanks,
Brice
--
> --
>
> You received this message because you are subscribed to the Google
> Groups "Puppet Developers" group.
> To post to this group, send email to puppe...@googlegroups.com.
> To unsubscribe from this group, send email to puppet-dev+...@googlegroups.com
> .
> For more options, visit this group at http://groups.google.com/group/puppet-dev?hl=
> .
>
>
--
When one admits that nothing is certain one must, I think, also admit
that some things are much more nearly certain than others.
-- Bertrand Russell