hiera 3.1.0-x64-mingw32 → 3.1.1-x64-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -101,6 +101,48 @@ $ hiera ssh_users.0
101
101
  root
102
102
  </pre>
103
103
 
104
+ ### Use quotes to disable qualified key behavior
105
+ In case you have dotted keys and thus want to avoid using the qualified key semantics, you
106
+ can put segments of a dotted key, or the whole key, within quotes.
107
+
108
+ Given the following data:
109
+
110
+ <pre>
111
+ # yaml
112
+ a:
113
+ b.c:
114
+ d: 'Data for a => b.c => d'
115
+ </pre>
116
+
117
+ it is possible to do a lookup of the data like this:
118
+
119
+ <pre>
120
+ $ hiera 'a."b.c".d'
121
+ Data for a => b.c => d
122
+ </pre>
123
+
124
+ Quoting works in interpolation expressions as well.
125
+
126
+ Interpolating from global scope:
127
+
128
+ <pre>
129
+ # yaml
130
+ other.key: 'scope data: %{a."b.c".d}'
131
+ </pre>
132
+
133
+ or using an interpolation method:
134
+
135
+ <pre>
136
+ # yaml
137
+ a:
138
+ b.c:
139
+ d: 'Data for a => b.c => d'
140
+ other.key: 'hiera data %{hiera("a.''b.c''.d")}'
141
+ </pre>
142
+
143
+ Note that two single quotes are used to escape a single quote inside a single quoted string
144
+ (that's YAML syntax, not Hiera) and that the quoted key must be quoted in turn.
145
+
104
146
  ## Future Enhancements
105
147
 
106
148
  * More backends should be created
data/lib/hiera/backend.rb CHANGED
@@ -231,7 +231,7 @@ class Hiera
231
231
  # databases then do so in your constructor, future calls to your
232
232
  # backend will not create new instances
233
233
 
234
- # @param key [String] The key to lookup
234
+ # @param key [String] The key to lookup. May be quoted with single or double quotes to avoid subkey traversal on dot characters
235
235
  # @param scope [#[]] The primary source of data for substitutions.
236
236
  # @param order_override [#[],nil] An override that will be pre-pended to the hierarchy definition.
237
237
  # @param resolution_type [Symbol,Hash,nil] One of :hash, :array,:priority or a Hash with deep merge behavior and options
@@ -250,7 +250,7 @@ class Hiera
250
250
 
251
251
  strategy = resolution_type.is_a?(Hash) ? :hash : resolution_type
252
252
 
253
- segments = key.split('.')
253
+ segments = Util.split_key(key) { |problem| ArgumentError.new("#{problem} in key: #{key}") }
254
254
  subsegments = nil
255
255
  if segments.size > 1
256
256
  raise ArgumentError, "Resolution type :#{strategy} is illegal when doing segmented key lookups" unless strategy.nil? || strategy == :priority
@@ -265,7 +265,7 @@ class Hiera
265
265
  found_in_backend = false
266
266
  new_answer = catch(:no_such_key) do
267
267
  if subsegments.nil?
268
- value = backend.lookup(key, scope, order_override, resolution_type, context)
268
+ value = backend.lookup(segments[0], scope, order_override, resolution_type, context)
269
269
  elsif backend.respond_to?(:lookup_with_segments)
270
270
  value = backend.lookup_with_segments(segments, scope, order_override, resolution_type, context)
271
271
  else
@@ -4,34 +4,51 @@ require 'hiera/recursive_guard'
4
4
 
5
5
  class Hiera::InterpolationInvalidValue < StandardError; end
6
6
 
7
+ # @api private
7
8
  class Hiera::Interpolate
9
+ RX_INTERPOLATION = /%\{([^\}]*)\}/
10
+ RX_ONLY_INTERPOLATION = /^%\{([^\}]*)\}$/
11
+ RX_METHOD_AND_ARG = /^(\w+)\(([^)]*)\)$/
12
+
13
+ EMPTY_INTERPOLATIONS = {
14
+ '' => true,
15
+ '::' => true,
16
+ '""' => true,
17
+ "''" => true,
18
+ '"::"' => true,
19
+ "'::'" => true
20
+ }.freeze
21
+
22
+ INTERPOLATION_METHODS = {
23
+ 'hiera' => :hiera_interpolate,
24
+ 'scope' => :scope_interpolate,
25
+ 'literal' => :literal_interpolate,
26
+ 'alias' => :alias_interpolate
27
+ }.freeze
28
+
8
29
  class << self
30
+ # These two patterns are never used but kept here anyway since they used to be public and therefore
31
+ # must be considered API. The class is now marked @api private and these should be removed in a
32
+ # future version
33
+ #
34
+ # @deprecated
9
35
  INTERPOLATION = /%\{([^\}]*)\}/
