Version information
This version is compatible with:
- Puppet Enterprise 2017.2.x, 2017.1.x, 2016.5.x, 2016.4.x
- Puppet >= 3.8.7 < 5.0.0
- , , ,
Start using this module
Add this module to your Puppetfile:
mod 'puppet-hiera', '2.4.0'Learn more about managing modules with a PuppetfileDocumentation
Hiera module for Puppet
Table of Contents
- Overview
- Module Description - What the module does and why it is useful
- Setup - The basics of getting started with hiera
- Usage - Configuration options and additional functionality
- Reference - An under-the-hood peek at what the module is doing and how
- Limitations - OS compatibility, etc.
- Development - Guide for contributing to the module
Module Description
This module configures Hiera for Puppet.
Setup
What hiera affects
- Hiera yaml file
- Hiera datadir
- hiera-eyaml package
- keys/ directory for eyaml
- /etc/hiera.yaml for symlink
Setup requirements
If you are using the eyaml backend on:
- Puppet Enterprise 3.3 or earlier then you will need the puppetlabs-pe_gem module to install the eyaml gem using PE's gem command.
- Puppet Enterprise 3.7 or 3.8 then you will need the puppetlabs-pe_puppetserver_gem module.
- Puppet Enterprise 2015.x or FOSS puppetserver then you will need the puppetlabs-puppetserver_gem module.
Beginning with hiera
Declaring the class with a given hierarchy is a pretty good starting point:
This class will write out a hiera.yaml file in either /etc/puppetlabs/puppet/hiera.yaml or /etc/puppet/hiera.yaml (depending on if the node is running Puppet Enterprise or not).
class { 'hiera':
hierarchy => [
'%{environment}/%{calling_class}',
'%{environment}',
'common',
],
}
The resulting output in /etc/puppet/hiera.yaml:
---
:backends:
- yaml
:logger: console
:hierarchy:
- "%{environment}/%{calling_class}"
- "%{environment}"
- common
:yaml:
:datadir: /etc/puppet/hieradata
Usage
Reference
This module will also allow you to configure different options for logger and merge_behavior. The default behavior is to set logger to console and merge behavior to native.
For details and valid options see Configuring Hiera.
class { 'hiera':
hierarchy => [
'%{environment}/%{calling_class}',
'%{environment}',
'common',
],
logger => 'console',
merge_behavior => 'deeper'
}
The resulting output in /etc/puppet/hiera.yaml:
---
:backends:
- yaml
:logger: console
:hierarchy:
- "%{environment}/%{calling_class}"
- "%{environment}"
- common
:yaml:
:datadir: /etc/puppet/hieradata
:merge_behavior: deeper
Hiera-Eyaml-GPG
The default PKCS#7 encryption scheme used by hiera-eyaml is perfect if only simple encryption and decryption is needed.
However, if you are in a sizable team it helps to encrypt and decrypt data with multiple keys. This means that each team member can hold their own private key and so can the puppetmaster. Equally, each puppet master can have their own key if desired and when you need to rotate keys for either users or puppet masters, re-encrypting your files and changing the key everywhere does not need to be done in lockstep.
Requirements
Note: This module will create a /gpg sub-directory in the $keysdir.
-
The GPG keyring must be passphraseless on the on the PuppetServer(Master).
-
The GPG keyring must live in the /gpg sub-directory in the
$keysdir. -
The GPG keyring must be owned by the Puppet user. ex: pe-puppet
GPG Keyring Creation Tips
RNG-TOOLS
When generating a GPG keyring the system requires a good amount of entropy.
To help generate entropy to speed up the process then rng-tools package on RHEL
based systems or equivilent can be used. Note: Update the /etc/sysconfig/rngd
or equivilent file to set the EXTRAOPTIONS to
EXTRAOPTIONS="-r /dev/urandom -o /dev/random -t 5"
Keyring Generation
Below is a sample GPG answers file that will assist in generating a passphraseless key
cat << EOF >> /tmp/gpg_answers
%echo Generating a Puppet Hiera GPG Key
Key-Type: RSA
Key-Length: 4096
Subkey-Type: ELG-E
Subkey-Length: 4096
Name-Real: Hiera Data
Name-Comment: Hiera Data Encryption
Name-Email: puppet@$(hostname -d)
Expire-Date: 0
%no-ask-passphrase
# Do a commit here, so that we can later print "done" :-)
# %commit
# %echo done
EOF
You can then use the GPG answer file to generate your keyring within the
/gpg sub-directory in the $keysdir
gpg --batch --homedir /etc/puppetlabs/code-staging/keys/gpg --gen-key /tmp/gpg_answers
Usage
class { 'hiera':
hierarchy => [
'nodes/%{::clientcert}',
'locations/%{::location}',
'environments/%{::applicationtier}',
'common',
],
eyaml => true,
eyaml_gpg => true,
eyaml_gpg_recipients => 'sihil@example.com,gtmtech@example.com,tpoulton@example.com',
}
The resulting output in /etc/puppet/hiera.yaml:
---
:backends:
- eyaml
- yaml
:logger: console
:hierarchy:
- "nodes/%{::clientcert}"
- "locations/%{::location}"
- "environments/%{::applicationtier}"
- common
:yaml:
:datadir: /etc/puppet/hieradata
:eyaml:
:datadir: /etc/puppet/hieradata
:pkcs7_private_key: /etc/puppet/keys/private_key.pkcs7.pem
:pkcs7_public_key: /etc/puppet/keys/public_key.pkcs7.pem
:encrypt_method: "gpg"
:gpg_gnupghome: "/etc/puppet/keys/gpg"
:gpg_recipients: "sihil@example.com,gtmtech@example.com,tpoulton@example.com"
Classes
Public Classes
- hiera: Main class to configure hiera
Private Classes
- hiera::params: Handles variable conditionals
- hiera::eyaml: Handles eyaml configuration
Parameters
The following parameters are available for the hiera class:
-
hierarchyThe hiera hierarchy. Default:[] -
backendsThe list of backends. Default:['yaml']If you supply a additional backend you must also supply the backend data in thebackend_optionshash. -
backend_optionsAn optional hash of backend data for any backend. Each key in the hash should be the name of the backend as listed in thebackendsarray. You can also supply additional settings for the backend by passing in a hash. By default theyamlandeyamlbackend data will be added if you enable them via their respective parameters. Any options you supply foryamlandeyamlbackend types will always override other parameters supplied to the hiera class for that backend.Example hiera data for the backend_options hash:
backend_options: json: datadir: '/etc/puppetlabs/puppet/%{::environment}/jsondata' redis: password: clearp@ssw0rd # if your Redis server requires authentication port: 6380 # unless present, defaults to 6379 db: 1 # unless present, defaults to 0 host: db.example.com # unless present, defaults to localhost path: /tmp/redis.sock # overrides port if unixsocket exists soft_connection_failure: true # bypass exception if Redis server is unavailable; default is false separator: / # unless present, defaults to : deserialize: :json # Try to deserialize; both :yaml and :json are supportedNOTE: The backend_options must not contain symbols as keys ie
:json:despite the hiera config needing symbols. The template will perform all the conversions to symbols in order for hiera to be happy. Because puppet does not use symbols there are minor annoyances when converting back and forth and merge data together. -
hiera_yamlThe path to the hiera config file. Note: Due to a bug, hiera.yaml is not placed in the codedir. Your puppet.confhiera_configsetting must match the configured value; see alsohiera::puppet_conf_manageDefault:'/etc/puppet/hiera.yaml'for Puppet Open Source'/etc/puppetlabs/puppet/hiera.yaml'for Puppet Enterprise
-
create_symlinkWhether to create the symlink/etc/hiera.yamlDefault: true -
datadirThe path to the directory where hiera will look for databases. Default:'/etc/puppet/hieradata'for Puppet Open Source'/etc/puppetlabs/puppet/hieradata'for PE Puppet < 4'/etc/puppetlabs/code/environments/%{::environment}/hieradata'for Puppet >= 4
-
datadir_manageWhether to create and manage the datadir as a file resource. Default:true -
ownerThe owner of managed files and directories. Default:'puppet'for Puppet Open Source'pe-puppet'for Puppet Enterprise
-
groupThe group owner of managed files and directories. Default:'puppet'for Puppet Open Source'pe-puppet'for Puppet Enterprise
-
eyamlWhether to install, configure, and enable the eyaml backend. Also see the provider and master_service parameters. Default:false -
eyaml_nameThe name of the eyaml gem. Default: 'hiera-eyaml' -
eyaml_versionThe version of hiera-eyaml to install. Accepts 'installed', 'latest', '2.0.7', etc Default:undef -
eyaml_sourceAn alternate gem source for installing hiera-eyaml. Default:undef, uses gem backend default -
eyaml_datadirThe path to the directory where hiera will look for databases with the eyaml backend. Default: same asdatadir -
eyaml_extensionThe file extension for the eyaml backend. Default:undef, backend defaults to'.eyaml' -
deep_merge_nameThe name of the deep_merge gem. Default: 'deep_merge' -
deep_merge_versionThe version of deep_merge to install. Accepts 'installed', 'latest', '2.0.7', etc. Default:undef -
deep_merge_sourceAn alternate gem source for installing deep_merge. Default:undef, uses gem backend default -
deep_merge_optionsA hash of options to set in hiera.yaml for the deep merge behavior. Default:{} -
manage_packageA boolean for wether the hiera package should be managed. Defaults totrueon FOSS 3 butfalseotherwise. -
package_nameSpecifies the name of the hiera package. Default: 'hiera' -
package_ensureSpecifies the ensure value of the hiera package. Default: 'present' -
confdirThe path to Puppet's confdir. Default:$::settings::confdirwhich should be the following:'/etc/puppet'for Puppet Open Source'/etc/puppetlabs/puppet'for Puppet Enterprise
-
loggerWhich hiera logger to use. Note: You need to manage any package/gem dependencies yourself. Default:undef, hiera defaults to'console' -
cmdpathSearch paths for command binaries, like theeyamlcommand. The default should cover most cases. Default:['/opt/puppet/bin', '/usr/bin', '/usr/local/bin'] -
create_keysWhether to create pkcs7 keys and manage key files for hiera-eyaml. This is useful if you need to distribute a pkcs7 key pair. Default:true -
merge_behaviorWhich hiera merge behavior to use. Valid values are 'native', 'deep', and 'deeper'. Deep and deeper values will install the deep_merge gem into the puppet runtime. Default:undef, hiera defaults to'native' -
extra_configArbitrary YAML content to append to the end of the hiera.yaml config file. This is useful for configuring backend-specific parameters. Default:'' -
keysdirDirectory for hiera to manage for eyaml keys. Default:$confdir/keysNote: If using PE 2013.x+ and code-manager set the keysdir under the$confdir/code-staging directoryto allow the code manager to sync the keys to all PuppetServers Example:/etc/puppetlabs/code-staging/keys -
puppet_conf_manageWhether to manage the puppet.confhiera_configvalue or not. Default:true -
providerWhich provider to use to install hiera-eyaml. Can be:puppetserver_gem(PE 2015.x or FOSS using puppetserver)pe_puppetserver_gem(PE 3.7 or 3.8)pe_gem(PE pre-3.7)puppet_gem(agent-only gem)gem(FOSS using system ruby (ie puppetmaster)) Note: this module cannot detect FOSS puppetserver and you must passprovider => 'puppetserver_gem'for that to work. See also master_service. Default: Depends on puppet version detected as specified above.
-
master_serviceThe service name of the master to restart after package installation or hiera.yaml changes. Note: You must passmaster_service => 'puppetserver'for FOSS puppetserver Default: 'pe-puppetserver' for PE 2015.x, otherwise 'puppetmaster'
Limitations
The eyaml_version parameter does not currently modify the eyaml version of the
command-line gem on pe-puppetserver.
Development
Pull requests on github! If someone wrote spec tests, that would be awesome.
Changelog
All notable changes to this project will be documented in this file. Each new release typically also includes the latest Vox Pupuli modulesync defaults. These should not impact the functionality of the module.
2017-01-13 - Release 2.4.0
This is the last release with Puppet 3 support!
- Do not make files in the gnupg home executable
- Support deep_merge_options with 'deeper' merge_behavior
- Correct spelling of @merge_behavior in template
- Bump min version_requirement for Puppet + deps
- Strict variables fix for
pe_server_version
2016-11-07 Release 2.3.0
- GH-128
The
manage_packageparameter now effects all packages. - GH-161 Regression fix. Make eyaml be the first backend again.
2016-10-07 Release 2.2.0
- Modulesync with latest Vox Pupuli defaults
- Removes unused
eyaml_gpg_keygenvariable
Features
- Adds support for 3rd party backends #153
This module now supports configuration of any backend via a new backend_options
parameter. This is a big deal as this opens the doors up to configuring any
backend in a generic way. This is also backwards compatible with prior versions
of this module.
2016-08-31 Release 2.1.2
- Modulesync with latest Vox Pupuli defaults
- Fix handling of
gem_source(correctly handle URLs)
2016-08-19 Release 2.1.1
- Modulesync with latest Vox Pupuli defaults
- Fix: Replace
to_yamlin hiera.yaml template (PR #134)
2016-05-21 Release 2.1.0
Note: this is the first release of the module in the voxpupuli namespace.
Features
- Add parameters to give more control over package management:
eyaml_nameeyaml_versioneyaml_source(deprecatesgem_sourceparameter)deep_merge_namedeep_merge_versiondeep_merge_sourcemanage_packagepackage_namepackage_source
- Add
deep_merge_optionsparameter for passing parameters in hiera.yaml - The
merge_behaviorparameter installs thedeep_mergegem when needed.
Bugfixes
- Typo for
master_serviceparameter in readme. - Improve dependency management around packages
- Fix
hierarchyparameter default on Puppet 4
2016-01-27 Release 2.0.1
Fixes
- Fix key creation when passing a custom
hiera::keysdir
2016-01-26 Release 2.0.0
Changes
- eyaml keys/ directory moved from
/etc/puppetlabs/code/keysto/etc/puppetlabs/puppet/keyson PE > 3.x. You should move you keys directory when upgrading. hiera::hiera_yamldefault changed from/etc/puppetlabs/code/hiera.yamlto/etc/puppetlabs/puppet/hiera.yamlon Puppet >= 4.x. The hiera_yaml puppet config setting in puppet.conf should be updated when upgrading; seehiera::puppet_conf_managehiera::datadirdefault changed from/etc/puppetlabs/puppet/hieradatato/etc/puppetlabs/code/environments/%{::environment}/hieradataon puppet versions >= 4. Verify that this is your prefered value when upgrading.
Features
- No longer using exec resources to install eyaml on puppet versions >= 4!
- Add
hiera::puppet_conf_manageparameter to managehiera_confpuppet.conf setting - Add
hiera::keysdirparameter for putting the keys somewhere other than $confdir/keys
Bugfixes
- Fix hiera.yaml and keys/ directory being overwritten by file sync on PE 2015.x
- Fix eyaml package provider detection on puppet versions >= 4
2016-01-08 Release 1.4.1
Bugfixes
- Fix rubocop linting
- Correct the name of the license file so the forge can find it.
- Add travis testing
2016-01-05 Release 1.4.0
Features
- Added
hiera::create_symlinkparameter to disable /etc/hiera.yaml creation - Added
hiera::master_serviceparameter to set the master service name - Added ability to restart master service on hiera.yaml change
- Added beaker-rspec acceptance tests
- Bumped PE range to include 2015.3
Bugfixes
- Fixed bugs on PE 2015.2 when versioncmp() raised errors
- Fixed hiera.yaml output to be consistent across puppet 3 and 4
- Fixed stdlib metadata requirement.
2015-09-14 Release 1.3.2
Bugfixes
- Detect correct user on 2015.2.0
- Clean up hiera formatting.
2015-07-24 Release 1.3.1
Bugfixes
- Allow
eyaml_versionto be undef (the default) on PE 3.7/3.8
2015-07-23 Release 1.3.0
Features
- Add PE 3.8 support
- Add Puppet 4 support
Bugfixes
- Fix
eyaml_datadirparameter default todatadirvalue - Handle cmdpath on different versions of puppet
2015-03-05 Release 1.2.0
Features
- Added
hiera::create_keysparam to disable pkcs7 key generation with hiera-eyaml - Added
hiera::gem_sourceparam to specify source of hiera-eyaml gem - Added
hiera::eyaml_versionparam to specify the version of eyaml
Bugfixes
- Change Modulefile to metadata.json
- Add validation on
merge_behaviorparam - Make it kind of work on PE 3.7 (pe-puppetserver must still be restarted after the gem is installed)
2014-11-21 Release 1.1.1
Bugfixes
- Correct handling of
cmdpath(using an array of paths instead of hardcoded path). Also addscmdpathparameter - Fix permissions on private key (604 was a typo)
- Add "Managed by puppet" header
2014-10-15 Release 1.1.0
Features
- Added
eyaml,eyaml_datadir, &eyaml_extensionparameters to hiera class for configuring hiera-eyaml - Added
hiera::datadir_manageparameter to disable datadir management - Added
hiera::loggerparameter to change logger - Added
hiera::merge_behaviorparameter to change the hash merge behavior - Added some spec tests
- Added new readme
Bugfixes
- Correct datadir regex
{}matching
2014-05-01 Release 1.0.2
- Remove swap files from package
2014-03-25 Release 1.0.1
Bugfixes
- Readme tweak
- Use template instance variables to remove warnings
2014-02-27 Release 1.0.0
Features
backendsparameter for an array of hiera backendsextra_configparameter for a string of extra yaml config
Bugfixes
- Correct the yaml formatting
2013-06-17 Release 0.3.1
Bugfixes
- Docs!
2013-06-17 Release 0.3.0
Features
- PE + POSS support
Bugfixes
- Only ensure datadir if it does not have
%{.*}
Dependencies
- puppetlabs/stdlib (>= 4.6.0 < 5.0.0)
- puppetlabs/inifile (>= 1.4.1 < 2.0.0)
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.
