puppet 4.10.0 → 4.10.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (34) hide show
  1. data/Gemfile +11 -35
  2. data/lib/puppet.rb +2 -2
  3. data/lib/puppet/defaults.rb +44 -12
  4. data/lib/puppet/indirector/catalog/compiler.rb +4 -2
  5. data/lib/puppet/module_tool/tar.rb +3 -3
  6. data/lib/puppet/parser/functions/new.rb +14 -1
  7. data/lib/puppet/pops/lookup.rb +3 -3
  8. data/lib/puppet/pops/lookup/global_data_provider.rb +6 -9
  9. data/lib/puppet/pops/lookup/interpolation.rb +6 -7
  10. data/lib/puppet/pops/lookup/invocation.rb +12 -2
  11. data/lib/puppet/pops/lookup/lookup_adapter.rb +11 -7
  12. data/lib/puppet/pops/serialization/object.rb +1 -1
  13. data/lib/puppet/pops/serialization/serializer.rb +9 -2
  14. data/lib/puppet/pops/types/string_converter.rb +24 -21
  15. data/lib/puppet/pops/types/types.rb +16 -0
  16. data/lib/puppet/resource.rb +58 -20
  17. data/lib/puppet/resource/catalog.rb +3 -10
  18. data/lib/puppet/version.rb +1 -1
  19. data/locales/puppet.pot +58 -3
  20. data/spec/integration/application/apply_spec.rb +1 -0
  21. data/spec/shared_contexts/types_setup.rb +28 -10
  22. data/spec/unit/functions/lookup_spec.rb +71 -0
  23. data/spec/unit/indirector/catalog/compiler_spec.rb +32 -4
  24. data/spec/unit/module_tool/tar_spec.rb +16 -10
  25. data/spec/unit/pops/lookup/interpolation_spec.rb +2 -2
  26. data/spec/unit/pops/serialization/serialization_spec.rb +30 -4
  27. data/spec/unit/pops/types/p_sem_ver_type_spec.rb +12 -17
  28. data/spec/unit/pops/types/p_type_set_type_spec.rb +2 -2
  29. data/spec/unit/pops/types/string_converter_spec.rb +21 -9
  30. data/spec/unit/pops/types/type_calculator_spec.rb +2 -2
  31. data/spec/unit/pops/types/types_spec.rb +11 -0
  32. data/spec/unit/resource/catalog_spec.rb +14 -15
  33. metadata +25 -13
  34. checksums.yaml +0 -7
@@ -1555,6 +1555,22 @@ class PRegexpType < PScalarType
1555
1555
  KEY_VALUE => nil
1556
1556
  })
1557
1557
  end
1558
+
1559
+
1560
+ # Returns a new function that produces a Regexp instance
1561
+ #
1562
+ def self.new_function(_, loader)
1563
+ @new_function ||= Puppet::Functions.create_loaded_function(:new_float, loader) do
1564
+ dispatch :from_string do
1565
+ param 'String', :pattern
1566
+ end
1567
+
1568
+ def from_string(pattern)
1569
+ Regexp.new(pattern)
1570
+ end
1571
+ end
1572
+ end
1573
+
1558
1574
  attr_reader :pattern
1559
1575
 
1560
1576
  def initialize(pattern)
@@ -30,22 +30,19 @@ class Puppet::Resource
30
30
  TYPE_NODE = 'Node'.freeze
31
31
  TYPE_SITE = 'Site'.freeze
32
32
 
33
- def self.from_data_hash(data, json_deserializer = nil)
33
+ PCORE_TYPE_KEY = '__pcore_type__'.freeze
34
+ VALUE_KEY = 'value'.freeze
35
+
36
+ def self.from_data_hash(data, rich_data_enabled = false)
34
37
  raise ArgumentError, "No resource type provided in serialized data" unless type = data['type']
35
38
  raise ArgumentError, "No resource title provided in serialized data" unless title = data['title']
36
39
 
37
40
  resource = new(type, title)
38
41
 
39
42
  if params = data['parameters']