36
+
37
+ # @deprecated
10
38
  METHOD_INTERPOLATION = /%\{(scope|hiera|literal|alias)\(['"]([^"']*)["']\)\}/
11
39
 
12
40
  def interpolate(data, scope, extra_data, context)
13
41
  if data.is_a?(String)
14
42
  # Wrapping do_interpolation in a gsub block ensures we process
15
43
  # each interpolation site in isolation using separate recursion guards.
16
- context ||= {}
17
- new_context = context.clone
44
+ new_context = context.nil? ? {} : context.clone
18
45
  new_context[:recurse_guard] ||= Hiera::RecursiveGuard.new
19
- data.gsub(INTERPOLATION) do |match|
20
- interp_val = do_interpolation(match, scope, extra_data, new_context)
21
-
22
- # Get interp method in case we are aliasing
23
- if data.is_a?(String) && (match = data.match(INTERPOLATION))
24
- interpolate_method, key = get_interpolation_method_and_key(data, new_context)
25
- else
26
- interpolate_method = nil
27
- end
46
+ data.gsub(RX_INTERPOLATION) do |match|
47
+ (interp_val, interpolate_method) = do_interpolation(match, scope, extra_data, new_context)
28
48
 
29
- if ( (interpolate_method == :alias_interpolate) and (!interp_val.is_a?(String)) )
30
- if data.match("^#{INTERPOLATION}$")
31
- return interp_val
32
- else
33
- raise Hiera::InterpolationInvalidValue, "Cannot call alias in the string context"
34
- end
49
+ if (interpolate_method == :alias_interpolate) && !interp_val.is_a?(String)
50
+ return interp_val if data.match(RX_ONLY_INTERPOLATION)
51
+ raise Hiera::InterpolationInvalidValue, "Cannot call alias in the string context"
35
52
  else
36
53
  interp_val
37
54
  end
@@ -42,47 +59,45 @@ class Hiera::Interpolate
42
59
  end
43
60
 
44
61
  def do_interpolation(data, scope, extra_data, context)
45
- if data.is_a?(String) && (match = data.match(INTERPOLATION))
62
+ if data.is_a?(String) && (match = data.match(RX_INTERPOLATION))
46
63
  interpolation_variable = match[1]
47
64
 
48
65
  # HI-494
49
- case interpolation_variable.strip
50
- when '', '::'
51
- return ''
52
- end
66
+ return ['', nil] if EMPTY_INTERPOLATIONS[interpolation_variable.strip]
53
67
 
54
68
  context[:recurse_guard].check(interpolation_variable) do
55
- interpolate_method, key = get_interpolation_method_and_key(data, context)
69
+ interpolate_method, key = get_interpolation_method_and_key(interpolation_variable, context)
56
70
  interpolated_data = send(interpolate_method, data, key, scope, extra_data, context)
57
71
 
58
72
  # Halt recursion if we encounter a literal.
59
- return interpolated_data if interpolate_method == :literal_interpolate
73
+ return [interpolated_data, interpolate_method] if interpolate_method == :literal_interpolate
60
74
 
61
- do_interpolation(interpolated_data, scope, extra_data, context)
75
+ [do_interpolation(interpolated_data, scope, extra_data, context)[0], interpolate_method]
62
76
  end
63
77
  else
64
- data
78
+ [data, nil]
65
79
  end
66
80
  end
67
81
  private :do_interpolation
68
82
 
69
- def get_interpolation_method_and_key(data, context)
70
- if (match = data.match(METHOD_INTERPOLATION))
83
+ def get_interpolation_method_and_key(interpolation_variable, context)
84
+ if (match = interpolation_variable.match(RX_METHOD_AND_ARG))
71
85
  Hiera.warn('Use of interpolation methods in hiera configuration file is deprecated') if context[:is_interpolate_config]
72
- case match[1]
73
- when 'hiera' then [:hiera_interpolate, match[2]]
74
- when 'scope' then [:scope_interpolate, match[2]]
75
- when 'literal' then [:literal_interpolate, match[2]]
76
- when 'alias' then [:alias_interpolate, match[2]]
77
- end
78
- elsif (match = data.match(INTERPOLATION))
79
- [:scope_interpolate, match[1]]
86
+ method = match[1]
87
+ method_sym = INTERPOLATION_METHODS[method]
88
+ raise Hiera::InterpolationInvalidValue, "Invalid interpolation method '#{method}'" unless method_sym
89
+ arg = match[2]
90
+ match_data = arg.match(Hiera::QUOTED_KEY)
91
+ raise Hiera::InterpolationInvalidValue, "Argument to interpolation method '#{method}' must be quoted, got '#{arg}'" unless match_data
92
+ [method_sym, match_data[1] || match_data[2]]
93
+ else
94
+ [:scope_interpolate, interpolation_variable]
80
95
  end
81
96
  end
82
97
  private :get_interpolation_method_and_key
83
98
 
84
99
  def scope_interpolate(data, key, scope, extra_data, context)
85
- segments = key.split('.')
100
+ segments = Hiera::Util.split_key(key) { |problem| Hiera::InterpolationInvalidValue.new("#{problem} in interpolation expression: #{data}") }
86
101
  catch(:no_such_key) { return Hiera::Backend.qualified_lookup(segments, scope) }
87
102
  catch(:no_such_key) { Hiera::Backend.qualified_lookup(segments, extra_data) }
88
103
  end
data/lib/hiera/util.rb CHANGED
@@ -1,4 +1,9 @@
1
1
  class Hiera
2
+
3
+ # Matches a key that is quoted using a matching pair of either single or double quotes.
4
+ QUOTED_KEY = /^(?:"([^"]+)"|'([^']+)')$/
5
+ QUOTES = /[",]/
6
+
2
7
  module Util
3
8
  module_function
4
9
 
@@ -42,6 +47,23 @@ class Hiera
42
47
  def common_appdata
43
48
  Dir::COMMON_APPDATA
44
49
  end
50
+
51
+ def split_key(key)
52
+ segments = key.split(/(?:"([^"]+)"|'([^']+)'|([^'".]+))/)
53
+ if segments.empty?
54
+ # Only happens if the original key was an empty string
55
+ ''
56
+ elsif segments.shift == ''
57
+ count = segments.size
58
+ raise yield('Syntax error') unless count > 0
59
+
60
+ segments.keep_if { |seg| seg != '.' }
61
+ raise yield('Syntax error') unless segments.size * 2 == count + 1
62
+ segments
63
+ else
64
+ raise yield('Syntax error')
65
+ end
66
+ end
45
67
  end
