summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMicah <micah@leap.se>2016-05-24 10:19:32 -0400
committerMicah <micah@leap.se>2016-05-24 10:19:32 -0400
commit99500c162d8bd5ed017112e7568272ad08adff6c (patch)
tree99fb52a1c98ed1b4a795c857b6de682645d671db
Squashed 'puppet/modules/augeas/' content from commit 27e3359
git-subtree-dir: puppet/modules/augeas git-subtree-split: 27e33591776f0226f78877df350d6a52995265d8
-rw-r--r--.fixtures.yml5
-rw-r--r--.gitignore7
-rw-r--r--.puppet-lint.rc5
-rw-r--r--.sync.yml3
-rw-r--r--.travis.yml30
-rw-r--r--CHANGELOG.md45
-rw-r--r--Gemfile41
-rw-r--r--LICENSE201
-rw-r--r--README.md76
-rw-r--r--Rakefile11
-rw-r--r--lib/puppet/parser/functions/augeas.rb68
-rw-r--r--manifests/files.pp36
-rw-r--r--manifests/init.pp24
-rw-r--r--manifests/lens.pp79
-rw-r--r--manifests/packages.pp14
-rw-r--r--manifests/params.pp37
-rw-r--r--metadata.json62
-rw-r--r--spec/.rspec6
-rw-r--r--spec/acceptance/nodesets/centos-7-x86_64-docker.yml12
-rw-r--r--spec/acceptance/nodesets/centos-7-x86_64-openstack.yml13
-rw-r--r--spec/acceptance/nodesets/centos-7-x86_64-vagrant.yml10
-rw-r--r--spec/acceptance/nodesets/debian-6-x86_64-docker.yml12
-rw-r--r--spec/acceptance/nodesets/debian-6-x86_64-vagrant.yml10
-rw-r--r--spec/acceptance/nodesets/debian-7-x86_64-docker.yml12
-rw-r--r--spec/acceptance/nodesets/debian-7-x86_64-openstack.yml13
-rw-r--r--spec/acceptance/nodesets/debian-7-x86_64-vagrant.yml10
-rw-r--r--spec/acceptance/nodesets/debian-8-x86_64-docker.yml12
-rw-r--r--spec/acceptance/nodesets/debian-8-x86_64-openstack.yml13
-rw-r--r--spec/acceptance/nodesets/ubuntu-14.04-x86_64-vagrant.yml10
-rw-r--r--spec/classes/augeas_spec.rb149
-rw-r--r--spec/defines/augeas_lens_spec.rb112
-rw-r--r--spec/spec.opts6
-rw-r--r--spec/spec_helper.rb42
-rw-r--r--spec/unit/puppet/parser/functions/augeas_spec.rb83
34 files changed, 1269 insertions, 0 deletions
diff --git a/.fixtures.yml b/.fixtures.yml
new file mode 100644
index 00000000..f074a0ff
--- /dev/null
+++ b/.fixtures.yml
@@ -0,0 +1,5 @@
+fixtures:
+ repositories:
+ "stdlib": "git://github.com/puppetlabs/puppetlabs-stdlib.git"
+ symlinks:
+ "augeas": "#{source_dir}"
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..b5b7a00d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+pkg/
+Gemfile.lock
+vendor/
+spec/fixtures/
+.vagrant/
+.bundle/
+coverage/
diff --git a/.puppet-lint.rc b/.puppet-lint.rc
new file mode 100644
index 00000000..d8f5c59e
--- /dev/null
+++ b/.puppet-lint.rc
@@ -0,0 +1,5 @@
+--fail-on-warnings
+--relative
+--no-80chars
+--no-documentation
+--no-class_inherits_from_params_class-check
diff --git a/.sync.yml b/.sync.yml
new file mode 100644
index 00000000..677d00cf
--- /dev/null
+++ b/.sync.yml
@@ -0,0 +1,3 @@
+---
+.travis.yml:
+ forge_password: "GYBg84VC7Mx8BhAJ/56VjPU8tctatVVafGjuM9rJVmvJpbHkTz+XORHkvdVxCCkAkiq0/NZjwWpbxkQGMz0MxnXT5V/H90+h6YRHnWIEEqlW+5dR76uKZ9mO65cqk+l8UA+GUr5ZWKTS0fEJzjNR8aFM56DaM1u+SWIfjBXfE0k="
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 00000000..777290cc
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,30 @@
+---
+language: ruby
+sudo: false
+cache: bundler
+bundler_args: --without system_tests
+script: ["bundle exec rake validate", "bundle exec rake lint", "bundle exec rake spec SPEC_OPTS='--format documentation'", "bundle exec rake metadata"]
+matrix:
+ fast_finish: true
+ include:
+ - rvm: 1.8.7
+ env: PUPPET_GEM_VERSION="~> 3.0" FACTER_GEM_VERSION="~> 1.7.0"
+ - rvm: 1.9.3
+ env: PUPPET_GEM_VERSION="~> 3.0"
+ - rvm: 2.0.0
+ env: PUPPET_GEM_VERSION="~> 3.0"
+ - rvm: 2.0.0
+ env: PUPPET_GEM_VERSION="~> 3.0" FUTURE_PARSER="yes"
+notifications:
+ email: false
+deploy:
+ provider: puppetforge
+ user: camptocamp
+ password:
+ secure: "GYBg84VC7Mx8BhAJ/56VjPU8tctatVVafGjuM9rJVmvJpbHkTz+XORHkvdVxCCkAkiq0/NZjwWpbxkQGMz0MxnXT5V/H90+h6YRHnWIEEqlW+5dR76uKZ9mO65cqk+l8UA+GUr5ZWKTS0fEJzjNR8aFM56DaM1u+SWIfjBXfE0k="
+ on:
+ tags: true
+ # all_branches is required to use tags
+ all_branches: true
+ # Only publish if our main Ruby target builds
+ rvm: 1.9.3
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 00000000..3bebf66a
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,45 @@
+## 2015-01-19 - Release 1.1.6
+
+- Add puppet-ling plugins
+
+##2015-01-12 - Release 1.1.5
+
+- Fix LICENSE file
+- Add some puppet-lint plugins to Gemfile
+
+##2015-01-07 - Release 1.1.4
+
+- Manage unit tests with rspec-puppet-facts
+
+##2014-12-09 - Release 1.1.0
+
+- Add future parser tests
+- Convert specs to rspec3 syntax
+- Fix metadata.json
+
+##2014-11-17 - Release 1.0.3
+
+- Lint metadata.json
+
+##2014-11-04 - Release 1.0.2
+
+- Fix path in unit tests
+- Drop Puppet 2.7 support
+
+##2014-10-28 - Release 1.0.1
+- Add path to exec in augeas::lens
+
+##2014-10-20 - Release 1.0.0
+- Linting
+- Setup automatic Forge releases
+
+##2014-10-06 - Release 0.3.2
+- Remove symlink in spec/ directory (Fix #40)
+
+##2014-09-23 - Release 0.3.1
+- Centralize metadata files
+
+##2014-07-02 - Release 0.3.0
+###Summary
+- Add purge parameter
+- Cleanup unscoped variables
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 00000000..a3a9eca0
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,41 @@
+source ENV['GEM_SOURCE'] || "https://rubygems.org"
+
+group :development, :unit_tests do
+ gem 'rake', :require => false
+ gem 'rspec', '~> 3.1.0', :require => false
+ gem 'rspec-puppet', :require => false, :git => 'https://github.com/camptocamp/rspec-puppet', :branch => 'rspec3'
+ gem 'puppetlabs_spec_helper', :require => false
+ gem 'metadata-json-lint', :require => false
+ gem 'puppet-lint', :require => false
+ gem 'puppet-lint-unquoted_string-check', :require => false
+ gem 'puppet-lint-empty_string-check', :require => false
+ gem 'puppet-lint-spaceship_operator_without_tag-check', :require => false
+ gem 'puppet-lint-variable_contains_upcase', :require => false
+ gem 'puppet-lint-absolute_classname-check', :require => false
+ gem 'puppet-lint-undef_in_function-check', :require => false
+ gem 'puppet-lint-leading_zero-check', :require => false
+ gem 'puppet-lint-trailing_comma-check', :require => false
+ gem 'puppet-lint-file_ensure-check', :require => false
+ gem 'puppet-lint-version_comparison-check', :require => false
+ gem 'rspec-puppet-facts', :require => false
+end
+
+group :system_tests do
+ gem 'beaker', :require => false
+ gem 'beaker-rspec', :require => false
+ gem 'serverspec', :require => false
+end
+
+if facterversion = ENV['FACTER_GEM_VERSION']
+ gem 'facter', facterversion, :require => false
+else
+ gem 'facter', :require => false
+end
+
+if puppetversion = ENV['PUPPET_GEM_VERSION']
+ gem 'puppet', puppetversion, :require => false
+else
+ gem 'puppet', :require => false
+end
+
+# vim:ft=ruby
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 00000000..8d968b6c
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ 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.
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..e2055b07
--- /dev/null
+++ b/README.md
@@ -0,0 +1,76 @@
+# Augeas Puppet module
+
+[![Puppet Forge](http://img.shields.io/puppetforge/v/camptocamp/augeas.svg)](https://forge.puppetlabs.com/camptocamp/augeas)
+[![Build Status](https://travis-ci.org/camptocamp/puppet-augeas.png?branch=master)](https://travis-ci.org/camptocamp/puppet-augeas)
+
+**Install and configure Augeas.**
+
+This module is provided by [Camptocamp](http://www.camptocamp.com/)
+
+## Usage
+
+Simple usage:
+
+ include augeas
+
+### Classes
+
+The module provides an `augeas` class which installs and configures Augeas.
+
+
+* lets you force the augeas version by defining `$augeas_version`, otherwise puppet will
+ only ensure the packages are present;
+* lets you force the ruby library version by defining `$augeas_ruby_version`, otherwise puppet will
+ only ensure the libaugeas-ruby version will be installed according to internal critera;
+* provides an `augeas()` master-side function to manipulate strings using Augeas;
+
+Note: the `augeas` class realizes all `augeas` resources in order to ensure they are managed after the required Augeas packages.
+
+
+### Definitions
+
+#### `augeas::lens`
+
+The `augeas::lens` definition allows you to deploy an Augeas lens and any associated test files, running unit tests and not installing if they fail:
+
+Parameters:
+
+- *ensure*: present/absent
+- *lens_source*: the source for the lens
+- *test_source*: optionally, the source for the test file.
+- *stock_since*: optionally, indicate in which version of Augeas
+ the lens became stock, so it will not be deployed above that version.
+
+Example usage:
+
+ augeas::lens { 'networkmanager':
+ lens_source => 'puppet:///modules/networkmanager/lenses/networkmanager.aug',
+ test_source => 'puppet:///modules/networkmanager/lenses/test_networkmanager.aug',
+ stock_since => '1.0.0',
+ }
+
+### Functions
+
+#### `augeas()`
+
+Modifies a string using Augeas.
+
+*Example:*
+
+ augeas("proc /proc proc nodev,noexec,nosuid 0 0\n", 'Fstab.lns', ['rm ./1/opt[3]'])
+
+Would result in:
+
+ "proc /proc proc nodev,noexec 0 0\n"
+
+
+- *Type*: rvalue
+
+## Contributing
+
+Please report bugs and feature request using [GitHub issue
+tracker](https://github.com/camptocamp/puppet-augeas/issues).
+
+For pull requests, it is very much appreciated to check your Puppet manifest
+with [puppet-lint](https://github.com/camptocamp/puppet-augeas/issues) to follow the recommended Puppet style guidelines from the
+[Puppet Labs style guide](http://docs.puppetlabs.com/guides/style_guide.html).
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 00000000..f87e6088
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,11 @@
+require 'puppetlabs_spec_helper/rake_tasks'
+require 'puppet-lint/tasks/puppet-lint'
+
+Rake::Task[:lint].clear
+PuppetLint::RakeTask.new :lint do |config|
+ config.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp", "vendor/**/*.pp"]
+ config.disable_checks = ['80chars']
+ config.fail_on_warnings = true
+end
+
+PuppetSyntax.exclude_paths = ["spec/fixtures/**/*.pp", "vendor/**/*"]
diff --git a/lib/puppet/parser/functions/augeas.rb b/lib/puppet/parser/functions/augeas.rb
new file mode 100644
index 00000000..08026f77
--- /dev/null
+++ b/lib/puppet/parser/functions/augeas.rb
@@ -0,0 +1,68 @@
+#
+# augeas.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:augeas, :type => :rvalue, :doc => <<-EOS
+Modifies a string using Augeas.
+
+*Example:*
+
+ augeas("proc /proc proc nodev,noexec,nosuid 0 0\n", 'Fstab.lns', ['rm ./1/opt[3]'])
+
+Would result in:
+
+ "proc /proc proc nodev,noexec 0 0\n"
+ EOS
+ ) do |arguments|
+ unless Puppet.features.augeas?
+ raise Puppet::ParseError, ('augeas(): this function requires the augeas feature. See http://projects.puppetlabs.com/projects/puppet/wiki/Puppet_Augeas#Pre-requisites for how to activate it.')
+ end
+
+ # Check that 2 arguments have been given ...
+ raise(Puppet::ParseError, 'augeas(): Wrong number of arguments ' +
+ "given (#{arguments.size} for 3)") if arguments.size != 3
+
+ content = arguments[0]
+ lens = arguments[1]
+ changes = arguments[2]
+
+ # Check arguments
+ raise(Puppet::ParseError, 'augeas(): content must be a string') unless content.is_a?(String)
+ raise(Puppet::ParseError, 'augeas(): lens must be a string') unless lens.is_a?(String)
+ raise(Puppet::ParseError, 'augeas(): changes must be an array') unless changes.is_a?(Array)
+
+ require 'augeas'
+ aug = Augeas::open(nil, nil, Augeas::NO_MODL_AUTOLOAD)
+ augeas_version = aug.get('/augeas/version')
+ raise(Puppet::ParseError, 'augeas(): requires Augeas 1.0.0 or greater') unless Puppet::Util::Package.versioncmp(augeas_version, '1.0.0') >= 0
+ raise(Puppet::ParseError, 'augeas(): requires ruby-augeas 0.5.0 or greater') unless aug.methods.include?('text_store')
+
+ result = nil
+ begin
+ aug.set('/input', content)
+ aug.text_store(lens, '/input', '/store')
+ unless aug.match("/augeas/text/store//error").empty?
+ error = aug.get("/augeas/text/store//error/message")
+ raise Puppet::ParseError, "augeas(): Failed to parse string with lens #{lens}: #{error}"
+ end
+
+ # Apply changes
+ aug.context = '/store'
+ changes.each do |c|
+ r = aug.srun(c)
+ raise Puppet::ParseError, "augeas(): Failed to apply change to tree" unless r and r[0] >= 0
+ end
+ unless aug.text_retrieve(lens, '/input', '/store', '/output')
+ error = aug.get("/augeas/text/store//error/message")
+ raise Puppet::ParseError, "augeas(): Failed to apply changes with lens #{lens}: #{error}"
+ end
+ result = aug.get("/output")
+ ensure
+ aug.close
+ end
+ return result
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/manifests/files.pp b/manifests/files.pp
new file mode 100644
index 00000000..c73c19bb
--- /dev/null
+++ b/manifests/files.pp
@@ -0,0 +1,36 @@
+# Class: augeas::files
+#
+# Sets up directories and files for Augeas
+#
+class augeas::files {
+ $lens_dir = $augeas::lens_dir
+
+ # ensure no file not managed by puppet ends up in there.
+ file { $lens_dir:
+ ensure => directory,
+ purge => $::augeas::purge,
+ force => true,
+ recurse => true,
+ recurselimit => 1,
+ mode => '0644',
+ owner => 'root',
+ group => 'root',
+ }
+
+ file { "${lens_dir}/dist":
+ ensure => directory,
+ purge => false,
+ mode => '0644',
+ owner => 'root',
+ group => 'root',
+ }
+
+ file { "${lens_dir}/tests":
+ ensure => directory,
+ purge => $::augeas::purge,
+ force => true,
+ mode => '0644',
+ owner => 'root',
+ group => 'root',
+ }
+}
diff --git a/manifests/init.pp b/manifests/init.pp
new file mode 100644
index 00000000..41f4f875
--- /dev/null
+++ b/manifests/init.pp
@@ -0,0 +1,24 @@
+# Class: augeas
+#
+# Install and configure Augeas
+#
+# Parameters:
+# ['version'] - the desired version of Augeas
+# ['ruby_version'] - the desired version of the Ruby bindings for Augeas
+# ['lens_dir'] - the lens directory to use
+# ['purge'] - whether to purge lens directories
+class augeas (
+ $version = present,
+ $ruby_version = present,
+ $lens_dir = $augeas::params::lens_dir,
+ $purge = true,
+) inherits augeas::params {
+
+ class {'::augeas::packages': } ->
+ class {'::augeas::files': } ->
+ Class['augeas']
+
+ # lint:ignore:spaceship_operator_without_tag
+ Package['ruby-augeas', $augeas::params::augeas_pkgs] -> Augeas <| |>
+ # lint:endignore
+}
diff --git a/manifests/lens.pp b/manifests/lens.pp
new file mode 100644
index 00000000..b5b9acd6
--- /dev/null
+++ b/manifests/lens.pp
@@ -0,0 +1,79 @@
+# Definition: augeas::lens
+#
+# Deploy an Augeas lens (and its test file).
+# Check the lens (and run the unit tests) automatically and remove the files if
+# the checks fail.
+#
+# Parameters:
+# ['ensure'] - present/absent
+# ['lens_source'] - the source for the lens
+# ['test_source'] - optionally, the source for the test file.
+# ['stock_since'] - optionally, indicate in which version of Augeas
+# the lens became stock, so it will not be deployed
+# above that version.
+#
+# Example usage:
+#
+# augeas::lens { 'networkmanager':
+# lens_source => 'puppet:///modules/networkmanager/lenses/networkmanager.aug',
+# test_source => 'puppet:///modules/networkmanager/lenses/test_networkmanager.aug',
+# stock_since => '1.0.0',
+# }
+#
+define augeas::lens (
+ $lens_source,
+ $ensure=present,
+ $test_source=false,
+ $stock_since=false,
+) {
+ if !defined(Class['augeas']) {
+ fail('You must declare the augeas class before using augeas::lens')
+ }
+
+ File {
+ owner => 'root',
+ group => 'root',
+ mode => '0644',
+ }
+
+ Exec {
+ path => $::path,
+ }
+
+ if (!$stock_since or versioncmp($::augeasversion, $stock_since) < 0) {
+
+ validate_re(
+ $augeas::lens_dir,
+ '/.*',
+ "'${augeas::lens_dir}' is not a valid path for lens ${name}"
+ )
+
+ $lens_dest = "${augeas::lens_dir}/${name}.aug"
+ $test_dest = "${augeas::lens_dir}/tests/test_${name}.aug"
+
+ file { $lens_dest:
+ ensure => $ensure,
+ source => $lens_source,
+ }
+
+ exec { "Typecheck lens ${name}":
+ command => "augparse -I ${augeas::lens_dir} ${lens_dest} || (rm -f ${lens_dest} && exit 1)",
+ refreshonly => true,
+ subscribe => File[$lens_dest],
+ }
+
+ if $test_source {
+ file { $test_dest:
+ ensure => $ensure,
+ source => $test_source,
+ notify => Exec["Test lens ${name}"],
+ }
+
+ exec { "Test lens ${name}":
+ command => "augparse -I ${augeas::lens_dir} ${test_dest} || (rm -f ${lens_dest} && rm -f ${test_dest} && exit 1)",
+ refreshonly => true,
+ subscribe => File[$lens_dest, $test_dest],
+ }
+ }
+ }
+}
diff --git a/manifests/packages.pp b/manifests/packages.pp
new file mode 100644
index 00000000..ff8628df
--- /dev/null
+++ b/manifests/packages.pp
@@ -0,0 +1,14 @@
+# Class: augeas::packages
+#
+# Sets up packages for Augeas
+#
+class augeas::packages {
+ package { $::augeas::params::augeas_pkgs:
+ ensure => $::augeas::version,
+ }
+
+ package { 'ruby-augeas':
+ ensure => $::augeas::ruby_version,
+ name => $::augeas::params::ruby_pkg,
+ }
+}
diff --git a/manifests/params.pp b/manifests/params.pp
new file mode 100644
index 00000000..e5400339
--- /dev/null
+++ b/manifests/params.pp
@@ -0,0 +1,37 @@
+# Class: augeas::params
+#
+# Default parameters for the Augeas module
+#
+class augeas::params {
+ $lens_dir = '/usr/share/augeas/lenses'
+
+ case $::osfamily {
+ 'RedHat': {
+ $ruby_pkg = 'ruby-augeas'
+ $augeas_pkgs = ['augeas', 'augeas-libs']
+ }
+
+ 'Suse': {
+ # RPM Sources: https://build.opensuse.org/project/show/systemsmanagement:puppet
+ # SLES 11 SP3
+ if versioncmp($::rubyversion, '1.8.7') >= 0 {
+ $ruby_pkg = 'ruby1.8-rubygem-ruby-augeas'
+ # SLES 12
+ } else {
+ $ruby_pkg = 'ruby2.1-rubygem-ruby-augeas'
+ }
+ $augeas_pkgs = ['augeas', 'augeas-lenses', 'libaugeas0' ]
+ }
+
+ 'Debian': {
+ if versioncmp($::rubyversion, '1.9.1') >= 0 {
+ $ruby_pkg = 'libaugeas-ruby1.9.1'
+ } else {
+ $ruby_pkg = 'libaugeas-ruby1.8'
+ }
+ $augeas_pkgs = ['augeas-lenses', 'libaugeas0', 'augeas-tools']
+ }
+
+ default: { fail("Unsupported OS family: ${::osfamily}") }
+ }
+}
diff --git a/metadata.json b/metadata.json
new file mode 100644
index 00000000..f6bfbf96
--- /dev/null
+++ b/metadata.json
@@ -0,0 +1,62 @@
+{
+ "name": "camptocamp-augeas",
+ "version": "1.1.6",
+ "author": "camptocamp",
+ "summary": "Camptocamp Augeas module",
+ "license": "Apache-2.0",
+ "source": "https://github.com/camptocamp/puppet-augeas",
+ "project_page": "https://github.com/camptocamp/puppet-augeas",
+ "issues_url": "https://github.com/camptocamp/puppet-augeas/issues",
+ "description": "Augeas Module for Puppet",
+ "dependencies": [
+ {
+ "name": "puppetlabs/stdlib",
+ "version_requirement": ">= 3.2.0 <5.0.0"
+ }
+ ],
+ "requirements": [
+ {
+ "name": "pe",
+ "version_requirement": "3.x"
+ },
+ {
+ "name": "puppet",
+ "version_requirement": "3.x"
+ }
+ ],
+ "operatingsystem_support": [
+ {
+ "operatingsystem": "Debian",
+ "operatingsystemrelease": [
+ "6",
+ "7"
+ ]
+ },
+ {
+ "operatingsystem": "Ubuntu",
+ "operatingsystemrelease": [
+ "10.04",
+ "12.04",
+ "14.04"
+ ]
+ },
+ {
+ "operatingsystem": "RedHat",
+ "operatingsystemrelease": [
+ "5",
+ "6"
+ ]
+ }
+ ],
+ "puppet_version": [
+ "2.7",
+ "3.0",
+ "3.1",
+ "3.2",
+ "3.3",
+ "3.4",
+ "3.5",
+ "3.6",
+ "3.7"
+ ]
+}
diff --git a/spec/.rspec b/spec/.rspec
new file mode 100644
index 00000000..91cd6427
--- /dev/null
+++ b/spec/.rspec
@@ -0,0 +1,6 @@
+--format
+s
+--colour
+--loadby
+mtime
+--backtrace
diff --git a/spec/acceptance/nodesets/centos-7-x86_64-docker.yml b/spec/acceptance/nodesets/centos-7-x86_64-docker.yml
new file mode 100644
index 00000000..599a681f
--- /dev/null
+++ b/spec/acceptance/nodesets/centos-7-x86_64-docker.yml
@@ -0,0 +1,12 @@
+HOSTS:
+ centos-7-x64:
+ default_apply_opts:
+ strict_variables:
+ platform: el-7-x86_64
+ hypervisor : docker
+ image: centos:7
+ # This stops the image from being deleted on completion, speeding up the process.
+ docker_preserve_image: true
+CONFIG:
+ type: foss
+ log_level: debug
diff --git a/spec/acceptance/nodesets/centos-7-x86_64-openstack.yml b/spec/acceptance/nodesets/centos-7-x86_64-openstack.yml
new file mode 100644
index 00000000..37dfc5f9
--- /dev/null
+++ b/spec/acceptance/nodesets/centos-7-x86_64-openstack.yml
@@ -0,0 +1,13 @@
+HOSTS:
+ centos-7-x64:
+ default_apply_opts:
+ strict_variables:
+ platform: el-7-x86_64
+ hypervisor : openstack
+ flavor: m1.small
+ image: centos-7-x86_64-genericcloud-20140929_01
+ user: centos
+CONFIG:
+ type: foss
+ log_level: debug
+ openstack_network: default
diff --git a/spec/acceptance/nodesets/centos-7-x86_64-vagrant.yml b/spec/acceptance/nodesets/centos-7-x86_64-vagrant.yml
new file mode 100644
index 00000000..fe0f83b8
--- /dev/null
+++ b/spec/acceptance/nodesets/centos-7-x86_64-vagrant.yml
@@ -0,0 +1,10 @@
+HOSTS:
+ centos-7-x64:
+ default_apply_opts:
+ strict_variables:
+ platform: el-7-x86_64
+ hypervisor : vagrant
+ box : puppetlabs/centos-7.0-64-nocm
+CONFIG:
+ type: foss
+ log_level: debug
diff --git a/spec/acceptance/nodesets/debian-6-x86_64-docker.yml b/spec/acceptance/nodesets/debian-6-x86_64-docker.yml
new file mode 100644
index 00000000..0296d129
--- /dev/null
+++ b/spec/acceptance/nodesets/debian-6-x86_64-docker.yml
@@ -0,0 +1,12 @@
+HOSTS:
+ debian-6-x64:
+ default_apply_opts:
+ strict_variables:
+ platform: debian-6-amd64
+ hypervisor : docker
+ image: debian:6
+ # This stops the image from being deleted on completion, speeding up the process.
+ docker_preserve_image: true
+CONFIG:
+ type: foss
+ log_level: debug
diff --git a/spec/acceptance/nodesets/debian-6-x86_64-vagrant.yml b/spec/acceptance/nodesets/debian-6-x86_64-vagrant.yml
new file mode 100644
index 00000000..23dae1b0
--- /dev/null
+++ b/spec/acceptance/nodesets/debian-6-x86_64-vagrant.yml
@@ -0,0 +1,10 @@
+HOSTS:
+ debian-6-x64:
+ default_apply_opts:
+ strict_variables:
+ platform: debian-6-amd64
+ hypervisor : vagrant
+ box : puppetlabs/debian-6.0.10-64-nocm
+CONFIG:
+ type: foss
+ log_level: debug
diff --git a/spec/acceptance/nodesets/debian-7-x86_64-docker.yml b/spec/acceptance/nodesets/debian-7-x86_64-docker.yml
new file mode 100644
index 00000000..ef1c9b22
--- /dev/null
+++ b/spec/acceptance/nodesets/debian-7-x86_64-docker.yml
@@ -0,0 +1,12 @@
+HOSTS:
+ debian-7-x64:
+ default_apply_opts:
+ strict_variables:
+ platform: debian-7-amd64
+ hypervisor : docker
+ image: debian:7
+ # This stops the image from being deleted on completion, speeding up the process.
+ docker_preserve_image: true
+CONFIG:
+ type: foss
+ log_level: debug
diff --git a/spec/acceptance/nodesets/debian-7-x86_64-openstack.yml b/spec/acceptance/nodesets/debian-7-x86_64-openstack.yml
new file mode 100644
index 00000000..e52336be
--- /dev/null
+++ b/spec/acceptance/nodesets/debian-7-x86_64-openstack.yml
@@ -0,0 +1,13 @@
+HOSTS:
+ debian-7-x64:
+ default_apply_opts:
+ strict_variables:
+ platform: debian-7-amd64
+ hypervisor : openstack
+ flavor: m1.small
+ image: debian-7-amd64-20141121
+ user: debian
+CONFIG:
+ type: foss
+ log_level: debug
+ openstack_network: default
diff --git a/spec/acceptance/nodesets/debian-7-x86_64-vagrant.yml b/spec/acceptance/nodesets/debian-7-x86_64-vagrant.yml
new file mode 100644
index 00000000..86c2165d
--- /dev/null
+++ b/spec/acceptance/nodesets/debian-7-x86_64-vagrant.yml
@@ -0,0 +1,10 @@
+HOSTS:
+ debian-7-x64:
+ default_apply_opts:
+ strict_variables:
+ platform: debian-7-amd64
+ hypervisor : vagrant
+ box : puppetlabs/debian-7.8-64-nocm
+CONFIG:
+ type: foss
+ log_level: debug
diff --git a/spec/acceptance/nodesets/debian-8-x86_64-docker.yml b/spec/acceptance/nodesets/debian-8-x86_64-docker.yml
new file mode 100644
index 00000000..28c3e02f
--- /dev/null
+++ b/spec/acceptance/nodesets/debian-8-x86_64-docker.yml
@@ -0,0 +1,12 @@
+HOSTS:
+ debian-8-x64:
+ default_apply_opts:
+ strict_variables:
+ platform: debian-8-amd64
+ hypervisor : docker
+ image: debian:8
+ # This stops the image from being deleted on completion, speeding up the process.
+ docker_preserve_image: true
+CONFIG:
+ type: foss
+ log_level: debug
diff --git a/spec/acceptance/nodesets/debian-8-x86_64-openstack.yml b/spec/acceptance/nodesets/debian-8-x86_64-openstack.yml
new file mode 100644
index 00000000..194ca460
--- /dev/null
+++ b/spec/acceptance/nodesets/debian-8-x86_64-openstack.yml
@@ -0,0 +1,13 @@
+HOSTS:
+ debian-8-x64:
+ default_apply_opts:
+ strict_variables:
+ platform: debian-8-amd64
+ hypervisor : openstack
+ flavor: m1.small
+ image: debian-8-amd64-20141121
+ user: debian
+CONFIG:
+ type: foss
+ openstack_network: default
+ log_level: debug
diff --git a/spec/acceptance/nodesets/ubuntu-14.04-x86_64-vagrant.yml b/spec/acceptance/nodesets/ubuntu-14.04-x86_64-vagrant.yml
new file mode 100644
index 00000000..a3edb70f
--- /dev/null
+++ b/spec/acceptance/nodesets/ubuntu-14.04-x86_64-vagrant.yml
@@ -0,0 +1,10 @@
+HOSTS:
+ ubuntu-14.04-x64:
+ default_apply_opts:
+ strict_variables:
+ platform: ubuntu-14.04-amd64
+ hypervisor : vagrant
+ box : puppetlabs/ubuntu-14.04-64-nocm
+CONFIG:
+ type: foss
+ log_level: debug
diff --git a/spec/classes/augeas_spec.rb b/spec/classes/augeas_spec.rb
new file mode 100644
index 00000000..ab4241f4
--- /dev/null
+++ b/spec/classes/augeas_spec.rb
@@ -0,0 +1,149 @@
+require 'spec_helper'
+
+describe 'augeas' do
+
+ context 'when on an unsupported Operating System' do
+ let (:facts) do
+ {
+ :osfamily => 'MS-DOS',
+ }
+ end
+
+ it 'should fail' do
+ expect { is_expected.to contain_package('ruby-augeas') }.to raise_error(Puppet::Error, /Unsupported OS family/)
+ end
+ end
+
+ on_supported_os.each do |os, facts|
+ context "on #{os}" do
+ let(:facts) do
+ facts
+ end
+
+ context 'without params' do
+ case facts[:osfamily]
+ when 'Debian'
+ it { is_expected.to contain_package('libaugeas0').with(
+ :ensure => 'present'
+ ) }
+ it { is_expected.to contain_package('augeas-tools').with(
+ :ensure => 'present'
+ ) }
+ it { is_expected.to contain_package('augeas-lenses').with(
+ :ensure => 'present'
+ ) }
+ case facts[:lsbdistcodename]
+ when 'squeeze', 'lucid', 'precise'
+ it { is_expected.to contain_package('ruby-augeas').with(
+ :ensure => 'present',
+ :name => 'libaugeas-ruby1.8'
+ ) }
+ else
+ it { is_expected.to contain_package('ruby-augeas').with(
+ :ensure => 'present',
+ :name => 'libaugeas-ruby1.9.1'
+ ) }
+ end
+ when 'RedHat'
+ it { is_expected.to contain_package('augeas').with(
+ :ensure => 'present'
+ ) }
+ it { is_expected.to contain_package('augeas-libs').with(
+ :ensure => 'present'
+ ) }
+ it { is_expected.to contain_package('ruby-augeas').with(
+ :ensure => 'present',
+ :name => 'ruby-augeas'
+ ) }
+ end
+ it { is_expected.to contain_file('/usr/share/augeas/lenses').with(
+ :ensure => 'directory',
+ :purge => 'true',
+ :force => 'true',
+ :recurse => 'true',
+ :recurselimit => 1
+ ) }
+ it { is_expected.to contain_file('/usr/share/augeas/lenses/dist').with(
+ :ensure => 'directory',
+ :purge => 'false'
+ ) }
+ it { is_expected.to contain_file('/usr/share/augeas/lenses/tests').with(
+ :ensure => 'directory',
+ :purge => 'true',
+ :force => 'true'
+ ).without(:recurse) }
+ end
+
+ context 'when versions are specified' do
+ let (:params) do
+ {
+ :version => '1.2.3',
+ :ruby_version => '3.2.1',
+ }
+ end
+
+ case facts[:osfamily]
+ when 'Debian'
+ it { is_expected.to contain_package('libaugeas0').with(
+ :ensure => '1.2.3'
+ ) }
+ it { is_expected.to contain_package('augeas-tools').with(
+ :ensure => '1.2.3'
+ ) }
+ it { is_expected.to contain_package('augeas-lenses').with(
+ :ensure => '1.2.3'
+ ) }
+ case facts[:lsbdistcodename]
+ when 'squeeze', 'lucid', 'precise'
+ it { is_expected.to contain_package('ruby-augeas').with(
+ :ensure => '3.2.1',
+ :name => 'libaugeas-ruby1.8'
+ ) }
+ else
+ it { is_expected.to contain_package('ruby-augeas').with(
+ :ensure => '3.2.1',
+ :name => 'libaugeas-ruby1.9.1'
+ ) }
+ end
+ when 'RedHat'
+ it { is_expected.to contain_package('augeas').with(
+ :ensure => '1.2.3'
+ ) }
+ it { is_expected.to contain_package('augeas-libs').with(
+ :ensure => '1.2.3'
+ ) }
+ it { is_expected.to contain_package('ruby-augeas').with(
+ :ensure => '3.2.1',
+ :name => 'ruby-augeas'
+ ) }
+ end
+
+ end
+
+ context 'with a non standard lens_dir' do
+ let (:params) do
+ {
+ :lens_dir => '/opt/augeas/lenses',
+ }
+ end
+
+ it { is_expected.to contain_file('/opt/augeas/lenses').with(
+ :ensure => 'directory',
+ :purge => 'true',
+ :force => 'true',
+ :recurse => 'true',
+ :recurselimit => 1
+ ) }
+ it { is_expected.to contain_file('/opt/augeas/lenses/dist').with(
+ :ensure => 'directory',
+ :purge => 'false'
+ ) }
+ it { is_expected.to contain_file('/opt/augeas/lenses/tests').with(
+ :ensure => 'directory',
+ :purge => 'true',
+ :force => 'true'
+ ).without(:recurse) }
+ end
+ end
+ end
+end
diff --git a/spec/defines/augeas_lens_spec.rb b/spec/defines/augeas_lens_spec.rb
new file mode 100644
index 00000000..7feeefbd
--- /dev/null
+++ b/spec/defines/augeas_lens_spec.rb
@@ -0,0 +1,112 @@
+require 'spec_helper'
+
+describe 'augeas::lens' do
+ let (:title) { 'foo' }
+
+ context 'when not declaring augeas class first' do
+ let (:params) do
+ {
+ :lens_source => '/tmp/foo.aug',
+ }
+ end
+
+ it 'should error' do
+ expect {
+ is_expected.to contain_file('/usr/share/augeas/lenses/foo.aug')
+ }.to raise_error(Puppet::Error, /You must declare the augeas class/)
+ end
+ end
+
+ context 'when declaring augeas class first' do
+
+ on_supported_os.each do |os, facts|
+ context "on #{os}" do
+ let(:facts) do
+ facts.merge({
+ :augeasversion => :undef,
+ })
+ end
+
+ context 'With standard augeas version' do
+
+ let(:pre_condition) do
+ "class { '::augeas': }"
+ end
+
+ context 'when no lens_source is passed' do
+ it 'should error' do
+ expect {
+ is_expected.to contain_file('/usr/share/augeas/lenses/foo.aug')
+ }.to raise_error(Puppet::Error, /Must pass lens_source/)
+ end
+ end
+
+ context 'when lens_source is passed' do
+ let (:params) do
+ {
+ :lens_source => '/tmp/foo.aug',
+ }
+ end
+
+ it { is_expected.to contain_file('/usr/share/augeas/lenses/foo.aug') }
+ it { is_expected.to contain_exec('Typecheck lens foo') }
+ it { is_expected.not_to contain_file('/usr/share/augeas/lenses/tests/test_foo.aug') }
+ it { is_expected.not_to contain_exec('Test lens foo') }
+ end
+
+ context 'when lens_source and test_source are passed' do
+ let (:params) do
+ {
+ :lens_source => '/tmp/foo.aug',
+ :test_source => '/tmp/test_foo.aug',
+ }
+ end
+
+ it { is_expected.to contain_file('/usr/share/augeas/lenses/foo.aug') }
+ it { is_expected.to contain_exec('Typecheck lens foo') }
+ it { is_expected.to contain_file('/usr/share/augeas/lenses/tests/test_foo.aug') }
+ it { is_expected.to contain_exec('Test lens foo') }
+ end
+ end
+
+ context 'when stock_since is passed and augeas is older' do
+ let (:params) do
+ {
+ :lens_source => '/tmp/foo.aug',
+ :stock_since => '1.2.3',
+ }
+ end
+
+ let(:pre_condition) do
+ "class { '::augeas': version => '1.0.0' }"
+ end
+
+ it { is_expected.to contain_file('/usr/share/augeas/lenses/foo.aug') }
+ it { is_expected.to contain_exec('Typecheck lens foo') }
+ end
+
+ context 'when stock_since is passed and augeas is newer' do
+ let (:params) do
+ {
+ :lens_source => '/tmp/foo.aug',
+ :stock_since => '1.2.3',
+ }
+ end
+
+ let(:pre_condition) do
+ "class { '::augeas': version => '1.3.0' }"
+ end
+
+ it do
+ pending "undefined method `negative_failure_message'"
+ is_expected.not_to contain_file('/usr/share/augeas/lenses/foo.aug')
+ end
+ it do
+ pending "undefined method `negative_failure_message'"
+ is_expected.not_to contain_exec('Typecheck lens foo')
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/spec.opts b/spec/spec.opts
new file mode 100644
index 00000000..91cd6427
--- /dev/null
+++ b/spec/spec.opts
@@ -0,0 +1,6 @@
+--format
+s
+--colour
+--loadby
+mtime
+--backtrace
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 00000000..86cc740a
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,42 @@
+require 'puppetlabs_spec_helper/module_spec_helper'
+require 'rspec-puppet-facts'
+include RspecPuppetFacts
+
+
+RSpec.configure do |c|
+ c.include PuppetlabsSpec::Files
+
+ c.before :each do
+ # Store any environment variables away to be restored later
+ @old_env = {}
+ ENV.each_key {|k| @old_env[k] = ENV[k]}
+
+ Puppet.settings[:strict_variables]=true if Gem::Version.new(Puppet::PUPPETVERSION) >= Gem::Version.new('3.5')
+ Puppet.features.stubs(:root?).returns(true)
+ end
+
+ c.after :each do
+ PuppetlabsSpec::Files.cleanup
+ end
+end
+
+require 'pathname'
+dir = Pathname.new(__FILE__).parent
+Puppet[:modulepath] = File.join(dir, 'fixtures', 'modules')
+
+# There's no real need to make this version dependent, but it helps find
+# regressions in Puppet
+#
+# 1. Workaround for issue #16277 where default settings aren't initialised from
+# a spec and so the libdir is never initialised (3.0.x)
+# 2. Workaround for 2.7.20 that now only loads types for the current node
+# environment (#13858) so Puppet[:modulepath] seems to get ignored
+# 3. Workaround for 3.5 where context hasn't been configured yet,
+# ticket https://tickets.puppetlabs.com/browse/MODULES-823
+#
+ver = Gem::Version.new(Puppet.version.split('-').first)
+if Gem::Requirement.new("~> 2.7.20") =~ ver || Gem::Requirement.new("~> 3.0.0") =~ ver || Gem::Requirement.new("~> 3.5") =~ ver
+ puts "augeasproviders: setting Puppet[:libdir] to work around broken type autoloading"
+ # libdir is only a single dir, so it can only workaround loading of one external module
+ Puppet[:libdir] = "#{Puppet[:modulepath]}/augeasproviders_core/lib"
+end
diff --git a/spec/unit/puppet/parser/functions/augeas_spec.rb b/spec/unit/puppet/parser/functions/augeas_spec.rb
new file mode 100644
index 00000000..b34fa5b5
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/augeas_spec.rb
@@ -0,0 +1,83 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+
+describe 'the augeas function' do
+ let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+ it "should fail if the augeas feature is not present" do
+ Puppet.features.expects(:augeas?).returns(false)
+ expect { scope.function_augeas([]) }.to raise_error(Puppet::ParseError, /requires the augeas feature/)
+ end
+
+ it "should exist" do
+ expect(Puppet::Parser::Functions.function("augeas")).to eq("function_augeas")
+ end
+
+ context "when passing wrong arguments" do
+ before :each do
+ Puppet.features.stubs(:augeas?).returns(true)
+ end
+
+ it "should raise a ParseError if there are no arguments" do
+ expect { scope.function_augeas([]) }.to raise_error(Puppet::ParseError, /Wrong number of arguments/)
+ end
+
+ it "should raise a ParseError if content is not a string" do
+ expect { scope.function_augeas([['foo'], 'Fstab.lns', []]) }.to raise_error(Puppet::ParseError, /content must be a string/)
+ end
+
+ it "should raise a ParseError if lens is not a string" do
+ expect { scope.function_augeas(['foo', ['Fstab.lns'], []]) }.to raise_error(Puppet::ParseError, /lens must be a string/)
+ end
+
+ it "should raise a ParseError if changes is not an array" do
+ expect { scope.function_augeas(['foo', 'Fstab.lns', 'changes']) }.to raise_error(Puppet::ParseError, /changes must be an array/)
+ end
+ end
+
+ if Puppet.features.augeas?
+ context "when passing invalid input" do
+ it "should fail to parse input with lens" do
+ expect { scope.function_augeas(['foo', 'Fstab.lns', []]) }.to raise_error(Puppet::ParseError, /Failed to parse string with lens Fstab.lns:/)
+ end
+ end
+
+ context "when passing illegal changes" do
+ it "should fail to apply illegal change" do
+ expect { scope.function_augeas(["\n", 'Fstab.lns', ['foo bar']]) }.to raise_error(Puppet::ParseError, /Failed to apply change to tree/)
+ end
+ end
+
+ context "when generating an invalid tree" do
+ it "should fail to apply changes with wrong tree" do
+ expect { scope.function_augeas(["\n", 'Fstab.lns', ['set ./1/opt 3']]) }.to raise_error(Puppet::ParseError, /Failed to apply changes with lens Fstab.lns:/)
+ end
+ end
+
+ context "when applying valid changes" do
+ it "should remove the 3rd option" do
+ result = scope.function_augeas(["proc /proc proc nodev,noexec,nosuid 0 0\n", 'Fstab.lns', ['rm ./1/opt[3]']])
+ expect(result.class).to eq(String)
+ #result.should == "proc /proc proc nodev,noexec 0 0\n"
+ end
+
+ it "should set a 4th option" do
+ result = scope.function_augeas(["proc /proc proc nodev,noexec,nosuid 0 0\n", 'Fstab.lns', ['ins opt after ./1/opt[last()]', 'set ./1/opt[last()] nofoo']])
+ expect(result.class).to eq(String)
+ #result.should == "proc /proc proc nodev,noexec,nosuid,nofoo 0 0\n"
+ end
+ end
+
+ context "when using old libs" do
+ it "should not work with Augeas prior to 1.0.0" do
+ Augeas.any_instance.expects(:get).with('/augeas/version').returns('0.10.0')
+ expect { scope.function_augeas(["\n", 'Fstab.lns', []]) }.to raise_error(Puppet::ParseError, /requires Augeas 1\.0\.0/)
+ end
+
+ it "should not work with ruby-augeas prior to 0.5.0" do
+ Augeas.any_instance.expects(:methods).returns([])
+ expect { scope.function_augeas(["\n", 'Fstab.lns', []]) }.to raise_error(Puppet::ParseError, /requires ruby-augeas 0\.5\.0/)
+ end
+ end
+ end
+end