40
- params.each { |param, value| resource[param] = value }
41
- end
42
-
43
- if ext_params = data['ext_parameters']
44
- raise Puppet::Error, 'Unable to deserialize non-Data type parameters unless a deserializer is provided' unless json_deserializer
45
- reader = json_deserializer.reader
46
- ext_params.each do |param, value|
47
- reader.re_initialize(value)
48
- resource[param] = json_deserializer.read
43
+ params.each do |param, value|
44
+ value = convert_rich_data_hash(value, rich_data_enabled) if value.is_a?(Hash) && value.include?(PCORE_TYPE_KEY)
45
+ resource[param] = value
49
46
  end
50
47
  end
51
48
 
@@ -66,11 +63,35 @@ class Puppet::Resource
66
63
  resource
67
64
  end
68
65
 
66
+ def self.convert_rich_data_hash(rich_data_hash, rich_data_enabled)
67
+ if rich_data_enabled
68
+ value = rich_data_hash[VALUE_KEY]
69
+ if value.is_a?(Array)
70
+ json_deserializer ||= Puppet::Pops::Serialization::Deserializer.new(Puppet::Pops::Serialization::JSON::Reader.new([]), nil)
71
+ reader = json_deserializer.reader
72
+ reader.re_initialize(value)
73
+ json_deserializer.read
74
+ else
75
+ pcore_type = Puppet::Pops::Types::TypeParser.singleton.parse(rich_data_hash[PCORE_TYPE_KEY])
76
+ pcore_type.create(value)
77
+ end
78
+ else
79
+ strict = Puppet[:strict]
80
+ unless strict == :off
81
+ msg = _('Unable to deserialize non-Data value for parameter %{param} unless rich data is enabled') % { :param => "#{resource.name}.#{param}" }
82
+ raise Puppet::Error, msg if strict == :error
83
+ Puppet.warn(msg)
84
+ end
85
+ rich_data_hash
86
+ end
87
+ end
88
+ private_class_method :convert_rich_data_hash
89
+
69
90
  def inspect
70
91
  "#{@type}[#{@title}]#{to_hash.inspect}"
71
92
  end
72
93
 
73
- def to_data_hash(json_serializer = nil)
94
+ def to_data_hash(rich_data_enabled = false)
74
95
  data = ([:type, :title, :tags] + ATTRIBUTES).inject({}) do |hash, param|
75
96
  next hash unless value = self.send(param)
76
97
  hash[param.to_s] = value
@@ -87,7 +108,7 @@ class Puppet::Resource
87
108
  value = Puppet::Resource.value_to_pson_data(value)
88
109
  if is_json_type?(value)
89
110
  params[param] = value
90
- elsif json_serializer.nil?
111
+ elsif !rich_data_enabled
91
112
  Puppet.warning("Resource '#{to_s}' contains a #{value.class.name} value. It will be converted to the String '#{value}'")
92
113
  params[param] = value
93
114
  else
@@ -96,18 +117,35 @@ class Puppet::Resource
96
117
  end
97
118
  end
98
119
 
99
- data['parameters'] = params unless params.empty?
100
120
  unless ext_params.empty?
101
- writer = json_serializer.writer
102
- ext_params.each_key do |key|
103
- writer.clear_io
104
- json_serializer.write(ext_params[key])
105
- writer.finish
106
- ext_params[key] = writer.to_a
121
+ tc = Puppet::Pops::Types::TypeCalculator.singleton
122
+ sc = Puppet::Pops::Types::StringConverter.singleton
123
+ ext_params.each_pair do |key, value|
124
+ pcore_type = tc.infer(value)
125
+
126
+ # Don't allow unknown runtime types to leak into the catalog
127
+ raise Puppet::Error, _('No Puppet Type found for %{type_name}') % { :type_name => value.class.name } if pcore_type.is_a?(Puppet::Pops::Types::PRuntimeType)
128
+
129
+ if value.is_a?(Hash) || value.is_a?(Array) || value.is_a?(Puppet::Pops::Types::PuppetObject)
130
+ # Non scalars and Objects are serialized into an array using Pcore
131
+ json_serializer ||= Puppet::Pops::Serialization::Serializer.new(Puppet::Pops::Serialization::JSON::Writer.new(''), :type_by_reference => true)
132
+ writer = json_serializer.writer
133
+ writer.clear_io
134
+ json_serializer.write(value)
135
+ writer.finish
136
+ value = writer.to_a
137
+ else
138
+ # Scalar values are stored using their default string representation
139
+ value = sc.convert(value)
140
+ end
141
+ params[key] = {
142
+ PCORE_TYPE_KEY => pcore_type.name,
143
+ VALUE_KEY => value
144
+ }
107
145
  end
