diff --git a/.fixtures.yml b/.fixtures.yml new file mode 100644 index 0000000..2412ccc --- /dev/null +++ b/.fixtures.yml @@ -0,0 +1,8 @@ +--- +fixtures: + repositories: + concat: https://github.com/simp/puppetlabs-concat + inifile: https://github.com/simp/puppetlabs-inifile + polkit: https://github.com/simp/pupmod-simp-polkit + simplib: https://github.com/simp/pupmod-simp-simplib + stdlib: https://github.com/simp/puppetlabs-stdlib diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3ee72d0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +.*.sw? +.yardoc +dist/ +pkg/ +spec/fixtures/ +spec/rp_env/ +!/spec/hieradata/default.yaml +!/spec/fixtures/site.pp +.rspec_system +.vagrant/ +.bundle/ +Gemfile.lock +vendor/ +junit/ +log/ +doc/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..7047fda --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,214 @@ +# The testing matrix considers ruby/puppet versions supported by SIMP and PE: +# +# https://puppet.com/docs/pe/2017.3/overview/component_versions_in_recent_pe_releases.html +# https://puppet.com/misc/puppet-enterprise-lifecycle +# https://puppet.com/docs/pe/2017.3/overview/getting_support_for_pe.html#standard-releases-and-long-term-support-releases +# ------------------------------------------------------------------------------ +# release pup ruby eol +# PE 2016.4 4.7 2.1.9 2018-10 (LTS) +# SIMP6.0.0 4.8 2.1.9 TBD +# PE 2017.2 4.10 2.1.9 2018-02-21 +# PE 2017.3 5.3 2.4.1 2018-07 +# PE 2018.1 ??? ????? ????-?? (LTS) +--- +.cache_bundler: &cache_bundler + cache: + untracked: true + # A broad attempt at caching between runs (ala Travis CI) + key: "${CI_PROJECT_NAMESPACE}__bundler" + paths: + - '.vendor' + - 'vendor' + +.setup_bundler_env: &setup_bundler_env + before_script: + - 'echo Files in cache: $(find .vendor | wc -l) || :' + - 'export GEM_HOME=.vendor/gem_install' + - 'export BUNDLE_CACHE_PATH=.vendor/bundler' + - 'declare GEM_BUNDLER_VER=(-v ''~> ${BUNDLER_VERSION:-1.16.0}'')' + - declare GEM_INSTALL=(gem install --no-document) + - declare BUNDLER_INSTALL=(bundle install --no-binstubs --jobs $(nproc) --path=.vendor "${FLAGS[@]}") + - gem list -ie "${GEM_BUNDLE_VER[@]}" --silent bundler || "${GEM_INSTALL[@]}" --local "${GEM_BUNDLE_VER[@]}" bundler || "${GEM_INSTALL[@]}" "${GEM_BUNDLE_VER[@]}" bundler + - 'rm -rf pkg/ || :' + - bundle check || rm -f Gemfile.lock && ("${BUNDLER_INSTALL[@]}" --local || "${BUNDLER_INSTALL[@]}") + + +.validation_checks: &validation_checks + script: + - bundle exec rake syntax + - bundle exec rake check:dot_underscore + - bundle exec rake check:test_file + - bundle exec rake pkg:check_version + - bundle exec rake pkg:compare_latest_tag + - bundle exec rake lint + - bundle exec rake clean + - bundle exec puppet module build + +.spec_tests: &spec_tests + script: + - bundle exec rake spec + +stages: + - validation + - unit + - acceptance + - deploy + +# Puppet 4.7 for PE 2016.4 LTS Support (EOL: 2018-10-21) +# See: https://puppet.com/misc/puppet-enterprise-lifecycle +# -------------------------------------- +pup4_7-validation: + stage: validation + tags: + - docker + image: ruby:2.1 + variables: + PUPPET_VERSION: '~> 4.7.0' + <<: *cache_bundler + <<: *setup_bundler_env + <<: *validation_checks + +pup4_7-unit: + stage: unit + tags: + - docker + image: ruby:2.1 + variables: + PUPPET_VERSION: '~> 4.7.0' + <<: *cache_bundler + <<: *setup_bundler_env + <<: *spec_tests + + +# Puppet 4.8 for SIMP 6.0 + 6.1 support +# -------------------------------------- +pup4_8-validation: + stage: validation + tags: + - docker + image: ruby:2.1 + variables: + PUPPET_VERSION: '~> 4.8.0' + <<: *cache_bundler + <<: *setup_bundler_env + <<: *validation_checks + +pup4_8-unit: + stage: unit + tags: + - docker + image: ruby:2.1 + variables: + PUPPET_VERSION: '~> 4.8.0' + <<: *cache_bundler + <<: *setup_bundler_env + <<: *spec_tests + + +# Puppet 4.10 for PE 2017.2 support (EOL:2018-02-21) +# See: https://puppet.com/misc/puppet-enterprise-lifecycle +# -------------------------------------- +pup4_10-validation: + stage: validation + tags: + - docker + image: ruby:2.1 + variables: + PUPPET_VERSION: '~> 4.10.0' + <<: *cache_bundler + <<: *setup_bundler_env + <<: *validation_checks + +pup4_10-unit: + stage: unit + tags: + - docker + image: ruby:2.1 + variables: + PUPPET_VERSION: '~> 4.10.0' + <<: *cache_bundler + <<: *setup_bundler_env + <<: *spec_tests + + +# Puppet 5.3 for PE 2017.3 support (EOL: 2018-07) +# See: https://puppet.com/misc/puppet-enterprise-lifecycle +# -------------------------------------- +pup5_3-validation: + stage: validation + tags: + - docker + image: ruby:2.4 + variables: + PUPPET_VERSION: '~> 5.3.0' + <<: *cache_bundler + <<: *setup_bundler_env + <<: *validation_checks + +pup5_3-unit: + stage: unit + tags: + - docker + image: ruby:2.4 + variables: + PUPPET_VERSION: '~> 5.3.0' + <<: *cache_bundler + <<: *setup_bundler_env + <<: *spec_tests + allow_failure: true + + +# Keep an eye on the latest puppet 5 +# ---------------------------------- +pup5_latest-validation: + stage: validation + tags: + - docker + image: ruby:2.4 + variables: + PUPPET_VERSION: '~> 5.0' + <<: *cache_bundler + <<: *setup_bundler_env + <<: *validation_checks + allow_failure: true + +pup5_latest-unit: + stage: unit + tags: + - docker + image: ruby:2.4 + variables: + PUPPET_VERSION: '~> 5.0' + <<: *cache_bundler + <<: *setup_bundler_env + <<: *spec_tests + allow_failure: true + + + +# Acceptance tests +# ============================================================================== +default-acceptance: + stage: acceptance + tags: + - beaker + <<: *cache_bundler + <<: *setup_bundler_env + variables: + PUPPET_VERSION: '4.10' + script: + - bundle exec rake spec_clean + - bundle exec rake beaker:suites[default] + +fips-acceptance: + stage: acceptance + tags: + - beaker + <<: *cache_bundler + <<: *setup_bundler_env + variables: + PUPPET_VERSION: '4.10' + BEAKER_fips: 'yes' + script: + - bundle exec rake spec_clean + - bundle exec rake beaker:suites[default] diff --git a/.pmtignore b/.pmtignore new file mode 100644 index 0000000..c3e1c72 --- /dev/null +++ b/.pmtignore @@ -0,0 +1,19 @@ +.*.sw? +.yardoc +dist/ +pkg/ +spec/fixtures/ +spec/rp_env/ +!/spec/hieradata/default.yaml +!/spec/fixtures/site.pp +.rspec_system +.vagrant/ +.bundle/ +Gemfile.lock +vendor/ +junit/ +log/ +doc/ +tests/ +spec/ + diff --git a/.puppet-lint.rc b/.puppet-lint.rc new file mode 100644 index 0000000..807455c --- /dev/null +++ b/.puppet-lint.rc @@ -0,0 +1,5 @@ +--log-format="%{path}:%{line}:%{check}:%{KIND}:%{message}" +--relative +--no-class_inherits_from_params_class-check +--no-140chars-check +--no-trailing_comma-check diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..4cd92bf --- /dev/null +++ b/.rspec @@ -0,0 +1,3 @@ +--format documentation +--color +--fail-fast diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..b88e500 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.1.9 \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..3f6f3ce --- /dev/null +++ b/.travis.yml @@ -0,0 +1,92 @@ +# The testing matrix considers ruby/puppet versions supported by SIMP and PE: +# ------------------------------------------------------------------------------ +# release pup ruby eol +# PE 2016.4 4.7 2.1.9 TBD (LTS) +# PE 2016.5 4.8 2.1.9 2017-10-31 +# SIMP6.0.0 4.8 2.1.9 TBD +# PE 2017.1 4.9 2.1.9 2017-10-31 +# PE 2017.2 4.10 2.1.9 TBD +--- +language: ruby +cache: bundler +sudo: false + +bundler_args: --without development system_tests --path .vendor + + +notifications: + email: false + +addons: + apt: + packages: + - rpm + +before_install: + - rm -f Gemfile.lock + +jobs: + allow_failures: + - env: STRICT_VARIABLES=yes TRUSTED_NODE_DATA=yes PUPPET_VERSION="~> 5.0" + + include: + - stage: check + rvm: 2.4.1 + env: STRICT_VARIABLES=yes TRUSTED_NODE_DATA=yes PUPPET_VERSION="~> 5" + script: + - bundle exec rake check:dot_underscore + - bundle exec rake check:test_file + - bundle exec rake pkg:check_version + - bundle exec rake lint + - bundle exec rake metadata_lint + - bundle exec rake pkg:compare_latest_tag + - bundle exec rake pkg:create_tag_changelog + - bundle exec puppet module build + + - stage: spec + rvm: 2.4.1 + env: STRICT_VARIABLES=yes TRUSTED_NODE_DATA=yes PUPPET_VERSION="~> 5.0" + script: + - bundle exec rake spec + + - stage: spec + rvm: 2.1.9 + env: STRICT_VARIABLES=yes TRUSTED_NODE_DATA=yes PUPPET_VERSION="~> 4.10.0" + script: + - bundle exec rake spec + + - stage: spec + rvm: 2.1.9 + env: STRICT_VARIABLES=yes TRUSTED_NODE_DATA=yes PUPPET_VERSION="~> 4.9.2" + script: + - bundle exec rake spec + + - stage: spec + rvm: 2.1.9 + env: STRICT_VARIABLES=yes TRUSTED_NODE_DATA=yes PUPPET_VERSION="~> 4.7.0" + script: + - bundle exec rake spec + + - stage: deploy + rvm: 2.4.1 + script: + - true + before_deploy: + - "export PUPMOD_METADATA_VERSION=`ruby -r json -e \"puts JSON.parse(File.read('metadata.json')).fetch('version')\"`" + - '[[ $TRAVIS_TAG =~ ^simp-${PUPMOD_METADATA_VERSION}$|^${PUPMOD_METADATA_VERSION}$ ]]' + deploy: + - provider: releases + api_key: + secure: "FnyifrSlS4tIrVUM0wQtTO8fspmJEcsGRWe+2CD63ZwAJ3V5AM6ydeGlw6fODcjZimJORDgP8sm4dpF/C6AqFmsIUP9Qo3iciG9c4SFbf+OroPkNNfVr5lIRu/hBca/fPdy7AqI/fmMZaqC4+uZ1qmpt+w3b9/W/WES0E4ycrMdlIuX7VbVyF+rrdju2csW6AUCK4GLzWd8m16gkIqKWn4cUItUUqkgn1CeVfY9LWZRvA3OYr51u2qMWy+VsKGOB479jmhHzw1OXfboLpTV6igMcuh3+ltpJzp6C1xl55FPGRuhZiHscIWXirPgnN1+MGqFZxtslM3DtZRWzoy/bK/7gwB1K7ynQCAA+FdWjPIptRoK0N/1aRP0mp5LGArfsOr8L79HSmk/hfkAgCUfCFsYnA5WxHx3MyXC6BblwhyS7dZ6U7Vf0u0Poh5IkgMgtWgi0W1CzCKQquEknRs4CcfbwHLT/e7Jgqd7U4iRAauRRiaLYTwGiHHfOzfsfIznGhOdhtZ9QAdLZ0d+M1/1FTYM546DNa8cPQJvSgOVi/y1EZ+oI0ADdvffak/rsaYgpjNHRnHIG5EfxPyzu28nq2ucmJlGlSxO9Ocf9CC8FYvbxbWZAPccNwvBTYpnVsiFRJdPjjc6iCjctUArxGsm27h7T67woEX4CHjfj6G7iP+A=" + skip_cleanup: true + on: + tags: true + condition: '($SKIP_FORGE_PUBLISH != true)' + - provider: puppetforge + user: simp + password: + secure: "a5g0rfOU+HSAaKKBOLjP3Q1wZbu09zbB6gsSDOz6L/t+ToroiYU4RlVdYyKx1I+B7QGzM1O3czIoAwMKxji4hiCfLXRNByOs1zI4kVBwHk6w7COYPsO61xAx2NDkbV6IZ0c1iwTyDh2/jJiw+TAa2l3khixOZkA1JLm7u0zjr5PgAdKnX3YAuMBhKFPGw3+d5NfkbTAjhkPCvrnArsX5UJvGgKjGJdQtplYlOh6egijdA3FSZuc16MLrNzsh+cEwgT4i0HlviHwuZ7IoMbKmr3+qw78qKTkF9i5xHuhs243pbiodDd1z0taVD14GcA/sLCgRu8M80nA6qKPN33yzAxs27+xklPe/ifQgkO+oZwa9u16yAUK04qKpxv4Y8pFwTaSsEmh88F4EoTdGNBsRR//MyBOgPfYjnqmK/dbEQQ3gTak5e9uwFOBOWn5+xf+ObLqL3OZ+D/3WqJ9VbcTdZ4Hu6uqH5rStQQFCWAgI8yg5h2ondkI5uiPGTekGjRmJNsCciOD+sfMDFMTdQu+3yz6uY1ZMm5+JvTCKoYxllq4zhEJxtAOR5K2VaNWaoSn2YQdeO8PE7kn1YY4I7y/LeEe5E8ZInNAEb6BeMWfMIisf4JrHYi487vF/AI8EfdlS0WftkflrTNGAUmPRra2ytcqfXlHxIBlnaX+e+W9yfo4=" + on: + tags: true + rvm: 2.4.1 + condition: '($SKIP_FORGE_PUBLISH != true)' diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..1943890 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,2 @@ +* Fri Jun 01 2018 Trevor Vaughan - 0.0.1 +- Initial Release diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..2d84b37 --- /dev/null +++ b/Gemfile @@ -0,0 +1,33 @@ +# ------------------------------------------------------------------------------ +# NOTE: SIMP Puppet rake tasks support ruby 2.1.9 +# ------------------------------------------------------------------------------ +gem_sources = ENV.fetch('GEM_SERVERS','https://rubygems.org').split(/[, ]+/) + +gem_sources.each { |gem_source| source gem_source } + +group :test do + gem 'rake' + gem 'puppet', ENV.fetch('PUPPET_VERSION', '~> 4.0') + gem 'rspec' + gem 'rspec-puppet', ['>= 2.6.11', '< 3.0.0'] + gem 'hiera-puppet-helper' + gem 'puppetlabs_spec_helper', '~> 2.7.0' + gem 'metadata-json-lint' + gem 'puppet-strings' + gem 'puppet-lint-empty_string-check', :require => false + gem 'puppet-lint-trailing_comma-check', :require => false + gem 'simp-rspec-puppet-facts', ENV.fetch('SIMP_RSPEC_PUPPET_FACTS_VERSION', '~> 2.0.0') + gem 'simp-rake-helpers', ENV.fetch('SIMP_RAKE_HELPERS_VERSION', ['>= 5.2', '< 6.0']) + gem 'facterdb' +end + +group :development do + gem 'pry' + gem 'pry-doc' +end + +group :system_tests do + gem 'beaker' + gem 'beaker-rspec' + gem 'simp-beaker-helpers', ENV.fetch('SIMP_BEAKER_HELPERS_VERSION', '~> 1.10') +end diff --git a/LICENSE b/LICENSE index 261eeb9..d07fdd5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,201 +1,27 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ +pupmod-simp-dconf - A Puppet Module for managing DConf - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +-- - 1. Definitions. +Per Section 105 of the Copyright Act of 1976, these works are not entitled to +domestic copyright protection under US Federal law. - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. +The US Government retains the right to pursue copyright protections outside of +the United States. - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. +The United States Government has unlimited rights in this software and all +derivatives thereof, pursuant to the contracts under which it was developed and +the License under which it falls. - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. +--- - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. + http://www.apache.org/licenses/LICENSE-2.0 - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/README.md b/README.md index 94309b6..43697f9 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,80 @@ -# pupmod-simp-dconf -Puppet module for managing Dconf settings +[![License](https://img.shields.io/:license-apache-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) +[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/73/badge)](https://bestpractices.coreinfrastructure.org/projects/73) +[![Puppet Forge](https://img.shields.io/puppetforge/v/simp/dconf.svg)](https://forge.puppetlabs.com/simp/dconf) +[![Puppet Forge Downloads](https://img.shields.io/puppetforge/dt/simp/dconf.svg)](https://forge.puppetlabs.com/simp/dconf) +[![Build Status](https://travis-ci.org/simp/pupmod-simp-dconf.svg)](https://travis-ci.org/simp/pupmod-simp-dconf) + +#### Table of Contents + + + +* [Description](#description) + * [This is a SIMP module](#this-is-a-simp-module) +* [Setup](#setup) +* [Usage](#usage) +* [Reference](#reference) +* [Limitations](#limitations) +* [Development](#development) + + + +## Description + +`dconf` is a Puppet module that installs and manages `dconf` and associated system settings. + +### This is a SIMP module + +This module is a component of the [System Integrity Management Platform](https://simp-project.com) +a compliance-management framework built on Puppet. + +If you find any issues, they may be submitted to our [bug tracker](https://simp-project.atlassian.net/). + +This module is optimally designed for use within a larger SIMP ecosystem, but +it can be used independently: + + * When included within the SIMP ecosystem, security compliance settings will + be managed from the Puppet server. + * If used independently, all SIMP-managed security subsystems are disabled by + default and must be explicitly opted into by administrators. See + [simp_options](https://github.com/simp/pupmod-simp-simp_options) for more + detail. + +## Setup + +To use the module with, just include the class: + +```ruby +include 'dconf' +``` + +## Usage + +All `dconf` settings are locked by default so that users can't change them. + +This can be disabled on a per setting basis, like in this entry for wallpaper +taken from the `simp-gnome` module. + +```yaml +gnome::dconf_hash: + org/dconf/desktop/background: + picture-uri: + value: file:///usr/local/corp/puppies.jpg + lock: false +``` + +## Reference + +See the [API documentation](./REFERENCE.md) or run `puppet strings` for full +details. + +## Limitations + +SIMP Puppet modules are generally intended for use on Red Hat Enterprise Linux +and compatible distributions, such as CentOS. + +Please see the [`metadata.json` file](./metadata.json) for the most up-to-date +list of supported operating systems, Puppet versions, and module dependencies. + +## Development + +Please read our [Contribution Guide] (http://simp-doc.readthedocs.io/en/stable/contributors_guide/index.html) diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..b3ed91e --- /dev/null +++ b/Rakefile @@ -0,0 +1,4 @@ +require 'simp/rake/pupmod/helpers' +require 'puppet-strings/tasks' + +Simp::Rake::Pupmod::Helpers.new(File.dirname(__FILE__)) diff --git a/data/common.yaml b/data/common.yaml new file mode 100644 index 0000000..a4c9028 --- /dev/null +++ b/data/common.yaml @@ -0,0 +1,20 @@ +--- +lookup_options: + dconf::user_profile: + merge: + strategy: deep + knockout_prefix: -- + +dconf::user_profile: + user: + type: user + order: 1 + local: + type: system + order: 20 + site: + type: system + order: 30 + distro: + type: system + order: 40 diff --git a/hiera.yaml b/hiera.yaml new file mode 100644 index 0000000..1e98ee4 --- /dev/null +++ b/hiera.yaml @@ -0,0 +1,14 @@ +--- +version: 4 +datadir: data +hierarchy: + - name: "OS family + Major.Minor Release" + backend: yaml + path: "os/%{facts.os.family}-%{facts.os.release.major}.%{facts.os.release.minor}" + + - name: "OS family + Major Release" + backend: yaml + path: "os/%{facts.os.family}-%{facts.os.release.major}" + + - name: "common" + backend: yaml diff --git a/manifests/init.pp b/manifests/init.pp new file mode 100644 index 0000000..3f76831 --- /dev/null +++ b/manifests/init.pp @@ -0,0 +1,35 @@ +# Manage 'dconf' and associated entries +# +# @param user_profile +# The contents of the user profile that will be added +# +# @see data/common.yaml +# +# @param package_ensure +# The version of `dconf` to install +# +# * Accepts any valid `ensure` parameter value for the `package` resource +# +# @param use_user_profile_defaults +# Add the default `user_profile` settings to the system +# +# @param user_profile_target +# The name of the profile that should be targeted for the defaults +# +class dconf ( + Dconf::DBSettings $user_profile, + Simplib::PackageEnsure $package_ensure = simplib::lookup('simp_options::package_ensure', { 'default_value' => 'installed' }), + Boolean $use_user_profile_defaults = true, + String[1] $user_profile_target = 'user' +) { + simplib::assert_metadata($module_name) + + include 'dconf::install' + + if $use_user_profile_defaults { + dconf::profile { 'Defaults': + target => $user_profile_target, + entries => $user_profile + } + } +} diff --git a/manifests/install.pp b/manifests/install.pp new file mode 100644 index 0000000..786cf2f --- /dev/null +++ b/manifests/install.pp @@ -0,0 +1,8 @@ +# Install the dconf packages +# +# @api private +class dconf::install { + assert_private() + + ensure_packages( 'dconf', { 'ensure' => $dconf::package_ensure } ) +} diff --git a/manifests/profile.pp b/manifests/profile.pp new file mode 100644 index 0000000..c380ec1 --- /dev/null +++ b/manifests/profile.pp @@ -0,0 +1,60 @@ +# Updates a ``dconf`` profile entry to ``/etc/dconf/profile/$name`` +# +# @see man 7 dconf +# +# @param name +# A globally unique name for the entry +# +# @param target +# The name of the profile file in ``base_dir`` +# +# @param entries +# One or entries in the following Hash format: +# +# @example Profile Hierarchy Hash +# 'user': # Name of the database +# 'type': 'user' # DB Type +# 'order': 0 # Priority order (optional, defaults to 15) +# +# * The suggested default hierarchy used by the module data is as follows: +# * User DB => 0 +# * SIMP DB => 10 +# * System DB => Between 11 and 39 +# * Distro DB => 40 +# +# @param target +# The target directory within which to create the profile +# +# @param base_dir +# The base directory that will hold the resulting file +# +define dconf::profile ( + Dconf::DBSettings $entries, + String[1] $target = $name, + Stdlib::AbsolutePath $base_dir = '/etc/dconf/profile' +) { + include 'dconf' + + ensure_resource('file', $base_dir, { + 'ensure' => 'directory', + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0644', + require => Class['dconf::install'] + }) + + ensure_resource('concat', "${base_dir}/${target}", { + 'ensure' => 'present', + 'order' => 'numeric' + }) + + $_default_order = 15 + + $entries.each |String[1] $db_name, Hash $attrs| { + concat::fragment { "${module_name}::profile::${target}::${db_name}": + target => "${base_dir}/${target}", + content => "${attrs['type']}-db:${db_name}\n", + order => pick($attrs['order'], $_default_order) + } + } +} diff --git a/manifests/settings.pp b/manifests/settings.pp new file mode 100644 index 0000000..4e4c41b --- /dev/null +++ b/manifests/settings.pp @@ -0,0 +1,113 @@ +# Add a dconf rule to the profile of your choice +# +# This adds a configuration file to the /etc/dconf/db/.d directory. +# The dconf datbase is updated when any rule is added. You can also elect to +# lock a value so that general users cannot change it. +# +# @param settings_hash A hash to define the settings to be generated. You can set +# whether to lock each setting like in the exmaple +# An example hash would look like: +# ``` +# { +# 'org/gnome/desktop/media-handling' => { +# 'automount' => { 'value' => false, 'lock' => false }, +# 'automount-open' => { 'value' => false } +# } +# } +# ``` +# +# @param profile The dconf profile where you want to place the key/value. +# @param ensure Ensure the setting is present or absent +# @param base_dir The database base directory. This probably shouldn't be changed. +# +define dconf::settings ( + Dconf::SettingsHash $settings_hash, + String[1] $profile, + Enum['present','absent'] $ensure = 'present', + Stdlib::AbsolutePath $base_dir = '/etc/dconf/db', +) { + + include 'dconf' + + $_name = regsubst($name.downcase, '( |/|!|@|#|\$|%|\^|&|\*|[|])', '_', 'G') + + $_profile_dir = "${base_dir}/${profile}.d" + $_target = "${_profile_dir}/${_name}" + + ensure_resource('file', $_profile_dir, { + 'ensure' => 'directory', + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0644', + 'recurse' => true, + 'purge' => true, + require => Class['dconf::install'] + }) + + ensure_resource('file', $_target, { + 'ensure' => 'file', + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0644' + }) + + $_lock_content = flatten($settings_hash.map |$_schema, $_settings| { + + $_settings.keys.each |$_key| { + ini_setting { "${_target} [${_schema}] $_key": + ensure => 'present', + path => $_target, + section => $_schema, + setting => $_key, + value => $_settings[$_key]['value'], + notify => Exec["dconf update ${name}"] + } + } + + $_settings_to_lock = $_settings.map |$_item, $_setting| { + if $_setting['lock'] == false { + $_ret = undef + } + else { + $_ret = "/${$_schema}/${_item}" + } + $_ret + } + + $_settings_to_lock.delete_undef_values + }).join("\n") + + if $_lock_content == '' { + file { "${_profile_dir}/locks/${_name}": + ensure => absent + } + } + else { + file { "${_profile_dir}/locks": + ensure => 'directory', + owner => 'root', + group => 'root', + mode => '0640', + recurse => true, + purge => true + } + + file { "${_profile_dir}/locks/${_name}": + ensure => 'file', + owner => 'root', + group => 'root', + mode => '0640', + content => $_lock_content, + notify => Exec["dconf update ${name}"] + } + } + + # `dconf update` doesn't return anything besides 0, so we have to figure out + # if it was successful + exec { "dconf update ${name}": + command => '/bin/dconf update |& /bin/tee /dev/fd/2 | /bin/wc -c | /bin/grep ^0$', + logoutput => true, + umask => '0033', + refreshonly => true + } +} diff --git a/metadata.json b/metadata.json new file mode 100644 index 0000000..b313869 --- /dev/null +++ b/metadata.json @@ -0,0 +1,52 @@ +{ + "name": "simp-dconf", + "version": "0.0.1", + "author": "SIMP Team", + "summary": "Provides an interface to system DConf configuration", + "license": "Apache-2.0", + "source": "https://github.com/simp/pupmod-simp-dconf", + "project_page": "https://github.com/simp/pupmod-simp-dconf", + "issues_url": "https://simp-project.atlassian.net", + "tags": [ + "simp", + "dconf", + "desktop" + ], + "dependencies": [ + { + "name": "simp/simplib", + "version_requirement": ">= 3.1.0 < 4.0.0" + }, + { + "name": "puppetlabs/stdlib", + "version_requirement": ">= 4.9.0 < 5.0.0" + } + ], + "operatingsystem_support": [ + { + "operatingsystem": "CentOS", + "operatingsystemrelease": [ + "7" + ] + }, + { + "operatingsystem": "RedHat", + "operatingsystemrelease": [ + "7" + ] + }, + { + "operatingsystem": "OracleLinux", + "operatingsystemrelease": [ + "7" + ] + } + ], + "requirements": [ + { + "name": "puppet", + "version_requirement": ">= 4.7.0 < 6.0.0" + } + ], + "data_provider": "hiera" +} diff --git a/spec/acceptance/nodesets/centos.yml b/spec/acceptance/nodesets/centos.yml new file mode 100644 index 0000000..b98cd16 --- /dev/null +++ b/spec/acceptance/nodesets/centos.yml @@ -0,0 +1,16 @@ +HOSTS: + el7: + roles: + - default + platform: el-7-x86_64 + box: centos/7 + hypervisor: vagrant + yum_repos: + epel: + mirrorlist: 'https://mirrors.fedoraproject.org/metalink?repo=epel-7&arch=$basearch' + gpgkeys: + - https://getfedora.org/static/352C64E5.txt +CONFIG: + log_level: verbose + type: aio + vagrant_memsize: 256 diff --git a/spec/acceptance/nodesets/default.yml b/spec/acceptance/nodesets/default.yml new file mode 120000 index 0000000..fa2c37f --- /dev/null +++ b/spec/acceptance/nodesets/default.yml @@ -0,0 +1 @@ +centos.yml \ No newline at end of file diff --git a/spec/acceptance/nodesets/oel.yml b/spec/acceptance/nodesets/oel.yml new file mode 100644 index 0000000..42ee267 --- /dev/null +++ b/spec/acceptance/nodesets/oel.yml @@ -0,0 +1,20 @@ +HOSTS: + oel7: + roles: + - default + - master + - client + - mate_enabled + platform: el-7-x86_64 + box: elastic/oel-7-x86_64 + hypervisor: vagrant + yum_repos: + epel: + mirrorlist: 'https://mirrors.fedoraproject.org/metalink?repo=epel-7&arch=$basearch' + gpgkeys: + - https://getfedora.org/static/352C64E5.txt + +CONFIG: + log_level: verbose + type: aio + vagrant_memsize: 256 diff --git a/spec/acceptance/suites/default/00_default_spec.rb b/spec/acceptance/suites/default/00_default_spec.rb new file mode 100644 index 0000000..3adc010 --- /dev/null +++ b/spec/acceptance/suites/default/00_default_spec.rb @@ -0,0 +1,62 @@ +require 'spec_helper_acceptance' + +test_name 'dconf class' + +describe 'dconf class' do + let(:manifest) { + <<-EOS + include '::dconf' + + dconf::profile { 'test': + entries => { + 'user' => { + 'type' => 'user', + 'order' => 1 + }, + 'system' => { + 'type' => 'system', + 'order' => 10 + } + } + } + + dconf::settings { 'test settings': + profile => 'test', + settings_hash => { + 'org/gnome/desktop/lockdown' => { + 'disable-command-line' => { + 'value' => true + }, + }, + 'org/gnome/desktop/screensaver' => { + 'lock-delay' => { + 'value' => true, + 'lock' => true + } + } + } + } + EOS + } + + hosts.each do |host| + context "on #{host}" do + # This is so that we actually have something to set + it 'should have gsettings-desktop-schemas installed' do + install_package(host, 'gsettings-desktop-schemas') + end + + it 'should work with no errors' do + apply_manifest_on(host, manifest, :catch_failures => true) + end + + it 'should be idempotent' do + apply_manifest_on(host, manifest, {:catch_changes => true}) + end + + it 'should have dconf installed' do + host.check_for_command('dconf').should be true + end + end + end +end diff --git a/spec/acceptance/suites/default/nodesets b/spec/acceptance/suites/default/nodesets new file mode 120000 index 0000000..aa8eb08 --- /dev/null +++ b/spec/acceptance/suites/default/nodesets @@ -0,0 +1 @@ +../../nodesets \ No newline at end of file diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb new file mode 100644 index 0000000..09beacf --- /dev/null +++ b/spec/classes/init_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' + +describe 'dconf' do + on_supported_os.each do |os, os_facts| + context "on #{os}" do + let(:facts) { os_facts } + + context 'with default parameters' do + it { is_expected.to compile.with_all_deps } + it { is_expected.to create_class('dconf') } + it { is_expected.to create_class('dconf::install') } + it { is_expected.to create_package('dconf').with_ensure('present') } + end + end + end +end diff --git a/spec/defines/profile_spec.rb b/spec/defines/profile_spec.rb new file mode 100644 index 0000000..55cbb79 --- /dev/null +++ b/spec/defines/profile_spec.rb @@ -0,0 +1,73 @@ +require 'spec_helper' + +describe 'dconf::profile', :type => :define do + on_supported_os.each do |os, os_facts| + context "on #{os}" do + let(:facts) do + os_facts + end + + context 'with a set of entries' do + let(:title) { 'test' } + let(:params) {{ + :target => 'test', + :entries => { + 'user' => { + 'type' => 'user', + 'order' => 1 + }, + 'test' => { + 'type' => 'system', + 'order' => 200 + }, + 'test2' => { + 'type' => 'service' + }, + '/some/file/path' => { + 'type' => 'file' + } + }, + :base_dir => '/tmp/foo' + }} + + it { is_expected.to compile.with_all_deps } + + it { is_expected.to create_file(params[:base_dir]).with_ensure('directory') } + + it { is_expected.to create_concat("#{params[:base_dir]}/#{params[:target]}").with_order('numeric') } + + it { + is_expected.to create_concat__fragment("dconf::profile::#{params[:target]}::user").with({ + :target => "#{params[:base_dir]}/#{params[:target]}", + :order => params[:entries]['user']['order'], + :content => "user-db:user\n" + }) + } + + it { + is_expected.to create_concat__fragment("dconf::profile::#{params[:target]}::test").with({ + :target => "#{params[:base_dir]}/#{params[:target]}", + :order => params[:entries]['test']['order'], + :content => "system-db:test\n" + }) + } + + it { + is_expected.to create_concat__fragment("dconf::profile::#{params[:target]}::test2").with({ + :target => "#{params[:base_dir]}/#{params[:target]}", + :order => 15, + :content => "service-db:test2\n" + }) + } + + it { + is_expected.to create_concat__fragment("dconf::profile::#{params[:target]}::/some/file/path").with({ + :target => "#{params[:base_dir]}/#{params[:target]}", + :order => 15, + :content => "file-db:/some/file/path\n" + }) + } + end + end + end +end diff --git a/spec/defines/settings_spec.rb b/spec/defines/settings_spec.rb new file mode 100644 index 0000000..c90bb88 --- /dev/null +++ b/spec/defines/settings_spec.rb @@ -0,0 +1,115 @@ +require 'spec_helper' + +describe 'dconf::settings', :type => :define do + on_supported_os.each do |os, os_facts| + context "on #{os}" do + let(:facts) do + os_facts + end + + + context 'with minimal parameters' do + let(:title) { 'Enable lock delay' } + let(:params) {{ + :ensure => 'present', + :settings_hash => { 'org/gnome/desktop/screensaver' => { 'lock-delay' => { 'value' => true } }}, + :profile => 'gdm' + }} + it { is_expected.to compile.with_all_deps } + it { is_expected.to create_file('/etc/dconf/db/gdm.d/enable_lock_delay') } + it { is_expected.to create_ini_setting('/etc/dconf/db/gdm.d/enable_lock_delay [org/gnome/desktop/screensaver] lock-delay') \ + .with_value('true') } + it { is_expected.to create_ini_setting('/etc/dconf/db/gdm.d/enable_lock_delay [org/gnome/desktop/screensaver] lock-delay').with({ + :section => 'org/gnome/desktop/screensaver', + :setting => 'lock-delay', + :value => true + }) } + it { is_expected.to create_file('/etc/dconf/db/gdm.d/locks/enable_lock_delay') \ + .with_content('/org/gnome/desktop/screensaver/lock-delay') } + end + + context 'a setting with many items' do + let(:title) { 'Set wallpaper' } + let(:params) {{ + :ensure => 'present', + :profile => 'gdm', + :settings_hash => { 'org/gnome/desktop/background' => { + 'picture-uri' => { 'value' => '/home/test/Pictures/puppies.jpg' }, + 'picture-options' => { 'value' => 'scaled' }, + 'primary-color' => { 'value' => '000000' }, + }} + }} + it { is_expected.to compile.with_all_deps } + it { is_expected.to create_ini_setting('/etc/dconf/db/gdm.d/set_wallpaper [org/gnome/desktop/background] picture-uri') \ + .with_value('/home/test/Pictures/puppies.jpg') } + it { is_expected.to create_ini_setting('/etc/dconf/db/gdm.d/set_wallpaper [org/gnome/desktop/background] picture-options') \ + .with_value('scaled') } + it { is_expected.to create_ini_setting('/etc/dconf/db/gdm.d/set_wallpaper [org/gnome/desktop/background] primary-color') \ + .with_value('000000') } + it { is_expected.to create_file('/etc/dconf/db/gdm.d/locks/set_wallpaper').with_content(<<-EOF.gsub(/^\s+/,'').strip + /org/gnome/desktop/background/picture-uri + /org/gnome/desktop/background/picture-options + /org/gnome/desktop/background/primary-color + EOF + ) } + end + + context 'with one setting with lock => false' do + let(:title) { 'Enable lock delay' } + let(:params) {{ + :ensure => 'present', + :settings_hash => { 'org/gnome/desktop/screensaver' => { 'lock-delay' => { 'value' => true, 'lock' => false } }}, + :profile => 'gdm' + }} + it { is_expected.to compile.with_all_deps } + it { is_expected.to create_ini_setting('/etc/dconf/db/gdm.d/enable_lock_delay [org/gnome/desktop/screensaver] lock-delay') \ + .with_value('true') } + it { is_expected.to create_ini_setting('/etc/dconf/db/gdm.d/enable_lock_delay [org/gnome/desktop/screensaver] lock-delay').with({ + :section => 'org/gnome/desktop/screensaver', + :setting => 'lock-delay', + :value => true + }) } + it { is_expected.to create_file('/etc/dconf/db/gdm.d/locks/enable_lock_delay') \ + .with_ensure('absent') } + end + + context 'a setting with many items, and one unlocked' do + let(:title) { 'Arbitrary Name' } + let(:params) {{ + :ensure => 'present', + :profile => 'gdm', + :settings_hash => { + 'org/gnome/desktop/screensaver' => { + 'lock-delay' => { 'value' => true, 'lock' => true } + }, + 'org/gnome/desktop/background' => { + 'picture-uri' => { 'value' => '/home/test/Pictures/puppies.jpg', 'lock' => false }, + 'picture-options' => { 'value' => 'scaled' , 'lock' => :undef }, + 'primary-color' => { 'value' => '000000'}, + } + } + }} + it { is_expected.to compile.with_all_deps } + it { is_expected.to create_ini_setting('/etc/dconf/db/gdm.d/arbitrary_name [org/gnome/desktop/background] picture-uri') \ + .with_value('/home/test/Pictures/puppies.jpg') } + it { is_expected.to create_ini_setting('/etc/dconf/db/gdm.d/arbitrary_name [org/gnome/desktop/background] picture-options') \ + .with_value('scaled') } + it { is_expected.to create_ini_setting('/etc/dconf/db/gdm.d/arbitrary_name [org/gnome/desktop/background] primary-color') \ + .with_value('000000') } + it { is_expected.to create_file('/etc/dconf/db/gdm.d/locks/arbitrary_name').with_content(<<-EOF.gsub(/^\s+/,'').strip + /org/gnome/desktop/screensaver/lock-delay + /org/gnome/desktop/background/picture-options + /org/gnome/desktop/background/primary-color + EOF + ) } + it { is_expected.to create_ini_setting('/etc/dconf/db/gdm.d/arbitrary_name [org/gnome/desktop/screensaver] lock-delay') \ + .with_value('true') } + it { is_expected.to create_ini_setting('/etc/dconf/db/gdm.d/arbitrary_name [org/gnome/desktop/screensaver] lock-delay').with({ + :section => 'org/gnome/desktop/screensaver', + :setting => 'lock-delay', + :value => true + }) } + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..646f104 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,148 @@ +require 'puppetlabs_spec_helper/module_spec_helper' +require 'rspec-puppet' +require 'simp/rspec-puppet-facts' +include Simp::RspecPuppetFacts + +require 'pathname' + +# RSpec Material +fixture_path = File.expand_path(File.join(__FILE__, '..', 'fixtures')) +module_name = File.basename(File.expand_path(File.join(__FILE__,'../..'))) + +# Add fixture lib dirs to LOAD_PATH. Work-around for PUP-3336 +if Puppet.version < "4.0.0" + Dir["#{fixture_path}/modules/*/lib"].entries.each do |lib_dir| + $LOAD_PATH << lib_dir + end +end + +default_hiera_config =<<-EOM +--- +:backends: + - "yaml" +:yaml: + :datadir: "stub" +:hierarchy: + - "%{custom_hiera}" + - "%{module_name}" + - "default" +EOM + +# This can be used from inside your spec tests to set the testable environment. +# You can use this to stub out an ENC. +# +# Example: +# +# context 'in the :foo environment' do +# let(:environment){:foo} +# ... +# end +# +def set_environment(environment = :production) + RSpec.configure { |c| c.default_facts['environment'] = environment.to_s } +end + +# This can be used from inside your spec tests to load custom hieradata within +# any context. +# +# Example: +# +# describe 'some::class' do +# context 'with version 10' do +# let(:hieradata){ "#{class_name}_v10" } +# ... +# end +# end +# +# Then, create a YAML file at spec/fixtures/hieradata/some__class_v10.yaml. +# +# Hiera will use this file as it's base of information stacked on top of +# 'default.yaml' and .yaml per the defaults above. +# +# Note: Any colons (:) are replaced with underscores (_) in the class name. +def set_hieradata(hieradata) + RSpec.configure { |c| c.default_facts['custom_hiera'] = hieradata } +end + +if not File.directory?(File.join(fixture_path,'hieradata')) then + FileUtils.mkdir_p(File.join(fixture_path,'hieradata')) +end + +if not File.directory?(File.join(fixture_path,'modules',module_name)) then + FileUtils.mkdir_p(File.join(fixture_path,'modules',module_name)) +end + +RSpec.configure do |c| + # If nothing else... + c.default_facts = { + :production => { + #:fqdn => 'production.rspec.test.localdomain', + :path => '/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin', + :concat_basedir => '/tmp' + } + } + + c.mock_framework = :rspec + c.mock_with :mocha + + c.module_path = File.join(fixture_path, 'modules') + c.manifest_dir = File.join(fixture_path, 'manifests') + + c.hiera_config = File.join(fixture_path,'hieradata','hiera.yaml') + + # Useless backtrace noise + backtrace_exclusion_patterns = [ + /spec_helper/, + /gems/ + ] + + if c.respond_to?(:backtrace_exclusion_patterns) + c.backtrace_exclusion_patterns = backtrace_exclusion_patterns + elsif c.respond_to?(:backtrace_clean_patterns) + c.backtrace_clean_patterns = backtrace_exclusion_patterns + end + + c.before(:all) do + data = YAML.load(default_hiera_config) + data[:yaml][:datadir] = File.join(fixture_path, 'hieradata') + + File.open(c.hiera_config, 'w') do |f| + f.write data.to_yaml + end + end + + c.before(:each) do + @spec_global_env_temp = Dir.mktmpdir('simpspec') + + if defined?(environment) + set_environment(environment) + FileUtils.mkdir_p(File.join(@spec_global_env_temp,environment.to_s)) + end + + # ensure the user running these tests has an accessible environmentpath + Puppet[:environmentpath] = @spec_global_env_temp + Puppet[:user] = Etc.getpwuid(Process.uid).name + Puppet[:group] = Etc.getgrgid(Process.gid).name + + # sanitize hieradata + if defined?(hieradata) + set_hieradata(hieradata.gsub(':','_')) + elsif defined?(class_name) + set_hieradata(class_name.gsub(':','_')) + end + end + + c.after(:each) do + # clean up the mocked environmentpath + FileUtils.rm_rf(@spec_global_env_temp) + @spec_global_env_temp = nil + end +end + +Dir.glob("#{RSpec.configuration.module_path}/*").each do |dir| + begin + Pathname.new(dir).realpath + rescue + fail "ERROR: The module '#{dir}' is not installed. Tests cannot continue." + end +end diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb new file mode 100644 index 0000000..079dfde --- /dev/null +++ b/spec/spec_helper_acceptance.rb @@ -0,0 +1,56 @@ +require 'beaker-rspec' +require 'tmpdir' +require 'yaml' +require 'simp/beaker_helpers' +include Simp::BeakerHelpers + +unless ENV['BEAKER_provision'] == 'no' + hosts.each do |host| + # Install Puppet + if host.is_pe? + install_pe + else + install_puppet + end + # Install git, it's a dependency for inspec profiles + # Found this when experiencing https://github.com/chef/inspec/issues/1270 + install_package(host, 'git') + end +end + + +RSpec.configure do |c| + # ensure that environment OS is ready on each host + fix_errata_on hosts + + # Readable test descriptions + c.formatter = :documentation + + # Configure all nodes in nodeset + c.before :suite do + begin + # Install modules and dependencies from spec/fixtures/modules + copy_fixture_modules_to( hosts ) + begin + server = only_host_with_role(hosts, 'server') + rescue ArgumentError =>e + server = only_host_with_role(hosts, 'default') + end + + # Generate and install PKI certificates on each SUT + Dir.mktmpdir do |cert_dir| + run_fake_pki_ca_on(server, hosts, cert_dir ) + hosts.each{ |sut| copy_pki_to( sut, cert_dir, '/etc/pki/simp-testing' )} + end + + # add PKI keys + copy_keydist_to(server) + rescue StandardError, ScriptError => e + if ENV['PRY'] + require 'pry'; binding.pry + else + raise e + end + end + end +end diff --git a/types/dbsettings.pp b/types/dbsettings.pp new file mode 100644 index 0000000..1ca3cd2 --- /dev/null +++ b/types/dbsettings.pp @@ -0,0 +1,7 @@ +type Dconf::DBSettings = Hash[ + String[1], # The name of the database + Struct[{ + 'type' => Enum['user', 'system', 'service', 'file'], # The type of database + 'order' => Optional[Integer[1]] # The order of the entry in the list + }] +] diff --git a/types/settingshash.pp b/types/settingshash.pp new file mode 100644 index 0000000..d713e65 --- /dev/null +++ b/types/settingshash.pp @@ -0,0 +1,10 @@ +type Dconf::SettingsHash = Hash[ + String[1], + Hash[ + String[1], + Struct[{ + 'value' => NotUndef, + 'lock' => Optional[Boolean] + }] + ] +]