Puppet Function: values_at

Defined in:
modules/stdlib/lib/puppet/parser/functions/values_at.rb
Function type:
Ruby 3.x API

Overview

values_at()Any

The first argument is the array you want to analyze, and the second element can be a combination of:

  • A single numeric index

  • A range in the form of 'start-stop' (eg. 4-9)

  • An array combining the above

> Note: Since Puppet 4.0.0 it is possible to slice an array with index and count directly in the language. A negative value is taken to be “from the end” of the array:

`['a', 'b', 'c', 'd'][1, 2]` results in `['b', 'c']` `['a', 'b', 'c', 'd'][2, -1]` results in `['c', 'd']` `['a', 'b', 'c', 'd'][1, -2]` results in `['b', 'c']`

Examples:

*Usage*


values_at(['a','b','c'], 2)
Would return ['c']

values_at(['a','b','c'], ["0-1"])
Would return ['a','b']

values_at(['a','b','c','d','e'], [0, "2-3"])
Would return ['a','c','d']

Returns:

  • (Any)

    an array of values identified by location



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'modules/stdlib/lib/puppet/parser/functions/values_at.rb', line 5

newfunction(:values_at, :type => :rvalue, :doc => <<-DOC
  @summary
    Finds value inside an array based on location.

  The first argument is the array you want to analyze, and the second element can
  be a combination of:

  * A single numeric index
  * A range in the form of 'start-stop' (eg. 4-9)
  * An array combining the above

  @return
    an array of values identified by location

  @example **Usage**

    values_at(['a','b','c'], 2)
    Would return ['c']

    values_at(['a','b','c'], ["0-1"])
    Would return ['a','b']

    values_at(['a','b','c','d','e'], [0, "2-3"])
    Would return ['a','c','d']

  > *Note:*
  Since Puppet 4.0.0 it is possible to slice an array with index and count directly in the language.
  A negative value is taken to be "from the end" of the array:

  `['a', 'b', 'c', 'd'][1, 2]`   results in `['b', 'c']`
  `['a', 'b', 'c', 'd'][2, -1]`  results in `['c', 'd']`
  `['a', 'b', 'c', 'd'][1, -2]`  results in `['b', 'c']`

  DOC
           ) do |arguments|

  raise(Puppet::ParseError, "values_at(): Wrong number of arguments given (#{arguments.size} for 2)") if arguments.size < 2

  array = arguments.shift

  unless array.is_a?(Array)
    raise(Puppet::ParseError, 'values_at(): Requires array to work with')
  end

  indices = [arguments.shift].flatten # Get them all ... Pokemon ...

  if !indices || indices.empty?
    raise(Puppet::ParseError, 'values_at(): You must provide at least one positive index to collect')
  end

  indices_list = []

  indices.each do |i|
    i = i.to_s
    m = i.match(%r{^(\d+)(\.\.\.?|\-)(\d+)$})
    if m
      start = m[1].to_i
      stop  = m[3].to_i

      type = m[2]

      raise(Puppet::ParseError, 'values_at(): Stop index in given indices range is smaller than the start index') if start > stop
      raise(Puppet::ParseError, 'values_at(): Stop index in given indices range exceeds array size') if stop > array.size - 1 # First element is at index 0 is it not?

      range = case type
              when %r{^(\.\.|\-)$} then (start..stop)
              when %r{^(\.\.\.)$}  then (start...stop) # Exclusive of last element ...
              end

      range.each { |i| indices_list << i.to_i } # rubocop:disable Lint/ShadowingOuterLocalVariable : Value is meant to be shadowed
    else
      # Only positive numbers allowed in this case ...
      unless i =~ %r{^\d+$}
        raise(Puppet::ParseError, 'values_at(): Unknown format of given index')
      end

      # In Puppet numbers are often string-encoded ...
      i = i.to_i

      if i > array.size - 1 # Same story.  First element is at index 0 ...
        raise(Puppet::ParseError, 'values_at(): Given index exceeds array size')
      end

      indices_list << i
    end
  end

  # We remove nil values as they make no sense in Puppet DSL ...
  result = indices_list.map { |i| array[i] }.compact

  return result
end