summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStig Sandbeck Mathisen <ssm@debian.org>2014-10-24 13:27:50 +0200
committerStig Sandbeck Mathisen <ssm@debian.org>2014-10-24 13:27:50 +0200
commitdeaf3b4969d6518166fd08a10a387c45a4fc58ec (patch)
tree1fc59395cdea4c292f53e377338649c1ea369703
parent52dd92b16375a2ab1242e3fadb42567abd798cd6 (diff)
parent652bc05e123a78ffe7b34f9b9f674e6e04be6ee5 (diff)
downloadpuppet-deaf3b4969d6518166fd08a10a387c45a4fc58ec.tar.gz
Imported Upstream version 3.7.2upstream/3.7.2
-rw-r--r--ext/build_defaults.yaml6
-rw-r--r--ext/debian/changelog6
-rw-r--r--ext/debian/control2
-rw-r--r--ext/ips/puppet.p5m4
-rw-r--r--ext/project_data.yaml4
-rw-r--r--ext/redhat/puppet.spec8
-rw-r--r--lib/puppet/application.rb5
-rw-r--r--lib/puppet/configurer.rb10
-rw-r--r--lib/puppet/environments.rb50
-rw-r--r--lib/puppet/indirector/node/exec.rb2
-rw-r--r--lib/puppet/indirector/request.rb3
-rw-r--r--lib/puppet/module.rb2
-rw-r--r--lib/puppet/module_tool.rb2
-rw-r--r--lib/puppet/network/http/webrick.rb24
-rw-r--r--lib/puppet/node.rb4
-rw-r--r--lib/puppet/parser/ast/pops_bridge.rb12
-rw-r--r--lib/puppet/parser/compiler.rb3
-rw-r--r--lib/puppet/parser/resource.rb4
-rw-r--r--lib/puppet/parser/resource/param.rb2
-rw-r--r--lib/puppet/parser/type_loader.rb2
-rw-r--r--lib/puppet/pops/evaluator/access_operator.rb14
-rw-r--r--lib/puppet/pops/evaluator/evaluator_impl.rb2
-rw-r--r--lib/puppet/pops/evaluator/runtime3_support.rb34
-rw-r--r--lib/puppet/pops/model/factory.rb17
-rw-r--r--lib/puppet/pops/parser/egrammar.ra2
-rw-r--r--lib/puppet/pops/parser/eparser.rb2
-rw-r--r--lib/puppet/pops/parser/parser_support.rb20
-rw-r--r--lib/puppet/pops/types/type_calculator.rb33
-rw-r--r--lib/puppet/provider/package/pkg.rb13
-rw-r--r--lib/puppet/provider/scheduled_task/win32_taskscheduler.rb31
-rw-r--r--lib/puppet/provider/ssh_authorized_key/parsed.rb16
-rw-r--r--lib/puppet/resource.rb9
-rw-r--r--lib/puppet/settings.rb17
-rw-r--r--lib/puppet/type/user.rb12
-rw-r--r--lib/puppet/util/autoload.rb16
-rw-r--r--lib/puppet/util/monkey_patches.rb4
-rw-r--r--lib/puppet/version.rb2
-rw-r--r--spec/fixtures/unit/provider/package/pkg/dummy_solaris11.certificate_warning2
-rw-r--r--spec/fixtures/unit/type/user/authorized_keys1
-rwxr-xr-xspec/integration/application/apply_spec.rb52
-rw-r--r--spec/integration/parser/future_compiler_spec.rb56
-rw-r--r--spec/integration/type/user_spec.rb23
-rwxr-xr-xspec/lib/puppet_spec/files.rb1
-rw-r--r--spec/unit/environments_spec.rb99
-rwxr-xr-xspec/unit/network/http/webrick_spec.rb23
-rwxr-xr-xspec/unit/parser/compiler_spec.rb20
-rw-r--r--spec/unit/parser/functions/lookup_spec.rb25
-rwxr-xr-xspec/unit/parser/resource/param_spec.rb32
-rwxr-xr-xspec/unit/parser/resource_spec.rb4
-rw-r--r--spec/unit/pops/evaluator/evaluating_parser_spec.rb35
-rw-r--r--spec/unit/pops/parser/parse_calls_spec.rb25
-rw-r--r--spec/unit/pops/types/type_calculator_spec.rb61
-rwxr-xr-xspec/unit/provider/package/pkg_spec.rb4
-rw-r--r--spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb61
-rwxr-xr-xspec/unit/provider/ssh_authorized_key/parsed_spec.rb15
-rwxr-xr-xspec/unit/type/user_spec.rb5
-rwxr-xr-xspec/unit/util/autoload_spec.rb47
-rwxr-xr-xspec/unit/util/monkey_patches_spec.rb12
-rw-r--r--tasks/memwalk.rake195
59 files changed, 968 insertions, 229 deletions
diff --git a/ext/build_defaults.yaml b/ext/build_defaults.yaml
index d62e70555..95b378942 100644
--- a/ext/build_defaults.yaml
+++ b/ext/build_defaults.yaml
@@ -16,7 +16,7 @@ build_gem: TRUE
build_dmg: TRUE
build_msi:
puppet_for_the_win:
- ref: 'c61dda253b09bd855488f7b6dd7332fdf84d3039'
+ ref: 'f4f74b1c8d8792089d1d3328b01f5ff075771eb0'
repo: 'git://github.com/puppetlabs/puppet_for_the_win.git'
facter:
ref: 'refs/tags/2.2.0'
@@ -26,8 +26,8 @@ build_msi:
repo: 'git://github.com/puppetlabs/hiera.git'
sys:
ref:
- x86: '890ad47c3b70de4e4956d2699b54d481d5a1b72e'
- x64: '2820779a3f4281534a6792b0ab20b2cf213647dc'
+ x86: 'cbe94f4cafb0f78d587e8addcf723bc671af7cca'
+ x64: '417378f607340d211fbfef89a96e6639bef1bfb1'
repo: 'git://github.com/puppetlabs/puppet-win32-ruby.git'
apt_host: 'apt.puppetlabs.com'
apt_repo_url: 'http://apt.puppetlabs.com'
diff --git a/ext/debian/changelog b/ext/debian/changelog
index f59ac3ba1..f34f69456 100644
--- a/ext/debian/changelog
+++ b/ext/debian/changelog
@@ -1,8 +1,8 @@
-puppet (3.7.1-1puppetlabs1) hardy lucid natty oneiric unstable sid squeeze wheezy precise; urgency=low
+puppet (3.7.2-1puppetlabs1) hardy lucid natty oneiric unstable sid squeeze wheezy precise; urgency=low
- * Update to version 3.7.1-1puppetlabs1
+ * Update to version 3.7.2-1puppetlabs1
- -- Puppet Labs Release <info@puppetlabs.com> Mon, 15 Sep 2014 13:33:06 -0700
+ -- Puppet Labs Release <info@puppetlabs.com> Tue, 21 Oct 2014 14:52:30 -0700
puppet (3.2.3-0.1rc0puppetlabs1) lucid unstable sid squeeze wheezy precise quantal raring; urgency=low
diff --git a/ext/debian/control b/ext/debian/control
index 02c1f8f42..3bdccb683 100644
--- a/ext/debian/control
+++ b/ext/debian/control
@@ -60,6 +60,7 @@ Architecture: all
Depends: ${misc:Depends}, ruby | ruby-interpreter, puppet-common (= ${binary:Version}), facter (>= 1.7.0), lsb-base
Breaks: puppet (<< 0.24.7-1), puppetmaster (<< 2.6.1~rc2-1)
Replaces: puppetmaster (<< 2.6.1~rc2-1)
+Conflicts: puppet-common (<< 3.3.0-1puppetlabs1)
Suggests: apache2 | nginx, puppet-el, vim-puppet, stompserver, ruby-stomp | libstomp-ruby1.8,
rdoc, ruby-ldap | libldap-ruby1.8, puppetdb-terminus
Description: Puppet master common scripts
@@ -81,6 +82,7 @@ Package: puppetmaster
Architecture: all
Depends: ${misc:Depends}, ruby | ruby-interpreter, puppetmaster-common (= ${source:Version}), facter (>= 1.7.0), lsb-base
Breaks: puppet (<< 0.24.7-1)
+Conflicts: puppet (<< 3.3.0-1puppetlabs1)
Suggests: apache2 | nginx, puppet-el, vim-puppet, stompserver, ruby-stomp | libstomp-ruby1.8,
rdoc, ruby-ldap | libldap-ruby1.8, puppetdb-terminus
Description: Centralized configuration management - master startup and compatibility scripts
diff --git a/ext/ips/puppet.p5m b/ext/ips/puppet.p5m
index fc3c204b3..f1fab5c2e 100644
--- a/ext/ips/puppet.p5m
+++ b/ext/ips/puppet.p5m
@@ -1,6 +1,6 @@
-set name=pkg.fmri value=pkg://puppetlabs.com/system/management/@3.7.1,13.3.0-0
+set name=pkg.fmri value=pkg://puppetlabs.com/system/management/@3.7.2,13.4.0-0
set name=pkg.summary value="Puppet, an automated configuration management tool"
-set name=pkg.human-version value="3.7.1"
+set name=pkg.human-version value="3.7.2"
set name=pkg.description value="Puppet, an automated configuration management tool"
set name=info.classification value="org.opensolaris.category.2008:System/Administration and Configuration"
set name=org.opensolaris.consolidation value="puppet"
diff --git a/ext/project_data.yaml b/ext/project_data.yaml
index 292d8de26..3f0867dc0 100644
--- a/ext/project_data.yaml
+++ b/ext/project_data.yaml
@@ -33,7 +33,7 @@ gem_platform_dependencies:
win32-eventlog: '~> 0.6.1'
win32-process: '~> 0.7.4'
win32-security: '~> 0.2.5'
- win32-service: '~> 0.8.4'
+ win32-service: '~> 0.8.6'
win32console: '1.3.2'
minitar: '~> 0.5.4'
x64-mingw32:
@@ -43,7 +43,7 @@ gem_platform_dependencies:
win32-eventlog: '~> 0.6.1'
win32-process: '~> 0.7.4'
win32-security: '~> 0.2.5'
- win32-service: '~> 0.8.4'
+ win32-service: '~> 0.8.6'
minitar: '~> 0.5.4'
bundle_platforms:
x86-mingw32: mingw
diff --git a/ext/redhat/puppet.spec b/ext/redhat/puppet.spec
index c027fcc5e..0887760a8 100644
--- a/ext/redhat/puppet.spec
+++ b/ext/redhat/puppet.spec
@@ -16,8 +16,8 @@
%endif
# VERSION is subbed out during rake srpm process
-%global realversion 3.7.1
-%global rpmversion 3.7.1
+%global realversion 3.7.2
+%global rpmversion 3.7.2
%global confdir ext/redhat
%global pending_upgrade_path %{_localstatedir}/lib/rpm-state/puppet
@@ -446,8 +446,8 @@ fi
rm -rf %{buildroot}
%changelog
-* Mon Sep 15 2014 Puppet Labs Release <info@puppetlabs.com> - 3.7.1-1
-- Build for 3.7.1
+* Tue Oct 21 2014 Puppet Labs Release <info@puppetlabs.com> - 3.7.2-1
+- Build for 3.7.2
* Wed Oct 2 2013 Jason Antman <jason@jasonantman.com>
- Move systemd service and unit file names back to "puppet" from erroneous "puppetagent"
diff --git a/lib/puppet/application.rb b/lib/puppet/application.rb
index 1d9611093..0e98d8adb 100644
--- a/lib/puppet/application.rb
+++ b/lib/puppet/application.rb
@@ -360,10 +360,7 @@ class Application
#
configured_environment_name = Puppet[:environment]
if self.class.run_mode.name != :agent
- configured_environment = Puppet.lookup(:environments).get(configured_environment_name)
- if configured_environment.nil?
- fail(Puppet::Environments::EnvironmentNotFound, configured_environment_name)
- end
+ configured_environment = Puppet.lookup(:environments).get!(configured_environment_name)
else
configured_environment = Puppet::Node::Environment.remote(configured_environment_name)
end
diff --git a/lib/puppet/configurer.rb b/lib/puppet/configurer.rb
index bfd4b518b..7206ee0ce 100644
--- a/lib/puppet/configurer.rb
+++ b/lib/puppet/configurer.rb
@@ -156,7 +156,9 @@ class Puppet::Configurer
unless options[:catalog]
begin
if node = Puppet::Node.indirection.find(Puppet[:node_name_value],
- :environment => @environment, :ignore_cache => true, :transaction_uuid => @transaction_uuid,
+ :environment => Puppet::Node::Environment.remote(@environment),
+ :ignore_cache => true,
+ :transaction_uuid => @transaction_uuid,
:fail_on_404 => true)
# If we have deserialized a node from a rest call, we want to set
@@ -242,7 +244,7 @@ class Puppet::Configurer
def send_report(report)
puts report.summary if Puppet[:summarize]
save_last_run_summary(report)
- Puppet::Transaction::Report.indirection.save(report, nil, :environment => @environment) if Puppet[:report]
+ Puppet::Transaction::Report.indirection.save(report, nil, :environment => Puppet::Node::Environment.remote(@environment)) if Puppet[:report]
rescue => detail
Puppet.log_exception(detail, "Could not send report: #{detail}")
end
@@ -274,7 +276,7 @@ class Puppet::Configurer
result = nil
@duration = thinmark do
result = Puppet::Resource::Catalog.indirection.find(Puppet[:node_name_value],
- query_options.merge(:ignore_terminus => true, :environment => @environment))
+ query_options.merge(:ignore_terminus => true, :environment => Puppet::Node::Environment.remote(@environment)))
end
Puppet.notice "Using cached catalog"
result
@@ -287,7 +289,7 @@ class Puppet::Configurer
result = nil
@duration = thinmark do
result = Puppet::Resource::Catalog.indirection.find(Puppet[:node_name_value],
- query_options.merge(:ignore_cache => true, :environment => @environment, :fail_on_404 => true))
+ query_options.merge(:ignore_cache => true, :environment => Puppet::Node::Environment.remote(@environment), :fail_on_404 => true))
end
result
rescue SystemExit,NoMemoryError
diff --git a/lib/puppet/environments.rb b/lib/puppet/environments.rb
index 9f7ac5c31..ec7a12940 100644
--- a/lib/puppet/environments.rb
+++ b/lib/puppet/environments.rb
@@ -48,6 +48,14 @@ module Puppet::Environments
# we are looking up
# @return [Puppet::Setting::EnvironmentConf, nil] the configuration for the
# requested environment, or nil if not found or no configuration is available
+ #
+ # @!macro [new] loader_get_or_fail
+ # Find a named environment or raise
+ # Puppet::Environments::EnvironmentNotFound when the named environment is
+ # does not exist.
+ #
+ # @param name [String,Symbol] The name of environment to find
+ # @return [Puppet::Node::Environment] the requested environment
# A source of pre-defined environments.
#
@@ -76,6 +84,14 @@ module Puppet::Environments
end
end
+ # @!macro loader_get_or_fail
+ def get!(name)
+ if !environment = get(name)
+ raise EnvironmentNotFound, name
+ end
+ environment
+ end
+
# Returns a basic environment configuration object tied to the environment's
# implementation values. Will not interpolate.
#
@@ -144,6 +160,14 @@ module Puppet::Environments
Puppet::Node::Environment.new(name)
end
+ # @note Because the Legacy system cannot list out all of its environments,
+ # this method will never fail and is only calling get directly.
+ #
+ # @!macro loader_get_or_fail
+ def get!(name)
+ get(name)
+ end
+
# @note we could return something here, but since legacy environments
# are deprecated, there is no point.
#
@@ -187,11 +211,11 @@ module Puppet::Environments
# @!macro loader_list
def list
valid_directories.collect do |envdir|
- name = Puppet::FileSystem.basename_string(envdir)
+ name = Puppet::FileSystem.basename_string(envdir).intern
setting_values = Puppet.settings.values(name, Puppet.settings.preferred_run_mode)
env = Puppet::Node::Environment.create(
- name.intern,
+ name,
Puppet::Node::Environment.split_path(setting_values.interpolate(:modulepath)),
setting_values.interpolate(:manifest),
setting_values.interpolate(:config_version)
@@ -206,6 +230,14 @@ module Puppet::Environments
list.find { |env| env.name == name.intern }
end
+ # @!macro loader_get_or_fail
+ def get!(name)
+ if !environment = get(name)
+ raise EnvironmentNotFound, name
+ end
+ environment
+ end
+
# @!macro loader_get_conf
def get_conf(name)
valid_directories.each do |envdir|
@@ -259,6 +291,16 @@ module Puppet::Environments
nil
end
+ # @!macro loader_get_or_fail
+ def get!(name)
+ @loaders.each do |loader|
+ if env = loader.get(name)
+ return env
+ end
+ end
+ raise EnvironmentNotFound, name
+ end
+
# @!macro loader_get_conf
def get_conf(name)
@loaders.each do |loader|
@@ -325,10 +367,12 @@ module Puppet::Environments
end
# Evicts the entry if it has expired
- #
+ # Also clears caches in Settings that may prevent the entry from being updated
def evict_if_expired(name)
if (result = @cache[name]) && result.expired?
@cache.delete(name)
+
+ Puppet.settings.clear_environment_settings(name)
end
end
diff --git a/lib/puppet/indirector/node/exec.rb b/lib/puppet/indirector/node/exec.rb
index d4faf74f4..2535ffac5 100644
--- a/lib/puppet/indirector/node/exec.rb
+++ b/lib/puppet/indirector/node/exec.rb
@@ -21,7 +21,7 @@ class Puppet::Node::Exec < Puppet::Indirector::Exec
# Set the requested environment if it wasn't overridden
# If we don't do this it gets set to the local default
- result[:environment] ||= request.environment.name
+ result[:environment] ||= request.environment
create_node(request.key, result)
end
diff --git a/lib/puppet/indirector/request.rb b/lib/puppet/indirector/request.rb
index 04c55f9a3..a156f9de5 100644
--- a/lib/puppet/indirector/request.rb
+++ b/lib/puppet/indirector/request.rb
@@ -95,8 +95,7 @@ class Puppet::Indirector::Request
elsif (current_environment = Puppet.lookup(:current_environment)).name == env
current_environment
else
- Puppet.lookup(:environments).get(env) ||
- raise(Puppet::Environments::EnvironmentNotFound, env)
+ Puppet.lookup(:environments).get!(env)
end
end
diff --git a/lib/puppet/module.rb b/lib/puppet/module.rb
index 3a3435c35..deecfd45b 100644
--- a/lib/puppet/module.rb
+++ b/lib/puppet/module.rb
@@ -29,7 +29,7 @@ class Puppet::Module
def self.find(modname, environment = nil)
return nil unless modname
# Unless a specific environment is given, use the current environment
- env = environment ? Puppet.lookup(:environments).get(environment) : Puppet.lookup(:current_environment)
+ env = environment ? Puppet.lookup(:environments).get!(environment) : Puppet.lookup(:current_environment)
env.module(modname)
end
diff --git a/lib/puppet/module_tool.rb b/lib/puppet/module_tool.rb
index 8f462f6d8..984947d33 100644
--- a/lib/puppet/module_tool.rb
+++ b/lib/puppet/module_tool.rb
@@ -151,7 +151,7 @@ module Puppet
elsif options[:environment]
# This use of looking up an environment is correct since it honours
# a reguest to get a particular environment via environment name.
- Puppet.lookup(:environments).get(options[:environment])
+ Puppet.lookup(:environments).get!(options[:environment])
else
Puppet.lookup(:current_environment)
end
diff --git a/lib/puppet/network/http/webrick.rb b/lib/puppet/network/http/webrick.rb
index 820d4556c..aa4f38359 100644
--- a/lib/puppet/network/http/webrick.rb
+++ b/lib/puppet/network/http/webrick.rb
@@ -8,18 +8,15 @@ require 'puppet/ssl/certificate_revocation_list'
require 'puppet/ssl/configuration'
class Puppet::Network::HTTP::WEBrick
+ CIPHERS = "EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!IDEA:!ECDSA:kEDH:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA"
+
def initialize
@listening = false
end
def listen(address, port)
- arguments = {:BindAddress => address, :Port => port, :DoNotReverseLookup => true}
- arguments.merge!(setup_logger)
- arguments.merge!(setup_ssl)
+ @server = create_server(address, port)
- BasicSocket.do_not_reverse_lookup = true
-
- @server = WEBrick::HTTPServer.new(arguments)
@server.listeners.each { |l| l.start_immediately = false }
@server.mount('/', Puppet::Network::HTTP::WEBrickREST)
@@ -55,6 +52,19 @@ class Puppet::Network::HTTP::WEBrick
@thread.join
end
+ # @api private
+ def create_server(address, port)
+ arguments = {:BindAddress => address, :Port => port, :DoNotReverseLookup => true}
+ arguments.merge!(setup_logger)
+ arguments.merge!(setup_ssl)
+
+ BasicSocket.do_not_reverse_lookup = true
+
+ server = WEBrick::HTTPServer.new(arguments)
+ server.ssl_context.ciphers = CIPHERS
+ server
+ end
+
# Configure our http log file.
def setup_logger
# Make sure the settings are all ready for us.
@@ -96,7 +106,7 @@ class Puppet::Network::HTTP::WEBrick
results[:SSLCertificate] = host.certificate.content
results[:SSLStartImmediately] = true
results[:SSLEnable] = true
- results[:SSLOptions] = OpenSSL::SSL::OP_NO_SSLv2
+ results[:SSLOptions] = OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3
raise Puppet::Error, "Could not find CA certificate" unless Puppet::SSL::Certificate.indirection.find(Puppet::SSL::CA_NAME)
diff --git a/lib/puppet/node.rb b/lib/puppet/node.rb
index d61d49385..32f11168c 100644
--- a/lib/puppet/node.rb
+++ b/lib/puppet/node.rb
@@ -67,7 +67,7 @@ class Puppet::Node
# for a node when it has not specified its environment
# Tt will be used to establish what the current environment is.
#
- self.environment = Puppet.lookup(:environments).get(Puppet[:environment])
+ self.environment = Puppet.lookup(:environments).get!(Puppet[:environment])
end
@environment
@@ -76,7 +76,7 @@ class Puppet::Node
def environment=(env)
if env.is_a?(String) or env.is_a?(Symbol)
- @environment = Puppet.lookup(:environments).get(env)
+ @environment = Puppet.lookup(:environments).get!(env)
else
@environment = env
end
diff --git a/lib/puppet/parser/ast/pops_bridge.rb b/lib/puppet/parser/ast/pops_bridge.rb
index 9c6a31744..22a687971 100644
--- a/lib/puppet/parser/ast/pops_bridge.rb
+++ b/lib/puppet/parser/ast/pops_bridge.rb
@@ -55,13 +55,6 @@ class Puppet::Parser::AST::PopsBridge
end
end
- class NilAsUndefExpression < Expression
- def evaluate(scope)
- result = super
- result.nil? ? :undef : result
- end
- end
-
# Bridges the top level "Program" produced by the pops parser.
# Its main purpose is to give one point where all definitions are instantiated (actually defined since the
# Puppet 3x terminology is somewhat misleading - the definitions are instantiated, but instances of the created types
@@ -113,11 +106,8 @@ class Puppet::Parser::AST::PopsBridge
def instantiate_Parameter(o)
# 3x needs parameters as an array of `[name]` or `[name, value_expr]`
- # One problem is that the parameter evaluation takes place in the wrong context in 3x (the caller's and
- # can thus reference all sorts of information. Here the value expression is wrapped in an AST Bridge to a Pops
- # expression since the Pops side can not control the evaluation
if o.value
- [o.name, NilAsUndefExpression.new(:value => o.value)]
+ [o.name, Expression.new(:value => o.value)]
else
[o.name]
end
diff --git a/lib/puppet/parser/compiler.rb b/lib/puppet/parser/compiler.rb
index 5df2916fc..125b8e9f2 100644
--- a/lib/puppet/parser/compiler.rb
+++ b/lib/puppet/parser/compiler.rb
@@ -187,9 +187,8 @@ class Puppet::Parser::Compiler
classes_without_params = @node.classes
end
- evaluate_classes(classes_without_params, @node_scope || topscope)
-
evaluate_classes(classes_with_params, @node_scope || topscope)
+ evaluate_classes(classes_without_params, @node_scope || topscope)
end
# Evaluate each specified class in turn. If there are any classes we can't
diff --git a/lib/puppet/parser/resource.rb b/lib/puppet/parser/resource.rb
index cde664a33..f1f8ccd00 100644
--- a/lib/puppet/parser/resource.rb
+++ b/lib/puppet/parser/resource.rb
@@ -162,12 +162,10 @@ class Puppet::Parser::Resource < Puppet::Resource
# if we ever receive a parameter named 'tag', set
# the resource tags with its value.
def set_parameter(param, value = nil)
- if ! value.nil?
+ if ! param.is_a?(Puppet::Parser::Resource::Param)
param = Puppet::Parser::Resource::Param.new(
:name => param, :value => value, :source => self.source
)
- elsif ! param.is_a?(Puppet::Parser::Resource::Param)
- raise ArgumentError, "Received incomplete information - no value provided for parameter #{param}"
end
tag(*param.value) if param.name == :tag
diff --git a/lib/puppet/parser/resource/param.rb b/lib/puppet/parser/resource/param.rb
index 423ae65f1..cb81043ba 100644
--- a/lib/puppet/parser/resource/param.rb
+++ b/lib/puppet/parser/resource/param.rb
@@ -11,7 +11,7 @@ class Puppet::Parser::Resource::Param
def initialize(hash)
set_options(hash)
- requiredopts(:name, :value)
+ requiredopts(:name)
@name = @name.intern
end
diff --git a/lib/puppet/parser/type_loader.rb b/lib/puppet/parser/type_loader.rb
index 1357f948d..2f6c77257 100644
--- a/lib/puppet/parser/type_loader.rb
+++ b/lib/puppet/parser/type_loader.rb
@@ -55,7 +55,7 @@ class Puppet::Parser::TypeLoader
def environment=(env)
if env.is_a?(String) or env.is_a?(Symbol)
- @environment = Puppet.lookup(:environments).get(env)
+ @environment = Puppet.lookup(:environments).get!(env)
else
@environment = env
end
diff --git a/lib/puppet/pops/evaluator/access_operator.rb b/lib/puppet/pops/evaluator/access_operator.rb
index e849a2c4e..623fb1a60 100644
--- a/lib/puppet/pops/evaluator/access_operator.rb
+++ b/lib/puppet/pops/evaluator/access_operator.rb
@@ -232,7 +232,7 @@ class Puppet::Pops::Evaluator::AccessOperator
when :default
'Default'
else
- actual.class.name
+ Puppet::Pops::Types::TypeCalculator.generalize!(Puppet::Pops::Types::TypeCalculator.infer(actual)).to_s
end
end
@@ -462,7 +462,7 @@ class Puppet::Pops::Evaluator::AccessOperator
else
# blame given left expression if it defined the type, else the first given key expression
blame = o.type_name.nil? ? @semantic.keys[0] : @semantic.left_expr
- fail(Puppet::Pops::Issues::ILLEGAL_RESOURCE_SPECIALIZATION, blame, {:actual => type_name.class})
+ fail(Puppet::Pops::Issues::ILLEGAL_RESOURCE_SPECIALIZATION, blame, {:actual => bad_key_type_name(type_name)})
end
# type name must conform
@@ -508,18 +508,10 @@ class Puppet::Pops::Evaluator::AccessOperator
keys = [:no_title] if keys.size < 1 # if there was only a type_name and it was consumed
result = keys.each_with_index.map do |t, i|
unless t.is_a?(String) || t == :no_title
- type_to_report = case t
- when nil
- 'Undef'
- when :default
- 'Default'
- else
- t.class.name
- end
index = keys_orig_size != keys.size ? i+1 : i
fail(Puppet::Pops::Issues::BAD_TYPE_SPECIALIZATION, @semantic.keys[index], {
:type => o,
- :message => "Cannot use #{type_to_report} where String is expected"
+ :message => "Cannot use #{bad_key_type_name(t)} where a resource title String is expected"
})
end
diff --git a/lib/puppet/pops/evaluator/evaluator_impl.rb b/lib/puppet/pops/evaluator/evaluator_impl.rb
index 02098d674..94e7a2a8b 100644
--- a/lib/puppet/pops/evaluator/evaluator_impl.rb
+++ b/lib/puppet/pops/evaluator/evaluator_impl.rb
@@ -706,7 +706,7 @@ class Puppet::Pops::Evaluator::EvaluatorImpl
if param_memo.include? p.name
fail(Puppet::Pops::Issues::DUPLICATE_ATTRIBUTE, o, {:attribute => p.name})
end
- param_memo[p.name] = p
+ param_memo[p.name] = p
end
param_memo
end
diff --git a/lib/puppet/pops/evaluator/runtime3_support.rb b/lib/puppet/pops/evaluator/runtime3_support.rb
index 127c7d6f5..a86228d33 100644
--- a/lib/puppet/pops/evaluator/runtime3_support.rb
+++ b/lib/puppet/pops/evaluator/runtime3_support.rb
@@ -255,8 +255,7 @@ module Puppet::Pops::Evaluator::Runtime3Support
file, line = extract_file_line(o)
Puppet::Parser::Resource::Param.new(
:name => name,
- # Here we must convert nil values to :undef for the 3x logic to work
- :value => convert(value, scope, :undef), # converted to 3x since 4x supports additional objects / types
+ :value => convert(value, scope, nil), # converted to 3x since 4x supports additional objects / types
:source => scope.source, :line => line, :file => file,
:add => operator == :'+>'
)
@@ -394,6 +393,7 @@ module Puppet::Pops::Evaluator::Runtime3Support
# Returns true, if the given name is the name of a resource parameter.
#
def is_parameter_of_resource?(scope, resource, name)
+ return false unless name.is_a?(String)
resource.valid_parameter?(name)
end
@@ -425,6 +425,7 @@ module Puppet::Pops::Evaluator::Runtime3Support
def initialize
@@convert_visitor ||= Puppet::Pops::Visitor.new(self, "convert", 2, 2)
+ @@convert2_visitor ||= Puppet::Pops::Visitor.new(self, "convert2", 2, 2)
end
# Converts 4x supported values to 3x values. This is required because
@@ -436,35 +437,53 @@ module Puppet::Pops::Evaluator::Runtime3Support
@@convert_visitor.visit_this_2(self, o, scope, undef_value)
end
+ # Converts nested 4x supported values to 3x values. This is required because
+ # resources and other objects do not know about the new type system, and does not support
+ # regular expressions. Unfortunately this has to be done for array and hash as well.
+ # A complication is that catalog types needs to be resolved against the scope.
+ #
+ def convert2(o, scope, undef_value)
+ @@convert2_visitor.visit_this_2(self, o, scope, undef_value)
+ end
+
def convert_NilClass(o, scope, undef_value)
undef_value
end
+ def convert2_NilClass(o, scope, undef_value)
+ :undef
+ end
+
def convert_String(o, scope, undef_value)
# although wasteful, needed because user code may mutate these strings in Resources
o.frozen? ? o.dup : o
end
+ alias convert2_String :convert_String
def convert_Object(o, scope, undef_value)
o
end
+ alias :convert2_Object :convert_Object
def convert_Array(o, scope, undef_value)
- o.map {|x| convert(x, scope, undef_value) }
+ o.map {|x| convert2(x, scope, undef_value) }
end
+ alias :convert2_Array :convert_Array
def convert_Hash(o, scope, undef_value)
result = {}
- o.each {|k,v| result[convert(k, scope, undef_value)] = convert(v, scope, undef_value) }
+ o.each {|k,v| result[convert2(k, scope, undef_value)] = convert2(v, scope, undef_value) }
result
end
+ alias :convert2_Hash :convert_Hash
def convert_Regexp(o, scope, undef_value)
# Puppet 3x cannot handle parameter values that are reqular expressions. Turn into regexp string in
# source form
o.inspect
end
+ alias :convert2_Regexp :convert_Regexp
def convert_Symbol(o, scope, undef_value)
case o
@@ -476,9 +495,15 @@ module Puppet::Pops::Evaluator::Runtime3Support
end
end
+ # The :undef symbol should not be converted when nested in arrays or hashes
+ def convert2_Symbol(o, scope, undef_value)
+ o
+ end
+
def convert_PAnyType(o, scope, undef_value)
o
end
+ alias :convert2_PAnyType :convert_PAnyType
def convert_PCatalogEntryType(o, scope, undef_value)
# Since 4x does not support dynamic scoping, all names are absolute and can be
@@ -489,6 +514,7 @@ module Puppet::Pops::Evaluator::Runtime3Support
Puppet::Resource.new(*catalog_type_to_split_type_title(o))
end
+ alias :convert2_PCatalogEntryType :convert_PCatalogEntryType
private
diff --git a/lib/puppet/pops/model/factory.rb b/lib/puppet/pops/model/factory.rb
index cf77d9185..a814a56b9 100644
--- a/lib/puppet/pops/model/factory.rb
+++ b/lib/puppet/pops/model/factory.rb
@@ -785,6 +785,14 @@ class Puppet::Pops::Model::Factory
STATEMENT_CALLS[name]
end
+ class ArgsToNonCallError < RuntimeError
+ attr_reader :args, :name_expr
+ def initialize(args, name_expr)
+ @args = args
+ @name_expr = name_expr
+ end
+ end
+
# Transforms an array of expressions containing literal name expressions to calls if followed by an
# expression, or expression list.
#
@@ -793,7 +801,12 @@ class Puppet::Pops::Model::Factory
expr = expr.current if expr.is_a?(Puppet::Pops::Model::Factory)
name = memo[-1]
if name.is_a?(Model::QualifiedName) && STATEMENT_CALLS[name.value]
- the_call = Puppet::Pops::Model::Factory.CALL_NAMED(name, false, expr.is_a?(Array) ? expr : [expr])
+ if expr.is_a?(Array)
+ expr = expr.reject {|e| e.is_a?(Puppet::Pops::Parser::LexerSupport::TokenValue) }
+ else
+ expr = [expr]
+ end
+ the_call = Puppet::Pops::Model::Factory.CALL_NAMED(name, false, expr)
# last positioned is last arg if there are several
record_position(the_call, name, expr.is_a?(Array) ? expr[-1] : expr)
memo[-1] = the_call
@@ -803,6 +816,8 @@ class Puppet::Pops::Model::Factory
# an argument to the name to call transform above.
expr.rval_required = true
end
+ elsif expr.is_a?(Array)
+ raise ArgsToNonCallError.new(expr, name)
else
memo << expr
if expr.is_a?(Model::CallNamedFunctionExpression)
diff --git a/lib/puppet/pops/parser/egrammar.ra b/lib/puppet/pops/parser/egrammar.ra
index 54b183a81..b9cc896ca 100644
--- a/lib/puppet/pops/parser/egrammar.ra
+++ b/lib/puppet/pops/parser/egrammar.ra
@@ -86,7 +86,7 @@ syntactic_statements
#
syntactic_statement
: assignment =LOW { result = val[0] }
- | syntactic_statement COMMA assignment =LOW { result = aryfy(val[0]).push val[2] }
+ | syntactic_statement COMMA assignment =LOW { result = aryfy(val[0]).push(val[1]).push(val[2]) }
# Assignment (is right recursive since assignment is right associative)
assignment
diff --git a/lib/puppet/pops/parser/eparser.rb b/lib/puppet/pops/parser/eparser.rb
index 26ff778fe..ef14487e8 100644
--- a/lib/puppet/pops/parser/eparser.rb
+++ b/lib/puppet/pops/parser/eparser.rb
@@ -1296,7 +1296,7 @@ module_eval(<<'.,.,', 'egrammar.ra', 87)
module_eval(<<'.,.,', 'egrammar.ra', 88)
def _reduce_9(val, _values, result)
- result = aryfy(val[0]).push val[2]
+ result = aryfy(val[0]).push(val[1]).push(val[2])
result
end
.,.,
diff --git a/lib/puppet/pops/parser/parser_support.rb b/lib/puppet/pops/parser/parser_support.rb
index cb1c83aa2..ee4f16938 100644
--- a/lib/puppet/pops/parser/parser_support.rb
+++ b/lib/puppet/pops/parser/parser_support.rb
@@ -163,7 +163,25 @@ class Puppet::Pops::Parser::Parser
# expression, or expression list
#
def transform_calls(expressions)
- Factory.transform_calls(expressions)
+ # Factory transform raises an error if a non qualified name is followed by an argument list
+ # since there is no way that that can be transformed back to sanity. This occurs in situations like this:
+ #
+ # $a = 10, notice hello
+ #
+ # where the "10, notice" forms an argument list. The parser builds an Array with the expressions and includes
+ # the comma tokens to enable the error to be reported against the first comma.
+ #
+ begin
+ Factory.transform_calls(expressions)
+ rescue Puppet::Pops::Model::Factory::ArgsToNonCallError => e
+ # e.args[1] is the first comma token in the list
+ # e.name_expr is the function name expression
+ if e.name_expr.is_a?(Puppet::Pops::Model::QualifiedName)
+ error(e.args[1], "attempt to pass argument list to the function '#{e.name_expr.value}' which cannot be called without parentheses")
+ else
+ error(e.args[1], "illegal comma separated argument list")
+ end
+ end
end
# Transforms a LEFT followed by the result of attribute_operations, this may be a call or an invalid sequence
diff --git a/lib/puppet/pops/types/type_calculator.rb b/lib/puppet/pops/types/type_calculator.rb
index 644d007cd..9db174132 100644
--- a/lib/puppet/pops/types/type_calculator.rb
+++ b/lib/puppet/pops/types/type_calculator.rb
@@ -453,12 +453,11 @@ class Puppet::Pops::Types::TypeCalculator
end
def instance_of_PNilType(t, o)
- return o.nil?
+ o.nil? || o == :undef
end
def instance_of_POptionalType(t, o)
- return true if (o.nil?)
- instance_of(t.optional_type, o)
+ instance_of_PNilType(t, o) || instance_of(t.optional_type, o)
end
def instance_of_PVariantType(t, o)
@@ -786,7 +785,6 @@ class Puppet::Pops::Types::TypeCalculator
case o
when :default
Types::PDefaultType.new()
-
else
infer_Object(o)
end
@@ -1151,15 +1149,20 @@ class Puppet::Pops::Types::TypeCalculator
# @api private
def assignable_PEnumType(t, t2)
- return true if t == t2 || (t.values.empty? && (t2.is_a?(Types::PStringType) || t2.is_a?(Types::PEnumType)))
+ return true if t == t2
+ if t.values.empty?
+ return true if t2.is_a?(Types::PStringType) || t2.is_a?(Types::PEnumType) || t2.is_a?(Types::PPatternType)
+ end
case t2
when Types::PStringType
# if the set of strings are all found in the set of enums
- t2.values.all? { |s| t.values.any? { |e| e == s }}
+ !t2.values.empty?() && t2.values.all? { |s| t.values.any? { |e| e == s }}
when Types::PVariantType
t2.types.all? {|variant_t| assignable_PEnumType(t, variant_t) }
when Types::PEnumType
- t2.values.all? { |s| t.values.any? {|e| e == s }}
+ # empty means any enum
+ return true if t.values.empty?
+ !t2.values.empty? && t2.values.all? { |s| t.values.any? {|e| e == s }}
else
false
end
@@ -1184,7 +1187,7 @@ class Puppet::Pops::Types::TypeCalculator
assignable_PIntegerType(size_t, @collection_default_size_t)
when Types::PEnumType
- if t2.values
+ if t2.values && !t2.values.empty?
# true if all enum values are within range
min, max = t2.values.map(&:size).minmax
trange = from_to_ordered(size_t.from, size_t.to)
@@ -1192,8 +1195,9 @@ class Puppet::Pops::Types::TypeCalculator
# If t2 min and max are within the range of t
trange[0] <= t2range[0] && trange[1] >= t2range[1]
else
- # no string can match this enum anyway since it does not accept anything
- false
+ # enum represents all enums, and thus all strings, a sized constrained string can thus not
+ # be assigned any enum (unless it is max size).
+ assignable_PIntegerType(size_t, @collection_default_size_t)
end
else
# no other type matches string
@@ -1217,6 +1221,8 @@ class Puppet::Pops::Types::TypeCalculator
values = t2.values
when Types::PVariantType
return t2.types.all? {|variant_t| assignable_PPatternType(t, variant_t) }
+ when Types::PPatternType
+ return t.patterns.empty? ? true : false
else
return false
end
@@ -1226,9 +1232,10 @@ class Puppet::Pops::Types::TypeCalculator
# (There should really always be a pattern, but better safe than sorry).
return t.patterns.empty? ? true : false
end
- # all strings in String/Enum type must match one of the patterns in Pattern type
+ # all strings in String/Enum type must match one of the patterns in Pattern type,
+ # or Pattern represents all Patterns == all Strings
regexps = t.patterns.map {|p| p.regexp }
- t2.values.all? { |v| regexps.any? {|re| re.match(v) } }
+ regexps.empty? || t2.values.all? { |v| regexps.any? {|re| re.match(v) } }
end
# @api private
@@ -1539,8 +1546,6 @@ class Puppet::Pops::Types::TypeCalculator
# translate to string, and skip Unit types
types = t.param_types.types.map {|t2| string(t2) unless t2.class == Types::PUnitType }.compact
- params_part= types.join(', ')
-
s = "Callable[" << types.join(', ')
unless range.empty?
(s << ', ') unless types.empty?
diff --git a/lib/puppet/provider/package/pkg.rb b/lib/puppet/provider/package/pkg.rb
index 4192dca85..db7c0a008 100644
--- a/lib/puppet/provider/package/pkg.rb
+++ b/lib/puppet/provider/package/pkg.rb
@@ -126,7 +126,18 @@ Puppet::Type.type(:package).provide :pkg, :parent => Puppet::Provider::Package d
# http://defect.opensolaris.org/bz/show_bug.cgi?id=19159%
# notes that we can't use -Ha for the same even though the manual page reads that way.
def latest
- lst = pkg(:list, "-Hn", @resource[:name]).split("\n").map{|l|self.class.parse_line(l)}
+ lines = pkg(:list, "-Hn", @resource[:name]).split("\n")
+
+ # remove certificate expiration warnings from the output, but report them
+ # Note: we'd like to use select! here to modify the lines array and avoid
+ # the second select further down. But Solaris 11 comes with ruby 1.8.7
+ # which doesn't support select!, so do this as two selects.
+ cert_warnings = lines.select { |line| line =~ /^Certificate/ }
+ if cert_warnings
+ Puppet.warning("pkg warning: #{cert_warnings}")
+ end
+
+ lst = lines.select { |line| line !~ /^Certificate/ }.map { |line| self.class.parse_line(line) }
# Now we know there is a newer version. But is that installable? (i.e are there any constraints?)
# return the first known we find. The only way that is currently available is to do a dry run of
diff --git a/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb b/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb
index 91526d7fa..d00d3da6f 100644
--- a/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb
+++ b/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb
@@ -105,7 +105,6 @@ Puppet::Type.type(:scheduled_task).provide(:win32_taskscheduler) do
@triggers << puppet_trigger
end
- @triggers = @triggers[0] if @triggers.length == 1
@triggers
end
@@ -235,7 +234,7 @@ Puppet::Type.type(:scheduled_task).provide(:win32_taskscheduler) do
return false if current_trigger.has_key?('enabled') && !current_trigger['enabled']
desired = desired_trigger.dup
-
+ desired['start_date'] ||= current_trigger['start_date'] if current_trigger.has_key?('start_date')
desired['every'] ||= current_trigger['every'] if current_trigger.has_key?('every')
desired['months'] ||= current_trigger['months'] if current_trigger.has_key?('months')
desired['on'] ||= current_trigger['on'] if current_trigger.has_key?('on')
@@ -255,13 +254,11 @@ Puppet::Type.type(:scheduled_task).provide(:win32_taskscheduler) do
def dummy_time_trigger
now = Time.now
-
{
'flags' => 0,
'random_minutes_interval' => 0,
'end_day' => 0,
"end_year" => 0,
- "trigger_type" => 0,
"minutes_interval" => 0,
"end_month" => 0,
"minutes_duration" => 0,
@@ -274,22 +271,16 @@ Puppet::Type.type(:scheduled_task).provide(:win32_taskscheduler) do
}
end
- def translate_hash_to_trigger(puppet_trigger, user_provided_input=false)
+ def translate_hash_to_trigger(puppet_trigger)
trigger = dummy_time_trigger
- if user_provided_input
- self.fail "'enabled' is read-only on scheduled_task triggers and should be removed ('enabled' is usually provided in puppet resource scheduled_task)." if puppet_trigger.has_key?('enabled')
- self.fail "'index' is read-only on scheduled_task triggers and should be removed ('index' is usually provided in puppet resource scheduled_task)." if puppet_trigger.has_key?('index')
- end
- puppet_trigger.delete('index')
-
- if puppet_trigger.delete('enabled') == false
+ if puppet_trigger['enabled'] == false
trigger['flags'] |= Win32::TaskScheduler::TASK_TRIGGER_FLAG_DISABLED
else
trigger['flags'] &= ~Win32::TaskScheduler::TASK_TRIGGER_FLAG_DISABLED
end
- extra_keys = puppet_trigger.keys.sort - ['schedule', 'start_date', 'start_time', 'every', 'months', 'on', 'which_occurrence', 'day_of_week']
+ extra_keys = puppet_trigger.keys.sort - ['index', 'enabled', 'schedule', 'start_date', 'start_time', 'every', 'months', 'on', 'which_occurrence', 'day_of_week']
self.fail "Unknown trigger option(s): #{Puppet::Parameter.format_value_for_display(extra_keys)}" unless extra_keys.empty?
self.fail "Must specify 'start_time' when defining a trigger" unless puppet_trigger['start_time']
@@ -361,9 +352,17 @@ Puppet::Type.type(:scheduled_task).provide(:win32_taskscheduler) do
def validate_trigger(value)
value = [value] unless value.is_a?(Array)
- # translate_hash_to_trigger handles the same validation that we
- # would be doing here at the individual trigger level.
- value.each {|t| translate_hash_to_trigger(t, true)}
+ value.each do |t|
+ if t.has_key?('index')
+ self.fail "'index' is read-only on scheduled_task triggers and should be removed ('index' is usually provided in puppet resource scheduled_task)."
+ end
+
+ if t.has_key?('enabled')
+ self.fail "'enabled' is read-only on scheduled_task triggers and should be removed ('enabled' is usually provided in puppet resource scheduled_task)."
+ end
+
+ translate_hash_to_trigger(t)
+ end
true
end
diff --git a/lib/puppet/provider/ssh_authorized_key/parsed.rb b/lib/puppet/provider/ssh_authorized_key/parsed.rb
index 67403c9d6..a1c9ad4c7 100644
--- a/lib/puppet/provider/ssh_authorized_key/parsed.rb
+++ b/lib/puppet/provider/ssh_authorized_key/parsed.rb
@@ -22,6 +22,8 @@ Puppet::Type.type(:ssh_authorized_key).provide(
h[:options] = Puppet::Type::Ssh_authorized_key::ProviderParsed.parse_options(h[:options]) if h[:options].is_a? String
},
:pre_gen => proc { |h|
+ # if this name was generated, don't write it back to disk
+ h[:name] = "" if h[:unnamed]
h[:options] = [] if h[:options].include?(:absent)
h[:options] = h[:options].join(',')
}
@@ -85,5 +87,19 @@ Puppet::Type.type(:ssh_authorized_key).provide(
end
result
end
+
+ def self.prefetch_hook(records)
+ name_index = 0
+ records.each do |record|
+ if record[:record_type] == :parsed && record[:name].empty?
+ record[:unnamed] = true
+ # Generate a unique ID for unnamed keys, in case they need purging.
+ # If you change this, you have to keep
+ # Puppet::Type::User#unknown_keys_in_file in sync! (PUP-3357)
+ record[:name] = "#{record[:target]}:unnamed-#{ name_index += 1 }"
+ Puppet.debug("generating name for on-disk ssh_authorized_key #{record[:key]}: #{record[:name]}")
+ end
+ end
+ end
end
diff --git a/lib/puppet/resource.rb b/lib/puppet/resource.rb
index a5419512b..82dec4bb0 100644
--- a/lib/puppet/resource.rb
+++ b/lib/puppet/resource.rb
@@ -186,9 +186,6 @@ class Puppet::Resource
@is_stage ||= @type.to_s.downcase == "stage"
end
- # Cache to reduce respond_to? lookups
- @@nondeprecating_type = {}
-
# Construct a resource from data.
#
# Constructs a resource instance with the given `type` and `title`. Multiple
@@ -242,12 +239,8 @@ class Puppet::Resource
extract_parameters(params)
end
- if resource_type and ! @@nondeprecating_type[resource_type]
- if resource_type.respond_to?(:deprecate_params)
+ if resource_type && resource_type.respond_to?(:deprecate_params)
resource_type.deprecate_params(title, attributes[:parameters])
- else
- @@nondeprecating_type[resource_type] = true
- end
end
tag(self.type)
diff --git a/lib/puppet/settings.rb b/lib/puppet/settings.rb
index 499ee1502..a0f41f1c7 100644
--- a/lib/puppet/settings.rb
+++ b/lib/puppet/settings.rb
@@ -205,6 +205,23 @@ class Puppet::Settings
end
private :unsafe_clear
+ # Clears all cached settings for a particular environment to ensure
+ # that changes to environment.conf are reflected in the settings if
+ # the environment timeout has expired.
+ #
+ # param [String, Symbol] environment the name of environment to clear settings for
+ #
+ # @api private
+ def clear_environment_settings(environment)
+
+ if environment.nil?
+ return
+ end
+
+ @cache[environment.to_sym].clear
+ @values[environment.to_sym] = {}
+ end
+
# Clear @cache, @used and the Environment.
#
# Whenever an object is returned by Settings, a copy is stored in @cache.
diff --git a/lib/puppet/type/user.rb b/lib/puppet/type/user.rb
index b9b26295f..81ad39a91 100644
--- a/lib/puppet/type/user.rb
+++ b/lib/puppet/type/user.rb
@@ -670,10 +670,20 @@ module Puppet
# representing the found keys
def unknown_keys_in_file(keyfile)
names = []
+ name_index = 0
File.new(keyfile).each do |line|
next unless line =~ Puppet::Type.type(:ssh_authorized_key).keyline_regex
# the name is stored in the 4th capture of the regex
- names << $4
+ name = $4
+ if name.empty?
+ key = $3.delete("\n")
+ # If no comment is specified for this key, generate a unique internal
+ # name. This uses the same rules as
+ # provider/ssh_authorized_key/parsed (PUP-3357)
+ name = "#{keyfile}:unnamed-#{name_index += 1}"
+ end
+ names << name
+ Puppet.debug "#{self.ref} parsed for purging Ssh_authorized_key[#{name}]"
end
names.map { |keyname|
diff --git a/lib/puppet/util/autoload.rb b/lib/puppet/util/autoload.rb
index 51ff94e1c..7173fe906 100644
--- a/lib/puppet/util/autoload.rb
+++ b/lib/puppet/util/autoload.rb
@@ -127,14 +127,18 @@ class Puppet::Util::Autoload
# now we are accomplishing that by calling the
# "app_defaults_initialized?" method on the main puppet Settings object.
# --cprice 2012-03-16
- if Puppet.settings.app_defaults_initialized? &&
+ if Puppet.settings.app_defaults_initialized?
env ||= Puppet.lookup(:environments).get(Puppet[:environment])
- # if the app defaults have been initialized then it should be safe to access the module path setting.
- $env_module_directories[env] ||= env.modulepath.collect do |dir|
- Dir.entries(dir).reject { |f| f =~ /^\./ }.collect { |f| File.join(dir, f, "lib") }
- end.flatten.find_all do |d|
- FileTest.directory?(d)
+ if env
+ # if the app defaults have been initialized then it should be safe to access the module path setting.
+ $env_module_directories[env] ||= env.modulepath.collect do |dir|
+ Dir.entries(dir).reject { |f| f =~ /^\./ }.collect { |f| File.join(dir, f, "lib") }
+ end.flatten.find_all do |d|
+ FileTest.directory?(d)
+ end
+ else
+ []
end
else
# if we get here, the app defaults have not been initialized, so we basically use an empty module path.
diff --git a/lib/puppet/util/monkey_patches.rb b/lib/puppet/util/monkey_patches.rb
index f9110986e..f1c6856f4 100644
--- a/lib/puppet/util/monkey_patches.rb
+++ b/lib/puppet/util/monkey_patches.rb
@@ -171,9 +171,9 @@ end
require 'openssl'
class OpenSSL::SSL::SSLContext
if DEFAULT_PARAMS[:options]
- DEFAULT_PARAMS[:options] |= OpenSSL::SSL::OP_NO_SSLv2
+ DEFAULT_PARAMS[:options] |= OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3
else
- DEFAULT_PARAMS[:options] = OpenSSL::SSL::OP_NO_SSLv2
+ DEFAULT_PARAMS[:options] = OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3
end
DEFAULT_PARAMS[:ciphers] << ':!SSLv2'
diff --git a/lib/puppet/version.rb b/lib/puppet/version.rb
index 08ed42f26..0fe170d5a 100644
--- a/lib/puppet/version.rb
+++ b/lib/puppet/version.rb
@@ -7,7 +7,7 @@
module Puppet
- PUPPETVERSION = '3.7.1'
+ PUPPETVERSION = '3.7.2'
##
# version is a public API method intended to always provide a fast and
diff --git a/spec/fixtures/unit/provider/package/pkg/dummy_solaris11.certificate_warning b/spec/fixtures/unit/provider/package/pkg/dummy_solaris11.certificate_warning
new file mode 100644
index 000000000..83849be03
--- /dev/null
+++ b/spec/fixtures/unit/provider/package/pkg/dummy_solaris11.certificate_warning
@@ -0,0 +1,2 @@
+Certificate '/var/pkg/ssl/871b4ed0ade09926e6adf95f86bf17535f987684' for publisher 'solarisstudio', needed to access 'https://pkg.oracle.com/solarisstudio/release/', will expire in '29' days.
+dummy 1.0.6-0.175.0.0.0.2.537 i--
diff --git a/spec/fixtures/unit/type/user/authorized_keys b/spec/fixtures/unit/type/user/authorized_keys
index dd1807e56..d58c62008 100644
--- a/spec/fixtures/unit/type/user/authorized_keys
+++ b/spec/fixtures/unit/type/user/authorized_keys
@@ -3,3 +3,4 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDTXvM7AslzjNUYrPLiNVBsF5VnqL2RmqrkzscdVdHzVxvieNwmLGeUkg8EfXPiz7j5F/Lr0J8oItTCWzyN2KmM+DhUMjvP4AbELO/VYbnVrZICRiUNYSO3EN9/uapKAuiev88d7ynbonCU0VZoTPg/ug4OondOrLCtcGri5ltF+mausGfAYiFAQVEWqXV+1tyejoawJ884etb3n4ilpsrH9JK6AtOkEWVD3TDrNi29O1mQQ/Cn88g472zAJ+DhsIn+iehtfX5nmOtDNN/1t1bGMIBzkSYEAYwUiRJbRXvbobT7qKZQPA3dh0m8AYQS5/hd4/c4pmlxL8kgr24SnBY5 key1 name
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDTXvM7AslzjNUYrPLiNVBsF5VnqL2RmqrkzscdVdHzVxvieNwmLGeUkg8EfXPiz7j5F/Lr0J8oItTCWzyN2KmM+DhUMjvP4AbELO/VYbnVrZICRiUNYSO3EN9/uapKAuiev88d7ynbonCU0VZoTPg/ug4OondOrLCtcGri5ltF+mausGfAYiFAQVEWqXV+1tyejoawJ884etb3n4ilpsrH9JK6AtOkEWVD3TDrNi29O1mQQ/Cn88g472zAJ+DhsIn+iehtfX5nmOtDNN/1t1bGMIBzkSYEAYwUiRJbRXvbobT7qKZQPA3dh0m8AYQS5/hd4/c4pmlxL8kgr24SnBY5 keyname2
#ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDTXvM7AslzjNUYrPLiNVBsF5VnqL2RmqrkzscdVdHzVxvieNwmLGeUkg8EfXPiz7j5F/Lr0J8oItTCWzyN2KmM+DhUMjvP4AbELO/VYbnVrZICRiUNYSO3EN9/uapKAuiev88d7ynbonCU0VZoTPg/ug4OondOrLCtcGri5ltF+mausGfAYiFAQVEWqXV+1tyejoawJ884etb3n4ilpsrH9JK6AtOkEWVD3TDrNi29O1mQQ/Cn88g472zAJ+DhsIn+iehtfX5nmOtDNN/1t1bGMIBzkSYEAYwUiRJbRXvbobT7qKZQPA3dh0m8AYQS5/hd4/c4pmlxL8kgr24SnBY5 keyname3
+ssh-rsa KEY-WITH-NO-NAME
diff --git a/spec/integration/application/apply_spec.rb b/spec/integration/application/apply_spec.rb
index e48808120..3ce1277d3 100755
--- a/spec/integration/application/apply_spec.rb
+++ b/spec/integration/application/apply_spec.rb
@@ -1,7 +1,5 @@
-#! /usr/bin/env ruby
require 'spec_helper'
require 'puppet_spec/files'
-require 'puppet/application/apply'
describe "apply" do
include PuppetSpec::Files
@@ -17,9 +15,8 @@ describe "apply" do
resource = Puppet::Resource.new(:file, file_to_create, :parameters => {:content => "my stuff"})
catalog.add_resource resource
- manifest = tmpfile("manifest")
+ manifest = file_containing("manifest", catalog.to_pson)
- File.open(manifest, "w") { |f| f.print catalog.to_pson }
puppet = Puppet::Application[:apply]
puppet.options[:catalog] = manifest
@@ -31,12 +28,7 @@ describe "apply" do
end
it "applies a given file even when a directory environment is specified" do
- manifest = tmpfile("manifest.pp")
- File.open(manifest, "w") do |f|
- f.puts <<-EOF
- notice('it was applied')
- EOF
- end
+ manifest = file_containing("manifest.pp", "notice('it was applied')")
special = Puppet::Node::Environment.create(:special, [])
Puppet.override(:current_environment => special) do
@@ -49,27 +41,41 @@ describe "apply" do
expect(@logs.map(&:to_s)).to include('it was applied')
end
+ it "applies a given file even when an ENC is configured", :if => !Puppet.features.microsoft_windows? do
+ manifest = file_containing("manifest.pp", "notice('specific manifest applied')")
+ site_manifest = file_containing("site_manifest.pp", "notice('the site manifest was applied instead')")
+ enc = file_containing("enc_script", "#!/bin/sh\necho 'classes: []'")
+ File.chmod(0755, enc)
+
+ special = Puppet::Node::Environment.create(:special, [])
+ Puppet.override(:current_environment => special) do
+ Puppet[:environment] = 'special'
+ Puppet[:node_terminus] = 'exec'
+ Puppet[:external_nodes] = enc
+ Puppet[:manifest] = site_manifest
+ puppet = Puppet::Application[:apply]
+ puppet.stubs(:command_line).returns(stub('command_line', :args => [manifest]))
+ expect { puppet.run_command }.to exit_with(0)
+ end
+
+ expect(@logs.map(&:to_s)).to include('specific manifest applied')
+ end
+
context "with a module" do
let(:modulepath) { tmpdir('modulepath') }
let(:execute) { 'include amod' }
let(:args) { ['-e', execute, '--modulepath', modulepath] }
before(:each) do
- Puppet::FileSystem.mkpath("#{modulepath}/amod/manifests")
- File.open("#{modulepath}/amod/manifests/init.pp", "w") do |f|
- f.puts <<-EOF
- class amod{
- notice('amod class included')
+ dir_contained_in(modulepath, {
+ "amod" => {
+ "manifests" => {
+ "init.pp" => "class amod{ notice('amod class included') }"
+ }
}
- EOF
- end
- environmentdir = Dir.mktmpdir('environments')
- Puppet[:environmentpath] = environmentdir
- create_default_directory_environment
- end
+ })
- def create_default_directory_environment
- Puppet::FileSystem.mkpath("#{Puppet[:environmentpath]}/#{Puppet[:environment]}")
+ Puppet[:environmentpath] = dir_containing("environments", { Puppet[:environment] => {} })
end
def init_cli_args_and_apply_app(args, execute)
diff --git a/spec/integration/parser/future_compiler_spec.rb b/spec/integration/parser/future_compiler_spec.rb
index d0fcfcdec..9b612e400 100644
--- a/spec/integration/parser/future_compiler_spec.rb
+++ b/spec/integration/parser/future_compiler_spec.rb
@@ -440,6 +440,16 @@ describe "Puppet::Parser::Compiler" do
expect(catalog).to have_resource("Foo[test]").with_parameter(:x, 'say friend')
end
+ it 'accepts undef as the default for an Optional argument' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ define foo(Optional[String] $x = undef) {
+ notify { "expected": message => $x == undef }
+ }
+ foo { 'test': }
+ MANIFEST
+ expect(catalog).to have_resource("Notify[expected]").with_parameter(:message, true)
+ end
+
it 'accepts anything when parameters are untyped' do
expect do
catalog = compile_to_catalog(<<-MANIFEST)
@@ -458,6 +468,15 @@ describe "Puppet::Parser::Compiler" do
end.to raise_error(/type Integer, got String/)
end
+ it 'denies undef for a non-optional type' do
+ expect do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ define foo(Integer $x) { }
+ foo { 'test': x => undef }
+ MANIFEST
+ end.to raise_error(/type Integer, got Undef/)
+ end
+
it 'denies non type compliant default argument' do
expect do
catalog = compile_to_catalog(<<-MANIFEST)
@@ -467,6 +486,15 @@ describe "Puppet::Parser::Compiler" do
end.to raise_error(/type Integer, got String/)
end
+ it 'denies undef as the default for a non-optional type' do
+ expect do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ define foo(Integer $x = undef) { }
+ foo { 'test': }
+ MANIFEST
+ end.to raise_error(/type Integer, got Undef/)
+ end
+
it 'accepts a Resource as a Type' do
catalog = compile_to_catalog(<<-MANIFEST)
define foo(Type[Bar] $x) {
@@ -489,6 +517,16 @@ describe "Puppet::Parser::Compiler" do
expect(catalog).to have_resource("Class[Foo]").with_parameter(:x, 'say friend')
end
+ it 'accepts undef as the default for an Optional argument' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ class foo(Optional[String] $x = undef) {
+ notify { "expected": message => $x == undef }
+ }
+ class { 'foo': }
+ MANIFEST
+ expect(catalog).to have_resource("Notify[expected]").with_parameter(:message, true)
+ end
+
it 'accepts anything when parameters are untyped' do
expect do
catalog = compile_to_catalog(<<-MANIFEST)
@@ -507,6 +545,15 @@ describe "Puppet::Parser::Compiler" do
end.to raise_error(/type Integer, got String/)
end
+ it 'denies undef for a non-optional type' do
+ expect do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ class foo(Integer $x) { }
+ class { 'foo': x => undef }
+ MANIFEST
+ end.to raise_error(/type Integer, got Undef/)
+ end
+
it 'denies non type compliant default argument' do
expect do
catalog = compile_to_catalog(<<-MANIFEST)
@@ -516,6 +563,15 @@ describe "Puppet::Parser::Compiler" do
end.to raise_error(/type Integer, got String/)
end
+ it 'denies undef as the default for a non-optional type' do
+ expect do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ class foo(Integer $x = undef) { }
+ class { 'foo': }
+ MANIFEST
+ end.to raise_error(/type Integer, got Undef/)
+ end
+
it 'accepts a Resource as a Type' do
catalog = compile_to_catalog(<<-MANIFEST)
class foo(Type[Bar] $x) {
diff --git a/spec/integration/type/user_spec.rb b/spec/integration/type/user_spec.rb
index 4724fe9d5..c542e51a9 100644
--- a/spec/integration/type/user_spec.rb
+++ b/spec/integration/type/user_spec.rb
@@ -8,7 +8,13 @@ describe Puppet::Type.type(:user), '(integration)', :unless => Puppet.features.m
include PuppetSpec::Compiler
context "when set to purge ssh keys from a file" do
- let(:tempfile) { file_containing('user_spec', "# comment\nssh-rsa KEY-DATA key-name\nssh-rsa KEY-DATA key name\n") }
+ let(:tempfile) do
+ file_containing('user_spec', <<-EOF)
+ # comment
+ ssh-rsa KEY-DATA key-name
+ ssh-rsa KEY-DATA key name
+ EOF
+ end
# must use an existing user, or the generated key resource
# will fail on account of an invalid user for the key
# - root should be a safe default
@@ -32,5 +38,20 @@ describe Puppet::Type.type(:user), '(integration)', :unless => Puppet.features.m
File.read(tempfile).should_not =~ /key-name/
end
end
+
+ context "with multiple unnamed keys" do
+ let(:tempfile) do
+ file_containing('user_spec', <<-EOF)
+ # comment
+ ssh-rsa KEY-DATA1
+ ssh-rsa KEY-DATA2
+ EOF
+ end
+
+ it "should purge authorized ssh keys" do
+ apply_compiled_manifest(manifest)
+ File.read(tempfile).should_not =~ /KEY-DATA/
+ end
+ end
end
end
diff --git a/spec/lib/puppet_spec/files.rb b/spec/lib/puppet_spec/files.rb
index 312c4fc95..2d0d95275 100755
--- a/spec/lib/puppet_spec/files.rb
+++ b/spec/lib/puppet_spec/files.rb
@@ -57,6 +57,7 @@ module PuppetSpec::Files
dir_contained_in(tmpdir(name), contents_hash)
end
+ def dir_contained_in(dir, contents_hash) PuppetSpec::Files.dir_contained_in(dir, contents_hash) end
def self.dir_contained_in(dir, contents_hash)
contents_hash.each do |k,v|
if v.is_a?(Hash)
diff --git a/spec/unit/environments_spec.rb b/spec/unit/environments_spec.rb
index 80a0bb2d5..fe0814814 100644
--- a/spec/unit/environments_spec.rb
+++ b/spec/unit/environments_spec.rb
@@ -97,6 +97,17 @@ describe Puppet::Environments do
end
end
+ it "raises error when environment not found" do
+ directory_tree = FS::MemoryFile.a_directory(File.expand_path("envdir"), [])
+
+ loader_from(:filesystem => [directory_tree],
+ :directory => directory_tree) do |loader|
+ expect do
+ loader.get!("does_not_exist")
+ end.to raise_error(Puppet::Environments::EnvironmentNotFound)
+ end
+ end
+
it "returns nil if an environment can't be found" do
directory_tree = FS::MemoryFile.a_directory("envdir", [])
@@ -106,6 +117,17 @@ describe Puppet::Environments do
end
end
+ it "raises error if an environment can't be found" do
+ directory_tree = FS::MemoryFile.a_directory("envdir", [])
+
+ loader_from(:filesystem => [directory_tree],
+ :directory => directory_tree) do |loader|
+ expect do
+ loader.get!("env_not_in_this_list")
+ end.to raise_error(Puppet::Environments::EnvironmentNotFound)
+ end
+ end
+
context "with an environment.conf" do
let(:envdir) do
FS::MemoryFile.a_directory(File.expand_path("envdir"), [
@@ -295,6 +317,49 @@ config_version=$vardir/random/scripts
with_config_version(File.expand_path('/some/script'))
end
end
+
+ it "should update environment settings if environment.conf has changed and timeout has expired" do
+ base_dir = File.expand_path("envdir")
+ original_envdir = FS::MemoryFile.a_directory(base_dir, [
+ FS::MemoryFile.a_directory("env3", [
+ FS::MemoryFile.a_regular_file_containing("environment.conf", <<-EOF)
+ manifest=/manifest_orig
+ modulepath=/modules_orig
+ environment_timeout=0
+ EOF
+ ]),
+ ])
+
+ FS.overlay(original_envdir) do
+ dir_loader = Puppet::Environments::Directories.new(original_envdir, [])
+ loader = Puppet::Environments::Cached.new(dir_loader)
+ Puppet.override(:environments => loader) do
+ original_env = loader.get("env3") # force the environment.conf to be read
+
+ changed_envdir = FS::MemoryFile.a_directory(base_dir, [
+ FS::MemoryFile.a_directory("env3", [
+ FS::MemoryFile.a_regular_file_containing("environment.conf", <<-EOF)
+ manifest=/manifest_changed
+ modulepath=/modules_changed
+ environment_timeout=0
+ EOF
+ ]),
+ ])
+
+ FS.overlay(changed_envdir) do
+ changed_env = loader.get("env3")
+
+ expect(original_env).to environment(:env3).
+ with_manifest(File.expand_path("/manifest_orig")).
+ with_full_modulepath([File.expand_path("/modules_orig")])
+
+ expect(changed_env).to environment(:env3).
+ with_manifest(File.expand_path("/manifest_changed")).
+ with_full_modulepath([File.expand_path("/modules_changed")])
+ end
+ end
+ end
+ end
end
end
@@ -315,6 +380,12 @@ config_version=$vardir/random/scripts
expect(loader.get(:doesnotexist)).to be_nil
end
+ it "raises error if environment is not found" do
+ expect do
+ loader.get!(:doesnotexist)
+ end.to raise_error(Puppet::Environments::EnvironmentNotFound)
+ end
+
it "gets a basic conf" do
conf = loader.get_conf(:static1)
expect(conf.modulepath).to eq('')
@@ -336,11 +407,34 @@ config_version=$vardir/random/scripts
end
end
+
+ describe "cached loaders" do
+ let(:cached1) { Puppet::Node::Environment.create(:cached1, []) }
+ let(:cached2) { Puppet::Node::Environment.create(:cached2, []) }
+ let(:static_loader) { Puppet::Environments::Static.new(cached1, cached2) }
+ let(:loader) { Puppet::Environments::Cached.new(static_loader) }
+
+ it "gets an environment" do
+ expect(loader.get(:cached2)).to eq(cached2)
+ end
+
+ it "returns nil if env not found" do
+ expect(loader.get(:doesnotexist)).to be_nil
+ end
+
+ it "raises error if environment is not found" do
+ expect do
+ loader.get!(:doesnotexist)
+ end.to raise_error(Puppet::Environments::EnvironmentNotFound)
+ end
+ end
+
RSpec::Matchers.define :environment do |name|
match do |env|
env.name == name &&
(!@manifest || @manifest == env.manifest) &&
(!@modulepath || @modulepath == env.modulepath) &&
+ (!@full_modulepath || @full_modulepath == env.full_modulepath) &&
(!@config_version || @config_version == env.config_version)
end
@@ -352,6 +446,10 @@ config_version=$vardir/random/scripts
@modulepath = modulepath
end
+ chain :with_full_modulepath do |full_modulepath|
+ @full_modulepath = full_modulepath
+ end
+
chain :with_config_version do |config_version|
@config_version = config_version
end
@@ -360,6 +458,7 @@ config_version=$vardir/random/scripts
"environment #{expected}" +
(@manifest ? " with manifest #{@manifest}" : "") +
(@modulepath ? " with modulepath [#{@modulepath.join(', ')}]" : "") +
+ (@full_modulepath ? " with full_modulepath [#{@full_modulepath.join(', ')}]" : "") +
(@config_version ? " with config_version #{@config_version}" : "")
end
diff --git a/spec/unit/network/http/webrick_spec.rb b/spec/unit/network/http/webrick_spec.rb
index edeb439a9..43662e0b4 100755
--- a/spec/unit/network/http/webrick_spec.rb
+++ b/spec/unit/network/http/webrick_spec.rb
@@ -22,6 +22,10 @@ describe Puppet::Network::HTTP::WEBrick do
s
end
+ let(:mock_ssl_context) do
+ stub('ssl_context', :ciphers= => nil)
+ end
+
let(:mock_webrick) do
stub('webrick',
:[] => {},
@@ -29,7 +33,8 @@ describe Puppet::Network::HTTP::WEBrick do
:status => :Running,
:mount => nil,
:start => nil,
- :shutdown => nil)
+ :shutdown => nil,
+ :ssl_context => mock_ssl_context)
end
before :each do
@@ -251,7 +256,15 @@ describe Puppet::Network::HTTP::WEBrick do
end
it "should reject SSLv2" do
- server.setup_ssl[:SSLOptions].should == OpenSSL::SSL::OP_NO_SSLv2
+ options = server.setup_ssl[:SSLOptions]
+
+ expect(options & OpenSSL::SSL::OP_NO_SSLv2).to eq(OpenSSL::SSL::OP_NO_SSLv2)
+ end
+
+ it "should reject SSLv3" do
+ options = server.setup_ssl[:SSLOptions]
+
+ expect(options & OpenSSL::SSL::OP_NO_SSLv3).to eq(OpenSSL::SSL::OP_NO_SSLv3)
end
it "should configure the verification method as 'OpenSSL::SSL::VERIFY_PEER'" do
@@ -267,5 +280,11 @@ describe Puppet::Network::HTTP::WEBrick do
it "should set the certificate name to 'nil'" do
server.setup_ssl[:SSLCertName].should be_nil
end
+
+ it "specifies the allowable ciphers" do
+ mock_ssl_context.expects(:ciphers=).with(server.class::CIPHERS)
+
+ server.create_server('localhost', '8888')
+ end
end
end
diff --git a/spec/unit/parser/compiler_spec.rb b/spec/unit/parser/compiler_spec.rb
index 0ca01f521..74cb326d9 100755
--- a/spec/unit/parser/compiler_spec.rb
+++ b/spec/unit/parser/compiler_spec.rb
@@ -1,6 +1,6 @@
-#! /usr/bin/env ruby
require 'spec_helper'
require 'puppet_spec/compiler'
+require 'matchers/resource'
class CompilerTestResource
attr_accessor :builtin, :virtual, :evaluated, :type, :title
@@ -53,6 +53,7 @@ end
describe Puppet::Parser::Compiler do
include PuppetSpec::Files
+ include Matchers::Resource
def resource(type, title)
Puppet::Parser::Resource.new(type, title, :scope => @scope)
@@ -864,6 +865,23 @@ describe Puppet::Parser::Compiler do
it "should fail if the class doesn't exist" do
expect { compile_to_catalog('', node) }.to raise_error(Puppet::Error, /Could not find class something/)
end
+
+ it 'evaluates classes declared with parameters before unparameterized classes' do
+ node = Puppet::Node.new('someone', :classes => { 'app::web' => {}, 'app' => { 'port' => 8080 } })
+ manifest = <<-MANIFEST
+ class app($port = 80) { }
+
+ class app::web($port = $app::port) inherits app {
+ notify { expected: message => "$port" }
+ }
+ MANIFEST
+
+ catalog = compile_to_catalog(manifest, node)
+
+ expect(catalog).to have_resource("Class[App]").with_parameter(:port, 8080)
+ expect(catalog).to have_resource("Class[App::Web]")
+ expect(catalog).to have_resource("Notify[expected]").with_parameter(:message, "8080")
+ end
end
end
end
diff --git a/spec/unit/parser/functions/lookup_spec.rb b/spec/unit/parser/functions/lookup_spec.rb
index b6d909b6f..54ea55423 100644
--- a/spec/unit/parser/functions/lookup_spec.rb
+++ b/spec/unit/parser/functions/lookup_spec.rb
@@ -8,6 +8,7 @@ describe "lookup function" do
before(:each) do
Puppet[:binder] = true
+ Puppet[:parser] = 'future'
end
it "must be called with at least a name to lookup" do
@@ -46,9 +47,9 @@ describe "lookup function" do
expect(scope.function_lookup(['a_value'])).to eq('from_hiera')
end
- it "returns :undef when the requested value is not bound and undef is accepted" do
+ it "returns nil when the requested value is not bound and undef is accepted" do
scope = scope_with_injections_from(bound(bind_single("a_value", "something")))
- expect(scope.function_lookup(['not_bound_value',{'accept_undef' => true}])).to eq(:undef)
+ expect(scope.function_lookup(['not_bound_value',{'accept_undef' => true}])).to eq(nil)
end
it "fails if the requested value is not bound and undef is not allowed" do
@@ -84,35 +85,35 @@ describe "lookup function" do
it "yields to a given lambda and returns the result" do
scope = scope_with_injections_from(bound(bind_single("a_value", "something")))
- expect(scope.function_lookup(['a_value', ast_lambda('|$x|{something_else}')])).to eq('something_else')
+ expect(scope.function_lookup(['a_value', ast_lambda(scope, '|$x|{something_else}')])).to eq('something_else')
end
it "fails if given lambda produces undef" do
scope = scope_with_injections_from(bound(bind_single("a_value", "something")))
expect do
- scope.function_lookup(['a_value', ast_lambda('|$x|{undef}')])
+ scope.function_lookup(['a_value', ast_lambda(scope, '|$x|{undef}')])
end.to raise_error(/did not find a value for the name 'a_value'/)
end
it "yields name and result to a given lambda" do
scope = scope_with_injections_from(bound(bind_single("a_value", "something")))
- expect(scope.function_lookup(['a_value', ast_lambda('|$name, $result|{[$name, $result]}')])).to eq(['a_value', 'something'])
+ expect(scope.function_lookup(['a_value', ast_lambda(scope, '|$name, $result|{[$name, $result]}')])).to eq(['a_value', 'something'])
end
it "yields name and result and default to a given lambda" do
scope = scope_with_injections_from(bound(bind_single("a_value", "something")))
expect(scope.function_lookup(['a_value', {'default' => 'cigar'},
- ast_lambda('|$name, $result, $d|{[$name, $result, $d]}')])).to eq(['a_value', 'something', 'cigar'])
+ ast_lambda(scope, '|$name, $result, $d|{[$name, $result, $d]}')])).to eq(['a_value', 'something', 'cigar'])
end
it "yields to a given lambda and returns the result when giving name and type" do
scope = scope_with_injections_from(bound(bind_single("a_value", "something")))
- expect(scope.function_lookup(['a_value', 'String', ast_lambda('|$x|{something_else}')])).to eq('something_else')
+ expect(scope.function_lookup(['a_value', 'String', ast_lambda(scope, '|$x|{something_else}')])).to eq('something_else')
end
it "yields :undef when value is not found and using a lambda" do
scope = scope_with_injections_from(bound(bind_single("a_value", "something")))
- expect(scope.function_lookup(['not_bound_value', ast_lambda('|$x|{ if $x == undef {good} else {bad}}')])).to eq('good')
+ expect(scope.function_lookup(['not_bound_value', ast_lambda(scope, '|$x|{ if $x == undef {good} else {bad}}')])).to eq('good')
end
def scope_with_injections_from(binder)
@@ -137,10 +138,10 @@ describe "lookup function" do
Puppet::Pops::Binder::Binder.new(layered_bindings)
end
- def ast_lambda(puppet_source)
+ def ast_lambda(scope, puppet_source)
puppet_source = "fake_func() " + puppet_source
- model = Puppet::Pops::Parser::EvaluatingParser.new().parse_string(puppet_source, __FILE__).current
- model = model.body.lambda
- Puppet::Pops::Model::AstTransformer.new(@file_source, nil).transform(model)
+ evaluator = Puppet::Pops::Parser::EvaluatingParser.new()
+ model = evaluator.parse_string(puppet_source, __FILE__).current
+ evaluator.closure(model.body.lambda, scope)
end
end
diff --git a/spec/unit/parser/resource/param_spec.rb b/spec/unit/parser/resource/param_spec.rb
index 7989d060d..dcb8a3616 100755
--- a/spec/unit/parser/resource/param_spec.rb
+++ b/spec/unit/parser/resource/param_spec.rb
@@ -1,19 +1,13 @@
-#! /usr/bin/env ruby
require 'spec_helper'
describe Puppet::Parser::Resource::Param do
- it "can be instantiated" do
- Puppet::Parser::Resource::Param.new(:name => 'myparam', :value => 'foo')
- end
-
- it "stores the source file" do
- param = Puppet::Parser::Resource::Param.new(:name => 'myparam', :value => 'foo', :file => 'foo.pp')
- param.file.should == 'foo.pp'
- end
+ it "has readers for all of the attributes" do
+ param = Puppet::Parser::Resource::Param.new(:name => 'myparam', :value => 'foo', :file => 'foo.pp', :line => 42)
- it "stores the line number" do
- param = Puppet::Parser::Resource::Param.new(:name => 'myparam', :value => 'foo', :line => 42)
- param.line.should == 42
+ expect(param.name).to eq(:myparam)
+ expect(param.value).to eq('foo')
+ expect(param.file).to eq('foo.pp')
+ expect(param.line).to eq(42)
end
context "parameter validation" do
@@ -23,21 +17,15 @@ describe Puppet::Parser::Resource::Param do
}.to raise_error(Puppet::Error, /name is a required option/)
end
- it "throws an error when instantiated without a value" do
- expect {
- Puppet::Parser::Resource::Param.new(:name => 'myparam')
- }.to raise_error(Puppet::Error, /value is a required option/)
- end
+ it "does not require a value" do
+ param = Puppet::Parser::Resource::Param.new(:name => 'myparam')
- it "throws an error when instantiated with a nil value" do
- expect {
- Puppet::Parser::Resource::Param.new(:name => 'myparam', :value => nil)
- }.to raise_error(Puppet::Error, /value is a required option/)
+ expect(param.value).to be_nil
end
it "includes file/line context in errors" do
expect {
- Puppet::Parser::Resource::Param.new(:name => 'myparam', :value => nil, :file => 'foo.pp', :line => 42)
+ Puppet::Parser::Resource::Param.new(:file => 'foo.pp', :line => 42)
}.to raise_error(Puppet::Error, /foo.pp:42/)
end
end
diff --git a/spec/unit/parser/resource_spec.rb b/spec/unit/parser/resource_spec.rb
index d0ec5f49c..97f19e21a 100755
--- a/spec/unit/parser/resource_spec.rb
+++ b/spec/unit/parser/resource_spec.rb
@@ -561,10 +561,6 @@ describe Puppet::Parser::Resource do
@resource["foo"].should == "bar"
end
- it "should fail when provided a parameter name but no value" do
- expect { @resource.set_parameter("myparam") }.to raise_error(ArgumentError)
- end
-
it "should allow parameters to be set to 'false'" do
@resource.set_parameter("myparam", false)
@resource["myparam"].should be_false
diff --git a/spec/unit/pops/evaluator/evaluating_parser_spec.rb b/spec/unit/pops/evaluator/evaluating_parser_spec.rb
index 5e80e4076..bc5b8bd66 100644
--- a/spec/unit/pops/evaluator/evaluating_parser_spec.rb
+++ b/spec/unit/pops/evaluator/evaluating_parser_spec.rb
@@ -680,12 +680,12 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
"'abc'[x]" => "The value 'x' cannot be converted to Numeric",
"'abc'[1.0]" => "A String[] cannot use Float where Integer is expected",
"'abc'[1,2,3]" => "String supports [] with one or two arguments. Got 3",
- "Resource[0]" => 'First argument to Resource[] must be a resource type or a String. Got Fixnum',
- "Resource[a, 0]" => 'Error creating type specialization of a Resource-Type, Cannot use Fixnum where String is expected',
- "File[0]" => 'Error creating type specialization of a File-Type, Cannot use Fixnum where String is expected',
+ "Resource[0]" => 'First argument to Resource[] must be a resource type or a String. Got Integer',
+ "Resource[a, 0]" => 'Error creating type specialization of a Resource-Type, Cannot use Integer where a resource title String is expected',
+ "File[0]" => 'Error creating type specialization of a File-Type, Cannot use Integer where a resource title String is expected',
"String[a]" => "A Type's size constraint arguments must be a single Integer type, or 1-2 integers (or default). Got a String",
- "Pattern[0]" => 'Error creating type specialization of a Pattern-Type, Cannot use Fixnum where String or Regexp or Pattern-Type or Regexp-Type is expected',
- "Regexp[0]" => 'Error creating type specialization of a Regexp-Type, Cannot use Fixnum where String or Regexp is expected',
+ "Pattern[0]" => 'Error creating type specialization of a Pattern-Type, Cannot use Integer where String or Regexp or Pattern-Type or Regexp-Type is expected',
+ "Regexp[0]" => 'Error creating type specialization of a Regexp-Type, Cannot use Integer where String or Regexp is expected',
"Regexp[a,b]" => 'A Regexp-Type[] accepts 1 argument. Got 2',
"true[0]" => "Operator '[]' is not applicable to a Boolean",
"1[0]" => "Operator '[]' is not applicable to an Integer",
@@ -963,6 +963,31 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
expect{parser.evaluate_string(scope, "assert_no_undef({undef => 1})")}.to_not raise_error()
expect{parser.evaluate_string(scope, "assert_no_undef({1 => undef})")}.to_not raise_error()
end
+
+ context 'using the 3x function api' do
+ it 'can call a 3x function' do
+ Puppet::Parser::Functions.newfunction("bazinga", :type => :rvalue) { |args| args[0] }
+ parser.evaluate_string(scope, "bazinga(42)", __FILE__).should == 42
+ end
+
+ it 'maps :undef to empty string' do
+ Puppet::Parser::Functions.newfunction("bazinga", :type => :rvalue) { |args| args[0] }
+ parser.evaluate_string(scope, "$a = {} bazinga($a[nope])", __FILE__).should == ''
+ parser.evaluate_string(scope, "bazinga(undef)", __FILE__).should == ''
+ end
+
+ it 'does not map :undef to empty string in arrays' do
+ Puppet::Parser::Functions.newfunction("bazinga", :type => :rvalue) { |args| args[0][0] }
+ parser.evaluate_string(scope, "$a = {} $b = [$a[nope]] bazinga($b)", __FILE__).should == :undef
+ parser.evaluate_string(scope, "bazinga([undef])", __FILE__).should == :undef
+ end
+
+ it 'does not map :undef to empty string in hashes' do
+ Puppet::Parser::Functions.newfunction("bazinga", :type => :rvalue) { |args| args[0]['a'] }
+ parser.evaluate_string(scope, "$a = {} $b = {a => $a[nope]} bazinga($b)", __FILE__).should == :undef
+ parser.evaluate_string(scope, "bazinga({a => undef})", __FILE__).should == :undef
+ end
+ end
end
context "When evaluator performs string interpolation" do
diff --git a/spec/unit/pops/parser/parse_calls_spec.rb b/spec/unit/pops/parser/parse_calls_spec.rb
index ee80544f5..6f75eabc8 100644
--- a/spec/unit/pops/parser/parse_calls_spec.rb
+++ b/spec/unit/pops/parser/parse_calls_spec.rb
@@ -59,11 +59,6 @@ describe "egrammar parsing function calls" do
dump(parse("$a = foo()")).should == "(= $a (call foo))"
end
- # # For regular grammar where a bare word can not be a "statement"
- # it "$a = foo bar # illegal, must have parentheses" do
- # expect { dump(parse("$a = foo bar"))}.to raise_error(Puppet::ParseError)
- # end
-
# For egrammar where a bare word can be a "statement"
it "$a = foo bar # illegal, must have parentheses" do
dump(parse("$a = foo bar")).should == "(block\n (= $a foo)\n bar\n)"
@@ -101,4 +96,24 @@ describe "egrammar parsing function calls" do
].join("\n")
end
end
+
+ context "When parsing an illegal argument list" do
+ it "raises an error if argument list is not for a call" do
+ expect do
+ parse("$a = 10, 3")
+ end.to raise_error(/illegal comma/)
+ end
+
+ it "raises an error if argument list is for a potential call not allowed without parentheses" do
+ expect do
+ parse("foo 10, 3")
+ end.to raise_error(/attempt to pass argument list to the function 'foo' which cannot be called without parentheses/)
+ end
+
+ it "does no raise an error for an argument list to an allowed call" do
+ expect do
+ parse("notice 10, 3")
+ end.to_not raise_error()
+ end
+ end
end
diff --git a/spec/unit/pops/types/type_calculator_spec.rb b/spec/unit/pops/types/type_calculator_spec.rb
index 0bd475263..bb0c890a8 100644
--- a/spec/unit/pops/types/type_calculator_spec.rb
+++ b/spec/unit/pops/types/type_calculator_spec.rb
@@ -10,6 +10,9 @@ describe 'The type calculator' do
t.to = to
t
end
+ def constrained_t(t, from, to)
+ Puppet::Pops::Types::TypeFactory.constrain_size(t, from, to)
+ end
def pattern_t(*patterns)
Puppet::Pops::Types::TypeFactory.pattern(*patterns)
@@ -827,6 +830,21 @@ describe 'The type calculator' do
calculator.assignable?(pattern, variant_t(string_t('a'), string_t('b'))).should == true
end
+ it 'pattern representing all patterns should accept any pattern' do
+ calculator.assignable?(pattern_t(), pattern_t('a')).should == true
+ calculator.assignable?(pattern_t(), pattern_t()).should == true
+ end
+
+ it 'pattern representing all patterns should accept any enum' do
+ calculator.assignable?(pattern_t(), enum_t('a')).should == true
+ calculator.assignable?(pattern_t(), enum_t()).should == true
+ end
+
+ it 'pattern representing all patterns should accept any string' do
+ calculator.assignable?(pattern_t(), string_t('a')).should == true
+ calculator.assignable?(pattern_t(), string_t()).should == true
+ end
+
end
context 'when dealing with enums' do
@@ -842,12 +860,51 @@ describe 'The type calculator' do
calculator.assignable?(enum_t('a', 'b'), enum_t('c')).should == false
end
+ it 'non parameterized enum accepts any other enum but not the reverse' do
+ calculator.assignable?(enum_t(), enum_t('a')).should == true
+ calculator.assignable?(enum_t('a'), enum_t()).should == false
+ end
+
it 'enum should accept a variant where all variants are acceptable' do
enum = enum_t('a', 'b')
calculator.assignable?(enum, variant_t(string_t('a'), string_t('b'))).should == true
end
end
+ context 'when dealing with string and enum combinations' do
+ it 'should accept assigning any enum to unrestricted string' do
+ calculator.assignable?(string_t(), enum_t('blue')).should == true
+ calculator.assignable?(string_t(), enum_t('blue', 'red')).should == true
+ end
+
+ it 'should not accept assigning longer enum value to size restricted string' do
+ calculator.assignable?(constrained_t(string_t(),2,2), enum_t('a','blue')).should == false
+ end
+
+ it 'should accept assigning any string to empty enum' do
+ calculator.assignable?(enum_t(), string_t()).should == true
+ end
+
+ it 'should accept assigning empty enum to any string' do
+ calculator.assignable?(string_t(), enum_t()).should == true
+ end
+
+ it 'should not accept assigning empty enum to size constrained string' do
+ calculator.assignable?(constrained_t(string_t(),2,2), enum_t()).should == false
+ end
+ end
+
+ context 'when dealing with string/pattern/enum combinations' do
+ it 'any string is equal to any enum is equal to any pattern' do
+ calculator.assignable?(string_t(), enum_t()).should == true
+ calculator.assignable?(string_t(), pattern_t()).should == true
+ calculator.assignable?(enum_t(), string_t()).should == true
+ calculator.assignable?(enum_t(), pattern_t()).should == true
+ calculator.assignable?(pattern_t(), string_t()).should == true
+ calculator.assignable?(pattern_t(), enum_t()).should == true
+ end
+ end
+
context 'when dealing with tuples' do
it 'matches empty tuples' do
tuple1 = tuple_t()
@@ -1057,6 +1114,10 @@ describe 'The type calculator' do
calculator.instance?(Puppet::Pops::Types::PRuntimeType.new(:runtime => :ruby, :runtime_type_name => 'Symbol'), :undef).should == true
end
+ it "should consider :undef to be instance of an Optional type" do
+ calculator.instance?(Puppet::Pops::Types::POptionalType.new(), :undef).should == true
+ end
+
it 'should not consider undef to be an instance of any other type than Any, NilType and Data' do
types_to_test = all_types - [
Puppet::Pops::Types::PAnyType,
diff --git a/spec/unit/provider/package/pkg_spec.rb b/spec/unit/provider/package/pkg_spec.rb
index 8ddbbbfe0..9442b7f21 100755
--- a/spec/unit/provider/package/pkg_spec.rb
+++ b/spec/unit/provider/package/pkg_spec.rb
@@ -70,6 +70,10 @@ describe Puppet::Type.type(:package).provider(:pkg) do
described_class.expects(:pkg).with(:list,'-Hn','dummy').returns File.read(my_fixture('dummy_solaris11.installed'))
provider.latest.should == "1.0.6-0.175.0.0.0.2.537"
end
+ it "should work correctly for ensure latest on solaris 11 in the presence of a certificate expiration warning" do
+ described_class.expects(:pkg).with(:list,'-Hn','dummy').returns File.read(my_fixture('dummy_solaris11.certificate_warning'))
+ provider.latest.should == "1.0.6-0.175.0.0.0.2.537"
+ end
it "should work correctly for ensure latest on solaris 11(known UFOXI)" do
Puppet::Util::Execution.expects(:execute).with(['/bin/pkg', 'update', '-n', 'dummy'], {:failonfail => false, :combine => true}).returns ''
$CHILD_STATUS.stubs(:exitstatus).returns 0
diff --git a/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb b/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb
index 3d37956c5..270ca6bae 100644
--- a/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb
+++ b/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb
@@ -142,14 +142,14 @@ describe Puppet::Type.type(:scheduled_task).provider(:win32_taskscheduler), :if
'type' => { 'days_interval' => 2 },
})
- resource.provider.trigger.should == {
+ resource.provider.trigger.should == [{
'start_date' => '2011-9-12',
'start_time' => '13:20',
'schedule' => 'daily',
'every' => '2',
'enabled' => true,
'index' => 0,
- }
+ }]
end
it 'should handle a single weekly trigger' do
@@ -171,7 +171,7 @@ describe Puppet::Type.type(:scheduled_task).provider(:win32_taskscheduler), :if
}
})
- resource.provider.trigger.should == {
+ resource.provider.trigger.should == [{
'start_date' => '2011-9-12',
'start_time' => '13:20',
'schedule' => 'weekly',
@@ -179,7 +179,7 @@ describe Puppet::Type.type(:scheduled_task).provider(:win32_taskscheduler), :if
'on' => ['sun', 'mon', 'wed', 'fri'],
'enabled' => true,
'index' => 0,
- }
+ }]
end
it 'should handle a single monthly date-based trigger' do
@@ -204,7 +204,7 @@ describe Puppet::Type.type(:scheduled_task).provider(:win32_taskscheduler), :if
}
})
- resource.provider.trigger.should == {
+ resource.provider.trigger.should == [{
'start_date' => '2011-9-12',
'start_time' => '13:20',
'schedule' => 'monthly',
@@ -212,7 +212,7 @@ describe Puppet::Type.type(:scheduled_task).provider(:win32_taskscheduler), :if
'on' => [1, 3, 5, 15, 'last'],
'enabled' => true,
'index' => 0,
- }
+ }]
end
it 'should handle a single monthly day-of-week-based trigger' do
@@ -240,7 +240,7 @@ describe Puppet::Type.type(:scheduled_task).provider(:win32_taskscheduler), :if
}
})
- resource.provider.trigger.should == {
+ resource.provider.trigger.should == [{
'start_date' => '2011-9-12',
'start_time' => '13:20',
'schedule' => 'monthly',
@@ -249,7 +249,7 @@ describe Puppet::Type.type(:scheduled_task).provider(:win32_taskscheduler), :if
'day_of_week' => ['sun', 'mon', 'wed', 'fri'],
'enabled' => true,
'index' => 0,
- }
+ }]
end
it 'should handle a single one-time trigger' do
@@ -263,13 +263,13 @@ describe Puppet::Type.type(:scheduled_task).provider(:win32_taskscheduler), :if
'flags' => 0,
})
- resource.provider.trigger.should == {
+ resource.provider.trigger.should == [{
'start_date' => '2011-9-12',
'start_time' => '13:20',
'schedule' => 'once',
'enabled' => true,
'index' => 0,
- }
+ }]
end
end
@@ -536,18 +536,18 @@ describe Puppet::Type.type(:scheduled_task).provider(:win32_taskscheduler), :if
'index' => 0,
}
- resource.provider.trigger.should == mock_task_trigger
- resource.provider.trigger.should == mock_task_trigger
+ resource.provider.trigger.should == [mock_task_trigger]
+ resource.provider.trigger.should == [mock_task_trigger]
resource.provider.clear_task
- resource.provider.trigger.should == {
+ resource.provider.trigger.should == [{
'start_date' => '2012-11-14',
'start_time' => '15:22',
'schedule' => 'once',
'enabled' => true,
'index' => 0,
- }
+ }]
end
end
@@ -635,6 +635,30 @@ describe Puppet::Type.type(:scheduled_task).provider(:win32_taskscheduler), :if
describe '#triggers_same?' do
let(:provider) { described_class.new(:name => 'foobar', :command => 'C:\Windows\System32\notepad.exe') }
+ it "should not mutate triggers" do
+ current = {'schedule' => 'daily', 'start_date' => '2011-09-12', 'start_time' => '15:30', 'every' => 3}
+ current.freeze
+
+ desired = {'schedule' => 'daily', 'start_date' => '2011-09-12', 'start_time' => '15:30'}
+ desired.freeze
+
+ expect(provider).to be_triggers_same(current, desired)
+ end
+
+ it "ignores 'index' in current trigger" do
+ current = {'index' => 0, 'schedule' => 'daily', 'start_date' => '2011-09-12', 'start_time' => '15:30', 'every' => 3}
+ desired = {'schedule' => 'daily', 'start_date' => '2011-09-12', 'start_time' => '15:30', 'every' => 3}
+
+ expect(provider).to be_triggers_same(current, desired)
+ end
+
+ it "ignores 'enabled' in current triggger" do
+ current = {'enabled' => true, 'schedule' => 'daily', 'start_date' => '2011-09-12', 'start_time' => '15:30', 'every' => 3}
+ desired = {'schedule' => 'daily', 'start_date' => '2011-09-12', 'start_time' => '15:30', 'every' => 3}
+
+ expect(provider).to be_triggers_same(current, desired)
+ end
+
it "should not consider a disabled 'current' trigger to be the same" do
current = {'schedule' => 'once', 'enabled' => false}
desired = {'schedule' => 'once'}
@@ -649,6 +673,15 @@ describe Puppet::Type.type(:scheduled_task).provider(:win32_taskscheduler), :if
provider.should_not be_triggers_same(current, desired)
end
+ describe 'start_date' do
+ it "considers triggers to be equal when start_date is not specified in the 'desired' trigger" do
+ current = {'schedule' => 'daily', 'start_date' => '2011-09-12', 'start_time' => '15:30', 'every' => 3}
+ desired = {'schedule' => 'daily', 'start_time' => '15:30', 'every' => 3}
+
+ provider.should be_triggers_same(current, desired)
+ end
+ end
+
describe 'comparing daily triggers' do
it "should consider 'desired' triggers not specifying 'every' to have the same value as the 'current' trigger" do
current = {'schedule' => 'daily', 'start_date' => '2011-09-12', 'start_time' => '15:30', 'every' => 3}
diff --git a/spec/unit/provider/ssh_authorized_key/parsed_spec.rb b/spec/unit/provider/ssh_authorized_key/parsed_spec.rb
index 2e88c57df..78abec901 100755
--- a/spec/unit/provider/ssh_authorized_key/parsed_spec.rb
+++ b/spec/unit/provider/ssh_authorized_key/parsed_spec.rb
@@ -136,6 +136,21 @@ describe provider_class, :unless => Puppet.features.microsoft_windows? do
end
end
+ describe "prefetch_hook" do
+ let(:path) { '/path/to/keyfile' }
+ let(:input) do
+ { :type => 'rsa',
+ :key => 'KEYDATA',
+ :name => '',
+ :record_type => :parsed,
+ :target => path,
+ }
+ end
+ it "adds an indexed name to unnamed resources" do
+ @provider_class.prefetch_hook([input])[0][:name].should =~ /^#{path}:unnamed-\d+/
+ end
+ end
+
end
describe provider_class, :unless => Puppet.features.microsoft_windows? do
diff --git a/spec/unit/type/user_spec.rb b/spec/unit/type/user_spec.rb
index f5a351752..974054309 100755
--- a/spec/unit/type/user_spec.rb
+++ b/spec/unit/type/user_spec.rb
@@ -501,6 +501,11 @@ describe Puppet::Type.type(:user) do
names = resources.collect { |res| res.name }
names.should_not include("keyname3")
end
+ it "should generate names for unnamed keys" do
+ names = resources.collect { |res| res.name }
+ fixture_path = File.join(my_fixture_dir, 'authorized_keys')
+ names.should include("#{fixture_path}:unnamed-1")
+ end
it "should each have a value for the user property" do
resources.map { |res|
res[:user]
diff --git a/spec/unit/util/autoload_spec.rb b/spec/unit/util/autoload_spec.rb
index 3028c9e82..d24006360 100755
--- a/spec/unit/util/autoload_spec.rb
+++ b/spec/unit/util/autoload_spec.rb
@@ -5,10 +5,10 @@ require 'puppet/util/autoload'
describe Puppet::Util::Autoload do
include PuppetSpec::Files
+
before do
@autoload = Puppet::Util::Autoload.new("foo", "tmp")
- @autoload.stubs(:eachdir).yields make_absolute("/my/dir")
@loaded = {}
@autoload.class.stubs(:loaded).returns(@loaded)
end
@@ -17,25 +17,44 @@ describe Puppet::Util::Autoload do
before :each do
## modulepath/libdir can't be used until after app settings are initialized, so we need to simulate that:
Puppet.settings.expects(:app_defaults_initialized?).returns(true).at_least_once
-
- @dira = File.expand_path('/a')
- @dirb = File.expand_path('/b')
- @dirc = File.expand_path('/c')
end
it "should collect all of the lib directories that exist in the current environment's module path" do
- environment = Puppet::Node::Environment.create(:foo, [@dira, @dirb, @dirc])
- Dir.expects(:entries).with(@dira).returns %w{. .. one two}
- Dir.expects(:entries).with(@dirb).returns %w{. .. one two}
+ dira = dir_containing('dir_a', {
+ "one" => {},
+ "two" => { "lib" => {} }
+ })
- Puppet::FileSystem.expects(:directory?).with(@dira).returns true
- Puppet::FileSystem.expects(:directory?).with(@dirb).returns true
- Puppet::FileSystem.expects(:directory?).with(@dirc).returns false
+ dirb = dir_containing('dir_a', {
+ "one" => {},
+ "two" => { "lib" => {} }
+ })
- FileTest.expects(:directory?).with(regexp_matches(%r{two/lib})).times(2).returns true
- FileTest.expects(:directory?).with(regexp_matches(%r{one/lib})).times(2).returns false
+ environment = Puppet::Node::Environment.create(:foo, [dira, dirb])
+
+ @autoload.class.module_directories(environment).should == ["#{dira}/two/lib", "#{dirb}/two/lib"]
+ end
+
+ it "ignores missing module directories" do
+ environment = Puppet::Node::Environment.create(:foo, [File.expand_path('does/not/exist')])
+
+ @autoload.class.module_directories(environment).should be_empty
+ end
- @autoload.class.module_directories(environment).should == ["#{@dira}/two/lib", "#{@dirb}/two/lib"]
+ it "ignores the configured environment when it doesn't exist" do
+ Puppet[:environment] = 'nonexistent'
+
+ Puppet.override({ :environments => Puppet::Environments::Static.new() }) do
+ @autoload.class.module_directories(nil).should be_empty
+ end
+ end
+
+ it "uses the configured environment when no environment is given" do
+ Puppet[:environment] = 'nonexistent'
+
+ Puppet.override({ :environments => Puppet::Environments::Static.new() }) do
+ @autoload.class.module_directories(nil).should be_empty
+ end
end
it "should include the module directories, the Puppet libdir, and all of the Ruby load directories" do
diff --git a/spec/unit/util/monkey_patches_spec.rb b/spec/unit/util/monkey_patches_spec.rb
index 13e10454c..7c8abb137 100755
--- a/spec/unit/util/monkey_patches_spec.rb
+++ b/spec/unit/util/monkey_patches_spec.rb
@@ -264,14 +264,26 @@ describe OpenSSL::SSL::SSLContext do
it 'disables SSLv2 via the SSLContext#options bitmask' do
(subject.options & OpenSSL::SSL::OP_NO_SSLv2).should == OpenSSL::SSL::OP_NO_SSLv2
end
+
+ it 'disables SSLv3 via the SSLContext#options bitmask' do
+ (subject.options & OpenSSL::SSL::OP_NO_SSLv3).should == OpenSSL::SSL::OP_NO_SSLv3
+ end
+
it 'explicitly disable SSLv2 ciphers using the ! prefix so they cannot be re-added' do
cipher_str = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ciphers]
cipher_str.split(':').should include('!SSLv2')
end
+
+ it 'does not exclude SSLv3 ciphers shared with TLSv1' do
+ cipher_str = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ciphers]
+ cipher_str.split(':').should_not include('!SSLv3')
+ end
+
it 'sets parameters on initialization' do
described_class.any_instance.expects(:set_params)
subject
end
+
it 'has no ciphers with version SSLv2 enabled' do
ciphers = subject.ciphers.select do |name, version, bits, alg_bits|
/SSLv2/.match(version)
diff --git a/tasks/memwalk.rake b/tasks/memwalk.rake
new file mode 100644
index 000000000..49077d6c8
--- /dev/null
+++ b/tasks/memwalk.rake
@@ -0,0 +1,195 @@
+# Walks the memory dumped into heap.json, and produces a graph of the memory dumped in diff.json
+# If a single argument (a hex address to one object) is given, the graph is limited to this object and what references it
+# The heap dumps should be in the format produced by Ruby ObjectSpace in Ruby version 2.1.0 or later.
+#
+# The command produces a .dot file that can be rendered with graphwiz dot into SVG. If a memwalk is performed for all
+# objects in the diff.json, the output file name is memwalk.dot. If it is produced for a single address, the name of the
+# output file is memwalk-<address>.dot
+#
+# The dot file can be rendered with something like: dot -Tsvg -omemwalk.svg memwalk.dot
+#
+desc "Process a diff.json of object ids, and a heap.json of a Ruby 2.1.0 ObjectSpace dump and produce a graph"
+task :memwalk, [:id] do |t, args|
+ puts "Memwalk"
+ puts "Computing for #{args[:id] ? args[:id] : 'all'}"
+ @single_id = args[:id] ? args[:id].to_i(16) : nil
+
+ require 'json'
+ #require 'debug'
+
+ TYPE = "type".freeze
+ ROOT = "root".freeze
+ ROOT_UC = "ROOT".freeze
+ ADDR = "address".freeze
+ NODE = "NODE".freeze
+ STRING = "STRING".freeze
+ DATA = "DATA".freeze
+ HASH = "HASH".freeze
+ ARRAY = "ARRAY".freeze
+ OBJECT = "OBJECT".freeze
+ CLASS = "CLASS".freeze
+
+ allocations = {}
+ # An array of integer addresses of the objects to trace bindings for
+ diff_index = {}
+ puts "Reading data"
+ begin
+ puts "Reading diff"
+ lines = 0;
+ File.readlines("diff.json").each do | line |
+ lines += 1
+ diff = JSON.parse(line)
+ case diff[ TYPE ]
+ when STRING, DATA, HASH, ARRAY
+ # skip the strings
+ else
+ diff_index[ diff[ ADDR ].to_i(16) ] = diff
+ end
+ end
+ puts "Read #{lines} number of diffs"
+ rescue => e
+ raise "ERROR READING DIFF at line #{lines} #{e.message[0, 200]}"
+ end
+
+ begin
+ puts "Reading heap"
+ lines = 0
+ allocation = nil
+ File.readlines("heap.json").each do | line |
+ lines += 1
+ allocation = JSON.parse(line)
+ case allocation[ TYPE ]
+ when ROOT_UC
+ # Graph for single id must include roots, as it may be a root that holds on to the reference
+ # a global variable, thread, etc.
+ #
+ if @single_id
+ allocations[ allocation[ ROOT ] ] = allocation
+ end
+ when NODE
+ # skip the NODE objects - they represent the loaded ruby code
+ when STRING
+ # skip all strings - they are everywhere
+ else
+ allocations[ allocation[ ADDR ].to_i(16) ] = allocation
+ end
+ end
+ puts "Read #{lines} number of entries"
+ rescue => e
+ require 'debug'
+ puts "ERROR READING HEAP #{e.message[0, 200]}"
+ raise e
+ end
+ @heap = allocations
+
+ puts "Building reference index"
+ # References is an index from a referenced object to an array with addresses to the objects that references it
+ @references = Hash.new { |h, k| h[k] = [] }
+ REFERENCES = "references".freeze
+ allocations.each do |k,v|
+ refs = v[ REFERENCES ]
+ if refs.is_a?(Array)
+ refs.each {|addr| @references[ addr.to_i(16) ] << k }
+ end
+ end
+
+ @printed = Set.new()
+
+ def print_object(addr, entry)
+ # only print each node once
+ return unless @printed.add?(addr)
+ begin
+ if addr.is_a?(String)
+ @output.write( "x#{node_name(addr)} [label=\"#{node_label(addr, entry)}\\n#{addr}\"];\n")
+ else
+ @output.write( "x#{node_name(addr)} [label=\"#{node_label(addr, entry)}\\n#{addr.to_s(16)}\"];\n")
+ end
+ rescue => e
+ require 'debug'
+ raise e
+ end
+ end
+
+ def node_label(addr, entry)
+ if entry[ TYPE ] == OBJECT
+ class_ref = entry[ "class" ].to_i(16)
+ @heap[ class_ref ][ "name" ]
+ elsif entry[ TYPE ] == CLASS
+ "CLASS #{entry[ "name"]}"
+ else
+ entry[TYPE]
+ end
+ end
+
+ def node_name(addr)
+ return addr if addr.is_a? String
+ addr.to_s(16)
+ end
+
+ def print_edge(from_addr, to_addr)
+ @output.write("x#{node_name(from_addr)}->x#{node_name(to_addr)};\n")
+ end
+
+ def closure_and_edges(diff)
+ edges = Set.new()
+ walked = Set.new()
+ puts "Number of diffs referenced = #{diff.count {|k,_| @references[k].is_a?(Array) && @references[k].size() > 0 }}"
+ diff.each {|k,_| walk(k, edges, walked) }
+ edges.each {|e| print_edge(*e) }
+ end
+
+ def walk(addr, edges, walked)
+ if !@heap[ addr ].nil?
+ print_object(addr, @heap[addr])
+
+ @references [ addr ].each do |r|
+ walk_to_object(addr, r, edges, walked)
+ end
+ end
+ end
+
+ def walk_to_object(to_addr, cursor, edges, walked)
+ return unless walked
+ # if walked to an object, or everything if a single_id is the target
+ if @heap[ cursor ][ TYPE ] == OBJECT || (@single_id && @heap[ cursor ][ TYPE ] == ROOT_UC || @heap[ cursor ][ TYPE ] == CLASS )
+ # and the edge is unique
+ if edges.add?( [ cursor, to_addr ] )
+ # then we may not have visited objects this objects is being referred from
+ print_object(cursor, @heap[ cursor ])
+ # Do not follow what binds a class
+ if @heap[ cursor ][ TYPE ] != CLASS
+ @references[ cursor ].each do |r|
+ walk_to_object(cursor, r, edges, walked.add?(r))
+ walked.delete(r)
+ end
+ end
+ end
+ else
+ # continue search until Object
+ @references[cursor].each do |r|
+ walk_to_object(to_addr, r, edges, walked.add?(r))
+ end
+ end
+ end
+
+ def single_closure_and_edges(the_target)
+ edges = Set.new()
+ walked = Set.new()
+ walk(the_target, edges, walked)
+ edges.each {|e| print_edge(*e) }
+ end
+
+ puts "creating graph"
+ if @single_id
+ @output = File.open("memwalk-#{@single_id.to_s(16)}.dot", "w")
+ @output.write("digraph root {\n")
+ single_closure_and_edges(@single_id)
+ else
+ @output = File.open("memwalk.dot", "w")
+ @output.write("digraph root {\n")
+ closure_and_edges(diff_index)
+ end
+ @output.write("}\n")
+ @output.close
+ puts "done"
+end