Puppet Function: simplib::rand_cron

Defined in:
lib/puppet/functions/simplib/rand_cron.rb
Function type:
Ruby 4.x API

Overview

simplib::rand_cron(String $modifier, RandCronAlgorithm $algorithm, Optional[Integer[1]] $occurs, Optional[Integer[1]] $max_value)Array[Integer]

Transforms an input string to one or more interval values for ‘cron`.

This can be used to avoid starting a certain cron job at the same
time on all servers.

Examples:

Generate one value for the ‘minute` cron interval using

the 'sha256' algorithm

rand_cron('myhost.test.local','sha256')

Generate 2 values for the ‘minute` cron interval using

the 'sha256' algorithm applied to the numeric representation of
an IP

rand_cron('10.0.23.45', 'sha256')

Generate 2 values for the ‘hour` cron interval, using the

'ip_mod' algorithm

rand_cron('10.0.6.78', 'ip_mod', 2, 23)

Parameters:

  • modifier (String)

    The input string to use as the basis for the generated values.

  • algorithm (RandCronAlgorithm)

    Randomization algorithm to apply to transform the input string.

    When ‘sha256’, a random number generated from the input string via sha256 is used as the basis for the returned values. If the input string is an IP address, this algorithm works well to create cron job intervals for multiple hosts, when the number of hosts is less than the ‘max_value` or the hosts do not have linearly-assigned IP addresses.

    When ‘ip_mod’ and the input string is an IP address, the modulus of the numeric IP is used as the basis for the returned values. This algorithm works well to create cron job intervals for multiple hosts, when the number of hosts exceeds the ‘max_value` and the hosts have linearly-assigned IP addresses.

    When ‘ip_mod’ and the input string is not an IP address, for backward compatibility, the crc32 of the input string will be used as the basis for the returned values.

    When ‘crc32’, the crc32 of the input string will be used as the basis for the returned values.

  • occurs (Optional[Integer[1]])

    The occurrence within an interval, i.e., the number of values to be generated for the interval. Defaults to ‘1`.

  • max_value (Optional[Integer[1]])

    The maximum value for the interval. The values generated will be in the inclusive range [0, max_value]. Defaults to ‘60` for use in the `minute` cron field.

Returns:

  • (Array[Integer])

    Array of integers suitable for use in the “minute“ or “hour“ cron field.



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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/puppet/functions/simplib/rand_cron.rb', line 5

Puppet::Functions.create_function(:'simplib::rand_cron') do

  local_types do
    type "RandCronAlgorithm = Enum['crc32', 'ip_mod', 'sha256']"
  end

  # @param modifier
  #   The input string to use as the basis for the generated values.
  #
  # @param algorithm
  #   Randomization algorithm to apply to transform the input string.
  #
  #   When 'sha256', a random number generated from the input string
  #   via sha256 is used as the basis for the returned values.
  #   If the input string is an IP address, this algorithm works well to
  #   create cron job intervals for multiple hosts, when the number
  #   of hosts is less than the `max_value` or the hosts do not have
  #   linearly-assigned IP addresses.
  #
  #   When 'ip_mod' and the input string is an IP address, the modulus
  #   of the numeric IP is used as the basis for the returned values.
  #   This algorithm works well to create cron job intervals for
  #   multiple hosts, when the number of hosts exceeds the `max_value`
  #   and the hosts have linearly-assigned IP addresses.
  #
  #   When 'ip_mod' and the input string is not an IP address, for
  #   backward compatibility,  the crc32 of the input string will
  #   be used as the basis for the returned values.
  #
  #   When 'crc32', the crc32 of the input string will be used as the
  #   basis for the returned values.
  #
  # @param occurs
  #   The occurrence within an interval, i.e., the number of values to
  #   be generated for the interval. Defaults to `1`.
  #
  # @param max_value
  #   The maximum value for the interval.  The values generated will
  #   be in the inclusive range [0, max_value]. Defaults to `60` for
  #   use in the `minute` cron field.
  #
  # @return [Array[Integer]] Array of integers suitable for use in the
  #   ``minute`` or ``hour`` cron field.
  #
  # @example Generate one value for the `minute` cron interval using
  #   the 'sha256' algorithm
  #
  #   rand_cron('myhost.test.local','sha256')
  #
  # @example Generate 2 values for the `minute` cron interval using
  #   the 'sha256' algorithm applied to the numeric representation of
  #   an IP
  #
  #   rand_cron('10.0.23.45', 'sha256')
  #
  # @example Generate 2 values for the `hour` cron interval, using the
  #   'ip_mod' algorithm
  #
  #   rand_cron('10.0.6.78', 'ip_mod', 2, 23)
  #
  dispatch :rand_cron do
    required_param 'String',            :modifier
    required_param 'RandCronAlgorithm', :algorithm
    optional_param 'Integer[1]',        :occurs
    optional_param 'Integer[1]',        :max_value
  end

  def generate_crc32_number(input_string)
    require 'zlib'
    Zlib.crc32(input_string)
  end

  def generate_ip_mod_number(input_string)
    require 'ipaddr'

    ip_num = nil
    begin
     ip_num = IPAddr.new(input_string).to_i
    rescue IPAddr::Error
    end

    num = nil
    if ip_num.nil?
      # crc32 calculation for backward compatibility
      num = generate_crc32_number(input_string)
    else
      num = ip_num
    end
    num
  end

  def generate_sha256_number(input_string)
    require 'digest'

    Digest::SHA256.hexdigest(input_string).hex
  end

  # @param modifier Input string to be transformed to an Integer
  # @param algorithm Algorithm to apply to transform input string into
  #   an Integer
  #
  # @return Integer to be used as a basis for generated cron values
  def generate_numeric_modifier(modifier, algorithm)
    eval("generate_#{algorithm}_number(modifier)")
  end

  def rand_cron(modifier, algorithm, occurs = 1, max_value = 59)
    range_modifier = generate_numeric_modifier(modifier, algorithm)
    modulus = max_value + 1
    base = range_modifier % modulus

    values = []
    if occurs == 1
      values << base
    else
      values = Array.new
      (1..occurs).each do |i|
        values << ((base - (modulus / occurs * i)) % modulus)
      end
    end
    return values.sort
  end
end