46
68
  end
47
69
 
data/lib/hiera/version.rb CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
 
9
9
  class Hiera
10
- VERSION = "3.1.0"
10
+ VERSION = "3.1.1"
11
11
 
12
12
  ##
13
13
  # version is a public API method intended to always provide a fast and
@@ -4,4 +4,8 @@
4
4
  :hierarchy:
5
5
  - recursive
6
6
  - niltest
7
+ - complex
7
8
  - empty_%{}inter%{::}polation
9
+ - dotted_keys
10
+ - weird_keys
11
+ - bad_interpolation
@@ -0,0 +1,9 @@
1
+ ---
2
+ quote_mismatch: 'Key delimited with singe quote on one side aand double qoute on the other: %{''the.key"}'
3
+ quote_mismatch_arg: 'Arg delimited with singe quote on one side and double qoute on the other: %{hiera(''the.key")}'
4
+ non_existing_method: 'The method flubber does not exist: %{flubber("hello")}'
5
+
6
+ one_quote: 'Key with only one quote: %{the.''key}'
7
+ empty_segment: 'Key with only one quote: %{the..key}'
8
+ empty_quoted_segment: 'Key with only one quote: %{the.''''.key}'
9
+ partly_quoted_segment: 'Key with only one quote: %{the.''pa''key}'
@@ -0,0 +1,12 @@
1
+ ---
2
+ root:
3
+ a:
4
+ aa: "%{alias('aaa')}"
5
+
6
+ aaa:
7
+ b:
8
+ bb: "%{alias('bbb')}"
9
+
10
+ bbb: [ "%{alias('ccc')}" ]
11
+
12
+ ccc: text
@@ -0,0 +1,40 @@
1
+ ---
2
+ a.b: '(hiera) a dot b'
3
+ a.c.scope: "a dot c: %{'a.b'}"
4
+ a.c.hiera: 'a dot c: %{hiera("''a.b''")}'
5
+ a.c.scope: "a dot c: %{'a.b'}"
6
+ a.c.hiera: 'a dot c: %{hiera("''a.b''")}'
7
+ a.c.alias: '%{alias("''a.b''")}'
8
+ a:
9
+ d: '(hiera) a dot d is a hash entry'
10
+ d.x: '(hiera) a dot d.x is a hash entry'
11
+ d.z:
12
+ g: '(hiera) a dot d.z dot g is a hash entry'
13
+
14
+ a.x:
15
+ d: '(hiera) a.x dot d is a hash entry'
16
+ d.x: '(hiera) a.x dot d.x is a hash entry'
17
+ d.z:
18
+ g: '(hiera) a.x dot d.z dot g is a hash entry'
19
+
20
+ a.e.scope: "a dot e: %{a.d}"
21
+ a.e.hiera: "a dot e: %{hiera('a.d')}"
22
+
23
+ a.ex.scope: "a dot ex: %{a.'d.x'}"
24
+ a.ex.hiera: 'a dot ex: %{hiera("a.''d.x''")}'
25
+
26
+ a.xe.scope: "a dot xe: %{'a.x'.d}"
27
+ a.xe.hiera: 'a dot xe: %{hiera("''a.x''.d")}'
28
+
29
+ a.xm.scope: "a dot xm: %{a.'d.z'.g}"
30
+ a.xm.hiera: 'a dot xm: %{hiera("a.''d.z''.g")}'
31
+
32
+ a.xx.scope: "a dot xx: %{'a.x'.'d.z'.g}"
33
+ a.xx.hiera: 'a dot xx: %{hiera("''a.x''.''d.z''.g")}'
34
+
35
+ a.f.scope: "a dot f: %{'a.d'}"
36
+ a.f.hiera: 'a dot f: %{hiera("''a.d''")}'
37
+
38
+ x.1: '(hiera) x dot 1'
39
+ x.2.scope: "x dot 2: %{'x.1'}"
40
+ x.2.hiera: 'x dot 2: %{hiera("''x.1''")}'
@@ -4,3 +4,10 @@ only_empty_interpolation: '%{}'
4
4
  empty_namespace: '%{::}'
5
5
  whitespace1: '%{ :: }'
6
6
  whitespace2: '%{ }'
7
+
8
+ quoted_empty_interpolation: 'clown%{""}shoe'
9
+ quoted_escaped_empty_interpolation: 'clown%%{""}{shoe}s'
10
+ quoted_only_empty_interpolation: '%{""}'
11
+ quoted_empty_namespace: '%{"::"}'
12
+ quoted_whitespace1: '%{ "::" }'
13
+ quoted_whitespace2: '%{ "" }'
@@ -0,0 +1,12 @@
1
+ ---
2
+
3
+ 'a key with whitespace': 'value for a ws key'
4
+ ws_key: '%{alias("a key with whitespace")}'
5
+
6
+ '#@!&%|§': 'not happy'
7
+ angry: '%{alias("#@!&%|§")}'
8
+
9
+ '!$\%!':
10
+ '#@!&%|§': 'not happy at all'
11
+
12
+ very_angry: '%{alias("!$\%!.#@!&%|§")}'
@@ -2,98 +2,233 @@ require 'spec_helper'
2
2
  require 'hiera/util'
3
3
 
4
4
  describe "Hiera" do
5
- context "when doing interpolation" do
6
- let(:fixtures) { File.join(HieraSpec::FIXTURE_DIR, 'interpolate') }
5
+ let!(:fixtures) { File.join(HieraSpec::FIXTURE_DIR, 'interpolate') }
6
+ let!(:fixture_data) { File.join(fixtures, 'data') }
7
+ let(:hiera) { Hiera.new(:config => File.join(fixtures, 'config', 'hiera.yaml')) }
8
+
9
+ before(:each) do
10
+ Hiera::Util.expects(:var_dir).at_most(3).returns(fixture_data)
11
+ end
7
12
 
13
+ context "when doing interpolation" do
8
14
  it 'should prevent endless recursion' do
9
- Hiera::Util.expects(:var_dir).at_least_once.returns(File.join(fixtures, 'data'))
10
15
  hiera = Hiera.new(:config => File.join(fixtures, 'config', 'hiera.yaml'))
11
16
  expect do
12
17
  hiera.lookup('foo', nil, {})
13
18
  end.to raise_error Hiera::InterpolationLoop, 'Lookup recursion detected in [hiera("bar"), hiera("foo")]'
14
19
  end
20
+
21
+ it 'produces a nested hash with arrays from nested aliases with hashes and arrays' do
22
+ Hiera::Util.expects(:var_dir).at_least_once.returns(File.join(fixtures, 'data'))
23
+ hiera = Hiera.new(:config => File.join(fixtures, 'config', 'hiera.yaml'))
24
+ expect(hiera.lookup('root', nil, {}, nil, :hash)).to eq({'a'=>{'aa'=>{'b'=>{'bb'=>['text']}}}})
25
+ end
26
+
27
+ it 'allows keys with white space' do
28
+ expect(hiera.lookup('ws_key', nil, {})).to eq('value for a ws key')
29
+ end
30
+
31
+ it 'allows keys with non alphanumeric characters' do
32
+ expect(hiera.lookup('angry', nil, {})).to eq('not happy')
33
+ end
15
34
  end
16
35
 
17
36
  context "when not finding value for interpolated key" do
18
- let(:fixtures) { File.join(HieraSpec::FIXTURE_DIR, 'interpolate') }
19
-
20
37
  it 'should resolve the interpolation to an empty string' do
21
- Hiera::Util.expects(:var_dir).at_least_once.returns(File.join(fixtures, 'data'))
22
- hiera = Hiera.new(:config => File.join(fixtures, 'config', 'hiera.yaml'))
23
38
  expect(hiera.lookup('niltest', nil, {})).to eq('Missing key ##. Key with nil ##')
24
39
  end
25
40
  end
26
41
 
27
42
  context "when there are empty interpolations %{} in data" do
28
- let(:fixtures) { File.join(HieraSpec::FIXTURE_DIR, 'interpolate') }
29
-
30
43
  it 'should should produce an empty string for the interpolation' do
31
- Hiera::Util.expects(:var_dir).at_least_once.returns(File.join(fixtures, 'data'))
32
- hiera = Hiera.new(:config => File.join(fixtures, 'config', 'hiera.yaml'))
33
44
  expect(hiera.lookup('empty_interpolation', nil, {})).to eq('clownshoe')
34
45
  end
35
46
 
36
47
  it 'the empty interpolation can be escaped' do
37
- Hiera::Util.expects(:var_dir).at_least_once.returns(File.join(fixtures, 'data'))
38
- hiera = Hiera.new(:config => File.join(fixtures, 'config', 'hiera.yaml'))
39
48
  expect(hiera.lookup('escaped_empty_interpolation', nil, {})).to eq('clown%{shoe}s')
40
49
  end
41
50
 
42
51
  it 'the value can consist of only an empty escape' do
43
- Hiera::Util.expects(:var_dir).at_least_once.returns(File.join(fixtures, 'data'))
44
- hiera = Hiera.new(:config => File.join(fixtures, 'config', 'hiera.yaml'))
45
52
  expect(hiera.lookup('only_empty_interpolation', nil, {})).to eq('')
46
53
  end
47
54
 
48
55
  it 'the value can consist of an empty namespace %{::}' do
49
- Hiera::Util.expects(:var_dir).at_least_once.returns(File.join(fixtures, 'data'))
50
- hiera = Hiera.new(:config => File.join(fixtures, 'config', 'hiera.yaml'))
51
56
  expect(hiera.lookup('empty_namespace', nil, {})).to eq('')
52
57
  end
53
58
 
54
59
  it 'the value can consist of whitespace %{ :: }' do
55
- Hiera::Util.expects(:var_dir).at_least_once.returns(File.join(fixtures, 'data'))
56
- hiera = Hiera.new(:config => File.join(fixtures, 'config', 'hiera.yaml'))
57
60
  expect(hiera.lookup('whitespace1', nil, {})).to eq('')
58
61
  end
59
62
 
60
63
  it 'the value can consist of whitespace %{ }' do
61
- Hiera::Util.expects(:var_dir).at_least_once.returns(File.join(fixtures, 'data'))
62
- hiera = Hiera.new(:config => File.join(fixtures, 'config', 'hiera.yaml'))
63
64
  expect(hiera.lookup('whitespace2', nil, {})).to eq('')
64
65
  end
65
66
  end
66
67
 
67
- context "when doing interpolation with override" do
68
- let(:fixtures) { File.join(HieraSpec::FIXTURE_DIR, 'override') }
68
+ context 'when there are quoted empty interpolations %{} in data' do
69
+ it 'should should produce an empty string for the interpolation' do
70
+ expect(hiera.lookup('quoted_empty_interpolation', nil, {})).to eq('clownshoe')
71
+ end
72
+
73
+ it 'the empty interpolation can be escaped' do
74
+ expect(hiera.lookup('quoted_escaped_empty_interpolation', nil, {})).to eq('clown%{shoe}s')
75
+ end
76
+
77
+ it 'the value can consist of only an empty escape' do
78
+ expect(hiera.lookup('quoted_only_empty_interpolation', nil, {})).to eq('')
79
+ end
80
+
81
+ it 'the value can consist of an empty namespace %{::}' do
82
+ expect(hiera.lookup('quoted_empty_namespace', nil, {})).to eq('')
83
+ end
84
+
85
+ it 'the value can consist of whitespace %{ :: }' do
86
+ expect(hiera.lookup('quoted_whitespace1', nil, {})).to eq('')
87
+ end
88
+
89
+ it 'the value can consist of whitespace %{ }' do
90
+ expect(hiera.lookup('quoted_whitespace2', nil, {})).to eq('')
91
+ end
92
+ end
93
+
94
+ context 'when using dotted keys' do
95
+ it 'should find an entry using a quoted interpolation' do
96
+ expect(hiera.lookup('"a.c.scope"', nil, {'a.b' => '(scope) a dot b'})).to eq('a dot c: (scope) a dot b')
97
+ end
98
+
99
+ it 'should find an entry using a quoted interpolation with method hiera' do
100
+ expect(hiera.lookup('"a.c.hiera"', nil, {'a.b' => '(scope) a dot b'})).to eq('a dot c: (hiera) a dot b')
101
+ end
102
+
103
+ it 'should find an entry using a quoted interpolation with method alias' do
104
+ expect(hiera.lookup('"a.c.alias"', nil, {'a.b' => '(scope) a dot b'})).to eq('(hiera) a dot b')
105
+ end
106
+
107
+ it 'should use a dotted key to navigate into a structure when it is not quoted' do
108
+ expect(hiera.lookup('"a.e.scope"', nil, {'a' => { 'd' => '(scope) a dot d is a hash entry'}})).to eq('a dot e: (scope) a dot d is a hash entry')
109
+ end
110
+
111
+ it 'should use a dotted key to navigate into a structure when when it is not quoted with method hiera' do
112
+ expect(hiera.lookup('"a.e.hiera"', nil, {'a' => { 'd' => '(scope) a dot d is a hash entry'}})).to eq('a dot e: (hiera) a dot d is a hash entry')
113
+ end
114
+
115
+ it 'should use a mix of quoted and dotted keys to navigate into a structure containing dotted keys and quoted key is last' do
116
+ expect(hiera.lookup('"a.ex.scope"', nil, {'a' => { 'd.x' => '(scope) a dot d.x is a hash entry'}})).to eq('a dot ex: (scope) a dot d.x is a hash entry')
117
+ end
118
+
119
+ it 'should use a mix of quoted and dotted keys to navigate into a structure containing dotted keys and quoted key is last and method is hiera' do
120
+ expect(hiera.lookup('"a.ex.hiera"', nil, {'a' => { 'd.x' => '(scope) a dot d.x is a hash entry'}})).to eq('a dot ex: (hiera) a dot d.x is a hash entry')
121
+ end
122
+
123
+ it 'should use a mix of quoted and dotted keys to navigate into a structure containing dotted keys and quoted key is first' do
124
+ expect(hiera.lookup('"a.xe.scope"', nil, {'a.x' => { 'd' => '(scope) a.x dot d is a hash entry'}})).to eq('a dot xe: (scope) a.x dot d is a hash entry')
125
+ end
126
+
127
+ it 'should use a mix of quoted and dotted keys to navigate into a structure containing dotted keys and quoted key is first and method is hiera' do
128
+ expect(hiera.lookup('"a.xe.hiera"', nil, {'a.x' => { 'd' => '(scope) a.x dot d is a hash entry'}})).to eq('a dot xe: (hiera) a.x dot d is a hash entry')
129
+ end
130
+
131
+ it 'should use a mix of quoted and dotted keys to navigate into a structure containing dotted keys and quoted key is in the middle' do
132
+ expect(hiera.lookup('"a.xm.scope"', nil, {'a' => { 'd.z' => { 'g' => '(scope) a dot d.z dot g is a hash entry'}}})).to eq('a dot xm: (scope) a dot d.z dot g is a hash entry')
133
+ end
134
+
135
+ it 'should use a mix of quoted and dotted keys to navigate into a structure containing dotted keys and quoted key is in the middle and method is hiera' do
136
+ expect(hiera.lookup('"a.xm.hiera"', nil, {'a' => { 'd.z' => { 'g' => '(scope) a dot d.z dot g is a hash entry'}}})).to eq('a dot xm: (hiera) a dot d.z dot g is a hash entry')
137
+ end
138
+
139
+ it 'should use a mix of several quoted and dotted keys to navigate into a structure containing dotted keys and quoted key is in the middle' do
140
+ expect(hiera.lookup('"a.xx.scope"', nil, {'a.x' => { 'd.z' => { 'g' => '(scope) a.x dot d.z dot g is a hash entry'}}})).to eq('a dot xx: (scope) a.x dot d.z dot g is a hash entry')
141
+ end
142
+
143
+ it 'should use a mix of several quoted and dotted keys to navigate into a structure containing dotted keys and quoted key is in the middle and method is hiera' do
144
+ expect(hiera.lookup('"a.xx.hiera"', nil, {'a.x' => { 'd.z' => { 'g' => '(scope) a.x dot d.z dot g is a hash entry'}}})).to eq('a dot xx: (hiera) a.x dot d.z dot g is a hash entry')
145
+ end
146
+
147
+ it 'should find an entry using using a quoted interpolation on dotted key containing numbers' do
148
+ expect(hiera.lookup('"x.2.scope"', nil, {'x.1' => '(scope) x dot 1'})).to eq('x dot 2: (scope) x dot 1')
149
+ end
150
+
151
+ it 'should find an entry using using a quoted interpolation on dotted key containing numbers using method hiera' do
152
+ expect(hiera.lookup('"x.2.hiera"', nil, {'x.1' => '(scope) x dot 1'})).to eq('x dot 2: (hiera) x dot 1')
153
+ end
154
+
155
+ it 'will allow strange characters in the key' do
156
+ expect(hiera.lookup('very_angry', nil, {})).to eq('not happy at all')
157
+ end
158
+
159
+ it 'should not find a subkey when the dotted key is quoted' do
160
+ expect(hiera.lookup('"a.f.scope"', nil, {'a' => { 'f' => '(scope) a dot f is a hash entry'}})).to eq('a dot f: ')
161
+ end
162
+
163
+ it 'should not find a subkey when the dotted key is quoted with method hiera' do
164
+ expect(hiera.lookup('"a.f.hiera"', nil, {'a' => { 'f' => '(scope) a dot f is a hash entry'}})).to eq('a dot f: ')
165
+ end
166
+ end
167
+
168
+ context 'when bad interpolation expressions are encountered' do
169
+ it 'should produce an error when different quotes are used on either side' do
170
+ expect { hiera.lookup('quote_mismatch', nil, {}) }.to raise_error(/Syntax error in interpolation expression: \%\{'the\.key"\}/)
171
+ end
172
+
173
+ it 'should produce an if there is only one quote' do
174
+ expect { hiera.lookup('one_quote', nil, {}) }.to raise_error(/Syntax error in interpolation expression: \%\{the\.'key\}/)
175
+ end
176
+
177
+ it 'should produce an error for an empty segment' do
178
+ expect { hiera.lookup('empty_segment', nil, {}) }.to raise_error(/Syntax error in interpolation expression: \%\{the\.\.key\}/)
179
+ end
180
+
181
+ it 'should produce an error for an empty quoted segment' do
182
+ expect { hiera.lookup('empty_quoted_segment', nil, {}) }.to raise_error(/Syntax error in interpolation expression: \%\{the\.''\.key\}/)
183
+ end
184
+
185
+ it 'should produce an error for an partly quoted segment' do
186
+ expect { hiera.lookup('partly_quoted_segment', nil, {}) }.to raise_error(/Syntax error in interpolation expression: \%\{the\.'pa'key\}/)
187
+ end
188
+
189
+ it 'should produce an error when different quotes are used on either side in a method argument' do
190
+ expect { hiera.lookup('quote_mismatch_arg', nil, {}) }.to raise_error(/Argument to interpolation method 'hiera' must be quoted, got ''the.key"'/)
191
+ end
192
+
193
+ it 'should produce an error unless a known interpolation method is used' do
194
+ expect { hiera.lookup('non_existing_method', nil, {}) }.to raise_error(/Invalid interpolation method 'flubber'/)
195
+ end
196
+
197
+ it 'should produce an error if there is only one quote' do
198
+ expect { hiera.lookup('one_quote', nil, {}) }.to raise_error(/Syntax error/)
199
+ end
200
+
201
+ it 'should produce an error when different quotes are used on either side in a top-level key' do
202
+ expect { hiera.lookup("'the.key\"", nil, {}) }.to raise_error(/Syntax error in key: 'the.key"/)
203
+ end
204
+ end
205
+
206
+ context 'when doing interpolation with override' do
207
+ let!(:fixtures) { File.join(HieraSpec::FIXTURE_DIR, 'override') }
69
208
 
70
209
  it 'should resolve interpolation using the override' do
71
- Hiera::Util.expects(:var_dir).at_least_once.returns(File.join(fixtures, 'data'))
72
- hiera = Hiera.new(:config => File.join(fixtures, 'config', 'hiera.yaml'))
73
210
  expect(hiera.lookup('foo', nil, {}, 'alternate')).to eq('alternate')
74
211
  end
75
212
  end
76
213
 
77
214
  context 'when doing interpolation in config file' do
78
- let(:fixtures) { File.join(HieraSpec::FIXTURE_DIR, 'interpolate') }
215
+ let(:hiera) { Hiera.new(:config => File.join(fixtures, 'config', 'hiera_iplm_hiera.yaml')) }
79
216
 
80
217
  it 'should allow and resolve a correctly configured interpolation using "hiera" method' do
81
- Hiera::Util.expects(:var_dir).at_least_once.returns(File.join(fixtures, 'data'))
82
- hiera = Hiera.new(:config => File.join(fixtures, 'config', 'hiera_iplm_hiera.yaml'))
83
218
  expect(hiera.lookup('foo', nil, {})).to eq('Foo')
84
219
  end
85
220
 
86
- it 'should detect interpolation recursion when using "hiera" method' do
87
- Hiera::Util.expects(:var_dir).at_least_once.returns(File.join(fixtures, 'data'))
88
- hiera = Hiera.new(:config => File.join(fixtures, 'config', 'hiera_iplm_hiera_bad.yaml'))
89
- expect{ hiera.lookup('foo', nil, {}) }.to raise_error(Hiera::InterpolationLoop, "Lookup recursion detected in [hiera('role')]")
90
- end
91
-
92
221
  it 'should issue warning when interpolation methods are used' do
93
222
  Hiera.expects(:warn).with('Use of interpolation methods in hiera configuration file is deprecated').at_least_once
94
- Hiera::Util.expects(:var_dir).at_least_once.returns(File.join(fixtures, 'data'))
95
- hiera = Hiera.new(:config => File.join(fixtures, 'config', 'hiera_iplm_hiera.yaml'))
96
223
  expect(hiera.lookup('foo', nil, {})).to eq('Foo')
97
224
  end
98
225
  end
226
+
227
+ context 'when doing interpolation in bad config file' do
228
+ let(:hiera) { Hiera.new(:config => File.join(fixtures, 'config', 'hiera_iplm_hiera_bad.yaml')) }
229
+
230
+ it 'should detect interpolation recursion when using "hiera" method' do
231
+ expect{ hiera.lookup('foo', nil, {}) }.to raise_error(Hiera::InterpolationLoop, "Lookup recursion detected in [hiera('role')]")
232
+ end
233
+ end
99
234
  end
metadata CHANGED
@@ -1,32 +1,36 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hiera
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.1.1
5
+ prerelease:
5
6
  platform: x64-mingw32
6
7
  authors:
7
8
  - Puppet Labs
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2016-03-11 00:00:00.000000000 Z
12
+ date: 2016-03-23 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: json_pure
15
16
  requirement: !ruby/object:Gem::Requirement
17
+ none: false
16
18
  requirements:
17
- - - '>='
19
+ - - ! '>='
18
20
  - !ruby/object:Gem::Version
19
21
  version: '0'
20
22
  type: :runtime
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
23
26
  requirements:
24
- - - '>='
27
+ - - ! '>='
25
28
  - !ruby/object:Gem::Version
26
29
  version: '0'
27
30
  - !ruby/object:Gem::Dependency
28
31
  name: win32-dir
29
32
  requirement: !ruby/object:Gem::Requirement
33
+ none: false
30
34
  requirements:
31
35
  - - ~>
32
36
  - !ruby/object:Gem::Version
@@ -34,6 +38,7 @@ dependencies:
34
38
  type: :runtime
35
39
  prerelease: false
36
40
  version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
37
42
  requirements:
38
43
  - - ~>
39
44
  - !ruby/object:Gem::Version
@@ -75,11 +80,15 @@ files:
75
80
  - spec/unit/fixtures/interpolate/config/hiera.yaml
76
81
  - spec/unit/fixtures/interpolate/config/hiera_iplm_hiera.yaml
77
82
  - spec/unit/fixtures/interpolate/config/hiera_iplm_hiera_bad.yaml
83
+ - spec/unit/fixtures/interpolate/data/bad_interpolation.yaml
84
+ - spec/unit/fixtures/interpolate/data/complex.yaml
85
+ - spec/unit/fixtures/interpolate/data/dotted_keys.yaml
78
86
  - spec/unit/fixtures/interpolate/data/empty_interpolation.yaml
79
87
  - spec/unit/fixtures/interpolate/data/frontend.json
80
88
  - spec/unit/fixtures/interpolate/data/niltest.yaml
81
89
  - spec/unit/fixtures/interpolate/data/recursive.yaml
82
90
  - spec/unit/fixtures/interpolate/data/role.json
91
+ - spec/unit/fixtures/interpolate/data/weird_keys.yaml
83
92
  - spec/unit/fixtures/override/config/hiera.yaml
84
93
  - spec/unit/fixtures/override/data/alternate.yaml
85
94
  - spec/unit/fixtures/override/data/common.yaml
@@ -90,26 +99,27 @@ files:
90
99
  - spec/unit/version_spec.rb
91
100
  homepage: https://github.com/puppetlabs/hiera
92
101
  licenses: []
93
- metadata: {}
94
102
  post_install_message:
95
103
  rdoc_options: []
96
104
  require_paths:
97
105
  - lib
98
106
  required_ruby_version: !ruby/object:Gem::Requirement
107
+ none: false
99
108
  requirements:
100
- - - '>='
109
+ - - ! '>='
101
110
  - !ruby/object:Gem::Version
102
111
  version: '0'
103
112
  required_rubygems_version: !ruby/object:Gem::Requirement
113
+ none: false
104
114
  requirements:
105
- - - '>='
115
+ - - ! '>='
106
116
  - !ruby/object:Gem::Version
107
117
  version: '0'
108
118
  requirements: []
109
119
  rubyforge_project:
110
- rubygems_version: 2.0.14
120
+ rubygems_version: 1.8.23
111
121
  signing_key:
112
- specification_version: 4
122
+ specification_version: 3
113
123
  summary: Light weight hierarchical data store
114
124
  test_files:
115
125
  - spec/spec_helper.rb
@@ -123,11 +133,15 @@ test_files:
123
133
  - spec/unit/fixtures/interpolate/config/hiera.yaml
124
134
  - spec/unit/fixtures/interpolate/config/hiera_iplm_hiera.yaml
125
135
  - spec/unit/fixtures/interpolate/config/hiera_iplm_hiera_bad.yaml
136
+ - spec/unit/fixtures/interpolate/data/bad_interpolation.yaml
137
+ - spec/unit/fixtures/interpolate/data/complex.yaml
138
+ - spec/unit/fixtures/interpolate/data/dotted_keys.yaml
126
139
  - spec/unit/fixtures/interpolate/data/empty_interpolation.yaml
127
140
  - spec/unit/fixtures/interpolate/data/frontend.json
128
141
  - spec/unit/fixtures/interpolate/data/niltest.yaml
129
142
  - spec/unit/fixtures/interpolate/data/recursive.yaml
130
143
  - spec/unit/fixtures/interpolate/data/role.json
144
+ - spec/unit/fixtures/interpolate/data/weird_keys.yaml
131
145
  - spec/unit/fixtures/override/config/hiera.yaml
132
146
  - spec/unit/fixtures/override/data/alternate.yaml
133
147
  - spec/unit/fixtures/override/data/common.yaml
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: d13558560b89acbbd6720376162e7b5e7352c541
4
- data.tar.gz: 6fd01d4e6590e18449bc6a70a43c46288e55e7ce
5
- SHA512:
6
- metadata.gz: 69785d29b404ab6eca305dfa70167e8efdf7f72dc806938eb852bac48541118e197a857b6c59496583bd48c07816a116721d286738b2692b07863bbf96f62794
7
- data.tar.gz: 0a5dfdc722e1c800339811f74a6e76354b380681f6d727f33285e383ff2a049bac1acaaface1705afea3e8c4e3f8cf205f7d935157f95419962593646877d39c