108
- data['ext_parameters'] = ext_params
109
146
  end
110
147
 
148
+ data['parameters'] = params unless params.empty?
111
149
  data["sensitive_parameters"] = sensitive_parameters unless sensitive_parameters.empty?
112
150
 
113
151
  data
@@ -424,15 +424,9 @@ class Puppet::Resource::Catalog < Puppet::Graph::SimpleGraph
424
424
  end
425
425
 
426
426
  if resources = data['resources']
427
- # TODO: The deserializer needs a loader in order to deserialize types defined using the puppet language.
428
- json_deserializer = nil
429
- if resources.any? { |res| res.has_key?('ext_parameters') }
430
- json_deserializer = Puppet::Pops::Serialization::Deserializer.new(
431
- Puppet::Pops::Serialization::JSON::Reader.new([]),
432
- Puppet::Pops::Loaders.catalog_loader)
433
- end
427
+ rich_data_enabled = Puppet[:rich_data] || result.environment_instance && result.environment_instance.rich_data?
434
428
  result.add_resource(*resources.collect do |res|
435
- Puppet::Resource.from_data_hash(res, json_deserializer)
429
+ Puppet::Resource.from_data_hash(res, rich_data_enabled)
436
430
  end)
437
431
  end
438
432
 
@@ -487,8 +481,7 @@ class Puppet::Resource::Catalog < Puppet::Graph::SimpleGraph
487
481
  resources = if @resources.empty?
488
482
  []
489
483
  elsif environment_instance.rich_data?
490
- json_serializer = Puppet::Pops::Serialization::Serializer.new(Puppet::Pops::Serialization::JSON::Writer.new(''))
491
- @resources.collect { |v| @resource_table[v].to_data_hash(json_serializer) }
484
+ @resources.collect { |v| @resource_table[v].to_data_hash(true) }
492
485
  else
493
486
  @resources.collect { |v| @resource_table[v].to_data_hash }
494
487
  end
@@ -6,7 +6,7 @@
6
6
  # Raketasks and such to set the version based on the output of `git describe`
7
7
 
8
8
  module Puppet
9
- PUPPETVERSION = '4.10.0'
9
+ PUPPETVERSION = '4.10.1'
10
10
 
11
11
  ##
12
12
  # version is a public API method intended to always provide a fast and
@@ -6,11 +6,11 @@
6
6
  #, fuzzy
7
7
  msgid ""
8
8
  msgstr ""
9
- "Project-Id-Version: Puppet automation framework 4.9.4-162-g7637326\n"
9
+ "Project-Id-Version: Puppet automation framework 4.10.0-45-gb0ff2a9\n"
10
10
  "\n"
11
11
  "Report-Msgid-Bugs-To: https://tickets.puppetlabs.com\n"
12
- "POT-Creation-Date: 2017-03-22 13:57-0700\n"
13
- "PO-Revision-Date: 2017-03-22 13:57-0700\n"
12
+ "POT-Creation-Date: 2017-04-18 09:07-0700\n"
13
+ "PO-Revision-Date: 2017-04-18 09:07-0700\n"
14
14
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
15
15
  "Language-Team: LANGUAGE <LL@li.org>\n"
16
16
  "Language: \n"
@@ -19,42 +19,66 @@ msgstr ""
19
19
  "Content-Transfer-Encoding: 8bit\n"
20
20
  "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
21
21
 
22
+ #: ../lib/puppet/application.rb:353
23
+ msgid "`puppet %{name}` is deprecated and will be removed in a future release."
24
+ msgstr ""
25
+
26
+ #: ../lib/puppet/defaults.rb:1698
27
+ msgid "Setting 'archive_files' is deprecated. It will be removed in a future release along with the `inspect` command."
28
+ msgstr ""
29
+
30
+ #: ../lib/puppet/defaults.rb:1707
31
+ msgid "Setting 'archive_file_server' is deprecated. It will be removed in a future release along with the `inspect` command."
32
+ msgstr ""
33
+
34
+ #: ../lib/puppet/face/help.rb:9
22
35
  msgid "Apache 2 license; see COPYING"
