Flexible data types
These abstract data types can match values with a variety of concrete data types.
Some of them are similar to a concrete type but offer alternate ways to restrict
them (for example, Enum
), and some of them let
you combine types and match a union of what they would individually match (for
example, Variant
and Optional
).
The Optional
data type
The Optional
data type
wraps one other data type, and results in a
data type that matches anything that type would
match plusundef
. This is useful for matching
values that are allowed to be absent. It takes one required
parameter.
The full signature for Optional
is:
Optional[<DATA TYPE>]
Position | Parameter | Data type | Default value | Description |
---|---|---|---|---|
1 | Data type | Type or String | none (you must specify a value) | The data type to add undef to. |
If you specify a string "my string"
as
the parameter, it's equivalent to using Optional[Enum["my string"]]
— it matches only
that exact string value or undef
.
Optional[<DATA TYPE>]
is
equivalent to Variant[ <DATA
TYPE>, Undef ]
.
Examples:
Optional[String]
undef
. Optional[Array[Integer[0,
10]]]
undef
.
Optional["present"]
"present"
or undef
. The NotUndef
data type
The NotUndef
type matches any
value except undef
. It can also wrap one other data type, resulting in
a type that matches anything the original type would match
except undef
. It
accepts one optional parameter.
The full signature for NotUndef
is:
NotUndef[<DATA TYPE>]
Position | Parameter | Data type | Default value | Description |
---|---|---|---|---|
1 | Data type | Type or String | Any | The data type to subtract undef from. |
If you specify a string as a parameter for NotUndef
, it's equivalent to
writing NotUndef[Enum["my
string"]]
— it matches only that exact string
value. This doesn’t actually subtract anything, because
the Enum
wouldn’t have
matched undef
anyway, but it's a convenient notation for
mandatory keys in Struct
schema hashes.
The Variant
data type
The Variant
data type combines
any number of other data types, and results in a type that matches
the union of what any of those data types would match. It
takes any number of parameters, and requires at least one.
The full signature for Variant
is:
Variant[ <DATA TYPE>, (<DATA TYPE, ...) ]
Position | Parameter | Data type | Default value | Description |
---|---|---|---|---|
1 and up | Data type | Type | none (required) | A data type to add to the resulting compound data type. You must provide at least one data type parameter, and can provide any number of additional ones. |
Examples:
Variant[Integer,
Float]
Numeric
). Variant[Enum['true',
'false'], Boolean]
'true'
, 'false'
, true
, or false
. The Pattern
data type
The Pattern data type only matches strings, but it provides an alternate way to restrict which strings it matches. It takes any number of regular expressions, and results in a data type that matches any strings that would match any of those regular expressions. It takes any number of parameters, and requires at least one.
The full signature for Pattern is:
Pattern[ <REGULAR EXPRESSION>, (<REGULAR EXPRESSION>, ...) ]
Position | Parameter | Data type | Default value | Description |
---|---|---|---|---|
1 and up | Regular expression | Regexp | none (required) | A regular expression describing a set of strings that the resulting data type matches. You must provide at least one regular expression parameter, and can provide any number of additional ones. |
You can use capture groups in the regular expressions, but they won’t
cause any variables, like $1
, to be set.
Examples:
Pattern[/\A[a-z].*/]
Pattern[/\A[a-z].*/,
/\ANone\Z/]
None
.
The Enum
data type
The Enum
data type only matches strings,
but it provides an alternate way to restrict which strings it
matches. It takes any number of strings, and results in a data type
that matches any string values that exactly match one of those
strings. Unlike the ==
operator,
this matching is case-sensitive. It takes any number of parameters,
and requires at least one.
The full signature for Enum
is:
Enum[ <OPTION>, (<OPTION>, ...) ]
Position | Parameter | Data type | Default value | Description |
---|---|---|---|---|
1 and up | Option | String | none (required) | One of the literal string values that the resulting data type matches. You must provide at least one option parameter, and can provide any number of additional ones. |
Examples:
Enum['stopped',
'running']
'stopped'
and 'running'
, and no other
values. Enum['true',
'false']
'true'
and 'false'
, and no other values. Does not
match the boolean values true
or false
(without quotes). The Tuple
data type
The Tuple
type only matches arrays, but
it lets you specify different data types for every element of the
array, in order. It takes any number of parameters, and requires at
least one.
The full signature for Tuple
is:
Tuple[ <CONTENT TYPE>, (<CONTENT TYPE>, ..., <MIN SIZE>, <MAX SIZE>) ]
Position | Parameter | Data type | Default value | Description |
---|---|---|---|---|
1 and up | Content type | Type | none (required) | What kind of values the array contains at the given position. You must provide at least one content type parameter, and can provide any number of additional ones. |
-2 (second-last) | Minimum size | Integer | number of content types | The minimum number of elements in the
array. If this is smaller than the number of
content types you provided, any elements beyond
the minimum are optional; however, if present,
they must still match the provided content types.
This parameter accepts the value default , but this won’t
use the default value; instead, it means 0 (all
elements optional). |
-1 (last) | Maximum size | Integer | number of content types | The maximum number of elements in the array.
You cannot specify a maximum without also
specifying a minimum. If the maximum is larger
than the number of content types you provided, it
means the array can contain any number of
additional elements, which all must match the last
content type. This parameter accepts the value
Don't set the maximum smaller than the number of content types you provide. |
Examples:
Tuple[String,
Integer]
["hi", 2]
. Tuple[String, Integer,
1]
Tuple[String, Integer, 1,
4]
Tuple[String, Integer, 1,
default]
The Struct
data type
The Struct
type only
matches hashes, but it lets you specify:
The name of every allowed key.
Whether each key is required or optional.
The allowed data type for each of those keys’ values.
It takes one mandatory parameter.
The full signature for Struct
is:
Struct[<SCHEMA HASH>]
Position | Parameter | Data type | Default value | Description |
---|---|---|---|---|
1 | Schema hash | Hash[Variant[String,
Optional, NotUndef], Type] | none (required) | A hash that has all of the allowed keys and data types for the struct. |
A Struct
’s schema hash must have the same
keys as the hashes it matches. Each value must be a data type that
matches the allowed values for that key.
The keys in a schema hash are usually strings. They can also be an
Optional
or NotUndef
type with the key’s name as
their parameter.
If a key is a string, Puppet uses the
value’s type to determine whether it’s optional —
because accessing a missing key resolves to the value undef
, the key is optional if the
value type accepts undef
(like
Optional[Array]
).
Note that this doesn’t distinguish between an explicit value of undef
and an absent key. If you want
to be more explicit, you can use Optional['my_key']
to indicate that a key can be
absent, and NotUndef['my_key']
to
make it mandatory. If you use one of these, a value type that
accepts undef
is only used to decide
about explicit undef
values, not
missing keys.
The following example Struct
matches
hashes like {mode => 'read', path =>
'/etc/fstab'}
. Both the mode
and path
keys
are mandatory; mode
’s value must be
one of 'read'
, 'write'
, or 'update'
, and path
must be a string of at least one
character:
Struct[{mode => Enum[read, write, update], path => String[1]}]
The following data type would match the same values as the previous
example, but the path
key is
optional. If present, path
must
match String[1]
or Undef
:
Struct[{mode => Enum[read, write, update], path => Optional[String[1]]}]
In the following data type, the owner
key
can be absent, but if it’s present, it must be a string; a value of
undef
isn’t
allowed:
Struct[{mode => Enum[read, write, update], path => Optional[String[1]], Optional[owner] => String[1]}]
In the following data type, the owner key is mandatory, but it allows an
explicit undef
value:
Struct[{mode => Enum[read, write, update], path => Optional[String[1]], NotUndef[owner] => Optional[String[1]]}]
The SemVer
data type
A SemVer
instance defines a single semantic version or range of
versions. For example, "1.2.3" or ">= 1.0.0 < 2.0.0".
It consists of the following five segments:
- Major version (required)
- Minor version (required)
- Patch version (required)
- Prerelease tag (optional)
- Build tag (optional)
You can create an instance of SemVer
from
a String, individual values, or a hash of individual values.
The signatures are:
type PositiveInteger = Integer[0,default] type SemVerQualifier = Pattern[/\A(?<part>[0-9A-Za-z-]+)(?:\.\g<part>)*\Z/] type SemVerString = String[1] type SemVerHash = Struct[{ major =>PositiveInteger, minor =>PositiveInteger, patch =>PositiveInteger, Optional[prerelease] =>SemVerQualifier, Optional[build] =>SemVerQualifier }] function SemVer.new(SemVerString $str) function SemVer.new( PositiveInteger $major PositiveInteger $minor PositiveInteger $patch Optional[SemVerQualifier] $prerelease = undef Optional[SemVerQualifier] $build = undef ) function SemVer.new(SemVerHash $hash_args)
Examples:
SemVer.new("1.2.3")
SemVer
instance from a stringSemVer.new(1, 2, 3, "rc4",
"5"
SemVer
instance from a list of arguments SemVer.new(major => 1,
minor => 2, patch => 3, prerelease => "rc4", build
=>"5")
SemVer
instance from a hash You can parameterize the SemVer
type to
restrict which values the type matches. The values are defined by
one or more Strings or SemVerRanges
.
The full signatures are:
SemVer[<String>]
The <String>
specifies a semantic
version string — representing a single version or range of versions.
A SemVer
instance matches the
parameterized type, if the instance is within the range defined by
the type. For example:
$t = SemVer['> 1.0.0 < 2.0.0'] notice(SemVer('1.2.3') =~ $t) # true notice(SemVer('2.3.4') =~ $t) # false
SemVer[ <SemVerRange>, ( <SemVerRange>, ... ) ]
The SemVer
type is accompanied by the
SemVerRange
type, which you
can define to restrict matches to a contiguous version range. For
example:
$t = SemVer[SemVerRange('>=1.0.0 <2.0.0')] notice(SemVer('1.2.3') =~ $t) # true notice(SemVer('2.3.4') =~ $t) # false
When you define a parameterized SemVer
type using multiple ranges, and the instance is enclosed in at least
one of the ranges, the SemVer
instance matches the type.
$t = SemVer[SemVerRange('>=1.0.0 <2.0.0'), SemVerRange('>=3.0.0 <4.0.0')] notice(SemVer('1.2.3') =~ $t) # true notice(SemVer('2.5.0') =~ $t) # false notice(SemVer('3.0.0') =~ $t) # true
If any of the ranges are adjacent or overlap, they get normalized (merged). For example, the following are equal:
SemVer['>=1.0.0 <4.0.0'] SemVer[SemVerRange('>=1.0.0 <3.0.0'), SemVerRange('>=2.0.0 <4.0.0')] # overlap SemVer[SemVerRange('>=1.0.0 <2.0.0'), SemVerRange('>=2.0.0 <4.0.0')] # adjacent
The SemVerRange
data type
An instance of SemVerRange
represents a
contiguous semantic version range. The string format of a SemVerRange
is specified by the
SemVer Range Grammar.
The SemVerRange
type does not
support the logical or operator (||
).
You can create an instance of SemVerRange
(SemVerRange.new
) from a
String, individual values, or a hash of individual values. The
signatures
are:
type SemVerRangeString = String[1] type SemVerRangeHash = Struct[{ min => Variant[default, SemVer], Optional[max] => Variant[default, SemVer], Optional[exclude_max] => Boolean }] function SemVerRange.new(SemVerRangeString $semver_range_string) function SemVerRange.new( Variant[default,SemVer] $min Variant[default,SemVer] $max Optional[Boolean] $exclude_max = undef } function SemVerRange.new(SemVerRangeHash $semver_range_hash)
Examples:
SemVerRange.new(">1.0.0"))
SemVerRange
from a StringSemVerRange.new(SemVer.new("1.0.0"),
SemVer.new("2.0.0"), true)
SemVerRange
instance from a list of
arguments.SemVerRange.new(min =>
SemVer.new("1.0.0"), max => SemVer.new("2.0.0"),
exclude_max => true)
SemVerRange
instance from a hash. By default, the range includes the maximum value so that the following examples are equal:
SemVerRange.new(">= 1.0.0 <= 2.0.0") SemVerRange.new(SemVer.new("1.0.0"), SemVer.new("2.0.0"))
The maximum value can be excluded so that the following examples are equal:
SemVerRange.new(">= 1.0.0 < 2.0.0") SemVerRange.new(SemVer.new("1.0.0"), SemVer.new("2.0.0"), true)
Unlike the SemVer
type, you cannot
paramatize the SemVerRange
type, as
it represents all semantic version ranges.