diff --git a/CHANGELOG.md b/CHANGELOG.md index 7178301e3..bcb50c1a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,23 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org). -## [v9.4.1](https://github.com/puppetlabs/puppetlabs-stdlib/tree/v9.4.1) - 2023-11-08 +## [v9.5.0](https://github.com/puppetlabs/puppetlabs-stdlib/tree/v9.5.0) - 2024-03-11 + +[Full Changelog](https://github.com/puppetlabs/puppetlabs-stdlib/compare/v9.4.1...v9.5.0) + +### Added + +- Add function stdlib::sort_by [#1384](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1384) ([XMol](https://github.com/XMol)) + +### Fixed + +- (#1389) - pw_hash with bcrypt not working on puppet master [#1410](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1410) ([TuningYourCode](https://github.com/TuningYourCode)) + +### Other + +- Deprecate `time` function [#1417](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1417) ([alexjfisher](https://github.com/alexjfisher)) + +## [v9.4.1](https://github.com/puppetlabs/puppetlabs-stdlib/tree/v9.4.1) - 2023-11-09 [Full Changelog](https://github.com/puppetlabs/puppetlabs-stdlib/compare/v9.4.0...v9.4.1) @@ -21,10 +37,6 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a - Modernise `fqdn_rotate` function [#1341](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1341) ([alexjfisher](https://github.com/alexjfisher)) -### Other - -- Remove unused parser deprecation function [#1392](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1392) ([ekohl](https://github.com/ekohl)) - ## [v9.3.0](https://github.com/puppetlabs/puppetlabs-stdlib/tree/v9.3.0) - 2023-08-01 [Full Changelog](https://github.com/puppetlabs/puppetlabs-stdlib/compare/v9.2.0...v9.3.0) @@ -68,11 +80,6 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a [Full Changelog](https://github.com/puppetlabs/puppetlabs-stdlib/compare/v8.6.0...v9.0.0) -### Added - -- Namespace Puppet 4.x functions [#1356](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1356) ([smortex](https://github.com/smortex)) -- Add a function to update / regenerate deprecated shims [#1349](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1349) ([smortex](https://github.com/smortex)) - ### Changed - Deprecate the `validate_legacy()` function [#1353](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1353) ([smortex](https://github.com/smortex)) - Remove deprecated functions [#1352](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1352) ([smortex](https://github.com/smortex)) @@ -108,6 +115,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a - Remove deprecated type and type3x functions [#1309](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1309) ([MartyEwings](https://github.com/MartyEwings)) - (CONT-801) Puppet 8 support / Drop Puppet 6 support [#1307](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1307) ([LukasAud](https://github.com/LukasAud)) +### Added + +- Namespace Puppet 4.x functions [#1356](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1356) ([smortex](https://github.com/smortex)) +- Add a function to update / regenerate deprecated shims [#1349](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1349) ([smortex](https://github.com/smortex)) + ### Fixed - Remove deprecated File.exists? [#1357](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1357) ([ekohl](https://github.com/ekohl)) @@ -226,18 +238,18 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a [Full Changelog](https://github.com/puppetlabs/puppetlabs-stdlib/compare/v7.1.0...v8.0.0) +### Changed +- Flip installed and present in Function ensure_packages [#1196](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1196) ([cocker-cc](https://github.com/cocker-cc)) + ### Added - New function to_python() / to_ruby() [#1200](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1200) ([smortex](https://github.com/smortex)) - pdksync - (IAC-1709) - Add Support for Debian 11 [#1199](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1199) ([david22swan](https://github.com/david22swan)) - Stdlib::Http::Method: Add new type for http methods [#1192](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1192) ([b4ldr](https://github.com/b4ldr)) -### Changed -- Flip installed and present in Function ensure_packages [#1196](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1196) ([cocker-cc](https://github.com/cocker-cc)) - ### Fixed -- (MODULES-11099) Make merge parameter data types actually backwards compatible [#1191](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1191) ([SimonPe](https://github.com/SimonPe)) +- (MODULES-11099) Make merge parameter data types actually backwards compatible [#1191](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1191) ([LadyNamedLaura](https://github.com/LadyNamedLaura)) ## [v7.1.0](https://github.com/puppetlabs/puppetlabs-stdlib/tree/v7.1.0) - 2021-05-17 @@ -259,13 +271,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a [Full Changelog](https://github.com/puppetlabs/puppetlabs-stdlib/compare/v6.6.0...v7.0.0) +### Changed +- pdksync - Remove Puppet 5 from testing and bump minimal version to 6.0.0 [#1164](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1164) ([carabasdaniel](https://github.com/carabasdaniel)) + ### Added - Stdlib::Email type [#1160](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1160) ([b4ldr](https://github.com/b4ldr)) -### Changed -- pdksync - Remove Puppet 5 from testing and bump minimal version to 6.0.0 [#1164](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1164) ([carabasdaniel](https://github.com/carabasdaniel)) - ### Fixed - (bugfix) Setting stricter email validation [#1163](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1163) ([pmcmaw](https://github.com/pmcmaw)) @@ -367,14 +379,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a [Full Changelog](https://github.com/puppetlabs/puppetlabs-stdlib/compare/5.2.0...v6.0.0) +### Changed +- pdksync - (MODULES-8444) - Raise lower Puppet bound [#1011](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1011) ([david22swan](https://github.com/david22swan)) + ### Added - (MODULES-8760) Add iterative feature to merge() function [#1008](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1008) ([hlindberg](https://github.com/hlindberg)) - Add a stdlib::ip_in_range() function [#1003](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1003) ([iglov](https://github.com/iglov)) -### Changed -- pdksync - (MODULES-8444) - Raise lower Puppet bound [#1011](https://github.com/puppetlabs/puppetlabs-stdlib/pull/1011) ([david22swan](https://github.com/david22swan)) - ## [5.2.0](https://github.com/puppetlabs/puppetlabs-stdlib/tree/5.2.0) - 2019-01-18 [Full Changelog](https://github.com/puppetlabs/puppetlabs-stdlib/compare/5.1.0...5.2.0) diff --git a/REFERENCE.md b/REFERENCE.md index 5e97d1ac8..8e6621420 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -139,6 +139,7 @@ Puppet structure * [`stdlib::seeded_rand_string`](#stdlib--seeded_rand_string): Generates a consistent random string of specific length based on provided seed. * [`stdlib::sha256`](#stdlib--sha256): Run a SHA256 calculation against a given value. * [`stdlib::shell_escape`](#stdlib--shell_escape): Escapes a string so that it can be safely used in a Bourne shell command line. +* [`stdlib::sort_by`](#stdlib--sort_by): Sort an Array, Hash or String by mapping values through a given block. * [`stdlib::start_with`](#stdlib--start_with): Returns true if str starts with one of the prefixes given. Each of the prefixes should be a String. * [`stdlib::str2resource`](#stdlib--str2resource): This converts a string to a puppet resource. * [`stdlib::time`](#stdlib--time): This function is deprecated. It implements the functionality of the original non-namespaced stdlib `time` function. @@ -4003,6 +4004,75 @@ Data type: `Any` The string to escape +### `stdlib::sort_by` + +Type: Ruby 4.x API + +Sort an Array, Hash or String by mapping values through a given block. + +#### Examples + +##### Sort local devices according to their used space. + +```puppet +$facts['mountpoints'].stdlib::sort_by |$m| { $m.dig(1, 'used_bytes') } +``` + +#### `stdlib::sort_by(Array $ary, Callable[1,1] &$block)` + +The stdlib::sort_by function. + +Returns: `Array` Returns an ordered copy of ary. + +##### `ary` + +Data type: `Array` + +The Array to sort. + +##### `&block` + +Data type: `Callable[1,1]` + +The block for transforming elements of ary. + +#### `stdlib::sort_by(String $str, Callable[1,1] &$block)` + +The stdlib::sort_by function. + +Returns: `String` Returns an ordered copy of str. + +##### `str` + +Data type: `String` + +The String to sort. + +##### `&block` + +Data type: `Callable[1,1]` + +The block for transforming elements of str. + +#### `stdlib::sort_by(Hash $hsh, Variant[Callable[1,1], Callable[2,2]] &$block)` + +The stdlib::sort_by function. + +Returns: `Hash` Returns an ordered copy of hsh. + +##### `hsh` + +Data type: `Hash` + +The Hash to sort. + +##### `&block` + +Data type: `Variant[Callable[1,1], Callable[2,2]]` + +The block for transforming elements of hsh. +The block may have arity of one or two. + ### `stdlib::start_with` Type: Ruby 4.x API diff --git a/lib/puppet/functions/stdlib/sort_by.rb b/lib/puppet/functions/stdlib/sort_by.rb new file mode 100644 index 000000000..30b69b5f6 --- /dev/null +++ b/lib/puppet/functions/stdlib/sort_by.rb @@ -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 diff --git a/lib/puppet/parser/functions/pw_hash.rb b/lib/puppet/parser/functions/pw_hash.rb index 6196e14ac..7bd8fd62a 100644 --- a/lib/puppet/parser/functions/pw_hash.rb +++ b/lib/puppet/parser/functions/pw_hash.rb @@ -76,7 +76,7 @@ # handle weak implementations of String#crypt # dup the string to get rid of frozen status for testing - if RUBY_PLATFORM == 'java' + if RUBY_PLATFORM == 'java' && !args[1].downcase.start_with?('bcrypt') # puppetserver bundles Apache Commons Codec org.apache.commons.codec.digest.Crypt.crypt(password.to_java_bytes, salt) elsif (+'test').crypt('$1$1') == '$1$1$Bp8CU9Oujr9SSEw53WV6G.' diff --git a/metadata.json b/metadata.json index ad43452cf..1befd5b66 100644 --- a/metadata.json +++ b/metadata.json @@ -1,6 +1,6 @@ { "name": "puppetlabs-stdlib", - "version": "9.4.1", + "version": "9.5.0", "author": "puppetlabs", "summary": "Standard library of resources for Puppet modules.", "license": "Apache-2.0", diff --git a/spec/functions/sort_by_spec.rb b/spec/functions/sort_by_spec.rb new file mode 100644 index 000000000..6a14f2977 --- /dev/null +++ b/spec/functions/sort_by_spec.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'stdlib::sort_by' do + it { is_expected.not_to be_nil } + + describe 'raise exception with inappropriate parameters' do + it { is_expected.to run.with_params.and_raise_error(ArgumentError, Regexp.new('expects 1 argument, got none')) } + it { is_expected.to run.with_params([]).and_raise_error(ArgumentError, Regexp.new('expects a block')) } + it { is_expected.to run.with_params(:undef).and_raise_error(ArgumentError, Regexp.new("rejected: parameter 'ary' expects an Array value, got Undef")) } + it { is_expected.to run.with_params(true).and_raise_error(ArgumentError, Regexp.new("rejected: parameter 'ary' expects an Array value, got Boolean")) } + it { is_expected.to run.with_params(1).and_raise_error(ArgumentError, Regexp.new("rejected: parameter 'ary' expects an Array value, got Integer")) } + it { is_expected.to run.with_params({}).with_lambda { 1 }.and_raise_error(ArgumentError, Regexp.new('block expects between 1 and 2 arguments, got none')) } + end + + # Puppet's each iterator considers Integers, Strings, Arrays and Hashes to be Iterable. + unordered_array = ['The', 'quick', 'brown', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog'] + ordered_array = ['The', 'brown', 'dog', 'fox', 'jumps', 'lazy', 'over', 'quick', 'the'] + unordered_hash = { 'The' => 'quick', 'brown' => 'fox', 'jumps' => 'over', 'the' => 'lazy', 'dog' => '.' } + ordered_hash = { 'dog' => '.', 'brown' => 'fox', 'the' => 'lazy', 'jumps' => 'over', 'The' => 'quick' } + unordered_string = 'The quick brown fox jumps over the lazy dog.' + ordered_string = ' .Tabcdeeefghhijklmnoooopqrrstuuvwxyz' + + describe 'with sane input' do + it 'does sort Array' do + expect(subject).to run \ + .with_params(unordered_array) \ + .with_lambda { |e| e } \ + .and_return(ordered_array) + end + + it 'does sort Hash by entry' do + expect(subject).to run \ + .with_params(unordered_hash) \ + .with_lambda { |e| e[1] } \ + .and_return(ordered_hash) + end + + it 'does sort Hash by key-value pairs' do + expect(subject).to run \ + .with_params(unordered_hash) \ + .with_lambda { |_, v| v } \ + .and_return(ordered_hash) + end + + it 'does sort String' do + expect(subject).to run \ + .with_params(unordered_string) \ + .with_lambda { |e| e } \ + .and_return(ordered_string) + end + end +end