23
36
  msgstr ""
24
37
 
38
+ #: ../lib/puppet/face/help.rb:11
25
39
  msgid "Display Puppet help."
26
40
  msgstr ""
27
41
 
42
+ #: ../lib/puppet/face/help.rb:14
28
43
  msgid "Display help about Puppet subcommands and their actions."
29
44
  msgstr ""
30
45
 
46
+ #: ../lib/puppet/face/help.rb:15
31
47
  msgid "[<subcommand>] [<action>]"
32
48
  msgstr ""
33
49
 
50
+ #: ../lib/puppet/face/help.rb:16
34
51
  msgid "Short help text for the specified subcommand or action."
35
52
  msgstr ""
36
53
 
54
+ #: ../lib/puppet/face/help.rb:17
37
55
  msgid ""
38
56
  " Get help for an action:\n"
39
57
  "\n"
40
58
  " $ puppet help\n"
41
59
  msgstr ""
42
60
 
61
+ #: ../lib/puppet/face/help.rb:23
43
62
  msgid "VERSION"
44
63
  msgstr ""
45
64
 
65
+ #: ../lib/puppet/face/help.rb:24
46
66
  msgid "The version of the subcommand for which to show help."
47
67
  msgstr ""
48
68
 
69
+ #: ../lib/puppet/face/help.rb:50
49
70
  msgid "Puppet help only takes two (optional) arguments: a subcommand and an action"
50
71
  msgstr ""
51
72
 
73
+ #: ../lib/puppet/face/help.rb:59
52
74
  msgid "Version only makes sense when a Faces subcommand is given"
53
75
  msgstr ""
54
76
 
77
+ #: ../lib/puppet/face/help.rb:69
55
78
  msgid "Legacy subcommands don't take actions"
56
79
  msgstr ""
57
80
 
81
+ #: ../lib/puppet/face/help.rb:81
58
82
  msgid ""
59
83
  "Could not load help for the application #{applicationname}.\n"
60
84
  "Please check the error logs for more information.\n"
@@ -62,6 +86,7 @@ msgid ""
62
86
  "Detail: \"#{detail.message}\"\n"
63
87
  msgstr ""
64
88
 
89
+ #: ../lib/puppet/face/help.rb:94
65
90
  msgid ""
66
91
  "Could not load help for the face #{facename}.\n"
67
92
  "Please check the error logs for more information.\n"
@@ -69,23 +94,53 @@ msgid ""
69
94
  "Detail: \"#{detail.message}\"\n"
70
95
  msgstr ""
71
96
 
97
+ #: ../lib/puppet/face/help.rb:108
72
98
  msgid "\"Unable to load action #{actionname} from #{face}\""
73
99
  msgstr ""
74
100
 
101
+ #: ../lib/puppet/face/help.rb:150
75
102
  msgid " (Deprecated)"
76
103
  msgstr ""
77
104
 
105
+ #: ../lib/puppet/face/help.rb:153 ../lib/puppet/face/help.rb:174
78
106
  msgid "! Subcommand unavailable due to error. Check error logs."
79
107
  msgstr ""
80
108
 
109
+ #: ../lib/puppet/indirector/file_bucket_file/file.rb:169
110
+ msgid "Unable to verify existing FileBucket backup at '%{path}'."
111
+ msgstr ""
112
+
113
+ #: ../lib/puppet/indirector/file_bucket_file/file.rb:170
114
+ msgid "Existing backup and new file have different content but same checksum, %{value}. Verify existing backup and remove if incorrect."
115
+ msgstr ""
116
+
117
+ #: ../lib/puppet/indirector/file_bucket_file/file.rb:176
118
+ msgid "Existing backup does not match its expected sum, %{sum}. Overwriting corrupted backup."
119
+ msgstr ""
120
+
121
+ #: ../lib/puppet/resource.rb:81
122
+ msgid "Unable to deserialize non-Data value for parameter %{param} unless rich data is enabled"
123
+ msgstr ""
124
+
125
+ #: ../lib/puppet/resource.rb:127
126
+ msgid "No Puppet Type found for %{type_name}"
127
+ msgstr ""
128
+
129
+ #: ../lib/puppet/type.rb:1324
130
+ msgid "The `audit` metaparameter is deprecated and will be ignored in a future release."
131
+ msgstr ""
132
+
133
+ #: ../lib/puppet/util/character_encoding.rb:75
81
134
  msgid "%{error}: %{value} is not valid UTF-8 and cannot be transcoded by Puppet."
