Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge remote-tracking branch 'upstream/2.7.x'

* upstream/2.7.x: (22 commits)
  Removed duplication of compiling a catalog
  Cleaner test for create_resources doing nothing
  Fixing problem caused by activerecord
  Put back require 'puppet' in Puppet::Util
  (#13299) Fix error message when agent is disabled
  Update puppet.spec for rpm packaging
  Fixed old log test to match new autoflush behavior
  Make sure the log file writable
  Default autoflushing of log files to true
  Created test that shows enc warning problem
  (Maint) Fix order-dependent test failure
  (Maint) Don't assume eventlog gem is installed on Windows
  options[:ca_location] is a string not a symbol. Safer to pull Puppet::SSL::Host.ca_location since it is already set correctly.
  (#13204) Don't ignore missing PATH.augnew files
  (#13640) Only agents should use next_agent_run
  Increased test coverage of scoping rules
  Use more descriptive terms for the differing scopes
  Make new scoping look through inherited scopes
  Add tests for mixed inheritence/inclusion
  Remove dynamic option for lookupvar
  ...

Conflicts:
	lib/puppet/defaults.rb
	lib/puppet/parser/scope.rb
	spec/unit/parser/functions/create_resources_spec.rb
	spec/unit/parser/scope_spec.rb
	spec/unit/resource/type_spec.rb
	test/util/log.rb
  • Loading branch information...
commit 7a430815424e053d6e6c5925eef711ca5edd8373 2 parents 32172d5 + 8908c09
@zaphod42 zaphod42 authored
View
80 acceptance/tests/language/ticket_8174_enc_causes_spurious_deprecation_warnings.rb
@@ -0,0 +1,80 @@
+test_name "#8174: incorrect warning about deprecated scoping"
+
+testdir = master.tmpdir('scoping_deprecation')
+
+create_remote_file(master, "#{testdir}/puppet.conf", <<END)
+[main]
+node_terminus = exec
+external_nodes = "#{testdir}/enc"
+manifest = "#{testdir}/site.pp"
+modulepath = "#{testdir}/modules"
+END
+
+on master, "mkdir -p #{testdir}/modules/a/manifests"
+
+create_remote_file(master, "#{testdir}/enc", <<-PP)
+#!/usr/bin/env sh
+
+cat <<END
+---
+classes:
+ a
+parameters:
+ enc_var: "Set from ENC."
+END
+exit 0
+PP
+
+create_remote_file(master, "#{testdir}/site.pp", <<-PP)
+$top_scope = "set from site.pp"
+node default {
+ $node_var = "in node"
+}
+PP
+create_remote_file(master, "#{testdir}/modules/a/manifests/init.pp", <<-PP)
+class a {
+ $locally = "locally declared"
+ $dynamic_for_b = "dynamic and declared in a"
+ notify { "fqdn from facts": message => $fqdn }
+ notify { "locally declared var": message => $locally }
+ notify { "var via enc": message => $enc_var }
+ notify { "declared top scope": message => $top_scope }
+ notify { "declared node": message => $node_var }
+
+ include a::b
+}
+PP
+create_remote_file(master, "#{testdir}/modules/a/manifests/b.pp", <<-PP)
+class a::b {
+ notify { "dynamic from elsewhere": message => $dynamic_for_b }
+}
+PP
+
+on master, "chown -R root:puppet #{testdir}"
+on master, "chmod -R g+rwX #{testdir}"
+on master, "chmod -R a+x #{testdir}/enc"
+on master, "touch #{testdir}/log"
+on master, "chown puppet #{testdir}/log"
+
+assert_log_on_master_contains = lambda do |string|
+ on master, "grep '#{string}' #{testdir}/log"
+end
+
+assert_log_on_master_does_not_contain = lambda do |string|
+ on master, "grep -v '#{string}' #{testdir}/log"
+end
+
+with_master_running_on(master, "--config #{testdir}/puppet.conf --debug --verbose --daemonize --dns_alt_names=\"puppet,$(hostname -s),$(hostname -f)\" --autosign true --logdest #{testdir}/log") do
+ agents.each do |agent|
+ run_agent_on(agent, "--no-daemonize --onetime --server #{master}")
+ end
+
+ assert_log_on_master_contains['Dynamic lookup of $dynamic_for_b']
+ assert_log_on_master_does_not_contain['Dynamic lookup of $fqdn']
+ assert_log_on_master_does_not_contain['Dynamic lookup of $locally']
+ assert_log_on_master_does_not_contain['Dynamic lookup of $enc_var']
+ assert_log_on_master_does_not_contain['Dynamic lookup of $top_scope']
+ assert_log_on_master_does_not_contain['Dynamic lookup of $node_var']
+end
+
+on master, "rm -rf #{testdir}"
View
7 acceptance/tests/windows/eventlog.rb
@@ -14,13 +14,16 @@ def get_cmd(host)
# get remote time
now = on(agent, "#{get_cmd(agent)} -e \"puts Time.now.utc.strftime('%m/%d/%Y %H:%M:%S')\"").stdout.chomp
+ # it should fail to start since parent directories don't exist
+ confdir = "/does/not/exist"
+
# generate an error, no master on windows boxes
- on agent, puppet_agent('--server', '127.0.0.1', '--test'), :acceptable_exit_codes => [1]
+ on agent, puppet_agent('--server', '127.0.0.1', '--test', '--confdir', confdir), :acceptable_exit_codes => [1]
# make sure there's a Puppet error message in the log
# cygwin + ssh + wmic hangs trying to read stdin, so echo '' |
on agent, "cmd /c echo '' | wmic ntevent where \"LogFile='Application' and SourceName='Puppet' and TimeWritten >= '#{now}'\" get Message,Type /format:csv" do
fail_test "Event not found in Application event log" unless
- stdout =~ /Could not retrieve catalog from remote server.*,Error/m
+ stdout =~ /Cannot create [a-z]:\/does\/not\/exist.*,Error/mi
end
end
View
11 conf/redhat/puppet.spec
@@ -5,7 +5,7 @@
%global confdir conf/redhat
Name: puppet
-Version: 2.7.12
+Version: 2.7.13
#Release: 0.1rc1%{?dist}
Release: 1%{?dist}
Summary: A network tool for managing many disparate systems
@@ -21,13 +21,11 @@ Group: System Environment/Base
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: facter >= 1.5
-BuildRequires: ruby >= 1.8.1
+BuildRequires: ruby >= 1.8.5
-%if 0%{?fedora} || 0%{?rhel} >= 5
BuildArch: noarch
Requires: ruby(abi) >= 1.8
Requires: ruby-shadow
-%endif
# Pull in ruby selinux bindings where available
%if 0%{?fedora} || 0%{?rhel} >= 6
@@ -39,7 +37,7 @@ Requires: ruby-shadow
%endif
Requires: facter >= 1.5
-Requires: ruby >= 1.8.1
+Requires: ruby >= 1.8.5
%{!?_without_augeas:Requires: ruby-augeas}
Requires(pre): shadow-utils
@@ -287,6 +285,9 @@ fi
rm -rf %{buildroot}
%changelog
+* Tue Apr 10 2012 Matthaus Litteken <matthaus@puppetlabs.com> - 2.7.13-1
+- Update for 2.7.13
+
* Mon Mar 12 2012 Michael Stahnke <stahnma@puppetlabs.com> - 2.7.12-1
- Update for 2.7.12
View
2  lib/puppet/agent.rb
@@ -32,7 +32,7 @@ def run(*args)
return
end
if disabled?
- Puppet.notice "Skipping run of #{client_class}; administratively disabled; use 'puppet #{client_class} --enable' to re-enable."
+ Puppet.notice "Skipping run of #{client_class}; administratively disabled; use 'puppet agent --enable' to re-enable."
return
end
View
27 lib/puppet/daemon.rb
@@ -167,6 +167,13 @@ def run_event_loop
loop do
now = Time.now.to_i
+ # We set a default wakeup of "one hour from now", which will
+ # recheck everything at a minimum every hour. Just in case something in
+ # the math messes up or something; it should be inexpensive enough to
+ # wake once an hour, then go back to sleep after doing nothing, if
+ # someone only wants listen mode.
+ next_event = now + 60 * 60
+
# Handle reparsing of configuration files, if desired and required.
# `reparse` will just check if the action is required, and would be
# better named `reparse_if_changed` instead.
@@ -176,7 +183,12 @@ def run_event_loop
# The time to the next reparse might have changed, so recalculate
# now. That way we react dynamically to reconfiguration.
reparse_interval = Puppet[:filetimeout].to_i
- next_reparse = now + reparse_interval
+
+ # Set up the next reparse check based on the new reparse_interval.
+ if reparse_interval > 0
+ next_reparse = now + reparse_interval
+ next_event > next_reparse and next_event = next_reparse
+ end
# We should also recalculate the agent run interval, and adjust the
# next time it is scheduled to run, just in case. In the event that
@@ -191,21 +203,14 @@ def run_event_loop
# behaviour. You should not change that. --daniel 2012-02-21
if agent and now >= next_agent_run
agent.run
+
+ # Set up the next agent run time
next_agent_run = now + agent_run_interval
+ next_event > next_agent_run and next_event = next_agent_run
end
# Finally, an interruptable able sleep until the next scheduled event.
- # We also set a default wakeup of "one hour from now", which will
- # recheck everything at a minimum every hour. Just in case something in
- # the math messes up or something; it should be inexpensive enough to
- # wake once an hour, then go back to sleep after doing nothing, if
- # someone only wants listen mode.
- next_event = now + 60 * 60
- next_event > next_reparse and next_event = next_reparse
- next_event > next_agent_run and next_event = next_agent_run
-
how_long = next_event - now
-
how_long > 0 and select([], [], [], how_long)
end
end
View
2  lib/puppet/defaults.rb
@@ -62,7 +62,7 @@ module Puppet
:desc => "Whether to print stack traces on some errors",
},
:autoflush => {
- :default => false,
+ :default => true,
:type => :boolean,
:desc => "Whether log files should always flush to disk.",
:hook => proc { |value| Log.autoflush = value }
View
63 lib/puppet/parser/scope.rb
@@ -20,7 +20,7 @@ class Puppet::Parser::Scope
attr_accessor :source, :resource
attr_accessor :base, :keyword
attr_accessor :top, :translated, :compiler
- attr_accessor :parent, :dynamic
+ attr_accessor :parent
attr_reader :namespaces
# thin wrapper around an ephemeral
@@ -258,10 +258,63 @@ def qualified_scope(classname)
private :qualified_scope
- # Look up a variable. The simplest value search we do.
- # This method is effectively deprecated - use self[] instead.
+ # Look up a variable with traditional scoping and then with new scoping. If
+ # the answers differ then print a deprecation warning.
def lookupvar(name, options = {})
- self[name, options]
+ dynamic_value = dynamic_lookupvar(name,options)
+ twoscope_value = twoscope_lookupvar(name,options)
+ if dynamic_value != twoscope_value
+ location = (options[:file] && options[:line]) ? " at #{options[:file]}:#{options[:line]}" : ''
+ Puppet.deprecation_warning "Dynamic lookup of $#{name}#{location} is deprecated. Support will be removed in a later version of Puppet. Use a fully-qualified variable name (e.g., $classname::variable) or parameterized classes."
+ end
+ dynamic_value
+ end
+
+ # Look up a variable. The simplest value search we do.
+ def twoscope_lookupvar(name, options = {})
+ # Save the originating scope for the request
+ options[:origin] = self unless options[:origin]
+ table = ephemeral?(name) ? @ephemeral.last : @symtable
+ if name =~ /^(.*)::(.+)$/
+ begin
+ qualified_scope($1).twoscope_lookupvar($2, options.merge({:origin => nil}))
+ rescue RuntimeError => e
+ location = (options[:file] && options[:line]) ? " at #{options[:file]}:#{options[:line]}" : ''
+ warning "Could not look up qualified variable '#{name}'; #{e.message}#{location}"
+ :undefined
+ end
+ # If the value is present and either we are top/node scope or originating scope...
+ elsif (ephemeral_include?(name) or table.include?(name)) and (compiler and self == compiler.topscope or (self.resource and self.resource.type == "Node") or self == options[:origin])
+ table[name]
+ elsif resource and resource.type == "Class" and parent_type = resource.resource_type.parent
+ class_scope(parent_type).twoscope_lookupvar(name,options.merge({:origin => nil}))
+ elsif parent
+ parent.twoscope_lookupvar(name, options)
+ else
+ :undefined
+ end
+ end
+
+ # Look up a variable. The simplest value search we do.
+ def dynamic_lookupvar(name, options = {})
+ table = ephemeral?(name) ? @ephemeral.last : @symtable
+ # If the variable is qualified, then find the specified scope and look the variable up there instead.
+ if name =~ /^(.*)::(.+)$/
+ begin
+ qualified_scope($1).dynamic_lookupvar($2,options)
+ rescue RuntimeError => e
+ location = (options[:file] && options[:line]) ? " at #{options[:file]}:#{options[:line]}" : ''
+ warning "Could not look up qualified variable '#{name}'; #{e.message}#{location}"
+ :undefined
+ end
+ elsif ephemeral_include?(name) or table.include?(name)
+ # We can't use "if table[name]" here because the value might be false
+ table[name]
+ elsif parent
+ parent.dynamic_lookupvar(name,options)
+ else
+ :undefined
+ end
end
# Return a hash containing our variables and their values, optionally (and
@@ -392,7 +445,7 @@ def unset_ephemeral_var(level=:all)
# check if name exists in one of the ephemeral scope.
def ephemeral_include?(name)
- @ephemeral.reverse.each do |eph|
+ @ephemeral.reverse_each do |eph|
return true if eph.include?(name)
end
false
View
5 lib/puppet/provider/augeas/augeas.rb
@@ -332,9 +332,8 @@ def need_to_run?
saved_files = @aug.match("/augeas/events/saved")
if saved_files.size > 0
root = resource[:root].sub(/^\/$/, "")
- saved_files.each do |key|
- saved_file = @aug.get(key).sub(/^\/files/, root)
- next unless File.exists?(saved_file + ".augnew")
+ saved_files.map! {|key| @aug.get(key).sub(/^\/files/, root) }
+ saved_files.uniq.each do |saved_file|
if Puppet[:show_diff]
notice "\n" + diff(saved_file, saved_file + ".augnew")
end
View
2  lib/puppet/resource/type.rb
@@ -66,7 +66,7 @@ def evaluate_code(resource)
static_parent = evaluate_parent_type(resource)
scope = static_parent || resource.scope
- scope = scope.newscope(:namespace => namespace, :source => self, :resource => resource, :dynamic => !static_parent) unless resource.title == :main
+ scope = scope.newscope(:namespace => namespace, :source => self, :resource => resource) unless resource.title == :main
scope.compiler.add_class(name) unless definition?
set_resource_parameters(resource, scope)
View
4 lib/puppet/util.rb
@@ -228,6 +228,10 @@ def absolute_path?(path, platform=nil)
:posix => %r!^/!,
}
+ # Due to weird load order issues, I was unable to remove this require.
+ # This is fixed in Telly so it can be removed there.
+ require 'puppet'
+
# Ruby only sets File::ALT_SEPARATOR on Windows and the Ruby standard
# library uses that to test what platform it's on. Normally in Puppet we
# would use Puppet.features.microsoft_windows?, but this method needs to
View
6 spec/lib/puppet_spec/compiler.rb
@@ -0,0 +1,6 @@
+module PuppetSpec::Compiler
+ def compile_to_catalog(string)
+ Puppet[:code] = string
+ Puppet::Parser::Compiler.compile(Puppet::Node.new('foonode'))
+ end
+end
View
200 spec/unit/parser/functions/create_resources_spec.rb
@@ -1,19 +1,16 @@
require 'puppet'
require 'spec_helper'
+require 'puppet_spec/compiler'
describe 'function for dynamically creating resources' do
+ include PuppetSpec::Compiler
- def get_scope
- @topscope = Puppet::Parser::Scope.new
- # This is necessary so we don't try to use the compiler to discover our parent.
- @topscope.parent = nil
+ before :each do
@scope = Puppet::Parser::Scope.new
@scope.compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("floppy", :environment => 'production'))
- @scope.parent = @topscope
+ @topscope = @scope.compiler.topscope
@compiler = @scope.compiler
- end
- before :each do
- get_scope
+ @scope.parent = @topscope
Puppet::Parser::Functions.function(:create_resources)
end
@@ -32,6 +29,7 @@ def get_scope
@scope.function_create_resources(['notify', {'test'=>{}}])
end
end
+
describe 'when the caller supplies a name parameter' do
it 'should set the resource name to the value provided' do
Puppet::Parser::Resource.any_instance.expects(:set_parameter).with(:name, 'user_supplied').once
@@ -41,131 +39,165 @@ def get_scope
end
describe 'when creating native types' do
- before :each do
- Puppet[:code]='notify{test:}'
- get_scope
- @scope.resource=Puppet::Parser::Resource.new('class', 't', :scope => @scope)
- end
-
it 'empty hash should not cause resources to be added' do
- @scope.function_create_resources(['file', {}])
- @compiler.catalog.resources.size == 1
+ noop_catalog = compile_to_catalog("create_resources('file', {})")
+ empty_catalog = compile_to_catalog("")
+ noop_catalog.resources.size.should == empty_catalog.resources.size
end
+
it 'should be able to add' do
- @scope.function_create_resources(['file', {'/etc/foo'=>{'ensure'=>'present'}}])
- @compiler.catalog.resource(:file, "/etc/foo")['ensure'].should == 'present'
+ catalog = compile_to_catalog("create_resources('file', {'/etc/foo'=>{'ensure'=>'present'}})")
+ catalog.resource(:file, "/etc/foo")['ensure'].should == 'present'
end
+
it 'should accept multiple types' do
- type_hash = {}
- type_hash['foo'] = {'message' => 'one'}
- type_hash['bar'] = {'message' => 'two'}
- @scope.function_create_resources(['notify', type_hash])
- @compiler.catalog.resource(:notify, "foo")['message'].should == 'one'
- @compiler.catalog.resource(:notify, "bar")['message'].should == 'two'
+ catalog = compile_to_catalog("create_resources('notify', {'foo'=>{'message'=>'one'}, 'bar'=>{'message'=>'two'}})")
+ catalog.resource(:notify, "foo")['message'].should == 'one'
+ catalog.resource(:notify, "bar")['message'].should == 'two'
end
+
it 'should fail to add non-existing type' do
expect { @scope.function_create_resources(['create-resource-foo', {}]) }.should raise_error(ArgumentError, 'could not create resource of unknown type create-resource-foo')
end
+
it 'should be able to add edges' do
- @scope.function_create_resources(['notify', {'foo'=>{'require' => 'Notify[test]'}}])
- @scope.compiler.compile
- rg = @scope.compiler.catalog.to_ral.relationship_graph
+ catalog = compile_to_catalog("notify { test: }\n create_resources('notify', {'foo'=>{'require'=>'Notify[test]'}})")
+ rg = catalog.to_ral.relationship_graph
test = rg.vertices.find { |v| v.title == 'test' }
foo = rg.vertices.find { |v| v.title == 'foo' }
test.should be
foo.should be
rg.path_between(test,foo).should be
end
+
it 'should account for default values' do
- @scope.function_create_resources(['file', {'/etc/foo'=>{'ensure'=>'present'}, '/etc/baz'=>{'group'=>'food'}}, {'group' => 'bar'}])
- @compiler.catalog.resource(:file, "/etc/foo")['group'].should == 'bar'
- @compiler.catalog.resource(:file, "/etc/baz")['group'].should == 'food'
+ catalog = compile_to_catalog("create_resources('file', {'/etc/foo'=>{'ensure'=>'present'}, '/etc/baz'=>{'group'=>'food'}}, {'group' => 'bar'})")
+ catalog.resource(:file, "/etc/foo")['group'].should == 'bar'
+ catalog.resource(:file, "/etc/baz")['group'].should == 'food'
end
end
describe 'when dynamically creating resource types' do
- before :each do
- Puppet[:code]=
-'define foocreateresource($one){notify{$name: message => $one}}
-notify{test:}
-'
- get_scope
- @scope.resource=Puppet::Parser::Resource.new('class', 't', :scope => @scope)
- Puppet::Parser::Functions.function(:create_resources)
- end
it 'should be able to create defined resoure types' do
- @scope.function_create_resources(['foocreateresource', {'blah'=>{'one'=>'two'}}])
- # still have to compile for this to work...
- # I am not sure if this constraint ruins the tests
- @scope.compiler.compile
- @compiler.catalog.resource(:notify, "blah")['message'].should == 'two'
+ catalog = compile_to_catalog(<<-MANIFEST)
+ define foocreateresource($one) {
+ notify { $name: message => $one }
+ }
+
+ create_resources('foocreateresource', {'blah'=>{'one'=>'two'}})
+ MANIFEST
+ catalog.resource(:notify, "blah")['message'].should == 'two'
end
+
it 'should fail if defines are missing params' do
- @scope.function_create_resources(['foocreateresource', {'blah'=>{}}])
- expect { @scope.compiler.compile }.should raise_error(Puppet::ParseError, 'Must pass one to Foocreateresource[blah]')
+ expect {
+ compile_to_catalog(<<-MANIFEST)
+ define foocreateresource($one) {
+ notify { $name: message => $one }
+ }
+
+ create_resources('foocreateresource', {'blah'=>{}})
+ MANIFEST
+ }.should raise_error(Puppet::Error, 'Must pass one to Foocreateresource[blah] at line 1 on node foonode')
end
+
it 'should be able to add multiple defines' do
- hash = {}
- hash['blah'] = {'one' => 'two'}
- hash['blaz'] = {'one' => 'three'}
- @scope.function_create_resources(['foocreateresource', hash])
- # still have to compile for this to work...
- # I am not sure if this constraint ruins the tests
- @scope.compiler.compile
- @compiler.catalog.resource(:notify, "blah")['message'].should == 'two'
- @compiler.catalog.resource(:notify, "blaz")['message'].should == 'three'
+ catalog = compile_to_catalog(<<-MANIFEST)
+ define foocreateresource($one) {
+ notify { $name: message => $one }
+ }
+
+ create_resources('foocreateresource', {'blah'=>{'one'=>'two'}, 'blaz'=>{'one'=>'three'}})
+ MANIFEST
+
+ catalog.resource(:notify, "blah")['message'].should == 'two'
+ catalog.resource(:notify, "blaz")['message'].should == 'three'
end
+
it 'should be able to add edges' do
- @scope.function_create_resources(['foocreateresource', {'blah'=>{'one'=>'two', 'require' => 'Notify[test]'}}])
- @scope.compiler.compile
- rg = @scope.compiler.catalog.to_ral.relationship_graph
+ catalog = compile_to_catalog(<<-MANIFEST)
+ define foocreateresource($one) {
+ notify { $name: message => $one }
+ }
+
+ notify { test: }
+
+ create_resources('foocreateresource', {'blah'=>{'one'=>'two', 'require' => 'Notify[test]'}})
+ MANIFEST
+
+ rg = catalog.to_ral.relationship_graph
test = rg.vertices.find { |v| v.title == 'test' }
blah = rg.vertices.find { |v| v.title == 'blah' }
test.should be
blah.should be
- # (Yoda speak like we do)
rg.path_between(test,blah).should be
- @compiler.catalog.resource(:notify, "blah")['message'].should == 'two'
+ catalog.resource(:notify, "blah")['message'].should == 'two'
end
+
it 'should account for default values' do
- @scope.function_create_resources(['foocreateresource', {'blah'=>{}}, {'one' => 'two'}])
- @scope.compiler.compile
- @compiler.catalog.resource(:notify, "blah")['message'].should == 'two'
+ catalog = compile_to_catalog(<<-MANIFEST)
+ define foocreateresource($one) {
+ notify { $name: message => $one }
+ }
+
+ create_resources('foocreateresource', {'blah'=>{}}, {'one' => 'two'})
+ MANIFEST
+
+ catalog.resource(:notify, "blah")['message'].should == 'two'
end
end
+
describe 'when creating classes' do
- before :each do
- Puppet[:code]=
-'class bar($one){notify{test: message => $one}}
-notify{tester:}
-'
- get_scope
- @scope.resource=Puppet::Parser::Resource.new('class', 't', :scope => @scope)
- Puppet::Parser::Functions.function(:create_resources)
- end
it 'should be able to create classes' do
- @scope.function_create_resources(['class', {'bar'=>{'one'=>'two'}}])
- @scope.compiler.compile
- @compiler.catalog.resource(:notify, "test")['message'].should == 'two'
- @compiler.catalog.resource(:class, "bar").should_not be_nil
+ catalog = compile_to_catalog(<<-MANIFEST)
+ class bar($one) {
+ notify { test: message => $one }
+ }
+
+ create_resources('class', {'bar'=>{'one'=>'two'}})
+ MANIFEST
+
+ catalog.resource(:notify, "test")['message'].should == 'two'
+ catalog.resource(:class, "bar").should_not be_nil
end
+
it 'should fail to create non-existing classes' do
- expect { @scope.function_create_resources(['class', {'blah'=>{'one'=>'two'}}]) }.should raise_error(ArgumentError ,'could not find hostclass blah')
+ expect {
+ compile_to_catalog(<<-MANIFEST)
+ create_resources('class', {'blah'=>{'one'=>'two'}})
+ MANIFEST
+ }.should raise_error(Puppet::Error ,'could not find hostclass blah at line 1 on node foonode')
end
+
it 'should be able to add edges' do
- @scope.function_create_resources(['class', {'bar'=>{'one'=>'two', 'require' => 'Notify[tester]'}}])
- @scope.compiler.compile
- rg = @scope.compiler.catalog.to_ral.relationship_graph
+ catalog = compile_to_catalog(<<-MANIFEST)
+ class bar($one) {
+ notify { test: message => $one }
+ }
+
+ notify { tester: }
+
+ create_resources('class', {'bar'=>{'one'=>'two', 'require' => 'Notify[tester]'}})
+ MANIFEST
+
+ rg = catalog.to_ral.relationship_graph
test = rg.vertices.find { |v| v.title == 'test' }
tester = rg.vertices.find { |v| v.title == 'tester' }
test.should be
tester.should be
rg.path_between(tester,test).should be
end
+
it 'should account for default values' do
- @scope.function_create_resources(['class', {'bar'=>{}}, {'one' => 'two'}])
- @scope.compiler.compile
- @compiler.catalog.resource(:notify, "test")['message'].should == 'two'
- @compiler.catalog.resource(:class, "bar").should_not be_nil
+ catalog = compile_to_catalog(<<-MANIFEST)
+ class bar($one) {
+ notify { test: message => $one }
+ }
+
+ create_resources('class', {'bar'=>{}}, {'one' => 'two'})
+ MANIFEST
+
+ catalog.resource(:notify, "test")['message'].should == 'two'
+ catalog.resource(:class, "bar").should_not be_nil
end
end
end
View
338 spec/unit/parser/scope_spec.rb
@@ -1,13 +1,13 @@
#!/usr/bin/env rspec
require 'spec_helper'
+require 'puppet_spec/compiler'
describe Puppet::Parser::Scope do
before :each do
- @topscope = Puppet::Parser::Scope.new
- # This is necessary so we don't try to use the compiler to discover our parent.
- @topscope.parent = nil
@scope = Puppet::Parser::Scope.new
@scope.compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("foo"))
+ @scope.source = Puppet::Resource::Type.new(:node, :foo)
+ @topscope = @scope.compiler.topscope
@scope.parent = @topscope
end
@@ -92,14 +92,6 @@
scope = Puppet::Parser::Scope.new
scope.singleton_class.ancestors.should be_include(Puppet::Parser::Functions.environment_module(root))
end
-
- it "should remember if it is dynamic" do
- (!!Puppet::Parser::Scope.new(:dynamic => true).dynamic).should == true
- end
-
- it "should assume it is not dynamic" do
- (!Puppet::Parser::Scope.new.dynamic).should == true
- end
end
describe "when looking up a variable" do
@@ -154,10 +146,20 @@
@scope.singleton_class.ancestors.should be_include(Enumerable)
end
+ it "should be able to look up intermediary variables in parent scopes (DEPRECATED)" do
+ Puppet.expects(:deprecation_warning)
+ thirdscope = Puppet::Parser::Scope.new
+ thirdscope.parent = @scope
+ thirdscope.source = Puppet::Resource::Type.new(:hostclass, :foo, :module_name => "foo")
+ @scope.source = Puppet::Resource::Type.new(:hostclass, :bar, :module_name => "bar")
+
+ @topscope.setvar("var2","parentval")
+ @scope.setvar("var2","childval")
+ thirdscope.lookupvar("var2").should == "childval"
+ end
+
describe "and the variable is qualified" do
- before do
- @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("foonode"))
- @scope.compiler = @compiler
+ before :each do
@known_resource_types = @scope.known_resource_types
end
@@ -177,6 +179,7 @@ def create_class_scope(name)
end
it "should be able to look up explicitly fully qualified variables from main" do
+ Puppet.expects(:deprecation_warning).never
other_scope = create_class_scope("")
other_scope["othervar"] = "otherval"
@@ -185,6 +188,7 @@ def create_class_scope(name)
end
it "should be able to look up explicitly fully qualified variables from other scopes" do
+ Puppet.expects(:deprecation_warning).never
other_scope = create_class_scope("other")
other_scope["var"] = "otherval"
@@ -193,6 +197,7 @@ def create_class_scope(name)
end
it "should be able to look up deeply qualified variables" do
+ Puppet.expects(:deprecation_warning).never
other_scope = create_class_scope("other::deep::klass")
other_scope["var"] = "otherval"
@@ -230,8 +235,311 @@ def create_class_scope(name)
end
end
+ describe "when mixing inheritence and inclusion" do
+ include PuppetSpec::Compiler
+
+ def expect_the_message_to_be(message)
+ catalog = compile_to_catalog(yield)
+ catalog.resource('Notify', 'something')[:message].should == message
+ end
+
+ context "deprecated scoping" do
+ before :each do
+ Puppet.expects(:deprecation_warning)
+ end
+
+ it "prefers values in its included scope over those from the node (DEPRECATED)" do
+ expect_the_message_to_be('baz_msg') do <<-MANIFEST
+ node default {
+ $var = "node_msg"
+ include foo
+ }
+ class baz {
+ $var = "baz_msg"
+ include bar
+ }
+ class foo inherits baz {
+ }
+ class bar {
+ notify { 'something': message => $var, }
+ }
+ MANIFEST
+ end
+ end
+
+ it "finds values in its included scope (DEPRECATED)" do
+ expect_the_message_to_be('baz_msg') do <<-MANIFEST
+ node default {
+ include baz
+ }
+ class foo {
+ }
+ class bar inherits foo {
+ notify { 'something': message => $var, }
+ }
+ class baz {
+ $var = "baz_msg"
+ include bar
+ }
+ MANIFEST
+ end
+ end
+
+ it "recognizes a dynamically scoped boolean (DEPRECATED)" do
+ expect_the_message_to_be(true) do <<-MANIFEST
+ node default {
+ $var = false
+ include baz
+ }
+ class foo {
+ }
+ class bar inherits foo {
+ notify { 'something': message => $var, }
+ }
+ class baz {
+ $var = true
+ include bar
+ }
+ MANIFEST
+ end
+ end
+ end
+
+ context "supported scoping" do
+ before :each do
+ Puppet.expects(:deprecation_warning).never
+ end
+
+ it "finds value define in the inherited node" do
+ expect_the_message_to_be('parent_msg') do <<-MANIFEST
+ $var = "top_msg"
+ node parent {
+ $var = "parent_msg"
+ }
+ node default inherits parent {
+ include foo
+ }
+ class foo {
+ notify { 'something': message => $var, }
+ }
+ MANIFEST
+ end
+ end
+
+ it "finds top scope when the class is included before the node defines the var" do
+ expect_the_message_to_be('top_msg') do <<-MANIFEST
+ $var = "top_msg"
+ node parent {
+ include foo
+ }
+ node default inherits parent {
+ $var = "default_msg"
+ }
+ class foo {
+ notify { 'something': message => $var, }
+ }
+ MANIFEST
+ end
+ end
+
+ it "finds top scope when the class is included before the node defines the var" do
+ expect_the_message_to_be('top_msg') do <<-MANIFEST
+ $var = "top_msg"
+ node parent {
+ include foo
+ }
+ node default inherits parent {
+ $var = "default_msg"
+ }
+ class foo {
+ notify { 'something': message => $var, }
+ }
+ MANIFEST
+ end
+ end
+
+
+ it "should find values in its local scope" do
+ expect_the_message_to_be('local_msg') do <<-MANIFEST
+ node default {
+ include baz
+ }
+ class foo {
+ }
+ class bar inherits foo {
+ $var = "local_msg"
+ notify { 'something': message => $var, }
+ }
+ class baz {
+ include bar
+ }
+ MANIFEST
+ end
+ end
+
+ it "should find values in its inherited scope" do
+ expect_the_message_to_be('foo_msg') do <<-MANIFEST
+ node default {
+ include baz
+ }
+ class foo {
+ $var = "foo_msg"
+ }
+ class bar inherits foo {
+ notify { 'something': message => $var, }
+ }
+ class baz {
+ include bar
+ }
+ MANIFEST
+ end
+ end
+
+ it "prefers values in its inherited scope over those in the node (with intermediate inclusion)" do
+ expect_the_message_to_be('foo_msg') do <<-MANIFEST
+ node default {
+ $var = "node_msg"
+ include baz
+ }
+ class foo {
+ $var = "foo_msg"
+ }
+ class bar inherits foo {
+ notify { 'something': message => $var, }
+ }
+ class baz {
+ include bar
+ }
+ MANIFEST
+ end
+ end
+
+ it "prefers values in its inherited scope over those in the node (without intermediate inclusion)" do
+ expect_the_message_to_be('foo_msg') do <<-MANIFEST
+ node default {
+ $var = "node_msg"
+ include bar
+ }
+ class foo {
+ $var = "foo_msg"
+ }
+ class bar inherits foo {
+ notify { 'something': message => $var, }
+ }
+ MANIFEST
+ end
+ end
+
+ it "prefers values in its inherited scope over those from where it is included" do
+ expect_the_message_to_be('foo_msg') do <<-MANIFEST
+ node default {
+ include baz
+ }
+ class foo {
+ $var = "foo_msg"
+ }
+ class bar inherits foo {
+ notify { 'something': message => $var, }
+ }
+ class baz {
+ $var = "baz_msg"
+ include bar
+ }
+ MANIFEST
+ end
+ end
+
+ it "does not used variables from classes included in the inherited scope" do
+ expect_the_message_to_be('node_msg') do <<-MANIFEST
+ node default {
+ $var = "node_msg"
+ include bar
+ }
+ class quux {
+ $var = "quux_msg"
+ }
+ class foo inherits quux {
+ }
+ class baz {
+ include foo
+ }
+ class bar inherits baz {
+ notify { 'something': message => $var, }
+ }
+ MANIFEST
+ end
+ end
+
+ it "does not use a variable from a scope lexically enclosing it" do
+ expect_the_message_to_be('node_msg') do <<-MANIFEST
+ node default {
+ $var = "node_msg"
+ include other::bar
+ }
+ class other {
+ $var = "other_msg"
+ class bar {
+ notify { 'something': message => $var, }
+ }
+ }
+ MANIFEST
+ end
+ end
+
+ it "finds values in its node scope" do
+ expect_the_message_to_be('node_msg') do <<-MANIFEST
+ node default {
+ $var = "node_msg"
+ include baz
+ }
+ class foo {
+ }
+ class bar inherits foo {
+ notify { 'something': message => $var, }
+ }
+ class baz {
+ include bar
+ }
+ MANIFEST
+ end
+ end
+
+ it "finds values in its top scope" do
+ expect_the_message_to_be('top_msg') do <<-MANIFEST
+ $var = "top_msg"
+ node default {
+ include baz
+ }
+ class foo {
+ }
+ class bar inherits foo {
+ notify { 'something': message => $var, }
+ }
+ class baz {
+ include bar
+ }
+ MANIFEST
+ end
+ end
+
+ it "prefers variables from the node over those in the top scope" do
+ expect_the_message_to_be('node_msg') do <<-MANIFEST
+ $var = "top_msg"
+ node default {
+ $var = "node_msg"
+ include foo
+ }
+ class foo {
+ notify { 'something': message => $var, }
+ }
+ MANIFEST
+ end
+ end
+ end
+ end
+
describe "when variables are set with append=true" do
- it "should raise an error if the variable is already defined in this scope" do
+ it "should raise error if the variable is already defined in this scope" do
@scope.setvar("var","1", :append => false)
lambda { @scope.setvar("var","1", :append => true) }.should raise_error(Puppet::ParseError)
end
View
13 spec/unit/provider/augeas/augeas_spec.rb
@@ -330,7 +330,6 @@
it "should call diff when a file is shown to have been changed" do
file = "/etc/hosts"
File.stubs(:delete)
- File.stubs(:exists?).returns(true)
@resource[:context] = "/files"
@resource[:changes] = ["set #{file}/foo bar"]
@@ -348,7 +347,6 @@
file1 = "/etc/hosts"
file2 = "/etc/resolv.conf"
File.stubs(:delete)
- File.stubs(:exists?).returns(true)
@resource[:context] = "/files"
@resource[:changes] = ["set #{file1}/foo bar", "set #{file2}/baz biz"]
@@ -369,7 +367,6 @@
root = "/tmp/foo"
file = "/etc/hosts"
File.stubs(:delete)
- File.stubs(:exists?).returns(true)
@resource[:context] = "/files"
@resource[:changes] = ["set #{file}/foo bar"]
@@ -402,7 +399,6 @@
it "should cleanup the .augnew file" do
file = "/etc/hosts"
- File.stubs(:exists?).returns(true)
@resource[:context] = "/files"
@resource[:changes] = ["set #{file}/foo bar"]
@@ -422,11 +418,6 @@
it "should handle duplicate /augeas/events/saved filenames" do
file = "/etc/hosts"
- augnew = states("augnew").starts_as("present")
-
- File.stubs(:exists?).returns(true).when(augnew.is("present"))
- File.stubs(:exists?).returns(false).when(augnew.is("absent"))
-
@resource[:context] = "/files"
@resource[:changes] = ["set #{file}/foo bar"]
@@ -436,9 +427,9 @@
@augeas.expects(:set).with("/augeas/save", "newfile")
@augeas.expects(:close)
- File.expects(:delete).with(file + ".augnew").when(augnew.is("present")).then(augnew.is("absent"))
+ File.expects(:delete).with(file + ".augnew").once()
- @provider.expects(:diff).with("#{file}", "#{file}.augnew").returns("").when(augnew.is("present"))
+ @provider.expects(:diff).with("#{file}", "#{file}.augnew").returns("").once()
@provider.should be_need_to_run
end
View
4 spec/unit/resource/type_spec.rb
@@ -238,7 +238,7 @@ def double_convert
describe "when setting its parameters in the scope" do
before do
- @scope = Puppet::Parser::Scope.new
+ @scope = Puppet::Parser::Scope.new(:compiler => Puppet::Parser::Compiler.new(Puppet::Node.new("foo")), :source => stub("source"))
@resource = Puppet::Parser::Resource.new(:foo, "bar", :scope => @scope)
@type = Puppet::Resource::Type.new(:definition, "foo")
@resource.environment.known_resource_types.add @type
@@ -433,7 +433,7 @@ def double_convert
it "should set all of its parameters in a subscope" do
subscope = stub 'subscope', :compiler => @compiler
- @scope.expects(:newscope).with(:source => @type, :dynamic => true, :namespace => 'foo', :resource => @resource).returns subscope
+ @scope.expects(:newscope).with(:source => @type, :namespace => 'foo', :resource => @resource).returns subscope
@type.expects(:set_resource_parameters).with(@resource, subscope)
@type.evaluate_code(@resource)
View
4 spec/unit/util/log/destinations_spec.rb
@@ -29,8 +29,8 @@
@class = Puppet::Util::Log.desttypes[:file]
end
- it "should default to autoflush false" do
- @class.new('/tmp/log').autoflush.should == false
+ it "should default to automatically flush log output" do
+ @class.new('/tmp/log').autoflush.should == true
end
describe "when matching" do
View
4 spec/unit/util/log_spec.rb
@@ -81,9 +81,7 @@
end
end
- describe Puppet::Util::Log::DestEventlog, :if => Puppet.features.microsoft_windows? do
- require 'win32/eventlog' if Puppet.features.microsoft_windows?
-
+ describe Puppet::Util::Log::DestEventlog, :if => Puppet.features.eventlog? do
before :each do
Win32::EventLog.stubs(:open).returns(mock 'mylog')
Win32::EventLog.stubs(:report_event)
Please sign in to comment.
Something went wrong with that request. Please try again.