summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTP Honey <tphoney@users.noreply.github.com>2017-08-11 09:56:53 +0100
committerGitHub <noreply@github.com>2017-08-11 09:56:53 +0100
commitc7ac34da3a8b70500143e326f8c4fa27ae7da311 (patch)
tree26721306dc6501ada77e48111b8e94f9856cf0b8
parentb89d5f388ca701e38a0e0337408f5ccb7e68565f (diff)
parent016f4dfd7f0c8a6b5b98fa38cf70434603c75883 (diff)
Merge branch 'master' into release
-rw-r--r--.travis.yml6
-rw-r--r--CHANGELOG.md96
-rw-r--r--Gemfile15
-rw-r--r--README.md135
-rw-r--r--appveyor.yml22
-rw-r--r--lib/puppet/functions/fact.rb58
-rw-r--r--lib/puppet/parser/functions/ensure_packages.rb6
-rw-r--r--lib/puppet/parser/functions/pw_hash.rb7
-rw-r--r--lib/puppet/parser/functions/round.rb33
-rw-r--r--lib/puppet/parser/functions/unique.rb4
-rw-r--r--lib/puppet/parser/functions/validate_domain_name.rb39
-rw-r--r--lib/puppet/provider/file_line/ruby.rb103
-rw-r--r--lib/puppet/type/file_line.rb18
-rw-r--r--spec/aliases/absolutepath_spec.rb2
-rw-r--r--spec/aliases/float_spec.rb2
-rw-r--r--spec/aliases/integer_spec.rb10
-rw-r--r--spec/aliases/numeric_spec.rb2
-rw-r--r--spec/aliases/string_spec.rb2
-rwxr-xr-xspec/functions/deep_merge_spec.rb2
-rwxr-xr-xspec/functions/ensure_packages_spec.rb12
-rw-r--r--spec/functions/ensure_resources_spec.rb25
-rwxr-xr-xspec/functions/is_integer_spec.rb3
-rwxr-xr-xspec/functions/merge_spec.rb2
-rw-r--r--spec/functions/pw_hash_spec.rb8
-rwxr-xr-xspec/functions/round_spec.rb14
-rwxr-xr-xspec/functions/strftime_spec.rb4
-rwxr-xr-xspec/functions/unique_spec.rb46
-rw-r--r--spec/functions/validate_domain_name_spec.rb35
-rw-r--r--spec/unit/ensure_resources_spec.rb22
-rwxr-xr-xspec/unit/puppet/provider/file_line/ruby_spec.rb58
-rw-r--r--types/mac.pp2
31 files changed, 601 insertions, 192 deletions
diff --git a/.travis.yml b/.travis.yml
index 4981b25..0c6f904 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -22,10 +22,10 @@ matrix:
script: bundle exec rake beaker
services: docker
sudo: required
- - rvm: 2.3.1
+ - rvm: 2.4.0
bundler_args: --without system_tests
- env: PUPPET_GEM_VERSION="~> 4.0"
- - rvm: 2.1.7
+ env: PUPPET_GEM_VERSION="~> 5.0"
+ - rvm: 2.1.9
bundler_args: --without system_tests
env: PUPPET_GEM_VERSION="~> 4.0"
notifications:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 39d892e..73b889c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -70,7 +70,7 @@ This release introduces multiple new functions, a new fact and the addition of U
- Addition of FQDN UUID generation function.
- Addition of Ubuntu Xenial to OS Support.
-####Bugfixes
+#### Bugfixes
- Ensure_packages now works with Ruby < 2.0.
- Updated the documentation of str2bool function.
@@ -156,11 +156,11 @@ Special thanks to [Voxpupuli's](https://voxpupuli.org/) Igor Galić for donating
* Puppet 4.5.0 (PE 2016.2) has a number of improvements around data types - especially error handling - that make working with them much nicer.
## Supported Release 4.12.0
-###Summary
+### Summary
This release provides several new functions, bugfixes, modulesync changes, and some documentation updates.
-####Features
+#### Features
- Adds `clamp`. This function keeps values within a specified range.
- Adds `validate_x509_rsa_key_pair`. This function validates an x509 RSA certificate and key pair.
- Adds `dig`. This function performs a deep lookup in nested hashes or arrays.
@@ -172,7 +172,7 @@ This release provides several new functions, bugfixes, modulesync changes, and s
- Apply modulesync changes.
- Add validate_email_address function.
-####Bugfixes
+#### Bugfixes
- Fixes `fqdn_rand_string` tests, since Puppet 4.4.0 and later have a higher `fqdn_rand` ceiling.
- (MODULES-3152) Adds a check to `package_provider` to prevent failures if Gem is not installed.
- Fixes to README.md.
@@ -181,39 +181,39 @@ This release provides several new functions, bugfixes, modulesync changes, and s
- Fixes concat with Hash arguments.
## Supported Release 4.11.0
-###Summary
+### Summary
Provides a validate_absolute_paths and Debian 8 support. There is a fix to the is_package_provider fact and a test improvement.
-####Features
+#### Features
- Adds new parser called is_absolute_path
- Supports Debian 8
-####Bugfixes
+#### Bugfixes
- Allow package_provider fact to resolve on PE 3.x
-####Improvements
+#### Improvements
- ensures that the test passes independently of changes to rubygems for ensure_resource
-##2015-12-15 - Supported Release 4.10.0
-###Summary
+## 2015-12-15 - Supported Release 4.10.0
+### Summary
Includes the addition of several new functions and considerable improvements to the existing functions, tests and documentation. Includes some bug fixes which includes compatibility, test and fact issues.
-####Features
+#### Features
- Adds service_provider fact
- Adds is_a() function
- Adds package_provider fact
- Adds validate_ip_address function
- Adds seeded_rand function
-####Bugfixes
+#### Bugfixes
- Fix backwards compatibility from an improvement to the parseyaml function
- Renaming of load_module_metadata test to include _spec.rb
- Fix root_home fact on AIX 5.x, now '-c' rather than '-C'
- Fixed Gemfile to work with ruby 1.8.7
-####Improvements
+#### Improvements
- (MODULES-2462) Improvement of parseyaml function
- Improvement of str2bool function
- Improvement to readme
@@ -228,26 +228,26 @@ Includes the addition of several new functions and considerable improvements to
- Improvement to naming convention in validate_ipv4_address function
## Supported Release 4.9.1
-###Summary
+### Summary
Small release for support of newer PE versions. This increments the version of PE in the metadata.json file.
-##2015-09-08 - Supported Release 4.9.0
-###Summary
+## 2015-09-08 - Supported Release 4.9.0
+### Summary
This release adds new features including the new functions dos2unix, unix2dos, try_get_value, convert_base as well as other features and improvements.
-####Features
+#### Features
- (MODULES-2370) allow `match` parameter to influence `ensure => absent` behavior
- (MODULES-2410) Add new functions dos2unix and unix2dos
- (MODULE-2456) Modify union to accept more than two arrays
- Adds a convert_base function, which can convert numbers between bases
- Add a new function "try_get_value"
-####Bugfixes
+#### Bugfixes
- n/a
-####Improvements
+#### Improvements
- (MODULES-2478) Support root_home fact on AIX through "lsuser" command
- Acceptance test improvements
- Unit test improvements
@@ -266,15 +266,15 @@ This release adds a function for reading metadata.json from any module, and expa
- Fix various docs typos
- Fix `file_line` resource on puppet < 3.3
-##2015-06-22 - Supported Release 4.7.0
-###Summary
+## 2015-06-22 - Supported Release 4.7.0
+### Summary
Adds Solaris 12 support along with improved Puppet 4 support. There are significant test improvements, and some minor fixes.
-####Features
+#### Features
- Add support for Solaris 12
-####Bugfixes
+#### Bugfixes
- Fix for AIO Puppet 4
- Fix time for ruby 1.8.7
- Specify rspec-puppet version
@@ -284,7 +284,7 @@ Adds Solaris 12 support along with improved Puppet 4 support. There are signific
- catch and rescue from looking up non-existent facts
- Use puppet_install_helper, for Puppet 4
-####Improvements
+#### Improvements
- Enforce support for Puppet 4 testing
- fqdn_rotate/fqdn_rand_string acceptance tests and implementation
- Simplify mac address regex
@@ -295,12 +295,12 @@ Adds Solaris 12 support along with improved Puppet 4 support. There are signific
- Add validate_slength optional 3rd arg
- Move tests directory to examples directory
-##2015-04-14 - Supported Release 4.6.0
-###Summary
+## 2015-04-14 - Supported Release 4.6.0
+### Summary
Adds functions and function argument abilities, and improves compatibility with the new puppet parser
-####Features
+#### Features
- MODULES-444: `concat()` can now take more than two arrays
- `basename()` added to have Ruby File.basename functionality
- `delete()` can now take an array of items to remove
@@ -317,7 +317,7 @@ Adds functions and function argument abilities, and improves compatibility with
- Adds `validate_integer()`
- Adds `validate_numeric()` (like `validate_integer()` but also accepts floats)
-####Bugfixes
+#### Bugfixes
- Fix seeding of `fqdn_rotate()`
- `ensure_resource()` is more verbose on debug mode
- Stricter argument checking for `dirname()`
@@ -325,37 +325,37 @@ Adds functions and function argument abilities, and improves compatibility with
- Fix `uriescape()` when called with array
- Fix `file_line` resource when using the `after` attribute with `match`
-##2015-01-14 - Supported Release 4.5.1
-###Summary
+## 2015-01-14 - Supported Release 4.5.1
+### Summary
This release changes the temporary facter_dot_d cache locations outside of the /tmp directory due to a possible security vunerability. CVE-2015-1029
-####Bugfixes
+#### Bugfixes
- Facter_dot_d cache will now be stored in puppet libdir instead of tmp
-##2014-12-15 - Supported Release 4.5.0
-###Summary
+## 2014-12-15 - Supported Release 4.5.0
+### Summary
This release improves functionality of the member function and adds improved future parser support.
-####Features
+#### Features
- MODULES-1329: Update member() to allow the variable to be an array.
- Sync .travis.yml, Gemfile, Rakefile, and CONTRIBUTING.md via modulesync
-####Bugfixes
+#### Bugfixes
- Fix range() to work with numeric ranges with the future parser
- Accurately express SLES support in metadata.json (was missing 10SP4 and 12)
- Don't require `line` to match the `match` parameter
-##2014-11-10 - Supported Release 4.4.0
-###Summary
+## 2014-11-10 - Supported Release 4.4.0
+### Summary
This release has an overhauled readme, new private manifest function, and fixes many future parser bugs.
-####Features
+#### Features
- All new shiny README
- New `private()` function for making private manifests (yay!)
-####Bugfixes
+#### Bugfixes
- Code reuse in `bool2num()` and `zip()`
- Fix many functions to handle `generate()` no longer returning a string on new puppets
- `concat()` no longer modifies the first argument (whoops)
@@ -367,20 +367,20 @@ This release has an overhauled readme, new private manifest function, and fixes
- Fix `file_line` matching on older rubies
-##2014-07-15 - Supported Release 4.3.2
-###Summary
+## 2014-07-15 - Supported Release 4.3.2
+### Summary
This release merely updates metadata.json so the module can be uninstalled and
upgraded via the puppet module command.
-##2014-07-14 - Supported Release 4.3.1
+## 2014-07-14 - Supported Release 4.3.1
### Summary
This supported release updates the metadata.json to work around upgrade behavior of the PMT.
#### Bugfixes
- Synchronize metadata.json with PMT-generated metadata to pass checksums
-##2014-06-27 - Supported Release 4.3.0
+## 2014-06-27 - Supported Release 4.3.0
### Summary
This release is the first supported release of the stdlib 4 series. It remains
backwards-compatible with the stdlib 3 series. It adds two new functions, one bugfix, and many testing updates.
@@ -392,7 +392,7 @@ backwards-compatible with the stdlib 3 series. It adds two new functions, one bu
#### Bugfixes
- Fix `has_interface_with()` when interfaces fact is nil
-##2014-06-04 - Release 4.2.2
+## 2014-06-04 - Release 4.2.2
### Summary
This release adds PE3.3 support in the metadata and fixes a few tests.
@@ -436,14 +436,14 @@ This release adds many new functions and fixes, and continues to be backwards co
- Add/update unit & acceptance tests.
-##2014-03-04 - Supported Release - 3.2.1
-###Summary
+## 2014-03-04 - Supported Release - 3.2.1
+### Summary
This is a supported release
-####Bugfixes
+#### Bugfixes
- Fixed `is_integer`/`is_float`/`is_numeric` for checking the value of arithmatic expressions.
-####Known bugs
+#### Known bugs
* No known bugs
---
diff --git a/Gemfile b/Gemfile
index 46cb2ea..a9f0161 100644
--- a/Gemfile
+++ b/Gemfile
@@ -33,13 +33,13 @@ ruby_version_segments = Gem::Version.new(RUBY_VERSION.dup).segments
minor_version = "#{ruby_version_segments[0]}.#{ruby_version_segments[1]}"
group :development do
- gem "puppet-module-posix-default-r#{minor_version}", :require => false, :platforms => "ruby"
- gem "puppet-module-win-default-r#{minor_version}", :require => false, :platforms => ["mswin", "mingw", "x64_mingw"]
- gem "puppet-module-posix-dev-r#{minor_version}", :require => false, :platforms => "ruby"
- gem "puppet-module-win-dev-r#{minor_version}", :require => false, :platforms => ["mswin", "mingw", "x64_mingw"]
- gem "json_pure", '<= 2.0.1', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0')
- gem "fast_gettext", '1.1.0', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.1.0')
- gem "fast_gettext", :require => false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1.0')
+ gem "puppet-module-posix-default-r#{minor_version}", :require => false, :platforms => "ruby"
+ gem "puppet-module-win-default-r#{minor_version}", :require => false, :platforms => ["mswin", "mingw", "x64_mingw"]
+ gem "puppet-module-posix-dev-r#{minor_version}", :require => false, :platforms => "ruby"
+ gem "puppet-module-win-dev-r#{minor_version}", '0.0.7', :require => false, :platforms => ["mswin", "mingw", "x64_mingw"]
+ gem "json_pure", '<= 2.0.1', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0')
+ gem "fast_gettext", '1.1.0', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.1.0')
+ gem "fast_gettext", :require => false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1.0')
end
group :system_tests do
@@ -50,6 +50,7 @@ group :system_tests do
gem "beaker-rspec", *location_for(ENV['BEAKER_RSPEC_VERSION'])
gem "beaker-hostgenerator", *location_for(ENV['BEAKER_HOSTGENERATOR_VERSION'])
gem "beaker-abs", *location_for(ENV['BEAKER_ABS_VERSION'] || '~> 0.1')
+ gem "puppet-blacksmith", '~> 3.4', :require => false
end
gem 'puppet', *location_for(ENV['PUPPET_GEM_VERSION'])
diff --git a/README.md b/README.md
index c5a7471..7813f19 100644
--- a/README.md
+++ b/README.md
@@ -115,6 +115,18 @@ file_line { 'bashrc_proxy':
In the example above, `match` looks for a line beginning with 'export' followed by 'HTTP_PROXY' and replaces it with the value in line.
+Match Example:
+
+ file_line { 'bashrc_proxy':
+ ensure => present,
+ path => '/etc/bashrc',
+ line => 'export HTTP_PROXY=http://squid.puppetlabs.vm:3128',
+ match => '^export\ HTTP_PROXY\=',
+ append_on_no_match => false,
+ }
+
+In this code example, `match` looks for a line beginning with export followed by HTTP_PROXY and replaces it with the value in line. If a match is not found, then no changes are made to the file.
+
Match Example with `ensure => absent`:
```puppet
@@ -178,7 +190,7 @@ Default value: 'present'.
Sets the line to be added to the file located by the `path` parameter.
Values: String.
-
+
##### `match`
Specifies a regular expression to compare against existing lines in the file; if a match is found, it is replaced rather than adding a new line. A regex comparison is performed against the line value, and if it does not match, an exception is raised.
@@ -207,7 +219,7 @@ Default value: `false`.
##### `name`
-Specifies the name to use as the identity of the resource. If you want the resource namevar to differ from the supplied `title` of the resource, specify it with `name`.
+Specifies the name to use as the identity of the resource. If you want the resource namevar to differ from the supplied `title` of the resource, specify it with `name`.
Values: String.
@@ -217,7 +229,7 @@ Default value: The value of the title.
**Required.**
-Specifies the file in which Puppet ensures the line specified by `line`.
+Specifies the file in which Puppet ensures the line specified by `line`.
Value: String specifying an absolute path to the file.
@@ -289,6 +301,10 @@ Unacceptable input example:
httds://notquiteright.org
```
+#### `Stdlib::MAC`
+
+Matches MAC addresses defined in [RFC5342](https://tools.ietf.org/html/rfc5342).
+
#### `Stdlib::Unixpath`
Matches paths on Unix operating systems.
@@ -311,7 +327,7 @@ C:/whatever
Matches paths on Windows operating systems.
-Acceptable input example:
+Acceptable input example:
```shell
C:\\WINDOWS\\System32
@@ -468,9 +484,9 @@ Converts a Boolean to a number. Converts values:
* `false`, 'f', '0', 'n', and 'no' to 0.
* `true`, 't', '1', 'y', and 'yes' to 1.
-
+
Argument: a single Boolean or string as an input.
-
+
*Type*: rvalue.
#### `bool2str`
@@ -538,8 +554,8 @@ Keeps value within the range [Min, X, Max] by sort based on integer value (param
* `clamp('24', [575, 187])` returns 187.
* `clamp(16, 88, 661)` returns 88.
* `clamp([4, 3, '99'])` returns 4.
-
-Arguments: strings, arrays, or numerics.
+
+Arguments: strings, arrays, or numerics.
*Type*: rvalue.
@@ -690,7 +706,7 @@ Other settings in Puppet affect the stdlib `deprecation` function:
Specifies whether or not to log deprecation warnings. This is especially useful for automated tests to avoid flooding your logs before you are ready to migrate.
This variable is Boolean, with the following effects:
-
+
* `true`: Functions log a warning.
* `false`: No warnings are logged.
* No value set: Puppet 4 emits warnings, but Puppet 3 does not.
@@ -895,6 +911,31 @@ userlist:
ensure_resources('user', hiera_hash('userlist'), {'ensure' => 'present'})
```
+#### `fact`
+
+Return the value of a given fact. Supports the use of dot-notation for referring to structured facts. If a fact requested does not exist, returns Undef.
+
+Example usage:
+
+```puppet
+fact('kernel')
+fact('osfamily')
+fact('os.architecture')
+```
+
+Array indexing:
+
+```puppet
+$first_processor = fact('processors.models.0')
+$second_processor = fact('processors.models.1')
+```
+
+Fact containing a "." in the fact name:
+
+```puppet
+fact('vmware."VRA.version"')
+```
+
#### `flatten`
Flattens deeply nested arrays and returns a single flat array as a result.
@@ -1167,6 +1208,13 @@ Returns `true` if the string passed to this function is a syntactically correct
*Type*: rvalue.
+#### `is_email_address`
+
+Returns true if the string passed to this function is a valid email address.
+
+*Type*: rvalue.
+
+
#### `is_float`
**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
@@ -1253,7 +1301,7 @@ Joins an array into a string using a separator. For example, `join(['a','b','c']
#### `join_keys_to_values`
-Joins each key of a hash to that key's corresponding value with a separator, returning the result as strings.
+Joins each key of a hash to that key's corresponding value with a separator, returning the result as strings.
If a value is an array, the key is prefixed to each element. The return value is a flattened array.
@@ -1407,7 +1455,7 @@ Arguments:
* The YAML string to convert, as a first argument.
* Optionally, the result to return if conversion fails, as a second error.
-*Type*: rvalue.
+*Type*: rvalue.
#### `pick`
@@ -1509,6 +1557,10 @@ For example, `reject(['aaa','bbb','ccc','aaaddd'], 'aaa')` returns ['bbb','ccc']
Reverses the order of a string or array.
+#### `round`
+
+ Rounds a number to the nearest integer
+
*Type*: rvalue.
#### `rstrip`
@@ -1696,7 +1748,7 @@ For example, `time()` returns something like '1311972653'.
Converts the argument into bytes.
-For example, "4 kB" becomes "4096".
+For example, "4 kB" becomes "4096".
Arguments: A single string.
@@ -1708,7 +1760,7 @@ Arguments: A single string.
Retrieves a value within multiple layers of hashes and arrays.
-Arguments:
+Arguments:
* A string containing a path, as the first argument. Provide this argument as a string of hash keys or array indexes starting with zero and separated by the path separator character (default "/"). This function goes through the structure by each path component and tries to return the value at the end of the path.
@@ -1819,7 +1871,7 @@ For example, `upcase('abcd')` returns 'ABCD'.
#### `uriescape`
-URLEncodes a string or array of strings.
+URLEncodes a string or array of strings.
Arguments: Either a single string or an array of strings.
@@ -1915,7 +1967,7 @@ validate_augeas($sudoerscontent, 'Sudoers.lns', [], 'Failed to validate sudoers
**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
-Validates that all passed values are either `true` or `false`.
+Validates that all passed values are either `true` or `false`.
Terminates catalog compilation if any value fails this check.
The following values pass:
@@ -1958,6 +2010,53 @@ validate_cmd($haproxycontent, '/usr/sbin/haproxy -f % -c', 'Haproxy failed to va
*Type*: statement.
+#### `validate_domain_name`
+
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
+
+Validate that all values passed are syntactically correct domain names. Aborts catalog compilation if any value fails this check.
+
+The following values pass:
+
+~~~
+$my_domain_name = 'server.domain.tld'
+validate_domain_name($my_domain_name)
+validate_domain_name('domain.tld', 'puppet.com', $my_domain_name)
+~~~
+
+The following values fail, causing compilation to abort:
+
+~~~
+validate_domain_name(1)
+validate_domain_name(true)
+validate_domain_name('invalid domain')
+validate_domain_name('-foo.example.com')
+validate_domain_name('www.example.2com')
+~~~
+
+*Type*: statement.
+
+#### `validate_email_address`
+
+Validate that all values passed are valid email addresses. Fail compilation if any value fails this check.
+
+The following values will pass:
+
+~~~
+$my_email = "waldo@gmail.com"
+validate_email_address($my_email)
+validate_email_address("bob@gmail.com", "alice@gmail.com", $my_email)
+~~~
+
+The following values will fail, causing compilation to abort:
+
+~~~
+$some_array = [ 'bad_email@/d/efdf.com' ]
+validate_email_address($some_array)
+~~~
+
+*Type*: statement.
+
#### `validate_hash`
**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
@@ -1992,7 +2091,7 @@ Arguments:
* An integer or an array of integers, as the first argument.
* Optionally, a maximum, as the second argument. (All elements of) the first argument must be equal to or less than this maximum.
-* Optionally, a minimum, as the third argument. (All elements of) the first argument must be equal to or greater than than this maximum.
+* Optionally, a minimum, as the third argument. (All elements of) the first argument must be equal to or greater than than this maximum.
This function fails if the first argument is not an integer or array of integers, or if the second or third arguments are not convertable to an integer. However, if (and only if) a minimum is given, the second argument may be an empty string or `undef`, which serves as a placeholder to ensure the minimum check.
@@ -2046,7 +2145,7 @@ validate_integer(1, 3, true)
**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
-Validates that the argument is an IP address, regardless of whether it is an IPv4 or an IPv6 address. It also validates IP address with netmask.
+Validates that the argument is an IP address, regardless of whether it is an IPv4 or an IPv6 address. It also validates IP address with netmask.
Arguments: A string specifying an IP address.
@@ -2117,7 +2216,7 @@ The deprecation messages you get can vary, depending on the modules and data tha
The `validate_legacy` function helps you move from Puppet 3 style validation to Puppet 4 validation without breaking functionality your module's users depend on.
-Moving to Puppet 4 type validation allows much better defined type checking using [data types](https://docs.puppet.com/puppet/latest/reference/lang_data.html). Many of Puppet 3's `validate_*` functions have surprising holes in their validation. For example, [validate_numeric](#validate_numeric) allows not only numbers, but also arrays of numbers or strings that look like numbers, without giving you any control over the specifics.
+Moving to Puppet 4 type validation allows much better defined type checking using [data types](https://docs.puppet.com/puppet/latest/reference/lang_data.html). Many of Puppet 3's `validate_*` functions have surprising holes in their validation. For example, [validate_numeric](#validate_numeric) allows not only numbers, but also arrays of numbers or strings that look like numbers, without giving you any control over the specifics.
For each parameter of your classes and defined types, choose a new Puppet 4 data type to use. In most cases, the new data type allows a different set of values than the original `validate_*` function. The situation then looks like this:
diff --git a/appveyor.yml b/appveyor.yml
index c87ed7c..7e05880 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -14,16 +14,28 @@ environment:
RUBY_VER: 21
- PUPPET_GEM_VERSION: ~> 4.0
RUBY_VER: 21-x64
- - PUPPET_GEM_VERSION: ~> 4.0
- RUBY_VER: 23
- - PUPPET_GEM_VERSION: ~> 4.0
- RUBY_VER: 23-x64
- - PUPPET_GEM_VERSION: 4.2.3
+ - PUPPET_GEM_VERSION: ~> 5.0
+ RUBY_VER: 24
+ - PUPPET_GEM_VERSION: ~> 5.0
+ RUBY_VER: 24-x64
+ - PUPPET_GEM_VERSION: 4.7.1
RUBY_VER: 21-x64
matrix:
fast_finish: true
install:
- SET PATH=C:\Ruby%RUBY_VER%\bin;%PATH%
+- ps: |
+ # AppVeyor appears to have OpenSSL headers available already
+ # which msys2 would normally install with:
+ # pacman -S mingw-w64-x86_64-openssl --noconfirm
+ #
+ if ( $(ruby --version) -match "^ruby\s+2\.4" ) {
+ Write-Output "Building OpenSSL gem ~> 2.0.4 to fix Ruby 2.4 / AppVeyor issue"
+ gem install openssl --version '~> 2.0.4' --no-ri --no-rdoc
+ }
+
+ gem list openssl
+ ruby -ropenssl -e 'puts \"OpenSSL Version - #{OpenSSL::OPENSSL_VERSION}\"; puts \"OpenSSL Library Version - #{OpenSSL::OPENSSL_LIBRARY_VERSION}\"'
- bundle install --jobs 4 --retry 2 --without system_tests
- type Gemfile.lock
build: off
diff --git a/lib/puppet/functions/fact.rb b/lib/puppet/functions/fact.rb
new file mode 100644
index 0000000..dfb048b
--- /dev/null
+++ b/lib/puppet/functions/fact.rb
@@ -0,0 +1,58 @@
+# Digs into the facts hash using dot-notation
+#
+# Example usage:
+#
+# fact('osfamily')
+# fact('os.architecture')
+#
+# Array indexing:
+#
+# fact('mountpoints."/dev".options.1')
+#
+# Fact containing a "." in the name:
+#
+# fact('vmware."VRA.version"')
+#
+Puppet::Functions.create_function(:fact) do
+ dispatch :fact do
+ param 'String', :fact_name
+ end
+
+ def to_dot_syntax(array_path)
+ array_path.map do |string|
+ string.include?('.') ? %Q{"#{string}"} : string
+ end.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(/([^."]+)|(?:")([^"]+)(?:")/).map {|x| x.compact.first }
+
+ walked_path = []
+ path.reduce(facts) do |d, k|
+ return nil if d.nil? || k.nil?
+
+ case
+ when d.is_a?(Array)
+ begin
+ result = d[Integer(k)]
+ rescue ArgumentError => e
+ Puppet.warning("fact request for #{fact_name} returning nil: '#{to_dot_syntax(walked_path)}' is an array; cannot index to '#{k}'")
+ result = nil
+ end
+ when 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
diff --git a/lib/puppet/parser/functions/ensure_packages.rb b/lib/puppet/parser/functions/ensure_packages.rb
index 034f997..1bf8bf1 100644
--- a/lib/puppet/parser/functions/ensure_packages.rb
+++ b/lib/puppet/parser/functions/ensure_packages.rb
@@ -19,6 +19,9 @@ third argument to the ensure_resource() function.
if arguments[0].is_a?(Hash)
if arguments[1]
defaults = { 'ensure' => 'present' }.merge(arguments[1])
+ if defaults['ensure'] == 'installed'
+ defaults['ensure'] = 'present'
+ end
else
defaults = { 'ensure' => 'present' }
end
@@ -30,6 +33,9 @@ third argument to the ensure_resource() function.
if arguments[1]
defaults = { 'ensure' => 'present' }.merge(arguments[1])
+ if defaults['ensure'] == 'installed'
+ defaults['ensure'] = 'present'
+ end
else
defaults = { 'ensure' => 'present' }
end
diff --git a/lib/puppet/parser/functions/pw_hash.rb b/lib/puppet/parser/functions/pw_hash.rb
index d99ee5b..0deeb3a 100644
--- a/lib/puppet/parser/functions/pw_hash.rb
+++ b/lib/puppet/parser/functions/pw_hash.rb
@@ -27,6 +27,13 @@ Puppet::Parser::Functions::newfunction(
environment contains several different operating systems, ensure that they
are compatible before using this function.") do |args|
raise ArgumentError, "pw_hash(): wrong number of arguments (#{args.size} for 3)" if args.size != 3
+ args.map! do |arg|
+ if arg.is_a? Puppet::Pops::Types::PSensitiveType::Sensitive
+ arg.unwrap
+ else
+ arg
+ end
+ end
raise ArgumentError, "pw_hash(): first argument must be a string" unless args[0].is_a? String or args[0].nil?
raise ArgumentError, "pw_hash(): second argument must be a string" unless args[1].is_a? String
hashes = { 'md5' => '1',
diff --git a/lib/puppet/parser/functions/round.rb b/lib/puppet/parser/functions/round.rb
new file mode 100644
index 0000000..489c301
--- /dev/null
+++ b/lib/puppet/parser/functions/round.rb
@@ -0,0 +1,33 @@
+#
+# round.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:round, :type => :rvalue, :doc => <<-EOS
+ Rounds a number to the nearest integer
+
+ *Examples:*
+
+ round(2.9)
+
+ returns: 3
+
+ round(2.4)
+
+ returns: 2
+
+ EOS
+ ) do |args|
+
+ raise Puppet::ParseError, "round(): Wrong number of arguments given #{args.size} for 1" if args.size != 1
+ raise Puppet::ParseError, "round(): Expected a Numeric, got #{args[0].class}" unless args[0].is_a? Numeric
+
+ value = args[0]
+
+ if value >= 0
+ Integer(value + 0.5)
+ else
+ Integer(value - 0.5)
+ end
+ end
+end
diff --git a/lib/puppet/parser/functions/unique.rb b/lib/puppet/parser/functions/unique.rb
index b57431d..1e2a895 100644
--- a/lib/puppet/parser/functions/unique.rb
+++ b/lib/puppet/parser/functions/unique.rb
@@ -24,6 +24,10 @@ This returns:
EOS
) do |arguments|
+ if Puppet::Util::Package.versioncmp(Puppet.version, '5.0.0') >= 0
+ function_deprecation([:unique, 'This method is deprecated, please use the core puppet unique function. There is further documentation for the function in the release notes of Puppet 5.0.'])
+ end
+
raise(Puppet::ParseError, "unique(): Wrong number of arguments given (#{arguments.size} for 1)") if arguments.size < 1
value = arguments[0]
diff --git a/lib/puppet/parser/functions/validate_domain_name.rb b/lib/puppet/parser/functions/validate_domain_name.rb
new file mode 100644
index 0000000..c3fad78
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_domain_name.rb
@@ -0,0 +1,39 @@
+module Puppet::Parser::Functions
+ newfunction(:validate_domain_name, :doc => <<-ENDHEREDOC
+ Validate that all values passed are syntactically correct domain names.
+ Fail compilation if any value fails this check.
+
+ The following values will pass:
+
+ $my_domain_name = 'server.domain.tld'
+ validate_domain_name($my_domain_name)
+ validate_domain_name('domain.tld', 'puppet.com', $my_domain_name)
+
+ The following values will fail, causing compilation to abort:
+
+ validate_domain_name(1)
+ validate_domain_name(true)
+ validate_domain_name('invalid domain')
+ validate_domain_name('-foo.example.com')
+ validate_domain_name('www.example.2com')
+
+ ENDHEREDOC
+ ) do |args|
+
+ rescuable_exceptions = [ArgumentError]
+
+ if args.empty?
+ raise Puppet::ParseError, "validate_domain_name(): wrong number of arguments (#{args.length}; must be > 0)"
+ end
+
+ args.each do |arg|
+ raise Puppet::ParseError, "#{arg.inspect} is not a string." unless arg.is_a?(String)
+
+ begin
+ raise Puppet::ParseError, "#{arg.inspect} is not a syntactically correct domain name" unless function_is_domain_name([arg])
+ rescue *rescuable_exceptions
+ raise Puppet::ParseError, "#{arg.inspect} is not a syntactically correct domain name"
+ end
+ end
+ end
+end
diff --git a/lib/puppet/provider/file_line/ruby.rb b/lib/puppet/provider/file_line/ruby.rb
index 42f287a..16f2709 100644
--- a/lib/puppet/provider/file_line/ruby.rb
+++ b/lib/puppet/provider/file_line/ruby.rb
@@ -1,32 +1,42 @@
Puppet::Type.type(:file_line).provide(:ruby) do
def exists?
- if resource[:replace].to_s != 'true' and count_matches(match_regex) > 0
- true
+ found = false
+ lines_count = 0
+ lines.each do |line|
+ found = line.chomp == resource[:line]
+ if found
+ lines_count += 1
+ end
+ end
+ if resource[:match] == nil
+ found = lines_count > 0
else
- lines.find do |line|
- if resource[:ensure].to_s == 'absent' and resource[:match_for_absence].to_s == 'true'
- line.chomp =~ Regexp.new(resource[:match])
- else
- line.chomp == resource[:line].chomp
- end
+ match_count = count_matches(new_match_regex)
+ if resource[:append_on_no_match].to_s == 'false'
+ found = true
+ elsif resource[:replace].to_s == 'true'
+ found = lines_count > 0 && lines_count == match_count
+ else
+ found = match_count > 0
end
end
+ found
end
def create
- unless resource[:replace].to_s != 'true' and count_matches(match_regex) > 0
+ unless resource[:replace].to_s != 'true' && count_matches(new_match_regex) > 0
if resource[:match]
handle_create_with_match
elsif resource[:after]
handle_create_with_after
else
- append_line
+ handle_append_line
end
end
end
def destroy
- if resource[:match_for_absence].to_s == 'true' and resource[:match]
+ if resource[:match_for_absence].to_s == 'true' && resource[:match]
handle_destroy_with_match
else
handle_destroy_line
@@ -34,6 +44,7 @@ Puppet::Type.type(:file_line).provide(:ruby) do
end
private
+
def lines
# If this type is ever used with very large files, we should
# write this in a different way, using a temp
@@ -48,25 +59,34 @@ Puppet::Type.type(:file_line).provide(:ruby) do
end
end
- def match_regex
+ def new_after_regex
+ resource[:after] ? Regexp.new(resource[:after]) : nil
+ end
+
+ def new_match_regex
resource[:match] ? Regexp.new(resource[:match]) : nil
end
+ def count_matches(regex)
+ lines.select{ |line| line.match(regex) }.size
+ end
+
def handle_create_with_match()
- regex_after = resource[:after] ? Regexp.new(resource[:after]) : nil
- match_count = count_matches(match_regex)
+ after_regex = new_after_regex
+ match_regex = new_match_regex
+ match_count = count_matches(new_match_regex)
if match_count > 1 && resource[:multiple].to_s != 'true'
raise Puppet::Error, "More than one line in file '#{resource[:path]}' matches pattern '#{resource[:match]}'"
end
File.open(resource[:path], 'w') do |fh|
- lines.each do |l|
- fh.puts(match_regex.match(l) ? resource[:line] : l)
- if (match_count == 0 and regex_after)
- if regex_after.match(l)
+ lines.each do |line|
+ fh.puts(match_regex.match(line) ? resource[:line] : line)
+ if match_count == 0 && after_regex
+ if after_regex.match(line)
fh.puts(resource[:line])
- match_count += 1 #Increment match_count to indicate that the new line has been inserted.
+ match_count += 1 # Increment match_count to indicate that the new line has been inserted.
end
end
end
@@ -78,32 +98,29 @@ Puppet::Type.type(:file_line).provide(:ruby) do
end
def handle_create_with_after
- regex = Regexp.new(resource[:after])
- count = count_matches(regex)
+ after_regex = new_after_regex
+ after_count = count_matches(after_regex)
- if count > 1 && resource[:multiple].to_s != 'true'
- raise Puppet::Error, "#{count} lines match pattern '#{resource[:after]}' in file '#{resource[:path]}'. One or no line must match the pattern."
+ if after_count > 1 && resource[:multiple].to_s != 'true'
+ raise Puppet::Error, "#{after_count} lines match pattern '#{resource[:after]}' in file '#{resource[:path]}'. One or no line must match the pattern."
end
- File.open(resource[:path], 'w') do |fh|
- lines.each do |l|
- fh.puts(l)
- if regex.match(l) then
+ File.open(resource[:path],'w') do |fh|
+ lines.each do |line|
+ fh.puts(line)
+ if after_regex.match(line)
fh.puts(resource[:line])
end
end
- end
- if (count == 0) # append the line to the end of the file
- append_line
+ if (after_count == 0)
+ fh.puts(resource[:line])
+ end
end
end
- def count_matches(regex)
- lines.select{|l| l.match(regex)}.size
- end
-
def handle_destroy_with_match
+ match_regex = new_match_regex
match_count = count_matches(match_regex)
if match_count > 1 && resource[:multiple].to_s != 'true'
raise Puppet::Error, "More than one line in file '#{resource[:path]}' matches pattern '#{resource[:match]}'"
@@ -111,27 +128,23 @@ Puppet::Type.type(:file_line).provide(:ruby) do
local_lines = lines
File.open(resource[:path],'w') do |fh|
- fh.write(local_lines.reject{|l| match_regex.match(l) }.join(''))
+ fh.write(local_lines.reject{ |line| match_regex.match(line) }.join(''))
end
end
def handle_destroy_line
local_lines = lines
File.open(resource[:path],'w') do |fh|
- fh.write(local_lines.reject{|l| l.chomp == resource[:line] }.join(''))
+ fh.write(local_lines.reject{ |line| line.chomp == resource[:line] }.join(''))
end
end
- ##
- # append the line to the file.
- #
- # @api private
- def append_line
- File.open(resource[:path], 'w') do |fh|
- lines.each do |l|
- fh.puts(l)
+ def handle_append_line
+ File.open(resource[:path],'w') do |fh|
+ lines.each do |line|
+ fh.puts(line)
end
- fh.puts resource[:line]
+ fh.puts(resource[:line])
end
end
end
diff --git a/lib/puppet/type/file_line.rb b/lib/puppet/type/file_line.rb
index e82b246..b2357b8 100644
--- a/lib/puppet/type/file_line.rb
+++ b/lib/puppet/type/file_line.rb
@@ -58,7 +58,7 @@ Puppet::Type.newtype(:file_line) do
encoding => "iso-8859-1",
}
- Files with special characters that are not valid UTF-8 will give the
+ Files with special characters that are not valid UTF-8 will give the
error message "invalid byte sequence in UTF-8". In this case, determine
the correct file encoding and specify the correct encoding using the
encoding attribute, the value of which needs to be a valid Ruby character
@@ -104,8 +104,16 @@ Puppet::Type.newtype(:file_line) do
' This is also takes a regex.'
end
- newparam(:line) do
+ # The line property never changes; the type only ever performs a create() or
+ # destroy(). line is a property in order to allow it to correctly handle
+ # Sensitive type values. Because it is a property which will never change,
+ # it should never be considered out of sync.
+ newproperty(:line) do
desc 'The line to be appended to the file or used to replace matches found by the match attribute.'
+
+ def retrieve
+ @resource[:line]
+ end
end
newparam(:path) do
@@ -128,6 +136,12 @@ Puppet::Type.newtype(:file_line) do
defaultto 'UTF-8'
end
+ newparam(:append_on_no_match) do
+ desc 'If true, append line if match is not found. If false, do not append line if a match is not found'
+ newvalues(true, false)
+ defaultto true
+ end
+
# Autorequire the file resource if it's being managed
autorequire(:file) do
self[:path]
diff --git a/spec/aliases/absolutepath_spec.rb b/spec/aliases/absolutepath_spec.rb
index cd442f2..ff23dc0 100644
--- a/spec/aliases/absolutepath_spec.rb
+++ b/spec/aliases/absolutepath_spec.rb
@@ -40,7 +40,7 @@ if Puppet::Util::Package.versioncmp(Puppet.version, '4.5.0') >= 0
].each do |value|
describe value.inspect do
let(:params) {{ value: value }}
- it { is_expected.to compile.and_raise_error(/parameter 'value' expects a match for Variant/) }
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a match for.*Variant/) }
end
end
end
diff --git a/spec/aliases/float_spec.rb b/spec/aliases/float_spec.rb
index 66079c6..84e1934 100644
--- a/spec/aliases/float_spec.rb
+++ b/spec/aliases/float_spec.rb
@@ -20,7 +20,7 @@ if Puppet::Util::Package.versioncmp(Puppet.version, '4.5.0') >= 0
[ true, 'true', false, 'false', 'iAmAString', '1test', '1 test', 'test 1', 'test 1 test', {}, { 'key' => 'value' }, { 1=> 2 }, '', :undef , 'x', 3, '3', -3, '-3'].each do |value|
describe value.inspect do
let(:params) {{ value: value }}
- it { is_expected.to compile.and_raise_error(/parameter 'value' expects a value of type Float or Pattern(\[.*\]+)?/) }
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects.*Float.*Pattern/) }
end
end
end
diff --git a/spec/aliases/integer_spec.rb b/spec/aliases/integer_spec.rb
index bd00c2a..9cf0357 100644
--- a/spec/aliases/integer_spec.rb
+++ b/spec/aliases/integer_spec.rb
@@ -8,6 +8,8 @@ if Puppet::Util::Package.versioncmp(Puppet.version, '4.5.0') >= 0
'3',
-3,
'-3',
+ "123\nfoo",
+ "foo\n123",
].each do |value|
describe value.inspect do
let(:params) {{ value: value }}
@@ -17,10 +19,14 @@ if Puppet::Util::Package.versioncmp(Puppet.version, '4.5.0') >= 0
end
describe 'rejects other values' do
- [ true, 'true', false, 'false', 'iAmAString', '1test', '1 test', 'test 1', 'test 1 test', {}, { 'key' => 'value' }, { 1=> 2 }, '', :undef , 'x', 3.7, '3.7',-3.7, '-342.2315e-12' ].each do |value|
+ [ "foo\nbar", true, 'true', false, 'false', 'iAmAString', '1test', '1 test', 'test 1', 'test 1 test', {}, { 'key' => 'value' }, { 1=> 2 }, '', :undef , 'x', 3.7, '3.7',-3.7, '-342.2315e-12' ].each do |value|
describe value.inspect do
let(:params) {{ value: value }}
- it { is_expected.to compile.and_raise_error(/parameter 'value' expects a value of type Integer, Pattern(\[.*\]+)?, or Array/) }
+ if Puppet::Util::Package.versioncmp(Puppet.version, '5.0.0') >= 0
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a Stdlib::Compat::Integer = Variant\[Integer, Pattern\[.*\], Array\[.*\]\] value/) }
+ else
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a value of type Integer, Pattern(\[.*\]+)?, or Array/) }
+ end
end
end
end
diff --git a/spec/aliases/numeric_spec.rb b/spec/aliases/numeric_spec.rb
index bc17f4f..09c28ec 100644
--- a/spec/aliases/numeric_spec.rb
+++ b/spec/aliases/numeric_spec.rb
@@ -24,7 +24,7 @@ if Puppet::Util::Package.versioncmp(Puppet.version, '4.5.0') >= 0
[ true, 'true', false, 'false', 'iAmAString', '1test', '1 test', 'test 1', 'test 1 test', {}, { 'key' => 'value' }, { 1=> 2 }, '', :undef , 'x' ].each do |value|
describe value.inspect do
let(:params) {{ value: value }}
- it { is_expected.to compile.and_raise_error(/parameter 'value' expects a value of type Numeric, Pattern(\[.*\]+)?, or Array/) }
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects.*Numeric.*Pattern.*Array/) }
end
end
end
diff --git a/spec/aliases/string_spec.rb b/spec/aliases/string_spec.rb
index 3ea1967..4fc8ce6 100644
--- a/spec/aliases/string_spec.rb
+++ b/spec/aliases/string_spec.rb
@@ -24,7 +24,7 @@ if Puppet::Util::Package.versioncmp(Puppet.version, '4.5.0') >= 0
].each do |value|
describe value.inspect do
let(:params) {{ value: value }}
- it { is_expected.to compile.and_raise_error(/parameter 'value' expects a (?:value of type Undef or )?String/) }
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a (?:value of type Undef or )?.*String/) }
end
end
end
diff --git a/spec/functions/deep_merge_spec.rb b/spec/functions/deep_merge_spec.rb
index c91a07e..819e025 100755
--- a/spec/functions/deep_merge_spec.rb
+++ b/spec/functions/deep_merge_spec.rb
@@ -4,7 +4,7 @@ describe 'deep_merge' do
it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
it { is_expected.to run.with_params({ 'key' => 'value' }).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
it { is_expected.to run.with_params({}, '2').and_raise_error(Puppet::ParseError, /unexpected argument type String/) }
- it { is_expected.to run.with_params({}, 2).and_raise_error(Puppet::ParseError, /unexpected argument type Fixnum/) }
+ it { is_expected.to run.with_params({}, 2).and_raise_error(Puppet::ParseError, /unexpected argument/) }
it { is_expected.to run.with_params({}, '').and_return({}) }
it { is_expected.to run.with_params({}, {}).and_return({}) }
it { is_expected.to run.with_params({}, {}, {}).and_return({}) }
diff --git a/spec/functions/ensure_packages_spec.rb b/spec/functions/ensure_packages_spec.rb
index 1f89785..190e580 100755
--- a/spec/functions/ensure_packages_spec.rb
+++ b/spec/functions/ensure_packages_spec.rb
@@ -56,4 +56,16 @@ describe 'ensure_packages' do
it { expect(lambda { catalogue }).to contain_package('ρǻ¢κầģẻ').with({'ensure' => 'absent'}) }
end
end
+
+ context 'given a catalog with "package { puppet: ensure => present }"' do
+ let(:pre_condition) { 'package { puppet: ensure => present }' }
+
+ describe 'after running ensure_package("puppet", { "ensure" => "installed" })' do
+ before { subject.call(['puppet', { "ensure" => "installed" }]) }
+
+ # this lambda is required due to strangeness within rspec-puppet's expectation handling
+ it { expect(lambda { catalogue }).to contain_package('puppet').with_ensure('present') }
+ end
+ end
+
end
diff --git a/spec/functions/ensure_resources_spec.rb b/spec/functions/ensure_resources_spec.rb
new file mode 100644
index 0000000..7cca671
--- /dev/null
+++ b/spec/functions/ensure_resources_spec.rb
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe 'ensure_resources' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(ArgumentError, /Must specify a type/) }
+ it { is_expected.to run.with_params('type').and_raise_error(ArgumentError, /Must specify a title/) }
+
+ describe 'given a title hash of multiple resources' do
+ before { subject.call(['user', {'dan' => { 'gid' => 'mygroup', 'uid' => '600' }, 'alex' => { 'gid' => 'mygroup', 'uid' => '700'}}, {'ensure' => 'present'}]) }
+
+ # this lambda is required due to strangeness within rspec-puppet's expectation handling
+ it { expect(lambda { catalogue }).to contain_user('dan').with_ensure('present') }
+ it { expect(lambda { catalogue }).to contain_user('alex').with_ensure('present') }
+ it { expect(lambda { catalogue }).to contain_user('dan').with({ 'gid' => 'mygroup', 'uid' => '600'}) }
+ it { expect(lambda { catalogue }).to contain_user('alex').with({ 'gid' => 'mygroup', 'uid' => '700'}) }
+ end
+
+ describe 'given a title hash of a single resource' do
+ before { subject.call(['user', {'dan' => { 'gid' => 'mygroup', 'uid' => '600' }}, {'ensure' => 'present'}]) }
+
+ # this lambda is required due to strangeness within rspec-puppet's expectation handling
+ it { expect(lambda { catalogue }).to contain_user('dan').with_ensure('present') }
+ it { expect(lambda { catalogue }).to contain_user('dan').with({ 'gid' => 'mygroup', 'uid' => '600'}) }
+ end
+end
diff --git a/spec/functions/is_integer_spec.rb b/spec/functions/is_integer_spec.rb
index b296830..8118ef4 100755
--- a/spec/functions/is_integer_spec.rb
+++ b/spec/functions/is_integer_spec.rb
@@ -11,6 +11,8 @@ describe 'is_integer' do
it { is_expected.to run.with_params('3').and_return(true) }
it { is_expected.to run.with_params(-3).and_return(true) }
it { is_expected.to run.with_params('-3').and_return(true) }
+ it { is_expected.to run.with_params("123\nfoo").and_return(true) }
+ it { is_expected.to run.with_params("foo\n123").and_return(true) }
it { is_expected.to run.with_params(3.7).and_return(false) }
it { is_expected.to run.with_params('3.7').and_return(false) }
@@ -24,6 +26,7 @@ describe 'is_integer' do
it { is_expected.to run.with_params(true).and_return(false) }
it { is_expected.to run.with_params(false).and_return(false) }
it { is_expected.to run.with_params('0001234').and_return(false) }
+ it { is_expected.to run.with_params("foo\nbar").and_return(false) }
context 'Checking for deprecation warning' do
after(:all) do
diff --git a/spec/functions/merge_spec.rb b/spec/functions/merge_spec.rb
index 7b53363..3b2e3ef 100755
--- a/spec/functions/merge_spec.rb
+++ b/spec/functions/merge_spec.rb
@@ -4,7 +4,7 @@ describe 'merge' do
it { is_expected.not_to eq(nil) }
it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
it { is_expected.to run.with_params({}, 'two').and_raise_error(Puppet::ParseError, /unexpected argument type String/) }
- it { is_expected.to run.with_params({}, 1).and_raise_error(Puppet::ParseError, /unexpected argument type Fixnum/) }
+ it { is_expected.to run.with_params({}, 1).and_raise_error(Puppet::ParseError, /unexpected argument type (Fixnum|Integer)/) }
it {
pending 'should not special case this'
is_expected.to run.with_params({}).and_return({})
diff --git a/spec/functions/pw_hash_spec.rb b/spec/functions/pw_hash_spec.rb
index df5348c..9e03464 100644
--- a/spec/functions/pw_hash_spec.rb
+++ b/spec/functions/pw_hash_spec.rb
@@ -65,5 +65,13 @@ describe 'pw_hash' do
it { is_expected.to run.with_params('password', 'sha-256', 'salt').and_return('$5$salt$Gcm6FsVtF/Qa77ZKD.iwsJlCVPY0XSMgLJL0Hnww/c1') }
it { is_expected.to run.with_params('password', 'sha-512', 'salt').and_return('$6$salt$IxDD3jeSOb5eB1CX5LBsqZFVkJdido3OUILO5Ifz5iwMuTS4XMS130MTSuDDl3aCI6WouIL9AjRbLCelDCy.g.') }
end
+
+ if Puppet::Util::Package.versioncmp(Puppet.version, '4.7.0') >= 0
+ describe 'when arguments are sensitive' do
+ it { is_expected.to run.with_params(Puppet::Pops::Types::PSensitiveType::Sensitive.new('password'), 'md5', 'salt').and_return('$1$salt$qJH7.N4xYta3aEG/dfqo/0') }
+ it { is_expected.to run.with_params(Puppet::Pops::Types::PSensitiveType::Sensitive.new('password'), 'md5', Puppet::Pops::Types::PSensitiveType::Sensitive.new('salt')).and_return('$1$salt$qJH7.N4xYta3aEG/dfqo/0') }
+ it { is_expected.to run.with_params('password', 'md5', Puppet::Pops::Types::PSensitiveType::Sensitive.new('salt')).and_return('$1$salt$qJH7.N4xYta3aEG/dfqo/0') }
+ end
+ end
end
end
diff --git a/spec/functions/round_spec.rb b/spec/functions/round_spec.rb
new file mode 100755
index 0000000..8b13478
--- /dev/null
+++ b/spec/functions/round_spec.rb
@@ -0,0 +1,14 @@
+require 'spec_helper'
+
+describe 'round' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params(34.3).and_return(34) }
+ it { is_expected.to run.with_params(-34.3).and_return(-34) }
+ it { is_expected.to run.with_params(34.5).and_return(35) }
+ it { is_expected.to run.with_params(-34.5).and_return(-35) }
+ it { is_expected.to run.with_params(34.7).and_return(35) }
+ it { is_expected.to run.with_params(-34.7).and_return(-35) }
+ it { is_expected.to run.with_params("test").and_raise_error Puppet::ParseError }
+ it { is_expected.to run.with_params("test", "best").and_raise_error Puppet::ParseError }
+ it { is_expected.to run.with_params(3, 4).and_raise_error Puppet::ParseError }
+end
diff --git a/spec/functions/strftime_spec.rb b/spec/functions/strftime_spec.rb
index 51f8a73..41cda6a 100755
--- a/spec/functions/strftime_spec.rb
+++ b/spec/functions/strftime_spec.rb
@@ -14,9 +14,9 @@ describe 'strftime' do
expect(result.to_i).to(be > 1311953157)
end
- it "using %s should be lower then 2.0 trillion" do
+ it "using %s should be greater than 1.5 trillion" do
result = scope.function_strftime(["%s"])
- expect(result.to_i).to(be < 2000000000)
+ expect(result.to_i).to(be > 1500000000)
end
it "should return a date when given %Y-%m-%d" do
diff --git a/spec/functions/unique_spec.rb b/spec/functions/unique_spec.rb
index 7955acb..76932ec 100755
--- a/spec/functions/unique_spec.rb
+++ b/spec/functions/unique_spec.rb
@@ -1,29 +1,31 @@
require 'spec_helper'
describe 'unique' do
- describe 'signature validation' do
- it { is_expected.not_to eq(nil) }
- it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
- it {
- pending("Current implementation ignores parameters after the first.")
- is_expected.to run.with_params([], 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
- }
- it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
- it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
- it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
- end
+ if Puppet.version.to_f < 5.0
+ describe 'signature validation' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+ it {
+ pending("Current implementation ignores parameters after the first.")
+ is_expected.to run.with_params([], 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+ }
+ it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+ it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+ end
- context 'when called with an array' do
- it { is_expected.to run.with_params([]).and_return([]) }
- it { is_expected.to run.with_params(['a']).and_return(['a']) }
- it { is_expected.to run.with_params(['a', 'b', 'a']).and_return(['a', 'b']) }
- it { is_expected.to run.with_params(['ã', 'ъ', 'ã']).and_return(['ã', 'ъ']) }
- end
+ context 'when called with an array' do
+ it { is_expected.to run.with_params([]).and_return([]) }
+ it { is_expected.to run.with_params(['a']).and_return(['a']) }
+ it { is_expected.to run.with_params(['a', 'b', 'a']).and_return(['a', 'b']) }
+ it { is_expected.to run.with_params(['ã', 'ъ', 'ã']).and_return(['ã', 'ъ']) }
+ end
- context 'when called with a string' do
- it { is_expected.to run.with_params('').and_return('') }
- it { is_expected.to run.with_params('a').and_return('a') }
- it { is_expected.to run.with_params('aaba').and_return('ab') }
- it { is_expected.to run.with_params('ããъã').and_return('ãъ') }
+ context 'when called with a string' do
+ it { is_expected.to run.with_params('').and_return('') }
+ it { is_expected.to run.with_params('a').and_return('a') }
+ it { is_expected.to run.with_params('aaba').and_return('ab') }
+ it { is_expected.to run.with_params('ããъã').and_return('ãъ') }
+ end
end
end
diff --git a/spec/functions/validate_domain_name_spec.rb b/spec/functions/validate_domain_name_spec.rb
new file mode 100644
index 0000000..69fcae4
--- /dev/null
+++ b/spec/functions/validate_domain_name_spec.rb
@@ -0,0 +1,35 @@
+require 'spec_helper'
+
+describe 'validate_domain_name' do
+ describe 'signature validation' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+ end
+
+ describe 'valid inputs' do
+ it { is_expected.to run.with_params('com', 'com.') }
+ it { is_expected.to run.with_params('x.com', 'x.com.') }
+ it { is_expected.to run.with_params('foo.example.com', 'foo.example.com.') }
+ it { is_expected.to run.with_params('2foo.example.com', '2foo.example.com.') }
+ it { is_expected.to run.with_params('www.2foo.example.com', 'www.2foo.example.com.') }
+ it { is_expected.to run.with_params('domain.tld', 'puppet.com') }
+ end
+
+ describe 'invalid inputs' do
+ it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /is not a string/) }
+
+ it { is_expected.to run.with_params('foo.example.com', []).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params('foo.example.com', {}).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params('foo.example.com', 1).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params('foo.example.com', true).and_raise_error(Puppet::ParseError, /is not a string/) }
+
+ it { is_expected.to run.with_params('').and_raise_error(Puppet::ParseError, /is not a syntactically correct domain name/) }
+ it { is_expected.to run.with_params('invalid domain').and_raise_error(Puppet::ParseError, /is not a syntactically correct domain name/) }
+ it { is_expected.to run.with_params('-foo.example.com').and_raise_error(Puppet::ParseError, /is not a syntactically correct domain name/) }
+ it { is_expected.to run.with_params('www.example.2com').and_raise_error(Puppet::ParseError, /is not a syntactically correct domain name/) }
+ it { is_expected.to run.with_params('192.168.1.1').and_raise_error(Puppet::ParseError, /is not a syntactically correct domain name/) }
+ end
+end
diff --git a/spec/unit/ensure_resources_spec.rb b/spec/unit/ensure_resources_spec.rb
deleted file mode 100644
index aea723e..0000000
--- a/spec/unit/ensure_resources_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-require 'spec_helper'
-
-describe 'test::ensure_resources', type: :class do
- let(:params) {{ resource_type: 'user', title_hash: title_param, attributes_hash: {'ensure' => 'present'} }}
-
- describe 'given a title hash of multiple resources' do
-
- let(:title_param) { {'dan' => { 'gid' => 'mygroup', 'uid' => '600' }, 'alex' => { 'gid' => 'mygroup', 'uid' => '700'}} }
-
- it { is_expected.to compile }
- it { is_expected.to contain_user('dan').with({ 'gid' => 'mygroup', 'uid' => '600', 'ensure' => 'present'}) }
- it { is_expected.to contain_user('alex').with({ 'gid' => 'mygroup', 'uid' => '700', 'ensure' => 'present'}) }
- end
-
- describe 'given a title hash of a single resource' do
-
- let(:title_param) { {'dan' => { 'gid' => 'mygroup', 'uid' => '600' }} }
-
- it { is_expected.to compile }
- it { is_expected.to contain_user('dan').with({ 'gid' => 'mygroup', 'uid' => '600', 'ensure' => 'present'}) }
- end
-end
diff --git a/spec/unit/puppet/provider/file_line/ruby_spec.rb b/spec/unit/puppet/provider/file_line/ruby_spec.rb
index 1f41f62..dcca4a4 100755
--- a/spec/unit/puppet/provider/file_line/ruby_spec.rb
+++ b/spec/unit/puppet/provider/file_line/ruby_spec.rb
@@ -2,7 +2,8 @@
require 'spec_helper'
require 'tempfile'
provider_class = Puppet::Type.type(:file_line).provider(:ruby)
-describe provider_class do
+# These tests fail on windows when run as part of the rake task. Individually they pass
+describe provider_class, :unless => Puppet::Util::Platform.windows? do
context "when adding" do
let :tmpfile do
tmp = Tempfile.new('tmp')
@@ -29,7 +30,7 @@ describe provider_class do
File.open(tmpfile, 'w') do |fh|
fh.write('foo1')
end
- expect(provider.exists?).to be_nil
+ expect(provider.exists?).to eql (false)
end
it 'should append to an existing file when creating' do
provider.create
@@ -69,7 +70,7 @@ describe provider_class do
File.open(@tmpfile, 'w') do |fh|
fh.write("foo1\nfoo2")
end
- expect(@provider.exists?).to be_nil
+ expect(@provider.exists?).to eql (false)
@provider.create
expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo2\nfoo = bar")
end
@@ -112,7 +113,7 @@ describe provider_class do
File.open(@tmpfile, 'w') do |fh|
fh.write("foo1\nfoo=blah\nfoo2\nfoo=baz")
end
- expect(@provider.exists?).to be_nil
+ expect(@provider.exists?).to eql(false)
expect { @provider.create }.to raise_error(Puppet::Error, /More than one line.*matches/)
expect(File.read(@tmpfile)).to eql("foo1\nfoo=blah\nfoo2\nfoo=baz")
end
@@ -131,11 +132,30 @@ describe provider_class do
File.open(@tmpfile, 'w') do |fh|
fh.write("foo1\nfoo=blah\nfoo2\nfoo=baz")
end
- expect(@provider.exists?).to be_nil
+ expect(@provider.exists?).to eql(false)
@provider.create
expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo = bar\nfoo2\nfoo = bar")
end
+ it 'should replace all lines that match, even when some lines are correct' do
+ @resource = Puppet::Type::File_line.new(
+ {
+ :name => 'neil',
+ :path => @tmpfile,
+ :line => "\thard\tcore\t0\n",
+ :match => '^[ \t]hard[ \t]+core[ \t]+.*',
+ :multiple => true,
+ }
+ )
+ @provider = provider_class.new(@resource)
+ File.open(@tmpfile, 'w') do |fh|
+ fh.write("\thard\tcore\t90\n\thard\tcore\t0\n")
+ end
+ expect(@provider.exists?).to eql(false)
+ @provider.create
+ expect(File.read(@tmpfile).chomp).to eql("\thard\tcore\t0\n\thard\tcore\t0")
+ end
+
it 'should raise an error with invalid values' do
expect {
@resource = Puppet::Type::File_line.new(
@@ -154,7 +174,7 @@ describe provider_class do
File.open(@tmpfile, 'w') do |fh|
fh.write("foo1\nfoo=blah\nfoo2")
end
- expect(@provider.exists?).to be_nil
+ expect(@provider.exists?).to eql(false)
@provider.create
expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo = bar\nfoo2")
end
@@ -162,7 +182,7 @@ describe provider_class do
File.open(@tmpfile, 'w') do |fh|
fh.write("foo1\nfoo2")
end
- expect(@provider.exists?).to be_nil
+ expect(@provider.exists?).to eql(false)
@provider.create
expect(File.read(@tmpfile)).to eql("foo1\nfoo2\nfoo = bar\n")
end
@@ -170,10 +190,28 @@ describe provider_class do
File.open(@tmpfile, 'w') do |fh|
fh.write("foo1\nfoo = bar\nfoo2")
end
- expect(@provider.exists?).to be_truthy
+ expect(@provider.exists?).to eql(true)
@provider.create
expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo = bar\nfoo2")
end
+
+ it 'should not add line after no matches found' do
+ @resource = Puppet::Type::File_line.new(
+ {
+ :name => 'foo',
+ :path => @tmpfile,
+ :line => 'inserted = line',
+ :match => '^foo3$',
+ :append_on_no_match => false,
+ }
+ )
+ @provider = provider_class.new(@resource)
+ File.open(@tmpfile, 'w') do |fh|
+ fh.write("foo1\nfoo = blah\nfoo2\nfoo = baz")
+ end
+ expect(@provider.exists?).to be true
+ expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo = blah\nfoo2\nfoo = baz")
+ end
end
describe 'using after' do
@@ -274,7 +312,7 @@ describe provider_class do
}
)
@provider = provider_class.new(@resource)
- expect(@provider.exists?).to be_nil
+ expect(@provider.exists?).to eql (false)
@provider.create
expect(File.read(@tmpfile).chomp).to eql("foo1\ninserted = line\nfoo = blah\nfoo2\nfoo1\ninserted = line\nfoo = baz")
end
@@ -367,7 +405,7 @@ describe provider_class do
File.open(@tmpfile, 'w') do |fh|
fh.write("foo1\nfoo\nfoo2")
end
- expect(@provider.exists?).to be_truthy
+ expect(@provider.exists?).to eql (true)
end
it 'should remove one line if it matches' do
diff --git a/types/mac.pp b/types/mac.pp
new file mode 100644
index 0000000..4103574
--- /dev/null
+++ b/types/mac.pp
@@ -0,0 +1,2 @@
+# A type for a MAC address
+type Stdlib::MAC = Pattern[/^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/]