82
135
  msgstr ""
83
136
 
84
137
  #. TRANSLATORS message accompanied by date of generation
138
+ #: ../lib/puppet/util/reference.rb:17
85
139
  msgid "This page autogenerated on "
86
140
  msgstr ""
87
141
 
88
142
  #. TRANSLATORS message accompanied by date of generation
143
+ #: ../lib/puppet/util/reference.rb:116
89
144
  msgid ""
90
145
  "\n"
91
146
  "\n"
@@ -210,6 +210,7 @@ end
210
210
  end
211
211
 
212
212
  it 'can apply the catalog' do
213
+ pending('awaits PUP-7423') # test no longer functional when Object types are serialized by reference
213
214
  catalog = compile_to_catalog('include mod', node)
214
215
 
215
216
  Puppet[:environment] = env_name
@@ -1,7 +1,7 @@
1
1
  shared_context 'types_setup' do
2
2
 
3
3
  # Do not include the special type Unit in this list
4
- def all_types
4
+ def self.all_types
5
5
  [ Puppet::Pops::Types::PAnyType,
6
6
  Puppet::Pops::Types::PUndefType,
7
7
  Puppet::Pops::Types::PNotUndefType,
@@ -40,8 +40,11 @@ shared_context 'types_setup' do
40
40
  Puppet::Pops::Types::PBinaryType,
41
41
  ]
42
42
  end
43
+ def all_types
44
+ self.class.all_types
45
+ end
43
46
 
44
- def scalar_types
47
+ def self.scalar_types
45
48
  # PVariantType is also scalar, if its types are all Scalar
46
49
  [
47
50
  Puppet::Pops::Types::PScalarType,
@@ -59,8 +62,11 @@ shared_context 'types_setup' do
59
62
  Puppet::Pops::Types::PTimestampType,
60
63
  ]
61
64
  end
65
+ def scalar_types
66
+ self.class.scalar_types
67
+ end
62
68
 
63
- def numeric_types
69
+ def self.numeric_types
64
70
  # PVariantType is also numeric, if its types are all numeric
65
71
  [
66
72
  Puppet::Pops::Types::PNumericType,
@@ -68,8 +74,11 @@ shared_context 'types_setup' do
68
74
  Puppet::Pops::Types::PFloatType,
69
75
  ]
70
76
  end
77
+ def numeric_types
78
+ self.class.numeric_types
79
+ end
71
80
 
72
- def string_types
81
+ def self.string_types
73
82
  # PVariantType is also string type, if its types are all compatible
74
83
  [
75
84
  Puppet::Pops::Types::PStringType,
@@ -77,8 +86,11 @@ shared_context 'types_setup' do
77
86
  Puppet::Pops::Types::PEnumType,
78
87
  ]
79
88
  end
89
+ def string_types
90
+ self.class.string_types
91
+ end
80
92
 
81
- def collection_types
93
+ def self.collection_types
82
94
  # PVariantType is also string type, if its types are all compatible
83
95
  [
84
96
  Puppet::Pops::Types::PCollectionType,
@@ -88,17 +100,23 @@ shared_context 'types_setup' do
88
100
  Puppet::Pops::Types::PTupleType,
89
101
  ]
90
102
  end
103
+ def collection_types
104
+ self.class.collection_types
105
+ end
91
106
 
92
- def data_compatible_types
107
+ def self.data_compatible_types
93
108
  result = scalar_types
94
109
  result << Puppet::Pops::Types::PDataType
95
- result << array_t(types::PDataType::DEFAULT)
96
- result << types::TypeFactory.hash_of_data
110
+ result << Puppet::Pops::Types::PArrayType::DATA
111
+ result << Puppet::Pops::Types::PHashType::DATA
97
112
  result << Puppet::Pops::Types::PUndefType
