feat: initial commit

This commit is contained in:
amy 2025-04-01 17:40:03 +00:00
commit 38f495e3f4
457 changed files with 40577 additions and 0 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,3 @@
# Setting ownership to the modules team
# include Trusted Contributors
* @puppetlabs/modules @alexjfisher @b4ldr @bastelfreak @ekohl @smortex @seanmil

View file

@ -0,0 +1,3 @@
# Contributing to Puppet modules
Check out our [Contributing to Supported Modules Blog Post](https://puppetlabs.github.io/iac/docs/contributing_to_a_module.html) to find all the information that you will need.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -0,0 +1,23 @@
stdlib puppet module
Copyright (C) 2011-2016 Puppet Labs, Inc.
and some parts:
Copyright (C) 2011 Krzysztof Wilczynski
Puppet Labs can be contacted at: info@puppetlabs.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -0,0 +1,593 @@
# stdlib
#### Table of Contents
1. [Overview](#overview)
1. [Module Description](#module-description)
1. [Setup](#setup)
1. [Usage](#usage)
1. [Reference](#reference)
1. [Data Types](#data-types)
1. [Facts](#facts)
1. [Limitations](#limitations)
1. [License](#license)
1. [Development](#development)
1. [Contributors](#contributors)
## Overview
This module provides a standard library of resources for Puppet modules.
## Module Description
Puppet modules make heavy use of this standard library. The stdlib module adds the following resources to Puppet:
* Stages
* Facts
* Functions
* Defined types
* Data types
* Providers
> *Note:* As of version 3.7, Puppet Enterprise no longer includes the stdlib module. If you're running Puppet Enterprise, you should install the most recent release of stdlib for compatibility with Puppet modules.
## Setup
[Install](https://puppet.com/docs/puppet/latest/modules_installing.html) the stdlib module to add the functions, facts, and resources of this standard library to Puppet.
If you are authoring a module that depends on stdlib, be sure to [specify dependencies](https://puppet.com/docs/puppet/latest/modules_installing.html) in your metadata.json.
## Usage
Most of stdlib's features are automatically loaded by Puppet. To use standardized run stages in Puppet, declare this class in your manifest with `include stdlib`.
When declared, stdlib declares all other classes in the module. This currently consists of `stdlib::manage` and `stdlib::stages`.
The `stdlib::stages` class declares various run stages for deploying infrastructure, language runtimes, and application layers. The high level stages are (in order):
* setup
* main
* runtime
* setup_infra
* deploy_infra
* setup_app
* deploy_app
* deploy
Sample usage:
```puppet
node default {
include stdlib
class { java: stage => 'runtime' }
}
```
The `stdlib::manage` class provides an interface for generating trivial resource declarations via the `create_resources` parameter. Depending on your usage, you may want to set `hiera`'s `lookup_options` for the `stdlib::manage::create_resources:` element.
```yaml
---
stdlib::manage::create_resources:
file:
/etc/somefile:
ensure: file
owner: root
group: root
package:
badpackage:
ensure: absent
```
## Reference
For information on the classes and types, see the [REFERENCE.md](https://github.com/puppetlabs/puppetlabs-stdlib/blob/main/REFERENCE.md).
<a id="data-types"></a>
### Data types
#### `Stdlib::Absolutepath`
A strict absolute path type. Uses a variant of Unixpath and Windowspath types.
Acceptable input examples:
```shell
/var/log
```
```shell
/usr2/username/bin:/usr/local/bin:/usr/bin:.
```
```shell
C:\\WINDOWS\\System32
```
Unacceptable input example:
```shell
../relative_path
```
#### `Stdlib::Ensure::Service`
Matches acceptable ensure values for service resources.
Acceptable input examples:
```shell
stopped
running
```
Unacceptable input example:
```shell
true
false
```
#### `Stdlib::HTTPSUrl`
Matches HTTPS URLs. It is a case insensitive match.
Acceptable input example:
```shell
https://hello.com
HTTPS://HELLO.COM
```
Unacceptable input example:
```shell
httds://notquiteright.org`
```
#### `Stdlib::HTTPUrl`
Matches both HTTPS and HTTP URLs. It is a case insensitive match.
Acceptable input example:
```shell
https://hello.com
http://hello.com
HTTP://HELLO.COM
```
Unacceptable input example:
```shell
httds://notquiteright.org
```
#### `Stdlib::MAC`
Matches MAC addresses defined in [RFC5342](https://tools.ietf.org/html/rfc5342).
#### `Stdlib::Unixpath`
Matches absolute paths on Unix operating systems.
Acceptable input example:
```shell
/usr2/username/bin:/usr/local/bin:/usr/bin:
/var/tmp
```
Unacceptable input example:
```shell
C:/whatever
some/path
../some/other/path
```
#### `Stdlib::Filemode`
Matches octal file modes consisting of one to four numbers and symbolic file modes.
Acceptable input examples:
```shell
0644
```
```shell
1777
```
```shell
a=Xr,g=w
```
Unacceptable input examples:
```shell
x=r,a=wx
```
```shell
0999
```
#### `Stdlib::Windowspath`
Matches paths on Windows operating systems.
Acceptable input example:
```shell
C:\\WINDOWS\\System32
C:\\
\\\\host\\windows
```
Valid values: A windows filepath.
#### `Stdlib::Filesource`
Matches paths valid values for the source parameter of the Puppet file type.
Acceptable input example:
```shell
http://example.com
https://example.com
file:///hello/bla
```
Valid values: A filepath.
#### `Stdlib::Fqdn`
Matches paths on fully qualified domain name.
Acceptable input example:
```shell
localhost
example.com
www.example.com
```
Valid values: Domain name of a server.
#### `Stdlib::Host`
Matches a valid host which could be a valid ipv4, ipv6 or fqdn.
Acceptable input example:
```shell
localhost
www.example.com
192.0.2.1
```
Valid values: An IP address or domain name.
#### `Stdlib::Port`
Matches a valid TCP/UDP Port number.
Acceptable input examples:
```shell
80
443
65000
```
Valid values: An Integer.
#### `Stdlib::Port::Privileged`
Matches a valid TCP/UDP Privileged port i.e. < 1024.
Acceptable input examples:
```shell
80
443
1023
```
Valid values: A number less than 1024.
#### `Stdlib::Port::Unprivileged`
Matches a valid TCP/UDP Privileged port i.e. >= 1024.
Acceptable input examples:
```shell
1024
1337
65000
```
Valid values: A number more than or equal to 1024.
#### `Stdlib::Base32`
Matches paths a valid base32 string.
Acceptable input example:
```shell
ASDASDDASD3453453
asdasddasd3453453=
ASDASDDASD3453453==
```
Valid values: A base32 string.
#### `Stdlib::Base64`
Matches paths a valid base64 string.
Acceptable input example:
```shell
asdasdASDSADA342386832/746+=
asdasdASDSADA34238683274/6+
asdasdASDSADA3423868327/46+==
```
Valid values: A base64 string.
#### `Stdlib::Ipv4`
This type is no longer available. To make use of this functionality, use [Stdlib::IP::Address::V4](https://github.com/puppetlabs/puppetlabs-stdlib#stdlibipaddressv4).
#### `Stdlib::Ipv6`
This type is no longer available. To make use of this functionality, use [Stdlib::IP::Address::V6](https://github.com/puppetlabs/puppetlabs-stdlib#stdlibipaddressv6).
#### `Stdlib::Ip_address`
This type is no longer available. To make use of this functionality, use [Stdlib::IP::Address](https://github.com/puppetlabs/puppetlabs-stdlib#stdlibipaddress)
#### `Stdlib::IP::Address`
Matches any IP address, including both IPv4 and IPv6 addresses. It will match them either with or without an address prefix as used in CIDR format IPv4 addresses.
Examples:
```
'127.0.0.1' =~ Stdlib::IP::Address # true
'10.1.240.4/24' =~ Stdlib::IP::Address # true
'52.10.10.141' =~ Stdlib::IP::Address # true
'192.168.1' =~ Stdlib::IP::Address # false
'FEDC:BA98:7654:3210:FEDC:BA98:7654:3210' =~ Stdlib::IP::Address # true
'FF01:0:0:0:0:0:0:101' =~ Stdlib::IP::Address # true
```
#### `Stdlib::IP::Address::V4`
Match any string consisting of an IPv4 address in the quad-dotted decimal format, with or without a CIDR prefix. It will not match any abbreviated form (for example, 192.168.1) because these are poorly documented and inconsistently supported.
Examples:
```
'127.0.0.1' =~ Stdlib::IP::Address::V4 # true
'10.1.240.4/24' =~ Stdlib::IP::Address::V4 # true
'192.168.1' =~ Stdlib::IP::Address::V4 # false
'FEDC:BA98:7654:3210:FEDC:BA98:7654:3210' =~ Stdlib::IP::Address::V4 # false
'12AB::CD30:192.168.0.1' =~ Stdlib::IP::Address::V4 # false
```
Valid values: An IPv4 address.
#### `Stdlib::IP::Address::V6`
Match any string consisting of an IPv6 address in any of the documented formats in RFC 2373, with or without an address prefix.
Examples:
```
'127.0.0.1' =~ Stdlib::IP::Address::V6 # false
'10.1.240.4/24' =~ Stdlib::IP::Address::V6 # false
'FEDC:BA98:7654:3210:FEDC:BA98:7654:3210' =~ Stdlib::IP::Address::V6 # true
'FF01:0:0:0:0:0:0:101' =~ Stdlib::IP::Address::V6 # true
'FF01::101' =~ Stdlib::IP::Address::V6 # true
```
Valid values: An IPv6 address.
#### `Stdlib::IP::Address::Nosubnet`
Match the same things as the `Stdlib::IP::Address` alias, except it will not match an address that includes an address prefix (for example, it will match '192.168.0.6' but not '192.168.0.6/24').
Valid values: An IP address with no subnet.
#### `Stdlib::IP::Address::V4::CIDR`
Match an IPv4 address in the CIDR format. It will only match if the address contains an address prefix (for example, it will match '192.168.0.6/24'
but not '192.168.0.6').
Valid values: An IPv4 address with a CIDR provided eg: '192.186.8.101/105'. This will match anything inclusive of '192.186.8.101' to '192.168.8.105'.
#### `Stdlib::IP::Address::V4::Nosubnet`
Match an IPv4 address only if the address does not contain an address prefix (for example, it will match '192.168.0.6' but not '192.168.0.6/24').
Valid values: An IPv4 address with no subnet.
#### `Stdlib::IP::Address::V6::Full`
Match an IPv6 address formatted in the "preferred form" as documented in section 2.2 of [RFC 2373](https://www.ietf.org/rfc/rfc2373.txt), with or without an address prefix as documented in section 2.3 of [RFC 2373](https://www.ietf.org/rfc/rfc2373.txt).
#### `Stdlib::IP::Address::V6::Alternate`
Match an IPv6 address formatted in the "alternative form" allowing for representing the last two 16-bit pieces of the address with a quad-dotted decimal, as documented in section 2.2.1 of [RFC 2373](https://www.ietf.org/rfc/rfc2373.txt). It will match addresses with or without an address prefix as documented in section 2.3 of [RFC 2373](https://www.ietf.org/rfc/rfc2373.txt).
#### `Stdlib::IP::Address::V6::Compressed`
Match an IPv6 address which may contain `::` used to compress zeros as documented in section 2.2.2 of [RFC 2373](https://www.ietf.org/rfc/rfc2373.txt). It will match addresses with or without an address prefix as documented in section 2.3 of [RFC 2373](https://www.ietf.org/rfc/rfc2373.txt).
#### `Stdlib::IP::Address::V6::Nosubnet`
Alias to allow `Stdlib::IP::Address::V6::Nosubnet::Full`, `Stdlib::IP::Address::V6::Nosubnet::Alternate` and `Stdlib::IP::Address::V6::Nosubnet::Compressed`.
#### `Stdlib::IP::Address::V6::Nosubnet::Full`
Match an IPv6 address formatted in the "preferred form" as documented in section 2.2 of [RFC 2373](https://www.ietf.org/rfc/rfc2373.txt). It will not match addresses with address prefix as documented in section 2.3 of [RFC 2373](https://www.ietf.org/rfc/rfc2373.txt).
#### `Stdlib::IP::Address::V6::Nosubnet::Alternate`
Match an IPv6 address formatted in the "alternative form" allowing for representing the last two 16-bit pieces of the address with a quad-dotted decimal, as documented in section 2.2.1 of [RFC 2373](https://www.ietf.org/rfc/rfc2373.txt). It will only match addresses without an address prefix as documented in section 2.3 of [RFC 2373](https://www.ietf.org/rfc/rfc2373.txt).
#### `Stdlib::IP::Address::V6::Nosubnet::Compressed`
Match an IPv6 address which may contain `::` used to compress zeros as documented in section 2.2.2 of [RFC 2373](https://www.ietf.org/rfc/rfc2373.txt). It will only match addresses without an address prefix as documented in section 2.3 of [RFC 2373](https://www.ietf.org/rfc/rfc2373.txt).
#### `Stdlib::IP::Address::V6::CIDR`
Match an IPv6 address in the CIDR format. It will only match if the address contains an address prefix (for example, it will match 'FF01:0:0:0:0:0:0:101/32', 'FF01::101/60', '::/0',
but not 'FF01:0:0:0:0:0:0:101', 'FF01::101', '::').
#### `Stdlib::ObjectStore`
Matches cloud object store uris.
Acceptable input example:
```shell
s3://mybucket/path/to/file
gs://bucket/file
```
Valid values: cloud object store uris.
#### `Stdlib::ObjectStore::GSUri`
Matches Google Cloud object store uris.
Acceptable input example:
```shell
gs://bucket/file
gs://bucket/path/to/file
```
Valid values: Google Cloud object store uris.
#### `Stdlib::ObjectStore::S3Uri`
Matches Amazon Web Services S3 object store uris.
Acceptable input example:
```shell
s3://bucket/file
s3://bucket/path/to/file
```
Valid values: Amazon Web Services S3 object store uris.
#### `Stdlib::Syslogfacility`
An enum that defines all syslog facilities defined in [RFC5424](https://tools.ietf.org/html/rfc5424). This is based on work in the [voxpupuli/nrpe](https://github.com/voxpupuli/puppet-nrpe/commit/5700fd4f5bfc3e237195c8833039f9ed1045cd6b) module.
<a id="facts"></a>
### Facts
#### `package_provider`
Returns the default provider Puppet uses to manage packages on this system.
#### `is_pe`
Returns whether Puppet Enterprise is installed. Does not report anything on platforms newer than PE 3.x.
#### `pe_version`
Returns the version of Puppet Enterprise installed. Does not report anything on platforms newer than PE 3.x.
#### `pe_major_version`
Returns the major version Puppet Enterprise that is installed. Does not report anything on platforms newer than PE 3.x.
#### `pe_minor_version`
Returns the minor version of Puppet Enterprise that is installed. Does not report anything on platforms newer than PE 3.x.
#### `pe_patch_version`
Returns the patch version of Puppet Enterprise that is installed.
#### `puppet_vardir`
Returns the value of the Puppet vardir setting for the node running Puppet or Puppet agent.
#### `puppet_environmentpath`
Returns the value of the Puppet environment path settings for the node running Puppet or Puppet agent.
#### `puppet_server`
Returns the Puppet agent's `server` value, which is the hostname of the Puppet server with which the agent should communicate.
#### `root_home`
Determines the root home directory.
Determines the root home directory, which depends on your operating system. Generally this is '/root'.
#### `service_provider`
Returns the default provider Puppet uses to manage services on this system
## Limitations
As of Puppet Enterprise 3.7, the stdlib module is no longer included in PE. PE users should install the most recent release of stdlib for compatibility with Puppet modules.
For an extensive list of supported operating systems, see [metadata.json](https://github.com/puppetlabs/puppetlabs-stdlib/blob/main/metadata.json)
## License
This codebase is licensed under the Apache2.0 licensing, however due to the nature of the codebase the open source dependencies may also use a combination of [AGPL](https://www.gnu.org/licenses/agpl-3.0.en.html), [BSD-2](https://opensource.org/license/bsd-2-claus), [BSD-3](https://opensource.org/license/bsd-3-claus), [GPL2.0](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html), [LGPL](https://opensource.org/license/lgpl-3-0/), [MIT](https://opensource.org/license/mit/) and [MPL](https://opensource.org/license/mpl-2-0/) Licensing.
## Development
Puppet modules on the Puppet Forge are open projects, and community contributions are essential for keeping them great. We cant access the huge number of platforms and myriad hardware, software, and deployment configurations that Puppet is intended to serve. We want to keep it as easy as possible to contribute changes so that our modules work in your environment. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things. For more information, see our [module contribution guide](https://github.com/puppetlabs/puppetlabs-stdlib/blob/main/CONTRIBUTING.md).
To report or research a bug with any part of this module, please go to [https://github.com/puppetlabs/puppetlabs-stdlib/issues](https://github.com/puppetlabs/puppetlabs-stdlib/issues).
## Contributors
The list of contributors can be found at: [https://github.com/puppetlabs/puppetlabs-stdlib/graphs/contributors](https://github.com/puppetlabs/puppetlabs-stdlib/graphs/contributors).

View file

@ -0,0 +1,35 @@
Puppet Specific Facts
=====================
Facter is meant to stand alone and apart from Puppet. However, Facter often
runs inside Puppet and all custom facts included in the stdlib module will
almost always be evaluated in the context of Puppet and Facter working
together.
Still, we don't want to write custom facts that blow up in the users face if
Puppet is not loaded in memory. This is often the case if the user runs
`facter` without also supplying the `--puppet` flag.
Ah! But Jeff, the custom fact won't be in the `$LOAD_PATH` unless the user
supplies `--facter`! You might say...
Not (always) true I say! If the user happens to have a CWD of
`<modulepath>/stdlib/lib` then the facts will automatically be evaluated and
blow up.
In any event, it's pretty easy to write a fact that has no value if Puppet is
not loaded. Simply do it like this:
Facter.add(:node_vardir) do
setcode do
# This will be nil if Puppet is not available.
Facter::Util::PuppetSettings.with_puppet do
Puppet[:vardir]
end
end
end
The `Facter::Util::PuppetSettings.with_puppet` method accepts a block and
yields to it only if the Puppet library is loaded. If the Puppet library is
not loaded, then the method silently returns `nil` which Facter interprets as
an undefined fact value. The net effect is that the fact won't be set.

View file

@ -0,0 +1,7 @@
NOTE
====
This project's specs depend on puppet core, and thus they require the
`puppetlabs_spec_helper` project. For more information please see the README
in that project, which can be found here: [puppetlabs spec
helper](https://github.com/puppetlabs/puppetlabs_spec_helper)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,24 @@
# Contributing to this module #
* Work in a topic branch
* Submit a github pull request
* Address any comments / feeback
* Merge into main using --no-ff
# Releasing this module #
* This module adheres to http://semver.org/
* Look for API breaking changes using git diff vX.Y.Z..
* If no API breaking changes, the minor version may be bumped.
* If there are API breaking changes, the major version must be bumped.
* If there are only small minor changes, the patch version may be bumped.
* Update the CHANGELOG
* Update the Modulefile
* Commit these changes with a message along the lines of "Update CHANGELOG and
Modulefile for release"
* Create an annotated tag with git tag -a vX.Y.Z -m 'version X.Y.Z' (NOTE the
leading v as per semver.org)
* Push the tag with git push origin --tags
* Build a new package with puppet-module or the rake build task if it exists
* Publish the new package to the forge
* Bonus points for an announcement to puppet-users.

View file

@ -0,0 +1 @@
--- {}

View file

@ -0,0 +1,9 @@
# This is a simple smoke test
# of the file_line resource type.
file { '/tmp/dansfile':
ensure => file,
}
-> file_line { 'dans_line':
line => 'dan is awesome',
path => '/tmp/dansfile',
}

View file

@ -0,0 +1,9 @@
include stdlib
info('has_interface_with(\'lo\'):', has_interface_with('lo'))
info('has_interface_with(\'loX\'):', has_interface_with('loX'))
info('has_interface_with(\'ipaddress\', \'127.0.0.1\'):', has_interface_with('ipaddress', '127.0.0.1'))
info('has_interface_with(\'ipaddress\', \'127.0.0.100\'):', has_interface_with('ipaddress', '127.0.0.100'))
info('has_interface_with(\'network\', \'127.0.0.0\'):', has_interface_with('network', '127.0.0.0'))
info('has_interface_with(\'network\', \'128.0.0.0\'):', has_interface_with('network', '128.0.0.0'))
info('has_interface_with(\'netmask\', \'255.0.0.0\'):', has_interface_with('netmask', '255.0.0.0'))
info('has_interface_with(\'netmask\', \'256.0.0.0\'):', has_interface_with('netmask', '256.0.0.0'))

View file

@ -0,0 +1,3 @@
include stdlib
info('has_ip_address(\'192.168.1.256\'):', has_ip_address('192.168.1.256'))
info('has_ip_address(\'127.0.0.1\'):', has_ip_address('127.0.0.1'))

View file

@ -0,0 +1,3 @@
include stdlib
info('has_ip_network(\'127.0.0.0\'):', has_ip_network('127.0.0.0'))
info('has_ip_network(\'128.0.0.0\'):', has_ip_network('128.0.0.0'))

View file

@ -0,0 +1 @@
include stdlib

View file

@ -0,0 +1,18 @@
# This function returns either a rendered template or a deferred function to render at runtime.
# If any of the values in the variables hash are deferred, then the template will be deferred.
#
# Note: this function requires all parameters to be explicitly passed in. It cannot expect to
# use facts, class variables, and other variables in scope. This is because when deferred, we
# have to explicitly pass the entire scope to the client.
#
function stdlib::deferrable_epp(String $template, Hash $variables) >> Variant[String, Sensitive[String], Deferred] {
if $variables.stdlib::nested_values.any |$value| { $value.is_a(Deferred) } {
Deferred(
'inline_epp',
[find_template($template).file, $variables],
)
}
else {
epp($template, $variables)
}
}

View file

@ -0,0 +1,33 @@
# @summary function to cast ensure parameter to resource specific value
#
# @return [String]
function stdlib::ensure(
Variant[Boolean, Enum['present', 'absent']] $ensure,
Optional[Enum['directory', 'link', 'mounted', 'service', 'file', 'package']] $resource = undef,
) >> String {
$_ensure = $ensure ? {
Boolean => $ensure.bool2str('present', 'absent'),
default => $ensure,
}
case $resource {
'package': {
$_ensure ? {
'present' => 'installed',
default => 'absent',
}
}
'service': {
$_ensure ? {
'present' => 'running',
default => 'stopped',
}
}
undef: { $_ensure }
default: {
$_ensure ? {
'present' => $resource,
default => $_ensure,
}
}
}
}

View file

@ -0,0 +1,11 @@
# @summary This function is deprecated. It implements the functionality of the original non-namespaced stdlib `time` function.
#
# It is provided for compatability, but users should use the native time related functions directly.
#
# @param _timezone
# This parameter doesn't do anything, but exists for compatability reasons
function stdlib::time(Optional[String] $_timezone = undef) >> Integer {
# Note the `timezone` parameter doesn't do anything and didn't in the ruby implementation for _years_ (pre 1.8.7 perhaps ???)
deprecation('time', 'The stdlib `time` function is deprecated. Please direcly use native Puppet functionality instead. eg. `Integer(Timestamp().strftime(\'%s\'))`', false)
Integer(Timestamp().strftime('%s'))
}

View file

@ -0,0 +1,21 @@
---
version: 5
defaults: # Used for any hierarchy level that omits these keys.
datadir: data # This path is relative to hiera.yaml's directory.
data_hash: yaml_data # Use the built-in YAML backend.
hierarchy:
- name: "osfamily/major release"
paths:
# Used to distinguish between Debian and Ubuntu
- "os/%{facts.os.name}/%{facts.os.release.major}.yaml"
- "os/%{facts.os.family}/%{facts.os.release.major}.yaml"
# Used for Solaris
- "os/%{facts.os.family}/%{facts.kernelrelease}.yaml"
- name: "osfamily"
paths:
- "os/%{facts.os.name}.yaml"
- "os/%{facts.os.family}.yaml"
- name: 'common'
path: 'common.yaml'

View file

@ -0,0 +1,21 @@
# frozen_string_literal: true
# Fact: package_provider
#
# Purpose: Returns the default provider Puppet will choose to manage packages
# on this system
#
# Resolution: Instantiates a dummy package resource and return the provider
#
# Caveats:
#
require 'puppet/type'
require 'puppet/type/package'
# These will be nil if Puppet is not available.
Facter.add(:package_provider) do
# Instantiates a dummy package resource and return the provider
setcode do
Puppet::Type.type(:package).newpackage(name: 'dummy', allow_virtual: 'true')[:provider].to_s
end
end

View file

@ -0,0 +1,62 @@
# frozen_string_literal: true
# Fact: is_pe, pe_version, pe_major_version, pe_minor_version, pe_patch_version
#
# Purpose: Return various facts about the PE state of the system
#
# Resolution: Uses a regex match against puppetversion to determine whether the
# machine has Puppet Enterprise installed, and what version (overall, major,
# minor, patch) is installed.
#
# Caveats:
#
# Fact: pe_version
Facter.add('pe_version') do
setcode do
found_version = Facter.value('pe_build')
unless found_version
puppet_ver = Facter.value('puppetversion')
unless puppet_ver.nil?
pe_ver = puppet_ver.match(%r{Puppet Enterprise (\d+\.\d+\.\d+)})
found_version = pe_ver[1] if pe_ver
end
end
found_version
end
end
# Fact: is_pe
Facter.add('is_pe') do
setcode do
!Facter.value(:pe_version).to_s.empty?
end
end
# Fact: pe_major_version
Facter.add('pe_major_version') do
confine is_pe: true
setcode do
pe_version = Facter.value(:pe_version)
pe_version.to_s.split('.')[0] if pe_version
end
end
# Fact: pe_minor_version
Facter.add('pe_minor_version') do
confine is_pe: true
setcode do
pe_version = Facter.value(:pe_version)
pe_version.to_s.split('.')[1] if pe_version
end
end
# Fact: pe_patch_version
Facter.add('pe_patch_version') do
confine is_pe: true
setcode do
pe_version = Facter.value(:pe_version)
pe_version.to_s.split('.')[2] if pe_version
end
end

View file

@ -0,0 +1,46 @@
# frozen_string_literal: true
# These facter facts return the value of the Puppet vardir and environment path
# settings for the node running puppet or puppet agent. The intent is to
# enable Puppet modules to automatically have insight into a place where they
# can place variable data, or for modules running on the puppet server to know
# where environments are stored.
#
# The values should be directly usable in a File resource path attribute.
#
begin
require 'facter/util/puppet_settings'
rescue LoadError => e
# puppet apply does not add module lib directories to the $LOAD_PATH (See
# #4248). It should (in the future) but for the time being we need to be
# defensive which is what this rescue block is doing.
rb_file = File.join(File.dirname(__FILE__), 'util', 'puppet_settings.rb')
load rb_file if File.exist?(rb_file) || raise(e)
end
# Facter fact returns the value of the Puppet vardir
Facter.add(:puppet_vardir) do
setcode do
Facter::Util::PuppetSettings.with_puppet do
Puppet[:vardir]
end
end
end
# Facter fact returns the value of the Puppet environment path
Facter.add(:puppet_environmentpath) do
setcode do
Facter::Util::PuppetSettings.with_puppet do
Puppet[:environmentpath]
end
end
end
# Facter fact returns the value of the Puppet server
Facter.add(:puppet_server) do
setcode do
Facter::Util::PuppetSettings.with_puppet do
Puppet[:server]
end
end
end

View file

@ -0,0 +1,11 @@
# frozen_string_literal: true
Facter.add(:root_home) do
setcode do
require 'etc'
rescue LoadError
# Unavailable on platforms like Windows
else
Etc.getpwnam('root')&.dir
end
end

View file

@ -0,0 +1,19 @@
# frozen_string_literal: true
# Fact: service_provider
#
# Purpose: Returns the default provider Puppet will choose to manage services
# on this system
#
# Resolution: Instantiates a dummy service resource and return the provider
#
# Caveats:
#
require 'puppet/type'
require 'puppet/type/service'
Facter.add(:service_provider) do
setcode do
Puppet::Type.type(:service).newservice(name: 'dummy')[:provider].to_s
end
end

View file

@ -0,0 +1,18 @@
# frozen_string_literal: true
# A method to evaluate a Facter code block if puppet is loaded.
module Facter::Util::PuppetSettings
# This method is intended to provide a convenient way to evaluate a
# Facter code block only if Puppet is loaded. This is to account for the
# situation where the fact happens to be in the load path, but Puppet is
# not loaded for whatever reason. Perhaps the user is simply running
# facter without the --puppet flag and they happen to be working in a lib
# directory of a module.
def self.with_puppet
Module.const_get(:Puppet)
rescue NameError
nil
else
yield
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::batch_escape`](#stdlibbatch_escape) instead.
Puppet::Functions.create_function(:batch_escape) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'batch_escape', 'This function is deprecated, please use stdlib::batch_escape instead.', false)
call_function('stdlib::batch_escape', *args)
end
end

View file

@ -0,0 +1,38 @@
# frozen_string_literal: true
# @summary Function to print deprecation warnings, Logs a warning once for a given key.
Puppet::Functions.create_function(:deprecation) do
# @param key
# The uniqueness key. This function logs once for any given key.
# @param message
# Is the message text including any positional information that is formatted by the user/caller of the function.
# @param use_strict_setting
# When `true`, (the default), the function is affected by the puppet setting 'strict', which can be set to :error
# (outputs as an error message), :off (no message / error is displayed) and :warning
# (default, outputs a warning).
dispatch :deprecation do
param 'String', :key
param 'String', :message
optional_param 'Boolean', :use_strict_setting
end
def deprecation(key, message, use_strict_setting = true) # rubocop:disable Style/OptionalBooleanParameter
if defined? Puppet::Pops::PuppetStack.stacktrace
stacktrace = Puppet::Pops::PuppetStack.stacktrace
file = stacktrace[0]
line = stacktrace[1]
message = "#{message} at #{file}:#{line}"
end
# Do nothing if using strict setting and strict is set to `off`
return if use_strict_setting && Puppet.settings[:strict] == :off
# Fail hard if using strict setting and strict is set to `error`
raise("deprecation. #{key}. #{message}") if use_strict_setting && Puppet.settings[:strict] == :error
# Otherwise raise a soft warning
# (unless the STDLIB_LOG_DEPRECATIONS has been set to `false`. This is mainly for use in rspec-puppet testing to suppress noise in logs)
Puppet.deprecation_warning(message, key) unless ENV['STDLIB_LOG_DEPRECATIONS'] == 'false'
nil
end
end

View file

@ -0,0 +1,13 @@
# frozen_string_literal: true
# @summary DEPRECATED. Use the namespaced function [`stdlib::ensure_packages`](#stdlibensure_packages) instead.
Puppet::Functions.create_function(:ensure_packages, Puppet::Functions::InternalFunction) do
dispatch :deprecation_gen do
scope_param
repeated_param 'Any', :args
end
def deprecation_gen(scope, *args)
call_function('deprecation', 'ensure_packages', 'This function is deprecated, please use stdlib::ensure_packages instead.', false)
scope.call_function('stdlib::ensure_packages', args)
end
end

View file

@ -0,0 +1,65 @@
# frozen_string_literal: true
# @summary
# Digs into the facts hash using dot-notation
#
# Supports the use of dot-notation for referring to structured facts. If a fact requested
# does not exist, returns Undef.
#
# @example Example usage:
# fact('osfamily')
# fact('os.architecture')
#
# @example Array indexing:
# fact('mountpoints."/dev".options.1')
#
# @example Fact containing a "." in the name:
# fact('vmware."VRA.version"')
#
Puppet::Functions.create_function(:fact) do
# @param fact_name
# The name of the fact to check
#
# @return
# All information retrieved on the given fact_name
dispatch :fact do
param 'String', :fact_name
end
def to_dot_syntax(array_path)
array_path.map { |string|
string.include?('.') ? %("#{string}") : string
}.join('.')
end
def fact(fact_name)
facts = closure_scope['facts']
# Transform the dot-notation string into an array of paths to walk. Make
# sure to correctly extract double-quoted values containing dots as single
# elements in the path.
path = fact_name.scan(%r{([^."]+)|(?:")([^"]+)(?:")}).map { |x| x.compact.first }
walked_path = []
path.reduce(facts) do |d, k|
return nil if d.nil? || k.nil?
if d.is_a?(Array)
begin
result = d[Integer(k)]
rescue ArgumentError => e # rubocop:disable Lint/UselessAssignment : Causes errors if assigment is removed.
Puppet.warning("fact request for #{fact_name} returning nil: '#{to_dot_syntax(walked_path)}' is an array; cannot index to '#{k}'")
result = nil
end
elsif d.is_a?(Hash)
result = d[k]
else
Puppet.warning("fact request for #{fact_name} returning nil: '#{to_dot_syntax(walked_path)}' is not a collection; cannot walk to '#{k}'")
result = nil
end
walked_path << k
result
end
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::fqdn_rand_string`](#stdlibfqdn_rand_string) instead.
Puppet::Functions.create_function(:fqdn_rand_string) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'fqdn_rand_string', 'This function is deprecated, please use stdlib::fqdn_rand_string instead.', false)
call_function('stdlib::fqdn_rand_string', *args)
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::fqdn_rotate`](#stdlibfqdn_rotate) instead.
Puppet::Functions.create_function(:fqdn_rotate) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'fqdn_rotate', 'This function is deprecated, please use stdlib::fqdn_rotate instead.', false)
call_function('stdlib::fqdn_rotate', *args)
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::has_interface_with`](#stdlibhas_interface_with) instead.
Puppet::Functions.create_function(:has_interface_with) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'has_interface_with', 'This function is deprecated, please use stdlib::has_interface_with instead.', false)
call_function('stdlib::has_interface_with', *args)
end
end

View file

@ -0,0 +1,44 @@
# frozen_string_literal: true
# @summary
# Boolean check to determine whether a variable is of a given data type.
# This is equivalent to the `=~` type checks.
#
# @example Example Usage:
# # check a data type
# foo = 3
# $bar = [1,2,3]
# $baz = 'A string!'
#
# if $foo.is_a(Integer) {
# notify { 'foo!': }
# }
# if $bar.is_a(Array) {
# notify { 'bar!': }
# }
# if $baz.is_a(String) {
# notify { 'baz!': }
# }
#
# See the documentation for "The Puppet Type System" for more information about types.
# See the `assert_type()` function for flexible ways to assert the type of a value.
#
Puppet::Functions.create_function(:is_a) do
# @param value
# The value to be checked
#
# @param type
# The expected type
#
# @return [Boolean]
# Return's `true` or `false`.
dispatch :is_a do
param 'Any', :value
param 'Type', :type
end
def is_a(value, type) # rubocop:disable Naming/PredicateName : Used in to many other places to rename at this time, attempting to refactor caused Rubocop to crash.
# See puppet's lib/puppet/pops/evaluator/evaluator_impl.rb eval_MatchExpression
Puppet::Pops::Types::TypeCalculator.instance?(type, value)
end
end

View file

@ -0,0 +1,15 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::merge`](#stdlibmerge) instead.
Puppet::Functions.create_function(:merge) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
optional_block_param 'Variant[Callable[2,2], Callable[3,3]]', :block
end
def deprecation_gen(*args, &block)
call_function('deprecation', 'merge', 'This function is deprecated, please use stdlib::merge instead.', false)
call_function('stdlib::merge', *args, &block)
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::os_version_gte`](#stdlibos_version_gte) instead.
Puppet::Functions.create_function(:os_version_gte) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'os_version_gte', 'This function is deprecated, please use stdlib::os_version_gte instead.', false)
call_function('stdlib::os_version_gte', *args)
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::parsehocon`](#stdlibparsehocon) instead.
Puppet::Functions.create_function(:parsehocon) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'parsehocon', 'This function is deprecated, please use stdlib::parsehocon instead.', false)
call_function('stdlib::parsehocon', *args)
end
end

View file

@ -0,0 +1,34 @@
# frozen_string_literal: true
# @summary
# **Deprecated:** Starting Puppet 8, we no longer natively support PSON usage. This function should be removed once we stop supporting Puppet 7.
#
# This function accepts PSON, a Puppet variant of JSON, as a string and converts
# it into the correct Puppet structure
#
# @example How to parse pson
# $data = parsepson('{"a":"1","b":"2"}')
#
# For more information on PSON please see the following link:
# https://puppet.com/docs/puppet/7/http_api/pson.html
#
Puppet::Functions.create_function(:parsepson) do
# @param pson_string A valid PSON string
# @param default An optional default to return if parsing the pson_string fails
# @return [Data]
dispatch :parsepson do
param 'String[1]', :pson_string
optional_param 'Any', :default
end
def parsepson(pson_string, default = :no_default_provided)
call_function('deprecation', 'parsepson', 'This method is deprecated. From Puppet 8, PSON is no longer natively supported. Please use JSON.parse().')
PSON.load(pson_string) if Puppet::Util::Package.versioncmp(Puppet.version, '8').negative?
rescue StandardError => e
Puppet.debug("Parsing PSON failed with error: #{e.message}")
raise e if default == :no_default_provided
default
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::powershell_escape`](#stdlibpowershell_escape) instead.
Puppet::Functions.create_function(:powershell_escape) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'powershell_escape', 'This function is deprecated, please use stdlib::powershell_escape instead.', false)
call_function('stdlib::powershell_escape', *args)
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::seeded_rand`](#stdlibseeded_rand) instead.
Puppet::Functions.create_function(:seeded_rand) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'seeded_rand', 'This function is deprecated, please use stdlib::seeded_rand instead.', false)
call_function('stdlib::seeded_rand', *args)
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::seeded_rand_string`](#stdlibseeded_rand_string) instead.
Puppet::Functions.create_function(:seeded_rand_string) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'seeded_rand_string', 'This function is deprecated, please use stdlib::seeded_rand_string instead.', false)
call_function('stdlib::seeded_rand_string', *args)
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::shell_escape`](#stdlibshell_escape) instead.
Puppet::Functions.create_function(:shell_escape) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'shell_escape', 'This function is deprecated, please use stdlib::shell_escape instead.', false)
call_function('stdlib::shell_escape', *args)
end
end

View file

@ -0,0 +1,31 @@
# frozen_string_literal: true
# @summary
# Escapes a string so that it can be safely used in a batch shell command line.
#
# >* Note:* that the resulting string should be used unquoted and is not intended for use in double quotes nor in single
# quotes.
Puppet::Functions.create_function(:'stdlib::batch_escape') do
# @param string
# The string to escape
#
# @return
# An escaped string that can be safely used in a batch command line.
dispatch :batch_escape do
param 'Any', :string
end
def batch_escape(string)
result = ''
string.to_s.chars.each do |char|
result += case char
when '"' then '""'
when '$', '\\' then "\\#{char}"
else char
end
end
%("#{result}")
end
end

View file

@ -0,0 +1,31 @@
# frozen_string_literal: true
require 'zlib'
# @note
# The CRC32 algorithm can easily generate collisions,
# but may be useful for generating sharding, describing
# secrets, or seeding nonce values.
#
# @summary
# Run a CRC32 calculation against a given value.
Puppet::Functions.create_function(:'stdlib::crc32') do
# @param my_data The ScalarData to evaluate
# @example Check a simple string value
# stdlib::crc32('my string') == '18fbd270'
# @example Check a Sensitive datatype
# stdlib::crc32(sensitive('my string')) == '18fbd270'
# @example Check a number
# stdlib::crc32(100.0) == 'a3fd429a'
# stdlib::crc32(100.00000) == 'a3fd429a'
# @return String
dispatch :crc32 do
param 'Variant[ScalarData, Sensitive[ScalarData], Binary, Sensitive[Binary]]', :my_data
return_type 'String'
end
def crc32(my_data)
Zlib.crc32(my_data.unwrap.to_s).to_s(16).downcase
rescue StandardError
Zlib.crc32(my_data.to_s).to_s(16).downcase
end
end

View file

@ -0,0 +1,23 @@
# frozen_string_literal: true
# @summary
# Returns true if str ends with one of the prefixes given. Each of the prefixes should be a String.
#
Puppet::Functions.create_function(:'stdlib::end_with') do
# @param test_string The string to check
# @param suffixes The suffixes to check
# @example
# 'foobar'.stdlib::end_with('bar') => true
# 'foobar'.stdlib::end_with('foo') => false
# 'foobar'.stdlib::end_with(['foo', 'baz']) => false
# @return [Boolean] True or False
dispatch :end_with do
param 'String', :test_string
param 'Variant[String[1],Array[String[1], 1]]', :suffixes
return_type 'Boolean'
end
def end_with(test_string, suffixes)
test_string.end_with?(*suffixes)
end
end

View file

@ -0,0 +1,61 @@
# frozen_string_literal: true
# @summary Takes a list of packages and only installs them if they don't already exist.
#
# It optionally takes a hash as a second parameter that will be passed as the
# third argument to the ensure_resource() function.
Puppet::Functions.create_function(:'stdlib::ensure_packages', Puppet::Functions::InternalFunction) do
# @param packages
# The packages to ensure are installed.
# @param default_attributes
# Default attributes to be passed to the `ensure_resource()` function
# @return [Undef] Returns nothing.
dispatch :ensure_packages do
scope_param
param 'Variant[String[1], Array[String[1]]]', :packages
optional_param 'Hash', :default_attributes
return_type 'Undef'
end
# @param packages
# The packages to ensure are installed. The keys are packages and values are the attributes specific to that package.
# @param default_attributes
# Default attributes. Package specific attributes from the `packages` parameter will take precedence.
# @return [Undef] Returns nothing.
dispatch :ensure_packages_hash do
scope_param
param 'Hash[String[1], Any]', :packages
optional_param 'Hash', :default_attributes
return_type 'Undef'
end
def ensure_packages(scope, packages, default_attributes = {})
Array(packages).each do |package_name|
defaults = { 'ensure' => 'installed' }.merge(default_attributes)
# `present` and `installed` are aliases for the `ensure` attribute. If `ensure` is set to either of these values replace
# with `installed` by default but `present` if this package is already in the catalog with `ensure => present`
defaults['ensure'] = default_ensure(package_name) if ['present', 'installed'].include?(defaults['ensure'])
scope.call_function('ensure_resource', ['package', package_name, defaults])
end
nil
end
def ensure_packages_hash(scope, packages, default_attributes = {})
packages.each do |package, attributes|
ensure_packages(scope, package, default_attributes.merge(attributes))
end
nil
end
private
def default_ensure(package_name)
if call_function('defined_with_params', "Package[#{package_name}]", { 'ensure' => 'present' })
'present'
else
'installed'
end
end
end

View file

@ -0,0 +1,28 @@
# frozen_string_literal: true
# @summary
# Returns the Extension (the Portion of Filename in Path starting from the
# last Period).
#
# If Path is a Dotfile, or starts with a Period, then the starting Dot is not
# dealt with the Start of the Extension.
#
# An empty String will also be returned, when the Period is the last Character
# in Path.
Puppet::Functions.create_function(:'stdlib::extname') do
# @param filename The Filename
# @return [String] The Extension starting from the last Period
# @example Determining the Extension of a Filename
# stdlib::extname('test.rb') => '.rb'
# stdlib::extname('a/b/d/test.rb') => '.rb'
# stdlib::extname('test') => ''
# stdlib::extname('.profile') => ''
dispatch :extname do
param 'String', :filename
return_type 'String'
end
def extname(filename)
File.extname(filename)
end
end

View file

@ -0,0 +1,39 @@
# frozen_string_literal: true
# @summary
# Generates a random alphanumeric string. Combining the `$fqdn` fact and an
# optional seed for repeatable randomness.
#
# Optionally, you can specify a character set for the function (defaults to alphanumeric).
Puppet::Functions.create_function(:'stdlib::fqdn_rand_string') do
# @param length The length of the resulting string.
# @param charset The character set to use.
# @param seed The seed for repeatable randomness.
#
# @return [String]
#
# @example Example Usage:
# stdlib::fqdn_rand_string(10)
# stdlib::fqdn_rand_string(10, 'ABCDEF!@$%^')
# stdlib::fqdn_rand_string(10, undef, 'custom seed')
dispatch :fqdn_rand_string do
param 'Integer[1]', :length
optional_param 'Optional[String]', :charset
optional_repeated_param 'Any', :seed
end
def fqdn_rand_string(length, charset = nil, *seed)
charset = if charset && !charset.empty?
charset.chars.to_a
else
(0..9).map(&:to_s) + ('A'..'Z').to_a + ('a'..'z').to_a
end
rand_string = ''
length.times do |current|
rand_string += charset[call_function('fqdn_rand', charset.size, (seed + [current + 1]).join(':'))]
end
rand_string
end
end

View file

@ -0,0 +1,66 @@
# frozen_string_literal: true
# @summary Rotates an array or string a random number of times, combining the `fqdn` fact and an optional seed for repeatable randomness.
Puppet::Functions.create_function(:'stdlib::fqdn_rotate') do
# @param input
# The String you want rotated a random number of times
# @param seeds
# One of more values to use as a custom seed. These will be combined with the host's FQDN
#
# @return [String] Returns the rotated String
#
# @example Rotating a String
# stdlib::fqdn_rotate('abcd')
# @example Using a custom seed
# stdlib::fqdn_rotate('abcd', 'custom seed')
dispatch :fqdn_rotate_string do
param 'String', :input
optional_repeated_param 'Variant[Integer,String]', :seeds
return_type 'String'
end
# @param input
# The Array you want rotated a random number of times
# @param seeds
# One of more values to use as a custom seed. These will be combined with the host's FQDN
#
# @return [String] Returns the rotated Array
#
# @example Rotating an Array
# stdlib::fqdn_rotate(['a', 'b', 'c', 'd'])
# @example Using custom seeds
# stdlib::fqdn_rotate([1, 2, 3], 'custom', 'seed', 1)
dispatch :fqdn_rotate_array do
param 'Array', :input
optional_repeated_param 'Variant[Integer,String]', :seeds
return_type 'Array'
end
def fqdn_rotate_array(input, *seeds)
# Check whether it makes sense to rotate ...
return input if input.size <= 1
result = input.clone
require 'digest/md5'
seed = Digest::MD5.hexdigest([fqdn_fact, seeds].join(':')).hex
offset = Puppet::Util.deterministic_rand(seed, result.size).to_i
offset.times do
result.push result.shift
end
result
end
def fqdn_rotate_string(input, *seeds)
fqdn_rotate_array(input.chars, seeds).join
end
private
def fqdn_fact
closure_scope['facts']['networking']['fqdn']
end
end

View file

@ -0,0 +1,33 @@
# frozen_string_literal: true
# @summary
# Returns whether the Puppet runtime has access to a given function.
#
# @example Using stdlib::has_function()
# stdlib::has_function('stdlib::has_function') # true
# stdlib::has_function('not_a_function') # false
#
# Determines whether the Puppet runtime has access to a function by the
# name provided.
#
# @return
# Returns true if the provided function name is available, false otherwise.
#
Puppet::Functions.create_function(:'stdlib::has_function', Puppet::Functions::InternalFunction) do
dispatch :has_function do
scope_param
param 'String[1]', :function_name
return_type 'Boolean'
end
def has_function(scope, function_name) # rubocop:disable Naming/PredicateName
loaders = scope.compiler.loaders
loader = loaders.private_environment_loader
return true unless loader&.load(:function, function_name).nil?
# If the loader cannot find the function it might be
# a 3x-style function stubbed in on-the-fly for testing.
func_3x = Puppet::Parser::Functions.function(function_name.to_sym)
func_3x.is_a?(String) && !func_3x.empty?
end
end

View file

@ -0,0 +1,47 @@
# frozen_string_literal: true
# @summary Returns boolean based on network interfaces present and their attribute values.
#
# Can be called with one, or two arguments.
Puppet::Functions.create_function(:'stdlib::has_interface_with') do
# @param interface
# The name of an interface
# @return [Boolean] Returns `true` if `interface` exists and `false` otherwise
# @example When called with a single argument, the presence of the interface is checked
# stdlib::has_interface_with('lo') # Returns `true`
dispatch :has_interface do
param 'String[1]', :interface
return_type 'Boolean'
end
# @param kind
# A supported interface attribute
# @param value
# The value of the attribute
# @return [Boolean] Returns `true` if any of the interfaces in the `networking` fact has a `kind` attribute with the value `value`. Otherwise returns `false`
# @example Checking if an interface exists with a given mac address
# stdlib::has_interface_with('macaddress', 'x:x:x:x:x:x') # Returns `false`
# @example Checking if an interface exists with a given IP address
# stdlib::has_interface_with('ipaddress', '127.0.0.1') # Returns `true`
dispatch :has_interface_with do
param "Enum['macaddress','netmask','ipaddress','network','ip','mac']", :kind
param 'String[1]', :value
return_type 'Boolean'
end
def has_interface(interface) # rubocop:disable Naming/PredicateName
interfaces.key? interface
end
def has_interface_with(kind, value) # rubocop:disable Naming/PredicateName
# For compatibility with older version of function that used the legacy facts, alias `ip` with `ipaddress` and `mac` with `macaddress`
kind = 'ip' if kind == 'ipaddress'
kind = 'mac' if kind == 'macaddress'
interfaces.any? { |_interface, params| params[kind] == value }
end
def interfaces
closure_scope['facts']['networking']['interfaces']
end
end

View file

@ -0,0 +1,32 @@
# frozen_string_literal: true
# @summary
# Returns true if the ipaddress is within the given CIDRs
#
# @example ip_in_range(<IPv4 Address>, <IPv4 CIDR>)
# stdlib::ip_in_range('10.10.10.53', '10.10.10.0/24') => true
Puppet::Functions.create_function(:'stdlib::ip_in_range') do
# @param ipaddress The IP address to check
# @param range One CIDR or an array of CIDRs
# defining the range(s) to check against
#
# @return [Boolean] True or False
dispatch :ip_in_range do
param 'String', :ipaddress
param 'Variant[String, Array]', :range
return_type 'Boolean'
end
require 'ipaddr'
def ip_in_range(ipaddress, range)
ip = IPAddr.new(ipaddress)
if range.is_a? Array
ranges = range.map { |r| IPAddr.new(r) }
ranges.any? { |rng| rng.include?(ip) }
elsif range.is_a? String
ranges = IPAddr.new(range)
ranges.include?(ip)
end
end
end

View file

@ -0,0 +1,112 @@
# frozen_string_literal: true
# @summary
# Merges two or more hashes together or hashes resulting from iteration, and returns
# the resulting hash.
#
# @example Using stdlib::merge()
# $hash1 = {'one' => 1, 'two', => 2}
# $hash2 = {'two' => 'dos', 'three', => 'tres'}
# $merged_hash = stdlib::merge($hash1, $hash2) # $merged_hash = {'one' => 1, 'two' => 'dos', 'three' => 'tres'}
#
# When there is a duplicate key, the key in the rightmost hash will "win."
#
# Note that since Puppet 4.0.0 the same merge can be achieved with the + operator.
# `$merged_hash = $hash1 + $hash2`
#
# If stdlib::merge is given a single Iterable (Array, Hash, etc.) it will call a given block with
# up to three parameters, and merge each resulting Hash into the accumulated result. All other types
# of values returned from the block (typically undef) are skipped (not merged).
#
# The codeblock can take 2 or three parameters:
# * with two, it gets the current hash (as built to this point), and each value (for hash the value is a [key, value] tuple)
# * with three, it gets the current hash (as built to this point), the key/index of each value, and then the value
#
# If the iterable is empty, or no hash was returned from the given block, an empty hash is returned. In the given block, a call to `next()`
# will skip that entry, and a call to `break()` will end the iteration.
#
# @example counting occurrences of strings in an array
# ['a', 'b', 'c', 'c', 'd', 'b'].stdlib::merge | $hsh, $v | { { $v => $hsh[$v].lest || { 0 } + 1 } } # results in { a => 1, b => 2, c => 2, d => 1 }
#
# @example skipping values for entries that are longer than 1 char
# ['a', 'b', 'c', 'c', 'd', 'b', 'blah', 'blah'].stdlib::merge | $hsh, $v | { if $v =~ String[1,1] { { $v => $hsh[$v].lest || { 0 } + 1 } } } # results in { a => 1, b => 2, c => 2, d => 1 }
#
# The iterative `stdlib::merge()` has an advantage over doing the same with a general `reduce()` in that the constructed hash
# does not have to be copied in each iteration and thus will perform much better with large inputs.
Puppet::Functions.create_function(:'stdlib::merge') do
# @param args
# Repeated Param - The hashes that are to be merged
#
# @return
# The merged hash
dispatch :merge2hashes do
repeated_param 'Variant[Hash[Scalar,Any], Undef, String[0,0]]', :args # this strange type is backwards compatible
return_type 'Hash[Scalar,Any]'
end
# @param args
# Repeated Param - The hashes that are to be merged
#
# @param block
# A block placed on the repeatable param `args`
#
# @return
# The merged hash
dispatch :merge_iterable3 do
repeated_param 'Iterable', :args
block_param 'Callable[3,3]', :block
return_type 'Hash'
end
# @param args
# Repeated Param - The hashes that are to be merged
#
# @param block
# A block placed on the repeatable param `args`
#
# @return
# The merged hash
dispatch :merge_iterable2 do
repeated_param 'Iterable', :args
block_param 'Callable[2,2]', :block
return_type 'Hash'
end
def merge2hashes(*hashes)
accumulator = {}
hashes.each { |h| accumulator.merge!(h) if h.is_a?(Hash) }
accumulator
end
def merge_iterable2(iterable)
accumulator = {}
enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable)
enum.each do |v|
r = yield(accumulator, v)
accumulator.merge!(r) if r.is_a?(Hash)
end
accumulator
end
def merge_iterable3(iterable)
accumulator = {}
enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable)
if enum.hash_style?
enum.each do |entry|
r = yield(accumulator, *entry)
accumulator.merge!(r) if r.is_a?(Hash)
end
else
begin
index = 0
loop do
r = yield(accumulator, index, enum.next)
accumulator.merge!(r) if r.is_a?(Hash)
index += 1
end
rescue StopIteration
end
end
accumulator
end
end

View file

@ -0,0 +1,27 @@
# frozen_string_literal: true
# @summary Get list of nested values from given hash
# This function will return list of nested Hash values and returns list of values in form of Array
#
# @example Example Usage:
# $hash = {
# "key1" => "value1",
# "key2" => { "key2.1" => "value2.1"},
# "key3" => "value3"
# }
# $data = $hash.stdlib::nested_values
# #Output : ["value1", "value2.1", "value3"]
Puppet::Functions.create_function(:'stdlib::nested_values') do
# @param hash A (nested) hash
# @return All the values found in the input hash included those deeply nested.
dispatch :nested_values do
param 'Hash', :hash
return_type 'Array'
end
def nested_values(hash)
hash.each_with_object([]) do |(_k, v), values|
v.is_a?(Hash) ? values.concat(nested_values(v)) : (values << v)
end
end
end

View file

@ -0,0 +1,27 @@
# frozen_string_literal: true
# @summary
# Checks if the OS version is at least a certain version.
# > *Note:*
# Only the major version is taken into account.
#
# @example Example usage:#
# if stdlib::os_version_gte('Debian', '9') { }
# if stdlib::os_version_gte('Ubuntu', '18.04') { }
Puppet::Functions.create_function(:'stdlib::os_version_gte') do
# @param os operating system
# @param version
#
# @return [Boolean] `true` or `false
dispatch :os_version_gte do
param 'String[1]', :os
param 'String[1]', :version
return_type 'Boolean'
end
def os_version_gte(os, version)
facts = closure_scope['facts']
(facts['os']['name'] == os &&
Puppet::Util::Package.versioncmp(facts['os']['release']['major'], version) >= 0)
end
end

View file

@ -0,0 +1,32 @@
# frozen_string_literal: true
# @summary
# This function accepts HOCON as a string and converts it into the correct
# Puppet structure
#
# @example How to parse hocon
# $data = stdlib::parsehocon("{any valid hocon: string}")
#
Puppet::Functions.create_function(:'stdlib::parsehocon') do
# @param hocon_string A valid HOCON string
# @param default An optional default to return if parsing hocon_string fails
# @return [Data]
dispatch :parsehocon do
param 'String', :hocon_string
optional_param 'Any', :default
end
def parsehocon(hocon_string, default = :no_default_provided)
require 'hocon/config_factory'
begin
data = Hocon::ConfigFactory.parse_string(hocon_string)
data.resolve.root.unwrapped
rescue Hocon::ConfigError::ConfigParseError => e
Puppet.debug("Parsing hocon failed with error: #{e.message}")
raise e if default == :no_default_provided
default
end
end
end

View file

@ -0,0 +1,31 @@
# frozen_string_literal: true
# @summary
# Escapes a string so that it can be safely used in a PowerShell command line.
#
# >* Note:* that the resulting string should be used unquoted and is not intended for use in double quotes nor in single
# quotes.
Puppet::Functions.create_function(:'stdlib::powershell_escape') do
# @param string
# The string to escape
#
# @return
# An escaped string that can be safely used in a PowerShell command line.
dispatch :powershell_escape do
param 'Any', :string
end
def powershell_escape(string)
result = ''
string.to_s.chars.each do |char|
result += case char
when ' ', "'", '`', '|', "\n", '$' then "`#{char}"
when '"' then '\`"'
else char
end
end
result
end
end

View file

@ -0,0 +1,22 @@
# frozen_string_literal: true
# @summary
# Generates a random whole number greater than or equal to 0 and less than max, using the value of seed for repeatable randomness.
Puppet::Functions.create_function(:'stdlib::seeded_rand') do
# @param max The maximum value.
# @param seed The seed used for repeatable randomness.
#
# @return [Integer]
# A random number greater than or equal to 0 and less than max
dispatch :seeded_rand do
param 'Integer[1]', :max
param 'String', :seed
end
def seeded_rand(max, seed)
require 'digest/md5'
seed = Digest::MD5.hexdigest(seed).hex
Puppet::Util.deterministic_rand_int(seed, max)
end
end

View file

@ -0,0 +1,32 @@
# frozen_string_literal: true
# @summary
# Generates a consistent random string of specific length based on provided seed.
#
# @example Generate a consistently random string of length 8 with a seed:
# stdlib::seeded_rand_string(8, "${module_name}::redis_password")
#
# @example Generate a random string from a specific set of characters:
# stdlib::seeded_rand_string(5, '', 'abcdef')
Puppet::Functions.create_function(:'stdlib::seeded_rand_string') do
# @param length Length of string to be generated.
# @param seed Seed string.
# @param charset String that contains characters to use for the random string.
#
# @return [String] Random string.
dispatch :rand_string do
param 'Integer[1]', :length
param 'String', :seed
optional_param 'String[2]', :charset
end
def rand_string(length, seed, charset = nil)
require 'digest/sha2'
charset ||= '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
random_generator = Random.new(Digest::SHA256.hexdigest(seed).to_i(16))
Array.new(length) { charset[random_generator.rand(charset.size)] }.join
end
end

View file

@ -0,0 +1,26 @@
# frozen_string_literal: true
require 'digest'
# @summary
# Run a SHA256 calculation against a given value.
Puppet::Functions.create_function(:'stdlib::sha256') do
# @param my_data The ScalarData to evaluate
# @example Check a simple string value
# stdlib::sha256('my string') == '2f7e2089add0288a309abd71ffcc3b3567e2d4215e20e6ed3b74d6042f7ef8e5'
# @example Check a Sensitive datatype
# stdlib::sha256(sensitive('my string')) == '2f7e2089add0288a309abd71ffcc3b3567e2d4215e20e6ed3b74d6042f7ef8e5'
# @example Check a number
# stdlib::sha256(100.0) == '43b87f618caab482ebe4976c92bcd6ad308b48055f1c27b4c574f3e31d7683e0'
# stdlib::sha256(100.00000) == '43b87f618caab482ebe4976c92bcd6ad308b48055f1c27b4c574f3e31d7683e0'
# @return String
dispatch :sha256 do
param 'Variant[ScalarData, Sensitive[ScalarData], Binary, Sensitive[Binary]]', :my_data
return_type 'String'
end
def sha256(my_data)
Digest::SHA256.hexdigest(my_data.unwrap.to_s)
rescue StandardError
Digest::SHA256.hexdigest(my_data.to_s)
end
end

View file

@ -0,0 +1,25 @@
# frozen_string_literal: true
# @summary
# Escapes a string so that it can be safely used in a Bourne shell command line.
#
# >* Note:* that the resulting string should be used unquoted and is not intended for use in double quotes nor in single
# quotes.
#
# This function behaves the same as ruby's Shellwords.shellescape() function.
Puppet::Functions.create_function(:'stdlib::shell_escape') do
# @param string
# The string to escape
#
# @return
# An escaped string that can be safely used in a Bourne shell command line.
dispatch :shell_escape do
param 'Any', :string
end
def shell_escape(string)
require 'shellwords'
Shellwords.shellescape(string.to_s)
end
end

View file

@ -0,0 +1,49 @@
# frozen_string_literal: true
# @summary Sort an Array, Hash or String by mapping values through a given block.
#
# @example Sort local devices according to their used space.
# $facts['mountpoints'].stdlib::sort_by |$m| { $m.dig(1, 'used_bytes') }
#
Puppet::Functions.create_function(:'stdlib::sort_by') do
# @param ary The Array to sort.
# @param block The block for transforming elements of ary.
# @return [Array] Returns an ordered copy of ary.
dispatch :sort_by_array do
param 'Array', :ary
block_param 'Callable[1,1]', :block
end
# @param str The String to sort.
# @param block The block for transforming elements of str.
# @return [String] Returns an ordered copy of str.
dispatch :sort_by_string do
param 'String', :str
block_param 'Callable[1,1]', :block
end
# @param hsh The Hash to sort.
# @param block The block for transforming elements of hsh.
# The block may have arity of one or two.
# @return [Hash] Returns an ordered copy of hsh.
dispatch :sort_by_hash do
param 'Hash', :hsh
block_param 'Variant[Callable[1,1], Callable[2,2]]', :block
end
def sort_by_iterable(iterable, &block)
Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable).sort_by(&block)
end
def sort_by_array(ary, &block)
sort_by_iterable(ary, &block)
end
def sort_by_string(str, &block)
sort_by_iterable(str, &block).join
end
def sort_by_hash(hsh, &block)
sort_by_iterable(hsh, &block).to_h
end
end

View file

@ -0,0 +1,23 @@
# frozen_string_literal: true
# @summary
# Returns true if str starts with one of the prefixes given. Each of the prefixes should be a String.
#
Puppet::Functions.create_function(:'stdlib::start_with') do
# @param test_string The string to check
# @param prefixes The prefixes to check.
# @example
# 'foobar'.stdlib::start_with('foo') => true
# 'foobar'.stdlib::start_with('bar') => false
# 'foObar'.stdlib::start_with(['bar', 'baz']) => false
# @return [Boolean] True or False
dispatch :start_with do
param 'String', :test_string
param 'Variant[String[1],Array[String[1], 1]]', :prefixes
return_type 'Boolean'
end
def start_with(test_string, prefixes)
test_string.start_with?(*prefixes)
end
end

View file

@ -0,0 +1,35 @@
# frozen_string_literal: true
# @summary
# This converts a string to a puppet resource.
#
# This attempts to convert a string like 'File[/foo]' into the
# puppet resource `File['/foo']` as detected by the catalog.
#
# Things like 'File[/foo, /bar]' are not supported as a
# title might contain things like ',' or ' '. There is
# no clear value seperator to use.
#
# This function can depend on the parse order of your
# manifests/modules as it inspects the catalog thus far.
Puppet::Functions.create_function(:'stdlib::str2resource') do
# @param res_string The string to lookup as a resource
# @example
# stdlib::str2resource('File[/foo]') => File[/foo]
# @return Puppet::Resource
dispatch :str2resource do
param 'String', :res_string
# return_type 'Puppet::Resource'
return_type 'Any'
end
def str2resource(res_string)
type_name, title = Puppet::Resource.type_and_title(res_string, nil)
resource = closure_scope.findresource(type_name, title)
raise(Puppet::ParseError, "stdlib::str2resource(): could not find #{type_name}[#{title}], this is parse order dependent and values should not be quoted") if resource.nil?
resource
end
end

View file

@ -0,0 +1,24 @@
# frozen_string_literal: true
require 'json'
# @summary
# Convert a data structure and output to JSON
Puppet::Functions.create_function(:'stdlib::to_json') do
# @param data
# Data structure which needs to be converted into JSON
#
# @example Output JSON to a file
# file { '/tmp/my.json':
# ensure => file,
# content => stdlib::to_json($myhash),
# }
#
# @return [String] Converted data to JSON
dispatch :to_json do
param 'Any', :data
end
def to_json(data)
data.to_json
end
end

View file

@ -0,0 +1,74 @@
# frozen_string_literal: true
require 'json'
# @summary
# Convert data structure and output to pretty JSON
#
# @example **Usage**
# * how to output pretty JSON to file
# file { '/tmp/my.json':
# ensure => file,
# content => stdlib::to_json_pretty($myhash),
# }
#
# * how to output pretty JSON skipping over keys with undef values
# file { '/tmp/my.json':
# ensure => file,
# content => stdlib::to_json_pretty({
# param_one => 'value',
# param_two => undef,
# }, true),
# }
#
# * how to output pretty JSON using tabs for indentation
# file { '/tmp/my.json':
# ensure => file,
# content => stdlib::to_json_pretty({
# param_one => 'value',
# param_two => {
# param_more => 42,
# },
# }, nil, {indent => ' '}),
# }
Puppet::Functions.create_function(:'stdlib::to_json_pretty') do
# @param data
# data structure which needs to be converted to pretty json
# @param skip_undef
# value `true` or `false`
# @param opts
# hash-map of settings passed to JSON.pretty_generate, see
# https://ruby-doc.org/stdlib-2.0.0/libdoc/json/rdoc/JSON.html#method-i-generate.
# Note that `max_nesting` doesn't take the value `false`; use `-1` instead.
# @return
# converted data to pretty json
dispatch :to_json_pretty do
param 'Variant[Hash, Array]', :data
optional_param 'Optional[Boolean]', :skip_undef
optional_param 'Struct[{
indent => Optional[String],
space => Optional[String],
space_before => Optional[String],
object_nl => Optional[String],
array_nl => Optional[String],
allow_nan => Optional[Boolean],
max_nesting => Optional[Integer[-1,default]],
}]', :opts
end
def to_json_pretty(data, skip_undef = false, opts = nil)
# It's not possible to make an abstract type that can be either a boolean
# false or an integer, so we use -1 as the falsey value
if opts
opts = opts.transform_keys(&:to_sym)
opts[:max_nesting] = false if opts[:max_nesting] == -1
end
data = data.compact if skip_undef && (data.is_a?(Array) || Hash)
# Call ::JSON to ensure it references the JSON library from Ruby's standard library
# instead of a random JSON namespace that might be in scope due to user code.
JSON.pretty_generate(data, opts) << "\n"
end
end

View file

@ -0,0 +1,42 @@
# frozen_string_literal: true
# @summary
# Convert an object into a String containing its Python representation
#
# @example how to output Python
# # output Python to a file
# $listen = '0.0.0.0'
# $port = 8000
# file { '/opt/acme/etc/settings.py':
# content => inline_epp(@("SETTINGS")),
# LISTEN = <%= stdlib::to_python($listen) %>
# PORT = <%= stdlib::to_python($mailserver) %>
# | SETTINGS
# }
Puppet::Functions.create_function(:'stdlib::to_python') do
# @param object
# The object to be converted
#
# @return [String]
# The String representation of the object
dispatch :to_python do
param 'Any', :object
end
def to_python(object)
serialized = Puppet::Pops::Serialization::ToDataConverter.convert(object, rich_data: true)
serialized_to_python(serialized)
end
def serialized_to_python(serialized)
case serialized
when true then 'True'
when false then 'False'
when nil then 'None'
when Array then "[#{serialized.map { |x| serialized_to_python(x) }.join(', ')}]"
when Hash then "{#{serialized.map { |k, v| "#{serialized_to_python(k)}: #{serialized_to_python(v)}" }.join(', ')}}"
else serialized.inspect
end
end
end

View file

@ -0,0 +1,39 @@
# frozen_string_literal: true
# @summary
# Convert an object into a String containing its Ruby representation
#
# @example how to output Ruby
# # output Ruby to a file
# $listen = '0.0.0.0'
# $port = 8000
# file { '/opt/acme/etc/settings.rb':
# content => inline_epp(@("SETTINGS")),
# LISTEN = <%= stdlib::to_ruby($listen) %>
# PORT = <%= stdlib::to_ruby($mailserver) %>
# | SETTINGS
# }
Puppet::Functions.create_function(:'stdlib::to_ruby') do
# @param object
# The object to be converted
#
# @return [String]
# The String representation of the object
dispatch :to_ruby do
param 'Any', :object
end
def to_ruby(object)
serialized = Puppet::Pops::Serialization::ToDataConverter.convert(object, rich_data: true)
serialized_to_ruby(serialized)
end
def serialized_to_ruby(serialized)
case serialized
when Array then "[#{serialized.map { |x| serialized_to_ruby(x) }.join(', ')}]"
when Hash then "{#{serialized.map { |k, v| "#{serialized_to_ruby(k)} => #{serialized_to_ruby(v)}" }.join(', ')}}"
else serialized.inspect
end
end
end

View file

@ -0,0 +1,22 @@
# frozen_string_literal: true
require_relative '../../../puppet_x/stdlib/toml_dumper'
# @summary Convert a data structure and output to TOML.
Puppet::Functions.create_function(:'stdlib::to_toml') do
# @param data Data structure which needs to be converted into TOML
# @return [String] Converted data as TOML string
# @example How to output TOML to a file
# file { '/tmp/config.toml':
# ensure => file,
# content => stdlib::to_toml($myhash),
# }
dispatch :to_toml do
required_param 'Hash', :data
return_type 'String'
end
def to_toml(data)
PuppetX::Stdlib::TomlDumper.new(data).toml_str
end
end

View file

@ -0,0 +1,32 @@
# frozen_string_literal: true
require 'yaml'
# @summary
# Convert a data structure and output it as YAML
Puppet::Functions.create_function(:'stdlib::to_yaml') do
# @param data
# The data you want to convert to YAML
# @param options
# A hash of options that will be passed to Ruby's Psych library. Note, this could change between Puppet versions, but at time of writing these are `line_width`, `indentation`, and `canonical`.
#
# @example Output YAML to a file
# file { '/tmp/my.yaml':
# ensure => file,
# content => stdlib::to_yaml($myhash),
# }
# @example Use options to control the output format
# file { '/tmp/my.yaml':
# ensure => file,
# content => stdlib::to_yaml($myhash, {indentation => 4})
# }
#
# @return [String] The YAML document
dispatch :to_yaml do
param 'Any', :data
optional_param 'Hash', :options
end
def to_yaml(data, options = {})
data.to_yaml(options.transform_keys(&:to_sym))
end
end

View file

@ -0,0 +1,26 @@
# frozen_string_literal: true
# @summary
# Returns the type of the passed value.
#
# @example how to compare values' types
# # compare the types of two values
# if stdlib::type_of($first_value) != stdlib::type_of($second_value) { fail("first_value and second_value are different types") }
# @example how to compare against an abstract type
# unless stdlib::type_of($first_value) <= Numeric { fail("first_value must be Numeric") }
# unless stdlib::type_of{$first_value) <= Collection[1] { fail("first_value must be an Array or Hash, and contain at least one element") }
#
# See the documentation for "The Puppet Type System" for more information about types.
# See the `assert_type()` function for flexible ways to assert the type of a value.
#
# The built-in type() function in puppet is generally preferred over this function
# this function is provided for backwards compatibility.
Puppet::Functions.create_function(:'stdlib::type_of') do
# @return [String]
# the type of the passed value
#
# @param value
def type_of(value)
Puppet::Pops::Types::TypeCalculator.infer_set(value)
end
end

View file

@ -0,0 +1,34 @@
# frozen_string_literal: true
# @summary
# Validate that all values passed are syntactically correct domain names.
# Fail compilation if any value fails this check.
Puppet::Functions.create_function(:'stdlib::validate_domain_name') do
# @param values A domain name or an array of domain names to check
#
# @return [Undef]
# passes when the given values are syntactically correct domain names or raise an error when they are not and fails compilation
#
# @example Passing examples
# $my_domain_name = 'server.domain.tld'
# stdlib::validate_domain_name($my_domain_name)
# stdlib::validate_domain_name('domain.tld', 'puppet.com', $my_domain_name)
# stdlib::validate_domain_name('www.example.2com')
#
# @example Failing examples (causing compilation to abort)
# stdlib::validate_domain_name(1)
# stdlib::validate_domain_name(true)
# stdlib::validate_domain_name('invalid domain')
# stdlib::validate_domain_name('-foo.example.com')
dispatch :validate_domain_name do
repeated_param 'Variant[Stdlib::Fqdn, Stdlib::Dns::Zone]', :values
end
def validate_domain_name(*args)
assert_arg_count(args)
end
def assert_arg_count(args)
raise(ArgumentError, 'stdlib::validate_domain_name(): Wrong number of arguments need at least one') if args.empty?
end
end

View file

@ -0,0 +1,31 @@
# frozen_string_literal: true
# @summary
# Validate that all values passed are valid email addresses.
# Fail compilation if any value fails this check.
Puppet::Functions.create_function(:'stdlib::validate_email_address') do
# @param values An e-mail address or an array of e-mail addresses to check
#
# @return [Undef]
# Fail compilation if any value fails this check.
#
# @example Passing examples
# $my_email = "waldo@gmail.com"
# stdlib::validate_email_address($my_email)
# stdlib::validate_email_address("bob@gmail.com", "alice@gmail.com", $my_email)
#
# @example Failing examples (causing compilation to abort)
# $some_array = [ 'bad_email@/d/efdf.com' ]
# stdlib::validate_email_address($some_array)
dispatch :validate_email_address do
repeated_param 'Stdlib::Email', :values
end
def validate_email_address(*args)
assert_arg_count(args)
end
def assert_arg_count(args)
raise(ArgumentError, 'stdlib::validate_email_address(): Wrong number of arguments need at least one') if args.empty?
end
end

View file

@ -0,0 +1,30 @@
# frozen_string_literal: true
# @summary Encode strings for XML files
#
# This function can encode strings such that they can be used directly in XML files.
# It supports encoding for both XML text (CharData) or attribute values (AttValue).
Puppet::Functions.create_function(:'stdlib::xml_encode') do
# @param str The string to encode
# @param type Whether to encode for text or an attribute
# @return Returns the encoded CharData or AttValue string suitable for use in XML
# @example Creating an XML file from a template
# file { '/path/to/config.xml':
# ensure => file,
# content => epp(
# 'mymodule/config.xml.epp',
# {
# password => $password.stdlib::xml_encode,
# },
# ),
# }
dispatch :xml_encode do
param 'String', :str
optional_param "Enum['text','attr']", :type
return_type 'String'
end
def xml_encode(str, type = 'text')
str.encode(xml: type.to_sym)
end
end

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
# @summary DEPRECATED. Use the native Puppet fuctionality instead of this function. eg `Integer(Timestamp().strftime('%s'))`
Puppet::Functions.create_function(:time) do
dispatch :call_puppet_function do
repeated_param 'Any', :args
end
def call_puppet_function(*args)
# Note, `stdlib::time` calls `deprecation`, so we don't also do that here.
call_function('stdlib::time', *args)
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::to_json`](#stdlibto_json) instead.
Puppet::Functions.create_function(:to_json) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'to_json', 'This function is deprecated, please use stdlib::to_json instead.', false)
call_function('stdlib::to_json', *args)
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::to_json_pretty`](#stdlibto_json_pretty) instead.
Puppet::Functions.create_function(:to_json_pretty) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'to_json_pretty', 'This function is deprecated, please use stdlib::to_json_pretty instead.', false)
call_function('stdlib::to_json_pretty', *args)
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::to_python`](#stdlibto_python) instead.
Puppet::Functions.create_function(:to_python) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'to_python', 'This function is deprecated, please use stdlib::to_python instead.', false)
call_function('stdlib::to_python', *args)
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::to_ruby`](#stdlibto_ruby) instead.
Puppet::Functions.create_function(:to_ruby) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'to_ruby', 'This function is deprecated, please use stdlib::to_ruby instead.', false)
call_function('stdlib::to_ruby', *args)
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::to_toml`](#stdlibto_toml) instead.
Puppet::Functions.create_function(:to_toml) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'to_toml', 'This function is deprecated, please use stdlib::to_toml instead.', false)
call_function('stdlib::to_toml', *args)
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::to_yaml`](#stdlibto_yaml) instead.
Puppet::Functions.create_function(:to_yaml) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'to_yaml', 'This function is deprecated, please use stdlib::to_yaml instead.', false)
call_function('stdlib::to_yaml', *args)
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::type_of`](#stdlibtype_of) instead.
Puppet::Functions.create_function(:type_of) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'type_of', 'This function is deprecated, please use stdlib::type_of instead.', false)
call_function('stdlib::type_of', *args)
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::validate_domain_name`](#stdlibvalidate_domain_name) instead.
Puppet::Functions.create_function(:validate_domain_name) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'validate_domain_name', 'This function is deprecated, please use stdlib::validate_domain_name instead.', false)
call_function('stdlib::validate_domain_name', *args)
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`
# @summary DEPRECATED. Use the namespaced function [`stdlib::validate_email_address`](#stdlibvalidate_email_address) instead.
Puppet::Functions.create_function(:validate_email_address) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'validate_email_address', 'This function is deprecated, please use stdlib::validate_email_address instead.', false)
call_function('stdlib::validate_email_address', *args)
end
end

View file

@ -0,0 +1,68 @@
# frozen_string_literal: true
# @summary
# **Deprecated:** Validate a value against both the target_type (new).
Puppet::Functions.create_function(:validate_legacy) do
# The function checks a value against both the target_type (new).
# @param scope
# The main value that will be passed to the method
# @param target_type
# @param function_name
# Unused
# @param value
# @param args
# Any additional values that are to be passed to the method
# @return
# A boolean value (`true` or `false`) returned from the called function.
dispatch :validate_legacy do
param 'Any', :scope
param 'Type', :target_type
param 'String', :function_name
param 'Any', :value
repeated_param 'Any', :args
end
# @param scope
# The main value that will be passed to the method
# @param type_string
# @param function_name
# Unused
# @param value
# @param args Any additional values that are to be passed to the method
# @return Legacy validation method
#
dispatch :validate_legacy_s do
param 'Any', :scope
param 'String', :type_string
param 'String', :function_name
param 'Any', :value
repeated_param 'Any', :args
end
# Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-
# c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
def call(scope, *args)
manipulated_args = [scope] + args
self.class.dispatcher.dispatch(self, scope, manipulated_args)
end
def validate_legacy_s(scope, type_string, *args)
t = Puppet::Pops::Types::TypeParser.new.parse(type_string, scope)
validate_legacy(scope, t, *args)
end
def validate_legacy(_scope, target_type, _function_name, value, *_prev_args)
call_function('deprecation', 'validate_legacy', 'This method is deprecated, please use Puppet data types to validate parameters')
if assert_type(target_type, value)
# "Silently" passes
else
inferred_type = Puppet::Pops::Types::TypeCalculator.infer_set(value)
error_msg = Puppet::Pops::Types::TypeMismatchDescriber.new.describe_mismatch("validate_legacy(#{target_type}, ...)", target_type, inferred_type)
call_function('fail', error_msg)
end
end
def assert_type(type, value)
Puppet::Pops::Types::TypeCalculator.instance?(type, value)
end
end

View file

@ -0,0 +1,56 @@
# frozen_string_literal: true
#
# any2array.rb
#
module Puppet::Parser::Functions
newfunction(:any2array, type: :rvalue, doc: <<-DOC
@summary
This converts any object to an array containing that object.
Empty argument lists are converted to an empty array. Arrays are left
untouched. Hashes are converted to arrays of alternating keys and values.
> *Note:*
since Puppet 5.0.0 it is possible to create new data types for almost any
datatype using the type system and the built-in
[`Array.new`](https://puppet.com/docs/puppet/latest/function.html#conversion-to-array-and-tuple)
function is used to create a new Array..
```
$hsh = {'key' => 42, 'another-key' => 100}
notice(Array($hsh))
```
Would notice `[['key', 42], ['another-key', 100]]`
The Array data type also has a special mode to "create an array if not already an array"
```
notice(Array({'key' => 42, 'another-key' => 100}, true))
```
Would notice `[{'key' => 42, 'another-key' => 100}]`, as the `true` flag prevents the hash from being
transformed into an array.
@return [Array] The new array containing the given object
DOC
) do |arguments|
return [] if arguments.empty?
return arguments unless arguments.length == 1
return arguments[0] if arguments[0].is_a?(Array)
return [] if arguments == ['']
if arguments[0].is_a?(Hash)
result = []
arguments[0].each do |key, value|
result << key << value
end
return result
end
return arguments
end
end
# vim: set ts=2 sw=2 et :

View file

@ -0,0 +1,54 @@
# frozen_string_literal: true
#
# any2bool.rb
#
module Puppet::Parser::Functions
newfunction(:any2bool, type: :rvalue, doc: <<-DOC
@summary
Converts 'anything' to a boolean.
In practise it does the following:
* Strings such as Y,y,1,T,t,TRUE,yes,'true' will return true
* Strings such as 0,F,f,N,n,FALSE,no,'false' will return false
* Booleans will just return their original value
* Number (or a string representation of a number) > 0 will return true, otherwise false
* undef will return false
* Anything else will return true
Also see the built-in [`Boolean.new`](https://puppet.com/docs/puppet/latest/function.html#conversion-to-boolean)
function.
@return [Boolean] The boolean value of the object that was given
DOC
) do |arguments|
raise(Puppet::ParseError, "any2bool(): Wrong number of arguments given (#{arguments.size} for 1)") if arguments.empty?
# If argument is already Boolean, return it
return arguments[0] if !!arguments[0] == arguments[0] # rubocop:disable Style/DoubleNegation : Could not find a better way to check if a boolean
arg = arguments[0]
return false if arg.nil?
return false if arg == :undef
valid_float = begin
!!Float(arg) # rubocop:disable Style/DoubleNegation : Could not find a better way to check if a boolean
rescue StandardError
false
end
return function_num2bool([arguments[0]]) if arg.is_a?(Numeric)
if arg.is_a?(String)
return function_num2bool([arguments[0]]) if valid_float
return function_str2bool([arguments[0]])
end
return true
end
end
# vim: set ts=2 sw=2 et :

View file

@ -0,0 +1,33 @@
# frozen_string_literal: true
#
# assert_private.rb
#
module Puppet::Parser::Functions
newfunction(:assert_private, doc: <<-DOC
@summary
Sets the current class or definition as private.
@return
set the current class or definition as private.
Calling the class or definition from outside the current module will fail.
DOC
) do |args|
raise(Puppet::ParseError, "assert_private(): Wrong number of arguments given (#{args.size}}) for 0 or 1)") if args.size > 1
scope = self
if scope.lookupvar('module_name') != scope.lookupvar('caller_module_name')
message = nil
if args[0].is_a?(String)
message = args[0]
else
manifest_name = scope.source.name
manifest_type = scope.source.type
message = (manifest_type.to_s == 'hostclass') ? 'Class' : 'Definition'
message += " #{manifest_name} is private"
end
raise(Puppet::ParseError, message)
end
end
end

View file

@ -0,0 +1,81 @@
# frozen_string_literal: true
# Please note: This function is an implementation of a Ruby class and as such may not be entirely UTF8 compatible. To ensure compatibility please use this function with Ruby 2.4.0 or greater - https://bugs.ruby-lang.org/issues/10085.
module Puppet::Parser::Functions
newfunction(:base64, type: :rvalue, doc: <<-DOC) do |args|
@summary
Base64 encode or decode a string based on the command and the string submitted
@example Example usage
Encode and decode a string
$encodestring = base64('encode', 'thestring')
$decodestring = base64('decode', 'dGhlc3RyaW5n')
Explicitly define encode/decode method: default, strict, urlsafe
$method = 'default'
$encodestring = base64('encode', 'thestring', $method)
$decodestring = base64('decode', 'dGhlc3RyaW5n', $method)
Encode a string as if it was binary
$encodestring = String(Binary('thestring', '%s'))
Decode a Binary assuming it is an UTF-8 String
$decodestring = String(Binary("dGhlc3RyaW5n"), "%s")
> **Note:*
Since Puppet 4.8.0, the Binary data type can be used to produce base 64 encoded strings.
See the `new()` function for the Binary and String types for documentation. Also see `binary_file()`
function for reading a file with binary (non UTF-8) content.
@return [String] The encoded/decoded value
DOC
require 'base64'
raise Puppet::ParseError, "base64(): Wrong number of arguments (#{args.length}; must be >= 2)" unless args.length >= 2
actions = ['encode', 'decode']
raise Puppet::ParseError, "base64(): the first argument must be one of 'encode' or 'decode'" unless actions.include?(args[0])
raise Puppet::ParseError, 'base64(): the second argument must be a string to base64' unless args[1].is_a?(String)
method = ['default', 'strict', 'urlsafe']
chosen_method = if args.length <= 2
'default'
else
args[2]
end
raise Puppet::ParseError, "base64(): the third argument must be one of 'default', 'strict', or 'urlsafe'" unless method.include?(chosen_method)
case args[0]
when 'encode'
case chosen_method
when 'default'
result = Base64.encode64(args[1])
when 'strict'
result = Base64.strict_encode64(args[1])
when 'urlsafe'
result = Base64.urlsafe_encode64(args[1])
end
when 'decode'
case chosen_method
when 'default'
result = Base64.decode64(args[1])
when 'strict'
result = Base64.strict_decode64(args[1])
when 'urlsafe'
result = Base64.urlsafe_decode64(args[1])
end
end
return result
end
end

View file

@ -0,0 +1,29 @@
# frozen_string_literal: true
#
# basename.rb
#
module Puppet::Parser::Functions
newfunction(:basename, type: :rvalue, doc: <<-DOC
@summary
Strips directory (and optional suffix) from a filename
@return [String] The stripped filename
DOC
) do |arguments|
raise(Puppet::ParseError, 'basename(): No arguments given') if arguments.empty?
raise(Puppet::ParseError, "basename(): Too many arguments given (#{arguments.size})") if arguments.size > 2
raise(Puppet::ParseError, 'basename(): Requires string as first argument') unless arguments[0].is_a?(String)
rv = File.basename(arguments[0]) if arguments.size == 1
if arguments.size == 2
raise(Puppet::ParseError, 'basename(): Requires string as second argument') unless arguments[1].is_a?(String)
rv = File.basename(arguments[0], arguments[1])
end
return rv
end
end
# vim: set ts=2 sw=2 et :

View file

@ -0,0 +1,44 @@
# frozen_string_literal: true
#
# bool2num.rb
#
module Puppet::Parser::Functions
newfunction(:bool2num, type: :rvalue, doc: <<-DOC
@summary
Converts a boolean to a number.
Converts the values:
```
false, f, 0, n, and no to 0
true, t, 1, y, and yes to 1
```
Requires a single boolean or string as an input.
> *Note:*
since Puppet 5.0.0 it is possible to create new data types for almost any
datatype using the type system and the built-in
[`Numeric.new`](https://puppet.com/docs/puppet/latest/function.html#conversion-to-numeric),
[`Integer.new`](https://puppet.com/docs/puppet/latest/function.html#conversion-to-integer), and
[`Float.new`](https://puppet.com/docs/puppet/latest/function.html#conversion-to-float)
function are used to convert to numeric values.
```
notice(Integer(false)) # Notices 0
notice(Float(true)) # Notices 1.0
```
@return [Integer] The converted value as a number
DOC
) do |arguments|
raise(Puppet::ParseError, "bool2num(): Wrong number of arguments given (#{arguments.size} for 1)") if arguments.empty?
value = function_str2bool([arguments[0]])
# We have real boolean values as well ...
result = value ? 1 : 0
return result
end
end
# vim: set ts=2 sw=2 et :

View file

@ -0,0 +1,58 @@
# frozen_string_literal: true
#
# bool2str.rb
#
module Puppet::Parser::Functions
newfunction(:bool2str, type: :rvalue, doc: <<-DOC
@summary
Converts a boolean to a string using optionally supplied arguments.
The optional second and third arguments represent what true and false will be
converted to respectively. If only one argument is given, it will be
converted from a boolean to a string containing 'true' or 'false'.
@return
The converted value to string of the given Boolean
**Examples of usage**
```
bool2str(true) => 'true'
bool2str(true, 'yes', 'no') => 'yes'
bool2str(false, 't', 'f') => 'f'
```
Requires a single boolean as an input.
> *Note:*
since Puppet 5.0.0 it is possible to create new data types for almost any
datatype using the type system and the built-in
[`String.new`](https://puppet.com/docs/puppet/latest/function.html#boolean-to-string)
function is used to convert to String with many different format options.
```
notice(String(false)) # Notices 'false'
notice(String(true)) # Notices 'true'
notice(String(false, '%y')) # Notices 'yes'
notice(String(true, '%y')) # Notices 'no'
```
DOC
) do |arguments|
raise(Puppet::ParseError, "bool2str(): Wrong number of arguments given (#{arguments.size} for 3)") unless arguments.size == 1 || arguments.size == 3
value = arguments[0]
true_string = arguments[1] || 'true'
false_string = arguments[2] || 'false'
klass = value.class
# We can have either true or false, and nothing else
raise(Puppet::ParseError, 'bool2str(): Requires a boolean to work with') unless [FalseClass, TrueClass].include?(klass)
raise(Puppet::ParseError, 'bool2str(): Requires strings to convert to') unless [true_string, false_string].all?(String)
return value ? true_string : false_string
end
end
# vim: set ts=2 sw=2 et :

View file

@ -0,0 +1,46 @@
# frozen_string_literal: true
#
# clamp.rb
#
module Puppet::Parser::Functions
newfunction(:clamp, type: :rvalue, arity: -2, doc: <<-DOC
@summary
Keeps value within the range [Min, X, Max] by sort based on integer value
(parameter order doesn't matter).
Strings are converted and compared numerically. Arrays of values are flattened
into a list for further handling.
@example Example usage
clamp('24', [575, 187])` returns 187.
clamp(16, 88, 661)` returns 88.
clamp([4, 3, '99'])` returns 4.
> *Note:*
From Puppet 6.0.0 this can be done with only core Puppet like this:
`[$minval, $maxval, $value_to_clamp].sort[1]`
@return [Array[Integer]] The sorted Array
DOC
) do |args|
args.flatten!
raise(Puppet::ParseError, 'clamp(): Wrong number of arguments, need three to clamp') if args.size != 3
# check values out
args.each do |value|
case [value.class]
when [String]
raise(Puppet::ParseError, "clamp(): Required explicit numeric (#{value}:String)") unless %r{^\d+$}.match?(value)
when [Hash]
raise(Puppet::ParseError, "clamp(): The Hash type is not allowed (#{value})")
end
end
# convert to numeric each element
# then sort them and get a middle value
args.map(&:to_i).sort[1]
end
end

View file

@ -0,0 +1,46 @@
# frozen_string_literal: true
#
# concat.rb
#
module Puppet::Parser::Functions
newfunction(:concat, type: :rvalue, doc: <<-DOC
@summary
Appends the contents of multiple arrays into array 1.
@example Example usage
concat(['1','2','3'],'4') returns ['1','2','3','4']
concat(['1','2','3'],'4',['5','6','7']) returns ['1','2','3','4','5','6','7']
> *Note:*
Since Puppet 4.0, you can use the `+`` operator for concatenation of arrays and
merge of hashes, and the `<<`` operator for appending:
`['1','2','3'] + ['4','5','6'] + ['7','8','9']` returns `['1','2','3','4','5','6','7','8','9']`
`[1, 2, 3] << 4` returns `[1, 2, 3, 4]`
`[1, 2, 3] << [4, 5]` returns `[1, 2, 3, [4, 5]]`
@return [Array] The single concatenated array
DOC
) do |arguments|
# Check that more than 2 arguments have been given ...
raise(Puppet::ParseError, "concat(): Wrong number of arguments given (#{arguments.size} for < 2)") if arguments.size < 2
a = arguments[0]
# Check that the first parameter is an array
raise(Puppet::ParseError, 'concat(): Requires array to work with') unless a.is_a?(Array)
result = a
arguments.shift
arguments.each do |x|
result += (x.is_a?(Array) ? x : [x])
end
return result
end
end
# vim: set ts=2 sw=2 et :

View file

@ -0,0 +1,49 @@
# frozen_string_literal: true
#
# convert_base.rb
#
module Puppet::Parser::Functions
newfunction(:convert_base, type: :rvalue, arity: 2, doc: <<-DOC) do |args|
@summary
Converts a given integer or base 10 string representing an integer to a
specified base, as a string.
@return
converted value as a string
@example Example usage
convert_base(5, 2)` results in: `'101'`
convert_base('254', '16')` results in: `'fe'`
> *Note:*
Since Puppet 4.5.0 this can be done with the built-in
[`String.new`](https://puppet.com/docs/puppet/latest/function.html#integer-to-string)
function and its many formatting options:
`$binary_repr = String(5, '%b')` return `"101"`
`$hex_repr = String(254, "%x")` return `"fe"`
`$hex_repr = String(254, "%#x")` return `"0xfe"`
@return [String] The converted value as a String
DOC
raise Puppet::ParseError, 'convert_base(): First argument must be either a string or an integer' unless args[0].is_a?(Integer) || args[0].is_a?(String)
raise Puppet::ParseError, 'convert_base(): Second argument must be either a string or an integer' unless args[1].is_a?(Integer) || args[1].is_a?(String)
raise Puppet::ParseError, 'convert_base(): First argument must be an integer or a string corresponding to an integer in base 10' if args[0].is_a?(String) && !%r{^[0-9]+$}.match?(args[0])
raise Puppet::ParseError, 'convert_base(): First argument must be an integer or a string corresponding to an integer in base 10' if args[1].is_a?(String) && !%r{^[0-9]+$}.match?(args[1])
number_to_convert = args[0]
new_base = args[1]
number_to_convert = number_to_convert.to_i
new_base = new_base.to_i
raise Puppet::ParseError, 'convert_base(): base must be at least 2 and must not be greater than 36' unless new_base >= 2 && new_base <= 36
return number_to_convert.to_s(new_base)
end
end

View file

@ -0,0 +1,40 @@
# frozen_string_literal: true
#
# count.rb
#
module Puppet::Parser::Functions
newfunction(:count, type: :rvalue, arity: -2, doc: <<-DOC
@summary
Counts the number of elements in array.
Takes an array as first argument and an optional second argument. Counts the number of elements in array that is equal to the second argument.
If called with only an array, it counts the number of elements that are not nil/undef/empty-string.
> *Note:*
equality is tested with a Ruby method and it is therefore subject to what Ruby considers
to be equal. For strings this means that equality is case sensitive.
In Puppet core, counting can be done in general by using a combination of the core functions
filter() (since Puppet 4.0.0) and length() (since Puppet 5.5.0, before that in stdlib).
Example below shows counting values that are not undef.
```notice([42, "hello", undef].filter |$x| { $x =~ NotUndef }.length)```
Would notice the value 2.
@return [Integer] The amount of elements counted within the array
DOC
) do |args|
raise(ArgumentError, "count(): Wrong number of arguments given #{args.size} for 1 or 2.") if args.size > 2
collection, item = args
if item
collection.count item
else
collection.count { |obj| !obj.nil? && obj != :undef && obj != '' }
end
end
end

View file

@ -0,0 +1,49 @@
# frozen_string_literal: true
#
# deep_merge.rb
#
module Puppet::Parser::Functions
newfunction(:deep_merge, type: :rvalue, doc: <<-DOC) do |args|
@summary
Recursively merges two or more hashes together and returns the resulting hash.
@example Example usage
$hash1 = {'one' => 1, 'two' => 2, 'three' => { 'four' => 4 } }
$hash2 = {'two' => 'dos', 'three' => { 'five' => 5 } }
$merged_hash = deep_merge($hash1, $hash2)
The resulting hash is equivalent to:
$merged_hash = { 'one' => 1, 'two' => 'dos', 'three' => { 'four' => 4, 'five' => 5 } }
When there is a duplicate key that is a hash, they are recursively merged.
When there is a duplicate key that is not a hash, the key in the rightmost hash will "win."
@return [Hash] The merged hash
DOC
raise Puppet::ParseError, "deep_merge(): wrong number of arguments (#{args.length}; must be at least 2)" if args.length < 2
deep_merge = proc do |hash1, hash2|
hash1.merge(hash2) do |_key, old_value, new_value|
if old_value.is_a?(Hash) && new_value.is_a?(Hash)
deep_merge.call(old_value, new_value)
else
new_value
end
end
end
result = {}
args.each do |arg|
next if arg.is_a?(String) && arg.empty? # empty string is synonym for puppet's undef
# If the argument was not a hash, skip it.
raise Puppet::ParseError, "deep_merge: unexpected argument type #{arg.class}, only expects hash arguments" unless arg.is_a?(Hash)
result = deep_merge.call(result, arg)
end
return(result)
end
end

View file

@ -0,0 +1,78 @@
# frozen_string_literal: true
# Test whether a given class or definition is defined
require 'puppet/parser/functions'
Puppet::Parser::Functions.newfunction(:defined_with_params, type: :rvalue, doc: <<-DOC
@summary
Takes a resource reference and an optional hash of attributes.
Returns `true` if a resource with the specified attributes has already been added
to the catalog, and `false` otherwise.
```
user { 'dan':
ensure => present,
}
if ! defined_with_params(User[dan], {'ensure' => 'present' }) {
user { 'dan': ensure => present, }
}
```
@return [Boolean]
returns `true` or `false`
DOC
) do |vals|
reference, params = vals
raise(ArgumentError, 'Must specify a reference') unless reference
params = {} if !params || params == ''
ret = false
if Puppet::Util::Package.versioncmp(Puppet.version, '4.6.0') >= 0
# Workaround for PE-20308
if reference.is_a?(String)
type_name, title = Puppet::Resource.type_and_title(reference, nil)
type = Puppet::Pops::Evaluator::Runtime3ResourceSupport.find_resource_type_or_class(find_global_scope, type_name.downcase)
elsif reference.is_a?(Puppet::Resource)
type = reference.type
title = reference.title
else
raise(ArgumentError, "Reference is not understood: '#{reference.class}'")
end
# end workaround
else
type = reference.to_s
title = nil
end
resources = if title.empty?
catalog.resources.select { |r| r.type == type }
else
[findresource(type, title)]
end
resources.compact.each do |res|
# If you call this from within a defined type, it will find itself
next if res.to_s == resource.to_s
matches = params.map do |key, value|
# eql? avoids bugs caused by monkeypatching in puppet
res_is_undef = res[key].eql?(:undef) || res[key].nil?
value_is_undef = value.eql?(:undef) || value.nil?
found_match = (res_is_undef && value_is_undef) || (res[key] == value)
Puppet.debug("Matching resource is #{res}") if found_match
found_match
end
ret = params.empty? || !matches.include?(false)
break if ret
end
Puppet.debug("Resource #{reference} was not determined to be defined") unless ret
ret
end

View file

@ -0,0 +1,68 @@
# frozen_string_literal: true
#
# delete.rb
#
module Puppet::Parser::Functions
newfunction(:delete, type: :rvalue, doc: <<-DOC
@summary
Deletes all instances of a given element from an array, substring from a
string, or key from a hash.
@example Example usage
delete(['a','b','c','b'], 'b')
Would return: ['a','c']
delete({'a'=>1,'b'=>2,'c'=>3}, 'b')
Would return: {'a'=>1,'c'=>3}
delete({'a'=>1,'b'=>2,'c'=>3}, ['b','c'])
Would return: {'a'=>1}
delete('abracadabra', 'bra')
Would return: 'acada'
['a', 'b', 'c', 'b'] - 'b'
Would return: ['a', 'c']
{'a'=>1,'b'=>2,'c'=>3} - ['b','c'])
Would return: {'a' => '1'}
'abracadabra'.regsubst(/bra/, '', 'G')
Would return: 'acada'
> *Note:*
From Puppet 4.0.0 the minus (-) operator deletes values from arrays and keys from a hash
`{'a'=>1,'b'=>2,'c'=>3} - ['b','c'])`
>
A global delete from a string can be performed with the
[`regsubst`](https://puppet.com/docs/puppet/latest/function.html#regsubst) function:
`'abracadabra'.regsubst(/bra/, '', 'G')`
In general, the built-in [`filter`](https://puppet.com/docs/puppet/latest/function.html#filter)
function can filter out entries from arrays and hashes based on keys and/or values.
@return [String] The filtered String, if one was given.
@return [Hash] The filtered Hash, if one was given.
@return [Array] The filtered Array, if one was given.
DOC
) do |arguments|
raise(Puppet::ParseError, "delete(): Wrong number of arguments given #{arguments.size} for 2") unless arguments.size == 2
collection = arguments[0].dup
Array(arguments[1]).each do |item|
case collection
when Array, Hash
collection.delete item
when String
collection.gsub! item, ''
else
raise(TypeError, "delete(): First argument must be an Array, String, or Hash. Given an argument of class #{collection.class}.")
end
end
collection
end
end
# vim: set ts=2 sw=2 et :

Some files were not shown because too many files have changed in this diff Show more