From 4708811ecfec1a76ae0e6b6f0d5e6e2ea24c1f5b Mon Sep 17 00:00:00 2001 From: lnemsick-simp Date: Thu, 23 Sep 2021 16:26:20 -0400 Subject: [PATCH] (SIMP-9883) Generalize simpkv acceptance tests (#63) Rewrote simpkv acceptance tests used by the file plugin so that the test infrastructure can be used by any plugin or any combination of plugins. Also, addressed test deficiencies such as the absence of global key testing and test infrastructure design flaws such as the confusing, unnecessary coupling of test data and the simpkv_test module. This test infrastructure is required for the ldap plugin. --- .gitlab-ci.yml | 42 + README.md | 7 +- spec/acceptance/helpers.rb | 2 + .../helpers/files/initial_key_info.erb | 119 ++ spec/acceptance/helpers/manifest_utils.rb | 25 + spec/acceptance/helpers/test_data.rb | 482 ++++++++ spec/acceptance/helpers/utils.rb | 40 + spec/acceptance/nodesets/centos7.yml | 23 + spec/acceptance/nodesets/default.yml | 10 +- spec/acceptance/nodesets/oel.yml | 12 +- spec/acceptance/nodesets/oel7.yml | 23 + spec/acceptance/shared_examples.rb | 2 + .../shared_examples/pre_populate_keystores.rb | 35 + .../shared_examples/simpkv_delete.rb | 97 ++ .../shared_examples/simpkv_deletetree.rb | 145 +++ .../shared_examples/simpkv_exists.rb | 84 ++ spec/acceptance/shared_examples/simpkv_get.rb | 52 + .../acceptance/shared_examples/simpkv_list.rb | 52 + .../shared_examples/simpkv_plugin.rb | 128 +++ spec/acceptance/shared_examples/simpkv_put.rb | 86 ++ .../default/00_file_plugin_setup_spec.rb | 18 + .../default/10_configured_file_plugin_spec.rb | 69 ++ .../20_auto_default_file_plugin_spec.rb | 47 + .../suites/default/file_plugin_spec.rb | 301 ----- .../suites/default/validate_file_entries.rb | 146 +++ spec/spec_helper_acceptance.rb | 12 +- spec/support/modules/simpkv_test/README.md | 94 ++ spec/support/modules/simpkv_test/REFERENCE.md | 1002 +++++++++++++++++ .../simpkv_test/files/test_krb5.keytab | Bin 0 -> 168 bytes .../simpkv_test/functions/assert_equal.pp | 23 +- .../simpkv_test/functions/code_source.pp | 16 + .../simpkv_test/functions/key_value.pp | 23 + .../puppet_functions/remove_folder.pp | 18 + .../functions/puppet_functions/remove_key.pp | 18 + .../retrieve_and_verify_folder.pp | 32 + .../retrieve_and_verify_key.pp | 38 + .../functions/puppet_functions/store_key.pp | 26 + .../puppet_functions/verify_name_exists.pp | 28 + .../simpkv_test/functions/put_pwrapper.pp | 17 - .../simpkv_test/functions/simpkv_options.pp | 45 + .../functions/verify_folder_data.pp | 42 + .../simpkv_test/functions/verify_key_data.pp | 59 + .../simpkv_test/manifests/binary_get.pp | 25 - .../simpkv_test/manifests/binary_put.pp | 7 - .../simpkv_test/manifests/defines/put.pp | 9 - .../manifests/defines/remove_folder.pp | 17 + .../manifests/defines/remove_key.pp | 17 + .../defines/retrieve_and_verify_folder.pp | 30 + .../defines/retrieve_and_verify_key.pp | 34 + .../manifests/defines/store_key.pp | 25 + .../manifests/defines/verify_name_exists.pp | 26 + .../modules/simpkv_test/manifests/delete.pp | 48 - .../simpkv_test/manifests/deletetree.pp | 44 - .../modules/simpkv_test/manifests/exists.pp | 55 - .../modules/simpkv_test/manifests/get.pp | 36 - .../modules/simpkv_test/manifests/list.pp | 79 -- .../modules/simpkv_test/manifests/params.pp | 33 - .../modules/simpkv_test/manifests/put.pp | 45 - .../simpkv_test/manifests/remove_folders.pp | 34 + .../simpkv_test/manifests/remove_keys.pp | 34 + .../manifests/retrieve_and_verify_folders.pp | 83 ++ .../manifests/retrieve_and_verify_keys.pp | 95 ++ .../simpkv_test/manifests/store_keys.pp | 44 + .../manifests/verify_folders_exist.pp | 51 + .../manifests/verify_keys_exist.pp | 51 + .../support/modules/simpkv_test/metadata.json | 30 +- .../modules/simpkv_test/types/appid.pp | 3 + .../modules/simpkv_test/types/folderdata.pp | 10 + .../modules/simpkv_test/types/folderinfo.pp | 31 + .../modules/simpkv_test/types/folders.pp | 2 + spec/support/modules/simpkv_test/types/key.pp | 5 + .../modules/simpkv_test/types/keydata.pp | 18 + .../modules/simpkv_test/types/keyinfo.pp | 32 + .../support/modules/simpkv_test/types/keys.pp | 2 + .../modules/simpkv_test/types/nameinfo.pp | 32 + .../simpkv_test/types/nonbinarykeydata.pp | 9 + 76 files changed, 3890 insertions(+), 746 deletions(-) create mode 100644 spec/acceptance/helpers.rb create mode 100644 spec/acceptance/helpers/files/initial_key_info.erb create mode 100644 spec/acceptance/helpers/manifest_utils.rb create mode 100644 spec/acceptance/helpers/test_data.rb create mode 100644 spec/acceptance/helpers/utils.rb create mode 100644 spec/acceptance/nodesets/centos7.yml create mode 100644 spec/acceptance/nodesets/oel7.yml create mode 100644 spec/acceptance/shared_examples.rb create mode 100644 spec/acceptance/shared_examples/pre_populate_keystores.rb create mode 100644 spec/acceptance/shared_examples/simpkv_delete.rb create mode 100644 spec/acceptance/shared_examples/simpkv_deletetree.rb create mode 100644 spec/acceptance/shared_examples/simpkv_exists.rb create mode 100644 spec/acceptance/shared_examples/simpkv_get.rb create mode 100644 spec/acceptance/shared_examples/simpkv_list.rb create mode 100644 spec/acceptance/shared_examples/simpkv_plugin.rb create mode 100644 spec/acceptance/shared_examples/simpkv_put.rb create mode 100644 spec/acceptance/suites/default/00_file_plugin_setup_spec.rb create mode 100644 spec/acceptance/suites/default/10_configured_file_plugin_spec.rb create mode 100644 spec/acceptance/suites/default/20_auto_default_file_plugin_spec.rb delete mode 100644 spec/acceptance/suites/default/file_plugin_spec.rb create mode 100644 spec/acceptance/suites/default/validate_file_entries.rb create mode 100644 spec/support/modules/simpkv_test/README.md create mode 100644 spec/support/modules/simpkv_test/REFERENCE.md create mode 100644 spec/support/modules/simpkv_test/files/test_krb5.keytab create mode 100644 spec/support/modules/simpkv_test/functions/code_source.pp create mode 100644 spec/support/modules/simpkv_test/functions/key_value.pp create mode 100644 spec/support/modules/simpkv_test/functions/puppet_functions/remove_folder.pp create mode 100644 spec/support/modules/simpkv_test/functions/puppet_functions/remove_key.pp create mode 100644 spec/support/modules/simpkv_test/functions/puppet_functions/retrieve_and_verify_folder.pp create mode 100644 spec/support/modules/simpkv_test/functions/puppet_functions/retrieve_and_verify_key.pp create mode 100644 spec/support/modules/simpkv_test/functions/puppet_functions/store_key.pp create mode 100644 spec/support/modules/simpkv_test/functions/puppet_functions/verify_name_exists.pp delete mode 100644 spec/support/modules/simpkv_test/functions/put_pwrapper.pp create mode 100644 spec/support/modules/simpkv_test/functions/simpkv_options.pp create mode 100644 spec/support/modules/simpkv_test/functions/verify_folder_data.pp create mode 100644 spec/support/modules/simpkv_test/functions/verify_key_data.pp delete mode 100644 spec/support/modules/simpkv_test/manifests/binary_get.pp delete mode 100644 spec/support/modules/simpkv_test/manifests/binary_put.pp delete mode 100644 spec/support/modules/simpkv_test/manifests/defines/put.pp create mode 100644 spec/support/modules/simpkv_test/manifests/defines/remove_folder.pp create mode 100644 spec/support/modules/simpkv_test/manifests/defines/remove_key.pp create mode 100644 spec/support/modules/simpkv_test/manifests/defines/retrieve_and_verify_folder.pp create mode 100644 spec/support/modules/simpkv_test/manifests/defines/retrieve_and_verify_key.pp create mode 100644 spec/support/modules/simpkv_test/manifests/defines/store_key.pp create mode 100644 spec/support/modules/simpkv_test/manifests/defines/verify_name_exists.pp delete mode 100644 spec/support/modules/simpkv_test/manifests/delete.pp delete mode 100644 spec/support/modules/simpkv_test/manifests/deletetree.pp delete mode 100644 spec/support/modules/simpkv_test/manifests/exists.pp delete mode 100644 spec/support/modules/simpkv_test/manifests/get.pp delete mode 100644 spec/support/modules/simpkv_test/manifests/list.pp delete mode 100644 spec/support/modules/simpkv_test/manifests/params.pp delete mode 100644 spec/support/modules/simpkv_test/manifests/put.pp create mode 100644 spec/support/modules/simpkv_test/manifests/remove_folders.pp create mode 100644 spec/support/modules/simpkv_test/manifests/remove_keys.pp create mode 100644 spec/support/modules/simpkv_test/manifests/retrieve_and_verify_folders.pp create mode 100644 spec/support/modules/simpkv_test/manifests/retrieve_and_verify_keys.pp create mode 100644 spec/support/modules/simpkv_test/manifests/store_keys.pp create mode 100644 spec/support/modules/simpkv_test/manifests/verify_folders_exist.pp create mode 100644 spec/support/modules/simpkv_test/manifests/verify_keys_exist.pp create mode 100644 spec/support/modules/simpkv_test/types/appid.pp create mode 100644 spec/support/modules/simpkv_test/types/folderdata.pp create mode 100644 spec/support/modules/simpkv_test/types/folderinfo.pp create mode 100644 spec/support/modules/simpkv_test/types/folders.pp create mode 100644 spec/support/modules/simpkv_test/types/key.pp create mode 100644 spec/support/modules/simpkv_test/types/keydata.pp create mode 100644 spec/support/modules/simpkv_test/types/keyinfo.pp create mode 100644 spec/support/modules/simpkv_test/types/keys.pp create mode 100644 spec/support/modules/simpkv_test/types/nameinfo.pp create mode 100644 spec/support/modules/simpkv_test/types/nonbinarykeydata.pp diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 00d9a52..eca7bf6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -353,9 +353,30 @@ pup6.pe: pup6.pe-fips: <<: *pup_6_pe <<: *acceptance_base + <<: *with_SIMP_ACCEPTANCE_MATRIX_LEVEL_3 script: - 'BEAKER_fips=yes bundle exec rake beaker:suites[default,default]' +pup6.x.centos7: + <<: *pup_6_x + <<: *acceptance_base + script: + - 'bundle exec rake beaker:suites[default,centos7]' + +pup6.x.centos7-fips: + <<: *pup_6_x + <<: *acceptance_base + <<: *with_SIMP_ACCEPTANCE_MATRIX_LEVEL_3 + script: + - 'BEAKER_fips=yes bundle exec rake beaker:suites[default,centos7]' + +pup6.pe.centos7: + <<: *pup_6_pe + <<: *acceptance_base + <<: *with_SIMP_ACCEPTANCE_MATRIX_LEVEL_3 + script: + - 'bundle exec rake beaker:suites[default,centos7]' + pup6.pe-oel: <<: *pup_6_pe <<: *acceptance_base @@ -369,8 +390,29 @@ pup6.pe-oel-fips: script: - 'BEAKER_fips=yes bundle exec rake beaker:suites[default,oel]' +pup6.pe.centos7-oel: + <<: *pup_6_pe + <<: *acceptance_base + <<: *with_SIMP_ACCEPTANCE_MATRIX_LEVEL_3 + script: + - 'bundle exec rake beaker:suites[default,oel7]' + +pup6.pe.centos7-oel-fips: + <<: *pup_6_pe + <<: *acceptance_base + <<: *with_SIMP_ACCEPTANCE_MATRIX_LEVEL_3 + script: + - 'BEAKER_fips=yes bundle exec rake beaker:suites[default,oel7]' + pup7.x: <<: *pup_7_x <<: *acceptance_base script: - 'bundle exec rake beaker:suites[default,default]' + +pup7.x.centos7: + <<: *pup_7_x + <<: *acceptance_base + <<: *with_SIMP_ACCEPTANCE_MATRIX_LEVEL_3 + script: + - 'bundle exec rake beaker:suites[default,centos7]' diff --git a/README.md b/README.md index 52eb5c4..e57a934 100644 --- a/README.md +++ b/README.md @@ -506,9 +506,10 @@ To create your own plugin test shows you how to instantiate an object of your plugin for testing purposes. * Write acceptance tests for your plugin, using the acceptance tests for - simpkv's file plugin, `spec/acceptances/suites/default/file_plugin_spec.rb`, - as an example. That test uses a test module, `spec/support/simpkv_test` to - exercise the the simpkv API and verify its operation. + simpkv's file plugin in `spec/acceptances/suites/default/`, + as an example. That test uses a test module, `spec/support/simpkv_test` + and a plugin-specific validator to exercise the the simpkv API and verify its + operation with the file plugin. * Document your plugin's type and configuration parameters in the README.md for your store plugin module. diff --git a/spec/acceptance/helpers.rb b/spec/acceptance/helpers.rb new file mode 100644 index 0000000..7ab878a --- /dev/null +++ b/spec/acceptance/helpers.rb @@ -0,0 +1,2 @@ +rb_files = File.expand_path( 'helpers/**/*.rb', __dir__) +Dir.glob( rb_files ).sort_by(&:to_s).each { |file| require file } diff --git a/spec/acceptance/helpers/files/initial_key_info.erb b/spec/acceptance/helpers/files/initial_key_info.erb new file mode 100644 index 0000000..603ddc8 --- /dev/null +++ b/spec/acceptance/helpers/files/initial_key_info.erb @@ -0,0 +1,119 @@ +--- +# NOTES FOR TEST MAINTAINERS: +# This file specifies test key information in a data structure corresponding to +# the Simpkv_test::KeyInfo type alias. This data or data derived from it will be +# used to stimulate simpkv_test manifests to test simpkv functions. +# +# ** Please take time to understand how the simpkv_test module works! ** +# +# Important details about this key information are as follows: +# * The keys are designed to cover a wide variety of keys types a user could +# specify. This includes: +# - Keys with simple values (Boolean, Integer, Float, String) +# - Keys with complex values (Hash, Array) +# - Keys that have to be handled with special Puppet code (Binary values) +# - Puppet-environment-specific keys +# - Global keys +# - Keys with/without metadata +# - Keys with/without path elements in their key names +# * The keys are explicitly designed to test that key uniqueness is +# appropriately handled. +# - Keys are supposed to be uniquely specified by their +# {key path, global status, and backend} triples. +# - This data and the tests **ASSUME** a one-to-one mapping of app_id +# to backend, and so a key is uniquely specified by its +# {key path, global status, and app_id} triple. +# - This file contains multiple keys with the same key path, but different +# content and different combinations of app_id and global status. +# * The key info is also designed to test different folder configurations +# - Folders with keys and sub-folders +# - Folders with only keys +# - Folders with only sub-folders +# +# Also of note: +# - This file currently only supports 3 different app_ids. +# - Binary data is loaded with the Puppet binary_file() method, so the +# 'file' specification must match what that function requires. +# - Validation logic elsewhere assumes the Binary value of a key will be found +# in a file in the simpkv_test module. +# +"<%= appid1 %>": + env: + boolean: + value: true + integer: + value: 1234567890 + metadata: + verified: true + float: + value: 0.123 + string: + value: "test string1" + metadata: + author: "Sally Smith" + complex/array_integers: + value: + - 8 + - 9 + - 10 + metadata: + normalized: true + complex/array_strings: + value: + - 'test string2' + complex/hash: + value: + attr1: "test string2" + attr2: 11.0 + attr3: false + attr4: + part1: "test string3" + part2: true + part3: + - 12 + - 13 + empty/string: + value: "" + empty/complex/array: + value: [] + empty/complex/hash: + value: {} + global: + boolean: + value: false + string: + value: "global test string1" + metadata: + auditor: "Jill Jones" + binary/keytabs/test_krb5.keytab: + file: "simpkv_test/test_krb5.keytab" + metadata: + comment: "from simp/krb5 test" +"<%= appid2 %>": + # list will have no sub-folders + env: + integer: + value: 123 + float: + value: 45.678 + metadata: + origin: sensor + version: 3 + global: + integer: + value: 901 + metadata: + truncated: true + string: + value: "global test string2" + +"<%= appid3 %>": + env: + # list will have only sub-folders + complex/hash: + value: + location: rack1 + slot: 10 + metadata: + last_reviewed: "2021-08-30" + # global list will be empty diff --git a/spec/acceptance/helpers/manifest_utils.rb b/spec/acceptance/helpers/manifest_utils.rb new file mode 100644 index 0000000..119c6b6 --- /dev/null +++ b/spec/acceptance/helpers/manifest_utils.rb @@ -0,0 +1,25 @@ +module Acceptance + module Helpers + module ManifestUtils + + def print_test_config(hieradata, manifest) + puts '>'*80 + if hieradata.is_a?(Hash) + puts "Hieradata:\n#{hieradata.to_yaml}" + else + puts "Hieradata:\n#{hieradata}" + end + puts '-'*80 + puts "Manifest:\n#{manifest}" + puts '<'*80 + end + + def set_hiera_and_apply_on(host, hieradata, manifest, apply_opts = {}, verbose = true ) + print_test_config(hieradata, manifest) if verbose + set_hieradata_on(host, hieradata) + apply_manifest_on(host, manifest, apply_opts) + end + + end + end +end diff --git a/spec/acceptance/helpers/test_data.rb b/spec/acceptance/helpers/test_data.rb new file mode 100644 index 0000000..f0b19f0 --- /dev/null +++ b/spec/acceptance/helpers/test_data.rb @@ -0,0 +1,482 @@ +require 'erb' +require 'pathname' +require 'set' +require 'yaml' + +module Acceptance; end +module Acceptance::Helpers; end + +# Methods to create simpkv backend hieradata and simpkv_test module hieradata +# to exercise and verify simpkv functions. +# +# - See the simpkv module README.md for a description of simpkv backend +# hieradata +# - See the simpkv_test module documentation for descriptions of the +# type aliases corresponding to the Hashes used in the data +# generation/transformation methods. + +module Acceptance::Helpers::TestData + + # @return simpkv::options hieradata with aliases to backend configuration + # derived from backend_configs + # + # @param backend_configs Hash of backend configuration + # - Key is the name of the backend and its value is its backend + # configuration Hash. + # - One of the backend names must be 'default'. + # - Each backend configuration Hash must have 'type' specifying the plugin + # type and any other plugin-specific configuration required in order for + # the plugin to connect to its keystore. + # - This method will set the required backend config 'id' attribute for + # each backend configuration in the hieradata. + # - 'id' will be set to the backend's name. + # - Backends are *not* required to be of the same 'type'. + # + # @raise RuntimeError if 'default' is not one of the backend config names or + # if any backend configuration is missing the required 'type' attribute + # + def generate_backend_hiera(backend_configs) + errors = [] + unless backend_configs.keys.include?('default') + errors << "'default' backend missing from backend config: #{backend_configs}" + end + + backend_configs.each do |name, config| + unless config.include?('type') + errors << "'#{name}' backend config missing 'type': #{config}" + end + end + + unless errors.empty? + raise("ERROR: Invalid backend configuration:\n#{errors.join("\n")}") + end + + hiera = {} + backends = {} + backend_configs.each do |name, config| + backend_tag = "simpkv::backend::#{name}" + hiera[backend_tag] = config + hiera[backend_tag]['id'] = name + backends[name]= "%{alias('#{backend_tag}')}" + end + + hiera['simpkv::options'] = { + 'environment' => '%{server_facts.environment}', + 'softfail' => false, + 'backends' => backends + } + + hiera + end + + # Generates a Hash of key information for 3 app ids + # + # >> See the comment block in initial_key_info.erb for important details! << + # + # Note that this method will map 'default' to '', in order to test the + # behavior of the simpkv functions when there is no `app_id` attribute in + # the `simpkv_options` parameter in a simpkv function call. + # + # @param app_id1 First app_id; expected to map uniquely to a backend + # @param app_id2 Second app_id; expected to map uniquely a backend + # @param app_id3 Third app_id; expected to map uniquely a backend + # + # @return Hash of key information whose format corresponds to the + # Simpkv_test::KeyInfo type alias + # + # @raise RuntimeError if the 3 app ids are not unique + # + def generate_initial_key_info(app_id1, app_id2, app_id3) + ids = [ app_id1, app_id2, app_id3 ].uniq + unless ids.size == 3 + raise("ERROR: App ids must be unique: <#{app_id1}, #{app_id2}, #{app_id3}>") + end + + data_template = File.join(__dir__, 'files', 'initial_key_info.erb') + appid1 = (app_id1 == 'default') ? '' : app_id1 + appid2 = (app_id2 == 'default') ? '' : app_id2 + appid3 = (app_id3 == 'default') ? '' : app_id3 + + data_yaml = ERB.new(File.read(data_template)).result(binding) + YAML.load(data_yaml) + end + + # @return transformed copy of original_key_info in which the key values and/or + # metadata have been modified + # + # TODO Change the 'file' attribute of a key specification for keys + # with Binary values. Currently only modifies all non-binary values, + # i.e., keys whose specification has a 'value' attribute. + # + # @param original_key_info Hash of key info whose format corresponds to + # the Simpkv_test::KeyInfo type alias + # + def modify_key_data(original_key_info) + updated_key_info = Marshal.load(Marshal.dump(original_key_info)) + updated_key_info.each do |app_id, key_struct| + key_struct.each do |key_type, keys| + keys.each do |key, key_data| + # modify non-binary values + if key_data.key?('value') + if key_data['value'].is_a?(Array) || key_data['value'].is_a?(String) + key_data['value'] = key_data['value'] + key_data['value'] + end + + if key_data['value'].is_a?(TrueClass) || key_data['value'].is_a?(FalseClass) + key_data['value'] = ! key_data['value'] + end + + if key_data['value'].is_a?(Hash) + key_data['value']['new_key'] = 'new string elem' + end + + if key_data['value'].is_a?(Numeric) + key_data['value'] *= 10 + end + end + + #TODO modify binary values specified by a 'file' attribute + + # modify metadata + if key_data.key?('metadata') + key_data.delete('metadata') + else + key_data['metadata'] = { 'version' => 2 } + end + end + end + end + + updated_key_info + end + + # @return transformed copy of original_folder_info in which each folder + # listed has suffix appended to its name + # + # @param original_folder_info Hash of folder name info whose format + # corresponds to the Simpkv_test::FolderInfo type alias + # + # @param suffix Suffix to be appended to each original folder name + # + def rename_folders_in_folder_info(original_folder_info, suffix='new') + new_info = {} + original_folder_info.each do |app_id,folder_struct| + new_info[app_id] = {} + folder_struct.each do |folder_type,folders| + new_info[app_id][folder_type] = {} + folders.each do |folder,folder_data| + new_info[app_id][folder_type]["#{folder}#{suffix}"] = folder_data + end + end + end + + new_info + end + + # @return transformed copy of original_foldername_info in which each folder + # listed has suffix appended to its name + # + # @param original_foldername_info Hash of folder name info whose format + # corresponds to the Simpkv_test::NameInfo type alias + # + # @param suffix Suffix to be appended to each original folder name + # + def rename_folders_in_name_info(original_foldername_info, suffix='new') + new_info = Marshal.load(Marshal.dump(original_foldername_info)) + new_info.each do |app_id,folder_struct| + folder_struct.each do |folder_type, folder_names| + folder_struct[folder_type] = folder_names.map { |folder| "#{folder}#{suffix}" } + end + end + + new_info + end + + # @return transformed copy of original_key_info in which the key names have been + # modified by suffix + # + # @param original_key_info Hash of key info whose format corresponds to + # the Simpkv_test::KeyInfo type alias + # + # @param suffix String to be appended to original key names + # + def rename_keys_in_key_info(original_key_info, suffix='new') + key_info = {} + original_key_info.each do |app_id, key_struct| + key_info[app_id] = {} + key_struct.each do |key_type, keys| + key_info[app_id][key_type] = {} + keys.each do |key, key_data| + new_key = key + suffix + key_info[app_id][key_type][new_key] = key_data + end + end + end + + key_info + end + + # Returns Hash of root folder names info for any non-empty root folders + # corresponding to the key data specified in key_info + # + # @param key_info Hash of key info whose format corresponds to the + # Simpkv_test::KeyInfo type alias + # + # @return Hash with root name info whose format corresponds to the + # Simpkv_test::NameInfo type alias or {} if no non-empty root directories are + # found + # + def root_foldername_info(key_info) + foldername_info = {} + full_foldername_info = to_foldername_info(key_info) + full_foldername_info.each do |app_id,folder_struct| + folder_struct.each do |folder_type, folder_names| + if folder_names.include?('/') + foldername_info[app_id] = {} unless foldername_info.key?(app_id) + foldername_info[app_id][folder_type] = [ '/' ] + end + end + end + + foldername_info + end + + # Creates a Hash of folder name info that is subset of subfolders in + # original_foldername_name + # + # NOTE: No child folders beneath a selected subfolder will be included in + # the returned result. + # + # @param original_foldername_info Hash with folder name info whose format + # corresponds to the Simpkv_test::NameInfo type alias + # + # @return Hash with subfolder name info whose format corresponds to the + # Simpkv_test::NameInfo type alias or {} if no subfolders are found + # + def select_subfolders_subset(original_foldername_info) + subset_info = {} + original_foldername_info.each do |app_id,folder_struct| + folder_struct.each do |folder_type, folder_names| + count = 0 + selected = [] + folder_names.sort.each do |folder| + next if folder == '/' + + within_selected_folder = false + selected.each do |subfolder| + if folder.start_with?("#{subfolder}/") + within_selected_folder = true + break + end + end + + if !within_selected_folder && ( (count % 2) == 0) + selected << folder + count += 1 + end + end + + unless selected.empty? + subset_info[app_id] = {} unless subset_info.key?(app_id) + subset_info[app_id][folder_type] = selected + end + end + end + + subset_info + end + + # Based on subfolder deletions specified in delete_foldernames_info, separate + # original_key_info into a pair of Hashes: one for retained keys and one + # for deleted keys + # + # @param original_key_info Hash of key info whose format corresponds to + # the Simpkv_test::KeyInfo type alias + # + # @param delete_foldernames_info Hash specifying the subfolders that have + # been deleted whose format corresponds to the Simpkv_test::NameInfo data + # type + # + # @param [ , ], where each is a Hash of key info + # whose format corresponds to the Simpkv_test::KeyInfo type alias + # + def split_key_info_per_subfolder_deletes(original_key_info, delete_foldernames_info) + retain_index = 0 + remove_index = 1 + key_infos = [ Hash.new, Hash.new ] + original_key_info.each do |app_id, key_struct| + key_struct.each do |key_type, keys| + keys.each do |key, key_data| + type = retain_index + if delete_foldernames_info.key?(app_id) && + delete_foldernames_info[app_id].key?(key_type) + delete_foldernames_info[app_id][key_type].each do |folder| + if key.start_with?("#{folder}/") + type = remove_index + break + end + end + end + + key_infos[type][app_id] = {} unless key_infos[type].key?(app_id) + key_infos[type][app_id][key_type] = {} unless key_infos[type][app_id].key?(key_type) + key_infos[type][app_id][key_type][key] = key_data + end + end + end + + key_infos + end + + # Split original_key_info into an Array of key info objects + # + # Input key data is assigned to an output Hash in a round-robin + # fashion per key type ('env' or 'global'). + # + # @param original_key_info Hash of key info whose format corresponds to + # the Simpkv_test::KeyInfo type alias + # + # @param split_size Number of key info hashes to create from original_key_info + # + # @return Array of key info hashes, each of which whose format corresponds to + # the Simpkv_test::KeyInfo type alias or is empty, if input key info hash is + # too sparse to support the split size specified. + # + def split_key_info(original_key_info, split_size=2) + key_infos = Array.new(split_size) { Hash.new } + + original_key_info.each do |app_id, key_struct| + key_infos.each { |key_info| key_info[app_id] = Hash.new } + key_struct.each do |key_type, keys| + key_infos.each { |key_info| key_info[app_id][key_type] = Hash.new } + + count = 0 + keys.each do |key, key_data| + key_infos[ count % split_size ][app_id][key_type][key] = key_data + count += 1 + end + + key_infos.each do |key_info| + if key_info[app_id][key_type].empty? + key_info[app_id].delete(key_type) + end + end + end + + key_infos.each do |key_info| + if key_info[app_id].empty? + key_info.delete(app_id) + end + end + end + + key_infos + end + + # @return Hash with full folder info derived from key_info and whose format + # corresponds to the Simpkv_test::FolderInfo type alias + # + # FIXME This method excludes any folders with binary key values in its + # output, because simpkv_test::retrieve_and_verify_folders doesn't yet handle + # verification of binary key data in simpk::list results + # + # @param key_info Hash of key information whose format corresponds to the + # Simpkv_test::KeyInfo type alias + # + # @param exclude_root_folder Whether to exclude the root folder from the returned + # listing + # + def to_folder_info(key_info, exclude_root_folder=false) + folder_info = {} + key_info.each do |app_id, key_struct| + folder_info[app_id] = {} + key_struct.each do |key_type, keys| + folder_info[app_id][key_type] = {} + keys.each do |key, key_data| + keypath = Pathname.new(key) + keypath.descend do |path| + parent = (path.dirname.to_s == '.') ? '/' : path.dirname.to_s + next if (parent == '/') && exclude_root_folder + + unless folder_info[app_id][key_type].key?(parent) + folder_info[app_id][key_type][parent] = { 'keys' => {}, 'folders' => [] } + end + if path.to_s == key + folder_info[app_id][key_type][parent]['keys'][path.basename.to_s] = key_data + else + unless folder_info[app_id][key_type][parent]['folders'].include?(path.basename.to_s) + folder_info[app_id][key_type][parent]['folders'] << path.basename.to_s + end + end + end + end + end + end + + folder_info.each do |app_id, folder_struct| + folder_struct.each do |folder_type, folders| + folders.delete_if do |folder, folder_data| + binary_data = false + folder_data['keys'].each do |key, key_data| + if key_data.key?('file') + binary_data = true + break + end + end + + binary_data + end + end + end + + folder_info + end + + # @return Hash with folder name info derived from key_info and whose format + # corresponds to the Simpkv_test::NameInfo type alias + # + # @param key_info Hash of key information whose format corresponds to the + # Simpkv_test::KeyInfo type alias + # + def to_foldername_info(key_info) + foldername_info = {} + key_info.each do |app_id, key_struct| + foldername_info[app_id] = {} + key_struct.each do |key_type, keys| + foldername_info[app_id][key_type] = Set.new + foldername_info[app_id][key_type] << '/' + keys.each do |key, key_data| + path = File.dirname(key) + unless path == '.' + Pathname.new(path).descend do |folder| + foldername_info[app_id][key_type] << folder.to_s + end + end + end + + foldername_info[app_id][key_type] = foldername_info[app_id][key_type].to_a.sort + end + end + + foldername_info + end + + # @return Hash with key name info derived from key_info and whose format + # corresponds to the Simpkv_test::NameInfo type alias + # + # @param key_info Hash of key information whose format corresponds to the + # Simpkv_test::KeyInfo type alias + # + def to_keyname_info(key_info) + keyname_info = {} + key_info.each do |app_id, key_struct| + keyname_info[app_id] = {} + key_struct.each do |key_type, keys| + keyname_info[app_id][key_type] = keys.keys + end + end + + keyname_info + end +end + diff --git a/spec/acceptance/helpers/utils.rb b/spec/acceptance/helpers/utils.rb new file mode 100644 index 0000000..08afe0d --- /dev/null +++ b/spec/acceptance/helpers/utils.rb @@ -0,0 +1,40 @@ +require 'json' +require 'base64' + +module Acceptance; end +module Acceptance::Helpers; end + +module Acceptance::Helpers::Utils + + # @return key string persisted to the backend for the key_data + # + # FIXME: If the data is binary and specified by the 'file' attribute, + # this method ASSUMES the file is in the simpkv_test module + # + # @param key_data + def key_data_string(key_data) + key_hash = {} + if key_data.key?('value') + key_hash['value'] = key_data['value'] + elsif key_data.key?('file') + simpkv_test_files = File.join(__dir__, '../../support/modules/simpkv_test/files') + value = IO.read( key_data['file'].gsub('simpkv_test', "#{simpkv_test_files}") ) + value.force_encoding('ASCII-8BIT') + + encoded_value = Base64.strict_encode64(value) + key_hash['value'] = encoded_value + key_hash['encoding'] = 'base64' + key_hash['original_encoding'] = 'ASCII-8BIT' + end + + if key_data.key?('metadata') + key_hash['metadata'] = key_data['metadata'] + else + key_hash['metadata'] = {} + end + + key_hash.to_json + end + +end + diff --git a/spec/acceptance/nodesets/centos7.yml b/spec/acceptance/nodesets/centos7.yml new file mode 100644 index 0000000..3537fb1 --- /dev/null +++ b/spec/acceptance/nodesets/centos7.yml @@ -0,0 +1,23 @@ +<% + if ENV['BEAKER_HYPERVISOR'] + hypervisor = ENV['BEAKER_HYPERVISOR'] + else + hypervisor = 'vagrant' + end +-%> +HOSTS: + el7: + roles: + - default + platform: el-7-x86_64 + box: centos/7 + hypervisor: <%= hypervisor %> + +CONFIG: + log_level: verbose + synced_folder : disabled + type: aio + vagrant_memsize: 256 +<% if ENV['BEAKER_PUPPET_COLLECTION'] -%> + puppet_collection: <%= ENV['BEAKER_PUPPET_COLLECTION'] %> +<% end -%> diff --git a/spec/acceptance/nodesets/default.yml b/spec/acceptance/nodesets/default.yml index 38453b7..0f2c175 100644 --- a/spec/acceptance/nodesets/default.yml +++ b/spec/acceptance/nodesets/default.yml @@ -8,19 +8,11 @@ HOSTS: el8: roles: - - server - default - - master - - client platform: el-8-x86_64 box: generic/centos8 hypervisor: <%= hypervisor %> - el7: - roles: - - client - platform: el-7-x86_64 - box: centos/7 - hypervisor: <%= hypervisor %> + CONFIG: log_level: verbose synced_folder : disabled diff --git a/spec/acceptance/nodesets/oel.yml b/spec/acceptance/nodesets/oel.yml index acc3f24..101da67 100644 --- a/spec/acceptance/nodesets/oel.yml +++ b/spec/acceptance/nodesets/oel.yml @@ -6,21 +6,13 @@ end -%> HOSTS: - oel8: - roles: - - server - - default - - master - - client - platform: el-8-x86_64 - box: generic/oracle8 - hypervisor: <%= hypervisor %> oel7: roles: - - client + - default platform: el-7-x86_64 box: generic/oracle7 hypervisor: <%= hypervisor %> + CONFIG: log_level: verbose synced_folder : disabled diff --git a/spec/acceptance/nodesets/oel7.yml b/spec/acceptance/nodesets/oel7.yml new file mode 100644 index 0000000..5d06091 --- /dev/null +++ b/spec/acceptance/nodesets/oel7.yml @@ -0,0 +1,23 @@ +<% + if ENV['BEAKER_HYPERVISOR'] + hypervisor = ENV['BEAKER_HYPERVISOR'] + else + hypervisor = 'vagrant' + end +-%> +HOSTS: + oel8: + roles: + - default + platform: el-8-x86_64 + box: generic/oracle8 + hypervisor: <%= hypervisor %> + +CONFIG: + log_level: verbose + synced_folder : disabled + type: aio + vagrant_memsize: 256 +<% if ENV['BEAKER_PUPPET_COLLECTION'] -%> + puppet_collection: <%= ENV['BEAKER_PUPPET_COLLECTION'] %> +<% end -%> diff --git a/spec/acceptance/shared_examples.rb b/spec/acceptance/shared_examples.rb new file mode 100644 index 0000000..b689f67 --- /dev/null +++ b/spec/acceptance/shared_examples.rb @@ -0,0 +1,2 @@ +rb_files = File.expand_path( 'shared_examples/**/*.rb', __dir__) +Dir.glob( rb_files ).sort_by(&:to_s).each { |file| require file } diff --git a/spec/acceptance/shared_examples/pre_populate_keystores.rb b/spec/acceptance/shared_examples/pre_populate_keystores.rb new file mode 100644 index 0000000..5ec8283 --- /dev/null +++ b/spec/acceptance/shared_examples/pre_populate_keystores.rb @@ -0,0 +1,35 @@ +# Execute simpkv::put operations via simpkv_test::store_keys to pre-populate key +# stores in the configured backend plugin. +# +# ASSUMED CONTEXT: +# The following are assumed to be available within this shared_examples context: +# * `clear_data_cmd`: Command string to be executed on the host to clear out +# all stored key data in the configured backends: +# - Must work from the host being tested, even when the keystore is not +# co-resident. +# +# * `backend_hiera`: 'simpkv::options' hash specifying backend configuration +# - One of the backends must be named 'default' +# +# * `initial_key_info`: Hash specifying key data to be initially stored in +# the backends: +# +shared_examples 'pre-populate keystores' do |host| + context "ensure keystores are pre-populated with initial keys on #{host}" do + let(:hieradata) { + backend_hiera.merge( { + 'simpkv_test::store_keys::key_info' => initial_key_info + } ) + } + + let(:manifest) { 'include simpkv_test::store_keys' } + + it 'should remove all backend instance data' do + on(host, clear_data_cmd, :accept_all_exit_codes => true) + end + + it 'should store keys' do + set_hiera_and_apply_on(host, hieradata, manifest, { :catch_failures => true }) + end + end +end diff --git a/spec/acceptance/shared_examples/simpkv_delete.rb b/spec/acceptance/shared_examples/simpkv_delete.rb new file mode 100644 index 0000000..59847b4 --- /dev/null +++ b/spec/acceptance/shared_examples/simpkv_delete.rb @@ -0,0 +1,97 @@ +# Execute and verify simpkv::delete using the configured backend plugins. +# +# ASSUMED CONTEXT: +# The following are assumed to be available within this shared_examples context: +# * `clear_data_cmd`: Command string to be executed on the host to clear out +# all stored key data in the configured backends: +# - Must work from the host being tested, even when the keystore is not +# co-resident. +# +# * `backend_hiera`: 'simpkv::options' hash specifying backend configuration +# - One of the backends must be named 'default' +# +# * `initial_key_info`: Hash specifying key data to be initially stored in +# the backends: +# - Format corresponds to the Simpkv_test::KeyInfo type alias +# - **Must** have app_ids that correspond to the backends named in +# backend_hiera +# +# * `validator`: Method object that can be called to independently validate +# backend state: +# - Method will be called to validate whether keys are present or absent in +# their corresponding backends, and when they are expected to be present, +# the stored key data is correct. +# - Method must return a Boolean indicating validation success +# - Method should log details of validation failures for debug +# - Method should attempt all validations before reporting failure +# - Method must have the following parameter list +# - Parameter 1: Hash of key information whose format corresponds to the +# Simpkv_test::KeyInfo type alias +# - Parameter 2: Whether keys should exist +# true = verify keys are present with correct stored data +# false = verify keys are absent +# - Parameter 3: Hash of backend configuration ('simpkv::options' Hash) +# - Parameter 4: Host object on which the validator will execute commands; +# Is the host under test, which may not be the host on which +# the keystore resides. +# +shared_examples 'simpkv::delete tests' do |host| + include_examples('pre-populate keystores', host) + + context "simpkv::delete operation on #{host}" do + # Hash with two keys: + # - :remove = Key info Hash of keys to remove + # - :retain = Key info Hash of keys to retain + # + # Hashes are subsets of initial_key_info + # + let(:test_key_infos) { + key_infos = split_key_info(initial_key_info, 2) + + if key_infos[0].empty? or key_infos[1].empty? + raise("Unable to split the initial_key_info into two non-empty Hashes. Data provided is too sparse") + end + + { + :remove => key_infos[0], + :retain => key_infos[1] + } + } + + let(:remove_manifest) { 'include simpkv_test::remove_keys' } + let(:remove_hieradata) { + backend_hiera.merge( { + 'simpkv_test::remove_keys::keyname_info' => to_keyname_info(test_key_infos[:remove]) + } ) + } + + let(:verify_manifest) { 'include simpkv_test::retrieve_and_verify_keys' } + let(:verify_hieradata) { + backend_hiera.merge( { + 'simpkv_test::retrieve_and_verify_keys::valid_key_info' => test_key_infos[:retain], + 'simpkv_test::retrieve_and_verify_keys::invalid_key_info' => test_key_infos[:remove] + } ) + } + + it 'should call simpkv::delete with valid keys without errors' do + set_hiera_and_apply_on(host, remove_hieradata, remove_manifest, + { :catch_failures => true }) + end + + it 'should retain only untouched keys in backends' do + expect( validator.call(test_key_infos[:retain], true, backend_hiera, host) ).to be true + expect( validator.call(test_key_infos[:remove], false, backend_hiera, host) ).to be true + end + + it 'should only be able to retrieve untouched keys via simpkv::get' do + set_hiera_and_apply_on(host, verify_hieradata, verify_manifest, + { :catch_failures => true }) + end + + it 'should call simpkv::delete with invalid keys without errors' do + set_hiera_and_apply_on(host, remove_hieradata, remove_manifest, + { :catch_failures => true }) + end + end +end + diff --git a/spec/acceptance/shared_examples/simpkv_deletetree.rb b/spec/acceptance/shared_examples/simpkv_deletetree.rb new file mode 100644 index 0000000..602cc43 --- /dev/null +++ b/spec/acceptance/shared_examples/simpkv_deletetree.rb @@ -0,0 +1,145 @@ +# Execute and verify simpkv::deletetree using the configured backend plugins. +# +# ASSUMED CONTEXT: +# The following are assumed to be available within this shared_examples context: +# * `clear_data_cmd`: Command string to be executed on the host to clear out +# all stored key data in the configured backends: +# - Must work from the host being tested, even when the keystore is not +# co-resident. +# +# * `backend_hiera`: 'simpkv::options' hash specifying backend configuration +# - One of the backends must be named 'default' +# +# * `initial_key_info`: Hash specifying key data to be initially stored in +# the backends: +# - Format corresponds to the Simpkv_test::KeyInfo type alias +# - **Must** have app_ids that correspond to the backends named in +# backend_hiera +# +# * `validator`: Method object that can be called to independently validate +# backend state: +# - Method will be called to validate whether keys are present or absent in +# their corresponding backends, and when they are expected to be present, +# the stored key data is correct. +# - Method must return a Boolean indicating validation success +# - Method should log details of validation failures for debug +# - Method should attempt all validations before reporting failure +# - Method must have the following parameter list +# - Parameter 1: Hash of key information whose format corresponds to the +# Simpkv_test::KeyInfo type alias +# - Parameter 2: Whether keys should exist +# true = verify keys are present with correct stored data +# false = verify keys are absent +# - Parameter 3: Hash of backend configuration ('simpkv::options' Hash) +# - Parameter 4: Host object on which the validator will execute commands; +# Is the host under test, which may not be the host on which +# the keystore resides. +# +shared_examples 'simpkv::deletetree tests' do |host| + include_examples('pre-populate keystores', host) + + context "simpkv::deletetree operation on #{host}" do + let(:initial_foldername_info) { to_foldername_info(initial_key_info) } + let(:subfolders_to_delete) { + subfolders = select_subfolders_subset(initial_foldername_info) + if subfolders.empty? + raise('No subfolders from initial_key_info selected for deletion: data too sparse') + end + + subfolders + } + + let(:test_key_infos_after_subfolder_delete) { + key_infos = split_key_info_per_subfolder_deletes(initial_key_info, subfolders_to_delete) + { :retain => key_infos[0], :remove => key_infos[1] } + } + + # Any root folder that originally had key data. + let(:root_folders) { + foldername_info = root_foldername_info(initial_key_info) + if foldername_info.empty? + raise('All root folders found in initial_key_info are empty: No keys!') + end + + foldername_info + } + + let(:remove_manifest) { 'include simpkv_test::remove_folders' } + let(:remove_subfolders_hieradata) { + backend_hiera.merge( { + 'simpkv_test::remove_folders::foldername_info' => subfolders_to_delete + } ) + } + + let(:remove_root_folders_hieradata) { + backend_hiera.merge( { + 'simpkv_test::remove_folders::foldername_info' => root_folders + } ) + } + + let(:verify_manifest) { 'include simpkv_test::retrieve_and_verify_folders' } + let(:verify_hieradata_after_subfolders_delete) { + backend_hiera.merge( { + 'simpkv_test::retrieve_and_verify_folders::valid_folder_info' => to_folder_info(test_key_infos_after_subfolder_delete[:retain]), + 'simpkv_test::retrieve_and_verify_folders::invalid_folder_info' => to_folder_info(test_key_infos_after_subfolder_delete[:remove], true) + } ) + } + + let(:verify_empty_backend_folders_hieradata) { + # Expected results after root directories have been removed: + # - The root folder for the Puppet environment in each backend will no + # longer exist, and so a listing of if will fail. + # - The 'globals' root folder in each backend will exist ('globals' + # folder is part of the infrastructure maintained by each plugin and + # not deletable via the simpkv functions API), but it will be empty. + # + env_folder_info = {} + global_folder_info = {} + empty_folders = { '/' => { 'keys' => {}, 'folders' => [] } } + initial_key_info.keys.each do |app_id| + env_folder_info[app_id] = { 'env' => Marshal.load(Marshal.dump(empty_folders)) } + global_folder_info[app_id] = { 'global' => Marshal.load(Marshal.dump(empty_folders)) } + end + + backend_hiera.merge( { + 'simpkv_test::retrieve_and_verify_folders::valid_folder_info' => global_folder_info, + 'simpkv_test::retrieve_and_verify_folders::invalid_folder_info' => env_folder_info + } ) + } + + it 'should call simpkv::deletetree with valid sub-folders without errors' do + set_hiera_and_apply_on(host, remove_subfolders_hieradata, remove_manifest, + { :catch_failures => true }) + end + + it 'should retain only untouched keys/folders in backends' do + set_hiera_and_apply_on(host, verify_hieradata_after_subfolders_delete, + verify_manifest, { :catch_failures => true }) + end + + it 'should call simpkv::deletetree with root folders without errors' do + set_hiera_and_apply_on(host, remove_root_folders_hieradata, + remove_manifest, { :catch_failures => true }) + end + + it 'should retain no key data in the backends' do + # This makes sure there is no key data, but does not verify that the + # directory tree is absent. That verification is done by the next test + # example. + expect( validator.call(initial_key_info, false, backend_hiera, host) ).to be true + end + + it 'should retrieve non-existent or empty root dir list results from the backends' do + # non-existent: Puppet environment root dirs + # empty: global root dirs + set_hiera_and_apply_on(host, verify_empty_backend_folders_hieradata, + verify_manifest, { :catch_failures => true }) + end + + it 'should call simpkv::deletetree with invalid folders without errors' do + set_hiera_and_apply_on(host, remove_subfolders_hieradata, + remove_manifest, { :catch_failures => true }) + end + end +end + diff --git a/spec/acceptance/shared_examples/simpkv_exists.rb b/spec/acceptance/shared_examples/simpkv_exists.rb new file mode 100644 index 0000000..9c71b38 --- /dev/null +++ b/spec/acceptance/shared_examples/simpkv_exists.rb @@ -0,0 +1,84 @@ +# Execute and verify simpkv::exists using the configured backend plugins. +# +# ASSUMED CONTEXT: +# The following are assumed to be available within this shared_examples context: +# * `clear_data_cmd`: Command string to be executed on the host to clear out +# all stored key data in the configured backends: +# - Must work from the host being tested, even when the keystore is not +# co-resident. +# +# * `backend_hiera`: 'simpkv::options' hash specifying backend configuration +# +# * `initial_key_info`: Hash specifying key data to be initially stored in +# the backends: +# - Format corresponds to the Simpkv_test::KeyInfo type alias +# - **Must** have app_ids that correspond to the backends named in +# backend_hiera +# +shared_examples 'simpkv::exists tests' do |host| + include_examples('pre-populate keystores', host) + + context "simpkv::exists operation for keys on #{host}" do + let(:initial_keyname_info) { to_keyname_info(initial_key_info) } + let(:hieradata_with_valid_keys) { + backend_hiera.merge( { + 'simpkv_test::verify_keys_exist::valid_keyname_info' => initial_keyname_info, + 'simpkv_test::verify_keys_exist::invalid_keyname_info' => {} + } ) + } + + # copy of initial_key_info for which all key names have been modified + let(:new_key_info) { rename_keys_in_key_info(initial_key_info) } + let(:new_keyname_info) { to_keyname_info(new_key_info) } + + let(:hieradata_with_invalid_keys) { + backend_hiera.merge( { + 'simpkv_test::verify_keys_exist::valid_keyname_info' => {}, + 'simpkv_test::verify_keys_exist::invalid_keyname_info' => new_keyname_info + } ) + } + + let(:manifest) { 'include simpkv_test::verify_keys_exist' } + + it 'should call simpkv::exists for valid keys and return true' do + set_hiera_and_apply_on(host, hieradata_with_valid_keys, manifest, + { :catch_failures => true }) + end + + it 'should call simpkv::exists for invalid keys and return false' do + set_hiera_and_apply_on(host, hieradata_with_invalid_keys, manifest, + { :catch_failures => true }) + end + end + + context "simpkv::exists operation for folders on #{host}" do + let(:initial_foldername_info) { to_foldername_info(initial_key_info) } + let(:hieradata_with_valid_folders) { + backend_hiera.merge( { + 'simpkv_test::verify_folders_exist::valid_foldername_info' => initial_foldername_info, + 'simpkv_test::verify_folders_exist::invalid_foldername_info' => {} + } ) + } + + # copy of inital_foldername_info for which all folder names have been modified + let(:new_foldername_info) { rename_folders_in_name_info(initial_foldername_info) } + let(:hieradata_with_invalid_folders) { + backend_hiera.merge( { + 'simpkv_test::verify_folders_exist::valid_foldername_info' => {}, + 'simpkv_test::verify_folders_exist::invalid_foldername_info' => new_foldername_info + } ) + } + + let(:manifest) { 'include simpkv_test::verify_folders_exist' } + + it 'should call simpkv::exists for valid folders and return true' do + set_hiera_and_apply_on(host, hieradata_with_valid_folders, manifest, + { :catch_failures => true }) + end + + it 'should call simpkv::exists for invalid folders and return false' do + set_hiera_and_apply_on(host, hieradata_with_invalid_folders, manifest, + { :catch_failures => true }) + end + end +end diff --git a/spec/acceptance/shared_examples/simpkv_get.rb b/spec/acceptance/shared_examples/simpkv_get.rb new file mode 100644 index 0000000..42eebfb --- /dev/null +++ b/spec/acceptance/shared_examples/simpkv_get.rb @@ -0,0 +1,52 @@ +# Execute and verify simpkv::get using the configured backend plugins. +# +# ASSUMED CONTEXT: +# The following are assumed to be available within this shared_examples context: +# * `clear_data_cmd`: Command string to be executed on the host to clear out +# all stored key data in the configured backends: +# - Must work from the host being tested, even when the keystore is not +# co-resident. +# +# * `backend_hiera`: 'simpkv::options' hash specifying backend configuration +# - One of the backends must be named 'default' +# +# * `initial_key_info`: Hash specifying key data to be initially stored in +# the backends: +# - Format corresponds to the Simpkv_test::KeyInfo type alias +# - **Must** have app_ids that correspond to the backends named in +# backend_hiera +# +shared_examples 'simpkv::get tests' do |host| + include_examples('pre-populate keystores', host) + + context "simpkv::get operation on #{host}" do + let(:hieradata_with_valid_keys) { + backend_hiera.merge( { + 'simpkv_test::retrieve_and_verify_keys::valid_key_info' => initial_key_info, + 'simpkv_test::retrieve_and_verify_keys::invalid_key_info' => {} + } ) + } + + # copy of initial_key_info for which all key names have been modified + let(:new_key_info) { rename_keys_in_key_info(initial_key_info) } + + let(:hieradata_with_invalid_keys) { + backend_hiera.merge( { + 'simpkv_test::retrieve_and_verify_keys::valid_key_info' => {}, + 'simpkv_test::retrieve_and_verify_keys::invalid_key_info' => new_key_info + } ) + } + + let(:manifest) { 'include simpkv_test::retrieve_and_verify_keys' } + + it 'should call simpkv::get for valid keys without errors and verify retrieved info' do + set_hieradata_on(host, hieradata_with_valid_keys) + apply_manifest_on(host, manifest, :catch_failures => true) + end + + it 'should call simpkv::get with softfail=true for invalid keys without errors and verify nothing is retrieved' do + set_hieradata_on(host, hieradata_with_invalid_keys) + apply_manifest_on(host, manifest, :catch_failures => true) + end + end +end diff --git a/spec/acceptance/shared_examples/simpkv_list.rb b/spec/acceptance/shared_examples/simpkv_list.rb new file mode 100644 index 0000000..2e1318a --- /dev/null +++ b/spec/acceptance/shared_examples/simpkv_list.rb @@ -0,0 +1,52 @@ +# Execute and verify simpkv::list using the configured backend plugins. +# +# ASSUMED CONTEXT: +# The following are assumed to be available within this shared_examples context: +# * `clear_data_cmd`: Command string to be executed on the host to clear out +# all stored key data in the configured backends: +# - Must work from the host being tested, even when the keystore is not +# co-resident. +# +# * `backend_hiera`: 'simpkv::options' hash specifying backend configuration +# - One of the backends must be named 'default' +# +# * `initial_key_info`: Hash specifying key data to be initially stored in +# the backends: +# - Format corresponds to the Simpkv_test::KeyInfo type alias +# - **Must** have app_ids that correspond to the backends named in +# backend_hiera +# +shared_examples 'simpkv::list tests' do |host| + include_examples('pre-populate keystores', host) + + context "simpkv::list operation on #{host}" do + let(:initial_folder_info) { to_folder_info(initial_key_info) } + let(:hieradata_with_valid_folders) { + backend_hiera.merge( { + 'simpkv_test::retrieve_and_verify_folders::valid_folder_info' => initial_folder_info, + 'simpkv_test::retrieve_and_verify_folders::invalid_folder_info' => {} + } ) + } + + # copy of initial_folder_info for which all folder names have been modified + let(:new_folder_info) { rename_folders_in_folder_info(initial_folder_info) } + let(:hieradata_with_invalid_folders) { + backend_hiera.merge( { + 'simpkv_test::retrieve_and_verify_folders::valid_folder_info' => {}, + 'simpkv_test::retrieve_and_verify_folders::invalid_folder_info' => new_folder_info + } ) + } + + let(:manifest) { 'include simpkv_test::retrieve_and_verify_folders' } + + it 'should call simpkv::list for valid folders without errors and verify retrieved info' do + set_hiera_and_apply_on(host, hieradata_with_valid_folders, manifest, + { :catch_failures => true }) + end + + it 'should call simpkv::list with softfail=true for invalid folders without errors and verify nothing is retrieved' do + set_hiera_and_apply_on(host, hieradata_with_invalid_folders, manifest, + { :catch_failures => true }) + end + end +end diff --git a/spec/acceptance/shared_examples/simpkv_plugin.rb b/spec/acceptance/shared_examples/simpkv_plugin.rb new file mode 100644 index 0000000..b0fb56a --- /dev/null +++ b/spec/acceptance/shared_examples/simpkv_plugin.rb @@ -0,0 +1,128 @@ +# Execute and verify simpkv functions using the configured backend plugin(s). +# +# TEST OVERVIEW +# This test uses the following: +# - A set of backend instances to verify app_id-based backend selection. +# - The simpkv_test module to exercise the simpkv::* functions and to verify +# their operation, independent of the backend type used. +# - A backend-specific validator function provided by the plugin developer to +# independently verify keys are present/absent in the appropriate backend. +# - Initial key data and methods to transform that data into hieradata for all +# the simpkv_test manifests that affect key storage, removal, retrieval, and +# validation. +# +# TEST STRUCTURE +# This test includes specific shared_examples for each simpkv function. These +# examples are written to be self contained. In other words, each included +# share_example resets the keystores to a known state before executing any +# tests. This makes the tests much easier to understand. +# +# VERIFICATION DETAILS: +# This test uses 2 types of verification: +# - API-self-consistency verification via the simpkv_test module. +# - The simpkv_test module exclusively uses simpkv functions for +# storage/retrieval operations. +# - The simpkv_test module verifies the content of the retrieve operations: +# - true/false returned values for existence checks of present/absent +# keys and folders. +# - Key value and metadata verification for existing keys +# - Folder list contents for existing folders +# - Null results for keys/folders that are expected to be absent, when +# the 'softfail' simpkv option is used. +# - Backend-specific verification via a plugin-developer-provided validator +# function. +# - Validates data is stored appropriately when it is expected to be present. +# - Validates data is not stored when it is expected to be absent. +# - The only mechanism that ensures the data is stored where it is +# supposed to be stored! +# +# ASSUMED CONTEXT: +# The following are assumed to be available within this shared_examples context: +# * `clear_data_cmd`: Command string to be executed on the host to clear out +# all stored key data in the configured backends: +# - Must work from the host being tested, even when the keystore is not +# co-resident. +# +# * `backend_hiera`: 'simpkv::options' hash specifying backend configuration +# - One of the backends must be named 'default' +# +# * `initial_key_info`: Hash specifying key data to be initially stored in +# the backends: +# - Format corresponds to the Simpkv_test::KeyInfo type alias +# - **Must** have app_ids that correspond to the backends named in +# backend_hiera +# +# * `validator`: Method object that can be called to independently validate +# backend state: +# - Method will be called to validate whether keys are present or absent in +# their corresponding backends, and when they are expected to be present, +# the stored key data is correct. +# - Method must return a Boolean indicating validation success +# - Method should log details of validation failures for debug +# - Method should attempt all validations before reporting failure +# - Method must have the following parameter list +# - Parameter 1: Hash of key information whose format corresponds to the +# Simpkv_test::KeyInfo type alias +# - Parameter 2: Whether keys should exist +# true = verify keys are present with correct stored data +# false = verify keys are absent +# - Parameter 3: Hash of backend configuration ('simpkv::options' Hash) +# - Parameter 4: Host object on which the validator will execute commands; +# Is the host under test, which may not be the host on which +# the keystore resides. +# +# NOTE FOR MAINTAINERS +# Before updating this test, please take time to understand what the simpkv_test +# module does and how the Acceptance::Helpers::TestData methods are used to +# drive that module to exercise and validate simpkv functions. To aid +# understanding and debug +# * Each time a simpkv_test manifest is used, the hieradata and manifest are +# logged to the console. +# * The simpkv_test manifests log info-level, detailed messages to tell you +# what is happening during a catalog complile. This includes when a simpkv +# function is called, the parameters used in the function call, when results +# from a simpkv retrieval operation are being compared with expected values, +# and details about any comparison failures. +# +# @param host Host object on which the test manifests will be applied and +# independent verification commands executed +# +shared_examples 'a simpkv plugin test' do |host| + + # This is a very high level, test configuration sanity check, but will not + # detect all misconfiguration errors (especially ones that result in + # non-unique keys, e.g., when multiple app_ids unexpectedly end up in the + # same backend). + # + # Included examples may have more specific validation, especially WRT to + # whether initial_key_info has appropriate data for derived data used to + # stimulate the key/folder removal tests. + it 'should have basic test configuration' do + expect( backend_hiera.key?('simpkv::options')).to be true + expect( backend_hiera['simpkv::options'].key?('backends')).to be true + expect( backend_hiera['simpkv::options']['backends'].key?('default')).to be true + + expect(initial_key_info).to_not be_empty + initial_key_info.keys.each do |app_id| + appid = app_id.empty? ? 'default' : app_id + expect( backend_hiera['simpkv::options']['backends'].keys.include?(appid) ).to be true + end + end + + # All other simpkv function tests depend upon the keystores being populated + # by simpkv::put via simpkv_test manifests. So, make sure the simpkv::put + # operation is verified **first**. + include_examples('simpkv::put tests', host) + + include_examples('simpkv::exists tests', host) + include_examples('simpkv::get tests', host) + include_examples('simpkv::list tests', host) + + # The simpkv::delete and simpkv::deletetree tests will use simpkv::get and + # simpkv::list, respectively, as part of their removal verfication. So, make + # sure these tests come **after** the simpkv:get and simpkv::list operations + # are verified by their tests. + include_examples('simpkv::delete tests', host) + include_examples('simpkv::deletetree tests', host) +end + diff --git a/spec/acceptance/shared_examples/simpkv_put.rb b/spec/acceptance/shared_examples/simpkv_put.rb new file mode 100644 index 0000000..3086b0a --- /dev/null +++ b/spec/acceptance/shared_examples/simpkv_put.rb @@ -0,0 +1,86 @@ +# Execute and verify simpkv::put using the configured backend plugins. +# +# ASSUMED CONTEXT: +# The following are assumed to be available within this shared_examples context: +# * `clear_data_cmd`: Command string to be executed on the host to clear out +# all stored key data in the configured backends. +# - Must work from the host being tested, even when the keystore is not +# co-resident. +# +# * `backend_hiera`: 'simpkv::options' hash specifying backend configuration +# +# * `initial_key_info`: Hash specifying key data to be initially stored in +# the backends: +# - Format corresponds to the Simpkv_test::KeyInfo type alias +# - **Must** have app_ids that correspond to the backends named in +# backend_hiera +# +# * `validator`: Method object that can be called to independently validate +# backend state: +# - Method will be called to validate whether keys are present or absent in +# their corresponding backends, and when they are expected to be present, +# the stored key data is correct. +# - Method must return a Boolean indicating validation success +# - Method should log details of validation failures for debug +# - Method must have the following parameter list +# - Parameter 1: Hash of key information whose format corresponds to the +# Simpkv_test::KeyInfo type alias +# - Parameter 2: Whether keys should exist +# true = verify keys are present with correct stored data +# false = verify keys are absent +# - Parameter 3: Hash of backend configuration ('simpkv::options' Hash) +# - Parameter 4: Host object on which the validator will execute commands; +# Is the host under test, which may not be the host on which +# the keystore resides. +# +# @param host Host object on which the test manifests will be applied and +# independent verification commands executed +# +shared_examples 'simpkv::put tests' do |host| + context "ensure empty keystore(s) on #{host}" do + it 'should remove all backend instance data' do + on(host, clear_data_cmd, :accept_all_exit_codes => true) + end + end + + context "simpkv::put operation on #{host}" do + let(:hieradata) { + backend_hiera.merge( { + 'simpkv_test::store_keys::key_info' => initial_key_info + } ) + } + + let(:updated_key_info) { modify_key_data(initial_key_info) } + let(:updated_hieradata) { + backend_hiera.merge( { + 'simpkv_test::store_keys::key_info' => updated_key_info + } ) + } + + let(:manifest) { 'include simpkv_test::store_keys' } + + it 'should call simpkv::put without errors' do + set_hiera_and_apply_on(host, hieradata, manifest, { :catch_failures => true }) + end + + it 'should store the keys in the configured backends' do + expect( validator.call(initial_key_info, true, backend_hiera, host) ).to be true + end + + it 'should call simpkv::put without errors when keys already exist with same value' do + apply_manifest_on(host, manifest, :catch_failures => true) + end + + it 'should retain the keys in the configured backends' do + expect( validator.call(initial_key_info, true, backend_hiera, host) ).to be true + end + + it 'should call simpkv::put without errors when keys already exist with different values' do + set_hiera_and_apply_on(host, updated_hieradata, manifest, { :catch_failures => true }) + end + + it 'should update the keys in the configured backends' do + expect( validator.call(updated_key_info, true, backend_hiera, host) ).to be true + end + end +end diff --git a/spec/acceptance/suites/default/00_file_plugin_setup_spec.rb b/spec/acceptance/suites/default/00_file_plugin_setup_spec.rb new file mode 100644 index 0000000..d9debf7 --- /dev/null +++ b/spec/acceptance/suites/default/00_file_plugin_setup_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper_acceptance' + +test_name 'simpkv file plugin setup' + +describe 'simpkv file plugin setup' do + # Ensure /var/simp/simpkv already exists + let(:manifest) { <<~EOM + file {'/var/simp': ensure => directory } + file {'/var/simp/simpkv': ensure => directory } + EOM + } + + hosts.each do |host| + it "should create /var/simp/simpkv on #{host}" do + apply_manifest_on(host, manifest, :catch_failures => true) + end + end +end diff --git a/spec/acceptance/suites/default/10_configured_file_plugin_spec.rb b/spec/acceptance/suites/default/10_configured_file_plugin_spec.rb new file mode 100644 index 0000000..5b82118 --- /dev/null +++ b/spec/acceptance/suites/default/10_configured_file_plugin_spec.rb @@ -0,0 +1,69 @@ +require_relative 'validate_file_entries' +require 'spec_helper_acceptance' + +test_name 'simpkv configured file plugin' + +describe 'simpkv configured file plugin' do + # Method object to validate key file entries in an file instance. + # - Conforms to the API specified in 'a simpkv plugin test' shared_examples + let(:validator) { method(:validate_file_entries) } + + # Command to run on the test host to clear out all stored key data. + # - Since the file plugin has to be on the same host as the file keystore, + # a local filesystem command is appropriate. + let(:clear_data_cmd) { 'rm -rf /var/simp/simpkv/file' } + + + # The ids below are the backend/app_id names used in the test: + # - One must be 'default' or simpkv::options validation will fail. + # - 'a simpkv plugin test' shared_examples assumes there is a one-to-one + # mapping of the app_ids in the input key data to the backend names. + # Although simpkv supports fuzzy logic for that mapping, we set the + # backend names/app_ids to the same values, here, for simplicity. The + # fuzzy mapping logic is tested in the unit test. + # - The input-data-generator currently supports exactly 3 app_ids. + # - 'default' app_id is mapped to '' in the generated input key data, which, in + # turn causes simpkv functions to be called in the test manifests without + # an app_id set. In other words, 'default' maps to the expected, normal + # usage of simpkv functions. + # + let(:id1) { 'default' } + let(:id2) { 'custom' } + let(:id3) { 'custom_snowflake' } + + # simpkv::options hieradata for 3 distinct backends, one of which must + # be 'default' + let(:backend_hiera) { + backend_configs = { + id1 => { + 'type' => 'file', + 'root_path' => "/var/simp/simpkv/file/#{id1}" + }, + id2 => { + 'type' => 'file', + 'root_path' => "/var/simp/simpkv/file/#{id2}" + }, + id3 => { + 'type' => 'file', + 'root_path' => "/var/simp/simpkv/file/#{id3}" + } + } + + generate_backend_hiera(backend_configs) + } + + # Hash of initial key information for the 3 test backends/app_ids. + # + # 'a simpkv plugin test' uses this data to test key storage operations + # and then transform the data into subsets that it uses to test key/folder + # existence, folder lists, and key and folder delete operations. + let(:initial_key_info) { + generate_initial_key_info(id1, id2, id3) + } + + hosts.each do |host| + context "configured simpkv file plugin on #{host}" do + it_behaves_like 'a simpkv plugin test', host + end + end +end diff --git a/spec/acceptance/suites/default/20_auto_default_file_plugin_spec.rb b/spec/acceptance/suites/default/20_auto_default_file_plugin_spec.rb new file mode 100644 index 0000000..e6f0692 --- /dev/null +++ b/spec/acceptance/suites/default/20_auto_default_file_plugin_spec.rb @@ -0,0 +1,47 @@ +require 'spec_helper_acceptance' + +test_name 'simpkv auto-default file plugin' + +# This test will not configure any backend in hieradata, store a few +# keys and verify they go to the auto-default file backend. +# +# Because /var/simp exists, the auto-default file backend will +# store its data within /var/simp/simpkv/file/auto_file +# +describe 'simpkv auto-default file plugin' do + let(:clean_data_cmd) { 'rm -rf /var/simp/simpkv/file' } + + # No backend configuration in hieradata + let(:hieradata) {{ }} + + # Store a few keys so we can spot check that the keys are being stored + # in the auto-default backend + let(:manifest) { + <<~EOS + simpkv::put('key1', 'environment key value1') + simpkv::put('global1', 'global key value 1', {'version' => 10}, {'global' => true}) + EOS + } + + hosts.each do |host| + context "without simpkv configuration on #{host}" do + it 'should start with no backend data' do + on(host, clean_data_cmd) + end + + it 'should call simpkv::put with no errors' do + set_hiera_and_apply_on(host, hieradata, manifest, + {:catch_failures => true} ) + end + + it 'should store keys in auto-default backend' do + [ + '/var/simp/simpkv/file/auto_default/environments/production/key1', + '/var/simp/simpkv/file/auto_default/globals/global1' + ].each do |file| + expect( file_exists_on(host, file) ).to be true + end + end + end + end +end diff --git a/spec/acceptance/suites/default/file_plugin_spec.rb b/spec/acceptance/suites/default/file_plugin_spec.rb deleted file mode 100644 index 444a3cc..0000000 --- a/spec/acceptance/suites/default/file_plugin_spec.rb +++ /dev/null @@ -1,301 +0,0 @@ -require 'spec_helper_acceptance' - -test_name 'simpkv file plugin' - -describe 'simpkv file plugin' do - - let(:hieradata) {{ - - 'simpkv::backend::file_class' => { - 'type' => 'file', - 'id' => 'class', - 'root_path' => '/var/simp/simpkv/file/class' - }, - - 'simpkv::backend::file_define_instance' => { - 'type' => 'file', - 'id' => 'define_instance', - 'root_path' => '/var/simp/simpkv/file/define_instance' - }, - - 'simpkv::backend::file_define_type' => { - 'type' => 'file', - 'id' => 'define_type', - 'root_path' => '/var/simp/simpkv/file/define_type' - }, - - 'simpkv::backend::file_default' => { - 'type' => 'file', - 'id' => 'default', - 'root_path' => '/var/simp/simpkv/file/default' - }, - - 'simpkv::options' => { - 'environment' => '%{server_facts.environment}', - 'softfail' => false, - 'backends' => { - 'simpkv_test_class' => "%{alias('simpkv::backend::file_class')}", - 'Simpkv_test::Defines::Put[define2]' => "%{alias('simpkv::backend::file_define_instance')}", - 'Simpkv_test::Defines::Put' => "%{alias('simpkv::backend::file_define_type')}", - 'default' => "%{alias('simpkv::backend::file_default')}", - } - - } - - }} - - hosts.each do |host| - context 'with simpkv configuration via simpkv::options' do - - context 'simpkv put operation' do - let(:manifest) { - <<-EOS - file {'/var/simp/simpkv': - ensure => directory - } - - # Calls simpkv::put directly and via a Puppet-language function - # * Stores values of different types. Binary content is handled - # via a separate test. - # * One of the calls to the Puppet-language function will go to the - # default backend - class { 'simpkv_test::put': } - - # These two defines call simpkv::put directly and via the Puppet-language - # function - # * The 'define1' put operations should use the 'file/define_instance' - # backend instance. - # * The 'define2' put operations should use the 'file/define_type' - simpkv_test::defines::put { 'define1': } - simpkv_test::defines::put { 'define2': } - EOS - } - - it 'should work with no errors' do - set_hieradata_on(host, hieradata) - apply_manifest_on(host, manifest, :catch_failures => true) - end - - [ - '/var/simp/simpkv/file/class/globals/from_class/boolean', - '/var/simp/simpkv/file/class/globals/from_class/string', - '/var/simp/simpkv/file/class/globals/from_class/integer', - '/var/simp/simpkv/file/class/globals/from_class/float', - '/var/simp/simpkv/file/class/globals/from_class/array_strings', - '/var/simp/simpkv/file/class/globals/from_class/array_integers', - '/var/simp/simpkv/file/class/globals/from_class/hash', - - '/var/simp/simpkv/file/class/environments/production/from_class/boolean', - '/var/simp/simpkv/file/class/environments/production/from_class/string', - '/var/simp/simpkv/file/class/environments/production/from_class/integer', - '/var/simp/simpkv/file/class/environments/production/from_class/float', - '/var/simp/simpkv/file/class/environments/production/from_class/array_strings', - '/var/simp/simpkv/file/class/environments/production/from_class/array_integers', - '/var/simp/simpkv/file/class/environments/production/from_class/hash', - - '/var/simp/simpkv/file/class/environments/production/from_class/boolean_with_meta', - '/var/simp/simpkv/file/class/environments/production/from_class/string_with_meta', - '/var/simp/simpkv/file/class/environments/production/from_class/integer_with_meta', - '/var/simp/simpkv/file/class/environments/production/from_class/float_with_meta', - '/var/simp/simpkv/file/class/environments/production/from_class/array_strings_with_meta', - '/var/simp/simpkv/file/class/environments/production/from_class/array_integers_with_meta', - '/var/simp/simpkv/file/class/environments/production/from_class/hash_with_meta', - - '/var/simp/simpkv/file/class/environments/production/from_class/boolean_from_pfunction', - '/var/simp/simpkv/file/default/environments/production/from_class/boolean_from_pfunction_no_app_id', - - '/var/simp/simpkv/file/define_instance/environments/production/from_define/define2/string', - '/var/simp/simpkv/file/define_instance/environments/production/from_define/define2/string_from_pfunction', - '/var/simp/simpkv/file/define_type/environments/production/from_define/define1/string', - '/var/simp/simpkv/file/define_type/environments/production/from_define/define1/string_from_pfunction' - ].each do |file| - # validation of content will be done in 'get' test - it "should create #{file}" do - expect( file_exists_on(host, file) ).to be true - end - end - end - - context 'simpkv exists operation' do - let(:manifest) { - <<-EOS - # class uses simpkv::exists to verify the existence of keys in - # the 'file/class' backend; fails compilation if any simpkv::exists - # result doesn't match expected - class { 'simpkv_test::exists': } - EOS - } - - it 'manifest should work with no errors' do - apply_manifest_on(host, manifest, :catch_failures => true) - end - end - - context 'simpkv get operation' do - let(:manifest) { - <<-EOS - # class uses simpkv::get to retrieve values with/without metadata for - # keys in the 'file/class' backend; fails compilation if any - # retrieved info does match expected - class { 'simpkv_test::get': } - EOS - } - - it 'manifest should work with no errors' do - apply_manifest_on(host, manifest, :catch_failures => true) - end - - end - - context 'simpkv list operation' do - let(:manifest) { - <<-EOS - # class uses simpkv::list to retrieve list of keys/values/metadata tuples - # for keys in the 'file/class' backend; fails compilation if the - # retrieved info does match expected - class { 'simpkv_test::list': } - EOS - } - - it 'manifest should work with no errors' do - apply_manifest_on(host, manifest, :catch_failures => true) - end - - end - - context 'simpkv delete operation' do - let(:manifest) { - <<-EOS - # class uses simpkv::delete to remove a subset of keys in the 'file/class' - # backend and the simpkv::exists to verify they are gone but the other keys - # are still present; fails compilation if any removed keys still exist or - # any preserved keys have been removed - class { 'simpkv_test::delete': } - EOS - } - - it 'manifest should work with no errors' do - apply_manifest_on(host, manifest, :catch_failures => true) - end - - [ - '/var/simp/simpkv/file/class/environments/production/from_class/boolean', - '/var/simp/simpkv/file/class/environments/production/from_class/string', - '/var/simp/simpkv/file/class/environments/production/from_class/integer', - '/var/simp/simpkv/file/class/environments/production/from_class/float', - '/var/simp/simpkv/file/class/environments/production/from_class/array_strings', - '/var/simp/simpkv/file/class/environments/production/from_class/array_integers', - '/var/simp/simpkv/file/class/environments/production/from_class/hash', - ].each do |file| - it "should remove #{file}" do - expect( file_exists_on(host, file) ).to be false - end - end - - - end - - context 'simpkv deletetree operation' do - let(:manifest) { - <<-EOS - # class uses simpkv::deletetree to remove the remaining Puppet env and - # global keys in the 'file/class' backend and the simpkv::exists to - # verify all keys are gone; fails compilation if any keys remain - class { 'simpkv_test::deletetree': } - EOS - } - - it 'manifest should work with no errors' do - apply_manifest_on(host, manifest, :catch_failures => true) - end - - it 'should remove specified folders' do - expect( file_exists_on(host, '/var/simp/simpkv/file/class/environments/production/from_class/') ).to be false - expect( file_exists_on(host, '/var/simp/simpkv/file/class/globals/from_class/') ).to be false - end - end - - context 'simpkv operations for binary data' do - context 'prep' do - it 'should create a binary file for test' do - on(host, 'mkdir /root/binary_data') - on(host, 'dd count=1 if=/dev/urandom of=/root/binary_data/input_data') - end - end - - context 'simpkv put operation for Binary type' do - let(:manifest) { - <<-EOS - # class uses simpkv::put to store binary data from binary_file() in - # a Binary type - class { 'simpkv_test::binary_put': } - EOS - } - - it 'manifest should work with no errors' do - apply_manifest_on(host, manifest, :catch_failures => true) - end - - [ - '/var/simp/simpkv/file/default/environments/production/from_class/binary', - '/var/simp/simpkv/file/default/environments/production/from_class/binary_with_meta' - ].each do |file| - it "should create #{file}" do - expect( file_exists_on(host, file) ).to be true - end - end - end - - context 'simpkv get operation for Binary type' do - let(:manifest) { - <<-EOS - # class uses simpkv::get to retrieve binary data for Binary type variables - # and to persist new files with binary content; fails compilation if any - # retrieved info does match expected - class { 'simpkv_test::binary_get': } - EOS - } - - it 'manifest should work with no errors' do - apply_manifest_on(host, manifest, :catch_failures => true) - end - - { - 'retrieved_data1' => 'retrieved from key without metadata', - 'retrieved_data2' => 'retrieved from key with metadata' - }.each do |output_file,summary| - it "should create binary file #{summary} that matches input binary file" do - on(host, "diff /root/binary_data/input_data /root/binary_data/#{output_file}") - end - end - end - end - end - - context 'without simpkv configuration' do - let(:manifest) { - <<-EOS - simpkv_test::defines::put { 'define1': } - simpkv_test::defines::put { 'define2': } - EOS - } - - it 'should work with no errors' do - # clear out hieradata that contained simpkv::options - set_hieradata_on(host, {}) - apply_manifest_on(host, manifest, :catch_failures => true) - end - - it 'should store keys in auto-default backend' do - [ - '/var/simp/simpkv/file/auto_default/environments/production/from_define/define2/string', - '/var/simp/simpkv/file/auto_default/environments/production/from_define/define2/string_from_pfunction', - '/var/simp/simpkv/file/auto_default/environments/production/from_define/define1/string', - '/var/simp/simpkv/file/auto_default/environments/production/from_define/define1/string_from_pfunction' - ].each do |file| - expect( file_exists_on(host, file) ).to be true - end - end - end - end -end diff --git a/spec/acceptance/suites/default/validate_file_entries.rb b/spec/acceptance/suites/default/validate_file_entries.rb new file mode 100644 index 0000000..c9e373b --- /dev/null +++ b/spec/acceptance/suites/default/validate_file_entries.rb @@ -0,0 +1,146 @@ +require 'acceptance/helpers/utils' +include Acceptance::Helpers::Utils + +# Validate file-plugin-managed keys on the local filesystem +# +# - Conforms to the API specified in 'a simpkv plugin test' shared_examples +# - Uses local filesystem commands, since the file plugin has to be on the +# same host as the file keystore +# +# @param key_info Hash of key information whose format corresponds to the +# Simpkv_test::KeyInfo type alias +# +# @param keys_should_exist Whether keys should exist +# - true = verify keys are present with correct stored data +# - false = verify keys are absent +# +# @param backend_hiera Hash of backend configuration ('simpkv::options' Hash) +# +# @param host Host object on which the validator will execute commands +# - Must be same host as file keystore +# +# @return Whether validation of keys succeeded +# +def validate_file_entries(key_info, keys_should_exist, backend_hiera, host) + if keys_should_exist + validate_file_entries_present(key_info, backend_hiera, host) + else + validate_file_entries_absent(key_info, backend_hiera, host) + end +end + +# Validate that file-plugin-managed keys exist on the local filesystem +# +# For each key specification, +# - Selects the backend whose name matches its 'app_id' or 'default', when +# no match is found +# - Checks for the existence of the appropriate file for the backend +# - Verifies the file content, when the file exists +# +# @param key_info Hash of key information whose format corresponds to the +# Simpkv_test::KeyInfo type alias +# +# @param backend_hiera Hash of backend configuration ('simpkv::options' Hash) +# +# @param host Host object on which the validator will execute commands +# - Must be same host as file file keystore +# +# @return Whether validation of keys succeeded +# +def validate_file_entries_present(key_info, backend_hiera, host) + errors = [] + key_info.each do |app_id, key_struct| + root_path = file_root_path_for_app_id(app_id, backend_hiera) + key_struct.each do |key_type, keys| + key_root_path = (key_type == 'global') ? "#{root_path}/globals" : "#{root_path}/environments/production" + keys.each do |key, key_data| + key_path = "#{key_root_path}/#{key}" + expected_key_string = key_data_string(key_data) + result = on(host, "cat #{key_path}", :accept_all_exit_codes => true) + if result.exit_code == 0 + if result.stdout.strip != expected_key_string + errors << [ + "Contents of #{key_path} did not match expected:", + " Expected: #{expected_key_string}", + " Actual: #{result.stdout}" + ].join("\n") + end + else + errors << "Validation of #{key_path} presence and data failed: #{result.stderr}" + end + end + end + end + + if errors.size == 0 + true + else + warn('Validation Failures:') + errors.each do |error| + warn(" #{error}") + end + + false + end +end + +# Validate that file-plugin-managed keys do not exist on the local filesystem +# +# For each key specification, +# - Selects the backend whose name matches its 'app_id' or 'default', when +# no match is found +# - Checks for the existence of the appropriate file for the backend +# +# @param key_info Hash of key information whose format corresponds to the +# Simpkv_test::KeyInfo type alias +# +# @param backend_hiera Hash of backend configuration ('simpkv::options' Hash) +# +# @param host Host object on which the validator will execute commands +# - Must be same host as file file keystore +# +# @return Whether validation of keys succeeded +# +def validate_file_entries_absent(key_info, backend_hiera, host) + errors = [] + key_info.each do |app_id, key_struct| + root_path = file_root_path_for_app_id(app_id, backend_hiera) + key_struct.each do |key_type, keys| + key_root_path = (key_type == 'global') ? "#{root_path}/globals" : "#{root_path}/environments/production" + keys.each do |key, key_data| + key_path = "#{key_root_path}/#{key}" + result = on(host, "ls -l #{key_path}", :accept_all_exit_codes => true) + if result.exit_code == 0 + errors << "Validation of #{key_path} absence failed: #{result.stdout}" + end + end + end + end + + if errors.size == 0 + true + else + warn('Validation Failures:') + errors.each do |error| + warn(" #{error}") + end + + false + end +end + +# @return Root path for the file backend that corresponds to the app_id +# +# @param app_id The app_id for a key or '', if none specified +# @param backend_hiera Hash of backend configuration ('simpkv::options' Hash) +# +def file_root_path_for_app_id(app_id, backend_hiera) + root_path = '' + if backend_hiera['simpkv::options']['backends'].keys.include?(app_id) + root_path = backend_hiera["simpkv::backend::#{app_id}"]['root_path'] + elsif backend_hiera['simpkv::options']['backends'].keys.include?('default') + root_path = backend_hiera['simpkv::backend::default']['root_path'] + end + + root_path +end diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index eac85b7..e1dcb84 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -1,11 +1,13 @@ require 'beaker-rspec' +require_relative 'acceptance/helpers' +require_relative 'acceptance/shared_examples' + require 'tmpdir' require 'yaml' require 'simp/beaker_helpers' include Simp::BeakerHelpers - -require 'data_helper' -include DataHelper +include Acceptance::Helpers::TestData +include Acceptance::Helpers::ManifestUtils unless ENV['BEAKER_provision'] == 'no' hosts.each do |host| @@ -26,6 +28,10 @@ # ensure that environment OS is ready on each host fix_errata_on hosts + # Detect cases in which no examples are executed (e.g., nodeset does not + # have hosts with required roles) + c.fail_if_no_examples = true + # Readable test descriptions c.formatter = :documentation diff --git a/spec/support/modules/simpkv_test/README.md b/spec/support/modules/simpkv_test/README.md new file mode 100644 index 0000000..42082ec --- /dev/null +++ b/spec/support/modules/simpkv_test/README.md @@ -0,0 +1,94 @@ +#### Table of Contents + + + +* [Module Description](#module-description) +* [Usage](#usage) +* [Limitations](#limitations) +* [Reference](#reference) + +## Module Description + +This is a module to test the simpkv function API. It uses Puppet manifests +to exercise all the simpkv functions and to verify the values stored in +each backend are correct. Specifically, it provides manifests that + +* store keys using `simpkv::put` +* remove keys using `simpkv::delete` +* remove folders using `simpkv::deletetree` +* verify the existence of key/folder names using `simpkv::exists` +* verify keys can be retrieved using `simpkv::get` and that the retrieved + key data is correct +* verify folder listings can be retrieved using `simpkv::list` and that the + retrieved list data is correct + +## Usage + +Usage of this module is fairly straight forward: + +* Include `simpkv_test::store_keys`, `simpkv_test::remove_keys`, or + `simpkv_test::remove_folders` to modify the state of one or more backends + + * These manifests use `simpkv::put`, `simpkv::delete`, and + `simpkv::deletetree`, respectively. + +* Include `simpkv_test::verify_keys_exist` and `simpkv_test::verify_folders_exist` + to verify that keys/folders are present or absent after the backend state + has been modified. + + * These manifests use `simpkv::exists`. + +* Include `simpkv_test::retrieve_and_verify_keys` and + `simpkv_test::retrieve_and_verify_folders` to retrieve and verify the + keys/folders information after the backend state has been modified. + + * These manifests use `simpkv::get` and `simpkv::list`, respectively. + +All key/folder information required by the manifests is driven by hieradata. + +For each key, this may include: + +* The key's name +* The key's value or a file containing its binary value +* The key's metadata +* The `app_id` to be used in the `simpkv::*` function calls for this key + or '' when no `app_id` is to be specified. +* Whether the keyis is a Puppet-environment key or a global key. + +For each folder, this may include: + +* The folder's name +* The key information for each key in the folder +* The list of subfolder names +* The `app_id` to be used in the `simpkv::*` function calls for this folder + or '' when no `app_id` is to be specified. +* Whether the folder is is a Puppet-environment folder or a global folder. + +IMPORTANT: +`simpkv::*` functions map `app_id` to the configured backend, or select the +'default' backend when no `app_id` is specified. To ensure uniqueness of test +keys, the data structures in this module are designed **assuming**, each +configured backend is uniquely mapped to the `app_id`. + +If your test setup violates this assumption, you use the same key name and +global status for different `app_ids`, and those `app_ids` map to the same +backend, the *last operation executed for that key name will determine its +state*. + +## Limitations + +* This test module verifies the simpkv function API is self-consistent, but + does not verify that the key data is actually stored in the correct location + in the desired backends. + + * The `simp-simpkv` module's acceptance test infrastructure uses + plugin-specific verification, in addition to the verifiction provided by + this module for full plugin verification! + +* This module only supports validation of Binary key data in `simpkv::get` + function call results. It does not support validation of Binary key data + in `simpkv::list` function call results. + +## Reference + +See [REFERENCE.md](./REFERENCE.md) for reference documentation. diff --git a/spec/support/modules/simpkv_test/REFERENCE.md b/spec/support/modules/simpkv_test/REFERENCE.md new file mode 100644 index 0000000..cb69c48 --- /dev/null +++ b/spec/support/modules/simpkv_test/REFERENCE.md @@ -0,0 +1,1002 @@ +# Reference + + + +## Table of Contents + +### Classes + +* [`simpkv_test::remove_folders`](#simpkv_testremove_folders): Remove folders using simpkv::deletetree +* [`simpkv_test::remove_keys`](#simpkv_testremove_keys): Remove keys using simpkv::delete +* [`simpkv_test::retrieve_and_verify_folders`](#simpkv_testretrieve_and_verify_folders): Retrieve folder lists with simpkv::list and verify the result +* [`simpkv_test::retrieve_and_verify_keys`](#simpkv_testretrieve_and_verify_keys): Retrieve keys with simpkv::get and verifies the results +* [`simpkv_test::store_keys`](#simpkv_teststore_keys): Store keys using simpkv::put +* [`simpkv_test::verify_folders_exist`](#simpkv_testverify_folders_exist): Check for the existence of folders using simpkv::exists +* [`simpkv_test::verify_keys_exist`](#simpkv_testverify_keys_exist): Check for the existence of keys using simpkv::exists + +### Defined types + +* [`simpkv_test::defines::remove_folder`](#simpkv_testdefinesremove_folder): Define that simply calls simpkv::deletetree +* [`simpkv_test::defines::remove_key`](#simpkv_testdefinesremove_key): Define that simply calls simpkv::delete +* [`simpkv_test::defines::retrieve_and_verify_folder`](#simpkv_testdefinesretrieve_and_verify_folder): Define that calls simpkv::list and validates its result +* [`simpkv_test::defines::retrieve_and_verify_key`](#simpkv_testdefinesretrieve_and_verify_key): Define that calls simpkv::get and validates its result +* [`simpkv_test::defines::store_key`](#simpkv_testdefinesstore_key): Define that simply calls simpkv::put +* [`simpkv_test::defines::verify_name_exists`](#simpkv_testdefinesverify_name_exists): Define that calls simpkv::exists and validates its result + +### Functions + +* [`simpkv_test::assert_equal`](#simpkv_testassert_equal): Compare 2 values and fail if they differ +* [`simpkv_test::code_source`](#simpkv_testcode_source): "Randomly" assigns the code source from which a simpkv function will +be called. +* [`simpkv_test::key_value`](#simpkv_testkey_value): Returns key value specified by `$key_data` +* [`simpkv_test::puppet_functions::remove_folder`](#simpkv_testpuppet_functionsremove_folder): Puppet language function that simply calls simpkv::deletetree +* [`simpkv_test::puppet_functions::remove_key`](#simpkv_testpuppet_functionsremove_key): Puppet language function that simply calls simpkv::delete +* [`simpkv_test::puppet_functions::retrieve_and_verify_folder`](#simpkv_testpuppet_functionsretrieve_and_verify_folder): Puppet language function that calls simpkv::list and validates its result +* [`simpkv_test::puppet_functions::retrieve_and_verify_key`](#simpkv_testpuppet_functionsretrieve_and_verify_key): Puppet language function that calls simpkv::get and validates +its result. +* [`simpkv_test::puppet_functions::store_key`](#simpkv_testpuppet_functionsstore_key): Puppet language function that simply calls simpkv::put +* [`simpkv_test::puppet_functions::verify_name_exists`](#simpkv_testpuppet_functionsverify_name_exists): Puppet language function that calls simpkv::exists and validates +its result. +* [`simpkv_test::simpkv_options`](#simpkv_testsimpkv_options): Generates simpkv_options Hash for use in simpkv function calls +* [`simpkv_test::verify_folder_data`](#simpkv_testverify_folder_data): Compare expected and actual folder contents and fail if they differ +* [`simpkv_test::verify_key_data`](#simpkv_testverify_key_data): Compare expected and actual key data and fail if they differ + +### Data types + +* [`Simpkv_test::AppId`](#simpkv_testappid): String used as the `app_id` attribute of the `simpkv_options` parameter in a simpkv function call +* [`Simpkv_test::FolderData`](#simpkv_testfolderdata): Information about an individual folder in a keystore +* [`Simpkv_test::FolderInfo`](#simpkv_testfolderinfo): Data structure specifying folder information Folders are unique based on 3 attributes: 1. The backend in which they are stored 2. Whether +* [`Simpkv_test::Folders`](#simpkv_testfolders): Data structure specifying folder listings +* [`Simpkv_test::Key`](#simpkv_testkey): Key or folder name The regex is not perfect (doesn't catch sequences that look like relative paths), but sufficient for this test module. +* [`Simpkv_test::KeyData`](#simpkv_testkeydata): Information about an individual key in a keystore +* [`Simpkv_test::KeyInfo`](#simpkv_testkeyinfo): Data structure specifying key information Keys are unique based on 3 attributes: 1. The backend in which they are stored 2. Whether they a +* [`Simpkv_test::Keys`](#simpkv_testkeys): Data structure specifying key/value pairs +* [`Simpkv_test::NameInfo`](#simpkv_testnameinfo): Data structure specifying simply key/folder names Key/folder names are unique based on 3 attributes: 1. The backend in which they are store +* [`Simpkv_test::NonBinaryKeyData`](#simpkv_testnonbinarykeydata): Information about an individual non-binary key in a keystore + +## Classes + +### `simpkv_test::remove_folders` + +Remove folders using simpkv::deletetree + +#### Parameters + +The following parameters are available in the `simpkv_test::remove_folders` class: + +* [`foldername_info`](#foldername_info) + +##### `foldername_info` + +Data type: `Simpkv_test::NameInfo` + +Info specifying the names of the folders to remove + +### `simpkv_test::remove_keys` + +Remove keys using simpkv::delete + +#### Parameters + +The following parameters are available in the `simpkv_test::remove_keys` class: + +* [`keyname_info`](#keyname_info) + +##### `keyname_info` + +Data type: `Simpkv_test::NameInfo` + +Info specifying the names of keys to remove + +### `simpkv_test::retrieve_and_verify_folders` + +Retrieve folder lists with simpkv::list and verify the result + +#### Parameters + +The following parameters are available in the `simpkv_test::retrieve_and_verify_folders` class: + +* [`valid_folder_info`](#valid_folder_info) +* [`invalid_folder_info`](#invalid_folder_info) + +##### `valid_folder_info` + +Data type: `Simpkv_test::FolderInfo` + +Info specifying folders that are expected to be present in the +keystore and their contents + +##### `invalid_folder_info` + +Data type: `Simpkv_test::FolderInfo` + +Info specifying folders that are not expected to be present in +the keystore + +### `simpkv_test::retrieve_and_verify_keys` + +Retrieve keys with simpkv::get and verifies the results + +#### Parameters + +The following parameters are available in the `simpkv_test::retrieve_and_verify_keys` class: + +* [`valid_key_info`](#valid_key_info) +* [`invalid_key_info`](#invalid_key_info) + +##### `valid_key_info` + +Data type: `Simpkv_test::KeyInfo` + +Info specifying keys that are expected to be present in the +keystore and their stored data + +##### `invalid_key_info` + +Data type: `Simpkv_test::KeyInfo` + +Info specifying keys that are not expected to be present in the +keystore + +### `simpkv_test::store_keys` + +Store keys using simpkv::put + +#### Parameters + +The following parameters are available in the `simpkv_test::store_keys` class: + +* [`key_info`](#key_info) + +##### `key_info` + +Data type: `Simpkv_test::KeyInfo` + +Info specifying the key names and data to be stored + +### `simpkv_test::verify_folders_exist` + +Check for the existence of folders using simpkv::exists + +#### Parameters + +The following parameters are available in the `simpkv_test::verify_folders_exist` class: + +* [`valid_foldername_info`](#valid_foldername_info) +* [`invalid_foldername_info`](#invalid_foldername_info) + +##### `valid_foldername_info` + +Data type: `Simpkv_test::NameInfo` + +Info specifying names of folder that are expected to be present in the +keystore + +##### `invalid_foldername_info` + +Data type: `Simpkv_test::NameInfo` + +Info specifying names of folder that are not expected to be present in +the keystore + +### `simpkv_test::verify_keys_exist` + +Check for the existence of keys using simpkv::exists + +#### Parameters + +The following parameters are available in the `simpkv_test::verify_keys_exist` class: + +* [`valid_keyname_info`](#valid_keyname_info) +* [`invalid_keyname_info`](#invalid_keyname_info) + +##### `valid_keyname_info` + +Data type: `Simpkv_test::NameInfo` + +Info specifying names of keys that are expected to be present in the +keystore + +##### `invalid_keyname_info` + +Data type: `Simpkv_test::NameInfo` + +Info specifying names of keys that are not expected to be present in +the keystore + +## Defined types + +### `simpkv_test::defines::remove_folder` + +Define that simply calls simpkv::deletetree + +#### Parameters + +The following parameters are available in the `simpkv_test::defines::remove_folder` defined type: + +* [`folder`](#folder) +* [`simpkv_options`](#simpkv_options) + +##### `folder` + +Data type: `Simpkv_test::Key` + +Name of the folder to remove + +##### `simpkv_options` + +Data type: `Hash` + +Value of the simpkv_options parameter to be used in the simpkv::deletetree +function call + +Default value: `{}` + +### `simpkv_test::defines::remove_key` + +Define that simply calls simpkv::delete + +#### Parameters + +The following parameters are available in the `simpkv_test::defines::remove_key` defined type: + +* [`key`](#key) +* [`simpkv_options`](#simpkv_options) + +##### `key` + +Data type: `Simpkv_test::Key` + +Name of the key to remove + +##### `simpkv_options` + +Data type: `Hash` + +Value of the simpkv_options parameter to be used in the simpkv::delete +function call + +Default value: `{}` + +### `simpkv_test::defines::retrieve_and_verify_folder` + +Fails if validation fails. + +#### Parameters + +The following parameters are available in the `simpkv_test::defines::retrieve_and_verify_folder` defined type: + +* [`folder`](#folder) +* [`expected_keys`](#expected_keys) +* [`expected_folders`](#expected_folders) +* [`simpkv_options`](#simpkv_options) + +##### `folder` + +Data type: `Simpkv_test::Key` + +Name of the folder to be listed + +##### `expected_keys` + +Data type: `Variant[Hash[Simpkv_test::Key,Simpkv_test::NonBinaryKeyData],Undef]` + +Expected key data + +##### `expected_folders` + +Data type: `Variant[Array[String[1]],Undef]` + +Expected folder data + +##### `simpkv_options` + +Data type: `Hash` + +Value of the simpkv_options parameter to be used in the simpkv::list +function call + +Default value: `{}` + +### `simpkv_test::defines::retrieve_and_verify_key` + +Fails if validation fails. + +#### Parameters + +The following parameters are available in the `simpkv_test::defines::retrieve_and_verify_key` defined type: + +* [`key`](#key) +* [`expected_value`](#expected_value) +* [`expected_metadata`](#expected_metadata) +* [`simpkv_options`](#simpkv_options) +* [`binary`](#binary) + +##### `key` + +Data type: `Simpkv_test::Key` + +Name of the key to be retrieved + +##### `expected_value` + +Data type: `Any` + +Expected key value + +##### `expected_metadata` + +Data type: `Variant[Hash,Undef]` + +Expected key metadata + +##### `simpkv_options` + +Data type: `Hash` + +Value of the simpkv_options parameter to be used in the simpkv::get +function call + +##### `binary` + +Data type: `Boolean` + +Whether the key has a binary value + +### `simpkv_test::defines::store_key` + +Define that simply calls simpkv::put + +#### Parameters + +The following parameters are available in the `simpkv_test::defines::store_key` defined type: + +* [`key`](#key) +* [`value`](#value) +* [`metadata`](#metadata) +* [`simpkv_options`](#simpkv_options) + +##### `key` + +Data type: `Simpkv_test::Key` + +Name of the key to store + +##### `value` + +Data type: `NotUndef` + +Value to store + +##### `metadata` + +Data type: `Hash` + +Metadata to store + +Default value: `{}` + +##### `simpkv_options` + +Data type: `Hash` + +Value of the simpkv_options parameter to be used in the simpkv::put +function call + +Default value: `{}` + +### `simpkv_test::defines::verify_name_exists` + +Fails if validation fails. + +#### Parameters + +The following parameters are available in the `simpkv_test::defines::verify_name_exists` defined type: + +* [`key`](#key) +* [`simpkv_options`](#simpkv_options) +* [`valid`](#valid) + +##### `key` + +Data type: `Simpkv_test::Key` + +Name of the key/folder whose existence is to be checked + +##### `simpkv_options` + +Data type: `Hash` + +Value of the simpkv_options parameter to be used in the simpkv::exists +function call + +Default value: `{}` + +##### `valid` + +Data type: `Boolean` + +Whether key/folder should exist + +## Functions + +### `simpkv_test::assert_equal` + +Type: Puppet Language + +Compare 2 values and fail if they differ + +#### `simpkv_test::assert_equal(Any $actual, Any $expected, String $message)` + +The simpkv_test::assert_equal function. + +Returns: `None` + +##### `actual` + +Data type: `Any` + +Actual value + +##### `expected` + +Data type: `Any` + +Expected value + +##### `message` + +Data type: `String` + +Explanatory text that is added to the failure message + +### `simpkv_test::code_source` + +Type: Puppet Language + +"Randomly" assigns the code source from which a simpkv function will +be called. + +#### `simpkv_test::code_source(String $id)` + +The simpkv_test::code_source function. + +Returns: `Enum['class', 'define', 'puppet_function']` + +##### `id` + +Data type: `String` + +Id of the key/folder used in the simpkv function + +- Used as the random generator seed + +### `simpkv_test::key_value` + +Type: Puppet Language + +Transforms to Binary as necessary, or undef if the value cannot be determined. + +#### `simpkv_test::key_value(Simpkv_test::KeyData $key_data)` + +Transforms to Binary as necessary, or undef if the value cannot be determined. + +Returns: `Any` + +##### `key_data` + +Data type: `Simpkv_test::KeyData` + +Key specification + +### `simpkv_test::puppet_functions::remove_folder` + +Type: Puppet Language + +Puppet language function that simply calls simpkv::deletetree + +#### `simpkv_test::puppet_functions::remove_folder(Simpkv_test::Key $folder, Hash $simpkv_options)` + +The simpkv_test::puppet_functions::remove_folder function. + +Returns: `None` + +##### `folder` + +Data type: `Simpkv_test::Key` + +Name of the folder to remove + +##### `simpkv_options` + +Data type: `Hash` + +Value of the simpkv_options parameter to be used in the simpkv::deletetree +function call + +### `simpkv_test::puppet_functions::remove_key` + +Type: Puppet Language + +Puppet language function that simply calls simpkv::delete + +#### `simpkv_test::puppet_functions::remove_key(Simpkv_test::Key $key, Hash $simpkv_options)` + +The simpkv_test::puppet_functions::remove_key function. + +Returns: `None` + +##### `key` + +Data type: `Simpkv_test::Key` + +Name of the key to remove + +##### `simpkv_options` + +Data type: `Hash` + +Value of the simpkv_options parameter to be used in the simpkv::delete +function call + +### `simpkv_test::puppet_functions::retrieve_and_verify_folder` + +Type: Puppet Language + +Fails if validation fails. + +#### `simpkv_test::puppet_functions::retrieve_and_verify_folder(Simpkv_test::Key $folder, Variant[Hash[Simpkv_test::Key,Simpkv_test::NonBinaryKeyData],Undef] $expected_keys, Variant[Array[String[1]],Undef] $expected_folders, Hash $simpkv_options = {})` + +Fails if validation fails. + +Returns: `None` + +##### `folder` + +Data type: `Simpkv_test::Key` + +Name of the folder to be listed + +##### `expected_keys` + +Data type: `Variant[Hash[Simpkv_test::Key,Simpkv_test::NonBinaryKeyData],Undef]` + +Expected key data + +##### `expected_folders` + +Data type: `Variant[Array[String[1]],Undef]` + +Expected folder data + +##### `simpkv_options` + +Data type: `Hash` + +Value of the simpkv_options parameter to be used in the simpkv::list +function call + +### `simpkv_test::puppet_functions::retrieve_and_verify_key` + +Type: Puppet Language + +Fails if validation fails. + +#### `simpkv_test::puppet_functions::retrieve_and_verify_key(Simpkv_test::Key $key, Any $expected_value, Variant[Hash,Undef] $expected_metadata, Hash $simpkv_options, Boolean $binary)` + +Fails if validation fails. + +Returns: `None` + +##### `key` + +Data type: `Simpkv_test::Key` + +Name of the key to be retrieved + +##### `expected_value` + +Data type: `Any` + +Expected key value + +##### `expected_metadata` + +Data type: `Variant[Hash,Undef]` + +Expected key metadata + +##### `simpkv_options` + +Data type: `Hash` + +Value of the simpkv_options parameter to be used in the simpkv::get +function call + +##### `binary` + +Data type: `Boolean` + +Whether the key has a binary value + +### `simpkv_test::puppet_functions::store_key` + +Type: Puppet Language + +Puppet language function that simply calls simpkv::put + +#### `simpkv_test::puppet_functions::store_key(Simpkv_test::Key $key, NotUndef $value, Hash $metadata, Hash $simpkv_options)` + +The simpkv_test::puppet_functions::store_key function. + +Returns: `None` + +##### `key` + +Data type: `Simpkv_test::Key` + +Name of the key to store + +##### `value` + +Data type: `NotUndef` + +Value to store + +##### `metadata` + +Data type: `Hash` + +Metadata to store + +##### `simpkv_options` + +Data type: `Hash` + +Value of the simpkv_options parameter to be used in the simpkv::put +function call + +### `simpkv_test::puppet_functions::verify_name_exists` + +Type: Puppet Language + +Fails if validation fails. + +#### `simpkv_test::puppet_functions::verify_name_exists(Simpkv_test::Key $key, Hash $simpkv_options, Boolean $valid)` + +Fails if validation fails. + +Returns: `None` + +##### `key` + +Data type: `Simpkv_test::Key` + +Name of the key/folder whose existence is to be checked + +##### `simpkv_options` + +Data type: `Hash` + +Value of the simpkv_options parameter to be used in the simpkv::exists +function call + +##### `valid` + +Data type: `Boolean` + +Whether key/folder should exist + +### `simpkv_test::simpkv_options` + +Type: Puppet Language + +Generates simpkv_options Hash for use in simpkv function calls + +#### `simpkv_test::simpkv_options(Simpkv_test::AppId $app_id, Enum['env', 'global'] $key_type, Hash $other_options = {})` + +The simpkv_test::simpkv_options function. + +Returns: `Hash` + +##### `app_id` + +Data type: `Simpkv_test::AppId` + +`app_id` to be set in the simpkv_options Hash + +- Ignored when an empty string + +##### `key_type` + +Data type: `Enum['env', 'global']` + +The key/folder type + +- 'env': key/folder is tied to a Puppet environment +- 'global': key/folder is global + +##### `other_options` + +Data type: `Hash` + +Other options to be set in the returned simpkv_options Hash + +### `simpkv_test::verify_folder_data` + +Type: Puppet Language + +Compare expected and actual folder contents and fail if they differ + +#### `simpkv_test::verify_folder_data(Variant[Hash,Undef] $list_result, Variant[Hash[Simpkv_test::Key,Simpkv_test::NonBinaryKeyData],Undef] $expected_keys, Variant[Array[String[1]],Undef] $expected_folders, String[1] $message)` + +The simpkv_test::verify_folder_data function. + +Returns: `None` + +##### `list_result` + +Data type: `Variant[Hash,Undef]` + +The actual `simpkv::list` result + +##### `expected_keys` + +Data type: `Variant[Hash[Simpkv_test::Key,Simpkv_test::NonBinaryKeyData],Undef]` + +Expected key data + +##### `expected_folders` + +Data type: `Variant[Array[String[1]],Undef]` + +Expected folder data + +##### `message` + +Data type: `String[1]` + +Explanatory text that is added to the failure message, if the comparison +fails + +### `simpkv_test::verify_key_data` + +Type: Puppet Language + +Compare expected and actual key data and fail if they differ + +#### `simpkv_test::verify_key_data(Variant[Hash,Undef] $get_result, Any $expected_value, Variant[Hash,Undef] $expected_metadata, Boolean $binary, String[1] $message)` + +The simpkv_test::verify_key_data function. + +Returns: `None` + +##### `get_result` + +Data type: `Variant[Hash,Undef]` + +The actual `simpkv::get` result + +##### `expected_value` + +Data type: `Any` + +Expected key value + +##### `expected_metadata` + +Data type: `Variant[Hash,Undef]` + +Expected key metadata + +##### `binary` + +Data type: `Boolean` + +Whether the key has a binary value + +##### `message` + +Data type: `String[1]` + +Explanatory text that is added to the failure message, if the comparison +fails + +## Data types + +### `Simpkv_test::AppId` + +String used as the `app_id` attribute of the `simpkv_options` parameter in +a simpkv function call + +Alias of + +```puppet +String +``` + +### `Simpkv_test::FolderData` + +Information about an individual folder in a keystore + +Alias of + +```puppet +Struct[{ + # Info about keys in the directory + # - Currently restricted to keys with non-binary data because of + # test manifest limitations + Optional[keys] => Hash[Simpkv_test::Key,Simpkv_test::NonBinaryKeyData], + + # List of subfolder names + Optional[folders] => Array[String[1]] +}] +``` + +### `Simpkv_test::FolderInfo` + +Data structure specifying folder information + +Folders are unique based on 3 attributes: + 1. The backend in which they are stored + 2. Whether they are tied to a Puppet environment or global + 3. The folder names (each of which may include a relative path) + +The grouping below was chosen to ensure uniqueness for test folders, +**ASSUMING**, backends are uniquely mapped to the `app_id` attribute that +will be used in the `simpkv_options` parameter of each simpkv function call. + +If you are mapping multiple `app_id` values to the same backend in a test, +be sure you don't have any folders that will resolve to the same storage +location! + +Alias of + +```puppet +Hash[Simpkv_test::AppId, Struct[{ + # - Any folder in 'env' is a folder tied to the Puppet environment. + # - Any folder in 'global' is a global folder. + # - For these folders, the 'global' attribute of the `simpkv_options` + # parameter of each simpkv function call will be automatically set + # to `true`. + Optional[env] => Simpkv_test::Folders, + Optional[global] => Simpkv_test::Folders + }]] +``` + +### `Simpkv_test::Folders` + +Data structure specifying folder listings + +Alias of + +```puppet +Hash[Simpkv_test::Key, Simpkv_test::FolderData] +``` + +### `Simpkv_test::Key` + +Key or folder name + +The regex is not perfect (doesn't catch sequences that look +like relative paths), but sufficient for this test module. + +Alias of + +```puppet +Pattern['^[a-z0-9._:\-\/]+$'] +``` + +### `Simpkv_test::KeyData` + +Information about an individual key in a keystore + +Alias of + +```puppet +Struct[{ + # Either 'value' or 'file' needs to be set. + # If both are set, 'value' will be used over 'file'. + # If neither are set, the Simpkv_test::KeyData instance will be skipped. + + # Non-binary value + Optional[value] => NotUndef, + + # File containing binary value + # - argument to binary_file, which is an absolute path or + # / string referencing a module file + Optional[file] => String[1], + + # Optional metadata stored with the value + Optional[metadata] => Hash +}] +``` + +### `Simpkv_test::KeyInfo` + +Data structure specifying key information + +Keys are unique based on 3 attributes: + 1. The backend in which they are stored + 2. Whether they are tied to a Puppet environment or global + 3. The key names (each of which may include a relative folder path) + +The grouping below was chosen to ensure uniqueness for test keys, +**ASSUMING**, backends are uniquely mapped to the `app_id` attribute that +will be used in the `simpkv_options` parameter of each simpkv function call. + +If you are mapping multiple `app_id` values to the same backend in a test, +be sure you don't have any keys that will resolve to the same storage +location! + +Alias of + +```puppet +Hash[Simpkv_test::AppId, Struct[{ + # - Any key in 'env' is a key tied to the Puppet environment. + # - Any key in 'global' is a global key. + # - For these keys, the 'global' attribute of the `simpkv_options` + # parameter of each simpkv function call will be automatically set + # to `true`. + Optional[env] => Simpkv_test::Keys, + Optional[global] => Simpkv_test::Keys + }]] +``` + +### `Simpkv_test::Keys` + +Data structure specifying key/value pairs + +Alias of + +```puppet +Hash[Simpkv_test::Key, Simpkv_test::KeyData] +``` + +### `Simpkv_test::NameInfo` + +Data structure specifying simply key/folder names + +Key/folder names are unique based on 3 attributes: + 1. The backend in which they are stored + 2. Whether they are tied to a Puppet environment or global + 3. The key/folder names (each of which may include a relative folder path) + +The grouping below was chosen to ensure uniqueness for test key/folder names, +**ASSUMING**, backends are uniquely mapped to the `app_id` attribute that +will be used in the `simpkv_options` parameter of each simpkv function call. + +If you are mapping multiple `app_id` values to the same backend in a test, +be sure you don't have any keys/folders that will resolve to the same storage +location! + +Alias of + +```puppet +Hash[Simpkv_test::AppId, Struct[{ + # - Any key/folder in 'env' is tied to the Puppet environment. + # - Any key/folder in 'global' is global + # - For these entities, the 'global' attribute of the `simpkv_options` + # parameter of each simpkv function call will be automatically set + # to `true`. + Optional[env] => Array[Simpkv_test::Key], + Optional[global] => Array[Simpkv_test::Key] + }]] +``` + +### `Simpkv_test::NonBinaryKeyData` + +Information about an individual non-binary key in a keystore + +Alias of + +```puppet +Struct[{ + # Non-binary value + value => NotUndef, + + # Optional metadata stored with the value + Optional[metadata] => Hash +}] +``` + diff --git a/spec/support/modules/simpkv_test/files/test_krb5.keytab b/spec/support/modules/simpkv_test/files/test_krb5.keytab new file mode 100644 index 0000000000000000000000000000000000000000..c0521855b28dd85a024c2a60de721fa73532542a GIT binary patch literal 168 zcmZQ&VqjnhXJBGr32_Y$VPMI~FD_vaOH0g7jR!Fe^@{UzQ}t5va}zW3fGQbd%Wvf{ zG6*p!WEh(`>!-B0aXyKU`#M*L{o>i==ZiPAs(&gum}^(KX&Xo}5WACVv>=0kS;F-j TV&88qkbZC>@y-02V31J&Tyix| literal 0 HcmV?d00001 diff --git a/spec/support/modules/simpkv_test/functions/assert_equal.pp b/spec/support/modules/simpkv_test/functions/assert_equal.pp index 940e8d3..b75cfb5 100644 --- a/spec/support/modules/simpkv_test/functions/assert_equal.pp +++ b/spec/support/modules/simpkv_test/functions/assert_equal.pp @@ -1,3 +1,16 @@ +# @summary Compare 2 values and fail if they differ +# +# @param actual +# Actual value +# +# @param expected +# Expected value +# +# @param message +# Explanatory text that is added to the failure message +# +# @return [None] +# function simpkv_test::assert_equal( Any $actual, Any $expected, @@ -6,7 +19,15 @@ function simpkv_test::assert_equal( info("Checking results for ${message}") - if ($actual != $expected) { + if ($actual == $expected) { + if $actual =~ Binary { + info("Actual binary results match expected") + } + else { + info("Actual results match expected '${expected}'") + } + } + else { fail("Expected '${expected}'; got '${actual}' for ${message}") } } diff --git a/spec/support/modules/simpkv_test/functions/code_source.pp b/spec/support/modules/simpkv_test/functions/code_source.pp new file mode 100644 index 0000000..1b9b6e0 --- /dev/null +++ b/spec/support/modules/simpkv_test/functions/code_source.pp @@ -0,0 +1,16 @@ +# @summary "Randomly" assigns the code source from which a simpkv function will +# be called. +# +# @param id +# Id of the key/folder used in the simpkv function +# +# - Used as the random generator seed +# +# @return [Enum['class', 'define', 'puppet_function']] +# +function simpkv_test::code_source(String $id) { + + $_values = [ 'class', 'define', 'puppet_function' ] + $_index = seeded_rand(3, $id) + $_values[$_index] +} diff --git a/spec/support/modules/simpkv_test/functions/key_value.pp b/spec/support/modules/simpkv_test/functions/key_value.pp new file mode 100644 index 0000000..4af7996 --- /dev/null +++ b/spec/support/modules/simpkv_test/functions/key_value.pp @@ -0,0 +1,23 @@ +# @summary Returns key value specified by `$key_data` +# +# Transforms to Binary as necessary, or undef if the value cannot be determined. +# +# @param key_data +# Key specification +# +# @return [Any] +# +function simpkv_test::key_value( + Simpkv_test::KeyData $key_data +) { + + if 'value' in $key_data { + $key_data['value'] + } + elsif 'file' in $key_data { + binary_file($key_data['file']) + } + else { + undef + } +} diff --git a/spec/support/modules/simpkv_test/functions/puppet_functions/remove_folder.pp b/spec/support/modules/simpkv_test/functions/puppet_functions/remove_folder.pp new file mode 100644 index 0000000..6736493 --- /dev/null +++ b/spec/support/modules/simpkv_test/functions/puppet_functions/remove_folder.pp @@ -0,0 +1,18 @@ +# @summary Puppet language function that simply calls simpkv::deletetree +# +# @param folder +# Name of the folder to remove +# +# @param simpkv_options +# Value of the simpkv_options parameter to be used in the simpkv::deletetree +# function call +# +# @return [None] +# +function simpkv_test::puppet_functions::remove_folder( + Simpkv_test::Key $folder, + Hash $simpkv_options +) { + info("Calling simpkv::deletetree('${folder}', ${simpkv_options})") + simpkv::deletetree($folder, $simpkv_options) +} diff --git a/spec/support/modules/simpkv_test/functions/puppet_functions/remove_key.pp b/spec/support/modules/simpkv_test/functions/puppet_functions/remove_key.pp new file mode 100644 index 0000000..243b8c9 --- /dev/null +++ b/spec/support/modules/simpkv_test/functions/puppet_functions/remove_key.pp @@ -0,0 +1,18 @@ +# @summary Puppet language function that simply calls simpkv::delete +# +# @param key +# Name of the key to remove +# +# @param simpkv_options +# Value of the simpkv_options parameter to be used in the simpkv::delete +# function call +# +# @return [None] +# +function simpkv_test::puppet_functions::remove_key( + Simpkv_test::Key $key, + Hash $simpkv_options +) { + info("Calling simpkv::delete('${key}', ${simpkv_options})") + simpkv::delete($key, $simpkv_options) +} diff --git a/spec/support/modules/simpkv_test/functions/puppet_functions/retrieve_and_verify_folder.pp b/spec/support/modules/simpkv_test/functions/puppet_functions/retrieve_and_verify_folder.pp new file mode 100644 index 0000000..83022c0 --- /dev/null +++ b/spec/support/modules/simpkv_test/functions/puppet_functions/retrieve_and_verify_folder.pp @@ -0,0 +1,32 @@ +# @summary Puppet language function that calls simpkv::list and validates its result +# +# Fails if validation fails. +# +# @param folder +# Name of the folder to be listed +# +# @param expected_keys +# Expected key data +# +# @param expected_folders +# Expected folder data +# +# @param simpkv_options +# Value of the simpkv_options parameter to be used in the simpkv::list +# function call +# +# @return [None] +# +function simpkv_test::puppet_functions::retrieve_and_verify_folder( + Simpkv_test::Key $folder, + Variant[Hash[Simpkv_test::Key,Simpkv_test::NonBinaryKeyData],Undef] $expected_keys, + Variant[Array[String[1]],Undef] $expected_folders, + Hash $simpkv_options = {} +) { + + $_message = "simpkv::list('${folder}', ${simpkv_options})" + info("Calling ${_message}") + + $_result = simpkv::list($folder, $simpkv_options) + simpkv_test::verify_folder_data($_result, $expected_keys, $expected_folders, $_message) +} diff --git a/spec/support/modules/simpkv_test/functions/puppet_functions/retrieve_and_verify_key.pp b/spec/support/modules/simpkv_test/functions/puppet_functions/retrieve_and_verify_key.pp new file mode 100644 index 0000000..87b9c03 --- /dev/null +++ b/spec/support/modules/simpkv_test/functions/puppet_functions/retrieve_and_verify_key.pp @@ -0,0 +1,38 @@ +# @summary Puppet language function that calls simpkv::get and validates +# its result. +# +# Fails if validation fails. +# +# @param key +# Name of the key to be retrieved +# +# @param expected_value +# Expected key value +# +# @param expected_metadata +# Expected key metadata +# +# @param simpkv_options +# Value of the simpkv_options parameter to be used in the simpkv::get +# function call +# +# @param binary +# Whether the key has a binary value +# +# @return [None] +# +function simpkv_test::puppet_functions::retrieve_and_verify_key( + Simpkv_test::Key $key, + Any $expected_value, + Variant[Hash,Undef] $expected_metadata, + Hash $simpkv_options, + Boolean $binary +) { + + $_message = "simpkv::get('${key}', ${simpkv_options})" + info("Calling ${_message}") + $_result = simpkv::get($key, $simpkv_options) + + simpkv_test::verify_key_data( $_result, $expected_value, + $expected_metadata, $binary, $_message) +} diff --git a/spec/support/modules/simpkv_test/functions/puppet_functions/store_key.pp b/spec/support/modules/simpkv_test/functions/puppet_functions/store_key.pp new file mode 100644 index 0000000..f9a2577 --- /dev/null +++ b/spec/support/modules/simpkv_test/functions/puppet_functions/store_key.pp @@ -0,0 +1,26 @@ +# @summary Puppet language function that simply calls simpkv::put +# +# @param key +# Name of the key to store +# +# @param value +# Value to store +# +# @param metadata +# Metadata to store +# +# @param simpkv_options +# Value of the simpkv_options parameter to be used in the simpkv::put +# function call +# +# @return [None] +# +function simpkv_test::puppet_functions::store_key( + Simpkv_test::Key $key, + NotUndef $value, + Hash $metadata, + Hash $simpkv_options +) { + info("Calling simpkv::put('${key}', ${value}, ${metadata}, ${simpkv_options})") + simpkv::put($key, $value, $metadata, $simpkv_options) +} diff --git a/spec/support/modules/simpkv_test/functions/puppet_functions/verify_name_exists.pp b/spec/support/modules/simpkv_test/functions/puppet_functions/verify_name_exists.pp new file mode 100644 index 0000000..b6f8d43 --- /dev/null +++ b/spec/support/modules/simpkv_test/functions/puppet_functions/verify_name_exists.pp @@ -0,0 +1,28 @@ +# @summary Puppet language function that calls simpkv::exists and validates +# its result. +# +# Fails if validation fails. +# +# @param key +# Name of the key/folder whose existence is to be checked +# +# @param simpkv_options +# Value of the simpkv_options parameter to be used in the simpkv::exists +# function call +# +# @param valid +# Whether key/folder should exist +# +# @return [None] +# +function simpkv_test::puppet_functions::verify_name_exists( + Simpkv_test::Key $key, + Hash $simpkv_options, + Boolean $valid +) { + + $_message = "simpkv::exists('${key}', ${simpkv_options})" + info("Calling ${_message}") + $_key_exists = simpkv::exists($key, $simpkv_options) + simpkv_test::assert_equal( $_key_exists, $valid, $_message) +} diff --git a/spec/support/modules/simpkv_test/functions/put_pwrapper.pp b/spec/support/modules/simpkv_test/functions/put_pwrapper.pp deleted file mode 100644 index 124aaa9..0000000 --- a/spec/support/modules/simpkv_test/functions/put_pwrapper.pp +++ /dev/null @@ -1,17 +0,0 @@ -# Puppet language wrapper function for simpkv::put -# -# We force the user to pass in options, so that simpkv::put -# doesn't always assume the backend in `default`! -function simpkv_test::put_pwrapper( - String $key, - Any $value, - Hash $options, - Hash $meta = {}, -) { - - # - # Insert application-specific work - # - - simpkv::put($key, $value, $meta, $options) -} diff --git a/spec/support/modules/simpkv_test/functions/simpkv_options.pp b/spec/support/modules/simpkv_test/functions/simpkv_options.pp new file mode 100644 index 0000000..57c2b22 --- /dev/null +++ b/spec/support/modules/simpkv_test/functions/simpkv_options.pp @@ -0,0 +1,45 @@ +# @summary Generates simpkv_options Hash for use in simpkv function calls +# +# @param app_id +# `app_id` to be set in the simpkv_options Hash +# +# - Ignored when an empty string +# +# @param key_type +# The key/folder type +# +# - 'env': key/folder is tied to a Puppet environment +# - 'global': key/folder is global +# +# @param other_options +# Other options to be set in the returned simpkv_options Hash +# +# @return [Hash] +# +function simpkv_test::simpkv_options( + Simpkv_test::AppId $app_id, + Enum['env', 'global'] $key_type, + Hash $other_options = {} +) { + if empty($app_id) { + if $key_type == 'env' { + $_simpkv_options = $other_options + } + else { + $_simpkv_options = $other_options.merge({ 'global' => true }) + } + } + else { + if $key_type == 'env' { + $_simpkv_options = $other_options.merge({ 'app_id' => $app_id }) + } + else { + $_simpkv_options = $other_options.merge({ + 'app_id' => $app_id, + 'global' => true + }) + } + } + + $_simpkv_options +} diff --git a/spec/support/modules/simpkv_test/functions/verify_folder_data.pp b/spec/support/modules/simpkv_test/functions/verify_folder_data.pp new file mode 100644 index 0000000..a725642 --- /dev/null +++ b/spec/support/modules/simpkv_test/functions/verify_folder_data.pp @@ -0,0 +1,42 @@ +# @summary Compare expected and actual folder contents and fail if they differ +# +# @param list_result +# The actual `simpkv::list` result +# +# @param expected_keys +# Expected key data +# +# @param expected_folders +# Expected folder data +# +# @param message +# Explanatory text that is added to the failure message, if the comparison +# fails +# +# @return [None] +# +function simpkv_test::verify_folder_data( + Variant[Hash,Undef] $list_result, + Variant[Hash[Simpkv_test::Key,Simpkv_test::NonBinaryKeyData],Undef] $expected_keys, + Variant[Array[String[1]],Undef] $expected_folders, + String[1] $message +) { + + info("Verifying list data for ${message}") + + if ($expected_keys =~ Undef) or ($expected_folders =~ Undef) { + simpkv_test::assert_equal($list_result, $expected_keys, $message) + } + elsif ($list_result =~ Undef) or !('keys' in $list_result) or !('folders' in $list_result) + { + fail("${message} returned invalid value << ${list_result} >>") + } + else { + $_expected_result = { + 'keys' => $expected_keys, + 'folders' => $expected_folders + } + + simpkv_test::assert_equal($list_result, $_expected_result, $message) + } +} diff --git a/spec/support/modules/simpkv_test/functions/verify_key_data.pp b/spec/support/modules/simpkv_test/functions/verify_key_data.pp new file mode 100644 index 0000000..6d3787a --- /dev/null +++ b/spec/support/modules/simpkv_test/functions/verify_key_data.pp @@ -0,0 +1,59 @@ +# @summary Compare expected and actual key data and fail if they differ +# +# @param get_result +# The actual `simpkv::get` result +# +# @param expected_value +# Expected key value +# +# @param expected_metadata +# Expected key metadata +# +# @param binary +# Whether the key has a binary value +# +# @param message +# Explanatory text that is added to the failure message, if the comparison +# fails +# +# @return [None] +# +function simpkv_test::verify_key_data( + Variant[Hash,Undef] $get_result, + Any $expected_value, + Variant[Hash,Undef] $expected_metadata, + Boolean $binary, + String[1] $message +) { + + info("Verifying key data for ${message}") + + if $expected_value =~ Undef { + simpkv_test::assert_equal($get_result, $expected_value, $message) + } + elsif ($get_result =~ Undef) or !('value' in $get_result) { + fail("${message} returned invalid value << ${get_result} >>") + } + elsif $binary { + $_value_binary = Binary.new($get_result['value'], '%r') + simpkv_test::assert_equal($_value_binary, $expected_value, + "${message} content") + + simpkv_test::assert_equal($get_result['metadata'], $expected_metadata, + "${message} metadata") + } + else { + if $expected_metadata { + $_expected_result = { + 'value' => $expected_value, + 'metadata' => $expected_metadata + } + } + else + { + $_expected_result = { 'value' => $expected_value } + } + + simpkv_test::assert_equal( $get_result, $_expected_result, $message) + } +} diff --git a/spec/support/modules/simpkv_test/manifests/binary_get.pp b/spec/support/modules/simpkv_test/manifests/binary_get.pp deleted file mode 100644 index df095a2..0000000 --- a/spec/support/modules/simpkv_test/manifests/binary_get.pp +++ /dev/null @@ -1,25 +0,0 @@ -class simpkv_test::binary_get( - Binary $test_binary = binary_file('/root/binary_data/input_data'), - Hash $test_meta = { 'some' => 'metadata for binary' } -) { - # Retrieving binary content requires careful handling, as the - # retrieved value is a String encoded in ASCII-8BIT - $_result1 = simpkv::get('from_class/binary') - $_value_binary1 = Binary.new($_result1['value'], '%r') - simpkv_test::assert_equal($_value_binary1, $test_binary, "simpkv::get('from_class/binary') content") - - $_result2 = simpkv::get('from_class/binary_with_meta') - $_value_binary2 = Binary.new($_result2['value'], '%r') - $_meta_binary2 = $_result2['metadata'] - simpkv_test::assert_equal($_value_binary2, $test_binary, "simpkv::get('from_class/binary_with_meta') content") - simpkv_test::assert_equal($_meta_binary2, $test_meta, "simpkv::get('from_class/binary_with_meta' metadata)") - - # persist the binary content for external verification - file { '/root/binary_data/retrieved_data1': - content => $_value_binary1 - } - - file { '/root/binary_data/retrieved_data2': - content => $_value_binary2 - } -} diff --git a/spec/support/modules/simpkv_test/manifests/binary_put.pp b/spec/support/modules/simpkv_test/manifests/binary_put.pp deleted file mode 100644 index a4a8207..0000000 --- a/spec/support/modules/simpkv_test/manifests/binary_put.pp +++ /dev/null @@ -1,7 +0,0 @@ -class simpkv_test::binary_put( - Binary $test_binary = binary_file('/root/binary_data/input_data'), - Hash $test_meta = { 'some' => 'metadata for binary' } -) { - simpkv::put('from_class/binary', $test_binary) - simpkv::put('from_class/binary_with_meta', $test_binary, $test_meta) -} diff --git a/spec/support/modules/simpkv_test/manifests/defines/put.pp b/spec/support/modules/simpkv_test/manifests/defines/put.pp deleted file mode 100644 index 237c1eb..0000000 --- a/spec/support/modules/simpkv_test/manifests/defines/put.pp +++ /dev/null @@ -1,9 +0,0 @@ -define simpkv_test::defines::put( - String $test_string = 'dstring', - Hash $test_meta = {}, - Hash $simpkv_options = { 'app_id' => "Simpkv_test::Defines::Put[${name}]" } -) { - - simpkv::put("from_define/${name}/string", $test_string, $test_meta, $simpkv_options) - simpkv_test::put_pwrapper("from_define/${name}/string_from_pfunction", $test_string, $simpkv_options, $test_meta) -} diff --git a/spec/support/modules/simpkv_test/manifests/defines/remove_folder.pp b/spec/support/modules/simpkv_test/manifests/defines/remove_folder.pp new file mode 100644 index 0000000..9e0259f --- /dev/null +++ b/spec/support/modules/simpkv_test/manifests/defines/remove_folder.pp @@ -0,0 +1,17 @@ +# @summary Define that simply calls simpkv::deletetree +# +# @param folder +# Name of the folder to remove +# +# @param simpkv_options +# Value of the simpkv_options parameter to be used in the simpkv::deletetree +# function call +# +define simpkv_test::defines::remove_folder( + Simpkv_test::Key $folder, + Hash $simpkv_options = {} +) { + + info("Calling simpkv::deletetree('${folder}', ${simpkv_options})") + simpkv::deletetree($folder, $simpkv_options) +} diff --git a/spec/support/modules/simpkv_test/manifests/defines/remove_key.pp b/spec/support/modules/simpkv_test/manifests/defines/remove_key.pp new file mode 100644 index 0000000..88dc992 --- /dev/null +++ b/spec/support/modules/simpkv_test/manifests/defines/remove_key.pp @@ -0,0 +1,17 @@ +# @summary Define that simply calls simpkv::delete +# +# @param key +# Name of the key to remove +# +# @param simpkv_options +# Value of the simpkv_options parameter to be used in the simpkv::delete +# function call +# +define simpkv_test::defines::remove_key( + Simpkv_test::Key $key, + Hash $simpkv_options = {} +) { + + info("Calling simpkv::delete('${key}', ${simpkv_options})") + simpkv::delete($key, $simpkv_options) +} diff --git a/spec/support/modules/simpkv_test/manifests/defines/retrieve_and_verify_folder.pp b/spec/support/modules/simpkv_test/manifests/defines/retrieve_and_verify_folder.pp new file mode 100644 index 0000000..a95e99d --- /dev/null +++ b/spec/support/modules/simpkv_test/manifests/defines/retrieve_and_verify_folder.pp @@ -0,0 +1,30 @@ +# @summary Define that calls simpkv::list and validates its result +# +# Fails if validation fails. +# +# @param folder +# Name of the folder to be listed +# +# @param expected_keys +# Expected key data +# +# @param expected_folders +# Expected folder data +# +# @param simpkv_options +# Value of the simpkv_options parameter to be used in the simpkv::list +# function call +# +define simpkv_test::defines::retrieve_and_verify_folder( + Simpkv_test::Key $folder, + Variant[Hash[Simpkv_test::Key,Simpkv_test::NonBinaryKeyData],Undef] $expected_keys, + Variant[Array[String[1]],Undef] $expected_folders, + Hash $simpkv_options = {} +) { + + $_message = "simpkv::list('${folder}', ${simpkv_options})" + info("Calling ${_message}") + + $_result = simpkv::list($folder, $simpkv_options) + simpkv_test::verify_folder_data($_result, $expected_keys, $expected_folders, $_message) +} diff --git a/spec/support/modules/simpkv_test/manifests/defines/retrieve_and_verify_key.pp b/spec/support/modules/simpkv_test/manifests/defines/retrieve_and_verify_key.pp new file mode 100644 index 0000000..b3ca359 --- /dev/null +++ b/spec/support/modules/simpkv_test/manifests/defines/retrieve_and_verify_key.pp @@ -0,0 +1,34 @@ +# @summary Define that calls simpkv::get and validates its result +# +# Fails if validation fails. +# +# @param key +# Name of the key to be retrieved +# +# @param expected_value +# Expected key value +# +# @param expected_metadata +# Expected key metadata +# +# @param simpkv_options +# Value of the simpkv_options parameter to be used in the simpkv::get +# function call +# +# @param binary +# Whether the key has a binary value +# +define simpkv_test::defines::retrieve_and_verify_key( + Simpkv_test::Key $key, + Any $expected_value, + Variant[Hash,Undef] $expected_metadata, + Hash $simpkv_options, + Boolean $binary +) { + + $_message = "simpkv::get('${key}', ${simpkv_options})" + info("Calling ${_message}") + $_result = simpkv::get($key, $simpkv_options) + simpkv_test::verify_key_data($_result, $expected_value, + $expected_metadata, $binary, $_message) +} diff --git a/spec/support/modules/simpkv_test/manifests/defines/store_key.pp b/spec/support/modules/simpkv_test/manifests/defines/store_key.pp new file mode 100644 index 0000000..8e7a18f --- /dev/null +++ b/spec/support/modules/simpkv_test/manifests/defines/store_key.pp @@ -0,0 +1,25 @@ +# @summary Define that simply calls simpkv::put +# +# @param key +# Name of the key to store +# +# @param value +# Value to store +# +# @param metadata +# Metadata to store +# +# @param simpkv_options +# Value of the simpkv_options parameter to be used in the simpkv::put +# function call +# +define simpkv_test::defines::store_key( + Simpkv_test::Key $key, + NotUndef $value, + Hash $metadata = {}, + Hash $simpkv_options = {} +) { + + info("Calling simpkv::put('${key}', ${value}, ${metadata}, ${simpkv_options})") + simpkv::put($key, $value, $metadata, $simpkv_options) +} diff --git a/spec/support/modules/simpkv_test/manifests/defines/verify_name_exists.pp b/spec/support/modules/simpkv_test/manifests/defines/verify_name_exists.pp new file mode 100644 index 0000000..7f1c997 --- /dev/null +++ b/spec/support/modules/simpkv_test/manifests/defines/verify_name_exists.pp @@ -0,0 +1,26 @@ +# @summary Define that calls simpkv::exists and validates its result +# +# Fails if validation fails. +# +# @param key +# Name of the key/folder whose existence is to be checked +# +# @param simpkv_options +# Value of the simpkv_options parameter to be used in the simpkv::exists +# function call +# +# @param valid +# Whether key/folder should exist +# +# @return [None] +# +define simpkv_test::defines::verify_name_exists( + Simpkv_test::Key $key, + Hash $simpkv_options = {}, + Boolean $valid +) { + $_message = "simpkv::exists('${key}', ${simpkv_options})" + info("Calling ${_message}") + $_key_exists = simpkv::exists($key, $simpkv_options) + simpkv_test::assert_equal($_key_exists, $valid, $_message) +} diff --git a/spec/support/modules/simpkv_test/manifests/delete.pp b/spec/support/modules/simpkv_test/manifests/delete.pp deleted file mode 100644 index d41ee47..0000000 --- a/spec/support/modules/simpkv_test/manifests/delete.pp +++ /dev/null @@ -1,48 +0,0 @@ -# Delete a subset of keys from the backend mapped to an app_id and verify -# only those keys were deleted -class simpkv_test::delete inherits simpkv_test::params -{ - # Delete Puppet env keys without metadata for the specified app_id - $simpkv_test::params::key_value_pairs.each |$key, $value| { - simpkv::delete($key, $simpkv_test::params::simpkv_options) - } - - # Verify Puppet env keys without metadata no longer exist for the specified - # app_id - $simpkv_test::params::key_value_pairs.each |$key, $value| { - simpkv_test::assert_equal( - simpkv::exists($key, $simpkv_test::params::simpkv_options), - false, - "simpkv::exists('${key}', ${simpkv_test::params::simpkv_options})" - ) - } - - # Verify global keys without still exist for the specified app_id - $simpkv_test::params::key_value_pairs.each |$key, $value| { - simpkv_test::assert_equal( - simpkv::exists($key, $simpkv_test::params::simpkv_global_options), - true, - "simpkv::exists('${key}', ${simpkv_test::params::simpkv_global_options})" - ) - } - - # Verify Puppet env keys with metadata still exist for the specified app_id - $simpkv_test::params::key_value_pairs.each |$key, $value| { - simpkv_test::assert_equal( - simpkv::exists("${key}_with_meta", $simpkv_test::params::simpkv_options), - true, - "simpkv::exists('${key}_with_meta', ${simpkv_test::params::simpkv_options})" - ) - } - - # Verify the Puppet env key added in a Puppet function call for the specified - # app_id still exists - simpkv_test::assert_equal( - simpkv::exists( - "${simpkv_test::params::test_keydir}/boolean_from_pfunction", - $simpkv_test::params::simpkv_options - ), - true, - "simpkv::exists('${simpkv_test::params::test_keydir}}/boolean_from_pfunction',${simpkv_test::params::simpkv_options})" - ) -} diff --git a/spec/support/modules/simpkv_test/manifests/deletetree.pp b/spec/support/modules/simpkv_test/manifests/deletetree.pp deleted file mode 100644 index 0950c0d..0000000 --- a/spec/support/modules/simpkv_test/manifests/deletetree.pp +++ /dev/null @@ -1,44 +0,0 @@ -# Delete parent dirs of Puppet env and global keys from the backend mapped to -# an app_id and verify all keys were deleted -class simpkv_test::deletetree inherits simpkv_test::params -{ - # Delete parent dir of global keys for the specified app_id - simpkv::deletetree($simpkv_test::params::test_keydir, $simpkv_test::params::simpkv_global_options) - - # Verify global keys no longer exist for the specified app_id - $simpkv_test::params::key_value_pairs.each |$key, $value| { - simpkv_test::assert_equal( - simpkv::exists($key, $simpkv_test::params::simpkv_global_options), - false, - "simpkv::exists('${key}', ${simpkv_test::params::simpkv_global_options})" - ) - } - - # Delete parent dir of Puppet env keys for the specified app_id - simpkv::deletetree($simpkv_test::params::test_keydir, $simpkv_test::params::simpkv_options) - - # Verify Puppet env keys with and without metadata no longer exist for the specified app_id - $simpkv_test::params::key_value_pairs.each |$key, $value| { - simpkv_test::assert_equal( - simpkv::exists($key, $simpkv_test::params::simpkv_options), - false, - "simpkv::exists('${key}', ${simpkv_test::params::simpkv_options})" - ) - - simpkv_test::assert_equal( - simpkv::exists("${key}_with_meta", $simpkv_test::params::simpkv_options), - false, - "simpkv::exists('${key}_with_meta', ${simpkv_test::params::simpkv_options})" - ) - } - - # Verify the key added in own Puppet function call for the specified app_id no longer exists - simpkv_test::assert_equal( - simpkv::exists( - "${simpkv_test::params::test_keydir}/boolean_from_pfunction", - $simpkv_test::params::simpkv_options - ), - false, - "simpkv::exists('${simpkv_test::params::test_keydir}}/boolean_from_pfunction',${simpkv_test::params::simpkv_options})" - ) -} diff --git a/spec/support/modules/simpkv_test/manifests/exists.pp b/spec/support/modules/simpkv_test/manifests/exists.pp deleted file mode 100644 index 782b53b..0000000 --- a/spec/support/modules/simpkv_test/manifests/exists.pp +++ /dev/null @@ -1,55 +0,0 @@ -# Check for the existance of keys stored via the simpkv_test::put Class -# -# FIXME: Not checking keys from simpkv_test::defines::put Defines -# -class simpkv_test::exists inherits simpkv_test::params -{ - # Check for keys with and without metadata for the specified app_id - $simpkv_test::params::key_value_pairs.each |$key, $value| { - # Puppet env keys without metadata - simpkv_test::assert_equal( - simpkv::exists($key, $simpkv_test::params::simpkv_options), - true, - "simpkv::exists('${key}', ${simpkv_test::params::simpkv_options})" - ) - - # Puppet env keys witht metadata - simpkv_test::assert_equal( - simpkv::exists("${key}_with_meta", $simpkv_test::params::simpkv_options), - true, - "simpkv::exists('${key}_with_meta', ${simpkv_test::params::simpkv_options})" - ) - - # global keys without metadata - simpkv_test::assert_equal( - simpkv::exists("${key}", $simpkv_test::params::simpkv_global_options), - true, - "simpkv::exists('${key}_with_meta', ${simpkv_test::params::simpkv_global_options})" - ) - } - - - # Check for the Puppet env key added in a Puppet function call for the - # specified app_id. - simpkv_test::assert_equal( - simpkv::exists( - "${simpkv_test::params::test_keydir}/boolean_from_pfunction", - $simpkv_test::params::simpkv_options - ), - true, - "simpkv::exists('${simpkv_test::params::test_keydir}}/boolean_from_pfunction', ${simpkv_test::params::simpkv_options})" - ) - - # Check for the Puppet env key added in a Puppet function call without the - # specified app_id. Should be in default backend but not the backend for the - # app_id. - $_empty_simpkv_options = {} - simpkv_test::assert_equal( - simpkv::exists( - "${simpkv_test::params::test_keydir}/boolean_from_pfunction_no_app_id", - $_empty_simpkv_options - ), - true, - "simpkv::exists('${simpkv_test::params::test_keydir}}/boolean_from_pfunction_no_appid')" - ) -} diff --git a/spec/support/modules/simpkv_test/manifests/get.pp b/spec/support/modules/simpkv_test/manifests/get.pp deleted file mode 100644 index 252476f..0000000 --- a/spec/support/modules/simpkv_test/manifests/get.pp +++ /dev/null @@ -1,36 +0,0 @@ -class simpkv_test::get inherits simpkv_test::params -{ - $_empty_test_meta = {} - $simpkv_test::params::key_value_pairs.each |$key, $value| { - # Get and verify Puppet env keys without metadata for the specified app_id - simpkv_test::assert_equal( - simpkv::get($key, $simpkv_test::params::simpkv_options), - { 'value' => $value }, - "simpkv::get('${key}', ${simpkv_test::params::simpkv_options})" - ) - - # Get and verify global keys without metadata for the specified app_id - simpkv_test::assert_equal( - simpkv::get($key, $simpkv_test::params::simpkv_global_options), - { 'value' => $value }, - "simpkv::get('${key}', ${simpkv_test::params::simpkv_global_options})" - ) - - # Get and verify Puppet env keys with metadata for the specified app_id - simpkv_test::assert_equal( - simpkv::get("${key}_with_meta", $simpkv_test::params::simpkv_options), - { 'value' => $value, 'metadata' => $simpkv_test::params::test_meta }, - "simpkv::get('${key}_with_meta',${simpkv_test::params::simpkv_options})" - ) - } - - # Get key added in own Puppet function call for the specified app_id - simpkv_test::assert_equal( - simpkv::get( - "${simpkv_test::params::test_keydir}/boolean_from_pfunction", - $simpkv_test::params::simpkv_options - ), - { 'value' => $simpkv_test::params::test_bool }, - "simpkv::get('${simpkv_test::params::test_keydir}/boolean_from_pfunction',${simpkv_test::params::simpkv_options})" - ) -} diff --git a/spec/support/modules/simpkv_test/manifests/list.pp b/spec/support/modules/simpkv_test/manifests/list.pp deleted file mode 100644 index e838c25..0000000 --- a/spec/support/modules/simpkv_test/manifests/list.pp +++ /dev/null @@ -1,79 +0,0 @@ -# List most of the keys/folders stored via the simpkv_test::put Class -# -# FIXME: -# - Not checking for keys without an app_id from simpkv_test::put -# - Not checking keys from simpkv_test::defines::put Defines -class simpkv_test::list inherits simpkv_test::params -{ - $_expected_env = { - 'keys' => { - basename($simpkv_test::params::test_bool_key) => { 'value' => $simpkv_test::params::test_bool }, - basename($simpkv_test::params::test_string_key) => { 'value' => $simpkv_test::params::test_string }, - basename($simpkv_test::params::test_integer_key) => { 'value' => $simpkv_test::params::test_integer }, - basename($simpkv_test::params::test_float_key) => { 'value' => $simpkv_test::params::test_float }, - basename($simpkv_test::params::test_array_strings_key) => { 'value' => $simpkv_test::params::test_array_strings }, - basename($simpkv_test::params::test_array_integers_key) => { 'value' => $simpkv_test::params::test_array_integers }, - basename($simpkv_test::params::test_hash_key) => { 'value' => $simpkv_test::params::test_hash }, - - basename("${simpkv_test::params::test_bool_key}_with_meta") => { 'value' => $simpkv_test::params::test_bool, 'metadata' => $simpkv_test::params::test_meta }, - basename("${simpkv_test::params::test_string_key}_with_meta") => { 'value' => $simpkv_test::params::test_string, 'metadata' => $simpkv_test::params::test_meta }, - basename("${simpkv_test::params::test_integer_key}_with_meta") => { 'value' => $simpkv_test::params::test_integer, 'metadata' => $simpkv_test::params::test_meta }, - basename("${simpkv_test::params::test_float_key}_with_meta") => { 'value' => $simpkv_test::params::test_float, 'metadata' => $simpkv_test::params::test_meta }, - basename("${simpkv_test::params::test_array_strings_key}_with_meta") => { 'value' => $simpkv_test::params::test_array_strings, 'metadata' => $simpkv_test::params::test_meta }, - basename("${simpkv_test::params::test_array_integers_key}_with_meta") => { 'value' => $simpkv_test::params::test_array_integers, 'metadata' => $simpkv_test::params::test_meta }, - basename("${simpkv_test::params::test_hash_key}_with_meta") => { 'value' => $simpkv_test::params::test_hash, 'metadata' => $simpkv_test::params::test_meta }, - - 'boolean_from_pfunction' => { 'value' => $simpkv_test::params::test_bool } - }, - 'folders' => [] - } - - simpkv_test::assert_equal( - simpkv::list($simpkv_test::params::test_keydir, $simpkv_test::params::simpkv_options), - $_expected_env, - "simpkv::list('${simpkv_test::params::test_keydir}', ${simpkv_test::params::simpkv_options})" - ) - - $_expected_global = { - 'keys' => { - basename($simpkv_test::params::test_bool_key) => { 'value' => $simpkv_test::params::test_bool }, - basename($simpkv_test::params::test_string_key) => { 'value' => $simpkv_test::params::test_string }, - basename($simpkv_test::params::test_integer_key) => { 'value' => $simpkv_test::params::test_integer }, - basename($simpkv_test::params::test_float_key) => { 'value' => $simpkv_test::params::test_float }, - basename($simpkv_test::params::test_array_strings_key) => { 'value' => $simpkv_test::params::test_array_strings }, - basename($simpkv_test::params::test_array_integers_key) => { 'value' => $simpkv_test::params::test_array_integers }, - basename($simpkv_test::params::test_hash_key) => { 'value' => $simpkv_test::params::test_hash } - }, - 'folders' => [] - } - - simpkv_test::assert_equal( - simpkv::list($simpkv_test::params::test_keydir, $simpkv_test::params::simpkv_global_options), - $_expected_global, - "simpkv::list('${simpkv_test::params::test_keydir}', ${simpkv_test::params::simpkv_global_options})" - ) - - # top level list for the Puppet env of the simpkv backend specified by - # $simpkv_test::params::simpkv_options - simpkv_test::assert_equal( - simpkv::list('/', $simpkv_test::params::simpkv_options), - {keys => {}, folders => [ $simpkv_test::params::test_keydir ]}, - "simpkv::list('/', ${simpkv_test::params::simpkv_options})" - ) - - # top level list for global keys of the simpkv backend specified by - # $simpkv_test::params::simpkv_options - simpkv_test::assert_equal( - simpkv::list('/', $simpkv_test::params::simpkv_global_options), - {keys => {}, folders => [ $simpkv_test::params::test_keydir ]}, - "simpkv::list('/', ${simpkv_test::params::simpkv_global_options})" - ) - - # top level list for global keys for default backend - $_default_global_options = { 'global' => true } - simpkv_test::assert_equal( - simpkv::list('/', $_default_global_options), - {keys => {}, folders => []}, - "simpkv::list('/', ${_default_global_options})" - ) -} diff --git a/spec/support/modules/simpkv_test/manifests/params.pp b/spec/support/modules/simpkv_test/manifests/params.pp deleted file mode 100644 index 717e95f..0000000 --- a/spec/support/modules/simpkv_test/manifests/params.pp +++ /dev/null @@ -1,33 +0,0 @@ -# This class sets key/value parameters used in simpkv_test manifests. -class simpkv_test::params ( - String $test_keydir = 'from_class', - String $test_bool_key = "${test_keydir}/boolean", - String $test_string_key = "${test_keydir}/string", - String $test_integer_key = "${test_keydir}/integer", - String $test_float_key = "${test_keydir}/float", - String $test_array_strings_key = "${test_keydir}/array_strings", - String $test_array_integers_key = "${test_keydir}/array_integers", - String $test_hash_key = "${test_keydir}/hash", - - Boolean $test_bool = true, - String $test_string = 'string1', - Integer $test_integer = 123, - Float $test_float = 4.567, - Array $test_array_strings = ['string2', 'string3' ], - Array[Integer] $test_array_integers = [ 8, 9, 10], - Hash $test_hash = { 'key1' => 'string4', 'key2' => 11, - 'key3' => false, 'key4' => { 'nkey1' => 'string5', 'nkey2' => true, 'nkey3' => 12 } }, - - Hash $key_value_pairs = { $test_bool_key => $test_bool, - $test_string_key => $test_string, - $test_integer_key => $test_integer, - $test_float_key => $test_float, - $test_array_strings_key => $test_array_strings, - $test_array_integers_key => $test_array_integers, - $test_hash_key => $test_hash }, - - Hash $test_meta = { 'some' => 'metadata' }, - String $app_id = 'simpkv_test_class', - Hash $simpkv_options = { 'app_id' => $app_id }, - Hash $simpkv_global_options = { 'app_id' => $app_id, 'global' => true } -) { } diff --git a/spec/support/modules/simpkv_test/manifests/put.pp b/spec/support/modules/simpkv_test/manifests/put.pp deleted file mode 100644 index 66fd270..0000000 --- a/spec/support/modules/simpkv_test/manifests/put.pp +++ /dev/null @@ -1,45 +0,0 @@ -class simpkv_test::put inherits simpkv_test::params -{ - $_empty_test_meta = {} - $simpkv_test::params::key_value_pairs.each |$key, $value| { - # Add Puppet env keys without metadata for the specified app_id - simpkv::put( - $key, - $value, - $_empty_test_meta, - $simpkv_test::params::simpkv_options - ) - - # Add Puppet env keys with metadata for the specified app_id - simpkv::put( - "${key}_with_meta", - $value, - $simpkv_test::params::test_meta, - $simpkv_test::params::simpkv_options - ) - - # Add global env keys without metadata for the specified app_id - simpkv::put( - $key, - $value, - $_empty_test_meta, - $simpkv_test::params::simpkv_global_options - ) - } - - # Add Puppet env key within a Puppet function call for the specified app_id. - simpkv_test::put_pwrapper( - "${simpkv_test::params::test_keydir}/boolean_from_pfunction", - $simpkv_test::params::test_bool, - $simpkv_test::params::simpkv_options - ) - - # Add Puppet env key within a Puppet function call but without the app_id. - # This key will be stored in the default backend. - $_empty_simpkv_options = {} - simpkv_test::put_pwrapper( - "${simpkv_test::params::test_keydir}/boolean_from_pfunction_no_app_id", - $simpkv_test::params::test_bool, - $_empty_simpkv_options - ) -} diff --git a/spec/support/modules/simpkv_test/manifests/remove_folders.pp b/spec/support/modules/simpkv_test/manifests/remove_folders.pp new file mode 100644 index 0000000..e12ad77 --- /dev/null +++ b/spec/support/modules/simpkv_test/manifests/remove_folders.pp @@ -0,0 +1,34 @@ +# @summary Remove folders using simpkv::deletetree +# +# @param foldername_info +# Info specifying the names of the folders to remove +# +class simpkv_test::remove_folders ( + Simpkv_test::NameInfo $foldername_info +) { + + $foldername_info.each |$app_id, $folder_struct| { + $folder_struct.each |$folder_type, $foldernames| { + $_simpkv_options = simpkv_test::simpkv_options($app_id, $folder_type) + + $foldernames.each |$folder| { + $_unique_id = "${app_id}_${folder_type}_${folder}" + case simpkv_test::code_source($_unique_id) { + 'class': { + info("Calling simpkv::deletetree('${folder}', ${_simpkv_options})") + simpkv::deletetree($folder, $_simpkv_options) + } + 'define': { + simpkv_test::defines::remove_folder { $_unique_id: + folder => $folder, + simpkv_options => $_simpkv_options + } + } + 'puppet_function': { + simpkv_test::puppet_functions::remove_folder($folder, $_simpkv_options) + } + } + } + } + } +} diff --git a/spec/support/modules/simpkv_test/manifests/remove_keys.pp b/spec/support/modules/simpkv_test/manifests/remove_keys.pp new file mode 100644 index 0000000..df2363e --- /dev/null +++ b/spec/support/modules/simpkv_test/manifests/remove_keys.pp @@ -0,0 +1,34 @@ +# @summary Remove keys using simpkv::delete +# +# @param keyname_info +# Info specifying the names of keys to remove +# +class simpkv_test::remove_keys ( + Simpkv_test::NameInfo $keyname_info +) { + + $keyname_info.each |$app_id, $key_struct| { + $key_struct.each |$key_type, $keynames| { + $_simpkv_options = simpkv_test::simpkv_options($app_id, $key_type) + + $keynames.each |$key| { + $_unique_id = "${app_id}_${key_type}_${key}" + case simpkv_test::code_source($_unique_id) { + 'class': { + info("Calling simpkv::delete('${key}', ${_simpkv_options})") + simpkv::delete($key, $_simpkv_options) + } + 'define': { + simpkv_test::defines::remove_key { $_unique_id: + key => $key, + simpkv_options => $_simpkv_options + } + } + 'puppet_function': { + simpkv_test::puppet_functions::remove_key($key, $_simpkv_options) + } + } + } + } + } +} diff --git a/spec/support/modules/simpkv_test/manifests/retrieve_and_verify_folders.pp b/spec/support/modules/simpkv_test/manifests/retrieve_and_verify_folders.pp new file mode 100644 index 0000000..a862046 --- /dev/null +++ b/spec/support/modules/simpkv_test/manifests/retrieve_and_verify_folders.pp @@ -0,0 +1,83 @@ +# @summary Retrieve folder lists with simpkv::list and verify the result +# +# @param valid_folder_info +# Info specifying folders that are expected to be present in the +# keystore and their contents +# +# @param invalid_folder_info +# Info specifying folders that are not expected to be present in +# the keystore +# +class simpkv_test::retrieve_and_verify_folders ( + Simpkv_test::FolderInfo $valid_folder_info, + Simpkv_test::FolderInfo $invalid_folder_info +) { + $valid_folder_info.each |$app_id, $folder_struct| { + $folder_struct.each |$folder_type, $folders| { + $_simpkv_options = simpkv_test::simpkv_options($app_id, $folder_type) + + $folders.each |$folder, $folder_data| { + $_expected_keys = pick($folder_data['keys'], {}) + $_expected_folders = pick($folder_data['folders'], []) + $_unique_id = "${app_id}_${folder_type}_${folder}" + case simpkv_test::code_source($_unique_id) { + 'class': { + $_message = "simpkv::list('${folder}', ${_simpkv_options})" + info("Calling ${_message}") + $_result = simpkv::list($folder, $_simpkv_options) + simpkv_test::verify_folder_data($_result, $_expected_keys, + $_expected_folders, $_message) + } + 'define': { + simpkv_test::defines::retrieve_and_verify_folder { $_unique_id: + folder => $folder, + expected_keys => $_expected_keys, + expected_folders => $_expected_folders, + simpkv_options => $_simpkv_options + } + } + 'puppet_function': { + simpkv_test::puppet_functions::retrieve_and_verify_folder($folder, + $_expected_keys, $_expected_folders, $_simpkv_options) + } + } + } + } + } + + $invalid_folder_info.each |$app_id, $folder_struct| { + $folder_struct.each |$folder_type, $folders| { + # Enable 'softfail', so failure returns Undef instead of failing catalog + # compilation + $_simpkv_options = simpkv_test::simpkv_options($app_id, $folder_type, + { 'softfail' => true }) + + $folders.each |$folder, $folder_data| { + $_expected_keys = undef + $_expected_folders = undef + $_unique_id = "${app_id}_${folder_type}_${folder}" + case simpkv_test::code_source($_unique_id) { + 'class': { + $_message = "simpkv::list('${folder}', ${_simpkv_options})" + info("Calling ${_message}") + $_result = simpkv::list($folder, $_simpkv_options) + simpkv_test::verify_folder_data( $_result, $_expected_keys, + $_expected_folders, $_message) + } + 'define': { + simpkv_test::defines::retrieve_and_verify_folder { $_unique_id: + folder => $folder, + expected_keys => $_expected_keys, + expected_folders => $_expected_folders, + simpkv_options => $_simpkv_options + } + } + 'puppet_function': { + simpkv_test::puppet_functions::retrieve_and_verify_folder( + $folder, $_expected_keys, $_expected_folders, $_simpkv_options) + } + } + } + } + } +} diff --git a/spec/support/modules/simpkv_test/manifests/retrieve_and_verify_keys.pp b/spec/support/modules/simpkv_test/manifests/retrieve_and_verify_keys.pp new file mode 100644 index 0000000..f599708 --- /dev/null +++ b/spec/support/modules/simpkv_test/manifests/retrieve_and_verify_keys.pp @@ -0,0 +1,95 @@ +# @summary Retrieve keys with simpkv::get and verifies the results +# +# @param valid_key_info +# Info specifying keys that are expected to be present in the +# keystore and their stored data +# +# @param invalid_key_info +# Info specifying keys that are not expected to be present in the +# keystore +# +class simpkv_test::retrieve_and_verify_keys ( + Simpkv_test::KeyInfo $valid_key_info, + Simpkv_test::KeyInfo $invalid_key_info +) { + + $valid_key_info.each |$app_id, $key_struct| { + $key_struct.each |$key_type, $keys| { + $_simpkv_options = simpkv_test::simpkv_options($app_id, $key_type) + + $keys.each |$key, $key_data| { + $_expected_value = simpkv_test::key_value($key_data) + if $_expected_value =~ Undef { + warning("Skipping '${app_id}' '${key_type}' key '${key}': Value not found in << ${key_data} >>") + next + } + + $_binary = ($_expected_value =~ Binary) + $_expected_metadata = $key_data['metadata'] + + $_unique_id = "${app_id}_${key_type}_${key}" + case simpkv_test::code_source($_unique_id) { + 'class': { + $_message = "simpkv::get('${key}', ${_simpkv_options})" + info("Calling ${_message}") + $_result = simpkv::get($key, $_simpkv_options) + simpkv_test::verify_key_data($_result, $_expected_value, + $_expected_metadata, $_binary, $_message) + } + 'define': { + simpkv_test::defines::retrieve_and_verify_key { $_unique_id: + key => $key, + expected_value => $_expected_value, + expected_metadata => $_expected_metadata, + simpkv_options => $_simpkv_options, + binary => $_binary + } + } + 'puppet_function': { + simpkv_test::puppet_functions::retrieve_and_verify_key($key, + $_expected_value, $_expected_metadata, $_simpkv_options, $_binary) + } + } + } + } + } + + $invalid_key_info.each |$app_id, $key_struct| { + $key_struct.each |$key_type, $keys| { + # Enable 'softfail', so failure returns Undef instead of failing catalog + # compilation + $_simpkv_options = simpkv_test::simpkv_options($app_id, $key_type, + { 'softfail' => true }) + + $keys.each |$key, $key_data| { + $_expected_value = undef + $_expected_metadata = undef + $_binary = false # value doesn't matter + + $_unique_id = "${app_id}_${key_type}_${key}" + case simpkv_test::code_source($_unique_id) { + 'class': { + $_message = "simpkv::get('${key}', ${_simpkv_options})" + info("Calling ${_message}") + $_result = simpkv::get($key, $_simpkv_options) + simpkv_test::verify_key_data($_result, $_expected_value, + $_expected_metadata, $_binary, $_message) + } + 'define': { + simpkv_test::defines::retrieve_and_verify_key { $_unique_id: + key => $key, + expected_value => $_expected_value, + expected_metadata => $_expected_metadata, + simpkv_options => $_simpkv_options, + binary => $_binary + } + } + 'puppet_function': { + simpkv_test::puppet_functions::retrieve_and_verify_key($key, + $_expected_value, $_expected_metadata, $_simpkv_options, $_binary) + } + } + } + } + } +} diff --git a/spec/support/modules/simpkv_test/manifests/store_keys.pp b/spec/support/modules/simpkv_test/manifests/store_keys.pp new file mode 100644 index 0000000..2753b76 --- /dev/null +++ b/spec/support/modules/simpkv_test/manifests/store_keys.pp @@ -0,0 +1,44 @@ +# @summary Store keys using simpkv::put +# +# @param key_info +# Info specifying the key names and data to be stored +# +class simpkv_test::store_keys ( + Simpkv_test::KeyInfo $key_info +) { + + $key_info.each |$app_id, $key_struct| { + $key_struct.each |$key_type, $keys| { + $_simpkv_options = simpkv_test::simpkv_options($app_id, $key_type) + + $keys.each |$key, $key_data| { + $_value = simpkv_test::key_value($key_data) + if $_value =~ Undef { + warning("Skipping '${app_id}' '${key_type}' key '${key}': Value not found in << ${key_data} >>") + next + } + + $_metadata = pick($key_data['metadata'], {}) + $_unique_id = "${app_id}_${key_type}_${key}" + case simpkv_test::code_source($_unique_id) { + 'class': { + info("Calling simpkv::put('${key}', ${_value}, ${_metadata}, ${_simpkv_options})") + simpkv::put($key, $_value, $_metadata, $_simpkv_options) + } + 'define': { + simpkv_test::defines::store_key { $_unique_id: + key => $key, + value => $_value, + metadata => $_metadata, + simpkv_options => $_simpkv_options + } + } + 'puppet_function': { + simpkv_test::puppet_functions::store_key($key, $_value, $_metadata, + $_simpkv_options) + } + } + } + } + } +} diff --git a/spec/support/modules/simpkv_test/manifests/verify_folders_exist.pp b/spec/support/modules/simpkv_test/manifests/verify_folders_exist.pp new file mode 100644 index 0000000..312e281 --- /dev/null +++ b/spec/support/modules/simpkv_test/manifests/verify_folders_exist.pp @@ -0,0 +1,51 @@ +# @summary Check for the existence of folders using simpkv::exists +# +# @param valid_foldername_info +# Info specifying names of folder that are expected to be present in the +# keystore +# +# @param invalid_foldername_info +# Info specifying names of folder that are not expected to be present in +# the keystore +# +class simpkv_test::verify_folders_exist ( + Simpkv_test::NameInfo $valid_foldername_info, + Simpkv_test::NameInfo $invalid_foldername_info +) { + + $_folders_to_check = { + true => $valid_foldername_info, + false => $invalid_foldername_info + } + + $_folders_to_check.each |$valid, $folder_info| { + $folder_info.each |$app_id, $folder_struct| { + $folder_struct.each |$folder_type, $foldernames| { + $_simpkv_options = simpkv_test::simpkv_options($app_id, $folder_type) + + $foldernames.each |$folder| { + $_unique_id = "${app_id}_${folder_type}_${folder}" + case simpkv_test::code_source($_unique_id) { + 'class': { + $_message = "simpkv::exists('${folder}', ${_simpkv_options})" + info("Calling ${_message}") + $_folder_exists = simpkv::exists($folder, $_simpkv_options) + simpkv_test::assert_equal($_folder_exists, $valid, $_message) + } + 'define': { + simpkv_test::defines::verify_name_exists{ $_unique_id: + key => $folder, + simpkv_options => $_simpkv_options, + valid => $valid + } + } + 'puppet_function': { + simpkv_test::puppet_functions::verify_name_exists($folder, + $_simpkv_options, $valid) + } + } + } + } + } + } +} diff --git a/spec/support/modules/simpkv_test/manifests/verify_keys_exist.pp b/spec/support/modules/simpkv_test/manifests/verify_keys_exist.pp new file mode 100644 index 0000000..1c96cb9 --- /dev/null +++ b/spec/support/modules/simpkv_test/manifests/verify_keys_exist.pp @@ -0,0 +1,51 @@ +# @summary Check for the existence of keys using simpkv::exists +# +# @param valid_keyname_info +# Info specifying names of keys that are expected to be present in the +# keystore +# +# @param invalid_keyname_info +# Info specifying names of keys that are not expected to be present in +# the keystore +# +class simpkv_test::verify_keys_exist ( + Simpkv_test::NameInfo $valid_keyname_info, + Simpkv_test::NameInfo $invalid_keyname_info +) { + + $_keys_to_check = { + true => $valid_keyname_info, + false => $invalid_keyname_info + } + + $_keys_to_check.each |$valid, $key_info| { + $key_info.each |$app_id, $key_struct| { + $key_struct.each |$key_type, $keynames| { + $_simpkv_options = simpkv_test::simpkv_options($app_id, $key_type) + + $keynames.each |$key| { + $_unique_id = "${app_id}_${key_type}_${key}" + case simpkv_test::code_source($_unique_id) { + 'class': { + $_message = "simpkv::exists('${key}', ${_simpkv_options})" + info("Calling ${_message}") + $_key_exists = simpkv::exists($key, $_simpkv_options) + simpkv_test::assert_equal( $_key_exists, $valid, $_message) + } + 'define': { + simpkv_test::defines::verify_name_exists{ $_unique_id: + key => $key, + simpkv_options => $_simpkv_options, + valid => $valid + } + } + 'puppet_function': { + simpkv_test::puppet_functions::verify_name_exists($key, + $_simpkv_options, $valid) + } + } + } + } + } + } +} diff --git a/spec/support/modules/simpkv_test/metadata.json b/spec/support/modules/simpkv_test/metadata.json index 964388d..021a2ac 100644 --- a/spec/support/modules/simpkv_test/metadata.json +++ b/spec/support/modules/simpkv_test/metadata.json @@ -1,8 +1,8 @@ { "name": "simp-simpkv_test", - "version": "1.0.0", + "version": "2.0.0", "author": "simp", - "summary": "test manifests for simpkv plugin testing", + "summary": "test manifests for simp kv testing", "license": "Apache-2.0", "source": "https://github.com/simp/pupmod-simp-simpkv", "project_page": "https://github.com/simp/pupmod-simp-simpkv", @@ -10,34 +10,22 @@ "tags": [], "dependencies": [ { - "name": "simp/simpkv", - "version_requirement": ">= 0.7.0" + "name": "puppetlabs/stdlib", + "version_requirement": ">= 4.9.0" }, { - "name": "simp/simplib", - "version_requirement": ">= 4.0.0 < 5.0.0" - } - ], - "operatingsystem_support": [ - { - "operatingsystem": "CentOS", - "operatingsystemrelease": [ - "6", - "7" - ] + "name": "simp/simpkv", + "version_requirement": ">= 0.8.0" }, { - "operatingsystem": "RedHat", - "operatingsystemrelease": [ - "6", - "7" - ] + "name": "simp/simplib", + "version_requirement": ">= 4.0.0" } ], "requirements": [ { "name": "puppet", - "version_requirement": ">= 5.0.0 < 7.0.0" + "version_requirement": ">= 6.5.0" } ] } diff --git a/spec/support/modules/simpkv_test/types/appid.pp b/spec/support/modules/simpkv_test/types/appid.pp new file mode 100644 index 0000000..e5d7ea8 --- /dev/null +++ b/spec/support/modules/simpkv_test/types/appid.pp @@ -0,0 +1,3 @@ +# String used as the `app_id` attribute of the `simpkv_options` parameter in +# a simpkv function call +type Simpkv_test::AppId = String diff --git a/spec/support/modules/simpkv_test/types/folderdata.pp b/spec/support/modules/simpkv_test/types/folderdata.pp new file mode 100644 index 0000000..6275359 --- /dev/null +++ b/spec/support/modules/simpkv_test/types/folderdata.pp @@ -0,0 +1,10 @@ +# Information about an individual folder in a keystore +type Simpkv_test::FolderData = Struct[{ + # Info about keys in the directory + # - Currently restricted to keys with non-binary data because of + # test manifest limitations + Optional[keys] => Hash[Simpkv_test::Key,Simpkv_test::NonBinaryKeyData], + + # List of subfolder names + Optional[folders] => Array[String[1]] +}] diff --git a/spec/support/modules/simpkv_test/types/folderinfo.pp b/spec/support/modules/simpkv_test/types/folderinfo.pp new file mode 100644 index 0000000..c266012 --- /dev/null +++ b/spec/support/modules/simpkv_test/types/folderinfo.pp @@ -0,0 +1,31 @@ +# Data structure specifying folder information +# +# Folders are unique based on 3 attributes: +# 1. The backend in which they are stored +# 2. Whether they are tied to a Puppet environment or global +# 3. The folder names (each of which may include a relative path) +# +# The grouping below was chosen to ensure uniqueness for test folders, +# **ASSUMING**, backends are uniquely mapped to the `app_id` attribute that +# will be used in the `simpkv_options` parameter of each simpkv function call. +# +# If you are mapping multiple `app_id` values to the same backend in a test, +# be sure you don't have any folders that will resolve to the same storage +# location! +# +type Simpkv_test::FolderInfo = Hash[ + + # When not empty, used to set the 'app_id' attribute of the `simpkv_options` + # parameter of each simpkv function call + Simpkv_test::AppId, + + Struct[{ + # - Any folder in 'env' is a folder tied to the Puppet environment. + # - Any folder in 'global' is a global folder. + # - For these folders, the 'global' attribute of the `simpkv_options` + # parameter of each simpkv function call will be automatically set + # to `true`. + Optional[env] => Simpkv_test::Folders, + Optional[global] => Simpkv_test::Folders + }] +] diff --git a/spec/support/modules/simpkv_test/types/folders.pp b/spec/support/modules/simpkv_test/types/folders.pp new file mode 100644 index 0000000..34a6e3d --- /dev/null +++ b/spec/support/modules/simpkv_test/types/folders.pp @@ -0,0 +1,2 @@ +# Data structure specifying folder listings +type Simpkv_test::Folders = Hash[Simpkv_test::Key, Simpkv_test::FolderData] diff --git a/spec/support/modules/simpkv_test/types/key.pp b/spec/support/modules/simpkv_test/types/key.pp new file mode 100644 index 0000000..b65396e --- /dev/null +++ b/spec/support/modules/simpkv_test/types/key.pp @@ -0,0 +1,5 @@ +# Key or folder name +# +# The regex is not perfect (doesn't catch sequences that look +# like relative paths), but sufficient for this test module. +type Simpkv_test::Key = Pattern['^[a-z0-9._:\-\/]+$'] diff --git a/spec/support/modules/simpkv_test/types/keydata.pp b/spec/support/modules/simpkv_test/types/keydata.pp new file mode 100644 index 0000000..12b9f1e --- /dev/null +++ b/spec/support/modules/simpkv_test/types/keydata.pp @@ -0,0 +1,18 @@ +# Information about an individual key in a keystore +type Simpkv_test::KeyData = Struct[{ + # Either 'value' or 'file' needs to be set. + # If both are set, 'value' will be used over 'file'. + # If neither are set, the Simpkv_test::KeyData instance will be skipped. + + # Non-binary value + Optional[value] => NotUndef, + + # File containing binary value + # - argument to binary_file, which is an absolute path or + # / string referencing a module file + Optional[file] => String[1], + + # Optional metadata stored with the value + Optional[metadata] => Hash +}] + diff --git a/spec/support/modules/simpkv_test/types/keyinfo.pp b/spec/support/modules/simpkv_test/types/keyinfo.pp new file mode 100644 index 0000000..6ceee85 --- /dev/null +++ b/spec/support/modules/simpkv_test/types/keyinfo.pp @@ -0,0 +1,32 @@ +# Data structure specifying key information +# +# Keys are unique based on 3 attributes: +# 1. The backend in which they are stored +# 2. Whether they are tied to a Puppet environment or global +# 3. The key names (each of which may include a relative folder path) +# +# The grouping below was chosen to ensure uniqueness for test keys, +# **ASSUMING**, backends are uniquely mapped to the `app_id` attribute that +# will be used in the `simpkv_options` parameter of each simpkv function call. +# +# If you are mapping multiple `app_id` values to the same backend in a test, +# be sure you don't have any keys that will resolve to the same storage +# location! +# +type Simpkv_test::KeyInfo = Hash[ + + # When not empty, used to set the 'app_id' attribute of the `simpkv_options` + # parameter of each simpkv function call + Simpkv_test::AppId, + + Struct[{ + # - Any key in 'env' is a key tied to the Puppet environment. + # - Any key in 'global' is a global key. + # - For these keys, the 'global' attribute of the `simpkv_options` + # parameter of each simpkv function call will be automatically set + # to `true`. + Optional[env] => Simpkv_test::Keys, + Optional[global] => Simpkv_test::Keys + }] +] + diff --git a/spec/support/modules/simpkv_test/types/keys.pp b/spec/support/modules/simpkv_test/types/keys.pp new file mode 100644 index 0000000..673d0bf --- /dev/null +++ b/spec/support/modules/simpkv_test/types/keys.pp @@ -0,0 +1,2 @@ +# Data structure specifying key/value pairs +type Simpkv_test::Keys = Hash[Simpkv_test::Key, Simpkv_test::KeyData] diff --git a/spec/support/modules/simpkv_test/types/nameinfo.pp b/spec/support/modules/simpkv_test/types/nameinfo.pp new file mode 100644 index 0000000..ccfc42f --- /dev/null +++ b/spec/support/modules/simpkv_test/types/nameinfo.pp @@ -0,0 +1,32 @@ +# Data structure specifying simply key/folder names +# +# Key/folder names are unique based on 3 attributes: +# 1. The backend in which they are stored +# 2. Whether they are tied to a Puppet environment or global +# 3. The key/folder names (each of which may include a relative folder path) +# +# The grouping below was chosen to ensure uniqueness for test key/folder names, +# **ASSUMING**, backends are uniquely mapped to the `app_id` attribute that +# will be used in the `simpkv_options` parameter of each simpkv function call. +# +# If you are mapping multiple `app_id` values to the same backend in a test, +# be sure you don't have any keys/folders that will resolve to the same storage +# location! +# +type Simpkv_test::NameInfo = Hash[ + + # When not empty, used to set the 'app_id' attribute of the `simpkv_options` + # parameter of each simpkv function call + Simpkv_test::AppId, + + Struct[{ + # - Any key/folder in 'env' is tied to the Puppet environment. + # - Any key/folder in 'global' is global + # - For these entities, the 'global' attribute of the `simpkv_options` + # parameter of each simpkv function call will be automatically set + # to `true`. + Optional[env] => Array[Simpkv_test::Key], + Optional[global] => Array[Simpkv_test::Key] + }] +] + diff --git a/spec/support/modules/simpkv_test/types/nonbinarykeydata.pp b/spec/support/modules/simpkv_test/types/nonbinarykeydata.pp new file mode 100644 index 0000000..fa308dd --- /dev/null +++ b/spec/support/modules/simpkv_test/types/nonbinarykeydata.pp @@ -0,0 +1,9 @@ +# Information about an individual non-binary key in a keystore +type Simpkv_test::NonBinaryKeyData = Struct[{ + # Non-binary value + value => NotUndef, + + # Optional metadata stored with the value + Optional[metadata] => Hash +}] +