Version information
This version is compatible with:
- Puppet Enterprise >=2.7.20 < 2015.3.0
- Puppet >=2.7.20 < 5.0.0
- , , , , , ,
Start using this module
Add this module to your Puppetfile:
mod 'biemond-wildfly', '0.5.4'
Learn more about managing modules with a PuppetfileDocumentation
####Table of Contents
- Overview
- Module Description - What the module does and why it is useful
- Setup - The basics of getting started with wildfly
- 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
##Overview
created by Edwin Biemond email biemond at gmail dot com biemond.blogspot.com Github homepage
Install, configures and manages Wildfly.
Should work on every Redhat or Debian family member, tested it with Wildfly 9.0, 8.2, 8.1 & 8.0
Can also work with JBoss EAP ( tested on 6.1/6.2/6.3), it may change in the future and probably is not supported on Debian
# hiera example
wildfly::service_name: jboss-as
wildfly::conf_file: /etc/jboss-as/jboss-as.conf
wildfly::service_file: jboss-as-standalone.sh
wildfly::install_source: http://mywebserver/jboss-eap-6.1.tar.gz
Vagrant Fedora 21, Puppet 4.2.1 example with Wildfly 8.2 and Apache AJP, Postgress db.
Vagrant CentOS Standalone HA + Gossip Router example with two nodes, a gossip router and a load balancer (http + mod_cluster).
Vagrant CentOS 7.2 Domain Mode with two nodes (Domain master and slave) and a load balancer.
MCollective JBoss Agent Plugin might be useful if you want to make consistent large scale changes.
##Module Description
The wildfly module can install, configure and manage (using its HTTP API) Wildfly (8/9) and JBoss AS7/EAP6 (with limitations).
##Setup
###What wildfly affects
-
Creates a wildfly service and manages its installation (in an unobtrusive way using Wildfly HTTP API meaning that there are no templates for its standalone/domain configurations file)
-
Installs requisite libaio and wget packages
###Setup Requirements
This module requires a JVM ( should already be there ).
Acceptance tests works with puppetlabs/java in both CentOS and Debian.
###Beginning with wildlfy
Module defaults
- version 9.0.2
- install_source http://download.jboss.org/wildfly/9.0.2.Final/wildfly-9.0.2.Final.tar.gz
- java_home /usr/java/jdk1.7.0_75/ (default dir for oracle official rpm)
- manage_user true
- group wildfly
- user wildfly
- dirname /opt/wildfly
- package_ensure present
- service_ensure true
- service_enable true
- java_home /usr/java/jdk1.7.0_75/
- mode standalone
- config standalone.xml
- domain_config domain.xml
- host_config host.xml
- console_log /var/log/wildfly/console.log
- mgmt_bind 0.0.0.0
- mgmt_http_port 9990
- mgmt_https_port 9993
- public_bind 0.0.0.0
- public_http_port 8080
- public_https_port 8443
- ajp_port 8009
- java_xmx 512m
- java_xms 128m
- java_maxpermsize 256m
- users_mgmt user 'wildfly' with wildfly as password
- install_cache_dir /var/cache/wget
##Usage
class { 'wildfly': }
or for wildfly 9.0.2
class { 'wildfly':
version => '9.0.2',
install_source => 'http://download.jboss.org/wildfly/9.0.2.Final/wildfly-9.0.2.Final.tar.gz',
java_home => '/opt/jdk-8',
}
or for wildfly 9.0.0
class { 'wildfly':
version => '9.0.0',
install_source => 'http://download.jboss.org/wildfly/9.0.0.Final/wildfly-9.0.0.Final.tar.gz',
java_home => '/opt/jdk-8',
}
or for wildfly 8.2.0
class { 'wildfly':
version => '8.2.0',
install_source => 'http://download.jboss.org/wildfly/8.2.0.Final/wildfly-8.2.0.Final.tar.gz',
java_home => '/opt/jdk-8',
}
or for wildfly 8.1.0
class { 'wildfly':
version => '8.1.0',
install_source => 'http://download.jboss.org/wildfly/8.1.0.Final/wildfly-8.1.0.Final.tar.gz',
java_home => '/opt/jdk-8',
}
or for wildfly 8.0.0
class { 'wildfly':
version => '8.0.0',
install_source => 'http://download.jboss.org/wildfly/8.0.0.Final/wildfly-8.0.0.Final.tar.gz',
java_home => '/opt/jdk-8',
}
or you can override a paramater
class { 'wildfly':
version => '8.1.0',
install_source => 'http://download.jboss.org/wildfly/8.1.0.Final/wildfly-8.1.0.Final.tar.gz',
java_home => '/opt/jdk-8',
group => 'wildfly',
user => 'wildfly',
dirname => '/opt/wildfly',
mode => 'standalone',
config => 'standalone-full.xml',
java_xmx => '512m',
java_xms => '256m',
java_maxpermsize => '256m',
mgmt_http_port => '9990',
mgmt_https_port => '9993',
public_http_port => '8080',
public_https_port => '8443',
ajp_port => '8009',
users_mgmt => { 'wildfly' => { password => 'wildfly'}},
}
or with java_opts instead of java_xmx, java_xms, java_maxpermsize
class { 'wildfly':
version => '8.1.0',
install_source => 'http://download.jboss.org/wildfly/8.1.0.Final/wildfly-8.1.0.Final.tar.gz',
java_home => '/opt/jdk-8',
group => 'wildfly',
user => 'wildfly',
dirname => '/opt/wildfly',
mode => 'standalone',
config => 'standalone-full.xml',
java_opts => '-Xms64m -Xmx512m -XX:MaxPermSize=256m',
mgmt_http_port => '9990',
mgmt_https_port => '9993',
public_http_port => '8080',
public_https_port => '8443',
ajp_port => '8009',
users_mgmt => { 'wildfly' => { password => 'wildfly'}},
}
Domain Mode
Domain Master
class { 'wildfly':
mode => 'domain',
host_config => 'host-master.xml'
}
wildfly::config::mgmt_user { 'slave1':
password => 'wildfly',
}
Domain Slave
class { 'wildfly':
mode => 'domain',
host_config => 'host-slave.xml',
domain_slave => {
host_name => 'slave1',
secret => 'd2lsZGZseQ==', #base64(password)
domain_master_address => 'DomainBindAddress',
}
}
Deployment
From a source:
Source supports: http://, ftp://, puppet://, file:
wildfly::deployment { 'hawtio.war':
source => 'http://central.maven.org/maven2/io/hawt/hawtio-web/1.4.48/hawtio-web-1.4.48.war',
}
wildfly::deployment { 'hawtio.war':
source => 'puppet:///modules/profile/wildfly/hawtio-web-1.4.48.war',
}
wildfly::deployment { 'hawtio.war':
source => 'file:/var/tmp/hawtio-web-1.4.48.war',
}
To a server-group (domain mode):
wildfly::deployment { 'hawtio.war':
source => 'http://central.maven.org/maven2/io/hawt/hawtio-web/1.4.48/hawtio-web-1.4.48.war',
server_group => 'main-server-group',
}
Deploy from nexus:
This feature was removed to avoid 'archive' name collision, but you can still use archive::nexus to download an artifact and use as an input for wildfly::deploy
User management
You can add App and Management users (requires server restart).
wildfly::config::mgmt_user { 'mgmtuser':
password => 'mgmtuser'
}
wildfly::config::app_user { 'appuser':
password => 'appuser'
}
And associate groups or roles to them (requires server restart)
wildfly::config::user_groups { 'mgmtuser':
groups => 'admin,mygroup'
}
wildfly::config::user_roles { 'appuser':
roles => 'guest,ejb'
}
Module installation
Install a JAR module from a remote file system, puppet file server or local file system.
wildfly::config::module { 'org.postgresql':
source => 'http://central.maven.org/maven2/org/postgresql/postgresql/9.3-1103-jdbc4/postgresql-9.3-1103-jdbc4.jar',
dependencies => ['javax.api', 'javax.transaction.api']
}
wildfly::config::module { 'org.postgresql':
source => 'puppet:///modules/profile/wildfly/postgresql-9.3-1103-jdbc4.jar',
dependencies => ['javax.api', 'javax.transaction.api']
}
wildfly::config::module { 'org.postgresql':
source => 'file:/var/tmp/postgresql-9.3-1103-jdbc4.jar',
dependencies => ['javax.api', 'javax.transaction.api']
}
Datasources
Setup a driver and a datasource (for domain mode you need to set target_profile parameter):
wildfly::datasources::driver { 'Driver postgresql':
driver_name => 'postgresql',
driver_module_name => 'org.postgresql',
driver_xa_datasource_class_name => 'org.postgresql.xa.PGXADataSource'
}
->
wildfly::datasources::datasource { 'DemoDS':
config => {
'driver-name' => 'postgresql',
'connection-url' => 'jdbc:postgresql://localhost/postgres',
'jndi-name' => 'java:jboss/datasources/DemoDS',
'user-name' => 'postgres',
'password' => 'postgres'
}
}
Alternatively, you can install a JDBC driver and module using deploy if your driver is JDBC4 compliant:
wildfly::deployment { 'postgresql-9.3-1103-jdbc4.jar':
source => 'http://central.maven.org/maven2/org/postgresql/postgresql/9.3-1103-jdbc4/postgresql-9.3-1103-jdbc4.jar'
}
->
wildfly::datasources::datasource { 'DemoDS':
config => {
'driver-name' => 'postgresql-9.3-1103-jdbc4.jar',
'connection-url' => 'jdbc:postgresql://localhost/postgres',
'jndi-name' => 'java:jboss/datasources/DemoDS',
'user-name' => 'postgres',
'password' => 'postgres'
}
}
A postgresql normal & XA datasource example
wildfly::config::module { 'org.postgresql':
source => 'http://central.maven.org/maven2/org/postgresql/postgresql/9.3-1103-jdbc4/postgresql-9.3-1103-jdbc4.jar',
dependencies => ['javax.api', 'javax.transaction.api'],
require => Class['wildfly'],
} ->
wildfly::datasources::driver { 'Driver postgresql':
driver_name => 'postgresql',
driver_module_name => 'org.postgresql',
driver_xa_datasource_class_name => 'org.postgresql.xa.PGXADataSource'
} ->
wildfly::datasources::datasource { 'petshop datasource':
name => 'petshopDS',
config => { 'driver-name' => 'postgresql',
'connection-url' => 'jdbc:postgresql://10.10.10.10/petshop',
'jndi-name' => 'java:jboss/datasources/petshopDS',
'user-name' => 'petshop',
'password' => 'password'
}
} ->
wildfly::datasources::xa_datasource { 'petshop xa datasource':
name => 'petshopDSXa',
config => { 'driver-name' => 'postgresql',
'jndi-name' => 'java:jboss/datasources/petshopDSXa',
'user-name' => 'petshop',
'password' => 'password',
'xa-datasource-class' => 'org.postgresql.xa.PGXADataSource',
'xa-datasource-properties' => {
'url' => {'value' => 'jdbc:postgresql://10.10.10.10/petshop'}
},
}
}
Configure Database Property, only works for normal datasources
wildfly::datasources::db_property { 'DemoDbProperty':
value => 'demovalue',
database => 'ExampleDS',
}
Datasource configuration uses a hash with elements that match JBoss-CLI datasource add elements name. More info here: https://docs.jboss.org/author/display/WFLY8/DataSource+configuration
HTTPS/SSL (Wildfly 8+)
wildfly::undertow::https { 'https':
socket_binding => 'https',
keystore_path => '/vagrant/identitystore.jks',
keystore_password => 'changeit',
key_alias => 'demo',
key_password => 'changeit'
}
Identity Store sample Configuration:
java_ks { 'demo:/opt/identitystore.jks':
ensure => latest,
certificate => '/opt/demo.pub.crt',
private_key => '/opt/demo.private.pem',
path => '/usr/java/jdk1.7.0_75/bin/',
password => 'changeit',
}
HTTPS/SSL (JBoss AS7/EAP 6)
wildfly::web::connector { 'https':
scheme => 'https',
protocol => 'HTTP/1.1',
socket_binding => 'https',
enable_lookups => false,
secure => true,
}
->
wildfly::web::ssl { 'ssl':
connector => 'https',
protocol => 'TLSv1,TLSv1.1,TLSv1.2',
password => 'changeit',
key_alias => 'demo',
certificate_key_file => '/opt/identitykeystore.jks',
cipher_suite => 'TLS_RSA_WITH_AES_128_CBC_SHA,SSL_RSA_WITH_3DES_EDE_CBC_SHA',
}
Server Reload
Some configurations like SSL and modcluster requires a server reload, it can be achieved with the following snippet:
wildfly::util::exec_cli { 'Reload if necessary':
command => 'reload',
onlyif => '(result == reload-required) of read-attribute server-state'
}
OR
## operation that needs reload
~>
widlfly::util::reload { 'Reload if necessary':
retries => 2,
wait => 15,
}
Messaging (Only for full profiles)
for domain mode you need to set target_profile parameter
wildfly::messaging::queue { 'DemoQueue':
durable => true,
entries => ['java:/jms/queue/DemoQueue'],
selector => "MessageType = 'AddRequest'"
}
wildfly::messaging::topic { 'DemoTopic':
entries => ['java:/jms/topic/DemoTopic']
}
Logging
for domain mode you need to set target_profile parameter
wildfly::logging::category { 'DemoCategory':
level => 'DEBUG',
use_parent_handlers => false,
handlers => ['DemoHandler']
}
System Property
for domain mode you need to set target_profile parameter
wildfly::system::property { 'DemoSysProperty':
value => 'demovalue'
}
Modcluster (Only for full and HA profiles)
for domain mode you need to set target_profile parameter
wildfly::modcluster::config { "Modcluster mybalancer":
balancer => 'mybalancer',
load_balancing_group => 'demolb',
proxy_url => '/',
proxy_list => '127.0.0.1:6666'
}
##Reference
###Classes
####Public classes
- [wildfly]
####Private classes
- [wildfly::install]
- [wildfly::prepare]
- [wildfly::setup]
- [wildfly::service]
###Resources
- [wildfly::config::app_user]
- [wildfly::config::mgmt_user]
- [wildfly::config::user_groups]
- [wildfly::config::user_roles]
- [wildfly::config::module]
- [wildfly::util::resource]
- [wildfly::util::exec_cli]
- [wildfly::deployment]
Check types tab for more info about custom types/providers.
##Limitations
wildfly definitions (datasources, messaging, undertow, etc) which are intended to enforce good practices, syntax sugar or serve as examples are built for Wildfly 8.x and may not work with other versions. (Check Issue #27 for more details)
JBoss AS7/EAP 6 support is limited due to the above limitation and to the fact that service scripts are a little different. (Don't support debian and have only one script for both standalone/domain modes) This bug might also be a problem for standalone-full-ha users in JBoss EAP: https://bugzilla.redhat.com/show_bug.cgi?id=1224170
##Development
This module uses puppet-lint, rubocop, rspec, beaker and travis-ci. Try to use them before submit your PR.
gem install bundler --no-rdoc --no-ri
bundle install --without development
gem update --system 2.1.11
bundle exec rake syntax
bundle exec rake lint
bundle exec rubocop
bundle exec rake spec
bundle exec rspec spec/acceptance # default centos-66-x64
BEAKER_set=centos-70-x64 bundle exec rspec spec/acceptance
BEAKER_set=debian-78-x64 bundle exec rspec spec/acceptance
JBoss/Wildfly management is based on three custom types and you can do virtually any JBoss/Wildfly configuration using them. So, before build your awesome definition to manage a resource (anything in configurations XML's) or deploy an artifact from my_internal_protocol://, check wildfly::deploy or wildfly::datasources namespace for guidance.
Examples:
wildfly_cli { 'Enable ExampleDS'
command => '/subsystem=datasources/data-source=ExampleDS:enable',
unless => '(result == true) of /subsystem=datasources/data-source=ExampleDS:read-attribute(name=enabled)'
}
wildfly_resource { '/subsystem=datasources/data-source=ExampleDS':
state => {
'driver-name' => 'postgresql',
'connection-url' => 'jdbc:postgresql://localhost/example',
'jndi-name' => 'java:jboss/datasources/ExampleDS',
'user-name' => 'postgres',
'password' => 'postgres'
}
}
wildfly_deployment { 'sample.war':
source => 'file:/vagrant/sample.war'
}
They all require a management username, password, host and port params, as it uses Wildfly HTTP API. Host defaults to 127.0.0.1 and port to 9990
##Author/Contributors
- Edwin Biemond (biemond at gmail dot com)
- Jairo Junior (junior.jairo1 at gmail dot com)
More: https://github.com/biemond/biemond-wildfly/graphs/contributors
Types in this module release
History
0.5.4
- Fix for digest authentication in Wildfly 10.
- Fix wildfly_cli should_execute? condition
- Excluded-contexts for modcluster configuration.
- HTTPS support for AS7/EAP6.
0.5.3
- Fix for true/false comparison in custom types.
- Improved wildfly::modcluster::config.
- Fix version comparison.
- SSL for Wildfly 9+
- Still support Ruby 1.8.7.
0.5.2
- Support file and puppet protocol for module/deployment installation
- Download timeout parameter
- Login module management
- Optional package dependencies management
- wildfly_reload custom type/provider
- Fix wildfly service in EL7
- Fix wildfly_resource when HTTP API return numbers
- Support digest authentication
- Ignore HTTP Proxy in net/http
- Improve acceptance tests
0.5.1
- Support datasource database properties
- Support logging::category, only for full profiles
- Support system property, only for full profiles
- Be able to provide your own service wildfly initd script
- Wildfy Service enable & ensure parameters
- Fix module installation
0.5.0
- Removed nanliu-archive dependency
- Removed nexus deployment support
- Rename deploy to deployment
- Simplify user management
0.4.3
- Allow setting the uid/gid for the wildfly user and group
- Uses JBOSS_OPTS to configure socket binding and bind address. (Operation mode independent)
- Improve Domain mode support. (Easy master/slave setup)
- User management defined types name refactor. (Breaking change)
- Non destructive update initial support.
0.4.2
- Adds timeout parameter for wildfly_deploy custom type.
0.4.1
- Template fixes so it also works for puppet 4.2.1
- Standalone mode also works with an empty java_opts
0.4.0
- Unified deploy for domain/standalone modes (wildfly::deploy)
- Removed wildfly::standalone namespace since domain and standalone configurations share the same defitions
- Fix wildfly service to detect profile changes
- Remove params of private classes. init.pp is suposed to be the only public class.
0.3.7
- Update README.md content and format to follow recommended guidelines
- Add acceptance test for Wildfly 9
0.3.6
- Service needs to restart if we change anything in the standalone.conf
- Several fixes for domain mode
- Support escaped slashes in resource names
- Support ensure parameter in resource util
- Support installing non-system modules
- Update definitions optional parameters.
- CLI, Support for 'has' operator to check if item is in array
0.3.5
- Changes to allow wildfly module to deploy jboss EAP
- java_opts parameters which will override the default
- puppet 4 templates path fix
- XA datasource support
0.3.4
- deploy from nexus
- manage_user parameter for controling the default creation of the wildfly user/group
0.3.3
- Beaker unit tests for CentOS 6.6, 7.0 and Debian 7
- fix debian wildlfy configuration file /etc/default/wildfly
0.3.2
- More improvements
0.3.1
- Code quality improvement and support for onlyif in wildfly_cli
0.3.0
- Introducing custom types/providers in replacement of cli-wrapper and jboss-cli.sh. These custom types/providers use HTTP API instead of JBoss-CLI. It maks it 5-10x faster and easier to maintain. More info here: cpitman/puppet-jboss_admin#68
- Using archive in replacement of wget cause it's faster and incredible simple.
- Removing nexus deployment support since cescoffier/puppet-nexus is not in forge and not being active developed, I'll try to work on a PR for archive (some sort of archive::nexus) and have a single define for deployment that accepts multiple formats of deployment.
- Users still can download from Nexus outside deploy and pass file URL as a parameter.
0.2.4
- Debian fix so wildfly-init-debian.sh will be used instead of redhat
0.2.3
- update readme
0.2.2
- Configure wildfly log with console_log parameter
- Deployment option
- User management
- Module installation
- Datasource configuration
- HTTPS/SSL & Identity store
- Modcluster (Only for HA profiles)
- Messaging Queue or Topics
0.2.1
- All port & interface sed actions has been replaced by augeas
0.2.0
- Major re-factoring by Jairo Junior
- Extracted some resources to new manifests in order to avoid excessive relationships (require, notify, before, after, etc).
- Created new manifests to express new concepts (wildfly user management).
- Removed shell script templates in order to use package script (wildfly/bin/init.d).
- Using only class { 'wildfly' } instead of class { 'wildfly:install' } cause it gives the impression that i am able to instantiate multiple instances*, like tomcat module (https://forge.puppetlabs.com/puppetlabs/tomcat).
- Removing $install_file parameter cause it can be inferred (file_name_from_url.rb).
- The wildfly management user password is declared in plain text and hash is performed internally (password_hash.rb).
- Introduced new dependencies (wget and stdlib)
0.1.9
- some exec executed on every puppet run
0.1.8
- Added license
- Support for Wildfly 8.2
- Removed the password on the wildfly user
0.1.7
- fix for updating user mgmt file
0.1.6
- Fix for Debian, Ubuntu
Dependencies
- puppetlabs/stdlib (>=3.2.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.