pax_global_header00006660000000000000000000000064132435565160014524gustar00rootroot0000000000000052 comment=eccb86fe33478b1dca3465aa703b9185e6b14d5b puppetlabs-concat-4.2.0/000077500000000000000000000000001324355651600151535ustar00rootroot00000000000000puppetlabs-concat-4.2.0/.fixtures.yml000066400000000000000000000002061324355651600176230ustar00rootroot00000000000000fixtures: repositories: 'stdlib': 'git://github.com/puppetlabs/puppetlabs-stdlib.git' symlinks: 'concat': '#{source_dir}' puppetlabs-concat-4.2.0/.gitattributes000066400000000000000000000001451324355651600200460ustar00rootroot00000000000000#This file is generated by ModuleSync, do not edit. *.rb eol=lf *.erb eol=lf *.pp eol=lf *.sh eol=lf puppetlabs-concat-4.2.0/.gitignore000066400000000000000000000003671324355651600171510ustar00rootroot00000000000000.*.sw[op] .metadata .yardoc .yardwarns *.iml /.bundle/ /.idea/ /.vagrant/ /coverage/ /bin/ /doc/ /Gemfile.local /Gemfile.lock /junit/ /log/ /log/ /pkg/ /spec/fixtures/manifests/ /spec/fixtures/modules/ /tmp/ /vendor/ /convert_report.txt .DS_Store puppetlabs-concat-4.2.0/.project000066400000000000000000000011201324355651600166140ustar00rootroot00000000000000 puppetlabs-concat com.puppetlabs.geppetto.pp.dsl.ui.modulefileBuilder org.eclipse.xtext.ui.shared.xtextBuilder com.puppetlabs.geppetto.pp.dsl.ui.puppetNature org.eclipse.xtext.ui.shared.xtextNature puppetlabs-concat-4.2.0/.rspec000066400000000000000000000000371324355651600162700ustar00rootroot00000000000000--color --format documentation puppetlabs-concat-4.2.0/.rubocop.yml000066400000000000000000000061031324355651600174250ustar00rootroot00000000000000--- require: rubocop-rspec AllCops: DisplayCopNames: true TargetRubyVersion: '2.1' Include: - "./**/*.rb" Exclude: - bin/* - ".vendor/**/*" - Gemfile - Rakefile - pkg/**/* - spec/fixtures/**/* - vendor/**/* Metrics/LineLength: Description: People have wide screens, use them. Max: 200 RSpec/BeforeAfterAll: Description: Beware of using after(:all) as it may cause state to leak between tests. A necessary evil in acceptance testing. Exclude: - spec/acceptance/**/*.rb RSpec/HookArgument: Description: Prefer explicit :each argument, matching existing module's style EnforcedStyle: each Style/BlockDelimiters: Description: Prefer braces for chaining. Mostly an aesthetical choice. Better to be consistent then. EnforcedStyle: braces_for_chaining Style/ClassAndModuleChildren: Description: Compact style reduces the required amount of indentation. EnforcedStyle: compact Style/EmptyElse: Description: Enforce against empty else clauses, but allow `nil` for clarity. EnforcedStyle: empty Style/FormatString: Description: Following the main puppet project's style, prefer the % format format. EnforcedStyle: percent Style/FormatStringToken: Description: Following the main puppet project's style, prefer the simpler template tokens over annotated ones. EnforcedStyle: template Style/Lambda: Description: Prefer the keyword for easier discoverability. EnforcedStyle: literal Style/RegexpLiteral: Description: Community preference. See https://github.com/voxpupuli/modulesync_config/issues/168 EnforcedStyle: percent_r Style/TernaryParentheses: Description: Checks for use of parentheses around ternary conditions. Enforce parentheses on complex expressions for better readability, but seriously consider breaking it up. EnforcedStyle: require_parentheses_when_complex Style/TrailingCommaInArguments: Description: Prefer always trailing comma on multiline argument lists. This makes diffs, and re-ordering nicer. EnforcedStyleForMultiline: comma Style/TrailingCommaInLiteral: Description: Prefer always trailing comma on multiline literals. This makes diffs, and re-ordering nicer. EnforcedStyleForMultiline: comma Style/SymbolArray: Description: Using percent style obscures symbolic intent of array's contents. EnforcedStyle: brackets Style/CollectionMethods: Enabled: true Style/MethodCalledOnDoEndBlock: Enabled: true Style/StringMethods: Enabled: true Layout/EndOfLine: Enabled: false Metrics/AbcSize: Enabled: false Metrics/BlockLength: Enabled: false Metrics/ClassLength: Enabled: false Metrics/CyclomaticComplexity: Enabled: false Metrics/MethodLength: Enabled: false Metrics/ModuleLength: Enabled: false Metrics/ParameterLists: Enabled: false Metrics/PerceivedComplexity: Enabled: false RSpec/DescribeClass: Enabled: false RSpec/ExampleLength: Enabled: false RSpec/MessageExpectation: Enabled: false RSpec/MultipleExpectations: Enabled: false RSpec/NestedGroups: Enabled: false Style/AsciiComments: Enabled: false Style/IfUnlessModifier: Enabled: false Style/SymbolProc: Enabled: false puppetlabs-concat-4.2.0/.rubocop_todo.yml000066400000000000000000000000001324355651600204400ustar00rootroot00000000000000puppetlabs-concat-4.2.0/.sync.yml000066400000000000000000000027141324355651600167340ustar00rootroot00000000000000--- appveyor.yml: matrix: - RUBY_VERSION: 24-x64 CHECK: "syntax lint" - RUBY_VERSION: 24-x64 CHECK: metadata_lint - RUBY_VERSION: 24-x64 CHECK: rubocop - PUPPET_GEM_VERSION: ~> 4.0 RUBY_VERSION: 21 CHECK: spec spec/spec_helper.rb: allow_deprecations: true .travis.yml: extras: - rvm: 2.1.9 script: bundle exec rake rubocop .travis.yml: bundle_args: --without system_tests docker_sets: - set: docker/centos-7 options: - set: docker/ubuntu-14.04 options: docker_defaults: bundler_args: "" secure: "" branches: - release extras: - env: CHECK=release_checks rvm: 2.1.9 Gemfile: required: ':system_tests': - gem: 'puppet-module-posix-system-r#{minor_version}' platforms: ruby - gem: 'puppet-module-win-system-r#{minor_version}' platforms: - mswin - mingw - x64_mingw - gem: beaker version: '~> 3.13' from_env: BEAKER_VERSION - gem: beaker-abs from_env: BEAKER_ABS_VERSION version: '~> 0.1' - gem: beaker-pe - gem: beaker-hostgenerator from_env: BEAKER_HOSTGENERATOR_VERSION - gem: beaker-rspec from_env: BEAKER_RSPEC_VERSION ':development': - gem: puppet-blacksmith version: '~> 3.4' Rakefile: requires: - puppet_blacksmith/rake_tasks spec/spec_helper.rb: spec_overrides: - "require 'spec_helper_local'" puppetlabs-concat-4.2.0/.travis.yml000066400000000000000000000022551324355651600172700ustar00rootroot00000000000000--- sudo: false dist: trusty language: ruby cache: bundler before_install: - bundle -v - rm Gemfile.lock || true - gem update --system - gem --version - bundle -v script: - 'bundle exec rake $CHECK' bundler_args: --without system_tests rvm: - 2.4.1 matrix: fast_finish: true include: - bundler_args: dist: trusty env: PUPPET_INSTALL_TYPE=agent BEAKER_debug=true BEAKER_set=docker/centos-7 script: bundle exec rake beaker services: docker sudo: required - bundler_args: dist: trusty env: PUPPET_INSTALL_TYPE=agent BEAKER_debug=true BEAKER_set=docker/ubuntu-14.04 script: bundle exec rake beaker services: docker sudo: required - env: CHECK=rubocop - env: CHECK="syntax lint" - env: CHECK=metadata_lint - env: CHECK=release_checks - env: PUPPET_GEM_VERSION="~> 4.0" CHECK=spec rvm: 2.1.9 - env: PUPPET_GEM_VERSION="~> 5.0" CHECK=spec branches: only: - master - /^v\d/ - release notifications: email: false deploy: provider: puppetforge user: puppet password: secure: "" on: tags: true all_branches: true condition: "$DEPLOY_TO_FORGE = yes" puppetlabs-concat-4.2.0/CHANGELOG.md000066400000000000000000000341611324355651600167710ustar00rootroot00000000000000## Supported Release 4.2.0 ### Summary This release introduces the conversion of the module to use PDK 1.3.2, along with the addition of rubocop with associated fixes. #### Changed - All changes in this release are for enabling rubocop, alongside the module then being converted over to the PDK. ## Supported Releases 4.1.1 ### Summary This release is to update the formatting of the module, rubocop having been run for all ruby files and been set to run automatically on all future commits. #### Changed - Rubocop has been implemented. - SLES 10, Windows 2003 R2 and OSX 10.9 removed as supported. - OSX 10.10 and 10.11 added as supported. ## Supported Releases 4.1.0 ### Summary This release is a rollup of changes. The most notable change being the addition of the 'format' attribute which allows output in JSON and YAML formats, and the 'force' attribute which if true forces a merge of duplicate keys for these formats. #### Features - Format and force attributes added. - Deprecated is_string in favour of puppet language. - End of Life Ubuntu releases removed as supported. - Debian 9 added and Debian 6 removed as supported. #### Bugfixes - (MODULES-4359) Fix native types so they can be used directly. - Update to tests to handle errors containing quote marks. - Update to tests to follow rspec-puppet pattern. ## Supported Releases 4.0.1 ### Summary This is a small release that updates regex in a test due to changes made in Puppet. #### Bugfixes - (MODULES-5085) Ensure that replace test handles qoutes in change message ## Supported Releases 3.0.0 & 4.0.0 ### Summary This double release adds new Puppet 4 data types. The 3.0.0 release is fully backwards compatible to existing Puppet 4 configurations and provides you with [deprecation warnings](https://github.com/puppetlabs/puppetlabs-stdlib#deprecation) for every argument that will not work as expected with the final 4.0.0 release. See the [stdlib docs](https://github.com/puppetlabs/puppetlabs-stdlib#validate_legacy) for an in-depth discussion of this. If you're still running Puppet 3, remain on the latest puppetlabs-concat 2.x release for now, and see the documentation to [upgrade to Puppet 4](https://docs.puppet.com/puppet/4.6/reference/upgrade_major_pre.html). #### Added - puppet-strings documentation - Puppet 4 data types and deprecation warnings #### Changed - stdlib dependency changed to 4.13.1 - supported Puppet version changed to 4.7. ## Supported Release 2.2.1 ### Summary This is a backwards compatible bugfix release. #### Bugfixes - (MODULES-4350) Makes :path the namevar for concat_file - (MODULES-4351) Prevents the :order parameter from accepting arbitrary values in concat_file - (MODULES-4352) Restricts the :replace parameter to values accepted by file - (MODULES-4474) Drops auto requirement of fragments - (MODULES-3900) Improves error messages in concat::fragment - Uses the whole fragment title when sorting ## Supported Release 2.2.0 ### Summary This release includes support for Debian 8 and Ubuntu 16.04 in addition to numerous bugfixes. #### Features - Adds Debian 8 support - Adds Ubuntu 16.04 support #### Bugfixes - Fixes the stdlib lower dependency. - (MODULES-3027) Fixes escaping the '*' character in tag creation. - (MODULES-3097) Fixes fragment sorting by alpha - Correctly propagates 'validate_cmd' parameter to generated file resource - Correctly escapes disallowed characters in fragment tag creation - (MODULES-3332) Correct the target path validation - (MODULES-3463) Properly passes metaparams to generated resource ## Supported Release 2.1.0 ### Summary This is a re-release of concat as a resource type. This release also includes new features and bugfixes on top of the previously YANKED 2.0.1 release. #### Features - Adds the show_diff property. - Adds the selinux related file params. - Allows integer UID/GID values to be passed into `$owner` and `$group` #### Bugfixes - Adds a workaround to PUP-1963: generated resources never receiving dependency edges. - Fixes occassional failure to find directory environment. ## Supported Release 1.2.5 ### Summary Small release for support of newer PE versions. This increments the version of PE in the metadata.json file. ## 2015-07-21 - Supported Release 1.2.4 ### Summary This release includes some ruby path and lint fixes. #### Bugfixes - Use correct ruby path with PE and AIO - Lint fixes - Use correct ruby path on FreeBSD - Test fixes ## 2015-06-02 - Supported Release 2.0.1 [YANKED] ### Summary This is a bugfix release. #### Bugfixes - Fixes dependency graphing with concurrent modification of the same file. - Fixes handling fragment target. - Fixes the defaulted force behavior to handle empty concats correctly. ## 2015-06-02 - Supported Release 1.2.3 ### Summary This release includes a README fix to document correct behavior of fragment target parameter. #### Bugfixes - README Fix to correctly document how a fragment $target param should work. ## 2015-05-12 - Supported Release 2.0.0 [YANKED] ### Summary This is a major release. Includes re-implementation of concat to use native Type and Providers, resulting in significantly improved performance and testability. Also includes a bugfix to alpha ordering of fragments. #### Features - Re-implementation of concat to use native Type and Providers. #### Bugfixes - Fixes a bug in alpha ordering of fragments. ## 2015-05-12 - Supported Release 1.2.2 ### Summary This release includes a bugfix. #### Bugfixes - Fixes a bug introduced by MODULES-1700, in handling default retrieval of fragment backup parameter. ## 2015-04-14 - Supported Release 1.2.1 ### Summary This release includes bugfixes, test improvements, and a rewritten README. #### Bugfixes - Verifies existence of $is_pe before using it. - Adds validation for $order param to not allow restricted characters. - Sets the group id on Fragments for versions of Facter that contain the $gid fact. - Sets the script group to 0 if the script is owned by root. - Explicitly sets script and concat directories to the same owner and group. - Re-adds support for fragment backup, so that static compiler can work with filebucket (MODULES-1700). ## 2015-02-17 - Supported Release 1.2.0 ### Summary This release includes a number of bugfixes and adds support for running a validation command when using puppet >= 3.5.0. #### Features - Support running a validation command for Puppet >= 3.5.0 #### Bugfixes - Reset poisoned defaults from Exec - Use concatfragments.rb on AIX since it doesn't support print0 - Make sure ruby is in the path for PE (MODULES-1456) - Fix missing method for check_is_owned_by for windows (MODULES-1764) - Fix sort by numeric ## 2014-10-28 - Supported Release 1.1.2 ### Summary This release includes bugfixes and test improvements. The module was tested against SLES10 and SLES12 and found to work against those platforms with no module improvements. Metadata was updated to include those as supported platforms. #### Bugfixes - newline didn't work for Windows and Solaris. This has been fixed. - Install certs on Windows for acceptance tests - Update tests to work with strict variables (no module updates were required) - Update tests to work on Windows - Fix typo in CHANGELOG.md ## 2014-09-10 - Supported Release 1.1.1 ### Summary This is a bugfix release, and the first supported release of the 1.1.x series. #### Bugfixes - Make the `$order` parameter default to a string and be validated as an integer or a string - Use the ruby script on Solaris to not break Sol10 support - Add quotes to the ruby script location for Windows - Fix typos in README.md - Make regex in concat::setup case-insensitive to make it work on Windows - Make sure concat fragments are always replaced - Fix validation to allow `$backup` to be a boolean - Remove dependency on stdlib 4.x - Fix for lack of idempotency with `ensure => 'absent'` - Fix tests and spec_helper - Synchronized files for more consistency across modules via modulesync ## 2014-05-14 - Release 1.1.0 ### Summary This release is primarily a bugfix release since 1.1.0-rc1. #### Features - Improved testing, with tests moved to beaker #### Bugfixes - No longer attempts to set fragment owner and mode on Windows - Fix numeric sorting - Fix incorrect quoting - Fix newlines ## 2014-01-03 - Release 1.1.0-rc1 ### Summary This release of concat was 90% written by Joshua Hoblitt, and the module team would like to thank him for the huge amount of work he put into this release. This module deprecates a bunch of old parameters and usage patterns, modernizes much of the manifest code, simplifies a whole bunch of logic and makes improvements to almost all parts of the module. The other major feature is windows support, courtesy of luisfdez, with an alternative version of the concat bash script in ruby. We've attempted to ensure that there are no backwards incompatible changes, all users of 1.0.0 should be able to use 1.1.0 without any failures, but you may find deprecation warnings and we'll be aggressively moving for a 2.0 to remove those too. For further information on deprecations, please read: https://github.com/puppetlabs/puppetlabs-concat/blob/master/README.md#api-deprecations #### Removed - Puppet 0.24 support. - Filebucket backup of all file resources except the target concatenated file. - Default owner/user/group values. - Purging of long unused /usr/local/bin/concatfragments.sh ### Features - Windows support via a ruby version of the concat bash script. - Huge amount of acceptance testing work added. - Documentation (README) completely rewritten. - New parameters in concat: - `ensure`: Controls if the file should be present/absent at all. - Remove requirement to include concat::setup in manifests. - Made `gnu` parameter deprecated. - Added parameter validation. ### Bugfixes - Ensure concat::setup runs before concat::fragment in all cases. - Pluginsync references updated for modern Puppet. - Fix incorrect group parameter. - Use $owner instead of $id to avoid confusion with $::id - Compatibility fixes for Puppet 2.7/ruby 1.8.7 - Use LC_ALL=C instead of LANG=C - Always exec the concatfragments script as root when running as root. - Syntax and other cleanup changes. ## 2014-06-25 - Supported Release 1.0.4 ### Summary This release has test fixes. #### Features - Added test support for OSX. #### Bugfixes #### Known bugs * Not supported on Windows. ## 2014-06-04 - Release 1.0.3 ### Summary This release adds compatibility for PE3.3 and fixes tests. #### Features - Added test support for Ubuntu Trusty. #### Bugfixes #### Known bugs *Not supported on Windows. ## 2014-03-04 - Supported Release 1.0.2 ### Summary This is a supported release. No functional changes were made from 1.0.1. #### Features - Huge amount of tests backported from 1.1. - Documentation rewrite. #### Bugfixes #### Known Bugs * Not supported on Windows. ## 2014-02-12 - 1.0.1 ### Summary Minor bugfixes for sorting of fragments and ordering of resources. #### Bugfixes - LANG => C replaced with LC_ALL => C to reduce spurious recreation of fragments. - Corrected pluginsync documentation. - Ensure concat::setup always runs before fragments. ## 2013-08-09 - 1.0.0 ### Summary Many new features and bugfixes in this release, and if you're a heavy concat user you should test carefully before upgrading. The features should all be backwards compatible but only light testing has been done from our side before this release. #### Features - New parameters in concat: - `replace`: specify if concat should replace existing files. - `ensure_newline`: controls if fragments should contain a newline at the end. - Improved README documentation. - Add rspec:system tests (rake spec:system to test concat) #### Bugfixes - Gracefully handle \n in a fragment resource name. - Adding more helpful message for 'pluginsync = true' - Allow passing `source` and `content` directly to file resource, rather than defining resource defaults. - Added -r flag to read so that filenames with \ will be read correctly. - sort always uses LANG=C. - Allow WARNMSG to contain/start with '#'. - Replace while-read pattern with for-do in order to support Solaris. #### CHANGELOG: - 2010/02/19 - initial release - 2010/03/12 - add support for 0.24.8 and newer - make the location of sort configurable - add the ability to add shell comment based warnings to top of files - add the ablity to create empty files - 2010/04/05 - fix parsing of WARN and change code style to match rest of the code - Better and safer boolean handling for warn and force - Don't use hard coded paths in the shell script, set PATH top of the script - Use file{} to copy the result and make all fragments owned by root. This means we can chnage the ownership/group of the resulting file at any time. - You can specify ensure => "/some/other/file" in concat::fragment to include the contents of a symlink into the final file. - 2010/04/16 - Add more cleaning of the fragment name - removing / from the $name - 2010/05/22 - Improve documentation and show the use of ensure => - 2010/07/14 - Add support for setting the filebucket behavior of files - 2010/10/04 - Make the warning message configurable - 2010/12/03 - Add flags to make concat work better on Solaris - thanks Jonathan Boyett - 2011/02/03 - Make the shell script more portable and add a config option for root group - 2011/06/21 - Make base dir root readable only for security - 2011/06/23 - Set base directory using a fact instead of hardcoding it - 2011/06/23 - Support operating as non privileged user - 2011/06/23 - Support dash instead of bash or sh - 2011/07/11 - Better solaris support - 2011/12/05 - Use fully qualified variables - 2011/12/13 - Improve Nexenta support - 2012/04/11 - Do not use any GNU specific extensions in the shell script - 2012/03/24 - Comply to community style guides - 2012/05/23 - Better errors when basedir isnt set - 2012/05/31 - Add spec tests - 2012/07/11 - Include concat::setup in concat improving UX - 2012/08/14 - Puppet Lint improvements - 2012/08/30 - The target path can be different from the $name - 2012/08/30 - More Puppet Lint cleanup - 2012/09/04 - RELEASE 0.2.0 - 2012/12/12 - Added (file) $replace parameter to concat puppetlabs-concat-4.2.0/CONTRIBUTING.md000066400000000000000000000230601324355651600174050ustar00rootroot00000000000000# Contributing to Puppet modules So you want to contribute to a Puppet module: Great! Below are some instructions to get you started doing that very thing while setting expectations around code quality as well as a few tips for making the process as easy as possible. ### Table of Contents 1. [Getting Started](#getting-started) 1. [Commit Checklist](#commit-checklist) 1. [Submission](#submission) 1. [More about commits](#more-about-commits) 1. [Testing](#testing) - [Running Tests](#running-tests) - [Writing Tests](#writing-tests) 1. [Get Help](#get-help) ## Getting Started - Fork the module repository on GitHub and clone to your workspace - Make your changes! ## Commit Checklist ### The Basics - [x] my commit is a single logical unit of work - [x] I have checked for unnecessary whitespace with "git diff --check" - [x] my commit does not include commented out code or unneeded files ### The Content - [x] my commit includes tests for the bug I fixed or feature I added - [x] my commit includes appropriate documentation changes if it is introducing a new feature or changing existing functionality - [x] my code passes existing test suites ### The Commit Message - [x] the first line of my commit message includes: - [x] an issue number (if applicable), e.g. "(MODULES-xxxx) This is the first line" - [x] a short description (50 characters is the soft limit, excluding ticket number(s)) - [x] the body of my commit message: - [x] is meaningful - [x] uses the imperative, present tense: "change", not "changed" or "changes" - [x] includes motivation for the change, and contrasts its implementation with the previous behavior ## Submission ### Pre-requisites - Make sure you have a [GitHub account](https://github.com/join) - [Create a ticket](https://tickets.puppet.com/secure/CreateIssue!default.jspa), or [watch the ticket](https://tickets.puppet.com/browse/) you are patching for. ### Push and PR - Push your changes to your fork - [Open a Pull Request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/) against the repository in the puppetlabs organization ## More about commits 1. Make separate commits for logically separate changes. Please break your commits down into logically consistent units which include new or changed tests relevant to the rest of the change. The goal of doing this is to make the diff easier to read for whoever is reviewing your code. In general, the easier your diff is to read, the more likely someone will be happy to review it and get it into the code base. If you are going to refactor a piece of code, please do so as a separate commit from your feature or bug fix changes. We also really appreciate changes that include tests to make sure the bug is not re-introduced, and that the feature is not accidentally broken. Describe the technical detail of the change(s). If your description starts to get too long, that is a good sign that you probably need to split up your commit into more finely grained pieces. Commits which plainly describe the things which help reviewers check the patch and future developers understand the code are much more likely to be merged in with a minimum of bike-shedding or requested changes. Ideally, the commit message would include information, and be in a form suitable for inclusion in the release notes for the version of Puppet that includes them. Please also check that you are not introducing any trailing whitespace or other "whitespace errors". You can do this by running "git diff --check" on your changes before you commit. 2. Sending your patches To submit your changes via a GitHub pull request, we _highly_ recommend that you have them on a topic branch, instead of directly on "master". It makes things much easier to keep track of, especially if you decide to work on another thing before your first change is merged in. GitHub has some pretty good [general documentation](http://help.github.com/) on using their site. They also have documentation on [creating pull requests](https://help.github.com/articles/creating-a-pull-request-from-a-fork/). In general, after pushing your topic branch up to your repository on GitHub, you can switch to the branch in the GitHub UI and click "Pull Request" towards the top of the page in order to open a pull request. 3. Update the related JIRA issue. If there is a JIRA issue associated with the change you submitted, then you should update the ticket to include the location of your branch, along with any other commentary you may wish to make. # Testing ## Getting Started Our Puppet modules provide [`Gemfile`](./Gemfile)s, which can tell a Ruby package manager such as [bundler](http://bundler.io/) what Ruby packages, or Gems, are required to build, develop, and test this software. Please make sure you have [bundler installed](http://bundler.io/#getting-started) on your system, and then use it to install all dependencies needed for this project in the project root by running ```shell % bundle install --path .bundle/gems Fetching gem metadata from https://rubygems.org/........ Fetching gem metadata from https://rubygems.org/.. Using rake (10.1.0) Using builder (3.2.2) -- 8><-- many more --><8 -- Using rspec-system-puppet (2.2.0) Using serverspec (0.6.3) Using rspec-system-serverspec (1.0.0) Using bundler (1.3.5) Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed. ``` NOTE: some systems may require you to run this command with sudo. If you already have those gems installed, make sure they are up-to-date: ```shell % bundle update ``` ## Running Tests With all dependencies in place and up-to-date, run the tests: ### Unit Tests ```shell % bundle exec rake spec ``` This executes all the [rspec tests](http://rspec-puppet.com/) in the directories defined [here](https://github.com/puppetlabs/puppetlabs_spec_helper/blob/699d9fbca1d2489bff1736bb254bb7b7edb32c74/lib/puppetlabs_spec_helper/rake_tasks.rb#L17) and so on. rspec tests may have the same kind of dependencies as the module they are testing. Although the module defines these dependencies in its [metadata.json](./metadata.json), rspec tests define them in [.fixtures.yml](./fixtures.yml). ### Acceptance Tests Some Puppet modules also come with acceptance tests, which use [beaker][]. These tests spin up a virtual machine under [VirtualBox](https://www.virtualbox.org/), controlled with [Vagrant](http://www.vagrantup.com/), to simulate scripted test scenarios. In order to run these, you need both Virtualbox and Vagrant installed on your system. Run the tests by issuing the following command ```shell % bundle exec rake spec_clean % bundle exec rspec spec/acceptance ``` This will now download a pre-fabricated image configured in the [default node-set](./spec/acceptance/nodesets/default.yml), install Puppet, copy this module, and install its dependencies per [spec/spec_helper_acceptance.rb](./spec/spec_helper_acceptance.rb) and then run all the tests under [spec/acceptance](./spec/acceptance). ## Writing Tests ### Unit Tests When writing unit tests for Puppet, [rspec-puppet][] is your best friend. It provides tons of helper methods for testing your manifests against a catalog (e.g. contain_file, contain_package, with_params, etc). It would be ridiculous to try and top rspec-puppet's [documentation][rspec-puppet_docs] but here's a tiny sample: Sample manifest: ```puppet file { "a test file": ensure => present, path => "/etc/sample", } ``` Sample test: ```ruby it 'does a thing' do expect(subject).to contain_file("a test file").with({:path => "/etc/sample"}) end ``` ### Acceptance Tests Writing acceptance tests for Puppet involves [beaker][] and its cousin [beaker-rspec][]. A common pattern for acceptance tests is to create a test manifest, apply it twice to check for idempotency or errors, then run expectations. ```ruby it 'does an end-to-end thing' do pp = <<-EOF file { 'a test file': ensure => present, path => "/etc/sample", content => "test string", } apply_manifest(pp, :catch_failures => true) apply_manifest(pp, :catch_changes => true) end describe file("/etc/sample") do it { is_expected.to contain "test string" } end ``` # If you have commit access to the repository Even if you have commit access to the repository, you still need to go through the process above, and have someone else review and merge in your changes. The rule is that **all changes must be reviewed by a project developer that did not write the code to ensure that all changes go through a code review process.** The record of someone performing the merge is the record that they performed the code review. Again, this should be someone other than the author of the topic branch. # Get Help ### On the web * [Puppet help messageboard](http://puppet.com/community/get-help) * [Writing tests](https://docs.puppet.com/guides/module_guides/bgtm.html#step-three-module-testing) * [General GitHub documentation](http://help.github.com/) * [GitHub pull request documentation](http://help.github.com/send-pull-requests/) ### On chat * Slack (slack.puppet.com) #forge-modules, #puppet-dev, #windows, #voxpupuli * IRC (freenode) #puppet-dev, #voxpupuli [rspec-puppet]: http://rspec-puppet.com/ [rspec-puppet_docs]: http://rspec-puppet.com/documentation/ [beaker]: https://github.com/puppetlabs/beaker [beaker-rspec]: https://github.com/puppetlabs/beaker-rspec puppetlabs-concat-4.2.0/Gemfile000066400000000000000000000135041324355651600164510ustar00rootroot00000000000000source ENV['GEM_SOURCE'] || 'https://rubygems.org' def location_for(place_or_version, fake_version = nil) if place_or_version =~ %r{\A(git[:@][^#]*)#(.*)} [fake_version, { git: Regexp.last_match(1), branch: Regexp.last_match(2), require: false }].compact elsif place_or_version =~ %r{\Afile:\/\/(.*)} ['>= 0', { path: File.expand_path(Regexp.last_match(1)), require: false }] else [place_or_version, { require: false }] end end def gem_type(place_or_version) if place_or_version =~ %r{\Agit[:@]} :git elsif !place_or_version.nil? && place_or_version.start_with?('file:') :file else :gem end end ruby_version_segments = Gem::Version.new(RUBY_VERSION.dup).segments minor_version = ruby_version_segments[0..1].join('.') group :development do gem "fast_gettext", '1.1.0', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.1.0') gem "fast_gettext", require: false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1.0') gem "json_pure", '<= 2.0.1', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0') gem "json", '= 1.8.1', require: false if Gem::Version.new(RUBY_VERSION.dup) == Gem::Version.new('2.1.9') gem "puppet-module-posix-default-r#{minor_version}", require: false, platforms: [:ruby] gem "puppet-module-posix-dev-r#{minor_version}", require: false, platforms: [:ruby] gem "puppet-module-win-default-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw] gem "puppet-module-win-dev-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw] gem "puppet-blacksmith", '~> 3.4', require: false end group :system_tests do gem "puppet-module-posix-system-r#{minor_version}", require: false, platforms: [:ruby] gem "puppet-module-win-system-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw] gem "beaker", *location_for(ENV['BEAKER_VERSION'] || '~> 3.13') gem "beaker-abs", *location_for(ENV['BEAKER_ABS_VERSION'] || '~> 0.1') gem "beaker-pe", require: false gem "beaker-hostgenerator" gem "beaker-rspec" end puppet_version = ENV['PUPPET_GEM_VERSION'] puppet_type = gem_type(puppet_version) facter_version = ENV['FACTER_GEM_VERSION'] hiera_version = ENV['HIERA_GEM_VERSION'] def puppet_older_than?(version) puppet_version = ENV['PUPPET_GEM_VERSION'] !puppet_version.nil? && Gem::Version.correct?(puppet_version) && Gem::Requirement.new("< #{version}").satisfied_by?(Gem::Version.new(puppet_version.dup)) end gems = {} gems['puppet'] = location_for(puppet_version) # If facter or hiera versions have been specified via the environment # variables, use those versions. If not, and if the puppet version is < 3.5.0, # use known good versions of both for puppet < 3.5.0. if facter_version gems['facter'] = location_for(facter_version) elsif puppet_type == :gem && puppet_older_than?('3.5.0') gems['facter'] = ['>= 1.6.11', '<= 1.7.5', require: false] end if hiera_version gems['hiera'] = location_for(ENV['HIERA_GEM_VERSION']) elsif puppet_type == :gem && puppet_older_than?('3.5.0') gems['hiera'] = ['>= 1.0.0', '<= 1.3.0', require: false] end if Gem.win_platform? && (puppet_type != :gem || puppet_older_than?('3.5.0')) # For Puppet gems < 3.5.0 (tested as far back as 3.0.0) on Windows if puppet_type == :gem gems['ffi'] = ['1.9.0', require: false] gems['minitar'] = ['0.5.4', require: false] gems['win32-eventlog'] = ['0.5.3', '<= 0.6.5', require: false] gems['win32-process'] = ['0.6.5', '<= 0.7.5', require: false] gems['win32-security'] = ['~> 0.1.2', '<= 0.2.5', require: false] gems['win32-service'] = ['0.7.2', '<= 0.8.8', require: false] else gems['ffi'] = ['~> 1.9.0', require: false] gems['minitar'] = ['~> 0.5.4', require: false] gems['win32-eventlog'] = ['~> 0.5', '<= 0.6.5', require: false] gems['win32-process'] = ['~> 0.6', '<= 0.7.5', require: false] gems['win32-security'] = ['~> 0.1', '<= 0.2.5', require: false] gems['win32-service'] = ['~> 0.7', '<= 0.8.8', require: false] end gems['win32-dir'] = ['~> 0.3', '<= 0.4.9', require: false] if RUBY_VERSION.start_with?('1.') gems['win32console'] = ['1.3.2', require: false] # sys-admin was removed in Puppet 3.7.0 and doesn't compile under Ruby 2.x gems['sys-admin'] = ['1.5.6', require: false] end # Puppet < 3.7.0 requires these. # Puppet >= 3.5.0 gem includes these as requirements. # The following versions are tested to work with 3.0.0 <= puppet < 3.7.0. gems['win32-api'] = ['1.4.8', require: false] gems['win32-taskscheduler'] = ['0.2.2', require: false] gems['windows-api'] = ['0.4.3', require: false] gems['windows-pr'] = ['1.2.3', require: false] elsif Gem.win_platform? # If we're using a Puppet gem on Windows which handles its own win32-xxx gem # dependencies (>= 3.5.0), set the maximum versions (see PUP-6445). gems['win32-dir'] = ['<= 0.4.9', require: false] gems['win32-eventlog'] = ['<= 0.6.5', require: false] gems['win32-process'] = ['<= 0.7.5', require: false] gems['win32-security'] = ['<= 0.2.5', require: false] gems['win32-service'] = ['<= 0.8.8', require: false] end gems.each do |gem_name, gem_params| gem gem_name, *gem_params end # Evaluate Gemfile.local and ~/.gemfile if they exist extra_gemfiles = [ "#{__FILE__}.local", File.join(Dir.home, '.gemfile'), ] extra_gemfiles.each do |gemfile| if File.file?(gemfile) && File.readable?(gemfile) eval(File.read(gemfile), binding) end end # vim: syntax=ruby puppetlabs-concat-4.2.0/LICENSE000066400000000000000000000261361324355651600161700ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. puppetlabs-concat-4.2.0/MAINTAINERS.md000066400000000000000000000002761324355651600172540ustar00rootroot00000000000000## Maintenance Maintainers: - Puppet Forge Modules Team `forge-modules |at| puppet |dot| com` Tickets: https://tickets.puppet.com/browse/MODULES. Make sure to set component to `concat`. puppetlabs-concat-4.2.0/NOTICE000066400000000000000000000011131324355651600160530ustar00rootroot00000000000000Puppet Module - puppetlabs-concat Copyright 2018 Puppet, Inc. 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.puppetlabs-concat-4.2.0/README.md000066400000000000000000000334621324355651600164420ustar00rootroot00000000000000# concat #### Table of Contents 1. [Overview](#overview) 2. [Module Description - What the module does and why it is useful](#module-description) 3. [Setup - The basics of getting started with concat](#setup) * [What concat affects](#what-concat-affects) * [Beginning with concat](#beginning-with-concat) 4. [Usage - Configuration options and additional functionality](#usage) 5. [Reference - An under-the-hood peek at what the module is doing and how](#reference) * [Defines](#defines) * [Parameters](#parameters) * [Removed functionality](#removed-functionality) 6. [Limitations - OS compatibility, etc.](#limitations) 7. [Development - Guide for contributing to the module](#development) ## Overview The concat module lets you construct files from multiple ordered fragments of text. ## Module Description The concat module lets you gather `concat::fragment` resources from your other modules and order them into a coherent file through a single `concat` resource. ### Beginning with concat To start using concat you need to create: * A concat{} resource for the final file. * One or more concat::fragment{}s. A minimal example might be: ~~~ concat { '/tmp/file': ensure => present, } concat::fragment { 'tmpfile': target => '/tmp/file', content => 'test contents', order => '01' } ~~~ ## Usage ### Maintain a list of the major modules on a node To maintain an motd file that lists the modules on one of your nodes, first create a class to frame up the file: ~~~ class motd { $motd = '/etc/motd' concat { $motd: owner => 'root', group => 'root', mode => '0644' } concat::fragment{ 'motd_header': target => $motd, content => "\nPuppet modules on this server:\n\n", order => '01' } # let local users add to the motd by creating a file called # /etc/motd.local concat::fragment{ 'motd_local': target => $motd, source => '/etc/motd.local', order => '15' } } # let other modules register themselves in the motd define motd::register($content="", $order='10') { if $content == "" { $body = $name } else { $body = $content } concat::fragment{ "motd_fragment_$name": target => '/etc/motd', order => $order, content => " -- $body\n" } } ~~~ Then, in the declarations for each module on the node, add `motd::register{ 'Apache': }` to register the module in the motd. ~~~ class apache { include apache::install, apache::config, apache::service motd::register{ 'Apache': } } ~~~ These two steps populate the /etc/motd file with a list of the installed and registered modules, which stays updated even if you just remove the registered modules' `include` lines. System administrators can append text to the list by writing to /etc/motd.local. When you're finished, the motd file will look something like this: ~~~ Puppet modules on this server: -- Apache -- MySQL ~~~ ## Reference ### Defines * `concat`: Manages a file, compiled from one or more text fragments. * `concat::fragment`: Manages a fragment of text to be compiled into a file. ### Types * `concat_file`: Generates a file with content from fragments sharing a common unique tag. * `concat_fragment`: Manages the fragment. ### Parameters #### Define: `concat` All the parameters listed below are optional. ##### `backup` Data type: Boolean, String. Specifies whether (and how) to back up the destination file before overwriting it. Your value gets passed on to Puppet's [native `file` resource](https://docs.puppetlabs.com/references/latest/type.html#file-attribute-backup) for execution. Valid options: `true`, `false`, or a string representing either a target filebucket or a filename extension beginning with ".". Default value: 'puppet'. ##### `ensure` Data type: String. Specifies whether the destination file should exist. Setting to 'absent' tells Puppet to delete the destination file if it exists, and negates the effect of any other parameters. Valid options: 'present' and 'absent'. Default value: 'present'. ##### `ensure_newline` Data type: Boolean. Specifies whether to add a line break at the end of each fragment that doesn't already end in one. Valid options: `true` and `false`. Default value: `false`. ##### `group` Optional. Data type: String, Integer. Specifies a permissions group for the destination file. Valid options: a string containing a group name. Default value: `undef`. ##### `mode` Data type: String. Specifies the permissions mode of the destination file. Valid options: a string containing a permission mode value in octal notation. Default value: '0644'. ##### `order` Data type: String. Specifies a method for sorting your fragments by name within the destination file. Valid options: 'alpha' (e.g., '1, 10, 2') or 'numeric' (e.g., '1, 2, 10'). You can override this setting for individual fragments by adjusting the `order` parameter in their `concat::fragment` declarations. Default value: 'alpha'. ##### `owner` Optional. Data type: String, Integer. Specifies the owner of the destination file. Valid options: a string containing a username. Default value: `undef`. ##### `path` Data type: Stdlib::AbsolutePath. Specifies a destination file for the combined fragments. Valid options: a string containing an absolute path. Default value: `namevar` ##### `replace` Data type: Boolean. Specifies whether to overwrite the destination file if it already exists. Valid options: `true` and `false`. Default value: `true`. ##### `show_diff` Data type: Boolean. Specifies whether to set the show_diff parameter for the file resource. Useful for hiding secrets stored in hiera from insecure reporting methods. Valid options: `true`. Default value: `true`. ##### `validate_cmd` Optional. Data type: String. Specifies a validation command to apply to the destination file. Requires Puppet version 3.5 or newer. Valid options: a string to be passed to a file resource. Default value: `undef`. ##### `warn` Data type: Boolean, String. Specifies whether to add a header message at the top of the destination file. Valid options: the booleans `true` and `false`, or a string to serve as the header. If you set 'warn' to `true`, `concat` adds the following line with an `order` of `0`: Default value: `false`. ~~~ # This file is managed by Puppet. DO NOT EDIT. ~~~ Before 2.0.0, this parameter would add a newline at the end of the warn message. To improve flexibilty, this was removed. Please add it explicitly if you need it. ##### `selinux_ignore_defaults` See the `file` type's [`selinux_ignore_defaults`](https://docs.puppetlabs.com/references/latest/type.html#file-attribute-selinux_ignore_defaults) documentention. ##### `selrange` See the `file` type's [`selrange`](https://docs.puppetlabs.com/references/latest/type.html#file-attribute-selrange) documentention. ##### `selrole` See the `file` type's [`selrole`](https://docs.puppetlabs.com/references/latest/type.html#file-attribute-selrole) documentention. ##### `seltype` See the `file` type's [`seltype`](https://docs.puppetlabs.com/references/latest/type.html#file-attribute-seltype) documentention. ##### `seluser` See the `file` type's [`seluser`](https://docs.puppetlabs.com/references/latest/type.html#file-attribute-seluser) documentention. #### Define: `concat::fragment` Except where noted, all the below parameters are optional. ##### `content` Data type: String. Supplies the content of the fragment. **Note**: You must supply either a `content` parameter or a `source` parameter. Valid options: a string. Default value: `undef`. ##### `order` Data type: String, Integer. Reorders your fragments within the destination file. Fragments that share the same order number are ordered by name. Valid options: a string (recommended) or an integer. Default value: '10'. ##### `source` Data type: String, Array. Specifies a file to read into the content of the fragment. **Note**: You must supply either a `content` parameter or a `source` parameter. Valid options: a string or an array, containing one or more Puppet URLs. Default value: `undef`. ##### `target` *Required.* Data type: String. Specifies the destination file of the fragment. Valid options: a string containing the path or title of the parent `concat` resource. #### Type: `concat_file` ##### `backup` Data type: String, Boolean. Specifies whether (and how) to back up the destination file before overwriting it. Your value gets passed on to Puppet's [native `file` resource](https://docs.puppetlabs.com/references/latest/type.html#file-attribute-backup) for execution. Valid options: `true`, `false`, or a string representing either a target filebucket or a filename extension beginning with ".". Default value: 'puppet'. ##### `ensure` Data type: String. Specifies whether the destination file should exist. Setting to 'absent' tells Puppet to delete the destination file if it exists, and negates the effect of any other parameters. Valid options: 'present' and 'absent'. Default value: 'present'. ##### `ensure_newline` Data type: Boolean. Specifies whether to add a line break at the end of each fragment that doesn't already end in one. Valid options: `true` and `false`. Default value: `false`. ##### `group` Data type: String, Integer. Specifies a permissions group for the destination file. Valid options: a string containing a group name. Default value: `undef`. ##### `mode` Data type: String. Specifies the permissions mode of the destination file. Valid options: a string containing a permission mode value in octal notation. Default value: '0644'. ##### `order` Data type: String. Specifies a method for sorting your fragments by name within the destination file. Valid options: 'alpha' (e.g., '1, 10, 2') or 'numeric' (e.g., '1, 2, 10'). You can override this setting for individual fragments by adjusting the `order` parameter in their `concat::fragment` declarations. Default value: 'numeric'. ##### `owner` Data type: String, Integer. Specifies the owner of the destination file. Valid options: a string containing a username. Default value: `undef`. ##### `path` Data type: String. Specifies a destination file for the combined fragments. Valid options: a string containing an absolute path. Default value: the title of your declared resource. Default value: `namevar`. ##### `replace` Data type: Boolean. Specifies whether to overwrite the destination file if it already exists. Valid options: `true` and `false`. Default value: `true`. ##### `tag` Data type: String. *Required.* Specifies a unique tag reference to collect all concat_fragments with the same tag. ##### `validate_cmd` Data type: String Specifies a validation command to apply to the destination file. Requires Puppet version 3.5 or newer. Valid options: a string to be passed to a file resource. Default value: `undef`. ##### `format` Data type: String Specify what data type to merge the fragments as. Valid options: 'plain', 'yaml', 'json', 'json-pretty'. Default value: `plain`. ##### `force` Data type: Boolean Specifies whether to merge data structures, keeping the values with higher order. Valid options: `true` and `false`. Default value: `false`. #### Type: `concat_fragment` ##### `content` Data type: String. Supplies the content of the fragment. **Note**: You must supply either a `content` parameter or a `source` parameter. Valid options: a string. Default value: `undef`. ##### `order` Data type: String, Integer. Reorders your fragments within the destination file. Fragments that share the same order number are ordered by name. Valid options: a string (recommended) or an integer. Default value: '10'. ##### `source` Data type: String. Specifies a file to read into the content of the fragment. **Note**: You must supply either a `content` parameter or a `source` parameter. Valid options: a string or an array, containing one or more Puppet URLs. Default value: `undef`. ##### `tag` Data type: String. *Required.* Specifies a unique tag to be used by concat_file to reference and collect content. ##### `target` Data type: String. *Required.* Specifies the destination file of the fragment. Valid options: a string containing the path or title of the parent `concat_file` resource. ### Removed functionality The following functionality existed in previous versions of the concat module, but was removed in version 2.0.0: Parameters removed from `concat::fragment`: * `gnu` * `backup` * `group` * `mode` * `owner` The `concat::setup` class has also been removed. Prior to concat version 2.0.0, if you set the `warn` parameter to a string value of `true`, `false`, 'yes', 'no', 'on', or 'off', the module translated the string to the corresponding boolean value. In concat version 2.0.0 and newer, the `warn_header` parameter treats those values the same as other strings and uses them as the content of your header message. To avoid that, pass the `true` and `false` values as booleans instead of strings. ## Limitations This module has been tested on [all PE-supported platforms](https://forge.puppetlabs.com/supported#compat-matrix), and no issues have been identified. ## Development Puppet modules on the Puppet Forge are open projects, and community contributions are essential for keeping them great. We can't access the huge number of platforms and myriad of hardware, software, and deployment configurations that Puppet is intended to serve. We want to keep it as easy as possible to contribute changes so that our modules work in your environment. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things. For more information, see our [module contribution guide.](https://docs.puppetlabs.com/forge/contributing.html) ### Contributors Richard Pijnenburg ([@Richardp82](http://twitter.com/richardp82)) Joshua Hoblitt ([@jhoblitt](http://twitter.com/jhoblitt)) [More contributors.](https://github.com/puppetlabs/puppetlabs-concat/graphs/contributors) puppetlabs-concat-4.2.0/Rakefile000066400000000000000000000001771324355651600166250ustar00rootroot00000000000000require 'puppetlabs_spec_helper/rake_tasks' require 'puppet-syntax/tasks/puppet-syntax' require 'puppet_blacksmith/rake_tasks' puppetlabs-concat-4.2.0/appveyor.yml000066400000000000000000000023271324355651600175470ustar00rootroot00000000000000version: 1.1.x.{build} skip_commits: message: /^\(?doc\)?.*/ clone_depth: 10 init: - SET - 'mkdir C:\ProgramData\PuppetLabs\code && exit 0' - 'mkdir C:\ProgramData\PuppetLabs\facter && exit 0' - 'mkdir C:\ProgramData\PuppetLabs\hiera && exit 0' - 'mkdir C:\ProgramData\PuppetLabs\puppet\var && exit 0' environment: matrix: - RUBY_VERSION: 24-x64 CHECK: syntax lint - RUBY_VERSION: 24-x64 CHECK: metadata_lint - RUBY_VERSION: 24-x64 CHECK: rubocop - PUPPET_GEM_VERSION: ~> 4.0 RUBY_VERSION: 21-x64 CHECK: spec - PUPPET_GEM_VERSION: ~> 5.0 RUBY_VERSION: 24-x64 CHECK: spec - PUPPET_GEM_VERSION: ~> 4.0 RUBY_VERSION: 21 CHECK: spec - PUPPET_GEM_VERSION: ~> 5.0 RUBY_VERSION: 24 CHECK: spec matrix: fast_finish: true install: - set PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH% - bundle install --jobs 4 --retry 2 --without system_tests - type Gemfile.lock build: off test_script: - bundle exec puppet -V - ruby -v - gem -v - bundle -v - bundle exec rake %CHECK% notifications: - provider: Email to: - nobody@nowhere.com on_build_success: false on_build_failure: false on_build_status_changed: false puppetlabs-concat-4.2.0/examples/000077500000000000000000000000001324355651600167715ustar00rootroot00000000000000puppetlabs-concat-4.2.0/examples/fragment.pp000066400000000000000000000005371324355651600211420ustar00rootroot00000000000000concat { 'testconcat': ensure => present, path => '/tmp/concat', owner => 'root', group => 'root', mode => '0664', show_diff => true, } concat::fragment { '1': target => 'testconcat', content => '1', order => '01', } concat::fragment { '2': target => 'testconcat', content => '2', order => '02', } puppetlabs-concat-4.2.0/examples/init.pp000066400000000000000000000001531324355651600202740ustar00rootroot00000000000000concat { '/tmp/concat': ensure => present, owner => 'root', group => 'root', mode => '0644', } puppetlabs-concat-4.2.0/lib/000077500000000000000000000000001324355651600157215ustar00rootroot00000000000000puppetlabs-concat-4.2.0/lib/puppet/000077500000000000000000000000001324355651600172365ustar00rootroot00000000000000puppetlabs-concat-4.2.0/lib/puppet/type/000077500000000000000000000000001324355651600202175ustar00rootroot00000000000000puppetlabs-concat-4.2.0/lib/puppet/type/concat_file.rb000066400000000000000000000203201324355651600230070ustar00rootroot00000000000000require 'puppet/type/file/owner' require 'puppet/type/file/group' require 'puppet/type/file/mode' require 'puppet/util/checksums' Puppet::Type.newtype(:concat_file) do @doc = "Gets all the file fragments and puts these into the target file. This will mostly be used with exported resources. example: Concat_fragment <<| tag == 'unique_tag' |>> concat_file { '/tmp/file': tag => 'unique_tag', # Optional. Default to undef path => '/tmp/file', # Optional. If given it overrides the resource name owner => 'root', # Optional. Default to undef group => 'root', # Optional. Default to undef mode => '0644' # Optional. Default to undef order => 'numeric' # Optional, Default to 'numeric' ensure_newline => false # Optional, Defaults to false } " ensurable do defaultvalues defaultto { :present } end def exists? self[:ensure] == :present end newparam(:tag) do desc "Tag reference to collect all concat_fragment's with the same tag" end newparam(:path, namevar: true) do desc 'The output file' validate do |value| unless Puppet::Util.absolute_path?(value, :posix) || Puppet::Util.absolute_path?(value, :windows) raise ArgumentError, "File paths must be fully qualified, not '#{value}'" end end end newparam(:owner, parent: Puppet::Type::File::Owner) do desc 'Desired file owner.' end newparam(:group, parent: Puppet::Type::File::Group) do desc 'Desired file group.' end newparam(:mode, parent: Puppet::Type::File::Mode) do desc 'Desired file mode.' end newparam(:order) do desc 'Controls the ordering of fragments. Can be set to alpha or numeric.' newvalues(:alpha, :numeric) defaultto :numeric end newparam(:backup) do desc 'Controls the filebucketing behavior of the final file and see File type reference for its use.' validate do |value| unless [TrueClass, FalseClass, String].include?(value.class) raise ArgumentError, 'Backup must be a Boolean or String' end end end newparam(:replace, boolean: true, parent: Puppet::Parameter::Boolean) do desc 'Whether to replace a file that already exists on the local system.' defaultto true end newparam(:validate_cmd) do desc 'Validates file.' validate do |value| unless value.is_a?(String) raise ArgumentError, 'Validate_cmd must be a String' end end end newparam(:ensure_newline, boolean: true, parent: Puppet::Parameter::Boolean) do desc 'Whether to ensure there is a newline after each fragment.' defaultto false end newparam(:format) do desc 'What data type to merge the fragments as.' newvalues(:plain, :yaml, :json, :'json-pretty') defaultto :plain end newparam(:force, boolean: true, parent: Puppet::Parameter::Boolean) do desc 'Forcibly merge duplicate keys keeping values of the highest order.' defaultto false end # Inherit File parameters newparam(:selinux_ignore_defaults, boolean: true, parent: Puppet::Parameter::Boolean) newparam(:selrange) do validate do |value| raise ArgumentError, 'Selrange must be a String' unless value.is_a?(String) end end newparam(:selrole) do validate do |value| raise ArgumentError, 'Selrole must be a String' unless value.is_a?(String) end end newparam(:seltype) do validate do |value| raise ArgumentError, 'Seltype must be a String' unless value.is_a?(String) end end newparam(:seluser) do validate do |value| raise ArgumentError, 'Seluser must be a String' unless value.is_a?(String) end end newparam(:show_diff, boolean: true, parent: Puppet::Parameter::Boolean) # End file parameters # Autorequire the file we are generating below # Why is this necessary ? autorequire(:file) do [self[:path]] end def fragments # Collect fragments that target this resource by path, title or tag. @fragments ||= catalog.resources.map { |resource| next unless resource.is_a?(Puppet::Type.type(:concat_fragment)) if resource[:target] == self[:path] || resource[:target] == title || (resource[:tag] && resource[:tag] == self[:tag]) resource end }.compact end def decompound(d) d.split('___', 2).map { |v| (v =~ %r{^\d+$}) ? v.to_i : v } end def should_content return @generated_content if @generated_content @generated_content = '' content_fragments = [] fragments.each do |r| content_fragments << ["#{r[:order]}___#{r[:name]}", fragment_content(r)] end sorted = if self[:order] == :numeric content_fragments.sort do |a, b| decompound(a[0]) <=> decompound(b[0]) end else content_fragments.sort_by do |a| a_order, a_name = a[0].split('__', 2) [a_order, a_name] end end case self[:format] when :plain @generated_content = sorted.map { |cf| cf[1] }.join when :yaml content_array = sorted.map do |cf| YAML.safe_load(cf[1]) end content_hash = content_array.reduce({}) do |memo, current| nested_merge(memo, current) end @generated_content = content_hash.to_yaml when :json content_array = sorted.map do |cf| JSON.parse(cf[1]) end content_hash = content_array.reduce({}) do |memo, current| nested_merge(memo, current) end # Convert Hash @generated_content = content_hash.to_json when :'json-pretty' content_array = sorted.map do |cf| JSON.parse(cf[1]) end content_hash = content_array.reduce({}) do |memo, current| nested_merge(memo, current) end @generated_content = JSON.pretty_generate(content_hash) end @generated_content end def nested_merge(hash1, hash2) # Deep-merge Hashes; higher order value is kept hash1.merge(hash2) do |k, v1, v2| if v1.is_a?(Hash) && v2.is_a?(Hash) nested_merge(v1, v2) elsif v1.is_a?(Array) && v2.is_a?(Array) (v1 + v2).uniq else # Fail if there are duplicate keys without force unless v1 == v2 unless self[:force] err_message = [ "Duplicate key '#{k}' found with values '#{v1}' and #{v2}'.", 'Use \'force\' attribute to merge keys.', ] raise(err_message.join(' ')) end Puppet.debug("Key '#{k}': replacing '#{v2}' with '#{v1}'.") end v1 end end end def fragment_content(r) if r[:content].nil? == false fragment_content = r[:content] elsif r[:source].nil? == false @source = nil Array(r[:source]).each do |source| if Puppet::FileServing::Metadata.indirection.find(source) @source = source break end end raise "Could not retrieve source(s) #{r[:source].join(', ')}" unless @source tmp = Puppet::FileServing::Content.indirection.find(@source) fragment_content = tmp.content unless tmp.nil? end if self[:ensure_newline] fragment_content << "\n" unless fragment_content =~ %r{\n$} end fragment_content end def generate file_opts = { ensure: (self[:ensure] == :absent) ? :absent : :file, } [:path, :owner, :group, :mode, :replace, :backup, :selinux_ignore_defaults, :selrange, :selrole, :seltype, :seluser, :validate_cmd, :show_diff].each do |param| file_opts[param] = self[param] unless self[param].nil? end metaparams = Puppet::Type.metaparams excluded_metaparams = [:before, :notify, :require, :subscribe, :tag] metaparams.reject! { |param| excluded_metaparams.include? param } metaparams.each do |metaparam| file_opts[metaparam] = self[metaparam] if self[metaparam] end [Puppet::Type.type(:file).new(file_opts)] end def eval_generate content = should_content if !content.nil? && !content.empty? catalog.resource("File[#{self[:path]}]")[:content] = content end [catalog.resource("File[#{self[:path]}]")] end end puppetlabs-concat-4.2.0/lib/puppet/type/concat_fragment.rb000066400000000000000000000047401324355651600237030ustar00rootroot00000000000000Puppet::Type.newtype(:concat_fragment) do @doc = "Create a concat fragment to be used by concat. the `concat_fragment` type creates a file fragment to be collected by concat based on the tag. The example is based on exported resources. Example: @@concat_fragment { \"uniqe_name_${::fqdn}\": tag => 'unique_name', order => 10, # Optional. Default to 10 content => 'some content' # OR content => template('template.erb') # OR source => 'puppet:///path/to/file' } " newparam(:name, namevar: true) do desc 'Unique name' end newparam(:target) do desc 'Target' validate do |value| raise ArgumentError, 'Target must be a String' unless value.is_a?(String) end end newparam(:content) do desc 'Content' validate do |value| raise ArgumentError, 'Content must be a String' unless value.is_a?(String) end end newparam(:source) do desc 'Source' validate do |value| raise ArgumentError, 'Content must be a String or Array' unless [String, Array].include?(value.class) end end newparam(:order) do desc 'Order' defaultto '10' validate do |val| raise Puppet::ParseError, '$order is not a string or integer.' unless val.is_a?(String) || val.is_a?(Integer) raise Puppet::ParseError, "Order cannot contain '/', ':', or '\n'." if val.to_s =~ %r{[:\n\/]} end end newparam(:tag) do desc 'Tag name to be used by concat to collect all concat_fragments by tag name' end autorequire(:file) do found = catalog.resources.select do |resource| next unless resource.is_a?(Puppet::Type.type(:concat_file)) resource[:path] == self[:target] || resource.title == self[:target] || (resource[:tag] && resource[:tag] == self[:tag]) end if found.empty? tag_message = (self[:tag]) ? "or tag '#{self[:tag]} " : '' warning "Target Concat_file with path or title '#{self[:target]}' #{tag_message}not found in the catalog" end end validate do # Check if target is set raise Puppet::ParseError, "No 'target' or 'tag' set" unless self[:target] || self[:tag] # Check if either source or content is set. raise error if none is set raise Puppet::ParseError, "Set either 'source' or 'content'" if self[:source].nil? && self[:content].nil? # Check if both are set, if so rais error raise Puppet::ParseError, "Can't use 'source' and 'content' at the same time" if !self[:source].nil? && !self[:content].nil? end end puppetlabs-concat-4.2.0/locales/000077500000000000000000000000001324355651600165755ustar00rootroot00000000000000puppetlabs-concat-4.2.0/locales/config.yaml000066400000000000000000000020441324355651600207260ustar00rootroot00000000000000--- # This is the project-specific configuration file for setting up # fast_gettext for your project. gettext: # This is used for the name of the .pot and .po files; they will be # called .pot? project_name: puppetlabs-concat # This is used in comments in the .pot and .po files to indicate what # project the files belong to and should bea little more desctiptive than # package_name: puppetlabs-concat # The locale that the default messages in the .pot file are in default_locale: en # The email used for sending bug reports. bugs_address: docs@puppet.com # The holder of the copyright. copyright_holder: Puppet, Inc. # This determines which comments in code should be eligible for translation. # Any comments that start with this string will be externalized. (Leave # empty to include all.) comments_tag: TRANSLATOR # Patterns for +Dir.glob+ used to find all files that might contain # translatable content, relative to the project root directory source_files: - './lib/**/*.rb' puppetlabs-concat-4.2.0/manifests/000077500000000000000000000000001324355651600171445ustar00rootroot00000000000000puppetlabs-concat-4.2.0/manifests/fragment.pp000066400000000000000000000023441324355651600213130ustar00rootroot00000000000000# Creates a concat_fragment in the catalogue # # @param target The file that these fragments belong to # @param content If present puts the content into the file # @param source If content was not specified, use the source # @param order # By default all files gets a 10_ prefix in the directory you can set it to # anything else using this to influence the order of the content in the file # define concat::fragment( String $target, Optional[String] $content = undef, Optional[Variant[String, Array]] $source = undef, Variant[String, Integer] $order = '10', ) { $resource = 'Concat::Fragment' if ($order =~ String and $order =~ /[:\n\/]/) { fail("${resource}['${title}']: 'order' cannot contain '/', ':', or '\n'.") } if ! ($content or $source) { crit('No content, source or symlink specified') } elsif ($content and $source) { fail("${resource}['${title}']: Can't use 'source' and 'content' at the same time.") } $safe_target_name = regsubst($target, '[/:~\n\s\+\*\(\)@]', '_', 'GM') concat_fragment { $name: target => $target, tag => $safe_target_name, order => $order, content => $content, source => $source, } } puppetlabs-concat-4.2.0/manifests/init.pp000066400000000000000000000117151324355651600204550ustar00rootroot00000000000000# Sets up so that you can use fragments to build a final config file, # # @param ensure # Present/Absent # @param path # The path to the final file. Use this in case you want to differentiate # between the name of a resource and the file path. Note: Use the name you # provided in the target of your fragments. # @param owner # Who will own the file # @param group # Who will own the file # @param mode # The mode of the final file # @param show_diff # Use metaparam for files to show/hide diffs for reporting when using eyaml # secrets. Defaults to true # @param warn # Adds a normal shell style comment top of the file indicating that it is # built by puppet. # Before 2.0.0, this parameter would add a newline at the end of the warn # message. To improve flexibilty, this was removed. Please add it explicitely # if you need it. # @param backup # Controls the filebucketing behavior of the final file and see File type # reference for its use. Defaults to 'puppet' # @param replace # Whether to replace a file that already exists on the local system # @param order # Select whether to order associated fragments by 'alpha' or 'numeric'. # Defaults to 'alpha'. # @param ensure_newline # Specifies whether to ensure there's a new line at the end of each fragment. # Valid options: 'true' and 'false'. Default value: 'false'. # @param selinux_ignore_defaults # @param selrange # @param selrole # @param seltype # @param seluser # @param validate_cmd # Specifies a validation command to apply to the destination file. # Requires Puppet version 3.5 or newer. Valid options: a string to be passed # to a file resource. Default value: undefined. # @param format # Specify what data type to merge the fragments as. # Valid options: 'plain', 'yaml', 'json', 'json-pretty'. Default value: `plain`. # @param force # Specifies whether to merge data structures, keeping the values with higher order. # Used when format is specified as a value other than 'plain'. # Valid options: `true` and `false`. Default value: `false`. # # define concat( Enum['present', 'absent'] $ensure = 'present', Stdlib::Absolutepath $path = $name, Optional[Variant[String, Integer]] $owner = undef, Optional[Variant[String, Integer]] $group = undef, String $mode = '0644', Variant[Boolean, String] $warn = false, Boolean $show_diff = true, Variant[Boolean, String] $backup = 'puppet', Boolean $replace = true, Enum['alpha','numeric'] $order = 'alpha', Boolean $ensure_newline = false, Optional[String] $validate_cmd = undef, Optional[Boolean] $selinux_ignore_defaults = undef, Optional[String] $selrange = undef, Optional[String] $selrole = undef, Optional[String] $seltype = undef, Optional[String] $seluser = undef, Optional[String] $format = 'plain', Optional[Boolean] $force = false, ) { $safe_name = regsubst($name, '[/:~\n\s\+\*\(\)@]', '_', 'G') $default_warn_message = "# This file is managed by Puppet. DO NOT EDIT.\n" case $warn { true: { $warn_message = $default_warn_message $_append_header = true } false: { $warn_message = '' $_append_header = false } default: { $warn_message = $warn $_append_header = true } } if $ensure == 'present' { concat_file { $name: tag => $safe_name, path => $path, owner => $owner, group => $group, mode => $mode, selinux_ignore_defaults => $selinux_ignore_defaults, selrange => $selrange, selrole => $selrole, seltype => $seltype, seluser => $seluser, replace => $replace, backup => $backup, show_diff => $show_diff, order => $order, ensure_newline => $ensure_newline, validate_cmd => $validate_cmd, format => $format, force => $force, } if $_append_header { concat_fragment { "${name}_header": target => $name, tag => $safe_name, content => $warn_message, order => '0', } } } else { concat_file { $name: ensure => $ensure, tag => $safe_name, path => $path, backup => $backup, } } } puppetlabs-concat-4.2.0/metadata.json000066400000000000000000000043511324355651600176310ustar00rootroot00000000000000{ "name": "puppetlabs-concat", "version": "4.2.0", "author": "Puppet Labs", "summary": "Construct files from multiple fragments.", "license": "Apache-2.0", "source": "https://github.com/puppetlabs/puppetlabs-concat", "project_page": "https://github.com/puppetlabs/puppetlabs-concat", "issues_url": "https://tickets.puppetlabs.com/browse/MODULES", "dependencies": [ { "name": "puppetlabs/stdlib", "version_requirement": ">= 4.13.1 < 5.0.0" } ], "operatingsystem_support": [ { "operatingsystem": "RedHat", "operatingsystemrelease": [ "5", "6", "7" ] }, { "operatingsystem": "CentOS", "operatingsystemrelease": [ "5", "6", "7" ] }, { "operatingsystem": "OracleLinux", "operatingsystemrelease": [ "5", "6", "7" ] }, { "operatingsystem": "Scientific", "operatingsystemrelease": [ "5", "6", "7" ] }, { "operatingsystem": "SLES", "operatingsystemrelease": [ "11 SP1", "12" ] }, { "operatingsystem": "Debian", "operatingsystemrelease": [ "7", "8", "9" ] }, { "operatingsystem": "Ubuntu", "operatingsystemrelease": [ "14.04", "16.04" ] }, { "operatingsystem": "Solaris", "operatingsystemrelease": [ "10", "11" ] }, { "operatingsystem": "Windows", "operatingsystemrelease": [ "Server 2008 R2", "Server 2012", "Server 2012 R2", "Server 2016", "Server 2012 R2 Core", "Server 2016 Core", "7", "8.1", "10" ] }, { "operatingsystem": "AIX", "operatingsystemrelease": [ "5.3", "6.1", "7.1" ] }, { "operatingsystem": "OSX", "operatingsystemrelease": [ "10.10", "10.11" ] } ], "requirements": [ { "name": "puppet", "version_requirement": ">= 4.7.0 < 6.0.0" } ], "template-url": "https://github.com/puppetlabs/pdk-templates", "template-ref": "1.3.2-0-g07678c8" } puppetlabs-concat-4.2.0/spec/000077500000000000000000000000001324355651600161055ustar00rootroot00000000000000puppetlabs-concat-4.2.0/spec/acceptance/000077500000000000000000000000001324355651600201735ustar00rootroot00000000000000puppetlabs-concat-4.2.0/spec/acceptance/backup_spec.rb000066400000000000000000000061751324355651600230100ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'concat backup parameter' do basedir = default.tmpdir('concat') context 'when puppet' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': content => "old contents\n", } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': backup => 'puppet', } concat::fragment { 'new file': target => '#{basedir}/file', content => 'new contents', } MANIFEST it 'applies the manifest twice with "Filebucketed" stdout and no stderr' do apply_manifest(pp, catch_failures: true) do |r| expect(r.stdout).to match(%r{Filebucketed #{basedir}/file to puppet with sum 0140c31db86293a1a1e080ce9b91305f}) end apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) { is_expected.to match %r{new contents} } end end context 'when .backup' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': content => "old contents\n", } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': backup => '.backup', } concat::fragment { 'new file': target => '#{basedir}/file', content => 'new contents', } MANIFEST # XXX Puppet doesn't mention anything about filebucketing with a given # extension like .backup it 'applies the manifest twice no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) { is_expected.to match %r{new contents} } end describe file("#{basedir}/file.backup") do it { is_expected.to be_file } its(:content) { is_expected.to match %r{old contents} } end end # XXX The backup parameter uses validate_string() and thus can't be the # boolean false value, but the string 'false' has the same effect in Puppet 3 context "when 'false'" do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': content => "old contents\n", } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': backup => '.backup', } concat::fragment { 'new file': target => '#{basedir}/file', content => 'new contents', } MANIFEST it 'applies the manifest twice with no "Filebucketed" stdout and no stderr' do apply_manifest(pp, catch_failures: true) do |r| expect(r.stdout).not_to match(%r{Filebucketed}) end apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) { is_expected.to match %r{new contents} } end end end puppetlabs-concat-4.2.0/spec/acceptance/concat_spec.rb000066400000000000000000000113241324355651600230020ustar00rootroot00000000000000require 'spec_helper_acceptance' case fact('osfamily') when 'AIX' username = 'root' groupname = 'system' when 'Darwin' username = 'root' groupname = 'wheel' when 'windows' username = 'Administrator' groupname = 'Administrators' when 'Solaris' username = 'root' groupname = 'root' else username = 'root' groupname = 'root' end describe 'basic concat test' do basedir = default.tmpdir('concat') shared_examples 'successfully_applied' do |pp| it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end end context 'with owner/group root' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': owner => '#{username}', group => '#{groupname}', mode => '0644', } concat::fragment { '1': target => '#{basedir}/file', content => '1', order => '01', } concat::fragment { '2': target => '#{basedir}/file', content => '2', order => '02', } MANIFEST it_behaves_like 'successfully_applied', pp describe file("#{basedir}/file") do it { is_expected.to be_file } it { is_expected.to be_owned_by username } it('is group', unless: (fact('osfamily') == 'windows')) { is_expected.to be_grouped_into groupname } it('is mode', unless: (fact('osfamily') == 'AIX' || fact('osfamily') == 'windows')) { is_expected.to be_mode 644 } its(:content) do is_expected.to match '1' end its(:content) do is_expected.to match '2' end end end context 'when present with path set' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } MANIFEST apply_manifest(pp) end pp = " concat { 'file': ensure => present, path => '#{basedir}/file', mode => '0644', } concat::fragment { '1': target => 'file', content => '1', order => '01', } " it_behaves_like 'successfully_applied', pp describe file("#{basedir}/file") do it { is_expected.to be_file } it('is mode', unless: (fact('osfamily') == 'AIX' || fact('osfamily') == 'windows')) { is_expected.to be_mode 644 } its(:content) { is_expected.to match '1' } end end context 'when absent with path set' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } MANIFEST apply_manifest(pp) end pp = " concat { 'file': ensure => absent, path => '#{basedir}/file', mode => '0644', } concat::fragment { '1': target => 'file', content => '1', order => '01', } " it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.not_to be_file } end end context 'when present with path that has special characters' do filename = (fact('osfamily') == 'windows') ? 'file(1)' : 'file(1:2)' before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } MANIFEST apply_manifest(pp) end pp = " concat { '#{filename}': ensure => present, path => '#{basedir}/#{filename}', mode => '0644', } concat::fragment { '1': target => '#{filename}', content => '1', order => '01', } " it_behaves_like 'successfully_applied', pp describe file("#{basedir}/#{filename}") do it { is_expected.to be_file } it('is mode', unless: (fact('osfamily') == 'AIX' || fact('osfamily') == 'windows')) { is_expected.to be_mode 644 } its(:content) { is_expected.to match '1' } end end context 'with noop properly' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } MANIFEST apply_manifest(pp) end pp = " concat { 'file': ensure => present, path => '#{basedir}/file', mode => '0644', noop => true, } concat::fragment { '1': target => 'file', content => '1', order => '01', } " it_behaves_like 'successfully_applied', pp describe file("#{basedir}/file") do it { is_expected.not_to be_file } end end end puppetlabs-concat-4.2.0/spec/acceptance/concurrency_spec.rb000066400000000000000000000015141324355651600240650ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'with file recursive purge' do basedir = default.tmpdir('concat') context 'when run should still create concat file' do pp = <<-MANIFEST file { '#{basedir}/bar': ensure => directory, purge => true, recurse => true, } concat { "foobar": ensure => 'present', path => '#{basedir}/bar/foobar', } concat::fragment { 'foo': target => 'foobar', content => 'foo', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/bar/foobar") do it { is_expected.to be_file } its(:content) do is_expected.to match 'foo' end end end end puppetlabs-concat-4.2.0/spec/acceptance/force_spec.rb000066400000000000000000000111231324355651600226260ustar00rootroot00000000000000require 'spec_helper_acceptance' basedir = default.tmpdir('concat') describe 'force merge of file' do context 'when run should not force' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': content => "file exists\n" } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': format => 'yaml', force => false, } concat::fragment { '1': target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': target => '#{basedir}/file', content => '{"one": "bar"}', } MANIFEST i = 0 num = 2 while i < num it 'applies the manifest twice with stderr' do expect(apply_manifest(pp, catch_failures: true).stderr).to match("Duplicate key 'one' found with values 'foo' and bar'. Use 'force' attribute to merge keys.") end i += 1 end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.to match 'file exists' end its(:content) do is_expected.not_to match 'one: foo' end its(:content) do is_expected.not_to match 'one: bar' end end end context 'when run should not force by default' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': content => "file exists\n" } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': format => 'yaml', } concat::fragment { '1': target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': target => '#{basedir}/file', content => '{"one": "bar"}', } MANIFEST i = 0 num = 2 while i < num it 'applies the manifest twice with stderr' do expect(apply_manifest(pp, catch_failures: true).stderr).to match("Duplicate key 'one' found with values 'foo' and bar'. Use 'force' attribute to merge keys.") end i += 1 end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.to match 'file exists' end its(:content) do is_expected.not_to match 'one: foo' end its(:content) do is_expected.not_to match 'one: bar' end end end context 'when run should force' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': content => "file exists\n" } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': format => 'yaml', force => true, } concat::fragment { '1': target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': target => '#{basedir}/file', content => '{"one": "bar"}', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.to match 'one: foo' end end end context 'when run should not force on plain' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': content => "file exists\n" } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': force => true, format => plain, } concat::fragment { '1': target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': target => '#{basedir}/file', content => '{"one": "bar"}', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.to match '{"one": "foo"}{"one": "bar"}' end end end end puppetlabs-concat-4.2.0/spec/acceptance/format_spec.rb000066400000000000000000000120321324355651600230200ustar00rootroot00000000000000require 'spec_helper_acceptance' basedir = default.tmpdir('concat') describe 'format of file' do context 'when run should default to plain' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': content => "file exists\n" } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': } concat::fragment { '1': target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': target => '#{basedir}/file', content => '{"one": "bar"}', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.to match '{"one": "foo"}{"one": "bar"}' end end end context 'when run should output to plain format' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': content => "file exists\n" } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': format => plain, } concat::fragment { '1': target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': target => '#{basedir}/file', content => '{"one": "bar"}', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.to match '{"one": "foo"}{"one": "bar"}' end end end context 'when run should output to yaml format' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': content => "file exists\n" } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': format => 'yaml', } concat::fragment { '1': target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': target => '#{basedir}/file', content => '{"two": "bar"}', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } end describe file("#{basedir}/file") do its(:content) do is_expected.to match 'one: foo\ntwo: bar' end end end context 'when run should output to json format' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': content => "file exists\n" } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': format => 'json', } concat::fragment { '1': target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': target => '#{basedir}/file', content => '{"two": "bar"}', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.to match '{"one":"foo","two":"bar"}' end end end context 'when run should output to json-pretty format' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': content => "file exists\n" } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': format => 'json-pretty', } concat::fragment { '1': target => '#{basedir}/file', content => '{"one": "foo"}', } concat::fragment { '2': target => '#{basedir}/file', content => '{"two": "bar"}', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.to match '{\n "one": "foo",\n "two": "bar"\n}' end end end end puppetlabs-concat-4.2.0/spec/acceptance/fragment_order_spec.rb000066400000000000000000000040351324355651600245320ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'concat::fragment order' do basedir = default.tmpdir('concat') context 'with reverse order' do shared_examples 'order_by' do |order_by, match_output| pp = <<-MANIFEST concat { '#{basedir}/foo': order => '#{order_by}' } concat::fragment { '1': target => '#{basedir}/foo', content => 'string1', order => '15', } concat::fragment { '2': target => '#{basedir}/foo', content => 'string2', # default order 10 } concat::fragment { '3': target => '#{basedir}/foo', content => 'string3', order => '1', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/foo") do it { is_expected.to be_file } its(:content) { is_expected.to match match_output } end end describe 'alpha' do it_behaves_like 'order_by', 'alpha', %r{string3string2string1} end describe 'numeric' do it_behaves_like 'order_by', 'numeric', %r{string3string2string1} end end context 'with normal order' do pp = <<-MANIFEST concat { '#{basedir}/foo': } concat::fragment { '1': target => '#{basedir}/foo', content => 'string1', order => '01', } concat::fragment { '2': target => '#{basedir}/foo', content => 'string2', order => '02' } concat::fragment { '3': target => '#{basedir}/foo', content => 'string3', order => '03', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/foo") do it { is_expected.to be_file } its(:content) { is_expected.to match %r{string1string2string3} } end end end # concat::fragment order puppetlabs-concat-4.2.0/spec/acceptance/fragment_source_spec.rb000066400000000000000000000113471324355651600247230ustar00rootroot00000000000000require 'spec_helper_acceptance' case fact('osfamily') when 'AIX' username = 'root' groupname = 'system' when 'Darwin' username = 'root' groupname = 'wheel' when 'windows' username = 'Administrator' groupname = 'Administrators' else username = 'root' groupname = 'root' end describe 'concat::fragment source' do basedir = default.tmpdir('concat') context 'when run should read file fragments from local system' do pp = <<-MANIFEST file { '#{basedir}/file1': content => "file1 contents\n" } file { '#{basedir}/file2': content => "file2 contents\n" } concat { '#{basedir}/foo': } concat::fragment { '1': target => '#{basedir}/foo', source => '#{basedir}/file1', require => File['#{basedir}/file1'], } concat::fragment { '2': target => '#{basedir}/foo', content => 'string1 contents', } concat::fragment { '3': target => '#{basedir}/foo', source => '#{basedir}/file2', require => File['#{basedir}/file2'], } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/foo") do it { is_expected.to be_file } its(:content) do is_expected.to match 'file1 contents' end its(:content) do is_expected.to match 'string1 contents' end its(:content) do is_expected.to match 'file2 contents' end end end # should read file fragments from local system context 'when run should create files containing first match only.' do pp = <<-MANIFEST file { '#{basedir}/file1': content => "file1 contents\n" } file { '#{basedir}/file2': content => "file2 contents\n" } concat { '#{basedir}/result_file1': owner => '#{username}', group => '#{groupname}', mode => '0644', } concat { '#{basedir}/result_file2': owner => '#{username}', group => '#{groupname}', mode => '0644', } concat { '#{basedir}/result_file3': owner => '#{username}', group => '#{groupname}', mode => '0644', } concat::fragment { '1': target => '#{basedir}/result_file1', source => [ '#{basedir}/file1', '#{basedir}/file2' ], require => [ File['#{basedir}/file1'], File['#{basedir}/file2'] ], order => '01', } concat::fragment { '2': target => '#{basedir}/result_file2', source => [ '#{basedir}/file2', '#{basedir}/file1' ], require => [ File['#{basedir}/file1'], File['#{basedir}/file2'] ], order => '01', } concat::fragment { '3': target => '#{basedir}/result_file3', source => [ '#{basedir}/file1', '#{basedir}/file2' ], require => [ File['#{basedir}/file1'], File['#{basedir}/file2'] ], order => '01', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/result_file1") do it { is_expected.to be_file } its(:content) do is_expected.to match 'file1 contents' end its(:content) do is_expected.not_to match 'file2 contents' end end describe file("#{basedir}/result_file2") do it { is_expected.to be_file } its(:content) do is_expected.to match 'file2 contents' end its(:content) do is_expected.not_to match 'file1 contents' end end describe file("#{basedir}/result_file3") do it { is_expected.to be_file } its(:content) do is_expected.to match 'file1 contents' end its(:content) do is_expected.not_to match 'file2 contents' end end end context 'when run should fail if no match on source.' do pp = <<-MANIFEST concat { '#{basedir}/fail_no_source': owner => '#{username}', group => '#{groupname}', mode => '0644', } concat::fragment { '1': target => '#{basedir}/fail_no_source', source => [ '#{basedir}/nofilehere', '#{basedir}/nothereeither' ], order => '01', } MANIFEST it 'applies the manifest with resource failures' do expect(apply_manifest(pp, catch_failures: true).stderr).to match(%r{Failed to generate additional resources using 'eval_generate'}) end describe file("#{basedir}/fail_no_source") do # FIXME: Serverspec::Type::File doesn't support exists? for some reason. so... hack. it { is_expected.not_to be_directory } end end end puppetlabs-concat-4.2.0/spec/acceptance/fragments_are_always_replaced_spec.rb000066400000000000000000000076721324355651600276020ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'concat::fragment replace' do basedir = default.tmpdir('concat') context 'when run should create fragment files' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } MANIFEST apply_manifest(pp) end pp1 = <<-MANIFEST concat { '#{basedir}/foo': } concat::fragment { '1': target => '#{basedir}/foo', content => 'caller has replace unset run 1', } MANIFEST pp2 = <<-MANIFEST concat { '#{basedir}/foo': } concat::fragment { '1': target => '#{basedir}/foo', content => 'caller has replace unset run 2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp1, catch_failures: true) apply_manifest(pp1, catch_changes: true) apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) end describe file("#{basedir}/foo") do it { is_expected.to be_file } its(:content) do is_expected.not_to match 'caller has replace unset run 1' end its(:content) do is_expected.to match 'caller has replace unset run 2' end end end # should create fragment files context 'when run should replace its own fragment files when caller has File { replace=>true } set' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } MANIFEST apply_manifest(pp) end pp1 = <<-MANIFEST File { replace=>true } concat { '#{basedir}/foo': } concat::fragment { '1': target => '#{basedir}/foo', content => 'caller has replace true set run 1', } MANIFEST pp2 = <<-MANIFEST File { replace=>true } concat { '#{basedir}/foo': } concat::fragment { '1': target => '#{basedir}/foo', content => 'caller has replace true set run 2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp1, catch_failures: true) apply_manifest(pp1, catch_changes: true) apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) end describe file("#{basedir}/foo") do it { is_expected.to be_file } its(:content) do is_expected.not_to match 'caller has replace true set run 1' end its(:content) do is_expected.to match 'caller has replace true set run 2' end end end # should replace its own fragment files when caller has File(replace=>true) set context 'when run should replace its own fragment files even when caller has File { replace=>false } set' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } MANIFEST apply_manifest(pp) end pp1 = <<-MANIFEST File { replace=>false } concat { '#{basedir}/foo': } concat::fragment { '1': target => '#{basedir}/foo', content => 'caller has replace false set run 1', } MANIFEST pp2 = <<-MANIFEST File { replace=>false } concat { '#{basedir}/foo': } concat::fragment { '1': target => '#{basedir}/foo', content => 'caller has replace false set run 2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp1, catch_failures: true) apply_manifest(pp1, catch_changes: true) apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) end describe file("#{basedir}/foo") do it { is_expected.to be_file } its(:content) do is_expected.not_to match 'caller has replace false set run 1' end its(:content) do is_expected.to match 'caller has replace false set run 2' end end end # should replace its own fragment files even when caller has File(replace=>false) set end puppetlabs-concat-4.2.0/spec/acceptance/native/000077500000000000000000000000001324355651600214615ustar00rootroot00000000000000puppetlabs-concat-4.2.0/spec/acceptance/native/backup_spec.rb000066400000000000000000000062161324355651600242720ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'concat_file backup parameter' do basedir = default.tmpdir('concat') context 'when puppet' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': content => "old contents\n", } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat_file { '#{basedir}/file': backup => 'puppet', } concat_fragment { 'new file': target => '#{basedir}/file', content => 'new contents', } MANIFEST it 'applies the manifest twice with "Filebucketed" stdout and no stderr' do apply_manifest(pp, catch_failures: true) do |r| expect(r.stdout).to match(%r{Filebucketed #{basedir}/file to puppet with sum 0140c31db86293a1a1e080ce9b91305f}) end apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) { is_expected.to match %r{new contents} } end end context 'when .backup' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': content => "old contents\n", } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat_file { '#{basedir}/file': backup => '.backup', } concat_fragment { 'new file': target => '#{basedir}/file', content => 'new contents', } MANIFEST # XXX Puppet doesn't mention anything about filebucketing with a given # extension like .backup it 'applies the manifest twice no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) { is_expected.to match %r{new contents} } end describe file("#{basedir}/file.backup") do it { is_expected.to be_file } its(:content) { is_expected.to match %r{old contents} } end end # XXX The backup parameter uses validate_string() and thus can't be the # boolean false value, but the string 'false' has the same effect in Puppet 3 context "when 'false'" do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': content => "old contents\n", } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat_file { '#{basedir}/file': backup => '.backup', } concat_fragment { 'new file': target => '#{basedir}/file', content => 'new contents', } MANIFEST it 'applies the manifest twice with no "Filebucketed" stdout and no stderr' do apply_manifest(pp, catch_failures: true) do |r| expect(r.stdout).not_to match(%r{Filebucketed}) end apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) { is_expected.to match %r{new contents} } end end end puppetlabs-concat-4.2.0/spec/acceptance/native/concat_spec.rb000066400000000000000000000113701324355651600242710ustar00rootroot00000000000000require 'spec_helper_acceptance' case fact('osfamily') when 'AIX' username = 'root' groupname = 'system' when 'Darwin' username = 'root' groupname = 'wheel' when 'windows' username = 'Administrator' groupname = 'Administrators' when 'Solaris' username = 'root' groupname = 'root' else username = 'root' groupname = 'root' end describe 'basic concat_file test' do basedir = default.tmpdir('concat') shared_examples 'successfully_applied' do |pp| it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end end context 'when owner/group root' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat_file { '#{basedir}/file': owner => '#{username}', group => '#{groupname}', mode => '0644', } concat_fragment { '1': target => '#{basedir}/file', content => '1', order => '01', } concat_fragment { '2': target => '#{basedir}/file', content => '2', order => '02', } MANIFEST it_behaves_like 'successfully_applied', pp describe file("#{basedir}/file") do it { is_expected.to be_file } it { is_expected.to be_owned_by username } it('is group', unless: (fact('osfamily') == 'windows')) { is_expected.to be_grouped_into groupname } it('is mode', unless: (fact('osfamily') == 'AIX' || fact('osfamily') == 'windows')) { is_expected.to be_mode 644 } its(:content) do is_expected.to match '1' end its(:content) do is_expected.to match '2' end end end context 'when set to present with path set' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } MANIFEST apply_manifest(pp) end pp = " concat_file { 'file': ensure => present, path => '#{basedir}/file', mode => '0644', } concat_fragment { '1': target => 'file', content => '1', order => '01', } " it_behaves_like 'successfully_applied', pp describe file("#{basedir}/file") do it { is_expected.to be_file } it('is mode', unless: (fact('osfamily') == 'AIX' || fact('osfamily') == 'windows')) { is_expected.to be_mode 644 } its(:content) { is_expected.to match '1' } end end context 'when set to absent with path set' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } MANIFEST apply_manifest(pp) end pp = " concat_file { 'file': ensure => absent, path => '#{basedir}/file', mode => '0644', } concat_fragment { '1': target => 'file', content => '1', order => '01', } " it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.not_to be_file } end end context 'when set to present with path that has special characters' do filename = (fact('osfamily') == 'windows') ? 'file(1)' : 'file(1:2)' before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } MANIFEST apply_manifest(pp) end pp = " concat_file { '#{filename}': ensure => present, path => '#{basedir}/#{filename}', mode => '0644', } concat_fragment { '1': target => '#{filename}', content => '1', order => '01', } " it_behaves_like 'successfully_applied', pp describe file("#{basedir}/#{filename}") do it { is_expected.to be_file } it('is mode', unless: (fact('osfamily') == 'AIX' || fact('osfamily') == 'windows')) { is_expected.to be_mode 644 } its(:content) { is_expected.to match '1' } end end context 'when noop' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } MANIFEST apply_manifest(pp) end pp = " concat_file { 'file': ensure => present, path => '#{basedir}/file', mode => '0644', noop => true, } concat_fragment { '1': target => 'file', content => '1', order => '01', } " it_behaves_like 'successfully_applied', pp describe file("#{basedir}/file") do it { is_expected.not_to be_file } end end end puppetlabs-concat-4.2.0/spec/acceptance/native/concurrency_spec.rb000066400000000000000000000015341324355651600253550ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'concat_file with file recursive purge' do basedir = default.tmpdir('concat') context 'when run should still create concat file' do pp = <<-MANIFEST file { '#{basedir}/bar': ensure => directory, purge => true, recurse => true, } concat_file { "foobar": ensure => 'present', path => '#{basedir}/bar/foobar', } concat_fragment { 'foo': target => 'foobar', content => 'foo', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/bar/foobar") do it { is_expected.to be_file } its(:content) do is_expected.to match 'foo' end end end end puppetlabs-concat-4.2.0/spec/acceptance/native/file_order_spec.rb000066400000000000000000000021331324355651600251310ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'concat_file order' do basedir = default.tmpdir('concat') shared_examples 'sortby' do |order_by, match_output| pp = <<-MANIFEST concat_file { '#{basedir}/foo': order => '#{order_by}' } concat_fragment { '1': target => '#{basedir}/foo', content => 'string1', order => '1', } concat_fragment { '2': target => '#{basedir}/foo', content => 'string2', order => '2', } concat_fragment { '10': target => '#{basedir}/foo', content => 'string10', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/foo") do it { is_expected.to be_file } its(:content) { is_expected.to match match_output } end end describe 'alpha' do it_behaves_like 'sortby', 'alpha', %r{string1string10string2} end describe 'numeric' do it_behaves_like 'sortby', 'numeric', %r{string1string2string10} end end # concat order puppetlabs-concat-4.2.0/spec/acceptance/native/fragment_order_spec.rb000066400000000000000000000040071324355651600260170ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'concat_fragment order' do basedir = default.tmpdir('concat') context 'when reverse order' do shared_examples 'order_by' do |order_by, match_output| pp = <<-MANIFEST concat_file { '#{basedir}/foo': order => '#{order_by}' } concat_fragment { '1': target => '#{basedir}/foo', content => 'string1', order => '15', } concat_fragment { '2': target => '#{basedir}/foo', content => 'string2', # default order 10 } concat_fragment { '3': target => '#{basedir}/foo', content => 'string3', order => '1', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/foo") do it { is_expected.to be_file } its(:content) { is_expected.to match match_output } end end describe 'alpha' do it_behaves_like 'order_by', 'alpha', %r{string3string2string1} end describe 'numeric' do it_behaves_like 'order_by', 'numeric', %r{string3string2string1} end end context 'when normal order' do pp = <<-MANIFEST concat_file { '#{basedir}/foo': } concat_fragment { '1': target => '#{basedir}/foo', content => 'string1', order => '01', } concat_fragment { '2': target => '#{basedir}/foo', content => 'string2', order => '02' } concat_fragment { '3': target => '#{basedir}/foo', content => 'string3', order => '03', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/foo") do it { is_expected.to be_file } its(:content) { is_expected.to match %r{string1string2string3} } end end end puppetlabs-concat-4.2.0/spec/acceptance/native/fragment_source_spec.rb000066400000000000000000000113601324355651600262040ustar00rootroot00000000000000require 'spec_helper_acceptance' case fact('osfamily') when 'AIX' username = 'root' groupname = 'system' when 'Darwin' username = 'root' groupname = 'wheel' when 'windows' username = 'Administrator' groupname = 'Administrators' else username = 'root' groupname = 'root' end describe 'concat_fragment source' do basedir = default.tmpdir('concat') context 'when run should read file fragments from local system' do pp = <<-MANIFEST file { '#{basedir}/file1': content => "file1 contents\n" } file { '#{basedir}/file2': content => "file2 contents\n" } concat_file { '#{basedir}/foo': } concat_fragment { '1': target => '#{basedir}/foo', source => '#{basedir}/file1', require => File['#{basedir}/file1'], } concat_fragment { '2': target => '#{basedir}/foo', content => 'string1 contents', } concat_fragment { '3': target => '#{basedir}/foo', source => '#{basedir}/file2', require => File['#{basedir}/file2'], } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/foo") do it { is_expected.to be_file } its(:content) do is_expected.to match 'file1 contents' end its(:content) do is_expected.to match 'string1 contents' end its(:content) do is_expected.to match 'file2 contents' end end end # should read file fragments from local system context 'when run should create files containing first match only.' do pp = <<-MANIFEST file { '#{basedir}/file1': content => "file1 contents\n" } file { '#{basedir}/file2': content => "file2 contents\n" } concat_file { '#{basedir}/result_file1': owner => '#{username}', group => '#{groupname}', mode => '0644', } concat_file { '#{basedir}/result_file2': owner => '#{username}', group => '#{groupname}', mode => '0644', } concat_file { '#{basedir}/result_file3': owner => '#{username}', group => '#{groupname}', mode => '0644', } concat_fragment { '1': target => '#{basedir}/result_file1', source => [ '#{basedir}/file1', '#{basedir}/file2' ], require => [ File['#{basedir}/file1'], File['#{basedir}/file2'] ], order => '01', } concat_fragment { '2': target => '#{basedir}/result_file2', source => [ '#{basedir}/file2', '#{basedir}/file1' ], require => [ File['#{basedir}/file1'], File['#{basedir}/file2'] ], order => '01', } concat_fragment { '3': target => '#{basedir}/result_file3', source => [ '#{basedir}/file1', '#{basedir}/file2' ], require => [ File['#{basedir}/file1'], File['#{basedir}/file2'] ], order => '01', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/result_file1") do it { is_expected.to be_file } its(:content) do is_expected.to match 'file1 contents' end its(:content) do is_expected.not_to match 'file2 contents' end end describe file("#{basedir}/result_file2") do it { is_expected.to be_file } its(:content) do is_expected.to match 'file2 contents' end its(:content) do is_expected.not_to match 'file1 contents' end end describe file("#{basedir}/result_file3") do it { is_expected.to be_file } its(:content) do is_expected.to match 'file1 contents' end its(:content) do is_expected.not_to match 'file2 contents' end end end context 'when no match on source it should fail' do pp = <<-MANIFEST concat_file { '#{basedir}/fail_no_source': owner => '#{username}', group => '#{groupname}', mode => '0644', } concat_fragment { '1': target => '#{basedir}/fail_no_source', source => [ '#{basedir}/nofilehere', '#{basedir}/nothereeither' ], order => '01', } MANIFEST it 'applies the manifest with resource failures' do expect(apply_manifest(pp, catch_failures: true).stderr).to match(%r{Failed to generate additional resources using 'eval_generate'}) end describe file("#{basedir}/fail_no_source") do # FIXME: Serverspec::Type::File doesn't support exists? for some reason. so... hack. it { is_expected.not_to be_directory } end end end puppetlabs-concat-4.2.0/spec/acceptance/native/fragments_are_always_replaced_spec.rb000066400000000000000000000077211324355651600310630ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'concat_fragment replace' do basedir = default.tmpdir('concat') context 'when run should create fragment files' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } MANIFEST apply_manifest(pp) end pp1 = <<-MANIFEST concat_file { '#{basedir}/foo': } concat_fragment { '1': target => '#{basedir}/foo', content => 'caller has replace unset run 1', } MANIFEST pp2 = <<-MANIFEST concat_file { '#{basedir}/foo': } concat_fragment { '1': target => '#{basedir}/foo', content => 'caller has replace unset run 2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp1, catch_failures: true) apply_manifest(pp1, catch_changes: true) apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) end describe file("#{basedir}/foo") do it { is_expected.to be_file } its(:content) do is_expected.not_to match 'caller has replace unset run 1' end its(:content) do is_expected.to match 'caller has replace unset run 2' end end end # should create fragment files context 'when run should replace its own fragment files when caller has File { replace=>true } set' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } MANIFEST apply_manifest(pp) end pp1 = <<-MANIFEST File { replace=>true } concat_file { '#{basedir}/foo': } concat_fragment { '1': target => '#{basedir}/foo', content => 'caller has replace true set run 1', } MANIFEST pp2 = <<-MANIFEST File { replace=>true } concat_file { '#{basedir}/foo': } concat_fragment { '1': target => '#{basedir}/foo', content => 'caller has replace true set run 2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp1, catch_failures: true) apply_manifest(pp1, catch_changes: true) apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) end describe file("#{basedir}/foo") do it { is_expected.to be_file } its(:content) do is_expected.not_to match 'caller has replace true set run 1' end its(:content) do is_expected.to match 'caller has replace true set run 2' end end end # should replace its own fragment files when caller has File(replace=>true) set context 'when run should replace its own fragment files even when caller has File { replace=>false } set' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } MANIFEST apply_manifest(pp) end pp1 = <<-MANIFEST File { replace=>false } concat_file { '#{basedir}/foo': } concat_fragment { '1': target => '#{basedir}/foo', content => 'caller has replace false set run 1', } MANIFEST pp2 = <<-MANIFEST File { replace=>false } concat_file { '#{basedir}/foo': } concat_fragment { '1': target => '#{basedir}/foo', content => 'caller has replace false set run 2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp1, catch_failures: true) apply_manifest(pp1, catch_changes: true) apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) end describe file("#{basedir}/foo") do it { is_expected.to be_file } its(:content) do is_expected.not_to match 'caller has replace false set run 1' end its(:content) do is_expected.to match 'caller has replace false set run 2' end end end # should replace its own fragment files even when caller has File(replace=>false) set end puppetlabs-concat-4.2.0/spec/acceptance/native/newline_spec.rb000066400000000000000000000030531324355651600244620ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'concat_file ensure_newline parameter' do basedir = default.tmpdir('concat') context 'when false' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat_file { '#{basedir}/file': ensure_newline => false, } concat_fragment { '1': target => '#{basedir}/file', content => '1', } concat_fragment { '2': target => '#{basedir}/file', content => '2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) { is_expected.to match '12' } end end context 'when true' do pp = <<-MANIFEST concat_file { '#{basedir}/file': ensure_newline => true, } concat_fragment { '1': target => '#{basedir}/file', content => '1', } concat_fragment { '2': target => '#{basedir}/file', content => '2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.to match %r{1\n2\n} end end end end puppetlabs-concat-4.2.0/spec/acceptance/native/pup_1963_spec_resources.rb000066400000000000000000000021311324355651600263750ustar00rootroot00000000000000require 'spec_helper_acceptance' command = case fact('osfamily') when 'Windows' 'cmd.exe /c echo triggered' else 'echo triggered' end describe 'concat_file with metaparameters with resources to notify' do basedir = default.tmpdir('concat') context 'when run should notify' do pp = <<-MANIFEST exec { 'trigger': path => $::path, command => "#{command}", refreshonly => true, } concat_file { "foobar": ensure => 'present', path => '#{basedir}/foobar', notify => Exec['trigger'], } concat_fragment { 'foo': target => 'foobar', content => 'foo', } MANIFEST it 'applies the manifest twice with stdout regex first' do expect(apply_manifest(pp, catch_failures: true).stdout).to match(%r{Triggered 'refresh'}) end it 'applies the manifest twice with stdout regex second' do expect(apply_manifest(pp, catch_changes: true).stdout).not_to match(%r{Triggered 'refresh'}) end end end puppetlabs-concat-4.2.0/spec/acceptance/native/pup_1963_spec_subscribed_resources.rb000066400000000000000000000021611324355651600306050ustar00rootroot00000000000000require 'spec_helper_acceptance' command = case fact('osfamily') when 'Windows' 'cmd.exe /c echo triggered' else 'echo triggered' end describe 'concat_file with metaparameters with subscribed resources' do basedir = default.tmpdir('concat') context 'when run should trigger refresh' do pp = <<-MANIFEST concat_file { "foobar": ensure => 'present', path => '#{basedir}/foobar', } concat_fragment { 'foo': target => 'foobar', content => 'foo', } exec { 'trigger': path => $::path, command => "#{command}", subscribe => Concat_file['foobar'], refreshonly => true, } MANIFEST it 'applies the manifest twice with stdout regex first' do expect(apply_manifest(pp, catch_failures: true).stdout).to match(%r{Triggered 'refresh'}) end it 'applies the manifest twice with stdout regex second' do expect(apply_manifest(pp, catch_changes: true).stdout).not_to match(%r{Triggered 'refresh'}) end end end puppetlabs-concat-4.2.0/spec/acceptance/native/quoted_paths_spec.rb000066400000000000000000000020011324355651600255110ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'concat_file with quoted paths' do basedir = default.tmpdir('concat') before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/concat test': ensure => directory, } MANIFEST apply_manifest(pp) end context 'with path with blanks' do pp = <<-MANIFEST concat_file { '#{basedir}/concat test/foo': } concat_fragment { '1': target => '#{basedir}/concat test/foo', content => 'string1', } concat_fragment { '2': target => '#{basedir}/concat test/foo', content => 'string2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/concat test/foo") do it { is_expected.to be_file } its(:content) { is_expected.to match %r{string1string2} } end end end puppetlabs-concat-4.2.0/spec/acceptance/native/replace_spec.rb000066400000000000000000000157301324355651600244410ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'concat_file' do basedir = default.tmpdir('concat') context 'with file replace => false' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': content => "file exists\n" } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat_file { '#{basedir}/file': replace => false, } concat_fragment { '1': target => '#{basedir}/file', content => '1', } concat_fragment { '2': target => '#{basedir}/file', content => '2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.to match 'file exists' end its(:content) do is_expected.not_to match '1' end its(:content) do is_expected.not_to match '2' end end end context 'with file replace => true' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': content => "file exists\n" } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat_file { '#{basedir}/file': replace => true, } concat_fragment { '1': target => '#{basedir}/file', content => '1', } concat_fragment { '2': target => '#{basedir}/file', content => '2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.not_to match 'file exists' end its(:content) do is_expected.to match '1' end its(:content) do is_expected.to match '2' end end end context 'when symlink should not succeed', unless: (fact('osfamily') == 'windows') do # XXX the core puppet file type will replace a symlink with a plain file # when using ensure => present and source => ... but it will not when using # ensure => present and content => ...; this is somewhat confusing behavior before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': ensure => link, target => '#{basedir}/dangling', } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat_file { '#{basedir}/file': replace => false, } concat_fragment { '1': target => '#{basedir}/file', content => '1', } concat_fragment { '2': target => '#{basedir}/file', content => '2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end # XXX specinfra doesn't support be_linked_to on AIX describe file("#{basedir}/file"), unless: (fact('osfamily') == 'AIX' || fact('osfamily') == 'windows') do it { is_expected.to be_linked_to "#{basedir}/dangling" } end describe file("#{basedir}/dangling") do # XXX serverspec does not have a matcher for 'exists' it { is_expected.not_to be_file } it { is_expected.not_to be_directory } end end context 'when symlink should succeed', unless: (fact('osfamily') == 'windows') do # XXX the core puppet file type will replace a symlink with a plain file # when using ensure => present and source => ... but it will not when using # ensure => present and content => ...; this is somewhat confusing behavior before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': ensure => link, target => '#{basedir}/dangling', } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat_file { '#{basedir}/file': replace => true, } concat_fragment { '1': target => '#{basedir}/file', content => '1', } concat_fragment { '2': target => '#{basedir}/file', content => '2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.to match '1' end its(:content) do is_expected.to match '2' end end end # symlink context 'when directory should not succeed' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': ensure => directory, } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat_file { '#{basedir}/file': } concat_fragment { '1': target => '#{basedir}/file', content => '1', } concat_fragment { '2': target => '#{basedir}/file', content => '2', } MANIFEST i = 0 num = 2 while i < num it 'applies the manifest twice with stderr for changing to file' do expect(apply_manifest(pp, expect_failures: true).stderr).to match(%r{change from '?directory'? to '?file'? failed}) end i += 1 end describe file("#{basedir}/file") do it { is_expected.to be_directory } end end # XXX # when there are no fragments, and the replace param will only replace # files and symlinks, not directories. The semantics either need to be # changed, extended, or a new param introduced to control directory # replacement. context 'when directory should succeed' do pending('This has yet to be implemented') # pp = <<-MANIFEST # concat_file { '#{basedir}/file': # } # # concat_fragment { '1': # target => '#{basedir}/file', # content => '1', # } # # concat_fragment { '2': # target => '#{basedir}/file', # content => '2', # } # MANIFEST # # it 'applies the manifest twice with no stderr' do # apply_manifest(pp, catch_failures: true) # apply_manifest(pp, catch_changes: true) # end # # describe file("#{basedir}/file") do # it { is_expected.to be_file } # its(:content) { is_expected.to match '1' } # end end # directory end puppetlabs-concat-4.2.0/spec/acceptance/native/symbolic_name_spec.rb000066400000000000000000000014251324355651600256430ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'concat_file symbolic name' do basedir = default.tmpdir('concat') pp = <<-MANIFEST concat_file { 'not_abs_path': path => '#{basedir}/file', } concat_fragment { '1': target => 'not_abs_path', content => '1', order => '01', } concat_fragment { '2': target => 'not_abs_path', content => '2', order => '02', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.to match '1' end its(:content) do is_expected.to match '2' end end end puppetlabs-concat-4.2.0/spec/acceptance/native/validation_spec.rb000066400000000000000000000015761324355651600251630ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'concat_file validate_cmd parameter', unless: (fact('kernel') != 'Linux') do basedir = default.tmpdir('concat') context 'with "/usr/bin/test -e %"' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat_file { '#{basedir}/file': validate_cmd => '/usr/bin/test -e %', } concat_fragment { 'content': target => '#{basedir}/file', content => 'content', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } it { is_expected.to contain 'content' } end end end puppetlabs-concat-4.2.0/spec/acceptance/native/warnings_spec.rb000066400000000000000000000016051324355651600246520ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'concat_fragment warnings' do basedir = default.tmpdir('concat') shared_examples 'has_warning' do |pp, w| it 'applies the manifest twice with a stderr regex first' do expect(apply_manifest(pp, catch_failures: true).stderr).to match(%r{#{Regexp.escape(w)}}m) end it 'applies the manifest twice with a stderr regex second' do expect(apply_manifest(pp, catch_changes: true).stderr).to match(%r{#{Regexp.escape(w)}}m) end end context 'when concat_fragment target not found' do context 'when target not found' do pp = <<-MANIFEST concat_file { 'file': path => '#{basedir}/file', } concat_fragment { 'foo': target => '#{basedir}/bar', content => 'bar', } MANIFEST w = 'not found in the catalog' it_behaves_like 'has_warning', pp, w end end end puppetlabs-concat-4.2.0/spec/acceptance/newline_spec.rb000066400000000000000000000030401324355651600231700ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'concat ensure_newline parameter' do basedir = default.tmpdir('concat') context 'when false' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': ensure_newline => false, } concat::fragment { '1': target => '#{basedir}/file', content => '1', } concat::fragment { '2': target => '#{basedir}/file', content => '2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) { is_expected.to match '12' } end end context 'when true' do pp = <<-MANIFEST concat { '#{basedir}/file': ensure_newline => true, } concat::fragment { '1': target => '#{basedir}/file', content => '1', } concat::fragment { '2': target => '#{basedir}/file', content => '2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.to match %r{1\n2\n} end end end end puppetlabs-concat-4.2.0/spec/acceptance/nodesets/000077500000000000000000000000001324355651600220175ustar00rootroot00000000000000puppetlabs-concat-4.2.0/spec/acceptance/nodesets/centos-7-x64.yml000066400000000000000000000002561324355651600246230ustar00rootroot00000000000000HOSTS: centos-7-x64: roles: - agent - default platform: el-7-x86_64 hypervisor: vagrant box: puppetlabs/centos-7.2-64-nocm CONFIG: type: foss puppetlabs-concat-4.2.0/spec/acceptance/nodesets/debian-8-x64.yml000066400000000000000000000002611324355651600245470ustar00rootroot00000000000000HOSTS: debian-8-x64: roles: - agent - default platform: debian-8-amd64 hypervisor: vagrant box: puppetlabs/debian-8.2-64-nocm CONFIG: type: foss puppetlabs-concat-4.2.0/spec/acceptance/nodesets/debian-9-x64.yml000066400000000000000000000005631324355651600245550ustar00rootroot00000000000000HOSTS: debian-9-x64: pe_dir: pe_ver: pe_upgrade_dir: pe_upgrade_ver: hypervisor: vmpooler platform: debian-9-x64 ruby_arch: x64 template: debian-9-x86_64 roles: - agent - master - database - dashboard - default CONFIG: nfs_server: none consoleport: 443 pooling_api: http://vmpooler.delivery.puppetlabs.net/ puppetlabs-concat-4.2.0/spec/acceptance/nodesets/default.yml000066400000000000000000000005221324355651600241650ustar00rootroot00000000000000--- HOSTS: windows2012-64-1: pe_dir: pe_ver: pe_upgrade_dir: pe_upgrade_ver: hypervisor: vmpooler platform: windows-2012-64 ruby_arch: x64 template: win-2012-x86_64 roles: - agent - default CONFIG: nfs_server: none consoleport: 443 pooling_api: http://vmpooler.delivery.puppetlabs.net/ puppetlabs-concat-4.2.0/spec/acceptance/nodesets/docker/000077500000000000000000000000001324355651600232665ustar00rootroot00000000000000puppetlabs-concat-4.2.0/spec/acceptance/nodesets/docker/centos-7.yml000066400000000000000000000005751324355651600254570ustar00rootroot00000000000000HOSTS: centos-7-x64: platform: el-7-x86_64 hypervisor: docker image: centos:7 docker_preserve_image: true docker_cmd: '["/usr/sbin/init"]' # install various tools required to get the image up to usable levels docker_image_commands: - 'yum install -y crontabs tar wget openssl sysvinit-tools iproute which initscripts' CONFIG: trace_limit: 200 puppetlabs-concat-4.2.0/spec/acceptance/nodesets/docker/debian-8.yml000066400000000000000000000005441324355651600254030ustar00rootroot00000000000000HOSTS: debian-8-x64: platform: debian-8-amd64 hypervisor: docker image: debian:8 docker_preserve_image: true docker_cmd: '["/sbin/init"]' docker_image_commands: - 'apt-get update && apt-get install -y net-tools wget locales strace lsof && echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && locale-gen' CONFIG: trace_limit: 200 puppetlabs-concat-4.2.0/spec/acceptance/nodesets/docker/ubuntu-14.04.yml000066400000000000000000000007321324355651600260010ustar00rootroot00000000000000HOSTS: ubuntu-1404-x64: platform: ubuntu-14.04-amd64 hypervisor: docker image: ubuntu:14.04 docker_preserve_image: true docker_cmd: '["/sbin/init"]' docker_image_commands: # ensure that upstart is booting correctly in the container - 'rm /usr/sbin/policy-rc.d && rm /sbin/initctl && dpkg-divert --rename --remove /sbin/initctl && apt-get update && apt-get install -y net-tools wget && locale-gen en_US.UTF-8' CONFIG: trace_limit: 200 puppetlabs-concat-4.2.0/spec/acceptance/order_spec.rb000066400000000000000000000021241324355651600226440ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'concat order' do basedir = default.tmpdir('concat') shared_examples 'sortby' do |order_by, match_output| pp = <<-MANIFEST concat { '#{basedir}/foo': order => '#{order_by}' } concat::fragment { '1': target => '#{basedir}/foo', content => 'string1', order => '1', } concat::fragment { '2': target => '#{basedir}/foo', content => 'string2', order => '2', } concat::fragment { '10': target => '#{basedir}/foo', content => 'string10', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/foo") do it { is_expected.to be_file } its(:content) { is_expected.to match match_output } end end describe 'alpha' do it_behaves_like 'sortby', 'alpha', %r{string1string10string2} end describe 'numeric' do it_behaves_like 'sortby', 'numeric', %r{string1string2string10} end end # concat order puppetlabs-concat-4.2.0/spec/acceptance/pup_1963_spec.rb000066400000000000000000000040301324355651600230150ustar00rootroot00000000000000require 'spec_helper_acceptance' command = case fact('osfamily') when 'Windows' 'cmd.exe /c echo triggered' else 'echo triggered' end describe 'with metaparameters' do describe 'with subscribed resources' do basedir = default.tmpdir('concat') context 'when run should trigger refresh' do pp = <<-MANIFEST concat { "foobar": ensure => 'present', path => '#{basedir}/foobar', } concat::fragment { 'foo': target => 'foobar', content => 'foo', } exec { 'trigger': path => $::path, command => "#{command}", subscribe => Concat['foobar'], refreshonly => true, } MANIFEST it 'applies the manifest twice with stdout regex first' do expect(apply_manifest(pp, catch_failures: true).stdout).to match(%r{Triggered 'refresh'}) end it 'applies the manifest twice with stdout regex second' do expect(apply_manifest(pp, catch_changes: true).stdout).not_to match(%r{Triggered 'refresh'}) end end end describe 'with resources to notify' do basedir = default.tmpdir('concat') context 'when run should notify' do pp = <<-MANIFEST exec { 'trigger': path => $::path, command => "#{command}", refreshonly => true, } concat { "foobar": ensure => 'present', path => '#{basedir}/foobar', notify => Exec['trigger'], } concat::fragment { 'foo': target => 'foobar', content => 'foo', } MANIFEST it 'applies the manifest twice with stdout regex first' do expect(apply_manifest(pp, catch_failures: true).stdout).to match(%r{Triggered 'refresh'}) end it 'applies the manifest twice with stdout regex second' do expect(apply_manifest(pp, catch_changes: true).stdout).not_to match(%r{Triggered 'refresh'}) end end end end puppetlabs-concat-4.2.0/spec/acceptance/quoted_paths_spec.rb000066400000000000000000000017551324355651600242420ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'quoted paths' do basedir = default.tmpdir('concat') before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/concat test': ensure => directory, } MANIFEST apply_manifest(pp) end context 'with path with blanks' do pp = <<-MANIFEST concat { '#{basedir}/concat test/foo': } concat::fragment { '1': target => '#{basedir}/concat test/foo', content => 'string1', } concat::fragment { '2': target => '#{basedir}/concat test/foo', content => 'string2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/concat test/foo") do it { is_expected.to be_file } its(:content) { is_expected.to match %r{string1string2} } end end end puppetlabs-concat-4.2.0/spec/acceptance/replace_spec.rb000066400000000000000000000155461324355651600231600ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'replacement of' do basedir = default.tmpdir('concat') context 'when file should not succeed' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': content => "file exists\n" } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': replace => false, } concat::fragment { '1': target => '#{basedir}/file', content => '1', } concat::fragment { '2': target => '#{basedir}/file', content => '2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.to match 'file exists' end its(:content) do is_expected.not_to match '1' end its(:content) do is_expected.not_to match '2' end end end context 'when file should succeed' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': content => "file exists\n" } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': replace => true, } concat::fragment { '1': target => '#{basedir}/file', content => '1', } concat::fragment { '2': target => '#{basedir}/file', content => '2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.not_to match 'file exists' end its(:content) do is_expected.to match '1' end its(:content) do is_expected.to match '2' end end end context 'when symlink should not succeed', unless: (fact('osfamily') == 'windows') do # XXX the core puppet file type will replace a symlink with a plain file # when using ensure => present and source => ... but it will not when using # ensure => present and content => ...; this is somewhat confusing behavior before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': ensure => link, target => '#{basedir}/dangling', } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': replace => false, } concat::fragment { '1': target => '#{basedir}/file', content => '1', } concat::fragment { '2': target => '#{basedir}/file', content => '2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end # XXX specinfra doesn't support be_linked_to on AIX describe file("#{basedir}/file"), unless: (fact('osfamily') == 'AIX' || fact('osfamily') == 'windows') do it { is_expected.to be_linked_to "#{basedir}/dangling" } end describe file("#{basedir}/dangling") do # XXX serverspec does not have a matcher for 'exists' it { is_expected.not_to be_file } it { is_expected.not_to be_directory } end end context 'when symlink should succeed', unless: (fact('osfamily') == 'windows') do # XXX the core puppet file type will replace a symlink with a plain file # when using ensure => present and source => ... but it will not when using # ensure => present and content => ...; this is somewhat confusing behavior before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': ensure => link, target => '#{basedir}/dangling', } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': replace => true, } concat::fragment { '1': target => '#{basedir}/file', content => '1', } concat::fragment { '2': target => '#{basedir}/file', content => '2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.to match '1' end its(:content) do is_expected.to match '2' end end end context 'when directory should not succeed' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory, } file { '#{basedir}/file': ensure => directory, } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': } concat::fragment { '1': target => '#{basedir}/file', content => '1', } concat::fragment { '2': target => '#{basedir}/file', content => '2', } MANIFEST i = 0 num = 2 while i < num it 'applies the manifest twice with stderr for changing to file' do expect(apply_manifest(pp, expect_failures: true).stderr).to match(%r{change from '?directory'? to '?file'? failed}) end i += 1 end describe file("#{basedir}/file") do it { is_expected.to be_directory } end end # XXX # when there are no fragments, and the replace param will only replace # files and symlinks, not directories. The semantics either need to be # changed, extended, or a new param introduced to control directory # replacement. context 'when directory should succeed', pending: 'not yet implemented' do pp = <<-MANIFEST concat { '#{basedir}/file': } concat::fragment { '1': target => '#{basedir}/file', content => '1', } concat::fragment { '2': target => '#{basedir}/file', content => '2', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) { is_expected.to match '1' } end end end puppetlabs-concat-4.2.0/spec/acceptance/specinfra_stubs.rb000066400000000000000000000011041324355651600237060ustar00rootroot00000000000000class Specinfra::Command::Windows::Base::File < Specinfra::Command::Windows::Base class << self def check_is_owned_by(file, owner) Backend::PowerShell::Command.new do exec "if((Get-Item '#{file}').GetAccessControl().Owner -match '#{owner}' -or ((Get-Item '#{file}').GetAccessControl().Owner -match '#{owner}').Length -gt 0){ exit 0 } else { exit 1 }" end end end end class Specinfra::Command::Base::File < Specinfra::Command::Base class << self def get_content(file) "cat '#{file}' 2> /dev/null || echo -n" end end end puppetlabs-concat-4.2.0/spec/acceptance/symbolic_name_spec.rb000066400000000000000000000014061324355651600243540ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'symbolic name' do basedir = default.tmpdir('concat') pp = <<-MANIFEST concat { 'not_abs_path': path => '#{basedir}/file', } concat::fragment { '1': target => 'not_abs_path', content => '1', order => '01', } concat::fragment { '2': target => 'not_abs_path', content => '2', order => '02', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.to match '1' end its(:content) do is_expected.to match '2' end end end puppetlabs-concat-4.2.0/spec/acceptance/validation_spec.rb000066400000000000000000000015651324355651600236730ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'concat validate_cmd parameter', unless: (fact('kernel') != 'Linux') do basedir = default.tmpdir('concat') context 'with "/usr/bin/test -e %"' do before(:all) do pp = <<-MANIFEST file { '#{basedir}': ensure => directory } MANIFEST apply_manifest(pp) end pp = <<-MANIFEST concat { '#{basedir}/file': validate_cmd => '/usr/bin/test -e %', } concat::fragment { 'content': target => '#{basedir}/file', content => 'content', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } it { is_expected.to contain 'content' } end end end puppetlabs-concat-4.2.0/spec/acceptance/warn_header_spec.rb000066400000000000000000000053741324355651600240220ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'concat warn =>' do basedir = default.tmpdir('concat') context 'when true should enable default warning message' do pp = <<-MANIFEST concat { '#{basedir}/file': warn => true, } concat::fragment { '1': target => '#{basedir}/file', content => '1', order => '01', } concat::fragment { '2': target => '#{basedir}/file', content => '2', order => '02', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.to match %r{# This file is managed by Puppet\. DO NOT EDIT\.} end its(:content) do is_expected.to match %r{1} end its(:content) do is_expected.to match %r{2} end end end context 'when false should not enable default warning message' do pp = <<-MANIFEST concat { '#{basedir}/file': warn => false, } concat::fragment { '1': target => '#{basedir}/file', content => '1', order => '01', } concat::fragment { '2': target => '#{basedir}/file', content => '2', order => '02', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.not_to match %r{# This file is managed by Puppet\. DO NOT EDIT\.} end its(:content) do is_expected.to match %r{1} end its(:content) do is_expected.to match %r{2} end end end context 'when foo should overide default warning message' do pp = <<-MANIFEST concat { '#{basedir}/file': warn => "# foo\n", } concat::fragment { '1': target => '#{basedir}/file', content => '1', order => '01', } concat::fragment { '2': target => '#{basedir}/file', content => '2', order => '02', } MANIFEST it 'applies the manifest twice with no stderr' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe file("#{basedir}/file") do it { is_expected.to be_file } its(:content) do is_expected.to match %r{# foo} end its(:content) do is_expected.to match %r{1} end its(:content) do is_expected.to match %r{2} end end end end puppetlabs-concat-4.2.0/spec/acceptance/warnings_spec.rb000066400000000000000000000015451324355651600233670ustar00rootroot00000000000000require 'spec_helper_acceptance' describe 'warnings' do basedir = default.tmpdir('concat') shared_examples 'has_warning' do |pp, w| it 'applies the manifest twice with a stderr regex' do expect(apply_manifest(pp, catch_failures: true).stderr).to match(%r{#{Regexp.escape(w)}}m) end it 'applies the manifest twice with a stderr regex' do expect(apply_manifest(pp, catch_changes: true).stderr).to match(%r{#{Regexp.escape(w)}}m) end end context 'when concat::fragment target not found' do context 'when target not found' do pp = <<-MANIFEST concat { 'file': path => '#{basedir}/file', } concat::fragment { 'foo': target => '#{basedir}/bar', content => 'bar', } MANIFEST w = 'not found in the catalog' it_behaves_like 'has_warning', pp, w end end end puppetlabs-concat-4.2.0/spec/defines/000077500000000000000000000000001324355651600175225ustar00rootroot00000000000000puppetlabs-concat-4.2.0/spec/defines/concat_fragment_spec.rb000066400000000000000000000102241324355651600242120ustar00rootroot00000000000000require 'spec_helper' describe 'concat::fragment' do shared_examples 'fragment' do |title, params| params = {} if params.nil? p = { content: nil, source: nil, order: 10, }.merge(params) let(:title) { title } let(:params) { params } let(:pre_condition) do "concat{ '#{p[:target]}': }" end it do is_expected.to contain_concat(p[:target]) end it do is_expected.to contain_concat_file(p[:target]) end it do is_expected.to contain_concat_fragment(title) end end context 'when title' do %w[0 1 a z].each do |title| it_behaves_like 'fragment', title, target: '/etc/motd', content: "content for #{title}" end end # title context 'when target =>' do ['./etc/motd', 'etc/motd', 'motd_header'].each do |target| context target do it_behaves_like 'fragment', target, target: '/etc/motd', content: "content for #{target}" end end context 'when false' do let(:title) { 'motd_header' } let(:params) { { target: false } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'target' expects a .*String.*}) end end end # target => context 'when content =>' do ['', 'ashp is our hero'].each do |content| context content do it_behaves_like 'fragment', 'motd_header', content: content, target: '/etc/motd' end end context 'when false' do let(:title) { 'motd_header' } let(:params) { { content: false, target: '/etc/motd' } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'content' expects a .*String.*}) end end end # content => context 'when source =>' do ['', '/foo/bar', ['/foo/bar', '/foo/baz']].each do |source| context source do it_behaves_like 'fragment', 'motd_header', source: source, target: '/etc/motd' end end context 'when false' do let(:title) { 'motd_header' } let(:params) { { source: false, target: '/etc/motd' } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'source' expects a .*String.*Array.*}) end end end # source => context 'when order =>' do ['', '42', 'a', 'z'].each do |order| context "'#{order}'" do it_behaves_like 'fragment', 'motd_header', order: order, target: '/etc/motd' end end context 'when false' do let(:title) { 'motd_header' } let(:params) { { order: false, target: '/etc/motd' } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{Evaluation Error.*expects.*Boolean.*}) end end context 'when 123:456' do let(:title) { 'motd_header' } let(:params) { { order: '123:456', target: '/etc/motd' } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{cannot contain}) end end context 'when 23/456' do let(:title) { 'motd_header' } let(:params) { { order: '123/456', target: '/etc/motd' } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{cannot contain}) end end context 'when 123\n456' do let(:title) { 'motd_header' } let(:params) { { order: "123\n456", target: '/etc/motd' } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{cannot contain}) end end end # order => context 'with more than one content source' do context 'with source and content' do let(:title) { 'motd_header' } let(:params) do { target: '/etc/motd', source: '/foo', content: 'bar', } end it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{Can\'t use \'source\' and \'content\' at the same time}m) end end end # more than one content source end puppetlabs-concat-4.2.0/spec/defines/concat_spec.rb000066400000000000000000000235071324355651600223370ustar00rootroot00000000000000require 'spec_helper' describe 'concat' do shared_examples 'concat' do |title, params, id| params = {} if params.nil? id = 'root' if id.nil? # default param values p = { ensure: 'present', path: title, owner: nil, group: nil, mode: '0644', warn: false, backup: 'puppet', replace: true, force: false, }.merge(params) file_defaults = { backup: p[:backup], } present_expect = { ensure: 'present', owner: p[:owner], group: p[:group], mode: p[:mode], path: p[:path], backup: p[:backup], replace: p[:replace], selinux_ignore_defaults: p[:selinux_ignore_defaults], selrange: p[:selrange], selrole: p[:selrole], seltype: p[:seltype], seluser: p[:seluser], force: p[:force], } let(:title) { title } let(:params) { params } let(:facts) do { id: id, osfamily: 'Debian', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', kernel: 'Linux', is_pe: false, } end if p[:ensure] == 'present' it do is_expected.to contain_concat(title).with(file_defaults.merge(present_expect)) end else it do is_expected.to contain_concat(title).with(file_defaults.merge(ensure: 'absent', backup: p[:backup])) end end end context 'when title without path param' do # title/name is the default value for the path param. therefore, the # title must be an absolute path unless path is specified ['/foo', '/foo/bar', '/foo/bar/baz'].each do |title| context title do it_behaves_like 'concat', '/etc/foo.bar' end end ['./foo', 'foo', 'foo/bar'].each do |title| context title do let(:title) { title } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{Stdlib::Unixpath}) end end end end context 'when title with path param' do ['/foo', 'foo', 'foo/bar'].each do |title| context title do it_behaves_like 'concat', title, path: '/etc/foo.bar' end end end context 'when title with special characters in title' do ['foo:bar', 'foo*bar', 'foo(bar)', 'foo@bar'].each do |title| context title do it_behaves_like 'concat', title, path: '/etc/foo.bar' end end end context 'when as non-root user' do it_behaves_like 'concat', '/etc/foo.bar', {}, 'bob' end context 'when ensure =>' do %w[present absent].each do |ens| context ens do it_behaves_like 'concat', '/etc/foo.bar', ensure: ens end end context 'when invalid' do let(:title) { '/etc/foo.bar' } let(:params) { { ensure: 'invalid' } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{expects a match for Enum\['absent', 'present'\]}) end end end # ensure => context 'when path =>' do context 'when /foo' do it_behaves_like 'concat', '/etc/foo.bar', path: '/foo' end context 'when false' do let(:title) { '/etc/foo.bar' } let(:params) { { path: false } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{Stdlib::Unixpath}) end end ['./foo', 'foo', 'foo/bar'].each do |path| context path do let(:title) { '/etc/foo.bar' } let(:params) { { path: path } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{Stdlib::Unixpath}) end end end end # path => context 'when owner =>' do ['apenney', 1000, '1001'].each do |owner| context owner do it_behaves_like 'concat', '/etc/foo.bar', owner: owner end end context 'when false' do let(:title) { '/etc/foo.bar' } let(:params) { { owner: false } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{Evaluation Error.*expects.*String.*Boolean.*}) end end end # owner => context 'when group =>' do ['apenney', 1000, '1001'].each do |group| context group do it_behaves_like 'concat', '/etc/foo.bar', group: group end end context 'when false' do let(:title) { '/etc/foo.bar' } let(:params) { { group: false } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{Evaluation Error.*expects.*String.*Boolean.*}) end end end # group => context 'when mode =>' do context 'when 1755' do it_behaves_like 'concat', '/etc/foo.bar', mode: '1755' end context 'when false' do let(:title) { '/etc/foo.bar' } let(:params) { { mode: false } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'mode' expects .*String.*}) end end end # mode => context 'when warn =>' do [true, false, '# foo'].each do |warn| context warn do it_behaves_like 'concat', '/etc/foo.bar', warn: warn end end context 'when (stringified boolean)' do %w[true yes on false no off].each do |warn| define warn do it_behaves_like 'concat', '/etc/foo.bar', warn: warn it 'creates a warning' do skip('rspec-puppet support for testing warning()') end end end end context 'when 123' do let(:title) { '/etc/foo.bar' } let(:params) { { warn: 123 } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'warn' expects .*Boolean.*String.*}) end end end # warn => context 'when show_diff =>' do [true, false].each do |show_diff| context show_diff do it_behaves_like 'concat', '/etc/foo.bar', show_diff: show_diff end end context 'when 123' do let(:title) { '/etc/foo.bar' } let(:params) { { show_diff: 123 } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'show_diff' expects .*Boolean.*}) end end end # show_diff => context 'when backup =>' do ['reverse', false, true].each do |backup| context backup.to_s do it_behaves_like 'concat', '/etc/foo.bar', backup: backup end end context 'when true' do let(:title) { '/etc/foo.bar' } let(:params) { { backup: [] } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'backup' expects .*Boolean.*String.*}) end end end # backup => context 'when replace =>' do [true, false].each do |replace| context replace do it_behaves_like 'concat', '/etc/foo.bar', replace: replace end end context 'when 123' do let(:title) { '/etc/foo.bar' } let(:params) { { replace: 123 } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'replace' expects .*Boolean.*}) end end end # replace => context 'when force =>' do [true, false].each do |force| context force do it_behaves_like 'concat', '/etc/foo.bar', force: force end end context 'when 123' do let(:title) { '/etc/foo.bar' } let(:params) { { force: 123 } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'force' expects .*Boolean.*}) end end end # force => context 'when order =>' do %w[alpha numeric].each do |order| context order do it_behaves_like 'concat', '/etc/foo.bar', order: order end end context 'when invalid' do let(:title) { '/etc/foo.bar' } let(:params) { { order: 'invalid' } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{expects a match for Enum\['alpha', 'numeric'\]}) end end end # order => context 'when ensure_newline =>' do [true, false].each do |ensure_newline| context 'when true' do it_behaves_like 'concat', '/etc/foo.bar', ensure_newline: ensure_newline end end context 'when 123' do let(:title) { '/etc/foo.bar' } let(:params) { { ensure_newline: 123 } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'ensure_newline' expects a Boolean value}) end end end # ensure_newline => context 'when validate_cmd =>' do context 'when /usr/bin/test -e %' do it_behaves_like 'concat', '/etc/foo.bar', validate_cmd: '/usr/bin/test -e %' end [1234, true].each do |cmd| context cmd do let(:title) { '/etc/foo.bar' } let(:params) { { validate_cmd: cmd } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter 'validate_cmd' expects.*String.*}) end end end end # validate_cmd => context 'when selinux_ignore_defaults =>' do let(:title) { '/etc/foo.bar' } [true, false].each do |v| context v do it_behaves_like 'concat', '/etc/foo.bar', selinux_ignore_defaults: v end end context 'when 123' do let(:title) { '/etc/foo.bar' } let(:params) { { selinux_ignore_defaults: 123 } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{Evaluation Error.*expects.*Boolean.*}) end end end # selinux_ignore_defaults => [ :selrange, :selrole, :seltype, :seluser, ].each do |p| context " #{p} =>" do let(:title) { '/etc/foo.bar' } context 'when foo' do it_behaves_like 'concat', '/etc/foo.bar', p => 'foo' end context 'when false' do let(:title) { '/etc/foo.bar' } let(:params) { { p => false } } it 'fails' do expect { catalogue }.to raise_error(Puppet::Error, %r{parameter '#{p}' expects.*String.*}) end end end # #{p} => end end puppetlabs-concat-4.2.0/spec/spec_helper.rb000066400000000000000000000014431324355651600207250ustar00rootroot00000000000000require 'puppetlabs_spec_helper/module_spec_helper' require 'rspec-puppet-facts' include RspecPuppetFacts default_facts = { puppetversion: Puppet.version, facterversion: Facter.version, } default_facts_path = File.expand_path(File.join(File.dirname(__FILE__), 'default_facts.yml')) default_module_facts_path = File.expand_path(File.join(File.dirname(__FILE__), 'default_module_facts.yml')) if File.exist?(default_facts_path) && File.readable?(default_facts_path) default_facts.merge!(YAML.safe_load(File.read(default_facts_path))) end if File.exist?(default_module_facts_path) && File.readable?(default_module_facts_path) default_facts.merge!(YAML.safe_load(File.read(default_module_facts_path))) end RSpec.configure do |c| c.default_facts = default_facts end require 'spec_helper_local' puppetlabs-concat-4.2.0/spec/spec_helper_acceptance.rb000066400000000000000000000011751324355651600230750ustar00rootroot00000000000000require 'beaker-rspec/spec_helper' require 'beaker-rspec/helpers/serverspec' require 'acceptance/specinfra_stubs' require 'beaker/puppet_install_helper' require 'beaker/module_install_helper' run_puppet_install_helper install_ca_certs unless ENV['PUPPET_INSTALL_TYPE'] =~ %r{pe}i install_module_on(hosts) install_module_dependencies_on(hosts) RSpec.configure do |c| # Readable test descriptions c.formatter = :documentation c.before(:each) do shell('mkdir -p /tmp/concat') end c.after(:each) do shell('rm -rf /tmp/concat /var/lib/puppet/concat') end c.treat_symbols_as_metadata_keys_with_true_values = true end puppetlabs-concat-4.2.0/spec/spec_helper_local.rb000066400000000000000000000027001324355651600220740ustar00rootroot00000000000000shared_examples 'Puppet::Parameter::Boolean' do |parameter| [true, :true, 'true', :yes, 'yes'].each do |value| it "accepts #{value} (#{value.class}) as a value" do resource[parameter] = value expect(resource[parameter]).to eq(true) end end [false, :false, 'false', :no, 'no'].each do |value| it "accepts #{value} (#{value.class}) as a value" do resource[parameter] = value expect(resource[parameter]).to eq(false) end end it 'does not accept "foo" as a value' do expect { resource[parameter] = 'foo' }.to raise_error(%r{Invalid value "foo"}) end end shared_examples 'a parameter that accepts only string values' do |parameter| it 'accepts a string value' do resource[parameter] = 'foo' expect(resource[parameter]).to eq('foo') end it 'does not accept an array value' do expect { resource[parameter] = %w[foo bar] }.to raise_error(%r{must be a String}) end it 'does not accept a hash value' do expect { resource[parameter] = { foo: 'bar' } }.to raise_error(%r{must be a String}) end it 'does not accept an integer value' do expect { resource[parameter] = 9001 }.to raise_error(%r{must be a String}) end it 'does not accept a boolean true value' do expect { resource[parameter] = true }.to raise_error(%r{must be a String}) end it 'does not accept a boolean false value' do expect { resource[parameter] = false }.to raise_error(%r{must be a String}) end end puppetlabs-concat-4.2.0/spec/unit/000077500000000000000000000000001324355651600170645ustar00rootroot00000000000000puppetlabs-concat-4.2.0/spec/unit/type/000077500000000000000000000000001324355651600200455ustar00rootroot00000000000000puppetlabs-concat-4.2.0/spec/unit/type/concat_file_spec.rb000066400000000000000000000071421324355651600236560ustar00rootroot00000000000000require 'spec_helper' describe Puppet::Type.type(:concat_file) do let(:resource) { described_class.new(name: '/foo/bar') } describe 'key attributes' do let(:subject) { described_class.key_attributes } it 'contain only :path' do is_expected.to eq([:path]) end end describe 'parameter :path' do it 'does not accept unqualified paths' do expect { resource[:path] = 'foo' }.to raise_error( %r{File paths must be fully qualified}, ) end end describe 'parameter :owner' do subject { described_class.attrclass(:owner) } it 'inherits Puppet::Type::File::Owner' do is_expected.to be < Puppet::Type::File::Owner end end describe 'parameter :group' do subject { described_class.attrclass(:group) } it 'inherits Puppet::Type::File::Group' do is_expected.to be < Puppet::Type::File::Group end end describe 'parameter :mode' do subject { described_class.attrclass(:mode) } it 'inherits Puppet::Type::File::Mode' do is_expected.to be < Puppet::Type::File::Mode end end describe 'parameter :order' do it 'accepts "alpha" as a value' do resource[:order] = 'alpha' expect(resource[:order]).to eq(:alpha) end it 'accepts "numeric" as a value' do resource[:order] = 'numeric' expect(resource[:order]).to eq(:numeric) end it 'does not accept "bar" as a value' do expect { resource[:order] = 'bar' }.to raise_error(%r{Invalid value "bar"}) end end describe 'parameter :backup' do it 'accepts true (TrueClass) as a value' do resource[:backup] = true expect(resource[:backup]).to eq(true) end it 'accepts false (FalseClass) as a value' do resource[:backup] = false expect(resource[:backup]).to eq(false) end it 'accepts "foo" as a value' do resource[:backup] = 'foo' expect(resource[:backup]).to eq('foo') end end describe 'parameter :selrange' do it_behaves_like 'a parameter that accepts only string values', :selrange end describe 'parameter :selrole' do it_behaves_like 'a parameter that accepts only string values', :selrole end describe 'parameter :seltype' do it_behaves_like 'a parameter that accepts only string values', :seltype end describe 'parameter :seluser' do it_behaves_like 'a parameter that accepts only string values', :seluser end describe 'parameter :replace' do it_behaves_like 'Puppet::Parameter::Boolean', :replace end describe 'parameter :ensure_newline' do it_behaves_like 'Puppet::Parameter::Boolean', :ensure_newline end describe 'parameter :show_diff' do it_behaves_like 'Puppet::Parameter::Boolean', :show_diff end describe 'parameter :selinux_ignore_defaults' do it_behaves_like 'Puppet::Parameter::Boolean', :selinux_ignore_defaults end describe 'parameter :force' do it_behaves_like 'Puppet::Parameter::Boolean', :force end describe 'parameter :format' do it 'accepts "plain" as a value' do resource[:format] = 'plain' expect(resource[:format]).to eq(:plain) end it 'accepts "yaml" as a value' do resource[:format] = 'yaml' expect(resource[:format]).to eq(:yaml) end it 'accepts "json" as a value' do resource[:format] = 'json' expect(resource[:format]).to eq(:json) end it 'accepts "json-pretty" as a value' do resource[:format] = 'json-pretty' expect(resource[:format]).to eq(:'json-pretty') end it 'does not accept "bar" as a value' do expect { resource[:format] = 'bar' }.to raise_error(%r{Invalid value "bar"}) end end end puppetlabs-concat-4.2.0/spec/unit/type/concat_fragment_spec.rb000066400000000000000000000066171324355651600245500ustar00rootroot00000000000000require 'spec_helper' describe Puppet::Type.type(:concat_fragment) do let(:resource) do described_class.new(name: 'foo', target: 'bar', content: 'baz') end describe 'key attributes' do let(:subject) { described_class.key_attributes } it 'contain only :name' do is_expected.to eq([:name]) end end describe 'parameter :target' do it_behaves_like 'a parameter that accepts only string values', :target end describe 'parameter :content' do it_behaves_like 'a parameter that accepts only string values', :content end describe 'parameter :source' do it 'accepts a string value' do resource[:source] = 'foo' expect(resource[:source]).to eq('foo') end it 'accepts an array value' do resource[:source] = %w[foo bar] expect(resource[:source]).to eq(%w[foo bar]) end it 'does not accept a hash value' do expect { resource[:source] = { foo: 'bar' } }.to raise_error(%r{must be a String or Array}) end it 'does not accept an integer value' do expect { resource[:source] = 9001 }.to raise_error(%r{must be a String or Array}) end it 'does not accept a boolean true value' do expect { resource[:source] = true }.to raise_error(%r{must be a String or Array}) end it 'does not accept a boolean false value' do expect { resource[:source] = false }.to raise_error(%r{must be a String or Array}) end end describe 'parameter :order' do it 'accepts a string value' do resource[:order] = 'foo' expect(resource[:order]).to eq('foo') end it 'accepts an integer value' do resource[:order] = 9001 expect(resource[:order]).to eq(9001) end it 'does not accept an array value' do expect { resource[:order] = %w[foo bar] }.to raise_error(%r{is not a string or integer}) end it 'does not accept a hash value' do expect { resource[:order] = { foo: 'bar' } }.to raise_error(%r{is not a string or integer}) end it 'does not accept a boolean true value' do expect { resource[:order] = true }.to raise_error(%r{is not a string or integer}) end it 'does not accept a boolean false value' do expect { resource[:order] = false }.to raise_error(%r{is not a string or integer}) end it 'does not accept a string with ":" in it/' do expect { resource[:order] = ':foo' }.to raise_error(%r{Order cannot contain}) end it 'does not accept a string with "\n" in it/' do expect { resource[:order] = "\nfoo" }.to raise_error(%r{Order cannot contain}) end it 'does not accept a string with "/" in it/' do expect { resource[:order] = '/foo' }.to raise_error(%r{Order cannot contain}) end end context 'without a value set for :target or :tag' do it 'throws an error' do expect { described_class.new(name: 'foo', content: 'baz') }.to raise_error(%r{No 'target' or 'tag' set}) end end context 'without a value set for both :content and :source' do it 'throws an error' do expect { described_class.new(name: 'foo', target: 'bar') }.to raise_error(%r{Set either 'source' or 'content'}) end end context 'with a value set for both :content and :source' do it 'throws an error' do expect { described_class.new(name: 'foo', target: 'bar', content: 'baz', source: 'qux') }.to raise_error(%r{Can't use 'source' and 'content' at the same time}) end end end