98
- result << not_undef_t(types::PDataType.new)
99
- result << constrained_tuple_t(range_t(0, nil), types::PDataType::DEFAULT)
113
+ result << Puppet::Pops::Types::PNotUndefType.new(Puppet::Pops::Types::PDataType::DEFAULT)
114
+ result << Puppet::Pops::Types::PTupleType.new([Puppet::Pops::Types::PDataType::DEFAULT], Puppet::Pops::Types::PIntegerType.new(0, nil))
100
115
  result
101
116
  end
117
+ def data_compatible_types
118
+ self.class.data_compatible_types
119
+ end
102
120
 
103
121
  def type_from_class(c)
104
122
  c.is_a?(Class) ? c::DEFAULT : c
@@ -438,6 +438,30 @@ describe "The lookup function" do
438
438
  expect(lookup('a')).to eql('value a (from environment)')
439
439
  end
440
440
 
441
+ context 'with log-level debug' do
442
+ before(:each) { Puppet[:log_level] = 'debug' }
443
+
444
+ it 'does not report a regular lookup as APL' do
445
+ expect(lookup('a')).to eql('value a (from environment)')
446
+ expect(debugs.count { |dbg| dbg =~ /\A\s*Automatic Parameter Lookup of/ }).to eql(0)
447
+ end
448
+
449
+ it 'reports regular lookup as lookup' do
450
+ expect(lookup('a')).to eql('value a (from environment)')
451
+ expect(debugs.count { |dbg| dbg =~ /\A\s*Lookup of/ }).to eql(1)
452
+ end
453
+
454
+ it 'does not report APL as lookup' do
455
+ collect_notices("class mod_a($a) { notice($a) }; include mod_a")
456
+ expect(debugs.count { |dbg| dbg =~ /\A\s*Lookup of/ }).to eql(0)
457
+ end
458
+
459
+ it 'reports APL as APL' do
460
+ collect_notices("class mod_a($a) { notice($a) }; include mod_a")
461
+ expect(debugs.count { |dbg| dbg =~ /\A\s*Automatic Parameter Lookup of/ }).to eql(1)
462
+ end
463
+ end
464
+
441
465
  context 'that has no lookup configured' do
442
466
  let(:environment_files) do
443
467
  {
@@ -2107,6 +2131,53 @@ describe "The lookup function" do
2107
2131
  end
2108
2132
  end
2109
2133
 
2134
+ context 'using deep merge and module values that aliases environment values' do
2135
+ let(:mod_a_files) do
2136
+ {
2137
+ 'mod_a' => {
2138
+ 'data' => {
2139
+ 'common.yaml' => <<-YAML.unindent,
2140
+ ---
2141
+ mod_a::hash:
2142
+ b: value b (from module)
2143
+ lookup_options:
2144
+ mod_a::hash:
2145
+ merge: deep
2146
+ YAML
2147
+ },
2148
+ 'hiera.yaml' => <<-YAML.unindent,
2149
+ ---
2150
+ version: 5
2151
+ hierarchy:
2152
+ - name: "Common"
2153
+ path: "common.yaml"
2154
+ - name: "Other"
2155
+ path: "other.yaml"
2156
+ YAML
2157
+ }
2158
+ }
2159
+ end
2160
+ let(:env_data) do
2161
+ {
2162
+ 'common.yaml' => <<-YAML.unindent
2163
+ a: value a (from environment)
2164
+ mod_a::hash:
2165
+ a: value mod_a::hash.a (from environment)
2166
+ c: '%{alias("a")}'
2167
+ YAML
2168
+ }
2169
+ end
2170
+
2171
+ it 'continues with module lookup after alias is resolved in environment' do
2172
+ expect(lookup('mod_a::hash')).to eql(
2173
+ {
2174
+ 'a' => 'value mod_a::hash.a (from environment)',
2175
+ 'b' => 'value b (from module)',
2176
+ 'c' => 'value a (from environment)'
2177
+ })
2178
+ end
2179
+ end
2180
+
2110
2181
  context 'using a data_hash that reads a yaml file' do
2111
2182
  let(:defaults) {
2112
2183
  {