diff --git a/cookbooks/apache2/.foodcritic b/cookbooks/apache2/.foodcritic new file mode 100644 index 0000000..18e0d2e --- /dev/null +++ b/cookbooks/apache2/.foodcritic @@ -0,0 +1,4 @@ +~FC007 +~FC015 +~FC023 +~FC024 diff --git a/cookbooks/apache2/CHANGELOG.md b/cookbooks/apache2/CHANGELOG.md new file mode 100644 index 0000000..39af225 --- /dev/null +++ b/cookbooks/apache2/CHANGELOG.md @@ -0,0 +1,491 @@ +apache2 Cookbook Changelog +========================== +This file is used to list changes made in each version of the apache2 cookbook. + +v3.3.0 (2017-04-11) +------------------- + +- [GH-478] Added support for the amazon platform_family, outside of rhel +- [GH-474] Update Berksfile to allow fetching of newer +- [GH-473] Update copyright header format +- [GH-472] foodcritic: add sous-chefs rules +- add CODE_OF_CONDUCT +- [GH-471] FCGI paths should not be messed with on RHEL/CenOS 7. CentOS 7 (and recent Fedoras) have Apache 2.4, where FCGI socket path and shared memory path is managed adequately without further involvment neccessary (subdirectory is created under /var/run/httpd). +- [GH-470] Remove support for EOL Fedora < 18 / FreeBSD 9 +- [GH-465] Testing updates +- [GH-469] Use the default cookbook style rules +- [GH-460] Serverspec to InSpec migration +- [GH-461] Update comment header format & other cookstyle fixes +- [GH-454] Test in Travis with Chef-DK and a Rakefile +- [GH-455] openSUSE Leap has it's own platform name +- [GH-279] leave stubs for rhel family `conf.d` files to avoid conflicts on package upgrade; no longer remove `conf.d`, just don't use it +- [GH-427] Add option to configure custom log level +- [GH-450] Ensure the lock_dir is owned by www-data for Apache 2.2 and 2.4 on Debian/Ubuntu +- Remove mod_auth_openid tests, as it is not part of the ASF release and plan to drop support for it and right now it is failing our tests +- [GH-440] Update default values in `apache.prefork` section of README +- [GH-443] fixed typo in copyright year +- Test on the latest chef with chef-zero +- Update supported platforms to Ubuntu 16.04, Debian 8.4, Centos 7.2; deprecating Ubuntu 12.04 +- [GH-422] Fix uniq for nil:NilClass error introduced in 3.2.2 +- [GH-423] allow for apache 2.4 usage on rhel < 7.0 +- Cookbook is now part of the sous-chefs, but still maintained by the same folks +- mod_perl: No longer install libapache2-mpm-prefork +- mod_php: renamed mod_php5 to more generic mod_php; using php 7.0 where available + +v3.2.2 (2016-04-13) +------------------- + +- [GH-420] Allow auto-conversion if either of `apache.listen_ports` or `apache.listen_addresses` are set rather than '&&'. This ensures conversion occurs if only one of the two is set. + + +v3.2.1 (2016-04-11) +------------------- + +- [GH-225] notify `restart` instead of `reload` service on `apache_conf`, `apache_config` +- Update to foodcritic 6 + +v3.2.0 (2016-03-26) +------------------- + +- [GH-378] Deprecates `apache.listen_addresses` and `apache.listen_ports` infavor of [GH-409] +- [GH-409] `apache.listen` now accepts an array of `addr:port` strings +- [GH-358] FreeBSD: Update 10.1 support; Adds php 5.6 in collaboration with chef-cookbooks/php#119 +- [GH-394] Have `apache.prefork.serverlimit` set ServerLimit directive on 2.4 +- [GH-363] Escape '.' in regex for .htaccess/.htpasswd files +- [GH-365] Force log directory creation to be recursive +- [GH-368] Change the service creation to use the `apache.service_name` attribute throughout +- [GH-374] Make metadata.rb compatible with chef versions < 12. +- [GH-382] Fixed typo in node['platform_family'] for NameError in `mod_proxy_html` +- [GH-369] README: Added on Ubuntu `mod_fastcgi` requires `multiverse` apt repository to enabled. +- [GH-381] README: Add missing backtick +- [GH-384] README: Fix names for a2enconf and a2disconf +- [GH-393] README: mention availability of `mod_actions` support +- [GH-383] Debian: Add possibility to use other releases via `apache.default_release` +- [GH-377] Restart service when including `mod_headers` to allow healing of failed service because of missing directives. +- [GH-416] Change the default of `apache.mod_fastcgi.install_method` to 'package' all platforms, as `source` is no longer available. +- [GH-401] Move `mod_deflate` to `apache.default_modules` and no longer force installation on `debian` families. +- [GH-386] Do not install an extra mod_ssl package on SUSE Linux Enterprise +- [GH-335] Do not hardcoded reload/restart on more modern rhel platforms, allowing systemd on CentOS 7 +- [GH-375] Install package `mod_ldap` on CentOS 7 (triggered by `apache.version` == 2.4) +- Update `apache.mod_ssl.cipher_suite` to latest from https://bettercrypto.org/ +- README: Re-organize README to make it easier to find usage and remove old references. +- Added new standard and missing modules (Note: these may not be available natively on all operating systems) + * [mod_http2](http://httpd.apache.org/docs/2.4/mod/mod_http2.html) - Support for the HTTP/2 transport layer. (available since 2.4.17) + * [mod_authnz_fcgi](http://httpd.apache.org/docs/2.4/mod/mod_authnz_fcgi.html) - Enable FastCGI authorizer applications to authenticate and/or authorize clients. (available since 2.4.10) + * [mod_cern_meta](http://httpd.apache.org/docs/2.4/mod/mod_cern_meta.html) - CERN httpd metafile semantics + * [mod_ident](http://httpd.apache.org/docs/2.4/mod/mod_ident.html) - RFC 1413 ident lookups + * [mod_privileges](http://httpd.apache.org/docs/2.4/mod/mod_privileges.html) - Support for Solaris privileges and for running virtual hosts under different user IDs. + * [mod_socache_dc](http://httpd.apache.org/docs/2.4/mod/mod_socache_dc.html) - Distcache based shared object cache provider. + * [mod_version](http://httpd.apache.org/docs/2.4/mod/mod_version.html) - Version dependent configuration + * [mod_watchdog](http://httpd.apache.org/docs/2.4/mod/mod_watchdog.html) - Provides infrastructure for other modules to periodically run tasks + +v3.1.0 (2015-05-25) +------------------- + +- [GH-315] Fix `apache.default_site_name` .conf extension references to ensure deletion +- [GH-258] Use `apache.default_site_name` for consistency, minimize hardcoding of filenames +- [GH-259] Add `&& sleep 1` to end of apache restart command on rhel-based systems using apache2.2 +- [GH-271] Remove FreeBSD 9.x, Red Hat and CentOS 5.x and OpenSUSE 11.x Series from tests and focus on newer releases +- [GH-276] Add psych gem to development gems +- [GH-293] Add `apache.mod_fastcgi.install_method` flag to allow install of mod_fastcgi from source (even on Debian family) +- [GH-285] Made `apache.devel_package` configurable based on platform, including support for Amazon Linux. +- [GH-316] Update Opscode references to Chef +- [GH-318] Apply default recipe in all definitions +- [GH-320] Add attribute to adjust `apache.default_site_port` +- [GH-321] Fix issue with default_site name in not_if guards +- [GH-322] Add `apache.mod_ssl.pkg_name` to allow custom mod_ssl package names. Set defaults for supported platforms including Amazon Linux +- [GH-323] Don't create the default site configuration file in `sites-available` unless it is enabled. +- [GH-324] Add `apache.mod_ssl.port` to set the default ssl port to something other than 443 +- [GH-328] Add the ability to pass in a pipe as to log +- [GH-332] `SSLStrictSNIVHostCheck` is only written to config if enabled to avoid breaking apache prior to 2.2.12. +- [GH-334] Removed `iptables`, `god-monitor`, and `logrotate` recipes to avoid having external dependencies. These services should be managed in a wrapper cookbook going forward. +- [GH-339] Allow custom names for php so_filename (`node['apache']['mod_php5']['so_filename']`) + + +v3.0.1 (2015-02-11) +------------------- + +- [GH-310] Ubuntu Apache 2.2 requires the lock_dir to be owned by www-data +- [GH-309] Clarify that apache.version is a string +- [GH-305] Restart service after MPM changes +- [GH-304] Don't install systemd module on Amazon Linux +- [GH-298] Add non-threaded MPM break notice for PHP users +- [GH-296] Create lock_dir automatically + +v3.0.0 (2014-11-30) +------------------- +Major version update because of SSL Improvements and new platform MPM and Version defaults. + +- [GH-286] Refactor MPM and Apache version defaults: default is now apache 2.4 +- Note: set `apache.mpm` to `prefork` if you are using `mod_php` in Ubuntu >=14.04 +- [GH-281] mod_ssl: Disable SSLv3 by default to protect against POODLE attack (CVE-2014-3566) +- [GH-280] mod_ssl: Major update with modern Cipher Suite, and best practices. + Updated to a more modern default `apache.mod_ssl.cipher_suite`. + Added the following additional mod_ssl attributes + * `apache.mod_ssl.honor_cipher_order` + * `apache.mod_ssl.insecure_renegotiation` + * `apache.mod_ssl.strict_sni_vhost_check` + * `apache.mod_ssl.session_cache_timeout` + * `apache.mod_ssl.compression` + * `apache.mod_ssl.use_stapling` + * `apache.mod_ssl.stapling_responder_timeout` + * `apache.mod_ssl.stapling_return_responder_errors` + * `apache.mod_ssl.stapling_cache` + * `apache.mod_ssl.pass_phrase_dialog` + * `apache.mod_ssl.mutex` + * `apache.mod_ssl.directives` +- [GH-278] Improved chefspec tests execution time +- [GH-277] Optimize files watching for Guard on Win32 platform +- [GH-270] Don't attempt start until after configuration is written +- [GH-268] Now uses chefspec 4.1 +- [GH-267] Use Supermarket as the Berkshelf 3 source +- [GH-266] Rubocop based ruby style/syntax improvements +- [GH-264] mod_ssl: Add new attribute for to be ready to any custom directive +- [GH-249] Don't prepend Apache log path when requesting error logging to syslog +- [GH-247] Explicitly include mod_ldap before mod_authnz_ldap +- [GH-243] Expand mpm options for different distros/versions. +- [GH-239] Added `apache.mod_php5.install_method` attribute defaults to `package`. Install packages unless PHP is compiled from source. +- OneHealth Solutions was acquired by Viverae +- Remove ArchLinux pacman as a dependency and handle similar to apt, yum, zypper +- Adjust ubuntu apache 2.4 docroot_dir to match package (from /var/www to /var/www/html) +- [GH-238] Bump service config syntax check guard timeout to 10 seconds +- [GH-235] Removed `apache2::mpm_itk` which is not part of core and therefore should be its own cookbook +- [GH-234] /var/run/httpd/mod_fcgid directory now belongs to apache on Fedora/RHEL systems. +- [GH-233] Default web_app template should return 503 status code when maintenance file is present +- [GH-232] Cookbook now deletes a2* if they are symlinks before dropping template versions +- [GH-222] Set TraceEnable to off by default. +- [GH-213] Adjust chefspec to use the package resource on FreeBSD (previously freebsd_package) +- [GH-212] New attribute apache.locale which sets LANG. defaults to 'C' +- [GH-210] Clarify web_app definition usage around configuration templates. +- [GH-208] `apache_conf` now accepts `source` and `cookbook` parameters. + +v2.0.0 (2014-08-06) +-------------------- +Major version update because of major overhaul to support Apache 2.4 and a2enconf and a2endisconf changes. + +- [GH-204] mod_auth_openid: Added `apache.mod_auth_openid.version` attribute +- FreeBSD support has been improved with the release of chef 11.14.2, portsnap is no longer used in favor of pkgng. +- [GH-157] - Apache will only be started when a configuration test passes, this allows the chef run to fix any broken configuration without failing the chef run. +- `apache.log_dir` directory is now 0755 on all platforms (including the debian platform family) +- [GH-166, GH-173] - `conf.d` is no longer used and replaced by `conf-available` and `conf-enabled` managed via the `a2enconf` and `a2disconf` scripts +- [GH-166, GH-173] - All configuration files need to end in `.conf` for them to be loaded +- [GH-173] - Perl is a required package on all platforms to support the a2* scripts as we now use the debian versions directly. +- [GH-193] - per MPM settings: `maxclients` is now `maxrequestworkers` +- [GH-194] - per MPM settings: `maxrequestsperchild` is now `maxconnectionsperchild` +- [GH-161] - Added support for CentOS 7 +- [GH-180] - Improved SuSE support +- [GH-100] - Apache HTTP 2.4 support + This provides Apache 2.4 support in a backwards compatible way. + It adds the following new attributes: + - `apache.version` - This defaults to `2.2` and if changed to `2.4`; it triggers and assumes 2.4 packages will be installed. + - `apache.mpm` - In 2.4 mode, this specifies which mpm to install. Default is `prefork`. + - `apache.run_dir` + - `apache.lock_dir` + - `apache.libexec_dir` replaces `apache.libexecdir` + - `apache.prefork.maxrequestworkers` replaces `apache.prefork.maxclients` + - `apache.prefork.maxconnectionsperchild` replaces `apache.prefork.maxrequestsperchild` + - `apache.worker.threadlimit` + - `apache.worker.maxrequestworkers` replaces `apache.worker.maxclients` + - `apache.worker.maxconnectionsperchild `replaces `apache.worker.maxrequestsperchild` + - `apache.event.startservers` + - `apache.event.serverlimit` + - `apache.event.minsparethreads` + - `apache.event.maxsparethreads` + - `apache.event.threadlimit` + - `apache.event.threadsperchild` + - `apache.event.maxrequestworkers` + - `apache.event.maxconnectionsperchild` + - `apache.itk.startservers` + - `apache.itk.minspareservers` + - `apache.itk.maxspareservers` + - `apache.itk.maxrequestworkers` + - `apache.itk.maxconnectionsperchild` + + Apache 2.4 Upgrade Notes: + + Since the changes between apache 2.2 and apache 2.4 are pretty significant, we are unable to account for all changes needed for your upgrade. Please take a moment to familiarize yourself with the Apache Software Foundation provided upgrade documentation before attempting to use this cookbook with apache 2.4. See http://httpd.apache.org/docs/current/upgrading.html + + - This cookbook does not automatically specify which version of apache to install. We are at the mercy of the `package` provider. It is important, however, to make sure that you configure the `apache.version` attribute to match. For your convenience, we try to set reasonable defaults based on different platforms in our test suite. + - `mod_proxy` - In 2.4 mode, `apache.proxy.order`, `apache.proxy.deny_from`, `apache.proxy.allow_from` are ignored, as the attributes can not be supported in a backwards compatible way. Please use `apache.proxy.require` instead. + +v1.11.0 (2014-07-25) +-------------------- +- [GH-152] - Checking if server_aliases is defined in example +- [GH-106] - Only turn rewrite on once in web_app.conf.erb +- [GH-156] - Correct mod_basic/digest recipe names in README +- Recipe iptables now includes the iptables::default recipe +- Upgrade test-kitchen to latest version +- Replaced minitest integration tests with serverspec tests +- Added chefspec tests + + +v1.10.4 (2014-04-23) +-------------------- +- [COOK-4249] mod_proxy_http requires mod_proxy + + +v1.10.2 (2014-04-09) +-------------------- +- [COOK-4490] - Fix minitest `apache_configured_ports` helper +- [COOK-4491] - Fix minitest: escape regex interpolation +- [COOK-4492] - Fix service[apache2] CHEF-3694 duplication +- [COOK-4493] - Fix template[ports.conf] CHEF-3694 duplication + +As of 2014-04-04 and per [Community Cookbook Diversification](https://wiki.chef.io/display/chef/Community+Cookbook+Diversification) this cookbook now maintained by OneHealth Solutions. Please be patient as we get into the swing of things. + +v1.10.0 (2014-03-28) +-------------------- +- [COOK-3990] - Fix minitest failures on EL5 +- [COOK-4416] - Support the ability to point to local apache configs +- [COOK-4469] - Use reload instead of restart on RHEL + + +v1.9.6 (2014-02-28) +------------------- +[COOK-4391] - uncommenting the PIDFILE line + + +v1.9.4 (2014-02-27) +------------------- +Bumping version for toolchain + + +v1.9.1 (2014-02-27) +------------------- +[COOK-4348] Allow arbitrary params in sysconfig + + +v1.9.0 (2014-02-21) +------------------- +### Improvement +- **[COOK-4076](https://tickets.chef.io/browse/COOK-4076)** - foodcritic: dependencies are not defined properly +- **[COOK-2572](https://tickets.chef.io/browse/COOK-2572)** - Add mod_pagespeed recipe to apache2 + +### Bug +- **[COOK-4043](https://tickets.chef.io/browse/COOK-4043)** - apache2 cookbook does not depend on 'iptables' +- **[COOK-3919](https://tickets.chef.io/browse/COOK-3919)** - Move the default pidfile for apache2 on Ubuntu 13.10 or greater +- **[COOK-3863](https://tickets.chef.io/browse/COOK-3863)** - Add recipe for mod_jk +- **[COOK-3804](https://tickets.chef.io/browse/COOK-3804)** - Fix incorrect datatype for apache/default_modules, use recipes option in metadata +- **[COOK-3800](https://tickets.chef.io/browse/COOK-3800)** - Cannot load modules that use non-standard module identifiers +- **[COOK-1689](https://tickets.chef.io/browse/COOK-1689)** - The perl package name should be configurable + + +v1.8.14 +------- +Version bump for toolchain sanity + + +v1.8.12 +------- +Fixing various style issues for travis + + +v1.8.10 +------- +fixing metadata version error. locking to 3.0" + + +v1.8.8 +------ +Version bump for toolchain sanity + + +v1.8.6 +------ +Locking yum dependency to '< 3' + + +v1.8.4 +------ +### Bug +- **[COOK-3769](https://tickets.chef.io/browse/COOK-3769)** - Fix a critical bug where the `apache_module` could not enable modules + + +v1.8.2 +------ +### Bug +- **[COOK-3766](https://tickets.chef.io/browse/COOK-3766)** - Fix an issue where the `mod_ssl` recipe fails due to a missing attribute + + +v1.8.0 +------ +### Bug +- **[COOK-3680](https://tickets.chef.io/browse/COOK-3680)** - Update template paths +- **[COOK-3570](https://tickets.chef.io/browse/COOK-3570)** - Apache cookbook breaks on RHEL / CentOS 6 +- **[COOK-2944](https://tickets.chef.io/browse/COOK-2944)** - Fix foodcritic failures +- **[COOK-2893](https://tickets.chef.io/browse/COOK-2893)** - Improve mod_auth_openid recipe with guards and idempotency +- **[COOK-2758](https://tickets.chef.io/browse/COOK-2758)** - Fix use of non-existent attribute + +### New Feature +- **[COOK-3665](https://tickets.chef.io/browse/COOK-3665)** - Add recipe for mod_userdir +- **[COOK-3646](https://tickets.chef.io/browse/COOK-3646)** - Add recipe for mod_cloudflare +- **[COOK-3213](https://tickets.chef.io/browse/COOK-3213)** - Add recipe for mod_info + +### Improvement +- **[COOK-3656](https://tickets.chef.io/browse/COOK-3656)** - Parameterize apache2 binary +- **[COOK-3562](https://tickets.chef.io/browse/COOK-3562)** - Allow mod_proxy settings to be configured as attributes +- **[COOK-3326](https://tickets.chef.io/browse/COOK-3326)** - Fix default_test to use ServerTokens attribute +- **[COOK-2635](https://tickets.chef.io/browse/COOK-2635)** - Add support for SVG mime types +- **[COOK-2598](https://tickets.chef.io/browse/COOK-2598)** - FastCGI Module only works on Debian-based platforms +- **[COOK-1984](https://tickets.chef.io/browse/COOK-1984)** - Add option to configure the address apache listens to + + +v1.7.0 +------ +### Improvement + +- [COOK-3073]: make access.log location configurable per-platform +- [COOK-3074]: don't hardcode the error.log location in the default site config +- [COOK-3268]: don't hardcode DocumentRoot and cgi-bin locations in `default_site` + +### New Feature + +- [COOK-3184]: Add `mod_filter` recipe to Apache2-cookbook +- [COOK-3236]: Add `mod_action` recipe to Apache2-cookbook + +v1.6.6 +------ +1.6.4 had a missed step in the automated release, long live 1.6.6. + +### Bug + +- [COOK-3018]: apache2_module does duplicate delayed restart of apache2 service when conf = true +- [COOK-3027]: Default site enable true, then false, does not disable default site +- [COOK-3109]: fix apache lib_dir arch attribute regexp + +v1.6.2 +------ +- [COOK-2535] - `mod_auth_openid` requires libtool to run autogen.sh +- [COOK-2667] - Typo in usage documentation +- [COOK-2461] - `apache2::mod_auth_openid` fails on some ubuntu systems +- [COOK-2720] - Apache2 minitest helper function `ran_recipe` is not portable + +v1.6.0 +------ +- [COOK-2372] - apache2 mpm_worker: add ServerLimit attribute (default to 16) + +v1.5.0 +------ +The `mod_auth_openid` attributes are changed. The upstream maintainer deprecated the older release versions, and the source repository has releases available at specific SHA1SUM references. The new attribute, `node['apache']['mod_auth_openid']['ref']` is used to set this. + +- [COOK-2198] - `apache::mod_auth_openid` compiles from source, but does not install make on debian/ubuntu +- [COOK-2224] - version conflict between cucumber and other gems +- [COOK-2248] - `apache2::mod_php5` uses `not_if` "which php" without ensuring package 'which' is installed +- [COOK-2269] - Set allow list for mod_status incase external monitor scripts need +- [COOK-2276] - cookbook apache2 documentation regarding listening ports doesn't match default attributes +- [COOK-2296] - `mod_auth_openid` doesn't have tags/releases for the version I need for features and fixes +- [COOK-2323] - Add Oracle linux support + +v1.4.2 +------ +- [COOK-1721] - fix logrotate recipe + +v1.4.0 +------ +- [COOK-1456] - iptables enhancements +- [COOK-1473] - apache2 does not disable default site when setting "`default_site_enabled`" back to false +- [COOK-1824] - the apache2 cookbook needs to specify which binary is used on rhel platform +- [COOK-1916] - Download location wrong for apache2 `mod_auth_openid` >= 0.7 +- [COOK-1917] - Improve `mod_auth_openid` recipe to handle module upgrade more gracefully +- [COOK-2029] - apache2 restarts on every run on RHEL and friends, generate-module-list on every run. +- [COOK-2036] - apache2: Cookbook style + +v1.3.2 +------ +- [COOK-1804] - fix `web_app` definition parameter so site can be disabled. + +v1.3.0 +------ +- [COOK-1738] - Better configuration for `mod_include` and some overrides in `web_app` definition +- [COOK-1470] - Change SSL Ciphers to Mitigate BEAST attack + +v1.2.0 +------ +- [COOK-692] - delete package conf.d files in module recipes, for EL +- [COOK-1693] - Foodcritic finding for unnecessary string interpolation +- [COOK-1757] - platform_family and better style / usage practices + +v1.1.16 +------- +re-releasing as .16 due to error on tag 1.1.14 + +- [COOK-1466] - add `mod_auth_cas` recipe +- [COOK-1609] - apache2 changes ports.conf twice per run when using apache2::mod_ssl + +v1.1.12 +------- +- [COOK-1436] - restore apache2 web_app definition +- [COOK-1356] - allow ExtendedStatus via attribute +- [COOK-1403] - add mod_fastcgi recipe + +v1.1.10 +------- +- [COOK-1315] - allow the default site to not be enabled +- [COOK-1328] - cookbook tests (minitest, cucumber) + +v1.1.8 +------ +- Some platforms with minimal installations that don't have perl won't have a `node['languages']['perl']` attribute, so remove the conditional and rely on the power of idempotence in the package resource. +- [COOK-1214] - address foodcritic warnings +- [COOK-1180] - add `mod_logio` and fix `mod_proxy` + +v1.1.6 +------ +FreeBSD users: This release requires the `freebsd` cookbook. See README.md. + +- [COOK-1025] - freebsd support in mod_php5 recipe + +v1.1.4 +------ +- [COOK-1100] - support amazon linux + +v1.1.2 +------ +- [COOK-996] - apache2::mod_php5 can cause PHP and module API mismatches +- [COOK-1083] - return string for v_f_p and use correct value for default + +v1.1.0 +------ +- [COOK-861] - Add `mod_perl` and apreq2 +- [COOK-941] - fix `mod_auth_openid` on FreeBSD +- [COOK-1021] - add a commented-out LoadModule directive to keep apxs happy +- [COOK-1022] - consistency for icondir attribute +- [COOK-1023] - fix platform test for attributes +- [COOK-1024] - fix a2enmod script so it runs cleanly on !bash +- [COOK-1026] - fix `error_log` location on FreeBSD + +v1.0.8 +------ +- COOK-548 - directory resource doesn't have backup parameter + +v1.0.6 +------ +- COOK-915 - update to `mod_auth_openid` version 0.6, see __Recipes/mod_auth_openid__ below. +- COOK-548 - Add support for FreeBSD. + +v1.0.4 +------ +- COOK-859 - don't hardcode module paths + +v1.0.2 +------ +- Tickets resolved in this release: COOK-788, COOK-782, COOK-780 + +v1.0.0 +------ +- Red Hat family support is greatly improved, all recipes except `god_monitor` converge. +- Recipe `mod_auth_openid` now works on RHEL family distros +- Recipe `mod_php5` will now remove config from package on RHEL family so it doesn't conflict with the cookbook's. +- Added `php5.conf.erb` template for `mod_php5` recipe. +- Create the run state directory for `mod_fcgid` to prevent a startup error on RHEL version 6. +- New attribute `node['apache']['lib_dir']` to handle lib vs lib64 on RHEL family distributions. +- New attribute `node['apache']['group']`. +- Scientific Linux support added. +- Use a file resource instead of the generate-module-list executed perl script on RHEL family. +- "default" site can now be disabled. +- web_app now has an "enable" parameter. +- Support for dav_fs apache module. +- Tickets resolved in this release: COOK-754, COOK-753, COOK-665, COOK-624, COOK-579, COOK-519, COOK-518 +- Fix node references in template for a2dissite +- Use proper user and group attributes on files and templates. +- Replace the anemic README.rdoc with this new and improved superpowered README.md :). diff --git a/cookbooks/apache2/CONTRIBUTING.md b/cookbooks/apache2/CONTRIBUTING.md new file mode 100644 index 0000000..b17a5fa --- /dev/null +++ b/cookbooks/apache2/CONTRIBUTING.md @@ -0,0 +1,105 @@ +# Contributing to the apache2 cookbook + +We are glad you want to contribute to the apache2 cookbook! The first +step is the desire to improve the project. + +## Quick-contribute + +* Create an issue on the github [issue tracker](https://github.com/sous-chefs/apache2/issues) +* Link to your patch as a rebased git branch or pull request from the ticket + +We regularly review contributions and will get back to you if we have +any suggestions or concerns. + +### Branches and Commits + +You should submit your patch as a git branch named after the change. + +It is a best practice to have your commit message have a _summary +line_, followed by an empty line and then a brief description of +the commit. This also helps other contributors understand the +purpose of changes to the code. + +Remember that not all users use Chef in the same way or on the same +operating systems as you, so it is helpful to be clear about your use +case and change so they can understand it even when it doesn't apply +to them. + +### Github and Pull Requests + +We don't require you to use Github, and we will even take patch diffs +attached to tickets on the issue tracker. However Github has a lot of +convenient features, such as being able to see a diff of changes +between a pull request and the main repository quickly without +downloading the branch. + +## Functional and Unit Tests + +This cookbook is set up to run tests under +[Test Kitchen](http://kitchen.ci/). It uses serverspec to run +integration tests after the node has been converged to verify that +the state of the node. + +Test kitchen should run completely without exception using the default +[baseboxes provided by Chef](http://chef.github.io/bento/). +Because Test Kitchen creates VirtualBox machines and runs through +every configuration in the .kitchen.yml file, it may take some time for +these tests to complete. + +If your changes are only for a specific recipe, run only its +configuration with Test Kitchen. If you are adding a new recipe, or +other functionality such as a LWRP or definition, please add +appropriate tests and ensure they run with Test Kitchen. + +If any don't pass, investigate them before submitting your patch. + +Any new feature should have unit tests included with the patch with +good code coverage to help protect it from future changes. Similarly, +patches that fix a bug or regression should have a _regression test_. +Simply put, this is a test that would fail without your patch but +passes with it. The goal is to ensure this bug doesn't regress in the +future. Consider a regular expression that doesn't match a certain +pattern that it should, so you provide a patch and a test to ensure +that the part of the code that uses this regular expression works as +expected. Later another contributor may modify this regular expression +in a way that breaks your use cases. The test you wrote will fail, +signalling to them to research your ticket and use case and accounting +for it. + +If you need help writing tests, please ask on the Chef Developer's +mailing list, or https://community-slack.chef.io/ + +## Cookbook Contribution Do's and Don't's + +Please do include tests for your contribution. If you need help, ask +on the +[chef-dev mailing list](http://lists.chef.io/sympa/info/chef-dev) +or the https://community-slack.chef.io/ + +Not all platforms that a cookbook supports may be supported by Test +Kitchen. Please provide evidence of testing your contribution if it +isn't trivial so we don't have to duplicate effort in testing. Chef +10.14+ "doc" formatted output is sufficient. + +Please do indicate new platform (families) or platform versions in the +commit message, and update the relevant ticket. If a contribution adds +new platforms or platform versions, indicate such in the body of the commit message(s). + +Please do use [foodcritic](http://www.foodcritic.io/) to +lint-check the cookbook. Except FC007, it should pass all correctness +rules. FC007 is okay as long as the dependent cookbooks are *required* +for the default behavior of the cookbook, such as to support an +uncommon platform, secondary recipe, etc. + +Please do ensure that your changes do not break or modify behavior for +other platforms supported by the cookbook. For example if your changes +are for Debian, make sure that they do not break on CentOS. + +Please do not modify the version number in the metadata.rb, the maintainer +will select the appropriate version based on the release cycle +information above. + +Please do not update the CHANGELOG.md for a new version. Not all +changes to a cookbook may be merged and released in the same versions. +We will update the CHANGELOG.md when releasing a new version of +the cookbook. diff --git a/cookbooks/apache2/README.md b/cookbooks/apache2/README.md new file mode 100644 index 0000000..b55bb33 --- /dev/null +++ b/cookbooks/apache2/README.md @@ -0,0 +1,693 @@ +apache2 Cookbook +================ +[![Cookbook Version](https://img.shields.io/cookbook/v/apache2.svg?style=flat)](https://supermarket.chef.io/cookbooks/apache2) +[![Build Status](https://travis-ci.org/sous-chefs/apache2.svg?branch=master)](https://travis-ci.org/sous-chefs/apache2) +[![Dependency Status](http://img.shields.io/gemnasium/sous-chefs/apache2.svg?style=flat)](https://gemnasium.com/sous-chefs/apache2) +[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) + +This cookbook provides a complete Debian/Ubuntu style Apache HTTPD +configuration. Non-Debian based distributions such as Red Hat/CentOS, +ArchLinux and others supported by this cookbook will have a +configuration that mimics Debian/Ubuntu style as it is easier to +manage with Chef. + +Debian-style Apache configuration uses scripts to manage modules and +sites (vhosts). The scripts are: + +* a2ensite +* a2dissite +* a2enmod +* a2dismod +* a2enconf +* a2disconf + +This cookbook ships with templates of these scripts for non +Debian/Ubuntu platforms. The scripts are used in the __Definitions__ +below. + +## Cookbooks: + +This cookbook has no direct external dependencies. + +Depending on your OS configuration and security policy, you may need +additional recipes or cookbooks for this cookbook's recipes to +converge on the node. In particular, the following Operating System +settings may affect the behavior of this cookbook: + +* apt cache outdated +* SELinux enabled +* firewalls (such as iptables, ufw, etc.) +* Compile tools +* 3rd party repositories + +On Ubuntu/Debian, use [apt](https://supermarket.chef.io/cookbooks/apt) cookbook to ensure the package +cache is updated so Chef can install packages, or consider putting +apt-get in your bootstrap process or +[knife bootstrap template](http://docs.chef.io/knife_bootstrap.html) + +On RHEL, SELinux is enabled by default. The [selinux](https://supermarket.chef.io/cookbooks/selinux) cookbook +contains a `permissive` recipe that can be used to set SELinux to +"Permissive" state. Otherwise, additional recipes need to be created +by the user to address SELinux permissions. + + +To deal with firewalls Chef Software does provide an [iptables](https://supermarket.chef.io/cookbooks/iptables) and [ufw](https://supermarket.chef.io/cookbooks/ufw) cookbook but is migrating from the approach used there to a more robust solution +utilizing the general [firewall](https://supermarket.chef.io/cookbooks/firewall) cookbook to setup rules. +See those cookbooks' READMEs for documentation. + +Build/compile tools may not be installed on the system by default. +Some recipes (e.g., `apache2::mod_auth_openid`) build the module from +source. Use the [build-essential](https://supermarket.chef.io/cookbooks/build-essential) cookbook to get essential +build packages installed. + +On ArchLinux, if you are using the `apache2::mod_auth_openid` recipe, +you also need the [pacman](https://supermarket.chef.io/cookbooks/pacman) cookbook for the `pacman_aur` LWRP. Put +`recipe[pacman]` on the node's expanded run list (on the node or in a +role). This is not an explicit dependency because it is only required +for this single recipe and platform; the pacman default recipe +performs `pacman -Sy` to keep pacman's package cache updated. + +## Platforms: + +The following platforms and versions are tested and supported using +[test-kitchen](http://kitchen.ci/) + +* Ubuntu 14.04 +* Ubuntu 16.04 +* Debian 8.6 +* CentOS 7.3 +* Fedora 25 + +The following platform families are supported in the code, and are +assumed to work based on the successful testing on Ubuntu and CentOS. + +* Red Hat (rhel) + +The following platforms are also supported in the code, have been +tested manually but are not regularly tested under test-kitchen. + +* Amazon Linux +* SUSE/OpenSUSE +* ArchLinux +* FreeBSD + +### Notes for RHEL Family: + +On Red Hat Enterprise Linux and derivatives, the EPEL repository may +be necessary to install packages used in certain recipes. The +`apache2::default` recipe, however, does not require any additional +repositories. The [yum-epel](https://supermarket.chef.io/cookbooks/yum-epel) cookbook can be used to add the +EPEL repository. See __Examples__ for more information. + +Usage +===== + +Using this cookbook is relatively straightforward. It is recommended to create +a project or organization specific [wrapper cookbook](https://www.chef.io/blog/2013/12/03/doing-wrapper-cookbooks-right/) +and add the desired recipes to the run list of a node, or create a role. Depending on your +environment, you may have multiple roles that use different recipes +from this cookbook. Adjust any attributes as desired. For example, to +create a basic role for web servers that provide both HTTP and HTTPS: + +```ruby + % cat roles/webserver.rb + name "webserver" + description "Systems that serve HTTP and HTTPS" + run_list( + "recipe[apache2]", + "recipe[apache2::mod_ssl]" + ) + default_attributes( + "apache" => { + "listen" => ["*:80", "*:443"] + } + ) +``` + +For examples of using the definitions in your own recipes, see their +respective sections below. + + +Attributes +========== + +This cookbook uses many attributes, broken up into a few different +kinds. + +Platform specific +----------------- + +In order to support the broadest number of platforms, several +attributes are determined based on the node's platform. See the +attributes/default.rb file for default values in the case statement at +the top of the file. + +* `node['apache']['package']` - Package name for Apache2 +* `node['apache']['perl_pkg']` - Package name for Perl +* `node['apache']['dir']` - Location for the Apache configuration +* `node['apache']['log_dir']` - Location for Apache logs +* `node['apache']['error_log']` - Location for the default error log +* `node['apache']['access_log']` - Location for the default access log +* `node['apache']['user']` - User Apache runs as +* `node['apache']['group']` - Group Apache runs as +* `node['apache']['binary']` - Apache httpd server daemon +* `node['apache']['conf_dir']` - Location for the main config file (e.g apache2.conf or httpd.conf) +* `node['apache']['docroot_dir']` - Location for docroot +* `node['apache']['cgibin_dir']` - Location for cgi-bin +* `node['apache']['icondir']` - Location for icons +* `node['apache']['cache_dir']` - Location for cached files used by Apache itself or recipes +* `node['apache']['pid_file']` - Location of the PID file for Apache httpd +* `node['apache']['lib_dir']` - Location for shared libraries +* `node['apache']['default_site_enabled']` - Default site enabled. Default is false. +* `node['apache']['ext_status']` - if true, enables ExtendedStatus for `mod_status` +* `node['apache']['locale']` - Locale to set in sysconfig or envvars and used for subprocesses and modules (like mod_dav and mod_wsgi). On debian systems Uses system-local if set to 'system', defaults to 'C'. + +General settings +---------------- + +These are general settings used in recipes and templates. Default +values are noted. + +* `node['apache']['version']` - Specifing 2.4 triggers apache 2.4 support. If the platform is known during our test to install 2.4 by default, it will be set to 2.4 for you. Otherwise it falls back to 2.2. This value should be specified as a string. +* `node['apache']['listen']` - Array of address:port combinations that httpd should listen on. Default is any address and port 80 (`["*:80"]`). +* `node['apache']['contact']` - Value for ServerAdmin directive. Default "ops@example.com". +* `node['apache']['timeout']` - Value for the Timeout directive. Default is 300. +* `node['apache']['keepalive']` - Value for the KeepAlive directive. Default is On. +* `node['apache']['keepaliverequests']` - Value for MaxKeepAliveRequests. Default is 100. +* `node['apache']['keepalivetimeout']` - Value for the KeepAliveTimeout directive. Default is 5. +* `node['apache']['sysconfig_additional_params']` - Additionals variables set in sysconfig file. Default is empty. +* `node['apache']['log_level']` - Value for LogLevel directive. Default is 'warn'. +* `node['apache']['default_modules']` - Array of module names. Can take "mod_FOO" or "FOO" as names, where FOO is the apache module, e.g. "`mod_status`" or "`status`". +* `node['apache']['mpm']` - With apache.version 2.4, specifies what Multi-Processing Module to enable. Defaults to platform default, otherwise it is "prefork" + +The modules listed in `default_modules` will be included as recipes in `recipe[apache::default]`. + +Prefork attributes +------------------ + +Prefork attributes are used for tuning the Apache HTTPD [prefork MPM](http://httpd.apache.org/docs/current/mod/prefork.html) configuration. + +* `node['apache']['prefork']['startservers']` - initial number of server processes to start. Default is 16. +* `node['apache']['prefork']['minspareservers']` - minimum number of spare server processes. Default 16. +* `node['apache']['prefork']['maxspareservers']` - maximum number of spare server processes. Default 32. +* `node['apache']['prefork']['serverlimit']` - upper limit on configurable server processes. Default 256. +* `node['apache']['prefork']['maxrequestworkers']` - Maximum number of connections that will be processed simultaneously. Default 256. +* `node['apache']['prefork']['maxconnectionsperchild']` - Maximum number of request a child process will handle. Default 10000. + +Worker attributes +----------------- + +Worker attributes are used for tuning the Apache HTTPD [worker MPM](http://httpd.apache.org/docs/current/mod/worker.html) +configuration. + +* `node['apache']['worker']['startservers']` - Initial number of server processes to start. Default 4 +* `node['apache']['worker']['serverlimit']` - Upper limit on configurable server processes. Default 16. +* `node['apache']['worker']['minsparethreads']` - Minimum number of spare worker threads. Default 64 +* `node['apache']['worker']['maxsparethreads']` - Maximum number of spare worker threads. Default 192. +* `node['apache']['worker']['maxrequestworkers']` - Maximum number of simultaneous connections. Default 1024. +* `node['apache']['worker']['maxconnectionsperchild']` - Limit on the number of connections that an individual child server will handle during its life. + +Event attributes +---------------- + +Event attributes are used for tuning the Apache HTTPD [event MPM](http://httpd.apache.org/docs/current/mod/event.html) +configuration. + +* `node['apache']['event']['startservers']` - Initial number of child server processes created at startup. Default 4. +* `node['apache']['event']['serverlimit']` - Upper limit on configurable number of processes. Default 16. +* `node['apache']['event']['minsparethreads']` - Minimum number of spare worker threads. Default 64 +* `node['apache']['event']['maxsparethreads']` - Maximum number of spare worker threads. Default 192. +* `node['apache']['event']['threadlimit']` - Upper limit on the configurable number of threads per child process. Default 192. +* `node['apache']['event']['threadsperchild']` - Number of threads created by each child process. Default 64. +* `node['apache']['event']['maxrequestworkers']` - Maximum number of connections that will be processed simultaneously. +* `node['apache']['event']['maxconnectionsperchild']` - Limit on the number of connections that an individual child server will handle during its life. + +Other/Unsupported MPM +--------------------- + +To use the cookbook with an unsupported mpm (other than prefork, event or worker): + +* set `node['apache']['mpm']` to the name of the module (e.g. `itk`) +* in your cookbook, after `include_recipe 'apache2'` use the `apache_module` definition to enable/disable the required module(s) + +Module specific attributes +-------------------------- + +Some module recipes have their own attributes that can be used to alter and modify the behavior of this cookbook. Please see the sections for the indivual modules below for more information on those attributes. + + + +Recipes +======= + +Most of the recipes in the cookbook are for enabling Apache modules. +Where additional configuration or behavior is used, it is documented +below in more detail. + +The following recipes merely enable the specified module: `mod_actions`, `mod_alias`, +`mod_auth_basic`, `mod_auth_digest`, `mod_authn_file`, `mod_authnz_ldap`, +`mod_authz_default`, `mod_authz_groupfile`, `mod_authz_host`, +`mod_authz_user`, `mod_autoindex`, `mod_cgi`, `mod_dav_fs`, +`mod_dav_svn`, `mod_deflate`, `mod_dir`, `mod_env`, `mod_expires`, +`mod_headers`, `mod_ldap`, `mod_log_config`, `mod_mime`, +`mod_negotiation`, `mod_proxy`, `mod_proxy_ajp`, `mod_proxy_balancer`, +`mod_proxy_connect`, `mod_proxy_http`, `mod_python`, `mod_rewrite`, +`mod_setenvif`, `mod_status`, `mod_wsgi`, `mod_xsendfile`. + +On RHEL Family distributions, certain modules ship with a config file +with the package. The recipes here may delete those configuration +files to ensure they don't conflict with the settings from the +cookbook, which will use per-module configuration in +`/etc/httpd/mods-enabled`. + +default +------- + +The default recipe does a number of things to set up Apache HTTPd. It +also includes a number of modules based on the attribute +`node['apache']['default_modules']` as recipes. + +mod\_auth\_cas +-------------- + +This recipe installs the proper package and enables the `auth_cas` +module. It can install from source or package. Package is the default, +set the attribute `node['apache']['mod_auth_cas']['from_source']` to +true to enable source installation. Modify the version to install by +changing the attribute +`node['apache']['mod_auth_cas']['source_revision']`. It is a version +tag by default, but could be master, or another tag, or branch. + +The module configuration is written out with the `CASCookiePath` set, +otherwise an error loading the module may cause Apache to not start. + +**Note**: This recipe does not work on EL 6 platforms unless +epel-testing repository is enabled (outside the scope of this +cookbook), or the package version 1.0.8.1-3.el6 or higher is otherwise +available to the system due to this bug: + +https://bugzilla.redhat.com/show_bug.cgi?format=multiple&id=708550 + +mod\_auth\_openid +----------------- + +This recipe compiles the module from source. In addition to +`build-essential`, some other packages are included for installation +like the GNU C++ compiler and development headers. + +To use the module in your own cookbooks to authenticate systems using +OpenIDs, specify an array of OpenIDs that are allowed to authenticate +with the attribute `node['apache']['allowed_openids']`. Use the +following in a vhost to protect with OpenID authentication: + + AuthType OpenID require user <%= node['apache']['allowed_openids'].join(' ') %> + AuthOpenIDDBLocation <%= node['apache']['mod_auth_openid']['dblocation'] %> + +Change the DBLocation with the attribute as required; this file is in +a different location than previous versions, see below. It should be a +sane default for most platforms, though, see +`attributes/mod_auth_openid.rb`. + +The following attributes are in the `attributes/mod_auth_openid.rb` file. + +* `node['apache']['mod_auth_openid']['checksum']` - sha256sum of the tarball containing the source. +* `node['apache']['mod_auth_openid']['ref']` - Any sha, tag, or branch found from https://github.com/bmuller/mod_auth_openid +* `node['apache']['mod_auth_openid']['version']` - directory name version within the tarball +* `node['apache']['mod_auth_openid']['cache_dir']` - the cache directory is where the sqlite3 database is stored. It is separate so it can be managed as a directory resource. +* `node['apache']['mod_auth_openid']['dblocation']` - filename of the sqlite3 database used for directive `AuthOpenIDDBLocation`, stored in the `cache_dir` by default. +* `node['apache']['mod_auth_openid']['configure_flags']` - optional array of configure flags passed to the `./configure` step in the compilation of the module. + + +mod\_fastcgi +------------ + +Install the fastcgi package and enable the module. + +Note: In Ubuntu 14.04, the `libapache2-mod-fastcgi` module is not available by default due to the [Multiverse](https://help.ubuntu.com/community/Repositories/Ubuntu) repositories. +You need to enable the multiverse repositories either from `/etc/apt/sources.list` or use the [apt](https://supermarket.chef.io/cookbooks/apt) cookbook. + +mod\_fcgid +---------- + +Installs the fcgi package and enables the module. Requires EPEL on +RHEL family. + +mod\_php5 +-------- + +Simply installs the appropriate package on Debian, Ubuntu and +ArchLinux. + +On Red Hat family distributions including Fedora, the php.conf that +comes with the package is removed. On RHEL platforms less than v6, the +`php53` package is used. + +* `node['apache']['mod_php5']['install_method']` - default `package` can be overridden to avoid package installs. + +mod\_ssl +-------- + +Besides installing and enabling `mod_ssl`, this recipe will append +port 443 to the `node['apache']['listen']` attributes for all addresses and +update the ports.conf. + + +* `node['apache']['mod_ssl']['cipher_suite']` - sets the SSLCiphersuite value to the specified string. The default is + considered "sane" but you may need to change it for your local security policy, e.g. if you have PCI-DSS requirements. Additional + commentary on the + [original pull request](https://github.com/sous-chefs/apache2/pull/15#commitcomment-1605406). +* `node['apache']['mod_ssl']['honor_cipher_order']` - Option to prefer the server's cipher preference order. Default 'On'. +* `node['apache']['mod_ssl']['insecure_renegotiation']` - Option to enable support for insecure renegotiation. Default 'Off'. +* `node['apache']['mod_ssl']['strict_sni_vhost_check']` - Whether to allow non-SNI clients to access a name-based virtual host. Default 'Off'. +* `node['apache']['mod_ssl']['session_cache']` - Configures the OCSP stapling cache. Default `shmcb:/var/run/apache2/ssl_scache` +* `node['apache']['mod_ssl']['session_cache_timeout']` - Number of seconds before an SSL session expires in the Session Cache. Default 300. +* `node['apache']['mod_ssl']['compression']` - Enable compression on the SSL level. Default 'Off'. +* `node['apache']['mod_ssl']['use_stapling']` - Enable stapling of OCSP responses in the TLS handshake. Default 'Off'. +* `node['apache']['mod_ssl']['stapling_responder_timeout']` - Timeout for OCSP stapling queries. Default 5 +* `node['apache']['mod_ssl']['stapling_return_responder_errors']` - Pass stapling related OCSP errors on to client. Default 'Off' +* `node['apache']['mod_ssl']['stapling_cache']` - Configures the OCSP stapling cache. Default `shmcb:/var/run/ocsp(128000)` +* `node['apache']['mod_ssl']['pass_phrase_dialog']` - Configures SSLPassPhraseDialog. Default `builtin` +* `node['apache']['mod_ssl']['mutex']` - Configures SSLMutex. Default `file:/var/run/apache2/ssl_mutex` +* `node['apache']['mod_ssl']['directives']` - Hash for add any custom directive. + +For general information on these attributes see http://httpd.apache.org/docs/current/mod/mod_ssl.html + +For more information on these directives and how to best secure your site see +- https://bettercrypto.org/ +- https://wiki.mozilla.org/Security/Server_Side_TLS +- https://www.insecure.ws/linux/apache_ssl.html +- https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ +- https://istlsfastyet.com/ +- https://www.ssllabs.com/projects/best-practices/ + +Definitions +=========== + +The cookbook provides a few definitions. At some point in the future +these definitions will be refactored into custom resources see +[issue 414](https://github.com/sous-chefs/apache2/issues/414). + +apache\_conf +------------ + +Writes conf files to the `conf-available` folder, and passes enabled values to `apache_config`. + +This definition should generally be called over `apache_config`. + +### Parameters: + +* `name` - Name of the config placed and enabled or disabled with the `a2enconf` or `a2disconf` scripts. +* `enable` - Default true, which uses `a2enconf` to enable the config. If false, the config will be disabled with `a2disconf`. +* `conf_path` - path to put the config in if you need to override the default `conf-available`. +* `source` - The source configuration template name. The default value is `params[:name].conf.erb` +* `cookbook` - The cookbook in which the configuration template is located. The default value is the current cookbook. + +### Examples: + +Place and enable the example conf: + +```ruby + apache_conf 'example' do + enable true + end +``` + +Place and disable (or never enable to begin with) the example conf: + +```ruby + apache_conf 'example' do + enable false + end +``` + +Place the example conf, which has a different path than the default (conf-*): + +```ruby + apache_conf 'example' do + conf_path '/random/example/path' + enable false + end +``` + + +apache\_config (internal) +-------------------------- + +Sets up configuration file for Apache from a template. The +template should be in the same cookbook where the definition is used. This is used by the `apache_conf` definition and should not be used directly. + +It will use `a2enconf` and `a2disconf` to control the symlinking of configuration files between `conf-available` and `conf-enabled`. + +Enable or disable an Apache config file in +`#{node['apache']['dir']}/conf-available` by calling `a2enconf` or +`a2disconf` to manage the symbolic link in +`#{node['apache']['dir']}/conf-enabled`. These config files should be created in your cookbook, and placed on the system using `apache_conf` + +### Parameters: + +* `name` - Name of the config enabled or disabled with the `a2enconf` or `a2disconf` scripts. +* `source` - The location of a template file. The default `name.erb`. +* `cookbook` - The cookbook in which the configuration template is located (if it is not located in the current cookbook). The default value is the current cookbook. +* `enable` - Default true, which uses `a2enconf` to enable the config. If false, the config will be disabled with `a2disconf`. + +### Examples: + +Enable the example config. + +```ruby + apache_config 'example' do + enable true + end +``` + +Disable a module: + +```ruby + apache_config 'disabled_example' do + enable false + end +``` + +See the recipes directory for many more examples of `apache_config`. + + +apache\_module +-------------- + +Enable or disable an Apache module in +`#{node['apache']['dir']}/mods-available` by calling `a2enmod` or +`a2dismod` to manage the symbolic link in +`#{node['apache']['dir']}/mods-enabled`. If the module has a +configuration file, a template should be created in the cookbook where +the definition is used. See __Examples__. + +### Parameters: + +* `name` - Name of the module enabled or disabled with the `a2enmod` or `a2dismod` scripts. +* `identifier` - String to identify the module for the `LoadModule` directive. Not typically needed, defaults to `#{name}_module` +* `enable` - Default true, which uses `a2enmod` to enable the module. If false, the module will be disabled with `a2dismod`. +* `conf` - Default false. Set to true if the module has a config file, which will use `apache_mod` for the file. +* `filename` - specify the full name of the file, e.g. + +### Examples: + +Enable the ssl module, which also has a configuration template in `templates/default/mods/ssl.conf.erb`. + +```ruby + apache_module "ssl" do + conf true + end +``` + +Enable the php5 module, which has a different filename than the module default: + +```ruby + apache_module "php5" do + filename "libphp5.so" + end +``` + +Disable a module: + +```ruby + apache_module "disabled_module" do + enable false + end +``` + +See the recipes directory for many more examples of `apache_module`. + +apache\_mod (internal) +---------------------- + +Sets up configuration file for an Apache module from a template. The +template should be in the same cookbook where the definition is used. +This is used by the `apache_module` definition and is not often used +directly. + +This will use a template resource to write the module's configuration +file in the `mods-available` under the Apache configuration directory +(`node['apache']['dir']`). This is a platform-dependent location. See +__apache\_module__. + +### Parameters: + +* `name` - Name of the template. When used from the `apache_module`, + it will use the same name as the module. + +### Examples: + +Create `#{node['apache']['dir']}/mods-available/alias.conf`. + +```ruby + apache_mod "alias" +``` + +apache\_site +------------ + +Enable or disable a VirtualHost in +`#{node['apache']['dir']}/sites-available` by calling a2ensite or +a2dissite to manage the symbolic link in +`#{node['apache']['dir']}/sites-enabled`. + +The template for the site must be managed as a separate resource. To +combine the template with enabling a site, see `web_app`. + +### Parameters: + +* `name` - Name of the site. +* `enable` - Default true, which uses `a2ensite` to enable the site. If false, the site will be disabled with `a2dissite`. + +web\_app +-------- + +Manage a template resource for a VirtualHost site, and enable it with +`apache_site`. This is commonly done for managing web applications +such as Ruby on Rails, PHP or Django, and the default behavior +reflects that. However it is flexible. + +This definition includes some recipes to make sure the system is +configured to have Apache and some sane default modules: + +* `apache2` +* `apache2::mod_rewrite` +* `apache2::mod_deflate` +* `apache2::mod_headers` + +It will then configure the template (see __Parameters__ and +__Examples__ below), and enable or disable the site per the `enable` +parameter. + +### Parameters: + +Current parameters used by the definition: + +* `name` - The name of the site. The template will be written to + `#{node['apache']['dir']}/sites-available/#{params['name']}.conf` +* `cookbook` - Optional. Cookbook where the source template is. If + this is not defined, Chef will use the named template in the + cookbook where the definition is used. +* `template` - Default `web_app.conf.erb`, source template file. +* `enable` - Default true. Passed to the `apache_site` definition. + +Additional parameters can be defined when the definition is called in +a recipe, see __Examples__. + +### Examples: + +The recommended way to use the `web_app` definition is in a application specific cookbook named "my_app". +The following example would look for a template named 'web_app.conf.erb' in your cookbook containing +the apache httpd directives defining the `VirtualHost` that would serve up "my_app". + +```ruby + web_app "my_app" do + template 'web_app.conf.erb' + server_name node['my_app']['hostname'] + end +``` + +All parameters are passed into the template. You can use whatever you +like. The apache2 cookbook comes with a `web_app.conf.erb` template as +an example. The following parameters are used in the template: + +* `server_name` - ServerName directive. +* `server_aliases` - ServerAlias directive. Must be an array of aliases. +* `docroot` - DocumentRoot directive. +* `application_name` - Used in RewriteLog directive. Will be set to the `name` parameter. +* `directory_index` - Allow overriding the default DirectoryIndex setting, optional +* `directory_options` - Override Options on the docroot, for example to add parameters like Includes or Indexes, optional. +* `allow_override` - Modify the AllowOverride directive on the docroot to support apps that need .htaccess to modify configuration or require authentication. + +To use the default web_app, for example: + +```ruby + web_app "my_site" do + server_name node['hostname'] + server_aliases [node['fqdn'], "my-site.example.com"] + docroot "/srv/www/my_site" + cookbook 'apache2' + end +``` + +The parameters specified will be used as: + +* `@params[:server_name]` +* `@params[:server_aliases]` +* `@params[:docroot]` + +In the template. When you write your own, the `@` is significant. + +For more information about Definitions and parameters, see the +[Chef Wiki](http://docs.chef.io/definitions.html) + +Tests +===== + +This cookbook in the [source repository](https://github.com/sous-chefs/apache2/) +contains chefspec, serverspec tests. + +Please see the CONTRIBUTING file for information on how to add tests +for your contributions. + + +License and Authors +=================== + +* Author:: Adam Jacob +* Author:: Joshua Timberman +* Author:: Bryan McLellan +* Author:: Dave Esposito +* Author:: David Abdemoulaie +* Author:: Edmund Haselwanter +* Author:: Eric Rochester +* Author:: Jim Browne +* Author:: Matthew Kent +* Author:: Nathen Harvey +* Author:: Ringo De Smet +* Author:: Sean OMeara +* Author:: Seth Chisamore +* Author:: Gilles Devaux +* Author:: Sander van Zoest +* Author:: Taylor Price +* Author:: Ben Dean + +* Copyright:: 2009-2012, Chef Software, Inc +* Copyright:: 2011, Atriso +* Copyright:: 2011, CustomInk, LLC. +* Copyright:: 2013-2014, OneHealth Solutions, Inc. +* Copyright:: 2014, Viverae, Inc. +* Copyright:: 2015-2016, Alexander van Zoest +* Copyright:: 2015, Ontario Systems, LLC + +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/cookbooks/apache2/attributes/default.rb b/cookbooks/apache2/attributes/default.rb new file mode 100644 index 0000000..654f753 --- /dev/null +++ b/cookbooks/apache2/attributes/default.rb @@ -0,0 +1,355 @@ +# +# Cookbook:: apache2 +# Attributes:: default +# +# Copyright:: 2008-2013, Chef Software, Inc. +# Copyright:: 2014, Viverae, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +default['apache']['mpm'] = + case node['platform_family'] + when 'debian' + case node['platform'] + when 'ubuntu' + if node['platform_version'].to_f >= 14.04 + 'event' + elsif node['platform_version'].to_f >= 12.04 + 'worker' + else + 'prefork' + end + when 'debian' + node['platform_version'].to_f >= 7.0 ? 'worker' : 'prefork' + when 'linuxmint' + node['platform_version'].to_i >= 17 ? 'event' : 'prefork' + else + 'prefork' + end + when 'suse' + 'prefork' + when 'rhel' + 'prefork' + when 'amazon' + 'prefork' + else + 'prefork' + end + +default['apache']['version'] = + case node['platform_family'] + when 'debian' + case node['platform'] + when 'ubuntu' + node['platform_version'].to_f >= 13.10 ? '2.4' : '2.2' + when 'linuxmint' + node['platform_version'].to_i >= 16 ? '2.4' : '2.2' + when 'debian', 'raspbian' + node['platform_version'].to_f >= 8.0 ? '2.4' : '2.2' + else + '2.4' + end + when 'amazon' + node['platform_version'].to_f >= 2013.09 ? '2.4' : '2.2' + when 'rhel' + case node['platform'] + when 'amazon' + node['platform_version'].to_f >= 2013.09 ? '2.4' : '2.2' + else + node['platform_version'].to_f >= 7.0 ? '2.4' : '2.2' + end + when 'fedora' + '2.4' + when 'suse' + case node['platform'] + when 'suse' + node['platform_version'].to_f >= 12.1 ? '2.4' : '2.2' + else + '2.4' + end + when 'freebsd' + '2.4' + end + +default['apache']['root_group'] = 'root' +default['apache']['default_site_name'] = 'default' + +# Where the various parts of apache are +case node['platform'] +when 'redhat', 'centos', 'scientific', 'fedora', 'amazon', 'oracle' + if node['platform'] == 'amazon' + if node['apache']['version'] == '2.4' + default['apache']['package'] = 'httpd24' + default['apache']['devel_package'] = 'httpd24-devel' + else + default['apache']['package'] = 'httpd22' + default['apache']['devel_package'] = 'httpd22-devel' + end + else + default['apache']['package'] = 'httpd' + default['apache']['devel_package'] = 'httpd-devel' + end + default['apache']['service_name'] = 'httpd' + default['apache']['perl_pkg'] = 'perl' + default['apache']['apachectl'] = '/usr/sbin/apachectl' + default['apache']['dir'] = '/etc/httpd' + default['apache']['log_dir'] = '/var/log/httpd' + default['apache']['error_log'] = 'error.log' + default['apache']['access_log'] = 'access.log' + default['apache']['user'] = 'apache' + default['apache']['group'] = 'apache' + default['apache']['binary'] = '/usr/sbin/httpd' + default['apache']['conf_dir'] = '/etc/httpd/conf' + default['apache']['docroot_dir'] = '/var/www/html' + default['apache']['cgibin_dir'] = '/var/www/cgi-bin' + default['apache']['icondir'] = + if node['apache']['version'] == '2.4' + '/usr/share/httpd/icons' + else + '/var/www/icons' + end + default['apache']['cache_dir'] = '/var/cache/httpd' + default['apache']['run_dir'] = '/var/run/httpd' + default['apache']['lock_dir'] = '/var/run/httpd' + default['apache']['pid_file'] = + if node['platform_version'].to_f >= 6 + '/var/run/httpd/httpd.pid' + else + '/var/run/httpd.pid' + end + default['apache']['lib_dir'] = node['kernel']['machine'] =~ /^i[36]86$/ ? '/usr/lib/httpd' : '/usr/lib64/httpd' + default['apache']['libexec_dir'] = "#{node['apache']['lib_dir']}/modules" +when 'suse', 'opensuse', 'opensuseleap' + default['apache']['package'] = 'apache2' + default['apache']['perl_pkg'] = 'perl' + default['apache']['devel_package'] = 'httpd-devel' + default['apache']['apachectl'] = '/usr/sbin/apache2ctl' + default['apache']['dir'] = '/etc/apache2' + default['apache']['log_dir'] = '/var/log/apache2' + default['apache']['error_log'] = 'error.log' + default['apache']['access_log'] = 'access.log' + default['apache']['user'] = 'wwwrun' + default['apache']['group'] = 'www' + default['apache']['binary'] = '/usr/sbin/httpd2' + default['apache']['conf_dir'] = '/etc/apache2' + default['apache']['docroot_dir'] = '/srv/www/htdocs' + default['apache']['cgibin_dir'] = '/srv/www/cgi-bin' + default['apache']['icondir'] = '/usr/share/apache2/icons' + default['apache']['cache_dir'] = '/var/cache/apache2' + default['apache']['run_dir'] = '/var/run/httpd' + default['apache']['lock_dir'] = '/var/run/httpd' + default['apache']['pid_file'] = + if node['platform_version'].to_f > 11.4 + '/var/run/httpd.pid' + else + '/var/run/httpd2.pid' + end + default['apache']['lib_dir'] = node['kernel']['machine'] =~ /^i[36]86$/ ? '/usr/lib/apache2' : '/usr/lib64/apache2' + default['apache']['libexec_dir'] = node['apache']['lib_dir'] +when 'debian', 'ubuntu' + default['apache']['package'] = 'apache2' + default['apache']['perl_pkg'] = 'perl' + default['apache']['devel_package'] = + if node['apache']['mpm'] == 'prefork' + 'apache2-prefork-dev' + else + 'apache2-dev' + end + default['apache']['apachectl'] = '/usr/sbin/apache2ctl' + default['apache']['dir'] = '/etc/apache2' + default['apache']['log_dir'] = '/var/log/apache2' + default['apache']['error_log'] = 'error.log' + default['apache']['access_log'] = 'access.log' + default['apache']['user'] = 'www-data' + default['apache']['group'] = 'www-data' + default['apache']['binary'] = '/usr/sbin/apache2' + default['apache']['conf_dir'] = '/etc/apache2' + default['apache']['cgibin_dir'] = '/usr/lib/cgi-bin' + default['apache']['icondir'] = '/usr/share/apache2/icons' + default['apache']['cache_dir'] = '/var/cache/apache2' + default['apache']['run_dir'] = '/var/run/apache2' + default['apache']['lock_dir'] = '/var/lock/apache2' + # this should use COOK-3917 to educate the initscript of the pid location + if node['apache']['version'] == '2.4' + default['apache']['pid_file'] = '/var/run/apache2/apache2.pid' + default['apache']['docroot_dir'] = '/var/www/html' + else + default['apache']['pid_file'] = '/var/run/apache2.pid' + default['apache']['docroot_dir'] = '/var/www' + end + default['apache']['lib_dir'] = '/usr/lib/apache2' + default['apache']['build_dir'] = '/usr/share/apache2' + default['apache']['libexec_dir'] = "#{node['apache']['lib_dir']}/modules" + default['apache']['default_site_name'] = '000-default' +when 'arch' + default['apache']['package'] = 'apache' + default['apache']['service_name'] = 'httpd' + default['apache']['perl_pkg'] = 'perl' + # default['apache']['apachectl'] = '/usr/sbin/apachectl' + default['apache']['dir'] = '/etc/httpd' + default['apache']['log_dir'] = '/var/log/httpd' + default['apache']['error_log'] = 'error.log' + default['apache']['access_log'] = 'access.log' + default['apache']['user'] = 'http' + default['apache']['group'] = 'http' + default['apache']['binary'] = '/usr/sbin/httpd' + default['apache']['conf_dir'] = '/etc/httpd' + default['apache']['docroot_dir'] = '/srv/http' + default['apache']['cgibin_dir'] = '/usr/share/httpd/cgi-bin' + default['apache']['icondir'] = '/usr/share/httpd/icons' + default['apache']['cache_dir'] = '/var/cache/httpd' + default['apache']['run_dir'] = '/var/run/httpd' + default['apache']['lock_dir'] = '/var/run/httpd' + default['apache']['pid_file'] = '/var/run/httpd/httpd.pid' + default['apache']['lib_dir'] = '/usr/lib/httpd' + default['apache']['libexec_dir'] = "#{node['apache']['lib_dir']}/modules" +when 'freebsd' + default['apache']['package'] = 'apache24' + default['apache']['dir'] = '/usr/local/etc/apache24' + default['apache']['conf_dir'] = '/usr/local/etc/apache24' + default['apache']['docroot_dir'] = '/usr/local/www/apache24/data' + default['apache']['cgibin_dir'] = '/usr/local/www/apache24/cgi-bin' + default['apache']['icondir'] = '/usr/local/www/apache24/icons' + default['apache']['cache_dir'] = '/var/cache/apache24' + default['apache']['run_dir'] = '/var/run' + default['apache']['lock_dir'] = '/var/run' + default['apache']['lib_dir'] = '/usr/local/libexec/apache24' + default['apache']['devel_package'] = 'httpd-devel' + default['apache']['perl_pkg'] = 'perl5' + default['apache']['apachectl'] = '/usr/local/sbin/apachectl' + default['apache']['pid_file'] = '/var/run/httpd.pid' + default['apache']['log_dir'] = '/var/log' + default['apache']['error_log'] = 'httpd-error.log' + default['apache']['access_log'] = 'httpd-access.log' + default['apache']['root_group'] = 'wheel' + default['apache']['user'] = 'www' + default['apache']['group'] = 'www' + default['apache']['binary'] = '/usr/local/sbin/httpd' + default['apache']['libexec_dir'] = node['apache']['lib_dir'] +else + default['apache']['package'] = 'apache2' + default['apache']['devel_package'] = 'apache2-dev' + default['apache']['perl_pkg'] = 'perl' + default['apache']['dir'] = '/etc/apache2' + default['apache']['log_dir'] = '/var/log/apache2' + default['apache']['error_log'] = 'error.log' + default['apache']['access_log'] = 'access.log' + default['apache']['user'] = 'www-data' + default['apache']['group'] = 'www-data' + default['apache']['binary'] = '/usr/sbin/apache2' + default['apache']['conf_dir'] = '/etc/apache2' + default['apache']['docroot_dir'] = '/var/www' + default['apache']['cgibin_dir'] = '/usr/lib/cgi-bin' + default['apache']['icondir'] = '/usr/share/apache2/icons' + default['apache']['cache_dir'] = '/var/cache/apache2' + default['apache']['run_dir'] = 'logs' + default['apache']['lock_dir'] = 'logs' + default['apache']['pid_file'] = 'logs/httpd.pid' + default['apache']['lib_dir'] = '/usr/lib/apache2' + default['apache']['libexec_dir'] = "#{node['apache']['lib_dir']}/modules" +end + +### +# These settings need the unless, since we want them to be tunable, +# and we don't want to override the tunings. +### + +# General settings +if node['apache']['service_name'].nil? + default['apache']['service_name'] = node['apache']['package'] +end +default['apache']['listen'] = ['*:80'] +default['apache']['contact'] = 'ops@example.com' +default['apache']['timeout'] = 300 +default['apache']['keepalive'] = 'On' +default['apache']['keepaliverequests'] = 100 +default['apache']['keepalivetimeout'] = 5 +default['apache']['locale'] = 'C' +default['apache']['sysconfig_additional_params'] = {} +default['apache']['default_site_enabled'] = false +default['apache']['default_site_port'] = '80' +default['apache']['access_file_name'] = '.htaccess' +default['apache']['default_release'] = nil +default['apache']['log_level'] = 'warn' + +# Security +default['apache']['servertokens'] = 'Prod' +default['apache']['serversignature'] = 'On' +default['apache']['traceenable'] = 'Off' + +# mod_status Allow list, space seprated list of allowed entries. +default['apache']['status_allow_list'] = '127.0.0.1 ::1' + +# mod_status ExtendedStatus, set to 'true' to enable +default['apache']['ext_status'] = false + +# mod_info Allow list, space seprated list of allowed entries. +default['apache']['info_allow_list'] = '127.0.0.1 ::1' + +# Supported mpm list +default['apache']['mpm_support'] = %w(prefork worker event) + +# Prefork Attributes +default['apache']['prefork']['startservers'] = 16 +default['apache']['prefork']['minspareservers'] = 16 +default['apache']['prefork']['maxspareservers'] = 32 +default['apache']['prefork']['serverlimit'] = 256 +default['apache']['prefork']['maxrequestworkers'] = 256 +default['apache']['prefork']['maxconnectionsperchild'] = 10_000 + +# Worker Attributes +default['apache']['worker']['startservers'] = 4 +default['apache']['worker']['serverlimit'] = 16 +default['apache']['worker']['minsparethreads'] = 64 +default['apache']['worker']['maxsparethreads'] = 192 +default['apache']['worker']['threadlimit'] = 192 +default['apache']['worker']['threadsperchild'] = 64 +default['apache']['worker']['maxrequestworkers'] = 1024 +default['apache']['worker']['maxconnectionsperchild'] = 0 + +# Event Attributes +default['apache']['event']['startservers'] = 4 +default['apache']['event']['serverlimit'] = 16 +default['apache']['event']['minsparethreads'] = 64 +default['apache']['event']['maxsparethreads'] = 192 +default['apache']['event']['threadlimit'] = 192 +default['apache']['event']['threadsperchild'] = 64 +default['apache']['event']['maxrequestworkers'] = 1024 +default['apache']['event']['maxconnectionsperchild'] = 0 + +# mod_proxy settings +default['apache']['proxy']['require'] = 'all denied' +default['apache']['proxy']['order'] = 'deny,allow' +default['apache']['proxy']['deny_from'] = 'all' +default['apache']['proxy']['allow_from'] = 'none' + +# Default modules to enable via include_recipe +default['apache']['default_modules'] = %w( + status alias auth_basic authn_core authn_file authz_core authz_groupfile + authz_host authz_user autoindex deflate dir env mime negotiation setenvif +) + +%w(log_config logio).each do |log_mod| + default['apache']['default_modules'] << log_mod if %w(rhel amazon fedora suse arch freebsd).include?(node['platform_family']) +end + +if node['apache']['version'] == '2.4' + %w(unixd).each do |unix_mod| + default['apache']['default_modules'] << unix_mod if %w(rhel amazon fedora suse arch freebsd).include?(node['platform_family']) + end + + unless node['platform'] == 'amazon' + default['apache']['default_modules'] << 'systemd' if %w(rhel fedora amazon).include?(node['platform_family']) + end +end diff --git a/cookbooks/apache2/attributes/mod_auth_cas.rb b/cookbooks/apache2/attributes/mod_auth_cas.rb new file mode 100644 index 0000000..4684859 --- /dev/null +++ b/cookbooks/apache2/attributes/mod_auth_cas.rb @@ -0,0 +1,21 @@ +# +# Cookbook:: apache2 +# Attributes:: mod_auth_cas +# +# Copyright:: 2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +default['apache']['mod_auth_cas']['from_source'] = false +default['apache']['mod_auth_cas']['source_revision'] = 'v1.0.9.1' diff --git a/cookbooks/apache2/attributes/mod_auth_openid.rb b/cookbooks/apache2/attributes/mod_auth_openid.rb new file mode 100644 index 0000000..a3812be --- /dev/null +++ b/cookbooks/apache2/attributes/mod_auth_openid.rb @@ -0,0 +1,38 @@ +# +# Cookbook:: apache2 +# Attributes:: mod_auth_openid +# +# Copyright:: 2013, Chef Software, Inc. +# Copyright:: 2014-2016, Alexander van Zoest +# +# 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. +# + +# mod_auth_openids +default['apache']['allowed_openids'] = [] +default['apache']['mod_auth_openid']['ref'] = 'v0.8' +default['apache']['mod_auth_openid']['version'] = '0.8' +default['apache']['mod_auth_openid']['source_url'] = "https://github.com/bmuller/mod_auth_openid/archive/#{node['apache']['mod_auth_openid']['ref']}.tar.gz" +default['apache']['mod_auth_openid']['cache_dir'] = '/var/cache/mod_auth_openid' +default['apache']['mod_auth_openid']['dblocation'] = "#{node['apache']['mod_auth_openid']['cache_dir']}/mod_auth_openid.db" + +default['apache']['mod_auth_openid']['configure_flags'] = + case node['platform_family'] + when 'freebsd' + [ + 'CPPFLAGS=-I/usr/local/include', + 'LDFLAGS=-I/usr/local/lib -lsqlite3', + ] + else + [] + end diff --git a/cookbooks/apache2/attributes/mod_fastcgi.rb b/cookbooks/apache2/attributes/mod_fastcgi.rb new file mode 100644 index 0000000..b8059ca --- /dev/null +++ b/cookbooks/apache2/attributes/mod_fastcgi.rb @@ -0,0 +1,39 @@ +# +# Cookbook:: apache2 +# Attributes:: mod_fastcgi +# +# Copyright:: 2013, Chef Software, Inc. +# Copyright:: 2016, Alexander van Zoest +# +# 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. +# + +default['apache']['mod_fastcgi']['download_url'] = 'http://www.fastcgi.com/dist/mod_fastcgi-current.tar.gz' +default['apache']['mod_fastcgi']['install_method'] = 'package' +default['apache']['mod_fastcgi']['package'] = + case node['platform_family'] + when 'debian' + 'libapache2-mod-fastcgi' + when 'amazon' + 'mod_fastcgi' + when 'rhel' + 'mod_fastcgi' + when 'freebsd' + if node['apache']['version'] == '2.4' + 'ap24-mod_fastcgi' + else + 'ap22-mod_fastcgi' + end + else + 'mod_fastcgi' + end diff --git a/cookbooks/apache2/attributes/mod_pagespeed.rb b/cookbooks/apache2/attributes/mod_pagespeed.rb new file mode 100644 index 0000000..db0f968 --- /dev/null +++ b/cookbooks/apache2/attributes/mod_pagespeed.rb @@ -0,0 +1,25 @@ +# +# Cookbook:: apache2 +# Attributes:: mod_pagespeed +# +# Copyright:: 2013, ZOZI +# +# 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. +# + +default['apache2']['mod_pagespeed']['package_link'] = + if node['kernel']['machine'] =~ /^i[36']86$/ + 'https://dl-ssl.google.com/dl/linux/direct/mod-pagespeed-stable_current_i386.deb' + else + 'https://dl-ssl.google.com/dl/linux/direct/mod-pagespeed-stable_current_amd64.deb' + end diff --git a/cookbooks/apache2/attributes/mod_php.rb b/cookbooks/apache2/attributes/mod_php.rb new file mode 100644 index 0000000..6bfbf2f --- /dev/null +++ b/cookbooks/apache2/attributes/mod_php.rb @@ -0,0 +1,34 @@ +# +# Cookbook:: apache2 +# Attributes:: mod_php5 +# +# Copyright:: 2014, Viverae, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +default['apache']['mod_php']['install_method'] = 'package' +default['apache']['mod_php']['module_name'] = 'php5' +default['apache']['mod_php']['so_filename'] = 'libphp5.so' +default['apache']['mod_php']['so_filename'] = 'mod_php5.so' if node['platform_family'] == 'suse' + +if node['platform'] == 'ubuntu' && node['platform_version'].to_f >= 16.04 + default['apache']['mod_php']['module_name'] = 'php7' + default['apache']['mod_php']['so_filename'] = 'libphp7.0.so' +end +if node['platform'] == 'debian' && node['platform_version'].to_f >= 9 + default['apache']['mod_php']['module_name'] = 'php7' + default['apache']['mod_php']['so_filename'] = 'libphp7.0.so' +end +if node['platform'] == 'amazon' && node['apache']['version'] == '2.4' + default['apache']['mod_php']['so_filename'] = 'libphp.so' +end diff --git a/cookbooks/apache2/attributes/mod_ssl.rb b/cookbooks/apache2/attributes/mod_ssl.rb new file mode 100644 index 0000000..86ab29c --- /dev/null +++ b/cookbooks/apache2/attributes/mod_ssl.rb @@ -0,0 +1,63 @@ +# +# Cookbook:: apache2 +# Attributes:: mod_ssl +# +# Copyright:: 2012-2013, Chef Software, Inc. +# Copyright:: 2014, Viverae, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +default['apache']['mod_ssl']['port'] = 443 +default['apache']['mod_ssl']['protocol'] = 'All -SSLv2 -SSLv3' +default['apache']['mod_ssl']['cipher_suite'] = 'EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA256:EECDH:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!IDEA:!ECDSA:kEDH:CAMELLIA128-SHA:AES128-SHA' +default['apache']['mod_ssl']['honor_cipher_order'] = 'On' +default['apache']['mod_ssl']['insecure_renegotiation'] = 'Off' +default['apache']['mod_ssl']['strict_sni_vhost_check'] = 'Off' +default['apache']['mod_ssl']['session_cache'] = 'shmcb:/var/run/apache2/ssl_scache' +default['apache']['mod_ssl']['session_cache_timeout'] = 300 +default['apache']['mod_ssl']['compression'] = 'Off' +default['apache']['mod_ssl']['use_stapling'] = 'Off' +default['apache']['mod_ssl']['stapling_responder_timeout'] = 5 +default['apache']['mod_ssl']['stapling_return_responder_errors'] = 'Off' +default['apache']['mod_ssl']['stapling_cache'] = 'shmcb:/var/run/ocsp(128000)' +default['apache']['mod_ssl']['pass_phrase_dialog'] = 'builtin' +default['apache']['mod_ssl']['mutex'] = 'file:/var/run/apache2/ssl_mutex' +default['apache']['mod_ssl']['directives'] = {} +default['apache']['mod_ssl']['pkg_name'] = 'mod_ssl' + +case node['platform_family'] +when 'debian' + case node['platform'] + when 'ubuntu' + if node['apache']['version'] == '2.4' + default['apache']['mod_ssl']['pass_phrase_dialog'] = 'exec:/usr/share/apache2/ask-for-passphrase' + end + end +when 'freebsd' + default['apache']['mod_ssl']['session_cache'] = 'shmcb:/var/run/ssl_scache(512000)' + default['apache']['mod_ssl']['mutex'] = 'file:/var/run/ssl_mutex' +when 'amazon' + if node['apache']['version'] == '2.4' + default['apache']['mod_ssl']['pkg_name'] = 'mod24_ssl' + end +when 'rhel', 'fedora', 'suse' + case node['platform'] + when 'amazon' + if node['apache']['version'] == '2.4' + default['apache']['mod_ssl']['pkg_name'] = 'mod24_ssl' + end + end + default['apache']['mod_ssl']['session_cache'] = 'shmcb:/var/cache/mod_ssl/scache(512000)' + default['apache']['mod_ssl']['mutex'] = 'default' +end diff --git a/cookbooks/apache2/definitions/apache_conf.rb b/cookbooks/apache2/definitions/apache_conf.rb new file mode 100644 index 0000000..7bbe948 --- /dev/null +++ b/cookbooks/apache2/definitions/apache_conf.rb @@ -0,0 +1,45 @@ +# +# Cookbook:: apache2 +# Definition:: apache_conf +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +define :apache_conf, enable: true do + include_recipe 'apache2::default' + + conf_name = "#{params[:name]}.conf" + params[:conf_path] = params[:conf_path] || "#{node['apache']['dir']}/conf-available" + + file "#{params[:conf_path]}/#{params[:name]}" do + action :delete + end + + template "#{params[:conf_path]}/#{conf_name}" do + source params[:source] || "#{conf_name}.erb" + cookbook params[:cookbook] if params[:cookbook] + owner 'root' + group node['apache']['root_group'] + backup false + mode '0644' + notifies :restart, 'service[apache2]', :delayed + end + + if params[:enable] + apache_config params[:name] do + enable true + end + end +end diff --git a/cookbooks/apache2/definitions/apache_config.rb b/cookbooks/apache2/definitions/apache_config.rb new file mode 100644 index 0000000..ffac01d --- /dev/null +++ b/cookbooks/apache2/definitions/apache_config.rb @@ -0,0 +1,42 @@ +# +# Cookbook:: apache2 +# Definition:: apache_config +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +define :apache_config, enable: true do + include_recipe 'apache2::default' + + conf_name = "#{params[:name]}.conf" + params[:conf_path] = params[:conf_path] || "#{node['apache']['dir']}/conf-available" + + if params[:enable] + execute "a2enconf #{conf_name}" do + command "/usr/sbin/a2enconf #{conf_name}" + notifies :restart, 'service[apache2]', :delayed + not_if do + ::File.symlink?("#{node['apache']['dir']}/conf-enabled/#{conf_name}") && + (::File.exist?(params[:conf_path]) ? ::File.symlink?("#{node['apache']['dir']}/conf-enabled/#{conf_name}") : true) + end + end + else + execute "a2disconf #{conf_name}" do + command "/usr/sbin/a2disconf #{conf_name}" + notifies :reload, 'service[apache2]', :delayed + only_if { ::File.symlink?("#{node['apache']['dir']}/conf-enabled/#{conf_name}") } + end + end +end diff --git a/cookbooks/apache2/definitions/apache_mod.rb b/cookbooks/apache2/definitions/apache_mod.rb new file mode 100644 index 0000000..b1f8275 --- /dev/null +++ b/cookbooks/apache2/definitions/apache_mod.rb @@ -0,0 +1,28 @@ +# +# Cookbook:: apache2 +# Definition:: apache_mod +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +define :apache_mod do + include_recipe 'apache2::default' + + template "#{node['apache']['dir']}/mods-available/#{params[:name]}.conf" do + source "mods/#{params[:name]}.conf.erb" + mode '0644' + notifies :reload, 'service[apache2]', :delayed + end +end diff --git a/cookbooks/apache2/definitions/apache_module.rb b/cookbooks/apache2/definitions/apache_module.rb new file mode 100644 index 0000000..04ae665 --- /dev/null +++ b/cookbooks/apache2/definitions/apache_module.rb @@ -0,0 +1,58 @@ +# +# Cookbook:: apache2 +# Definition:: apache_module +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +define :apache_module, enable: true, conf: false, restart: false do + include_recipe 'apache2::default' + + params[:filename] = params[:filename] || "mod_#{params[:name]}.so" + params[:module_path] = params[:module_path] || "#{node['apache']['libexec_dir']}/#{params[:filename]}" + params[:identifier] = params[:identifier] || "#{params[:name]}_module" + + apache_mod params[:name] if params[:conf] + + file "#{node['apache']['dir']}/mods-available/#{params[:name]}.load" do + content "LoadModule #{params[:identifier]} #{params[:module_path]}\n" + mode '0644' + end + + if params[:enable] + execute "a2enmod #{params[:name]}" do + command "/usr/sbin/a2enmod #{params[:name]}" + if params[:restart] + notifies :restart, 'service[apache2]', :delayed + else + notifies :reload, 'service[apache2]', :delayed + end + not_if do + ::File.symlink?("#{node['apache']['dir']}/mods-enabled/#{params[:name]}.load") && + (::File.exist?("#{node['apache']['dir']}/mods-available/#{params[:name]}.conf") ? ::File.symlink?("#{node['apache']['dir']}/mods-enabled/#{params[:name]}.conf") : true) + end + end + else + execute "a2dismod #{params[:name]}" do + command "/usr/sbin/a2dismod #{params[:name]}" + if params[:restart] + notifies :restart, 'service[apache2]', :delayed + else + notifies :reload, 'service[apache2]', :delayed + end + only_if { ::File.symlink?("#{node['apache']['dir']}/mods-enabled/#{params[:name]}.load") } + end + end +end diff --git a/cookbooks/apache2/definitions/apache_site.rb b/cookbooks/apache2/definitions/apache_site.rb new file mode 100644 index 0000000..8524a99 --- /dev/null +++ b/cookbooks/apache2/definitions/apache_site.rb @@ -0,0 +1,44 @@ +# +# Cookbook:: apache2 +# Definition:: apache_site +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +define :apache_site, enable: true do + include_recipe 'apache2::default' + conf_name = "#{params[:name]}.conf" + + if params[:enable] + execute "a2ensite #{conf_name}" do + command "/usr/sbin/a2ensite #{conf_name}" + notifies :reload, 'service[apache2]', :delayed + not_if do + ::File.symlink?("#{node['apache']['dir']}/sites-enabled/#{conf_name}") || + ::File.symlink?("#{node['apache']['dir']}/sites-enabled/000-#{conf_name}") + end + only_if { ::File.exist?("#{node['apache']['dir']}/sites-available/#{conf_name}") } + end + else + execute "a2dissite #{conf_name}" do + command "/usr/sbin/a2dissite #{conf_name}" + notifies :reload, 'service[apache2]', :delayed + only_if do + ::File.symlink?("#{node['apache']['dir']}/sites-enabled/#{conf_name}") || + ::File.symlink?("#{node['apache']['dir']}/sites-enabled/000-#{conf_name}") + end + end + end +end diff --git a/cookbooks/apache2/definitions/web_app.rb b/cookbooks/apache2/definitions/web_app.rb new file mode 100644 index 0000000..c9784c0 --- /dev/null +++ b/cookbooks/apache2/definitions/web_app.rb @@ -0,0 +1,48 @@ +# +# Cookbook:: apache2 +# Definition:: web_app +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +define :web_app, template: 'web_app.conf.erb', local: false, enable: true, server_port: 80 do + application_name = params[:name] + + include_recipe 'apache2::default' + include_recipe 'apache2::mod_rewrite' + include_recipe 'apache2::mod_deflate' + include_recipe 'apache2::mod_headers' + + template "#{node['apache']['dir']}/sites-available/#{application_name}.conf" do + source params[:template] + local params[:local] + owner 'root' + group node['apache']['root_group'] + mode '0644' + cookbook params[:cookbook] if params[:cookbook] + variables( + application_name: application_name, + params: params + ) + if ::File.exist?("#{node['apache']['dir']}/sites-enabled/#{application_name}.conf") + notifies :reload, 'service[apache2]', :delayed + end + end + + site_enabled = params[:enable] + apache_site params[:name] do + enable site_enabled + end +end diff --git a/cookbooks/apache2/files/default/apache2_module_conf_generate.pl b/cookbooks/apache2/files/default/apache2_module_conf_generate.pl new file mode 100644 index 0000000..e161fbb --- /dev/null +++ b/cookbooks/apache2/files/default/apache2_module_conf_generate.pl @@ -0,0 +1,41 @@ +#!/usr/bin/perl + +=begin + +Generates Ubuntu style module.load files. + +./apache2_module_conf_generate.pl /usr/lib64/httpd/modules /etc/httpd/mods-available + +ARGV[0] is the apache modules directory, ARGV[1] is where you want 'em. + +=cut + +use File::Find; + +use strict; +use warnings; + +die "Must have '/path/to/modules' and '/path/to/modules.load'" + unless $ARGV[0] && $ARGV[1]; + +find( + { + wanted => sub { + return 1 if $File::Find::name !~ /\.so$/; + my $modfile = $_; + $modfile =~ /(lib|mod_)(.+)\.so$/; + my $modname = $2; + my $filename = "$ARGV[1]/$modname.load"; + unless ( -f $filename ) { + open( FILE, ">", $filename ) or die "Cannot open $filename"; + print FILE "LoadModule " . $modname . "_module $File::Find::name\n"; + close(FILE); + } + }, + follow => 1, + }, + $ARGV[0] +); + +exit 0; + diff --git a/cookbooks/apache2/libraries/listen.rb b/cookbooks/apache2/libraries/listen.rb new file mode 100644 index 0000000..1c12192 --- /dev/null +++ b/cookbooks/apache2/libraries/listen.rb @@ -0,0 +1,45 @@ +# encoding: utf-8 +# +# Cookbook:: apache2 +# Libraries:: listen +# +# Copyright:: 2015, Ontario Systems, LLC +# +# 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. +# +module Apache2 + # Provides method to convert node['apache']['listen_ports'] and node['apache']['listen_addresses'] into new node['apache']['listen'] + module Listen + # @param node [Chef::Node] the chef node + # @return [Hash] a hash indexed by address where the values are arrays of ports to listen to + def merge_listen_attributes(node) + (Apache2::Listen.converted_listen_ports_and_addresses(node) + node['apache']['listen']).uniq + end + + module_function :merge_listen_attributes + + private_class_method + + def self.converted_listen_ports_and_addresses(node) + return [] unless node['apache']['listen_ports'] || node['apache']['listen_addresses'] + Chef::Log.warn "node['apache']['listen_ports'] and node['apache']['listen_addresses'] are deprecated in favor of node['apache']['listen']. Please adjust your cookbooks" + + # Defaults to * for addresses or 80 / 443 for ports if not specified + (node['apache']['listen_addresses'] || %w(*)).uniq.each_with_object([]) do |address, listen| + (node['apache']['listen_ports'] || %w(80 443)).uniq.each do |port| + listen << "#{address}:#{port}" + end + end + end + end +end diff --git a/cookbooks/apache2/metadata.json b/cookbooks/apache2/metadata.json new file mode 100644 index 0000000..e5fb366 --- /dev/null +++ b/cookbooks/apache2/metadata.json @@ -0,0 +1 @@ +{"name":"apache2","version":"3.3.0","description":"Installs and configures all aspects of apache2 using Debian style symlinks with helper definitions","long_description":"apache2 Cookbook\n================\n[![Cookbook Version](https://img.shields.io/cookbook/v/apache2.svg?style=flat)](https://supermarket.chef.io/cookbooks/apache2)\n[![Build Status](https://travis-ci.org/sous-chefs/apache2.svg?branch=master)](https://travis-ci.org/sous-chefs/apache2)\n[![Dependency Status](http://img.shields.io/gemnasium/sous-chefs/apache2.svg?style=flat)](https://gemnasium.com/sous-chefs/apache2)\n[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)\n\nThis cookbook provides a complete Debian/Ubuntu style Apache HTTPD\nconfiguration. Non-Debian based distributions such as Red Hat/CentOS,\nArchLinux and others supported by this cookbook will have a\nconfiguration that mimics Debian/Ubuntu style as it is easier to\nmanage with Chef.\n\nDebian-style Apache configuration uses scripts to manage modules and\nsites (vhosts). The scripts are:\n\n* a2ensite\n* a2dissite\n* a2enmod\n* a2dismod\n* a2enconf\n* a2disconf\n\nThis cookbook ships with templates of these scripts for non\nDebian/Ubuntu platforms. The scripts are used in the __Definitions__\nbelow.\n\n## Cookbooks:\n\nThis cookbook has no direct external dependencies.\n\nDepending on your OS configuration and security policy, you may need\nadditional recipes or cookbooks for this cookbook's recipes to\nconverge on the node. In particular, the following Operating System\nsettings may affect the behavior of this cookbook:\n\n* apt cache outdated\n* SELinux enabled\n* firewalls (such as iptables, ufw, etc.)\n* Compile tools\n* 3rd party repositories\n\nOn Ubuntu/Debian, use [apt](https://supermarket.chef.io/cookbooks/apt) cookbook to ensure the package\ncache is updated so Chef can install packages, or consider putting\napt-get in your bootstrap process or\n[knife bootstrap template](http://docs.chef.io/knife_bootstrap.html)\n\nOn RHEL, SELinux is enabled by default. The [selinux](https://supermarket.chef.io/cookbooks/selinux) cookbook\ncontains a `permissive` recipe that can be used to set SELinux to\n\"Permissive\" state. Otherwise, additional recipes need to be created\nby the user to address SELinux permissions.\n\n\nTo deal with firewalls Chef Software does provide an [iptables](https://supermarket.chef.io/cookbooks/iptables) and [ufw](https://supermarket.chef.io/cookbooks/ufw) cookbook but is migrating from the approach used there to a more robust solution\nutilizing the general [firewall](https://supermarket.chef.io/cookbooks/firewall) cookbook to setup rules.\nSee those cookbooks' READMEs for documentation.\n\nBuild/compile tools may not be installed on the system by default.\nSome recipes (e.g., `apache2::mod_auth_openid`) build the module from\nsource. Use the [build-essential](https://supermarket.chef.io/cookbooks/build-essential) cookbook to get essential\nbuild packages installed.\n\nOn ArchLinux, if you are using the `apache2::mod_auth_openid` recipe,\nyou also need the [pacman](https://supermarket.chef.io/cookbooks/pacman) cookbook for the `pacman_aur` LWRP. Put\n`recipe[pacman]` on the node's expanded run list (on the node or in a\nrole). This is not an explicit dependency because it is only required\nfor this single recipe and platform; the pacman default recipe\nperforms `pacman -Sy` to keep pacman's package cache updated.\n\n## Platforms:\n\nThe following platforms and versions are tested and supported using\n[test-kitchen](http://kitchen.ci/)\n\n* Ubuntu 14.04\n* Ubuntu 16.04\n* Debian 8.6\n* CentOS 7.3\n* Fedora 25\n\nThe following platform families are supported in the code, and are\nassumed to work based on the successful testing on Ubuntu and CentOS.\n\n* Red Hat (rhel)\n\nThe following platforms are also supported in the code, have been\ntested manually but are not regularly tested under test-kitchen.\n\n* Amazon Linux\n* SUSE/OpenSUSE\n* ArchLinux\n* FreeBSD\n\n### Notes for RHEL Family:\n\nOn Red Hat Enterprise Linux and derivatives, the EPEL repository may\nbe necessary to install packages used in certain recipes. The\n`apache2::default` recipe, however, does not require any additional\nrepositories. The [yum-epel](https://supermarket.chef.io/cookbooks/yum-epel) cookbook can be used to add the\nEPEL repository. See __Examples__ for more information.\n\nUsage\n=====\n\nUsing this cookbook is relatively straightforward. It is recommended to create\na project or organization specific [wrapper cookbook](https://www.chef.io/blog/2013/12/03/doing-wrapper-cookbooks-right/)\nand add the desired recipes to the run list of a node, or create a role. Depending on your\nenvironment, you may have multiple roles that use different recipes\nfrom this cookbook. Adjust any attributes as desired. For example, to\ncreate a basic role for web servers that provide both HTTP and HTTPS:\n\n```ruby\n % cat roles/webserver.rb\n name \"webserver\"\n description \"Systems that serve HTTP and HTTPS\"\n run_list(\n \"recipe[apache2]\",\n \"recipe[apache2::mod_ssl]\"\n )\n default_attributes(\n \"apache\" => {\n \"listen\" => [\"*:80\", \"*:443\"]\n }\n )\n```\n\nFor examples of using the definitions in your own recipes, see their\nrespective sections below.\n\n\nAttributes\n==========\n\nThis cookbook uses many attributes, broken up into a few different\nkinds.\n\nPlatform specific\n-----------------\n\nIn order to support the broadest number of platforms, several\nattributes are determined based on the node's platform. See the\nattributes/default.rb file for default values in the case statement at\nthe top of the file.\n\n* `node['apache']['package']` - Package name for Apache2\n* `node['apache']['perl_pkg']` - Package name for Perl\n* `node['apache']['dir']` - Location for the Apache configuration\n* `node['apache']['log_dir']` - Location for Apache logs\n* `node['apache']['error_log']` - Location for the default error log\n* `node['apache']['access_log']` - Location for the default access log\n* `node['apache']['user']` - User Apache runs as\n* `node['apache']['group']` - Group Apache runs as\n* `node['apache']['binary']` - Apache httpd server daemon\n* `node['apache']['conf_dir']` - Location for the main config file (e.g apache2.conf or httpd.conf)\n* `node['apache']['docroot_dir']` - Location for docroot\n* `node['apache']['cgibin_dir']` - Location for cgi-bin\n* `node['apache']['icondir']` - Location for icons\n* `node['apache']['cache_dir']` - Location for cached files used by Apache itself or recipes\n* `node['apache']['pid_file']` - Location of the PID file for Apache httpd\n* `node['apache']['lib_dir']` - Location for shared libraries\n* `node['apache']['default_site_enabled']` - Default site enabled. Default is false.\n* `node['apache']['ext_status']` - if true, enables ExtendedStatus for `mod_status`\n* `node['apache']['locale']` - Locale to set in sysconfig or envvars and used for subprocesses and modules (like mod_dav and mod_wsgi). On debian systems Uses system-local if set to 'system', defaults to 'C'.\n\nGeneral settings\n----------------\n\nThese are general settings used in recipes and templates. Default\nvalues are noted.\n\n* `node['apache']['version']` - Specifing 2.4 triggers apache 2.4 support. If the platform is known during our test to install 2.4 by default, it will be set to 2.4 for you. Otherwise it falls back to 2.2. This value should be specified as a string.\n* `node['apache']['listen']` - Array of address:port combinations that httpd should listen on. Default is any address and port 80 (`[\"*:80\"]`).\n* `node['apache']['contact']` - Value for ServerAdmin directive. Default \"ops@example.com\".\n* `node['apache']['timeout']` - Value for the Timeout directive. Default is 300.\n* `node['apache']['keepalive']` - Value for the KeepAlive directive. Default is On.\n* `node['apache']['keepaliverequests']` - Value for MaxKeepAliveRequests. Default is 100.\n* `node['apache']['keepalivetimeout']` - Value for the KeepAliveTimeout directive. Default is 5.\n* `node['apache']['sysconfig_additional_params']` - Additionals variables set in sysconfig file. Default is empty.\n* `node['apache']['log_level']` - Value for LogLevel directive. Default is 'warn'.\n* `node['apache']['default_modules']` - Array of module names. Can take \"mod_FOO\" or \"FOO\" as names, where FOO is the apache module, e.g. \"`mod_status`\" or \"`status`\".\n* `node['apache']['mpm']` - With apache.version 2.4, specifies what Multi-Processing Module to enable. Defaults to platform default, otherwise it is \"prefork\"\n\nThe modules listed in `default_modules` will be included as recipes in `recipe[apache::default]`.\n\nPrefork attributes\n------------------\n\nPrefork attributes are used for tuning the Apache HTTPD [prefork MPM](http://httpd.apache.org/docs/current/mod/prefork.html) configuration.\n\n* `node['apache']['prefork']['startservers']` - initial number of server processes to start. Default is 16.\n* `node['apache']['prefork']['minspareservers']` - minimum number of spare server processes. Default 16.\n* `node['apache']['prefork']['maxspareservers']` - maximum number of spare server processes. Default 32.\n* `node['apache']['prefork']['serverlimit']` - upper limit on configurable server processes. Default 256.\n* `node['apache']['prefork']['maxrequestworkers']` - Maximum number of connections that will be processed simultaneously. Default 256.\n* `node['apache']['prefork']['maxconnectionsperchild']` - Maximum number of request a child process will handle. Default 10000.\n\nWorker attributes\n-----------------\n\nWorker attributes are used for tuning the Apache HTTPD [worker MPM](http://httpd.apache.org/docs/current/mod/worker.html)\nconfiguration.\n\n* `node['apache']['worker']['startservers']` - Initial number of server processes to start. Default 4\n* `node['apache']['worker']['serverlimit']` - Upper limit on configurable server processes. Default 16.\n* `node['apache']['worker']['minsparethreads']` - Minimum number of spare worker threads. Default 64\n* `node['apache']['worker']['maxsparethreads']` - Maximum number of spare worker threads. Default 192.\n* `node['apache']['worker']['maxrequestworkers']` - Maximum number of simultaneous connections. Default 1024.\n* `node['apache']['worker']['maxconnectionsperchild']` - Limit on the number of connections that an individual child server will handle during its life.\n\nEvent attributes\n----------------\n\nEvent attributes are used for tuning the Apache HTTPD [event MPM](http://httpd.apache.org/docs/current/mod/event.html)\nconfiguration.\n\n* `node['apache']['event']['startservers']` - Initial number of child server processes created at startup. Default 4.\n* `node['apache']['event']['serverlimit']` - Upper limit on configurable number of processes. Default 16.\n* `node['apache']['event']['minsparethreads']` - Minimum number of spare worker threads. Default 64\n* `node['apache']['event']['maxsparethreads']` - Maximum number of spare worker threads. Default 192.\n* `node['apache']['event']['threadlimit']` - Upper limit on the configurable number of threads per child process. Default 192.\n* `node['apache']['event']['threadsperchild']` - Number of threads created by each child process. Default 64.\n* `node['apache']['event']['maxrequestworkers']` - Maximum number of connections that will be processed simultaneously.\n* `node['apache']['event']['maxconnectionsperchild']` - Limit on the number of connections that an individual child server will handle during its life.\n\nOther/Unsupported MPM\n---------------------\n\nTo use the cookbook with an unsupported mpm (other than prefork, event or worker):\n\n* set `node['apache']['mpm']` to the name of the module (e.g. `itk`)\n* in your cookbook, after `include_recipe 'apache2'` use the `apache_module` definition to enable/disable the required module(s)\n\nModule specific attributes\n--------------------------\n\nSome module recipes have their own attributes that can be used to alter and modify the behavior of this cookbook. Please see the sections for the indivual modules below for more information on those attributes.\n\n\n\nRecipes\n=======\n\nMost of the recipes in the cookbook are for enabling Apache modules.\nWhere additional configuration or behavior is used, it is documented\nbelow in more detail.\n\nThe following recipes merely enable the specified module: `mod_actions`, `mod_alias`,\n`mod_auth_basic`, `mod_auth_digest`, `mod_authn_file`, `mod_authnz_ldap`,\n`mod_authz_default`, `mod_authz_groupfile`, `mod_authz_host`,\n`mod_authz_user`, `mod_autoindex`, `mod_cgi`, `mod_dav_fs`,\n`mod_dav_svn`, `mod_deflate`, `mod_dir`, `mod_env`, `mod_expires`,\n`mod_headers`, `mod_ldap`, `mod_log_config`, `mod_mime`,\n`mod_negotiation`, `mod_proxy`, `mod_proxy_ajp`, `mod_proxy_balancer`,\n`mod_proxy_connect`, `mod_proxy_http`, `mod_python`, `mod_rewrite`,\n`mod_setenvif`, `mod_status`, `mod_wsgi`, `mod_xsendfile`.\n\nOn RHEL Family distributions, certain modules ship with a config file\nwith the package. The recipes here may delete those configuration\nfiles to ensure they don't conflict with the settings from the\ncookbook, which will use per-module configuration in\n`/etc/httpd/mods-enabled`.\n\ndefault\n-------\n\nThe default recipe does a number of things to set up Apache HTTPd. It\nalso includes a number of modules based on the attribute\n`node['apache']['default_modules']` as recipes.\n\nmod\\_auth\\_cas\n--------------\n\nThis recipe installs the proper package and enables the `auth_cas`\nmodule. It can install from source or package. Package is the default,\nset the attribute `node['apache']['mod_auth_cas']['from_source']` to\ntrue to enable source installation. Modify the version to install by\nchanging the attribute\n`node['apache']['mod_auth_cas']['source_revision']`. It is a version\ntag by default, but could be master, or another tag, or branch.\n\nThe module configuration is written out with the `CASCookiePath` set,\notherwise an error loading the module may cause Apache to not start.\n\n**Note**: This recipe does not work on EL 6 platforms unless\nepel-testing repository is enabled (outside the scope of this\ncookbook), or the package version 1.0.8.1-3.el6 or higher is otherwise\navailable to the system due to this bug:\n\nhttps://bugzilla.redhat.com/show_bug.cgi?format=multiple&id=708550\n\nmod\\_auth\\_openid\n-----------------\n\nThis recipe compiles the module from source. In addition to\n`build-essential`, some other packages are included for installation\nlike the GNU C++ compiler and development headers.\n\nTo use the module in your own cookbooks to authenticate systems using\nOpenIDs, specify an array of OpenIDs that are allowed to authenticate\nwith the attribute `node['apache']['allowed_openids']`. Use the\nfollowing in a vhost to protect with OpenID authentication:\n\n AuthType OpenID require user <%= node['apache']['allowed_openids'].join(' ') %>\n AuthOpenIDDBLocation <%= node['apache']['mod_auth_openid']['dblocation'] %>\n\nChange the DBLocation with the attribute as required; this file is in\na different location than previous versions, see below. It should be a\nsane default for most platforms, though, see\n`attributes/mod_auth_openid.rb`.\n\nThe following attributes are in the `attributes/mod_auth_openid.rb` file.\n\n* `node['apache']['mod_auth_openid']['checksum']` - sha256sum of the tarball containing the source.\n* `node['apache']['mod_auth_openid']['ref']` - Any sha, tag, or branch found from https://github.com/bmuller/mod_auth_openid\n* `node['apache']['mod_auth_openid']['version']` - directory name version within the tarball\n* `node['apache']['mod_auth_openid']['cache_dir']` - the cache directory is where the sqlite3 database is stored. It is separate so it can be managed as a directory resource.\n* `node['apache']['mod_auth_openid']['dblocation']` - filename of the sqlite3 database used for directive `AuthOpenIDDBLocation`, stored in the `cache_dir` by default.\n* `node['apache']['mod_auth_openid']['configure_flags']` - optional array of configure flags passed to the `./configure` step in the compilation of the module.\n\n\nmod\\_fastcgi\n------------\n\nInstall the fastcgi package and enable the module.\n\nNote: In Ubuntu 14.04, the `libapache2-mod-fastcgi` module is not available by default due to the [Multiverse](https://help.ubuntu.com/community/Repositories/Ubuntu) repositories.\nYou need to enable the multiverse repositories either from `/etc/apt/sources.list` or use the [apt](https://supermarket.chef.io/cookbooks/apt) cookbook.\n\nmod\\_fcgid\n----------\n\nInstalls the fcgi package and enables the module. Requires EPEL on\nRHEL family.\n\nmod\\_php5\n--------\n\nSimply installs the appropriate package on Debian, Ubuntu and\nArchLinux.\n\nOn Red Hat family distributions including Fedora, the php.conf that\ncomes with the package is removed. On RHEL platforms less than v6, the\n`php53` package is used.\n\n* `node['apache']['mod_php5']['install_method']` - default `package` can be overridden to avoid package installs.\n\nmod\\_ssl\n--------\n\nBesides installing and enabling `mod_ssl`, this recipe will append\nport 443 to the `node['apache']['listen']` attributes for all addresses and\nupdate the ports.conf.\n\n\n* `node['apache']['mod_ssl']['cipher_suite']` - sets the SSLCiphersuite value to the specified string. The default is\n considered \"sane\" but you may need to change it for your local security policy, e.g. if you have PCI-DSS requirements. Additional\n commentary on the\n [original pull request](https://github.com/sous-chefs/apache2/pull/15#commitcomment-1605406).\n* `node['apache']['mod_ssl']['honor_cipher_order']` - Option to prefer the server's cipher preference order. Default 'On'.\n* `node['apache']['mod_ssl']['insecure_renegotiation']` - Option to enable support for insecure renegotiation. Default 'Off'.\n* `node['apache']['mod_ssl']['strict_sni_vhost_check']` - Whether to allow non-SNI clients to access a name-based virtual host. Default 'Off'.\n* `node['apache']['mod_ssl']['session_cache']` - Configures the OCSP stapling cache. Default `shmcb:/var/run/apache2/ssl_scache`\n* `node['apache']['mod_ssl']['session_cache_timeout']` - Number of seconds before an SSL session expires in the Session Cache. Default 300.\n* `node['apache']['mod_ssl']['compression']` - \tEnable compression on the SSL level. Default 'Off'.\n* `node['apache']['mod_ssl']['use_stapling']` - Enable stapling of OCSP responses in the TLS handshake. Default 'Off'.\n* `node['apache']['mod_ssl']['stapling_responder_timeout']` - \tTimeout for OCSP stapling queries. Default 5\n* `node['apache']['mod_ssl']['stapling_return_responder_errors']` - Pass stapling related OCSP errors on to client. Default 'Off'\n* `node['apache']['mod_ssl']['stapling_cache']` - Configures the OCSP stapling cache. Default `shmcb:/var/run/ocsp(128000)`\n* `node['apache']['mod_ssl']['pass_phrase_dialog']` - Configures SSLPassPhraseDialog. Default `builtin`\n* `node['apache']['mod_ssl']['mutex']` - Configures SSLMutex. Default `file:/var/run/apache2/ssl_mutex`\n* `node['apache']['mod_ssl']['directives']` - Hash for add any custom directive.\n\nFor general information on these attributes see http://httpd.apache.org/docs/current/mod/mod_ssl.html\n\nFor more information on these directives and how to best secure your site see\n- https://bettercrypto.org/\n- https://wiki.mozilla.org/Security/Server_Side_TLS\n- https://www.insecure.ws/linux/apache_ssl.html\n- https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/\n- https://istlsfastyet.com/\n- https://www.ssllabs.com/projects/best-practices/\n\nDefinitions\n===========\n\nThe cookbook provides a few definitions. At some point in the future\nthese definitions will be refactored into custom resources see\n[issue 414](https://github.com/sous-chefs/apache2/issues/414).\n\napache\\_conf\n------------\n\nWrites conf files to the `conf-available` folder, and passes enabled values to `apache_config`.\n\nThis definition should generally be called over `apache_config`.\n\n### Parameters:\n\n* `name` - Name of the config placed and enabled or disabled with the `a2enconf` or `a2disconf` scripts.\n* `enable` - Default true, which uses `a2enconf` to enable the config. If false, the config will be disabled with `a2disconf`.\n* `conf_path` - path to put the config in if you need to override the default `conf-available`.\n* `source` - The source configuration template name. The default value is `params[:name].conf.erb`\n* `cookbook` - The cookbook in which the configuration template is located. The default value is the current cookbook.\n\n### Examples:\n\nPlace and enable the example conf:\n\n```ruby\n apache_conf 'example' do\n enable true\n end\n```\n\nPlace and disable (or never enable to begin with) the example conf:\n\n```ruby\n apache_conf 'example' do\n enable false\n end\n```\n\nPlace the example conf, which has a different path than the default (conf-*):\n\n```ruby\n apache_conf 'example' do\n conf_path '/random/example/path'\n enable false\n end\n```\n\n\napache\\_config (internal)\n--------------------------\n\nSets up configuration file for Apache from a template. The\ntemplate should be in the same cookbook where the definition is used. This is used by the `apache_conf` definition and should not be used directly.\n\nIt will use `a2enconf` and `a2disconf` to control the symlinking of configuration files between `conf-available` and `conf-enabled`.\n\nEnable or disable an Apache config file in\n`#{node['apache']['dir']}/conf-available` by calling `a2enconf` or\n`a2disconf` to manage the symbolic link in\n`#{node['apache']['dir']}/conf-enabled`. These config files should be created in your cookbook, and placed on the system using `apache_conf`\n\n### Parameters:\n\n* `name` - Name of the config enabled or disabled with the `a2enconf` or `a2disconf` scripts.\n* `source` - The location of a template file. The default `name.erb`.\n* `cookbook` - The cookbook in which the configuration template is located (if it is not located in the current cookbook). The default value is the current cookbook.\n* `enable` - Default true, which uses `a2enconf` to enable the config. If false, the config will be disabled with `a2disconf`.\n\n### Examples:\n\nEnable the example config.\n\n```ruby\n apache_config 'example' do\n enable true\n end\n```\n\nDisable a module:\n\n```ruby\n apache_config 'disabled_example' do\n enable false\n end\n```\n\nSee the recipes directory for many more examples of `apache_config`.\n\n\napache\\_module\n--------------\n\nEnable or disable an Apache module in\n`#{node['apache']['dir']}/mods-available` by calling `a2enmod` or\n`a2dismod` to manage the symbolic link in\n`#{node['apache']['dir']}/mods-enabled`. If the module has a\nconfiguration file, a template should be created in the cookbook where\nthe definition is used. See __Examples__.\n\n### Parameters:\n\n* `name` - Name of the module enabled or disabled with the `a2enmod` or `a2dismod` scripts.\n* `identifier` - String to identify the module for the `LoadModule` directive. Not typically needed, defaults to `#{name}_module`\n* `enable` - Default true, which uses `a2enmod` to enable the module. If false, the module will be disabled with `a2dismod`.\n* `conf` - Default false. Set to true if the module has a config file, which will use `apache_mod` for the file.\n* `filename` - specify the full name of the file, e.g.\n\n### Examples:\n\nEnable the ssl module, which also has a configuration template in `templates/default/mods/ssl.conf.erb`.\n\n```ruby\n apache_module \"ssl\" do\n conf true\n end\n```\n\nEnable the php5 module, which has a different filename than the module default:\n\n```ruby\n apache_module \"php5\" do\n filename \"libphp5.so\"\n end\n```\n\nDisable a module:\n\n```ruby\n apache_module \"disabled_module\" do\n enable false\n end\n```\n\nSee the recipes directory for many more examples of `apache_module`.\n\napache\\_mod (internal)\n----------------------\n\nSets up configuration file for an Apache module from a template. The\ntemplate should be in the same cookbook where the definition is used.\nThis is used by the `apache_module` definition and is not often used\ndirectly.\n\nThis will use a template resource to write the module's configuration\nfile in the `mods-available` under the Apache configuration directory\n(`node['apache']['dir']`). This is a platform-dependent location. See\n__apache\\_module__.\n\n### Parameters:\n\n* `name` - Name of the template. When used from the `apache_module`,\n it will use the same name as the module.\n\n### Examples:\n\nCreate `#{node['apache']['dir']}/mods-available/alias.conf`.\n\n```ruby\n apache_mod \"alias\"\n```\n\napache\\_site\n------------\n\nEnable or disable a VirtualHost in\n`#{node['apache']['dir']}/sites-available` by calling a2ensite or\na2dissite to manage the symbolic link in\n`#{node['apache']['dir']}/sites-enabled`.\n\nThe template for the site must be managed as a separate resource. To\ncombine the template with enabling a site, see `web_app`.\n\n### Parameters:\n\n* `name` - Name of the site.\n* `enable` - Default true, which uses `a2ensite` to enable the site. If false, the site will be disabled with `a2dissite`.\n\nweb\\_app\n--------\n\nManage a template resource for a VirtualHost site, and enable it with\n`apache_site`. This is commonly done for managing web applications\nsuch as Ruby on Rails, PHP or Django, and the default behavior\nreflects that. However it is flexible.\n\nThis definition includes some recipes to make sure the system is\nconfigured to have Apache and some sane default modules:\n\n* `apache2`\n* `apache2::mod_rewrite`\n* `apache2::mod_deflate`\n* `apache2::mod_headers`\n\nIt will then configure the template (see __Parameters__ and\n__Examples__ below), and enable or disable the site per the `enable`\nparameter.\n\n### Parameters:\n\nCurrent parameters used by the definition:\n\n* `name` - The name of the site. The template will be written to\n `#{node['apache']['dir']}/sites-available/#{params['name']}.conf`\n* `cookbook` - Optional. Cookbook where the source template is. If\n this is not defined, Chef will use the named template in the\n cookbook where the definition is used.\n* `template` - Default `web_app.conf.erb`, source template file.\n* `enable` - Default true. Passed to the `apache_site` definition.\n\nAdditional parameters can be defined when the definition is called in\na recipe, see __Examples__.\n\n### Examples:\n\nThe recommended way to use the `web_app` definition is in a application specific cookbook named \"my_app\".\nThe following example would look for a template named 'web_app.conf.erb' in your cookbook containing\nthe apache httpd directives defining the `VirtualHost` that would serve up \"my_app\".\n\n```ruby\n web_app \"my_app\" do\n template 'web_app.conf.erb'\n server_name node['my_app']['hostname']\n end\n```\n\nAll parameters are passed into the template. You can use whatever you\nlike. The apache2 cookbook comes with a `web_app.conf.erb` template as\nan example. The following parameters are used in the template:\n\n* `server_name` - ServerName directive.\n* `server_aliases` - ServerAlias directive. Must be an array of aliases.\n* `docroot` - DocumentRoot directive.\n* `application_name` - Used in RewriteLog directive. Will be set to the `name` parameter.\n* `directory_index` - Allow overriding the default DirectoryIndex setting, optional\n* `directory_options` - Override Options on the docroot, for example to add parameters like Includes or Indexes, optional.\n* `allow_override` - Modify the AllowOverride directive on the docroot to support apps that need .htaccess to modify configuration or require authentication.\n\nTo use the default web_app, for example:\n\n```ruby\n web_app \"my_site\" do\n server_name node['hostname']\n server_aliases [node['fqdn'], \"my-site.example.com\"]\n docroot \"/srv/www/my_site\"\n cookbook 'apache2'\n end\n```\n\nThe parameters specified will be used as:\n\n* `@params[:server_name]`\n* `@params[:server_aliases]`\n* `@params[:docroot]`\n\nIn the template. When you write your own, the `@` is significant.\n\nFor more information about Definitions and parameters, see the\n[Chef Wiki](http://docs.chef.io/definitions.html)\n\nTests\n=====\n\nThis cookbook in the [source repository](https://github.com/sous-chefs/apache2/)\ncontains chefspec, serverspec tests.\n\nPlease see the CONTRIBUTING file for information on how to add tests\nfor your contributions.\n\n\nLicense and Authors\n===================\n\n* Author:: Adam Jacob \n* Author:: Joshua Timberman \n* Author:: Bryan McLellan \n* Author:: Dave Esposito \n* Author:: David Abdemoulaie \n* Author:: Edmund Haselwanter \n* Author:: Eric Rochester \n* Author:: Jim Browne \n* Author:: Matthew Kent \n* Author:: Nathen Harvey \n* Author:: Ringo De Smet \n* Author:: Sean OMeara \n* Author:: Seth Chisamore \n* Author:: Gilles Devaux \n* Author:: Sander van Zoest \n* Author:: Taylor Price \n* Author:: Ben Dean \n\n* Copyright:: 2009-2012, Chef Software, Inc\n* Copyright:: 2011, Atriso\n* Copyright:: 2011, CustomInk, LLC.\n* Copyright:: 2013-2014, OneHealth Solutions, Inc.\n* Copyright:: 2014, Viverae, Inc.\n* Copyright:: 2015-2016, Alexander van Zoest\n* Copyright:: 2015, Ontario Systems, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","maintainer":"Sous Chefs","maintainer_email":"help@sous-chefs.org","license":"Apache 2.0","platforms":{"debian":">= 0.0.0","ubuntu":">= 0.0.0","redhat":">= 0.0.0","centos":">= 0.0.0","fedora":">= 0.0.0","amazon":">= 0.0.0","scientific":">= 0.0.0","freebsd":">= 0.0.0","suse":">= 0.0.0","opensuse":">= 0.0.0","opensuseleap":">= 0.0.0","arch":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/sous-chefs/apache2","issues_url":"https://github.com/sous-chefs/apache2/issues","chef_version":[[">= 11"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/apache2/recipes/default.rb b/cookbooks/apache2/recipes/default.rb new file mode 100644 index 0000000..7f39842 --- /dev/null +++ b/cookbooks/apache2/recipes/default.rb @@ -0,0 +1,219 @@ +# +# Cookbook:: apache2 +# Recipe:: default +# +# Copyright:: 2008-2013, Chef Software, Inc. +# Copyright:: 2014-2015, Alexander van Zoest +# +# 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. +# + +package 'apache2' do # ~FC009 only available in apt_package. See #388 + package_name node['apache']['package'] + default_release node['apache']['default_release'] unless node['apache']['default_release'].nil? +end + +%w(sites-available sites-enabled mods-available mods-enabled conf-available conf-enabled).each do |dir| + directory "#{node['apache']['dir']}/#{dir}" do + mode '0755' + owner 'root' + group node['apache']['root_group'] + end +end + +%w(default default.conf 000-default 000-default.conf).each do |site| + link "#{node['apache']['dir']}/sites-enabled/#{site}" do + action :delete + not_if { site == "#{node['apache']['default_site_name']}.conf" && node['apache']['default_site_enabled'] } + end + + file "#{node['apache']['dir']}/sites-available/#{site}" do + action :delete + backup false + not_if { site == "#{node['apache']['default_site_name']}.conf" && node['apache']['default_site_enabled'] } + end +end + +directory node['apache']['log_dir'] do + mode '0755' + recursive true +end + +# perl is needed for the a2* scripts +package node['apache']['perl_pkg'] + +package 'perl-Getopt-Long-Descriptive' if platform?('fedora') + +%w(a2ensite a2dissite a2enmod a2dismod a2enconf a2disconf).each do |modscript| + link "/usr/sbin/#{modscript}" do + action :delete + only_if { ::File.symlink?("/usr/sbin/#{modscript}") } + end + + template "/usr/sbin/#{modscript}" do + source "#{modscript}.erb" + mode '0700' + owner 'root' + group node['apache']['root_group'] + action :create + end +end + +unless platform_family?('debian') + cookbook_file '/usr/local/bin/apache2_module_conf_generate.pl' do + source 'apache2_module_conf_generate.pl' + mode '0755' + owner 'root' + group node['apache']['root_group'] + end + + execute 'generate-module-list' do + command "/usr/local/bin/apache2_module_conf_generate.pl #{node['apache']['lib_dir']} #{node['apache']['dir']}/mods-available" + action :nothing + end +end + +if platform_family?('freebsd') + + directory "#{node['apache']['dir']}/Includes" do + action :delete + recursive true + end + + directory "#{node['apache']['dir']}/extra" do + action :delete + recursive true + end +end + +if platform_family?('suse') + + directory "#{node['apache']['dir']}/vhosts.d" do + action :delete + recursive true + end + + %w(charset.conv default-vhost.conf default-server.conf default-vhost-ssl.conf errors.conf listen.conf mime.types mod_autoindex-defaults.conf mod_info.conf mod_log_config.conf mod_status.conf mod_userdir.conf mod_usertrack.conf uid.conf).each do |file| + file "#{node['apache']['dir']}/#{file}" do + action :delete + backup false + end + end +end + +%W( + #{node['apache']['dir']}/ssl + #{node['apache']['cache_dir']} +).each do |path| + directory path do + mode '0755' + owner 'root' + group node['apache']['root_group'] + end +end + +directory node['apache']['lock_dir'] do + mode '0755' + if node['platform_family'] == 'debian' + owner node['apache']['user'] + else + owner 'root' + end + group node['apache']['root_group'] +end + +# Set the preferred execution binary - prefork or worker +template "/etc/sysconfig/#{node['apache']['package']}" do + source 'etc-sysconfig-httpd.erb' + owner 'root' + group node['apache']['root_group'] + mode '0644' + notifies :restart, 'service[apache2]', :delayed + only_if { platform_family?('rhel', 'amazon', 'fedora', 'suse') } +end + +template "#{node['apache']['dir']}/envvars" do + source 'envvars.erb' + owner 'root' + group node['apache']['root_group'] + mode '0644' + notifies :reload, 'service[apache2]', :delayed + only_if { platform_family?('debian') } +end + +template 'apache2.conf' do + if platform_family?('rhel', 'amazon', 'fedora', 'arch', 'freebsd') + path "#{node['apache']['conf_dir']}/httpd.conf" + elsif platform_family?('debian') + path "#{node['apache']['conf_dir']}/apache2.conf" + elsif platform_family?('suse') + path "#{node['apache']['conf_dir']}/httpd.conf" + end + action :create + source 'apache2.conf.erb' + owner 'root' + group node['apache']['root_group'] + mode '0644' + notifies :reload, 'service[apache2]', :delayed +end + +%w(security charset).each do |conf| + apache_conf conf do + enable true + end +end + +apache_conf 'ports' do + enable false + conf_path node['apache']['dir'] +end + +if node['apache']['version'] == '2.4' + if node['apache']['mpm_support'].include?(node['apache']['mpm']) + include_recipe "apache2::mpm_#{node['apache']['mpm']}" + else + Chef::Log.warn("apache2: #{node['apache']['mpm']} module is not supported and must be handled separately!") + end +end + +node['apache']['default_modules'].each do |mod| + module_recipe_name = mod =~ /^mod_/ ? mod : "mod_#{mod}" + include_recipe "apache2::#{module_recipe_name}" +end + +if node['apache']['default_site_enabled'] + web_app node['apache']['default_site_name'] do + template 'default-site.conf.erb' + enable node['apache']['default_site_enabled'] + end +end + +apache_service_name = node['apache']['service_name'] + +service 'apache2' do + service_name apache_service_name + case node['platform_family'] + when 'rhel' + if node['platform_version'].to_f < 7.0 && node['apache']['version'] != '2.4' + restart_command "/sbin/service #{apache_service_name} restart && sleep 1" + reload_command "/sbin/service #{apache_service_name} graceful && sleep 1" + end + when 'debian' + provider Chef::Provider::Service::Debian + when 'arch' + service_name apache_service_name + end + supports [:start, :restart, :reload, :status] + action [:enable, :start] + only_if "#{node['apache']['binary']} -t", environment: { 'APACHE_LOG_DIR' => node['apache']['log_dir'] }, timeout: 10 +end diff --git a/cookbooks/apache2/recipes/mod_access_compat.rb b/cookbooks/apache2/recipes/mod_access_compat.rb new file mode 100644 index 0000000..6bd2e4a --- /dev/null +++ b/cookbooks/apache2/recipes/mod_access_compat.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_access_compat +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'access_compat' diff --git a/cookbooks/apache2/recipes/mod_actions.rb b/cookbooks/apache2/recipes/mod_actions.rb new file mode 100644 index 0000000..d33df83 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_actions.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_actions +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'actions' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_alias.rb b/cookbooks/apache2/recipes/mod_alias.rb new file mode 100644 index 0000000..6ff5f18 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_alias.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_alias +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'alias' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_allowmethods.rb b/cookbooks/apache2/recipes/mod_allowmethods.rb new file mode 100644 index 0000000..f182b69 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_allowmethods.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_allowmethods +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'allowmethods' diff --git a/cookbooks/apache2/recipes/mod_apreq2.rb b/cookbooks/apache2/recipes/mod_apreq2.rb new file mode 100644 index 0000000..57e8057 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_apreq2.rb @@ -0,0 +1,50 @@ +# +# Cookbook:: apache2 +# Recipe:: apreq2 +# +# modified from the python recipe by Jeremy Bingham +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'apache2::default' + +case node['platform_family'] +when 'debian' + package 'libapache2-mod-apreq2' +when 'suse' + package 'apache2-mod_apreq2' do + notifies :run, 'execute[generate-module-list]', :immediately + end +when 'rhel', 'fedora', 'amazon' + package 'libapreq2' do + notifies :run, 'execute[generate-module-list]', :immediately + end + + # seems that the apreq lib is weirdly broken or something - it needs to be + # loaded as 'apreq', but on RHEL & derivitatives the file needs a symbolic + # link to mod_apreq.so. + link "#{node['apache']['libexec_dir']}/mod_apreq.so" do + to "#{node['apache']['libexec_dir']}/mod_apreq2.so" + only_if "test -f #{node['apache']['libexec_dir']}/mod_apreq2.so" + end +end + +file "#{node['apache']['dir']}/conf.d/apreq.conf" do + content '# conf is under mods-available/apreq.conf - apache2 cookbook\n' + only_if { ::Dir.exist?("#{node['apache']['dir']}/conf.d") } +end + +apache_module 'apreq' diff --git a/cookbooks/apache2/recipes/mod_asis.rb b/cookbooks/apache2/recipes/mod_asis.rb new file mode 100644 index 0000000..63502a9 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_asis.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_asis +# +# Copyright:: 2008-2009, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'asis' diff --git a/cookbooks/apache2/recipes/mod_auth_basic.rb b/cookbooks/apache2/recipes/mod_auth_basic.rb new file mode 100644 index 0000000..ac6c8be --- /dev/null +++ b/cookbooks/apache2/recipes/mod_auth_basic.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_auth_basic +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'auth_basic' diff --git a/cookbooks/apache2/recipes/mod_auth_cas.rb b/cookbooks/apache2/recipes/mod_auth_cas.rb new file mode 100644 index 0000000..ff0e61e --- /dev/null +++ b/cookbooks/apache2/recipes/mod_auth_cas.rb @@ -0,0 +1,68 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_auth_cas +# +# Copyright:: 2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'apache2::default' + +if node['apache']['mod_auth_cas']['from_source'] + package node['apache']['devel_package'] + + git '/tmp/mod_auth_cas' do + repository 'git://github.com/Jasig/mod_auth_cas.git' + revision node['apache']['mod_auth_cas']['source_revision'] + notifies :run, 'execute[compile mod_auth_cas]', :immediately + end + + execute 'compile mod_auth_cas' do + command './configure && make && make install' + cwd '/tmp/mod_auth_cas' + not_if "test -f #{node['apache']['libexec_dir']}/mod_auth_cas.so" + end + + template "#{node['apache']['dir']}/mods-available/auth_cas.load" do + source 'mods/auth_cas.load.erb' + owner 'root' + group node['apache']['root_group'] + mode '0644' + end +else + case node['platform_family'] + when 'debian' + package 'libapache2-mod-auth-cas' + + when 'rhel', 'fedora', 'amazon' + yum_package 'mod_auth_cas' do + notifies :run, 'execute[generate-module-list]', :immediately + end + + file "#{node['apache']['dir']}/conf.d/auth_cas.conf" do + content '# conf is under mods-available/auth_cas.conf - apache2 cookbook\n' + only_if { ::Dir.exist?("#{node['apache']['dir']}/conf.d") } + end + end +end + +apache_module 'auth_cas' do + conf true +end + +directory "#{node['apache']['cache_dir']}/mod_auth_cas" do + owner node['apache']['user'] + group node['apache']['group'] + mode '0700' +end diff --git a/cookbooks/apache2/recipes/mod_auth_digest.rb b/cookbooks/apache2/recipes/mod_auth_digest.rb new file mode 100644 index 0000000..5c87167 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_auth_digest.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_auth_digest +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'auth_digest' diff --git a/cookbooks/apache2/recipes/mod_auth_form.rb b/cookbooks/apache2/recipes/mod_auth_form.rb new file mode 100644 index 0000000..8ddddd3 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_auth_form.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_auth_form +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'auth_form' diff --git a/cookbooks/apache2/recipes/mod_auth_openid.rb b/cookbooks/apache2/recipes/mod_auth_openid.rb new file mode 100644 index 0000000..193fbb8 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_auth_openid.rb @@ -0,0 +1,122 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_auth_openid +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +openid_dev_pkgs = value_for_platform_family( + 'debian' => %W(automake make g++ #{node['apache']['devel_package']} libopkele-dev libopkele3 libtool), + 'suse' => %W(automake make g++ #{node['apache']['devel_package']} libopkele-dev libopkele3 libtool), + %w(rhel fedora amazon) => %W(gcc-c++ #{node['apache']['devel_package']} curl-devel libtidy libtidy-devel sqlite-devel pcre-devel openssl-devel make libtool), + 'arch' => %w(libopkele), + 'freebsd' => %w(libopkele pcre sqlite3) +) + +make_cmd = value_for_platform_family( + 'freebsd' => { 'default' => 'gmake' }, + 'default' => 'make' +) + +case node['platform_family'] +when 'arch' + package 'tidyhtml' + + pacman_aur openid_dev_pkgs.first do + action [:build, :install] + end +else + openid_dev_pkgs.each do |pkg| + package pkg + end +end + +case node['platform_family'] +when 'rhel', 'fedora', 'amazon' + remote_file "#{Chef::Config['file_cache_path']}/libopkele-2.0.4.tar.gz" do + source 'http://kin.klever.net/dist/libopkele-2.0.4.tar.gz' + mode '0644' + checksum '57a5bc753b7e80c5ece1e5968b2051b0ce7ed9ce4329d17122c61575a9ea7648' + end + + bash 'install libopkele' do + cwd Chef::Config['file_cache_path'] + # Ruby 1.8.6 does not have rpartition, unfortunately + syslibdir = node['apache']['lib_dir'][0..node['apache']['lib_dir'].rindex('/')] + code <<-EOH + tar zxvf libopkele-2.0.4.tar.gz + cd libopkele-2.0.4 && ./configure --prefix=/usr --libdir=#{syslibdir} + #{make_cmd} && #{make_cmd} install + EOH + creates "#{syslibdir}/libopkele.a" + end +end + +version = node['apache']['mod_auth_openid']['version'] +configure_flags = node['apache']['mod_auth_openid']['configure_flags'] + +remote_file "#{Chef::Config['file_cache_path']}/mod_auth_openid-#{version}.tar.gz" do + source node['apache']['mod_auth_openid']['source_url'] + mode '0644' + action :create_if_missing +end + +directory node['apache']['mod_auth_openid']['cache_dir'] do + owner node['apache']['user'] + group node['apache']['group'] + mode '0700' +end + +bash 'untar mod_auth_openid' do + cwd Chef::Config['file_cache_path'] + code <<-EOH + tar zxvf mod_auth_openid-#{version}.tar.gz + EOH + creates "#{Chef::Config['file_cache_path']}/mod_auth_openid-#{version}/src/types.h" +end + +bash 'compile mod_auth_openid' do + cwd "#{Chef::Config['file_cache_path']}/mod_auth_openid-#{version}" + code <<-EOH + ./autogen.sh + ./configure #{configure_flags.join(' ')} + perl -pi -e "s/-i -a -n 'authopenid'/-i -n 'authopenid'/g" Makefile + #{make_cmd} + EOH + creates "#{Chef::Config['file_cache_path']}/mod_auth_openid-#{version}/src/.libs/mod_auth_openid.so" + notifies :run, 'bash[install-mod_auth_openid]', :immediately + not_if "test -f #{Chef::Config['file_cache_path']}/mod_auth_openid-#{version}/src/.libs/mod_auth_openid.so" +end + +bash 'install-mod_auth_openid' do + cwd "#{Chef::Config['file_cache_path']}/mod_auth_openid-#{version}" + code <<-EOH + #{make_cmd} install + EOH + creates "#{node['apache']['libexec_dir']}/mod_auth_openid.so" + notifies :restart, 'service[apache2]' + not_if "test -f #{node['apache']['libexec_dir']}/mod_auth_openid.so" +end + +template "#{node['apache']['dir']}/mods-available/authopenid.load" do + source 'mods/authopenid.load.erb' + owner 'root' + group node['apache']['root_group'] + mode '0644' +end + +apache_module 'authopenid' do + filename 'mod_auth_openid.so' +end diff --git a/cookbooks/apache2/recipes/mod_authn_anon.rb b/cookbooks/apache2/recipes/mod_authn_anon.rb new file mode 100644 index 0000000..d767e9f --- /dev/null +++ b/cookbooks/apache2/recipes/mod_authn_anon.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_authn_anon +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'authn_anon' diff --git a/cookbooks/apache2/recipes/mod_authn_core.rb b/cookbooks/apache2/recipes/mod_authn_core.rb new file mode 100644 index 0000000..c7b826e --- /dev/null +++ b/cookbooks/apache2/recipes/mod_authn_core.rb @@ -0,0 +1,23 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_authn_core +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +if node['apache']['version'] == '2.4' + apache_module 'authn_core' +else + Chef::Log.info('Ignoring apache2::mod_authn_core. not available until apache 2.4') +end diff --git a/cookbooks/apache2/recipes/mod_authn_dbd.rb b/cookbooks/apache2/recipes/mod_authn_dbd.rb new file mode 100644 index 0000000..68edb8f --- /dev/null +++ b/cookbooks/apache2/recipes/mod_authn_dbd.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_authn_dbd +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'authn_dbd' diff --git a/cookbooks/apache2/recipes/mod_authn_dbm.rb b/cookbooks/apache2/recipes/mod_authn_dbm.rb new file mode 100644 index 0000000..418dafb --- /dev/null +++ b/cookbooks/apache2/recipes/mod_authn_dbm.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_authn_dbm +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'authn_dbm' diff --git a/cookbooks/apache2/recipes/mod_authn_file.rb b/cookbooks/apache2/recipes/mod_authn_file.rb new file mode 100644 index 0000000..46f8458 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_authn_file.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_authn_file +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'authn_file' diff --git a/cookbooks/apache2/recipes/mod_authn_socache.rb b/cookbooks/apache2/recipes/mod_authn_socache.rb new file mode 100644 index 0000000..148be8e --- /dev/null +++ b/cookbooks/apache2/recipes/mod_authn_socache.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_authn_socache +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'authn_socache' diff --git a/cookbooks/apache2/recipes/mod_authnz_fcgi.rb b/cookbooks/apache2/recipes/mod_authnz_fcgi.rb new file mode 100644 index 0000000..fba9ca9 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_authnz_fcgi.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_authnz_fcgi +# +# Copyright:: 2016, Alexander van Zoest +# +# 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. +# + +apache_module 'authnz_fcgi' diff --git a/cookbooks/apache2/recipes/mod_authnz_ldap.rb b/cookbooks/apache2/recipes/mod_authnz_ldap.rb new file mode 100644 index 0000000..53ca785 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_authnz_ldap.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_authnz_ldap +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'apache2::mod_ldap' + +apache_module 'authnz_ldap' diff --git a/cookbooks/apache2/recipes/mod_authz_core.rb b/cookbooks/apache2/recipes/mod_authz_core.rb new file mode 100644 index 0000000..97529fb --- /dev/null +++ b/cookbooks/apache2/recipes/mod_authz_core.rb @@ -0,0 +1,24 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_authz_core +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if node['apache']['version'] == '2.4' + apache_module 'authz_core' +else + apache_module 'authz_default' +end diff --git a/cookbooks/apache2/recipes/mod_authz_dbd.rb b/cookbooks/apache2/recipes/mod_authz_dbd.rb new file mode 100644 index 0000000..4d114b5 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_authz_dbd.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_authz_dbd +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'authz_dbd' diff --git a/cookbooks/apache2/recipes/mod_authz_dbm.rb b/cookbooks/apache2/recipes/mod_authz_dbm.rb new file mode 100644 index 0000000..7d900f1 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_authz_dbm.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_authz_dbm +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'authz_dbm' diff --git a/cookbooks/apache2/recipes/mod_authz_default.rb b/cookbooks/apache2/recipes/mod_authz_default.rb new file mode 100644 index 0000000..4973fdf --- /dev/null +++ b/cookbooks/apache2/recipes/mod_authz_default.rb @@ -0,0 +1,21 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_authz_default +# +# Copyright:: 2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +log 'apache2::mod_authz_default is deprecated in favor of apache2::mod_authz_core. Please adjust your cookbooks' +include_recipe 'apache2::mod_authz_core' diff --git a/cookbooks/apache2/recipes/mod_authz_groupfile.rb b/cookbooks/apache2/recipes/mod_authz_groupfile.rb new file mode 100644 index 0000000..1df8ad0 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_authz_groupfile.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_authz_groupfile +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'authz_groupfile' diff --git a/cookbooks/apache2/recipes/mod_authz_host.rb b/cookbooks/apache2/recipes/mod_authz_host.rb new file mode 100644 index 0000000..202fd08 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_authz_host.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_authz_host +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'authz_host' diff --git a/cookbooks/apache2/recipes/mod_authz_owner.rb b/cookbooks/apache2/recipes/mod_authz_owner.rb new file mode 100644 index 0000000..e1a958d --- /dev/null +++ b/cookbooks/apache2/recipes/mod_authz_owner.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_authz_owner +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'authz_owner' diff --git a/cookbooks/apache2/recipes/mod_authz_user.rb b/cookbooks/apache2/recipes/mod_authz_user.rb new file mode 100644 index 0000000..03d1b16 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_authz_user.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_authz_user +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'authz_user' diff --git a/cookbooks/apache2/recipes/mod_autoindex.rb b/cookbooks/apache2/recipes/mod_autoindex.rb new file mode 100644 index 0000000..2b0f4f2 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_autoindex.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_autoindex +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'autoindex' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_buffer.rb b/cookbooks/apache2/recipes/mod_buffer.rb new file mode 100644 index 0000000..8df551e --- /dev/null +++ b/cookbooks/apache2/recipes/mod_buffer.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_buffer +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'buffer' diff --git a/cookbooks/apache2/recipes/mod_cache.rb b/cookbooks/apache2/recipes/mod_cache.rb new file mode 100644 index 0000000..4eb7c90 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_cache.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_cache +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'cache' diff --git a/cookbooks/apache2/recipes/mod_cache_disk.rb b/cookbooks/apache2/recipes/mod_cache_disk.rb new file mode 100644 index 0000000..be53224 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_cache_disk.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_cache_disk +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'cache_disk' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_cache_socache.rb b/cookbooks/apache2/recipes/mod_cache_socache.rb new file mode 100644 index 0000000..b2fa8ca --- /dev/null +++ b/cookbooks/apache2/recipes/mod_cache_socache.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_cache_socache +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'cache_socache' diff --git a/cookbooks/apache2/recipes/mod_cern_meta.rb b/cookbooks/apache2/recipes/mod_cern_meta.rb new file mode 100644 index 0000000..be6018e --- /dev/null +++ b/cookbooks/apache2/recipes/mod_cern_meta.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_cern_meta +# +# Copyright:: 2016, Alexander van Zoest +# +# 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. +# + +apache_module 'cern_meta' diff --git a/cookbooks/apache2/recipes/mod_cgi.rb b/cookbooks/apache2/recipes/mod_cgi.rb new file mode 100644 index 0000000..bc8fac1 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_cgi.rb @@ -0,0 +1,26 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_cgi +# +# Copyright:: 2008-2013, Chef Software, Inc. +# Copyright:: 2014, Viverae, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if node['apache']['mpm'] == 'prefork' + apache_module 'cgi' +else + Chef::Log.warn "apache::mod_cgi. Your MPM #{node['apache']['mpm']} seems to be threaded. Selecting cgid instead of cgi." + apache_module 'cgid' +end diff --git a/cookbooks/apache2/recipes/mod_cgid.rb b/cookbooks/apache2/recipes/mod_cgid.rb new file mode 100644 index 0000000..08dfc9d --- /dev/null +++ b/cookbooks/apache2/recipes/mod_cgid.rb @@ -0,0 +1,23 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_cgid +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# Copyright:: 2014, Viverae, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'cgid' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_charset_lite.rb b/cookbooks/apache2/recipes/mod_charset_lite.rb new file mode 100644 index 0000000..2ce46e3 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_charset_lite.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_charset_lite +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'charset_lite' diff --git a/cookbooks/apache2/recipes/mod_cloudflare.rb b/cookbooks/apache2/recipes/mod_cloudflare.rb new file mode 100644 index 0000000..18b5e98 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_cloudflare.rb @@ -0,0 +1,30 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_cloudflare +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apt_repository 'cloudflare' do + uri 'http://pkg.cloudflare.com' + distribution node['lsb']['codename'] + components ['main'] + key 'http://pkg.cloudflare.com/pubkey.gpg' + action :add +end + +package 'libapache2-mod-cloudflare' do + notifies :restart, 'service[apache2]' +end diff --git a/cookbooks/apache2/recipes/mod_data.rb b/cookbooks/apache2/recipes/mod_data.rb new file mode 100644 index 0000000..9ebb567 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_data.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_data +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'data' diff --git a/cookbooks/apache2/recipes/mod_dav.rb b/cookbooks/apache2/recipes/mod_dav.rb new file mode 100644 index 0000000..f96bcaf --- /dev/null +++ b/cookbooks/apache2/recipes/mod_dav.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_dav +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'dav' diff --git a/cookbooks/apache2/recipes/mod_dav_fs.rb b/cookbooks/apache2/recipes/mod_dav_fs.rb new file mode 100644 index 0000000..0e589ff --- /dev/null +++ b/cookbooks/apache2/recipes/mod_dav_fs.rb @@ -0,0 +1,23 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_dav_fs +# +# Copyright:: 2011-2013, Atriso +# +# 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. +# + +include_recipe 'apache2::mod_dav' +apache_module 'dav_fs' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_dav_lock.rb b/cookbooks/apache2/recipes/mod_dav_lock.rb new file mode 100644 index 0000000..6104743 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_dav_lock.rb @@ -0,0 +1,21 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_dav_lock +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'apache2::mod_dav' +apache_module 'dav_lock' diff --git a/cookbooks/apache2/recipes/mod_dav_svn.rb b/cookbooks/apache2/recipes/mod_dav_svn.rb new file mode 100644 index 0000000..d3cfd2f --- /dev/null +++ b/cookbooks/apache2/recipes/mod_dav_svn.rb @@ -0,0 +1,39 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_dav_svn +# +# Copyright:: 2008-2009, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'apache2::mod_dav' + +package 'libapache2-svn' do + case node['platform_family'] + when 'rhel', 'fedora', 'suse', 'amazon' + package_name 'mod_dav_svn' + else + package_name 'libapache2-svn' + end +end + +case node['platform_family'] +when 'rhel', 'fedora', 'suse', 'amazon' + file "#{node['apache']['dir']}/conf.d/subversion.conf" do + action :delete + backup false + end +end + +apache_module 'dav_svn' diff --git a/cookbooks/apache2/recipes/mod_dbd.rb b/cookbooks/apache2/recipes/mod_dbd.rb new file mode 100644 index 0000000..d496162 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_dbd.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_dbd +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'dbd' diff --git a/cookbooks/apache2/recipes/mod_deflate.rb b/cookbooks/apache2/recipes/mod_deflate.rb new file mode 100644 index 0000000..c976d96 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_deflate.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_deflate +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'deflate' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_dialup.rb b/cookbooks/apache2/recipes/mod_dialup.rb new file mode 100644 index 0000000..105f3ca --- /dev/null +++ b/cookbooks/apache2/recipes/mod_dialup.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_dialup +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'dialup' diff --git a/cookbooks/apache2/recipes/mod_dir.rb b/cookbooks/apache2/recipes/mod_dir.rb new file mode 100644 index 0000000..c9d0387 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_dir.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_dir +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'dir' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_dump_io.rb b/cookbooks/apache2/recipes/mod_dump_io.rb new file mode 100644 index 0000000..5d77ed1 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_dump_io.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_dump_io +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'dumpio' diff --git a/cookbooks/apache2/recipes/mod_echo.rb b/cookbooks/apache2/recipes/mod_echo.rb new file mode 100644 index 0000000..8770b7e --- /dev/null +++ b/cookbooks/apache2/recipes/mod_echo.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_echo +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'echo' diff --git a/cookbooks/apache2/recipes/mod_env.rb b/cookbooks/apache2/recipes/mod_env.rb new file mode 100644 index 0000000..b392cc1 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_env.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_env +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'env' diff --git a/cookbooks/apache2/recipes/mod_expires.rb b/cookbooks/apache2/recipes/mod_expires.rb new file mode 100644 index 0000000..23977d9 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_expires.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_expires +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'expires' diff --git a/cookbooks/apache2/recipes/mod_ext_filter.rb b/cookbooks/apache2/recipes/mod_ext_filter.rb new file mode 100644 index 0000000..296b262 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_ext_filter.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_ext_filter +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'ext_filter' diff --git a/cookbooks/apache2/recipes/mod_fastcgi.rb b/cookbooks/apache2/recipes/mod_fastcgi.rb new file mode 100644 index 0000000..e2d0759 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_fastcgi.rb @@ -0,0 +1,62 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_fastcgi +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if node['apache']['mod_fastcgi']['install_method'] == 'package' + package node['apache']['mod_fastcgi']['package'] +else + if platform_family?('debian') + package 'build-essential' + package node['apache']['devel_package'] + elsif platform_family?('rhel', 'amazon') + %W(gcc make libtool #{node['apache']['devel_package']} apr-devel apr).each do |package| + package package do + action :upgrade + end + end + end + + src_filepath = "#{Chef::Config['file_cache_path']}/fastcgi.tar.gz" + remote_file 'download fastcgi source' do + source node['apache']['mod_fastcgi']['download_url'] + path src_filepath + backup false + end + + top_dir = if platform_family?('debian') + node['apache']['build_dir'] + else + node['apache']['lib_dir'] + end + include_recipe 'apache2::default' + bash 'compile fastcgi source' do + notifies :run, 'execute[generate-module-list]', :immediately if platform_family?('rhel', 'amazon') + not_if "test -f #{node['apache']['dir']}/mods-available/fastcgi.conf" + cwd ::File.dirname(src_filepath) + code <<-EOH + tar zxf #{::File.basename(src_filepath)} && + cd mod_fastcgi-* && + cp Makefile.AP2 Makefile && + make top_dir=#{top_dir} && make install top_dir=#{top_dir} + EOH + end +end + +apache_module 'fastcgi' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_fcgid.rb b/cookbooks/apache2/recipes/mod_fcgid.rb new file mode 100644 index 0000000..5283fec --- /dev/null +++ b/cookbooks/apache2/recipes/mod_fcgid.rb @@ -0,0 +1,67 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_fcgid +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if platform_family?('debian') + package 'libapache2-mod-fcgid' +elsif platform_family?('rhel', 'fedora', 'amazon') + package 'mod_fcgid' do + notifies :run, 'execute[generate-module-list]', :immediately + end + + file "#{node['apache']['dir']}/conf.d/fcgid.conf" do + content '# conf is under mods-available/fcgid.conf - apache2 cookbook\n' + only_if { ::Dir.exist?("#{node['apache']['dir']}/conf.d") } + end + + # CentOS 7 (and recent Fedoras) have Apache 2.4, where FCGI socket path + # and shared memory path is managed adequately without further involvment + # neccessary (subdirectory is created under /var/run/httpd). + # + # However, when the path is specified manually, that subdirectory is NOT + # created automatically if it doesn't already exist and Apache fails to + # start. Since in recent RHEL systems /var/run is on tmpfs, end result is + # that chef-created subdirectory disappears on shutdown, and Apache fails + # to start after server reboot. Best to leave out these two settings + # unset then. + if (node['platform_family'] == 'rhel') && (node['platform_version'].to_i == 6) + directory '/var/run/httpd/mod_fcgid' do + owner node['apache']['user'] + group node['apache']['group'] + recursive true + end + end + +elsif platform_family?('suse') + apache_lib_path = node['apache']['lib_dir'] + + package node['apache']['devel_package'] + + bash 'install-fcgid' do + code <<-EOH +(cd #{Chef::Config['file_cache_path']}; wget http://superb-east.dl.sourceforge.net/sourceforge/mod-fcgid/mod_fcgid.2.2.tgz) +(cd #{Chef::Config['file_cache_path']}; tar zxvf mod_fcgid.2.2.tgz) +(cd #{Chef::Config['file_cache_path']}; perl -pi -e 's!/usr/local/apache2!#{apache_lib_path}!g' ./mod_fcgid.2.2/Makefile) +(cd #{Chef::Config['file_cache_path']}/mod_fcgid.2.2; make install) +EOH + end +end + +apache_module 'fcgid' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_file_cache.rb b/cookbooks/apache2/recipes/mod_file_cache.rb new file mode 100644 index 0000000..c1ae79b --- /dev/null +++ b/cookbooks/apache2/recipes/mod_file_cache.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_file_cache +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'file_cache' diff --git a/cookbooks/apache2/recipes/mod_filter.rb b/cookbooks/apache2/recipes/mod_filter.rb new file mode 100644 index 0000000..7b6f444 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_filter.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_filter +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'filter' diff --git a/cookbooks/apache2/recipes/mod_headers.rb b/cookbooks/apache2/recipes/mod_headers.rb new file mode 100644 index 0000000..a88de10 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_headers.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_headers +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'headers' do + restart true +end diff --git a/cookbooks/apache2/recipes/mod_heartbeat.rb b/cookbooks/apache2/recipes/mod_heartbeat.rb new file mode 100644 index 0000000..a19d2f0 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_heartbeat.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_heartbeat +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'heartbeat' diff --git a/cookbooks/apache2/recipes/mod_heartmonitor.rb b/cookbooks/apache2/recipes/mod_heartmonitor.rb new file mode 100644 index 0000000..e45f765 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_heartmonitor.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_heartmonitor +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'heartmonitor' diff --git a/cookbooks/apache2/recipes/mod_http2.rb b/cookbooks/apache2/recipes/mod_http2.rb new file mode 100644 index 0000000..cb13c0d --- /dev/null +++ b/cookbooks/apache2/recipes/mod_http2.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_http2 +# +# Copyright:: 2016, Alexander van Zoest +# +# 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. +# + +apache_module 'http2' diff --git a/cookbooks/apache2/recipes/mod_ident.rb b/cookbooks/apache2/recipes/mod_ident.rb new file mode 100644 index 0000000..ce5cade --- /dev/null +++ b/cookbooks/apache2/recipes/mod_ident.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_ident +# +# Copyright:: 2016, Alexander van Zoest +# +# 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. +# + +apache_module 'ident' diff --git a/cookbooks/apache2/recipes/mod_include.rb b/cookbooks/apache2/recipes/mod_include.rb new file mode 100644 index 0000000..679f04f --- /dev/null +++ b/cookbooks/apache2/recipes/mod_include.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_include +# +# Copyright:: 2012-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'include' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_info.rb b/cookbooks/apache2/recipes/mod_info.rb new file mode 100644 index 0000000..46932b3 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_info.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_info +# +# Copyright:: 2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'info' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_jk.rb b/cookbooks/apache2/recipes/mod_jk.rb new file mode 100644 index 0000000..9d9fca7 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_jk.rb @@ -0,0 +1,30 @@ +# +# Cookbook:: apache2 +# Recipe:: jk +# +# Copyright:: 2013, Mike Babineau +# Copyright:: 2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package 'libapache2-mod-jk' do + case node['platform_family'] + when 'rhel', 'fedora', 'suse', 'amazon' + package_name 'mod_jk' + else + package_name 'libapache2-mod-jk' + end +end + +apache_module 'jk' diff --git a/cookbooks/apache2/recipes/mod_lbmethod_bybusyness.rb b/cookbooks/apache2/recipes/mod_lbmethod_bybusyness.rb new file mode 100644 index 0000000..3398583 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_lbmethod_bybusyness.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_lbmethod_bybusyness +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'lbmethod_bybusyness' diff --git a/cookbooks/apache2/recipes/mod_lbmethod_byrequests.rb b/cookbooks/apache2/recipes/mod_lbmethod_byrequests.rb new file mode 100644 index 0000000..43e910d --- /dev/null +++ b/cookbooks/apache2/recipes/mod_lbmethod_byrequests.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_lbmethod_byrequests +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'lbmethod_byrequests' diff --git a/cookbooks/apache2/recipes/mod_lbmethod_bytraffic.rb b/cookbooks/apache2/recipes/mod_lbmethod_bytraffic.rb new file mode 100644 index 0000000..1faf84f --- /dev/null +++ b/cookbooks/apache2/recipes/mod_lbmethod_bytraffic.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_lbmethod_bytraffic +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'lbmethod_bytraffic' diff --git a/cookbooks/apache2/recipes/mod_lbmethod_heartbeat.rb b/cookbooks/apache2/recipes/mod_lbmethod_heartbeat.rb new file mode 100644 index 0000000..a79b738 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_lbmethod_heartbeat.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_lbmethod_heartbeat +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'lbmethod_heartbeat' diff --git a/cookbooks/apache2/recipes/mod_ldap.rb b/cookbooks/apache2/recipes/mod_ldap.rb new file mode 100644 index 0000000..612b17f --- /dev/null +++ b/cookbooks/apache2/recipes/mod_ldap.rb @@ -0,0 +1,26 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_ldap +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if platform_family?('rhel', 'amazon') && node['apache']['version'] == '2.4' + package 'mod_ldap' +end + +apache_module 'ldap' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_log_config.rb b/cookbooks/apache2/recipes/mod_log_config.rb new file mode 100644 index 0000000..1817387 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_log_config.rb @@ -0,0 +1,24 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_log_config +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if platform_family?('rhel', 'fedora', 'suse', 'arch', 'freebsd', 'amazon') + apache_module 'log_config' +else + include_recipe 'apache2::default' +end diff --git a/cookbooks/apache2/recipes/mod_log_debug.rb b/cookbooks/apache2/recipes/mod_log_debug.rb new file mode 100644 index 0000000..9615b41 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_log_debug.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_log_debug +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'log_debug' diff --git a/cookbooks/apache2/recipes/mod_log_forensic.rb b/cookbooks/apache2/recipes/mod_log_forensic.rb new file mode 100644 index 0000000..c9dabb4 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_log_forensic.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_log_forensic +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'log_forensic' diff --git a/cookbooks/apache2/recipes/mod_logio.rb b/cookbooks/apache2/recipes/mod_logio.rb new file mode 100644 index 0000000..5bce35e --- /dev/null +++ b/cookbooks/apache2/recipes/mod_logio.rb @@ -0,0 +1,24 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_logio +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if platform_family?('rhel', 'fedora', 'suse', 'arch', 'freebsd', 'amazon') + apache_module 'logio' +else + include_recipe 'apache2::default' +end diff --git a/cookbooks/apache2/recipes/mod_lua.rb b/cookbooks/apache2/recipes/mod_lua.rb new file mode 100644 index 0000000..b6855f6 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_lua.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_lua +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'lua' diff --git a/cookbooks/apache2/recipes/mod_macro.rb b/cookbooks/apache2/recipes/mod_macro.rb new file mode 100644 index 0000000..1fe377a --- /dev/null +++ b/cookbooks/apache2/recipes/mod_macro.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_macro +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'macro' diff --git a/cookbooks/apache2/recipes/mod_mime.rb b/cookbooks/apache2/recipes/mod_mime.rb new file mode 100644 index 0000000..890dcec --- /dev/null +++ b/cookbooks/apache2/recipes/mod_mime.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_mime +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'mime' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_mime_magic.rb b/cookbooks/apache2/recipes/mod_mime_magic.rb new file mode 100644 index 0000000..5fb23cb --- /dev/null +++ b/cookbooks/apache2/recipes/mod_mime_magic.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_mime_magic +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'mime_magic' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_negotiation.rb b/cookbooks/apache2/recipes/mod_negotiation.rb new file mode 100644 index 0000000..ba26f89 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_negotiation.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_negotiation +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'negotiation' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_pagespeed.rb b/cookbooks/apache2/recipes/mod_pagespeed.rb new file mode 100644 index 0000000..5e7bb72 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_pagespeed.rb @@ -0,0 +1,37 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_pagespeed +# +# Copyright:: 2013, ZOZI +# +# 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. +# + +if platform_family?('debian') + remote_file "#{Chef::Config[:file_cache_path]}/mod-pagespeed.deb" do + source node['apache2']['mod_pagespeed']['package_link'] + mode '0644' + action :create_if_missing + end + + package 'mod_pagespeed' do + source "#{Chef::Config[:file_cache_path]}/mod-pagespeed.deb" + action :install + end + + apache_module 'pagespeed' do + conf true + end +else + Chef::Log.warn "apache::mod_pagespeed does not support #{node['platform_family']} yet, and is not being installed" +end diff --git a/cookbooks/apache2/recipes/mod_perl.rb b/cookbooks/apache2/recipes/mod_perl.rb new file mode 100644 index 0000000..f2c8027 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_perl.rb @@ -0,0 +1,59 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_perl +# +# adapted from the mod_python recipe by Jeremy Bingham +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +case node['platform_family'] +when 'debian' + %w(libapache2-mod-perl2 libapache2-request-perl).each do |pkg| + package pkg + end + if node['platform'] == 'ubuntu' && node['platform_version'].to_f <= 14.04 + package 'apache2-mpm-prefork' + end + if node['platform'] == 'debian' && node['platform_version'].to_f <= 8 + package 'apache2-mpm-prefork' + end +when 'suse' + package 'apache2-mod_perl' do + notifies :run, 'execute[generate-module-list]', :immediately + end + + package 'perl-Apache2-Request' +when 'rhel', 'fedora', 'amazon' + package 'mod_perl' do + notifies :run, 'execute[generate-module-list]', :immediately + end + + package 'perl-libapreq2' +when 'freebsd' + if node['apache']['version'] == '2.4' + package 'ap24-mod_perl2' + else + package 'ap22-mod_perl2' + end + package 'p5-libapreq2' +end + +file "#{node['apache']['dir']}/conf.d/perl.conf" do + content '# conf is under mods-available/perl.conf - apache2 cookbook\n' + only_if { ::Dir.exist?("#{node['apache']['dir']}/conf.d") } +end + +apache_module 'perl' diff --git a/cookbooks/apache2/recipes/mod_php.rb b/cookbooks/apache2/recipes/mod_php.rb new file mode 100644 index 0000000..20b10f2 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_php.rb @@ -0,0 +1,101 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_php5 +# +# Copyright:: 2008-2013, Chef Software, Inc. +# Copyright:: 2014, OneHealth Solutions, Inc. +# Copyright:: 2014, Viverae, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if node['apache']['mpm'] != 'prefork' + Chef::Log.warn('apache2::mod_php generally is expected to be run under a non-threaded MPM, such as prefork') + Chef::Log.warn('See http://php.net/manual/en/faq.installation.php#faq.installation.apache2') + Chef::Log.warn("Currently the apache2 cookbook is configured to use the '#{node['apache']['mpm']}' MPM") +end + +case node['platform_family'] +when 'debian' + if node['platform'] == 'ubuntu' && node['platform_version'].to_f < 16.04 + package 'libapache2-mod-php5' + elsif node['platform'] == 'debian' && node['platform_version'].to_f < 9 + package 'libapache2-mod-php5' + else + package 'libapache2-mod-php' + end +when 'arch' + package 'php-apache' do + notifies :run, 'execute[generate-module-list]', :immediately + end +when 'rhel', 'amazon' + package 'which' + package 'php package' do + if node['platform_version'].to_f < 6.0 && node['platform'] != 'amazon' + package_name 'php53' + else + package_name 'php' + end + notifies :run, 'execute[generate-module-list]', :immediately + not_if 'which php' + end +when 'fedora' + package 'which' + package 'php' do + notifies :run, 'execute[generate-module-list]', :immediately + not_if 'which php' + end +when 'suse' + package 'which' + package 'php' do + notifies :run, 'execute[generate-module-list]', :immediately + not_if 'which php' + end +when 'freebsd' + %w(php56 libxml2).each do |pkg| + package pkg + end + %w(mod_php56).each do |pkg| + package pkg do + options '-I' + end + end +end unless node['apache']['mod_php']['install_method'] == 'source' + +case node['platform_family'] +when 'debian' + # on debian plaform_family php creates newly named incompatible config + file "#{node['apache']['dir']}/mods-available/php7.0.conf" do + content '# conf is under mods-available/php.conf - apache2 cookbook\n' + end + + file "#{node['apache']['dir']}/mods-available/php7.0.load" do + content '# conf is under mods-available/php.load - apache2 cookbook\n' + end +when 'rhel', 'fedora', 'suse', 'amazon' + file "#{node['apache']['dir']}/conf.d/php.conf" do + content '# conf is under mods-available/php.conf - apache2 cookbook\n' + only_if { ::Dir.exist?("#{node['apache']['dir']}/conf.d") } + end +end + +template "#{node['apache']['dir']}/mods-available/php.conf" do + source 'mods/php.conf.erb' + mode '0644' + notifies :reload, 'service[apache2]', :delayed +end + +apache_module node['apache']['mod_php']['module_name'] do + conf false + filename node['apache']['mod_php']['so_filename'] +end diff --git a/cookbooks/apache2/recipes/mod_php5.rb b/cookbooks/apache2/recipes/mod_php5.rb new file mode 100644 index 0000000..b14bb41 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_php5.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_php5 +# +# Copyright:: 2008-2013, Chef Software, Inc. +# Copyright:: 2014, OneHealth Solutions, Inc. +# Copyright:: 2014, Viverae, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +log 'apache2::mod_php5 is deprecated in favor of apache2::mod_php. Please adjust your cookbooks' +include_recipe 'apache2::mod_php' diff --git a/cookbooks/apache2/recipes/mod_privileges.rb b/cookbooks/apache2/recipes/mod_privileges.rb new file mode 100644 index 0000000..d122cb3 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_privileges.rb @@ -0,0 +1,26 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_privileges +# +# Copyright:: 2016, Alexander van Zoest +# +# 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. +# + +# https://httpd.apache.org/docs/trunk/mod/mod_privileges.html +# Available in Apache 2.3 and up, on Solaris 10 and OpenSolaris platforms +if node['apache']['version'] == '2.4' && node['platform_family'] == 'solaris' + apache_module 'privileges' +else + log 'Ignoring apache2::mod_privileges. Not available until apache 2.3 and only on Solaris' +end diff --git a/cookbooks/apache2/recipes/mod_proxy.rb b/cookbooks/apache2/recipes/mod_proxy.rb new file mode 100644 index 0000000..d936d24 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_proxy.rb @@ -0,0 +1,25 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_proxy +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'proxy' do + conf true + if node['platform'] == 'ubuntu' && node['platform_version'].to_f == 12.04 + restart true + end +end diff --git a/cookbooks/apache2/recipes/mod_proxy_ajp.rb b/cookbooks/apache2/recipes/mod_proxy_ajp.rb new file mode 100644 index 0000000..ae5f6f9 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_proxy_ajp.rb @@ -0,0 +1,21 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_proxy_ajp +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'apache2::mod_proxy' +apache_module 'proxy_ajp' diff --git a/cookbooks/apache2/recipes/mod_proxy_balancer.rb b/cookbooks/apache2/recipes/mod_proxy_balancer.rb new file mode 100644 index 0000000..2c4725d --- /dev/null +++ b/cookbooks/apache2/recipes/mod_proxy_balancer.rb @@ -0,0 +1,27 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_proxy_balancer +# +# Copyright:: 2008-2013, Chef Software, Inc. +# Copyright:: 2014, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if !platform_family?('freebsd') && node['apache']['version'] == '2.4' + include_recipe 'apache2::mod_slotmem_shm' +end + +apache_module 'proxy_balancer' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_proxy_connect.rb b/cookbooks/apache2/recipes/mod_proxy_connect.rb new file mode 100644 index 0000000..3822afb --- /dev/null +++ b/cookbooks/apache2/recipes/mod_proxy_connect.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_proxy_connect +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'proxy_connect' diff --git a/cookbooks/apache2/recipes/mod_proxy_express.rb b/cookbooks/apache2/recipes/mod_proxy_express.rb new file mode 100644 index 0000000..642a22a --- /dev/null +++ b/cookbooks/apache2/recipes/mod_proxy_express.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_proxy_express +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'proxy_express' diff --git a/cookbooks/apache2/recipes/mod_proxy_fcgi.rb b/cookbooks/apache2/recipes/mod_proxy_fcgi.rb new file mode 100644 index 0000000..1f795c2 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_proxy_fcgi.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_proxy_fcgi +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'proxy_fcgi' diff --git a/cookbooks/apache2/recipes/mod_proxy_fdpass.rb b/cookbooks/apache2/recipes/mod_proxy_fdpass.rb new file mode 100644 index 0000000..8a976bb --- /dev/null +++ b/cookbooks/apache2/recipes/mod_proxy_fdpass.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_proxy_fdpass +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'proxy_fdpass' diff --git a/cookbooks/apache2/recipes/mod_proxy_ftp.rb b/cookbooks/apache2/recipes/mod_proxy_ftp.rb new file mode 100644 index 0000000..59e3def --- /dev/null +++ b/cookbooks/apache2/recipes/mod_proxy_ftp.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_proxy_ftp +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'proxy_ftp' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_proxy_html.rb b/cookbooks/apache2/recipes/mod_proxy_html.rb new file mode 100644 index 0000000..68f456b --- /dev/null +++ b/cookbooks/apache2/recipes/mod_proxy_html.rb @@ -0,0 +1,25 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_proxy_html +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# Copyright:: 2015, Alexander van Zoest +# +# 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. +# + +if node['apache']['version'] != '2.4' && node['platform_family'] == 'debian' + package 'libapache2-mod-proxy-html' +end + +apache_module 'proxy_html' diff --git a/cookbooks/apache2/recipes/mod_proxy_http.rb b/cookbooks/apache2/recipes/mod_proxy_http.rb new file mode 100644 index 0000000..c1db7d6 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_proxy_http.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_proxy_http +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'apache2::mod_proxy' + +apache_module 'proxy_http' diff --git a/cookbooks/apache2/recipes/mod_proxy_scgi.rb b/cookbooks/apache2/recipes/mod_proxy_scgi.rb new file mode 100644 index 0000000..75f500c --- /dev/null +++ b/cookbooks/apache2/recipes/mod_proxy_scgi.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_proxy_scgi +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'proxy_scgi' diff --git a/cookbooks/apache2/recipes/mod_proxy_wstunnel.rb b/cookbooks/apache2/recipes/mod_proxy_wstunnel.rb new file mode 100644 index 0000000..316fecc --- /dev/null +++ b/cookbooks/apache2/recipes/mod_proxy_wstunnel.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_proxy_wstunnel +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'proxy_wstunnel' diff --git a/cookbooks/apache2/recipes/mod_python.rb b/cookbooks/apache2/recipes/mod_python.rb new file mode 100644 index 0000000..84d30a1 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_python.rb @@ -0,0 +1,44 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_python +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +case node['platform_family'] +when 'debian' + package 'libapache2-mod-python' +when 'suse' + package 'apache2-mod_python' do + notifies :run, 'execute[generate-module-list]', :immediately + end +when 'rhel', 'fedora', 'amazon' + package 'mod_python' do + notifies :run, 'execute[generate-module-list]', :immediately + end +when 'freebsd' + if node['apache']['version'] == '2.4' + package 'ap24-mod_python35' + else + package 'ap22-mod_python35' + end +end + +file "#{node['apache']['dir']}/conf.d/python.conf" do + content '# conf is under mods-available/python.conf - apache2 cookbook\n' + only_if { ::Dir.exist?("#{node['apache']['dir']}/conf.d") } +end + +apache_module 'python' diff --git a/cookbooks/apache2/recipes/mod_ratelimit.rb b/cookbooks/apache2/recipes/mod_ratelimit.rb new file mode 100644 index 0000000..ca00bf4 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_ratelimit.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_ratelimit +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'ratelimit' diff --git a/cookbooks/apache2/recipes/mod_reflector.rb b/cookbooks/apache2/recipes/mod_reflector.rb new file mode 100644 index 0000000..c495f49 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_reflector.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_reflector +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'reflector' diff --git a/cookbooks/apache2/recipes/mod_remoteip.rb b/cookbooks/apache2/recipes/mod_remoteip.rb new file mode 100644 index 0000000..d55cfb5 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_remoteip.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_remoteip +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'remoteip' diff --git a/cookbooks/apache2/recipes/mod_reqtimeout.rb b/cookbooks/apache2/recipes/mod_reqtimeout.rb new file mode 100644 index 0000000..5e157d9 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_reqtimeout.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_reqtimeout +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'reqtimeout' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_request.rb b/cookbooks/apache2/recipes/mod_request.rb new file mode 100644 index 0000000..5b65513 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_request.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_request +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'request' diff --git a/cookbooks/apache2/recipes/mod_rewrite.rb b/cookbooks/apache2/recipes/mod_rewrite.rb new file mode 100644 index 0000000..11c2b11 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_rewrite.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_rewrite +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'rewrite' diff --git a/cookbooks/apache2/recipes/mod_sed.rb b/cookbooks/apache2/recipes/mod_sed.rb new file mode 100644 index 0000000..5a4f2d8 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_sed.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_sed +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'sed' diff --git a/cookbooks/apache2/recipes/mod_session.rb b/cookbooks/apache2/recipes/mod_session.rb new file mode 100644 index 0000000..7d88cd6 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_session.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_session +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'session' diff --git a/cookbooks/apache2/recipes/mod_session_cookie.rb b/cookbooks/apache2/recipes/mod_session_cookie.rb new file mode 100644 index 0000000..cf12a8e --- /dev/null +++ b/cookbooks/apache2/recipes/mod_session_cookie.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_session_cookie +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'session_cookie' diff --git a/cookbooks/apache2/recipes/mod_session_crypto.rb b/cookbooks/apache2/recipes/mod_session_crypto.rb new file mode 100644 index 0000000..12c0db2 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_session_crypto.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_session_crypto +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'session_crypto' diff --git a/cookbooks/apache2/recipes/mod_session_dbd.rb b/cookbooks/apache2/recipes/mod_session_dbd.rb new file mode 100644 index 0000000..218de64 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_session_dbd.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_session_dbd +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'session_dbd' diff --git a/cookbooks/apache2/recipes/mod_setenvif.rb b/cookbooks/apache2/recipes/mod_setenvif.rb new file mode 100644 index 0000000..e5847f5 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_setenvif.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_setenvif +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'setenvif' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_slotmem_plain.rb b/cookbooks/apache2/recipes/mod_slotmem_plain.rb new file mode 100644 index 0000000..45bdd26 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_slotmem_plain.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_slotmem_plain +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'slotmem_plain' diff --git a/cookbooks/apache2/recipes/mod_slotmem_shm.rb b/cookbooks/apache2/recipes/mod_slotmem_shm.rb new file mode 100644 index 0000000..774cf85 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_slotmem_shm.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_slotmem_shm +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'slotmem_shm' diff --git a/cookbooks/apache2/recipes/mod_socache_dbm.rb b/cookbooks/apache2/recipes/mod_socache_dbm.rb new file mode 100644 index 0000000..6aead61 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_socache_dbm.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_socache_dbm +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'socache_dbm' diff --git a/cookbooks/apache2/recipes/mod_socache_dc.rb b/cookbooks/apache2/recipes/mod_socache_dc.rb new file mode 100644 index 0000000..0bbda31 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_socache_dc.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_socache_dc +# +# Copyright:: 2016, Alexander van Zoest +# +# 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. +# + +apache_module 'socache_dc' diff --git a/cookbooks/apache2/recipes/mod_socache_memcache.rb b/cookbooks/apache2/recipes/mod_socache_memcache.rb new file mode 100644 index 0000000..0897b98 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_socache_memcache.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_socache_memcache +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'socache_memcache' diff --git a/cookbooks/apache2/recipes/mod_socache_shmcb.rb b/cookbooks/apache2/recipes/mod_socache_shmcb.rb new file mode 100644 index 0000000..31733fe --- /dev/null +++ b/cookbooks/apache2/recipes/mod_socache_shmcb.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_socache_shmcb +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'socache_shmcb' diff --git a/cookbooks/apache2/recipes/mod_speling.rb b/cookbooks/apache2/recipes/mod_speling.rb new file mode 100644 index 0000000..b4b74c5 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_speling.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_speling +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'speling' diff --git a/cookbooks/apache2/recipes/mod_ssl.rb b/cookbooks/apache2/recipes/mod_ssl.rb new file mode 100644 index 0000000..9b34516 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_ssl.rb @@ -0,0 +1,50 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_ssl +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +if node['apache']['listen'] == ['*:80'] + node.default['apache']['listen'] = ['*:80', "*:#{node['apache']['mod_ssl']['port']}"] +end + +include_recipe 'apache2::default' + +if platform_family?('rhel', 'fedora', 'suse', 'amazon') + package node['apache']['mod_ssl']['pkg_name'] do + notifies :run, 'execute[generate-module-list]', :immediately + not_if { platform_family?('suse') } + end + + file "#{node['apache']['dir']}/conf.d/ssl.conf" do + content '# SSL Conf is under mods-available/ssl.conf - apache2 cookbook\n' + only_if { ::Dir.exist?("#{node['apache']['dir']}/conf.d") } + end +end + +template 'ssl_ports.conf' do + path "#{node['apache']['dir']}/ports.conf" + source 'ports.conf.erb' + mode '0644' + notifies :restart, 'service[apache2]', :delayed +end + +apache_module 'ssl' do + conf true +end + +if node['apache']['version'] == '2.4' + include_recipe 'apache2::mod_socache_shmcb' +end diff --git a/cookbooks/apache2/recipes/mod_status.rb b/cookbooks/apache2/recipes/mod_status.rb new file mode 100644 index 0000000..6ec4f0c --- /dev/null +++ b/cookbooks/apache2/recipes/mod_status.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_status +# +# Copyright:: 2008-2012, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'status' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_substitute.rb b/cookbooks/apache2/recipes/mod_substitute.rb new file mode 100644 index 0000000..e10cb53 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_substitute.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_substitute +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'substitute' diff --git a/cookbooks/apache2/recipes/mod_suexec.rb b/cookbooks/apache2/recipes/mod_suexec.rb new file mode 100644 index 0000000..94213d5 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_suexec.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_suexec +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'suexec' diff --git a/cookbooks/apache2/recipes/mod_systemd.rb b/cookbooks/apache2/recipes/mod_systemd.rb new file mode 100644 index 0000000..11fdd4b --- /dev/null +++ b/cookbooks/apache2/recipes/mod_systemd.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_systemd +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'systemd' diff --git a/cookbooks/apache2/recipes/mod_unique_id.rb b/cookbooks/apache2/recipes/mod_unique_id.rb new file mode 100644 index 0000000..27e1cb2 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_unique_id.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_unique_id +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'unique_id' diff --git a/cookbooks/apache2/recipes/mod_unixd.rb b/cookbooks/apache2/recipes/mod_unixd.rb new file mode 100644 index 0000000..56891a1 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_unixd.rb @@ -0,0 +1,25 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_unixd +# +# Copyright:: 2014, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# on platform_family debian this module is staticly linked into apache2 +if node['apache']['version'] == '2.4' && !platform_family?('debian') + apache_module 'unixd' +else + log 'Ignoring apache2::mod_unixd. Not available until apache 2.4' +end diff --git a/cookbooks/apache2/recipes/mod_userdir.rb b/cookbooks/apache2/recipes/mod_userdir.rb new file mode 100644 index 0000000..d56f676 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_userdir.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_userdir +# +# Copyright:: 2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'userdir' do + conf true +end diff --git a/cookbooks/apache2/recipes/mod_usertrack.rb b/cookbooks/apache2/recipes/mod_usertrack.rb new file mode 100644 index 0000000..2315d12 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_usertrack.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_usertrack +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'usertrack' diff --git a/cookbooks/apache2/recipes/mod_version.rb b/cookbooks/apache2/recipes/mod_version.rb new file mode 100644 index 0000000..baad18c --- /dev/null +++ b/cookbooks/apache2/recipes/mod_version.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_version +# +# Copyright:: 2016, Alexander van Zoest +# +# 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. +# + +apache_module 'version' diff --git a/cookbooks/apache2/recipes/mod_vhost_alias.rb b/cookbooks/apache2/recipes/mod_vhost_alias.rb new file mode 100644 index 0000000..5029b04 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_vhost_alias.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_vhost_alias +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'vhost_alias' diff --git a/cookbooks/apache2/recipes/mod_watchdog.rb b/cookbooks/apache2/recipes/mod_watchdog.rb new file mode 100644 index 0000000..18f8030 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_watchdog.rb @@ -0,0 +1,23 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_watchdog +# +# Copyright:: 2016, Alexander van Zoest +# +# 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. +# + +# http://httpd.apache.org/docs/2.4/mod/mod_watchdog.html +# To allow a module to use mod_watchdog functionality be loaded before the calling module. +# see https://github.com/sous-chefs/apache2/issues/224 +apache_module 'watchdog' diff --git a/cookbooks/apache2/recipes/mod_wsgi.rb b/cookbooks/apache2/recipes/mod_wsgi.rb new file mode 100644 index 0000000..024d6d4 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_wsgi.rb @@ -0,0 +1,34 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_wsgi +# +# Copyright:: 2008-2013, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +case node['platform_family'] +when 'debian' + package 'libapache2-mod-wsgi' +when 'rhel', 'fedora', 'arch', 'amazon' + package 'mod_wsgi' do + notifies :run, 'execute[generate-module-list]', :immediately + end +end + +file "#{node['apache']['dir']}/conf.d/wsgi.conf" do + content '# conf is under mods-available/wsgi.conf - apache2 cookbook\n' + only_if { ::Dir.exist?("#{node['apache']['dir']}/conf.d") } +end + +apache_module 'wsgi' diff --git a/cookbooks/apache2/recipes/mod_xml2enc.rb b/cookbooks/apache2/recipes/mod_xml2enc.rb new file mode 100644 index 0000000..b39a2e8 --- /dev/null +++ b/cookbooks/apache2/recipes/mod_xml2enc.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_xml2enc +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apache_module 'xml2enc' diff --git a/cookbooks/apache2/recipes/mod_xsendfile.rb b/cookbooks/apache2/recipes/mod_xsendfile.rb new file mode 100644 index 0000000..a33ee0f --- /dev/null +++ b/cookbooks/apache2/recipes/mod_xsendfile.rb @@ -0,0 +1,38 @@ +# +# Cookbook:: apache2 +# Recipe:: mod_xsendfile +# +# Copyright:: 2011-2013, CustomInk, LLC. +# +# 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. +# + +case node['platform_family'] +when 'suse' + package 'apache2-mod_xsendfile' do + notifies :run, 'execute[generate-module-list]', :immediately + end +when 'debian' + package 'libapache2-mod-xsendfile' +when 'rhel', 'fedora', 'amazon' + package 'mod_xsendfile' do + notifies :run, 'execute[generate-module-list]', :immediately + end +end + +file "#{node['apache']['dir']}/conf.d/xsendfile.conf" do + content '# conf is under mods-available/xsendfile.conf - apache2 cookbook\n' + only_if { ::Dir.exist?("#{node['apache']['dir']}/conf.d") } +end + +apache_module 'xsendfile' diff --git a/cookbooks/apache2/recipes/mpm_event.rb b/cookbooks/apache2/recipes/mpm_event.rb new file mode 100644 index 0000000..b806d3e --- /dev/null +++ b/cookbooks/apache2/recipes/mpm_event.rb @@ -0,0 +1,27 @@ +# +# Cookbook:: apache2 +# Recipe:: mpm_event +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# apache_module('mpm_itk') { enable false } +apache_module('mpm_prefork') { enable false } +apache_module('mpm_worker') { enable false } + +apache_module 'mpm_event' do + conf true + restart true +end diff --git a/cookbooks/apache2/recipes/mpm_prefork.rb b/cookbooks/apache2/recipes/mpm_prefork.rb new file mode 100644 index 0000000..6a0d025 --- /dev/null +++ b/cookbooks/apache2/recipes/mpm_prefork.rb @@ -0,0 +1,27 @@ +# +# Cookbook:: apache2 +# Recipe:: mpm_prefork +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# apache_module('mpm_itk') { enable false } +apache_module('mpm_event') { enable false } +apache_module('mpm_worker') { enable false } + +apache_module 'mpm_prefork' do + conf true + restart true +end diff --git a/cookbooks/apache2/recipes/mpm_worker.rb b/cookbooks/apache2/recipes/mpm_worker.rb new file mode 100644 index 0000000..755a77a --- /dev/null +++ b/cookbooks/apache2/recipes/mpm_worker.rb @@ -0,0 +1,27 @@ +# +# Cookbook:: apache2 +# Recipe:: mpm_worker +# +# Copyright:: 2013, OneHealth Solutions, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# apache_module('mpm_itk') { enable false } +apache_module('mpm_event') { enable false } +apache_module('mpm_prefork') { enable false } + +apache_module 'mpm_worker' do + conf true + restart true +end diff --git a/cookbooks/apache2/templates/default/a2disconf.erb b/cookbooks/apache2/templates/default/a2disconf.erb new file mode 100644 index 0000000..aec9f23 --- /dev/null +++ b/cookbooks/apache2/templates/default/a2disconf.erb @@ -0,0 +1,532 @@ +#!<%= node['platform_family'] == 'freebsd' ? '/usr/local/bin/perl' : '/usr/bin/perl'%> -w +# +# a2enmod by Stefan Fritsch +# Licensed under Apache License 2.0 +# +# The coding style is "perltidy -pbp" + +use strict; +use Cwd 'realpath'; +use File::Spec; +use File::Basename; +use File::Path; +use Getopt::Long; + +my $quiet; +my $force; +my $maintmode; +my $purge; + +Getopt::Long::Configure('bundling'); +GetOptions( + 'quiet|q' => \$quiet, + 'force|f' => \$force, + 'maintmode|m' => \$maintmode, + 'purge|p' => \$purge +) or exit 2; + +my $basename = basename($0); +$basename =~ /^a2(en|dis)(mod|site|conf)((?:-.+)?)$/ + or die "$basename call name unknown\n"; +my $act = $1; +my $obj = $2; +my $dir_suffix = $3; + +my $env_file = $ENV{APACHE_ENVVARS} + || ( + $ENV{APACHE_CONFDIR} + ? "$ENV{APACHE_CONFDIR}/envvars" + : "<%= node['apache']['dir'] %>$dir_suffix/envvars" + ); +$ENV{LANG} = 'C'; +read_env_file($env_file); + +$act .= 'able'; +my ( $name, $dir, $sffx, $reload ); +if ( $obj eq 'mod' ) { + $obj = 'module'; + $dir = 'mods'; + $sffx = '.load'; + $reload = 'restart'; +} +elsif ( $obj eq 'conf' ) { + $obj = 'conf'; + $dir = 'conf'; + $sffx = '.conf'; + $reload = 'reload'; +} +else { + $dir = 'sites'; + $sffx = '.conf'; + $reload = 'reload'; +} +$name = ucfirst($obj); + +my $confdir = $ENV{APACHE_CONFDIR} || "<%= node['apache']['dir'] %>$dir_suffix"; +my $availdir = $ENV{ uc("APACHE_${dir}_AVAILABLE") } + || "$confdir/$dir-available"; +my $enabldir = $ENV{ uc("APACHE_${dir}_ENABLED") } || "$confdir/$dir-enabled"; +my $statedir = $ENV{ uc("APACHE_STATE_DIRECTORY") } || "<%= node['apache']['lib_dir'] %>"; + +$statedir .= "/$obj"; + +my $choicedir = $act eq 'enable' ? $availdir : $enabldir; +my $linkdir = File::Spec->abs2rel( $availdir, $enabldir ); + +my $request_reload = 0; + +my $rc = 0; + +if ( !scalar @ARGV ) { + my @choices = myglob('*'); + print "Your choices are: @choices\n"; + print "Which ${obj}(s) do you want to $act (wildcards ok)?\n"; + my $input = <>; + @ARGV = split /\s+/, $input; + +} + +my @objs; +foreach my $arg (@ARGV) { + $arg =~ s/${sffx}$//; + my @glob = myglob($arg); + if ( !@glob ) { + error("No $obj found matching $arg!\n"); + $rc = 1; + } + else { + push @objs, @glob; + } +} + +foreach my $acton (@objs) { + doit($acton) or $rc = 1; +} + +info( + "To activate the new configuration, you need to run:\n service apache2 $reload\n" +) if $request_reload; + +exit($rc); + +############################################################################## + +sub myglob { + my $arg = shift; + + my @glob = map { + s{^$choicedir/}{}; + s{$sffx$}{}; + $_ + } glob("$choicedir/$arg$sffx"); + + return @glob; +} + +sub doit { + my $acton = shift; + + my ( $conftgt, $conflink ); + if ( $obj eq 'module' ) { + if ( $acton eq 'cgi' && threaded() ) { + print + "Your MPM seems to be threaded. Selecting cgid instead of cgi.\n"; + $acton = 'cgid'; + } + + $conftgt = "$availdir/$acton.conf"; + if ( -e $conftgt ) { + $conflink = "$enabldir/$acton.conf"; + } + } + + my $tgt = "$availdir/$acton$sffx"; + my $link = "$enabldir/$acton$sffx"; + + if ( !-e $tgt ) { + if ( -l $link && !-e $link ) { + if ( $act eq 'disable' ) { + info("removing dangling symlink $link\n"); + unlink($link); + + # force a .conf path. It may exist as dangling link, too + $conflink = "$enabldir/$acton.conf"; + + if ( -l $conflink && !-e $conflink ) { + info("removing dangling symlink $conflink\n"); + unlink($conflink); + } + + return 1; + } + else { + error("$link is a dangling symlink!\n"); + } + } + + if ( $purge ) { + switch_marker( $obj, $act, $acton ); + # exit silently, we are purging anyway + return 1; + } + + error("$name $acton does not exist!\n"); + return 0; + } + + # handle module dependencies + if ( $obj eq 'module' ) { + if ( $act eq 'enable' ) { + if ( $acton eq 'mpm_itk' ) { + warning( "MPM_ITK is a third party module that is not part " + . "of the official Apache HTTPD. It has seen less " + . "testing than the official MPM modules." ); + } + my @depends = get_deps("$availdir/$acton.load"); + do_deps( $acton, @depends ) or return 0; + + my @conflicts = get_deps( "$availdir/$acton.load", "Conflicts" ); + check_conflicts( $acton, @conflicts ) or return 0; + } + else { + my @depending; + foreach my $d ( glob("$enabldir/*.load") ) { + my @deps = get_deps($d); + if ( is_in( $acton, @deps ) ) { + $d =~ m,/([^/]+).load$,; + push @depending, $1; + } + } + if ( scalar @depending ) { + if ($force) { + do_deps( $acton, @depending ) or return 0; + } + else { + error( + "The following modules depend on $acton ", + "and need to be disabled first: @depending\n" + ); + return 0; + } + } + } + } + elsif ( $act eq 'enable' ) { + my @depends = get_deps("$availdir/$acton$sffx"); + warn_deps( $acton, @depends ) or return 0; + } + + if ( $act eq 'enable' ) { + my $check = check_link( $tgt, $link ); + if ( $check eq 'ok' ) { + if ($conflink) { + + # handle .conf file + my $confcheck = check_link( $conftgt, $conflink ); + if ( $confcheck eq 'ok' ) { + info("$name $acton already enabled\n"); + return 1; + } + elsif ( $confcheck eq 'missing' ) { + print "Enabling config file $acton.conf.\n"; + add_link( $conftgt, $conflink ) or return 0; + } + else { + error( + "Config file $acton.conf not properly enabled: $confcheck\n" + ); + return 0; + } + } + else { + info("$name $acton already enabled\n"); + return 1; + } + } + elsif ( $check eq 'missing' ) { + if ($conflink) { + + # handle .conf file + my $confcheck = check_link( $conftgt, $conflink ); + if ( $confcheck eq 'missing' ) { + add_link( $conftgt, $conflink ) or return 0; + } + elsif ( $confcheck ne 'ok' ) { + error( + "Config file $acton.conf not properly enabled: $confcheck\n" + ); + return 0; + } + } + + print "Enabling $obj $acton.\n"; + if ( $acton eq 'ssl' ) { + info( "See /usr/share/doc/apache2/README.Debian.gz on " + . "how to configure SSL and create self-signed certificates.\n" + ); + } + return add_link( $tgt, $link ) + && switch_marker( $obj, $act, $acton ); + } + else { + error("$name $acton not properly enabled: $check\n"); + return 0; + } + } + else { + if ( -e $link || -l $link ) { + remove_link($link); + if ( $conflink && -e $conflink ) { + remove_link($conflink); + } + switch_marker( $obj, $act, $acton ); + print "$name $acton disabled.\n"; + } + elsif ( $conflink && -e $conflink ) { + print "Disabling stale config file $acton.conf.\n"; + remove_link($conflink); + } + else { + info("$name $acton already disabled\n"); + if ( $purge ) { + switch_marker( $obj, $act, $acton ); + } + return 1; + } + } + + return 1; +} + +sub get_deps { + my $file = shift; + my $type = shift || "Depends"; + + my $fd; + if ( !open( $fd, '<', $file ) ) { + error("Can't open $file: $!"); + return; + } + my $line; + while ( defined( $line = <$fd> ) ) { + chomp $line; + if ( $line =~ /^# $type:\s+(.*?)\s*$/ ) { + my $deps = $1; + return split( /[\n\s]+/, $deps ); + } + + # only check until the first non-empty non-comment line + last if ( $line !~ /^\s*(?:#.*)?$/ ); + } + return; +} + +sub do_deps { + my $acton = shift; + foreach my $d (@_) { + info("Considering dependency $d for $acton:\n"); + if ( !doit($d) ) { + error("Could not $act dependency $d for $acton, aborting\n"); + return 0; + } + } + return 1; +} + +sub warn_deps { + my $acton = shift; + my $modsenabldir = $ENV{APACHE_MODS_ENABLED} || "$confdir/mods-enabled"; + foreach my $d (@_) { + info("Checking dependency $d for $acton:\n"); + if ( !-e "$modsenabldir/$d.load" ) { + warning( + "Module $d is not enabled, but $acton depends on it, aborting\n" + ); + return 0; + } + } + return 1; +} + +sub check_conflicts { + my $acton = shift; + my $haderror = 0; + foreach my $d (@_) { + info("Considering conflict $d for $acton:\n"); + + my $tgt = "$availdir/$d$sffx"; + my $link = "$enabldir/$d$sffx"; + + my $confcheck = check_link( $tgt, $link ); + if ( $confcheck eq 'ok' ) { + error( + "Module $d is enabled - cannot proceed due to conflicts. It needs to be disabled first!\n" + ); + + # Don't return immediately, there could be several conflicts + $haderror++; + } + } + + if ($haderror) { + return 0; + } + + return 1; +} + +sub add_link { + my ( $tgt, $link ) = @_; + + # create relative link + if ( !symlink( File::Spec->abs2rel( $tgt, dirname($link) ), $link ) ) { + die("Could not create $link: $!\n"); + } + $request_reload = 1; + return 1; +} + +sub check_link { + my ( $tgt, $link ) = @_; + + if ( !-e $link ) { + if ( -l $link ) { + + # points to nowhere + info("Removing dangling link $link"); + unlink($link) or die "Could not remove $link\n"; + } + return 'missing'; + } + + if ( -e $link && !-l $link ) { + return "$link is a real file, not touching it"; + } + if ( realpath($link) ne realpath($tgt) ) { + return "$link exists but does not point to $tgt, not touching it"; + } + return 'ok'; +} + +sub remove_link { + my ($link) = @_; + + if ( -l $link ) { + unlink($link) or die "Could not remove $link: $!\n"; + } + elsif ( -e $link ) { + error("$link is not a symbolic link, not deleting\n"); + return 0; + } + $request_reload = 1; + return 1; +} + +sub threaded { + my $result = ""; + $result = qx{<%= node['apache']['apachectl'] %> -V | grep 'threaded'} + if -x '<%= node['apache']['apachectl'] %>'; + if ( $? != 0 ) { + + # config doesn't work + if ( -e "$enabldir/mpm_prefork.load" || -e "$enabldir/mpm_itk.load" ) + { + return 0; + } + elsif (-e "$enabldir/mpm_worker.load" + || -e "$enabldir/mpm_event.load" ) + { + return 1; + } + else { + error("Can't determine enabled MPM"); + + # do what user requested + return 0; + } + } + if ( $result =~ / no/ ) { + return 0; + } + elsif ( $result =~ / yes/ ) { + return 1; + } + else { + die("Can't parse output from apache2ctl -V:\n$result\n"); + } +} + +sub info { + print @_ if !$quiet; +} + +sub error { + print STDERR 'ERROR: ', @_; +} + +sub warning { + print STDERR 'WARNING: ', @_; +} + +sub is_in { + my $needle = shift; + foreach my $e (@_) { + return 1 if $needle eq $e; + } + return 0; +} + +sub read_env_file { + my $file = shift; + + -r $file or return; + my @lines = qx{env - sh -c '. $file && env'}; + if ($?) { + die "Could not read $file\n"; + } + + foreach my $l (@lines) { + chomp $l; + $l =~ /^(.*)?=(.*)$/ or die "Could not parse $file\n"; + $ENV{$1} = $2; + } +} + +sub switch_marker { + die('usage: switch_marker([module|site|conf], [enable|disable], $name)') + if @_ != 3; + my $which = shift; + my $what = shift; + my $name = shift; + + my $mode = "admin"; + $mode = "maint" if $maintmode; + + #print("switch_marker $which $what $name\n"); + # TODO: get rid of the magic string(s) + my $state_marker_dir = "$statedir/$what" . "d" . "_by_$mode"; + my $state_marker = "$state_marker_dir/$name"; + if ( !-d $state_marker_dir ) { + File::Path::mkpath("$state_marker_dir") + || error( + "Failed to create marker directory: '$state_marker_dir'\n"); + } + + # XXX: swap find with perl alternative + my @markers = qx{find "$statedir" -type f -a -name "$name"}; + chomp(@markers); + foreach (@markers) { + unless ( unlink $_ ) { + error("Failed to remove old marker '$_'!\n") && return 0; + } + } + unless ($purge) { + qx{touch "$state_marker"}; + if ( $? != 0 ) { + error("Failed to create marker '$state_marker'!\n") && return 0; + } + return 1; + } +} + +# vim: syntax=perl sw=4 sts=4 sr et diff --git a/cookbooks/apache2/templates/default/a2dismod.erb b/cookbooks/apache2/templates/default/a2dismod.erb new file mode 100644 index 0000000..aec9f23 --- /dev/null +++ b/cookbooks/apache2/templates/default/a2dismod.erb @@ -0,0 +1,532 @@ +#!<%= node['platform_family'] == 'freebsd' ? '/usr/local/bin/perl' : '/usr/bin/perl'%> -w +# +# a2enmod by Stefan Fritsch +# Licensed under Apache License 2.0 +# +# The coding style is "perltidy -pbp" + +use strict; +use Cwd 'realpath'; +use File::Spec; +use File::Basename; +use File::Path; +use Getopt::Long; + +my $quiet; +my $force; +my $maintmode; +my $purge; + +Getopt::Long::Configure('bundling'); +GetOptions( + 'quiet|q' => \$quiet, + 'force|f' => \$force, + 'maintmode|m' => \$maintmode, + 'purge|p' => \$purge +) or exit 2; + +my $basename = basename($0); +$basename =~ /^a2(en|dis)(mod|site|conf)((?:-.+)?)$/ + or die "$basename call name unknown\n"; +my $act = $1; +my $obj = $2; +my $dir_suffix = $3; + +my $env_file = $ENV{APACHE_ENVVARS} + || ( + $ENV{APACHE_CONFDIR} + ? "$ENV{APACHE_CONFDIR}/envvars" + : "<%= node['apache']['dir'] %>$dir_suffix/envvars" + ); +$ENV{LANG} = 'C'; +read_env_file($env_file); + +$act .= 'able'; +my ( $name, $dir, $sffx, $reload ); +if ( $obj eq 'mod' ) { + $obj = 'module'; + $dir = 'mods'; + $sffx = '.load'; + $reload = 'restart'; +} +elsif ( $obj eq 'conf' ) { + $obj = 'conf'; + $dir = 'conf'; + $sffx = '.conf'; + $reload = 'reload'; +} +else { + $dir = 'sites'; + $sffx = '.conf'; + $reload = 'reload'; +} +$name = ucfirst($obj); + +my $confdir = $ENV{APACHE_CONFDIR} || "<%= node['apache']['dir'] %>$dir_suffix"; +my $availdir = $ENV{ uc("APACHE_${dir}_AVAILABLE") } + || "$confdir/$dir-available"; +my $enabldir = $ENV{ uc("APACHE_${dir}_ENABLED") } || "$confdir/$dir-enabled"; +my $statedir = $ENV{ uc("APACHE_STATE_DIRECTORY") } || "<%= node['apache']['lib_dir'] %>"; + +$statedir .= "/$obj"; + +my $choicedir = $act eq 'enable' ? $availdir : $enabldir; +my $linkdir = File::Spec->abs2rel( $availdir, $enabldir ); + +my $request_reload = 0; + +my $rc = 0; + +if ( !scalar @ARGV ) { + my @choices = myglob('*'); + print "Your choices are: @choices\n"; + print "Which ${obj}(s) do you want to $act (wildcards ok)?\n"; + my $input = <>; + @ARGV = split /\s+/, $input; + +} + +my @objs; +foreach my $arg (@ARGV) { + $arg =~ s/${sffx}$//; + my @glob = myglob($arg); + if ( !@glob ) { + error("No $obj found matching $arg!\n"); + $rc = 1; + } + else { + push @objs, @glob; + } +} + +foreach my $acton (@objs) { + doit($acton) or $rc = 1; +} + +info( + "To activate the new configuration, you need to run:\n service apache2 $reload\n" +) if $request_reload; + +exit($rc); + +############################################################################## + +sub myglob { + my $arg = shift; + + my @glob = map { + s{^$choicedir/}{}; + s{$sffx$}{}; + $_ + } glob("$choicedir/$arg$sffx"); + + return @glob; +} + +sub doit { + my $acton = shift; + + my ( $conftgt, $conflink ); + if ( $obj eq 'module' ) { + if ( $acton eq 'cgi' && threaded() ) { + print + "Your MPM seems to be threaded. Selecting cgid instead of cgi.\n"; + $acton = 'cgid'; + } + + $conftgt = "$availdir/$acton.conf"; + if ( -e $conftgt ) { + $conflink = "$enabldir/$acton.conf"; + } + } + + my $tgt = "$availdir/$acton$sffx"; + my $link = "$enabldir/$acton$sffx"; + + if ( !-e $tgt ) { + if ( -l $link && !-e $link ) { + if ( $act eq 'disable' ) { + info("removing dangling symlink $link\n"); + unlink($link); + + # force a .conf path. It may exist as dangling link, too + $conflink = "$enabldir/$acton.conf"; + + if ( -l $conflink && !-e $conflink ) { + info("removing dangling symlink $conflink\n"); + unlink($conflink); + } + + return 1; + } + else { + error("$link is a dangling symlink!\n"); + } + } + + if ( $purge ) { + switch_marker( $obj, $act, $acton ); + # exit silently, we are purging anyway + return 1; + } + + error("$name $acton does not exist!\n"); + return 0; + } + + # handle module dependencies + if ( $obj eq 'module' ) { + if ( $act eq 'enable' ) { + if ( $acton eq 'mpm_itk' ) { + warning( "MPM_ITK is a third party module that is not part " + . "of the official Apache HTTPD. It has seen less " + . "testing than the official MPM modules." ); + } + my @depends = get_deps("$availdir/$acton.load"); + do_deps( $acton, @depends ) or return 0; + + my @conflicts = get_deps( "$availdir/$acton.load", "Conflicts" ); + check_conflicts( $acton, @conflicts ) or return 0; + } + else { + my @depending; + foreach my $d ( glob("$enabldir/*.load") ) { + my @deps = get_deps($d); + if ( is_in( $acton, @deps ) ) { + $d =~ m,/([^/]+).load$,; + push @depending, $1; + } + } + if ( scalar @depending ) { + if ($force) { + do_deps( $acton, @depending ) or return 0; + } + else { + error( + "The following modules depend on $acton ", + "and need to be disabled first: @depending\n" + ); + return 0; + } + } + } + } + elsif ( $act eq 'enable' ) { + my @depends = get_deps("$availdir/$acton$sffx"); + warn_deps( $acton, @depends ) or return 0; + } + + if ( $act eq 'enable' ) { + my $check = check_link( $tgt, $link ); + if ( $check eq 'ok' ) { + if ($conflink) { + + # handle .conf file + my $confcheck = check_link( $conftgt, $conflink ); + if ( $confcheck eq 'ok' ) { + info("$name $acton already enabled\n"); + return 1; + } + elsif ( $confcheck eq 'missing' ) { + print "Enabling config file $acton.conf.\n"; + add_link( $conftgt, $conflink ) or return 0; + } + else { + error( + "Config file $acton.conf not properly enabled: $confcheck\n" + ); + return 0; + } + } + else { + info("$name $acton already enabled\n"); + return 1; + } + } + elsif ( $check eq 'missing' ) { + if ($conflink) { + + # handle .conf file + my $confcheck = check_link( $conftgt, $conflink ); + if ( $confcheck eq 'missing' ) { + add_link( $conftgt, $conflink ) or return 0; + } + elsif ( $confcheck ne 'ok' ) { + error( + "Config file $acton.conf not properly enabled: $confcheck\n" + ); + return 0; + } + } + + print "Enabling $obj $acton.\n"; + if ( $acton eq 'ssl' ) { + info( "See /usr/share/doc/apache2/README.Debian.gz on " + . "how to configure SSL and create self-signed certificates.\n" + ); + } + return add_link( $tgt, $link ) + && switch_marker( $obj, $act, $acton ); + } + else { + error("$name $acton not properly enabled: $check\n"); + return 0; + } + } + else { + if ( -e $link || -l $link ) { + remove_link($link); + if ( $conflink && -e $conflink ) { + remove_link($conflink); + } + switch_marker( $obj, $act, $acton ); + print "$name $acton disabled.\n"; + } + elsif ( $conflink && -e $conflink ) { + print "Disabling stale config file $acton.conf.\n"; + remove_link($conflink); + } + else { + info("$name $acton already disabled\n"); + if ( $purge ) { + switch_marker( $obj, $act, $acton ); + } + return 1; + } + } + + return 1; +} + +sub get_deps { + my $file = shift; + my $type = shift || "Depends"; + + my $fd; + if ( !open( $fd, '<', $file ) ) { + error("Can't open $file: $!"); + return; + } + my $line; + while ( defined( $line = <$fd> ) ) { + chomp $line; + if ( $line =~ /^# $type:\s+(.*?)\s*$/ ) { + my $deps = $1; + return split( /[\n\s]+/, $deps ); + } + + # only check until the first non-empty non-comment line + last if ( $line !~ /^\s*(?:#.*)?$/ ); + } + return; +} + +sub do_deps { + my $acton = shift; + foreach my $d (@_) { + info("Considering dependency $d for $acton:\n"); + if ( !doit($d) ) { + error("Could not $act dependency $d for $acton, aborting\n"); + return 0; + } + } + return 1; +} + +sub warn_deps { + my $acton = shift; + my $modsenabldir = $ENV{APACHE_MODS_ENABLED} || "$confdir/mods-enabled"; + foreach my $d (@_) { + info("Checking dependency $d for $acton:\n"); + if ( !-e "$modsenabldir/$d.load" ) { + warning( + "Module $d is not enabled, but $acton depends on it, aborting\n" + ); + return 0; + } + } + return 1; +} + +sub check_conflicts { + my $acton = shift; + my $haderror = 0; + foreach my $d (@_) { + info("Considering conflict $d for $acton:\n"); + + my $tgt = "$availdir/$d$sffx"; + my $link = "$enabldir/$d$sffx"; + + my $confcheck = check_link( $tgt, $link ); + if ( $confcheck eq 'ok' ) { + error( + "Module $d is enabled - cannot proceed due to conflicts. It needs to be disabled first!\n" + ); + + # Don't return immediately, there could be several conflicts + $haderror++; + } + } + + if ($haderror) { + return 0; + } + + return 1; +} + +sub add_link { + my ( $tgt, $link ) = @_; + + # create relative link + if ( !symlink( File::Spec->abs2rel( $tgt, dirname($link) ), $link ) ) { + die("Could not create $link: $!\n"); + } + $request_reload = 1; + return 1; +} + +sub check_link { + my ( $tgt, $link ) = @_; + + if ( !-e $link ) { + if ( -l $link ) { + + # points to nowhere + info("Removing dangling link $link"); + unlink($link) or die "Could not remove $link\n"; + } + return 'missing'; + } + + if ( -e $link && !-l $link ) { + return "$link is a real file, not touching it"; + } + if ( realpath($link) ne realpath($tgt) ) { + return "$link exists but does not point to $tgt, not touching it"; + } + return 'ok'; +} + +sub remove_link { + my ($link) = @_; + + if ( -l $link ) { + unlink($link) or die "Could not remove $link: $!\n"; + } + elsif ( -e $link ) { + error("$link is not a symbolic link, not deleting\n"); + return 0; + } + $request_reload = 1; + return 1; +} + +sub threaded { + my $result = ""; + $result = qx{<%= node['apache']['apachectl'] %> -V | grep 'threaded'} + if -x '<%= node['apache']['apachectl'] %>'; + if ( $? != 0 ) { + + # config doesn't work + if ( -e "$enabldir/mpm_prefork.load" || -e "$enabldir/mpm_itk.load" ) + { + return 0; + } + elsif (-e "$enabldir/mpm_worker.load" + || -e "$enabldir/mpm_event.load" ) + { + return 1; + } + else { + error("Can't determine enabled MPM"); + + # do what user requested + return 0; + } + } + if ( $result =~ / no/ ) { + return 0; + } + elsif ( $result =~ / yes/ ) { + return 1; + } + else { + die("Can't parse output from apache2ctl -V:\n$result\n"); + } +} + +sub info { + print @_ if !$quiet; +} + +sub error { + print STDERR 'ERROR: ', @_; +} + +sub warning { + print STDERR 'WARNING: ', @_; +} + +sub is_in { + my $needle = shift; + foreach my $e (@_) { + return 1 if $needle eq $e; + } + return 0; +} + +sub read_env_file { + my $file = shift; + + -r $file or return; + my @lines = qx{env - sh -c '. $file && env'}; + if ($?) { + die "Could not read $file\n"; + } + + foreach my $l (@lines) { + chomp $l; + $l =~ /^(.*)?=(.*)$/ or die "Could not parse $file\n"; + $ENV{$1} = $2; + } +} + +sub switch_marker { + die('usage: switch_marker([module|site|conf], [enable|disable], $name)') + if @_ != 3; + my $which = shift; + my $what = shift; + my $name = shift; + + my $mode = "admin"; + $mode = "maint" if $maintmode; + + #print("switch_marker $which $what $name\n"); + # TODO: get rid of the magic string(s) + my $state_marker_dir = "$statedir/$what" . "d" . "_by_$mode"; + my $state_marker = "$state_marker_dir/$name"; + if ( !-d $state_marker_dir ) { + File::Path::mkpath("$state_marker_dir") + || error( + "Failed to create marker directory: '$state_marker_dir'\n"); + } + + # XXX: swap find with perl alternative + my @markers = qx{find "$statedir" -type f -a -name "$name"}; + chomp(@markers); + foreach (@markers) { + unless ( unlink $_ ) { + error("Failed to remove old marker '$_'!\n") && return 0; + } + } + unless ($purge) { + qx{touch "$state_marker"}; + if ( $? != 0 ) { + error("Failed to create marker '$state_marker'!\n") && return 0; + } + return 1; + } +} + +# vim: syntax=perl sw=4 sts=4 sr et diff --git a/cookbooks/apache2/templates/default/a2dissite.erb b/cookbooks/apache2/templates/default/a2dissite.erb new file mode 100644 index 0000000..aec9f23 --- /dev/null +++ b/cookbooks/apache2/templates/default/a2dissite.erb @@ -0,0 +1,532 @@ +#!<%= node['platform_family'] == 'freebsd' ? '/usr/local/bin/perl' : '/usr/bin/perl'%> -w +# +# a2enmod by Stefan Fritsch +# Licensed under Apache License 2.0 +# +# The coding style is "perltidy -pbp" + +use strict; +use Cwd 'realpath'; +use File::Spec; +use File::Basename; +use File::Path; +use Getopt::Long; + +my $quiet; +my $force; +my $maintmode; +my $purge; + +Getopt::Long::Configure('bundling'); +GetOptions( + 'quiet|q' => \$quiet, + 'force|f' => \$force, + 'maintmode|m' => \$maintmode, + 'purge|p' => \$purge +) or exit 2; + +my $basename = basename($0); +$basename =~ /^a2(en|dis)(mod|site|conf)((?:-.+)?)$/ + or die "$basename call name unknown\n"; +my $act = $1; +my $obj = $2; +my $dir_suffix = $3; + +my $env_file = $ENV{APACHE_ENVVARS} + || ( + $ENV{APACHE_CONFDIR} + ? "$ENV{APACHE_CONFDIR}/envvars" + : "<%= node['apache']['dir'] %>$dir_suffix/envvars" + ); +$ENV{LANG} = 'C'; +read_env_file($env_file); + +$act .= 'able'; +my ( $name, $dir, $sffx, $reload ); +if ( $obj eq 'mod' ) { + $obj = 'module'; + $dir = 'mods'; + $sffx = '.load'; + $reload = 'restart'; +} +elsif ( $obj eq 'conf' ) { + $obj = 'conf'; + $dir = 'conf'; + $sffx = '.conf'; + $reload = 'reload'; +} +else { + $dir = 'sites'; + $sffx = '.conf'; + $reload = 'reload'; +} +$name = ucfirst($obj); + +my $confdir = $ENV{APACHE_CONFDIR} || "<%= node['apache']['dir'] %>$dir_suffix"; +my $availdir = $ENV{ uc("APACHE_${dir}_AVAILABLE") } + || "$confdir/$dir-available"; +my $enabldir = $ENV{ uc("APACHE_${dir}_ENABLED") } || "$confdir/$dir-enabled"; +my $statedir = $ENV{ uc("APACHE_STATE_DIRECTORY") } || "<%= node['apache']['lib_dir'] %>"; + +$statedir .= "/$obj"; + +my $choicedir = $act eq 'enable' ? $availdir : $enabldir; +my $linkdir = File::Spec->abs2rel( $availdir, $enabldir ); + +my $request_reload = 0; + +my $rc = 0; + +if ( !scalar @ARGV ) { + my @choices = myglob('*'); + print "Your choices are: @choices\n"; + print "Which ${obj}(s) do you want to $act (wildcards ok)?\n"; + my $input = <>; + @ARGV = split /\s+/, $input; + +} + +my @objs; +foreach my $arg (@ARGV) { + $arg =~ s/${sffx}$//; + my @glob = myglob($arg); + if ( !@glob ) { + error("No $obj found matching $arg!\n"); + $rc = 1; + } + else { + push @objs, @glob; + } +} + +foreach my $acton (@objs) { + doit($acton) or $rc = 1; +} + +info( + "To activate the new configuration, you need to run:\n service apache2 $reload\n" +) if $request_reload; + +exit($rc); + +############################################################################## + +sub myglob { + my $arg = shift; + + my @glob = map { + s{^$choicedir/}{}; + s{$sffx$}{}; + $_ + } glob("$choicedir/$arg$sffx"); + + return @glob; +} + +sub doit { + my $acton = shift; + + my ( $conftgt, $conflink ); + if ( $obj eq 'module' ) { + if ( $acton eq 'cgi' && threaded() ) { + print + "Your MPM seems to be threaded. Selecting cgid instead of cgi.\n"; + $acton = 'cgid'; + } + + $conftgt = "$availdir/$acton.conf"; + if ( -e $conftgt ) { + $conflink = "$enabldir/$acton.conf"; + } + } + + my $tgt = "$availdir/$acton$sffx"; + my $link = "$enabldir/$acton$sffx"; + + if ( !-e $tgt ) { + if ( -l $link && !-e $link ) { + if ( $act eq 'disable' ) { + info("removing dangling symlink $link\n"); + unlink($link); + + # force a .conf path. It may exist as dangling link, too + $conflink = "$enabldir/$acton.conf"; + + if ( -l $conflink && !-e $conflink ) { + info("removing dangling symlink $conflink\n"); + unlink($conflink); + } + + return 1; + } + else { + error("$link is a dangling symlink!\n"); + } + } + + if ( $purge ) { + switch_marker( $obj, $act, $acton ); + # exit silently, we are purging anyway + return 1; + } + + error("$name $acton does not exist!\n"); + return 0; + } + + # handle module dependencies + if ( $obj eq 'module' ) { + if ( $act eq 'enable' ) { + if ( $acton eq 'mpm_itk' ) { + warning( "MPM_ITK is a third party module that is not part " + . "of the official Apache HTTPD. It has seen less " + . "testing than the official MPM modules." ); + } + my @depends = get_deps("$availdir/$acton.load"); + do_deps( $acton, @depends ) or return 0; + + my @conflicts = get_deps( "$availdir/$acton.load", "Conflicts" ); + check_conflicts( $acton, @conflicts ) or return 0; + } + else { + my @depending; + foreach my $d ( glob("$enabldir/*.load") ) { + my @deps = get_deps($d); + if ( is_in( $acton, @deps ) ) { + $d =~ m,/([^/]+).load$,; + push @depending, $1; + } + } + if ( scalar @depending ) { + if ($force) { + do_deps( $acton, @depending ) or return 0; + } + else { + error( + "The following modules depend on $acton ", + "and need to be disabled first: @depending\n" + ); + return 0; + } + } + } + } + elsif ( $act eq 'enable' ) { + my @depends = get_deps("$availdir/$acton$sffx"); + warn_deps( $acton, @depends ) or return 0; + } + + if ( $act eq 'enable' ) { + my $check = check_link( $tgt, $link ); + if ( $check eq 'ok' ) { + if ($conflink) { + + # handle .conf file + my $confcheck = check_link( $conftgt, $conflink ); + if ( $confcheck eq 'ok' ) { + info("$name $acton already enabled\n"); + return 1; + } + elsif ( $confcheck eq 'missing' ) { + print "Enabling config file $acton.conf.\n"; + add_link( $conftgt, $conflink ) or return 0; + } + else { + error( + "Config file $acton.conf not properly enabled: $confcheck\n" + ); + return 0; + } + } + else { + info("$name $acton already enabled\n"); + return 1; + } + } + elsif ( $check eq 'missing' ) { + if ($conflink) { + + # handle .conf file + my $confcheck = check_link( $conftgt, $conflink ); + if ( $confcheck eq 'missing' ) { + add_link( $conftgt, $conflink ) or return 0; + } + elsif ( $confcheck ne 'ok' ) { + error( + "Config file $acton.conf not properly enabled: $confcheck\n" + ); + return 0; + } + } + + print "Enabling $obj $acton.\n"; + if ( $acton eq 'ssl' ) { + info( "See /usr/share/doc/apache2/README.Debian.gz on " + . "how to configure SSL and create self-signed certificates.\n" + ); + } + return add_link( $tgt, $link ) + && switch_marker( $obj, $act, $acton ); + } + else { + error("$name $acton not properly enabled: $check\n"); + return 0; + } + } + else { + if ( -e $link || -l $link ) { + remove_link($link); + if ( $conflink && -e $conflink ) { + remove_link($conflink); + } + switch_marker( $obj, $act, $acton ); + print "$name $acton disabled.\n"; + } + elsif ( $conflink && -e $conflink ) { + print "Disabling stale config file $acton.conf.\n"; + remove_link($conflink); + } + else { + info("$name $acton already disabled\n"); + if ( $purge ) { + switch_marker( $obj, $act, $acton ); + } + return 1; + } + } + + return 1; +} + +sub get_deps { + my $file = shift; + my $type = shift || "Depends"; + + my $fd; + if ( !open( $fd, '<', $file ) ) { + error("Can't open $file: $!"); + return; + } + my $line; + while ( defined( $line = <$fd> ) ) { + chomp $line; + if ( $line =~ /^# $type:\s+(.*?)\s*$/ ) { + my $deps = $1; + return split( /[\n\s]+/, $deps ); + } + + # only check until the first non-empty non-comment line + last if ( $line !~ /^\s*(?:#.*)?$/ ); + } + return; +} + +sub do_deps { + my $acton = shift; + foreach my $d (@_) { + info("Considering dependency $d for $acton:\n"); + if ( !doit($d) ) { + error("Could not $act dependency $d for $acton, aborting\n"); + return 0; + } + } + return 1; +} + +sub warn_deps { + my $acton = shift; + my $modsenabldir = $ENV{APACHE_MODS_ENABLED} || "$confdir/mods-enabled"; + foreach my $d (@_) { + info("Checking dependency $d for $acton:\n"); + if ( !-e "$modsenabldir/$d.load" ) { + warning( + "Module $d is not enabled, but $acton depends on it, aborting\n" + ); + return 0; + } + } + return 1; +} + +sub check_conflicts { + my $acton = shift; + my $haderror = 0; + foreach my $d (@_) { + info("Considering conflict $d for $acton:\n"); + + my $tgt = "$availdir/$d$sffx"; + my $link = "$enabldir/$d$sffx"; + + my $confcheck = check_link( $tgt, $link ); + if ( $confcheck eq 'ok' ) { + error( + "Module $d is enabled - cannot proceed due to conflicts. It needs to be disabled first!\n" + ); + + # Don't return immediately, there could be several conflicts + $haderror++; + } + } + + if ($haderror) { + return 0; + } + + return 1; +} + +sub add_link { + my ( $tgt, $link ) = @_; + + # create relative link + if ( !symlink( File::Spec->abs2rel( $tgt, dirname($link) ), $link ) ) { + die("Could not create $link: $!\n"); + } + $request_reload = 1; + return 1; +} + +sub check_link { + my ( $tgt, $link ) = @_; + + if ( !-e $link ) { + if ( -l $link ) { + + # points to nowhere + info("Removing dangling link $link"); + unlink($link) or die "Could not remove $link\n"; + } + return 'missing'; + } + + if ( -e $link && !-l $link ) { + return "$link is a real file, not touching it"; + } + if ( realpath($link) ne realpath($tgt) ) { + return "$link exists but does not point to $tgt, not touching it"; + } + return 'ok'; +} + +sub remove_link { + my ($link) = @_; + + if ( -l $link ) { + unlink($link) or die "Could not remove $link: $!\n"; + } + elsif ( -e $link ) { + error("$link is not a symbolic link, not deleting\n"); + return 0; + } + $request_reload = 1; + return 1; +} + +sub threaded { + my $result = ""; + $result = qx{<%= node['apache']['apachectl'] %> -V | grep 'threaded'} + if -x '<%= node['apache']['apachectl'] %>'; + if ( $? != 0 ) { + + # config doesn't work + if ( -e "$enabldir/mpm_prefork.load" || -e "$enabldir/mpm_itk.load" ) + { + return 0; + } + elsif (-e "$enabldir/mpm_worker.load" + || -e "$enabldir/mpm_event.load" ) + { + return 1; + } + else { + error("Can't determine enabled MPM"); + + # do what user requested + return 0; + } + } + if ( $result =~ / no/ ) { + return 0; + } + elsif ( $result =~ / yes/ ) { + return 1; + } + else { + die("Can't parse output from apache2ctl -V:\n$result\n"); + } +} + +sub info { + print @_ if !$quiet; +} + +sub error { + print STDERR 'ERROR: ', @_; +} + +sub warning { + print STDERR 'WARNING: ', @_; +} + +sub is_in { + my $needle = shift; + foreach my $e (@_) { + return 1 if $needle eq $e; + } + return 0; +} + +sub read_env_file { + my $file = shift; + + -r $file or return; + my @lines = qx{env - sh -c '. $file && env'}; + if ($?) { + die "Could not read $file\n"; + } + + foreach my $l (@lines) { + chomp $l; + $l =~ /^(.*)?=(.*)$/ or die "Could not parse $file\n"; + $ENV{$1} = $2; + } +} + +sub switch_marker { + die('usage: switch_marker([module|site|conf], [enable|disable], $name)') + if @_ != 3; + my $which = shift; + my $what = shift; + my $name = shift; + + my $mode = "admin"; + $mode = "maint" if $maintmode; + + #print("switch_marker $which $what $name\n"); + # TODO: get rid of the magic string(s) + my $state_marker_dir = "$statedir/$what" . "d" . "_by_$mode"; + my $state_marker = "$state_marker_dir/$name"; + if ( !-d $state_marker_dir ) { + File::Path::mkpath("$state_marker_dir") + || error( + "Failed to create marker directory: '$state_marker_dir'\n"); + } + + # XXX: swap find with perl alternative + my @markers = qx{find "$statedir" -type f -a -name "$name"}; + chomp(@markers); + foreach (@markers) { + unless ( unlink $_ ) { + error("Failed to remove old marker '$_'!\n") && return 0; + } + } + unless ($purge) { + qx{touch "$state_marker"}; + if ( $? != 0 ) { + error("Failed to create marker '$state_marker'!\n") && return 0; + } + return 1; + } +} + +# vim: syntax=perl sw=4 sts=4 sr et diff --git a/cookbooks/apache2/templates/default/a2enconf.erb b/cookbooks/apache2/templates/default/a2enconf.erb new file mode 100644 index 0000000..aec9f23 --- /dev/null +++ b/cookbooks/apache2/templates/default/a2enconf.erb @@ -0,0 +1,532 @@ +#!<%= node['platform_family'] == 'freebsd' ? '/usr/local/bin/perl' : '/usr/bin/perl'%> -w +# +# a2enmod by Stefan Fritsch +# Licensed under Apache License 2.0 +# +# The coding style is "perltidy -pbp" + +use strict; +use Cwd 'realpath'; +use File::Spec; +use File::Basename; +use File::Path; +use Getopt::Long; + +my $quiet; +my $force; +my $maintmode; +my $purge; + +Getopt::Long::Configure('bundling'); +GetOptions( + 'quiet|q' => \$quiet, + 'force|f' => \$force, + 'maintmode|m' => \$maintmode, + 'purge|p' => \$purge +) or exit 2; + +my $basename = basename($0); +$basename =~ /^a2(en|dis)(mod|site|conf)((?:-.+)?)$/ + or die "$basename call name unknown\n"; +my $act = $1; +my $obj = $2; +my $dir_suffix = $3; + +my $env_file = $ENV{APACHE_ENVVARS} + || ( + $ENV{APACHE_CONFDIR} + ? "$ENV{APACHE_CONFDIR}/envvars" + : "<%= node['apache']['dir'] %>$dir_suffix/envvars" + ); +$ENV{LANG} = 'C'; +read_env_file($env_file); + +$act .= 'able'; +my ( $name, $dir, $sffx, $reload ); +if ( $obj eq 'mod' ) { + $obj = 'module'; + $dir = 'mods'; + $sffx = '.load'; + $reload = 'restart'; +} +elsif ( $obj eq 'conf' ) { + $obj = 'conf'; + $dir = 'conf'; + $sffx = '.conf'; + $reload = 'reload'; +} +else { + $dir = 'sites'; + $sffx = '.conf'; + $reload = 'reload'; +} +$name = ucfirst($obj); + +my $confdir = $ENV{APACHE_CONFDIR} || "<%= node['apache']['dir'] %>$dir_suffix"; +my $availdir = $ENV{ uc("APACHE_${dir}_AVAILABLE") } + || "$confdir/$dir-available"; +my $enabldir = $ENV{ uc("APACHE_${dir}_ENABLED") } || "$confdir/$dir-enabled"; +my $statedir = $ENV{ uc("APACHE_STATE_DIRECTORY") } || "<%= node['apache']['lib_dir'] %>"; + +$statedir .= "/$obj"; + +my $choicedir = $act eq 'enable' ? $availdir : $enabldir; +my $linkdir = File::Spec->abs2rel( $availdir, $enabldir ); + +my $request_reload = 0; + +my $rc = 0; + +if ( !scalar @ARGV ) { + my @choices = myglob('*'); + print "Your choices are: @choices\n"; + print "Which ${obj}(s) do you want to $act (wildcards ok)?\n"; + my $input = <>; + @ARGV = split /\s+/, $input; + +} + +my @objs; +foreach my $arg (@ARGV) { + $arg =~ s/${sffx}$//; + my @glob = myglob($arg); + if ( !@glob ) { + error("No $obj found matching $arg!\n"); + $rc = 1; + } + else { + push @objs, @glob; + } +} + +foreach my $acton (@objs) { + doit($acton) or $rc = 1; +} + +info( + "To activate the new configuration, you need to run:\n service apache2 $reload\n" +) if $request_reload; + +exit($rc); + +############################################################################## + +sub myglob { + my $arg = shift; + + my @glob = map { + s{^$choicedir/}{}; + s{$sffx$}{}; + $_ + } glob("$choicedir/$arg$sffx"); + + return @glob; +} + +sub doit { + my $acton = shift; + + my ( $conftgt, $conflink ); + if ( $obj eq 'module' ) { + if ( $acton eq 'cgi' && threaded() ) { + print + "Your MPM seems to be threaded. Selecting cgid instead of cgi.\n"; + $acton = 'cgid'; + } + + $conftgt = "$availdir/$acton.conf"; + if ( -e $conftgt ) { + $conflink = "$enabldir/$acton.conf"; + } + } + + my $tgt = "$availdir/$acton$sffx"; + my $link = "$enabldir/$acton$sffx"; + + if ( !-e $tgt ) { + if ( -l $link && !-e $link ) { + if ( $act eq 'disable' ) { + info("removing dangling symlink $link\n"); + unlink($link); + + # force a .conf path. It may exist as dangling link, too + $conflink = "$enabldir/$acton.conf"; + + if ( -l $conflink && !-e $conflink ) { + info("removing dangling symlink $conflink\n"); + unlink($conflink); + } + + return 1; + } + else { + error("$link is a dangling symlink!\n"); + } + } + + if ( $purge ) { + switch_marker( $obj, $act, $acton ); + # exit silently, we are purging anyway + return 1; + } + + error("$name $acton does not exist!\n"); + return 0; + } + + # handle module dependencies + if ( $obj eq 'module' ) { + if ( $act eq 'enable' ) { + if ( $acton eq 'mpm_itk' ) { + warning( "MPM_ITK is a third party module that is not part " + . "of the official Apache HTTPD. It has seen less " + . "testing than the official MPM modules." ); + } + my @depends = get_deps("$availdir/$acton.load"); + do_deps( $acton, @depends ) or return 0; + + my @conflicts = get_deps( "$availdir/$acton.load", "Conflicts" ); + check_conflicts( $acton, @conflicts ) or return 0; + } + else { + my @depending; + foreach my $d ( glob("$enabldir/*.load") ) { + my @deps = get_deps($d); + if ( is_in( $acton, @deps ) ) { + $d =~ m,/([^/]+).load$,; + push @depending, $1; + } + } + if ( scalar @depending ) { + if ($force) { + do_deps( $acton, @depending ) or return 0; + } + else { + error( + "The following modules depend on $acton ", + "and need to be disabled first: @depending\n" + ); + return 0; + } + } + } + } + elsif ( $act eq 'enable' ) { + my @depends = get_deps("$availdir/$acton$sffx"); + warn_deps( $acton, @depends ) or return 0; + } + + if ( $act eq 'enable' ) { + my $check = check_link( $tgt, $link ); + if ( $check eq 'ok' ) { + if ($conflink) { + + # handle .conf file + my $confcheck = check_link( $conftgt, $conflink ); + if ( $confcheck eq 'ok' ) { + info("$name $acton already enabled\n"); + return 1; + } + elsif ( $confcheck eq 'missing' ) { + print "Enabling config file $acton.conf.\n"; + add_link( $conftgt, $conflink ) or return 0; + } + else { + error( + "Config file $acton.conf not properly enabled: $confcheck\n" + ); + return 0; + } + } + else { + info("$name $acton already enabled\n"); + return 1; + } + } + elsif ( $check eq 'missing' ) { + if ($conflink) { + + # handle .conf file + my $confcheck = check_link( $conftgt, $conflink ); + if ( $confcheck eq 'missing' ) { + add_link( $conftgt, $conflink ) or return 0; + } + elsif ( $confcheck ne 'ok' ) { + error( + "Config file $acton.conf not properly enabled: $confcheck\n" + ); + return 0; + } + } + + print "Enabling $obj $acton.\n"; + if ( $acton eq 'ssl' ) { + info( "See /usr/share/doc/apache2/README.Debian.gz on " + . "how to configure SSL and create self-signed certificates.\n" + ); + } + return add_link( $tgt, $link ) + && switch_marker( $obj, $act, $acton ); + } + else { + error("$name $acton not properly enabled: $check\n"); + return 0; + } + } + else { + if ( -e $link || -l $link ) { + remove_link($link); + if ( $conflink && -e $conflink ) { + remove_link($conflink); + } + switch_marker( $obj, $act, $acton ); + print "$name $acton disabled.\n"; + } + elsif ( $conflink && -e $conflink ) { + print "Disabling stale config file $acton.conf.\n"; + remove_link($conflink); + } + else { + info("$name $acton already disabled\n"); + if ( $purge ) { + switch_marker( $obj, $act, $acton ); + } + return 1; + } + } + + return 1; +} + +sub get_deps { + my $file = shift; + my $type = shift || "Depends"; + + my $fd; + if ( !open( $fd, '<', $file ) ) { + error("Can't open $file: $!"); + return; + } + my $line; + while ( defined( $line = <$fd> ) ) { + chomp $line; + if ( $line =~ /^# $type:\s+(.*?)\s*$/ ) { + my $deps = $1; + return split( /[\n\s]+/, $deps ); + } + + # only check until the first non-empty non-comment line + last if ( $line !~ /^\s*(?:#.*)?$/ ); + } + return; +} + +sub do_deps { + my $acton = shift; + foreach my $d (@_) { + info("Considering dependency $d for $acton:\n"); + if ( !doit($d) ) { + error("Could not $act dependency $d for $acton, aborting\n"); + return 0; + } + } + return 1; +} + +sub warn_deps { + my $acton = shift; + my $modsenabldir = $ENV{APACHE_MODS_ENABLED} || "$confdir/mods-enabled"; + foreach my $d (@_) { + info("Checking dependency $d for $acton:\n"); + if ( !-e "$modsenabldir/$d.load" ) { + warning( + "Module $d is not enabled, but $acton depends on it, aborting\n" + ); + return 0; + } + } + return 1; +} + +sub check_conflicts { + my $acton = shift; + my $haderror = 0; + foreach my $d (@_) { + info("Considering conflict $d for $acton:\n"); + + my $tgt = "$availdir/$d$sffx"; + my $link = "$enabldir/$d$sffx"; + + my $confcheck = check_link( $tgt, $link ); + if ( $confcheck eq 'ok' ) { + error( + "Module $d is enabled - cannot proceed due to conflicts. It needs to be disabled first!\n" + ); + + # Don't return immediately, there could be several conflicts + $haderror++; + } + } + + if ($haderror) { + return 0; + } + + return 1; +} + +sub add_link { + my ( $tgt, $link ) = @_; + + # create relative link + if ( !symlink( File::Spec->abs2rel( $tgt, dirname($link) ), $link ) ) { + die("Could not create $link: $!\n"); + } + $request_reload = 1; + return 1; +} + +sub check_link { + my ( $tgt, $link ) = @_; + + if ( !-e $link ) { + if ( -l $link ) { + + # points to nowhere + info("Removing dangling link $link"); + unlink($link) or die "Could not remove $link\n"; + } + return 'missing'; + } + + if ( -e $link && !-l $link ) { + return "$link is a real file, not touching it"; + } + if ( realpath($link) ne realpath($tgt) ) { + return "$link exists but does not point to $tgt, not touching it"; + } + return 'ok'; +} + +sub remove_link { + my ($link) = @_; + + if ( -l $link ) { + unlink($link) or die "Could not remove $link: $!\n"; + } + elsif ( -e $link ) { + error("$link is not a symbolic link, not deleting\n"); + return 0; + } + $request_reload = 1; + return 1; +} + +sub threaded { + my $result = ""; + $result = qx{<%= node['apache']['apachectl'] %> -V | grep 'threaded'} + if -x '<%= node['apache']['apachectl'] %>'; + if ( $? != 0 ) { + + # config doesn't work + if ( -e "$enabldir/mpm_prefork.load" || -e "$enabldir/mpm_itk.load" ) + { + return 0; + } + elsif (-e "$enabldir/mpm_worker.load" + || -e "$enabldir/mpm_event.load" ) + { + return 1; + } + else { + error("Can't determine enabled MPM"); + + # do what user requested + return 0; + } + } + if ( $result =~ / no/ ) { + return 0; + } + elsif ( $result =~ / yes/ ) { + return 1; + } + else { + die("Can't parse output from apache2ctl -V:\n$result\n"); + } +} + +sub info { + print @_ if !$quiet; +} + +sub error { + print STDERR 'ERROR: ', @_; +} + +sub warning { + print STDERR 'WARNING: ', @_; +} + +sub is_in { + my $needle = shift; + foreach my $e (@_) { + return 1 if $needle eq $e; + } + return 0; +} + +sub read_env_file { + my $file = shift; + + -r $file or return; + my @lines = qx{env - sh -c '. $file && env'}; + if ($?) { + die "Could not read $file\n"; + } + + foreach my $l (@lines) { + chomp $l; + $l =~ /^(.*)?=(.*)$/ or die "Could not parse $file\n"; + $ENV{$1} = $2; + } +} + +sub switch_marker { + die('usage: switch_marker([module|site|conf], [enable|disable], $name)') + if @_ != 3; + my $which = shift; + my $what = shift; + my $name = shift; + + my $mode = "admin"; + $mode = "maint" if $maintmode; + + #print("switch_marker $which $what $name\n"); + # TODO: get rid of the magic string(s) + my $state_marker_dir = "$statedir/$what" . "d" . "_by_$mode"; + my $state_marker = "$state_marker_dir/$name"; + if ( !-d $state_marker_dir ) { + File::Path::mkpath("$state_marker_dir") + || error( + "Failed to create marker directory: '$state_marker_dir'\n"); + } + + # XXX: swap find with perl alternative + my @markers = qx{find "$statedir" -type f -a -name "$name"}; + chomp(@markers); + foreach (@markers) { + unless ( unlink $_ ) { + error("Failed to remove old marker '$_'!\n") && return 0; + } + } + unless ($purge) { + qx{touch "$state_marker"}; + if ( $? != 0 ) { + error("Failed to create marker '$state_marker'!\n") && return 0; + } + return 1; + } +} + +# vim: syntax=perl sw=4 sts=4 sr et diff --git a/cookbooks/apache2/templates/default/a2enmod.erb b/cookbooks/apache2/templates/default/a2enmod.erb new file mode 100644 index 0000000..aec9f23 --- /dev/null +++ b/cookbooks/apache2/templates/default/a2enmod.erb @@ -0,0 +1,532 @@ +#!<%= node['platform_family'] == 'freebsd' ? '/usr/local/bin/perl' : '/usr/bin/perl'%> -w +# +# a2enmod by Stefan Fritsch +# Licensed under Apache License 2.0 +# +# The coding style is "perltidy -pbp" + +use strict; +use Cwd 'realpath'; +use File::Spec; +use File::Basename; +use File::Path; +use Getopt::Long; + +my $quiet; +my $force; +my $maintmode; +my $purge; + +Getopt::Long::Configure('bundling'); +GetOptions( + 'quiet|q' => \$quiet, + 'force|f' => \$force, + 'maintmode|m' => \$maintmode, + 'purge|p' => \$purge +) or exit 2; + +my $basename = basename($0); +$basename =~ /^a2(en|dis)(mod|site|conf)((?:-.+)?)$/ + or die "$basename call name unknown\n"; +my $act = $1; +my $obj = $2; +my $dir_suffix = $3; + +my $env_file = $ENV{APACHE_ENVVARS} + || ( + $ENV{APACHE_CONFDIR} + ? "$ENV{APACHE_CONFDIR}/envvars" + : "<%= node['apache']['dir'] %>$dir_suffix/envvars" + ); +$ENV{LANG} = 'C'; +read_env_file($env_file); + +$act .= 'able'; +my ( $name, $dir, $sffx, $reload ); +if ( $obj eq 'mod' ) { + $obj = 'module'; + $dir = 'mods'; + $sffx = '.load'; + $reload = 'restart'; +} +elsif ( $obj eq 'conf' ) { + $obj = 'conf'; + $dir = 'conf'; + $sffx = '.conf'; + $reload = 'reload'; +} +else { + $dir = 'sites'; + $sffx = '.conf'; + $reload = 'reload'; +} +$name = ucfirst($obj); + +my $confdir = $ENV{APACHE_CONFDIR} || "<%= node['apache']['dir'] %>$dir_suffix"; +my $availdir = $ENV{ uc("APACHE_${dir}_AVAILABLE") } + || "$confdir/$dir-available"; +my $enabldir = $ENV{ uc("APACHE_${dir}_ENABLED") } || "$confdir/$dir-enabled"; +my $statedir = $ENV{ uc("APACHE_STATE_DIRECTORY") } || "<%= node['apache']['lib_dir'] %>"; + +$statedir .= "/$obj"; + +my $choicedir = $act eq 'enable' ? $availdir : $enabldir; +my $linkdir = File::Spec->abs2rel( $availdir, $enabldir ); + +my $request_reload = 0; + +my $rc = 0; + +if ( !scalar @ARGV ) { + my @choices = myglob('*'); + print "Your choices are: @choices\n"; + print "Which ${obj}(s) do you want to $act (wildcards ok)?\n"; + my $input = <>; + @ARGV = split /\s+/, $input; + +} + +my @objs; +foreach my $arg (@ARGV) { + $arg =~ s/${sffx}$//; + my @glob = myglob($arg); + if ( !@glob ) { + error("No $obj found matching $arg!\n"); + $rc = 1; + } + else { + push @objs, @glob; + } +} + +foreach my $acton (@objs) { + doit($acton) or $rc = 1; +} + +info( + "To activate the new configuration, you need to run:\n service apache2 $reload\n" +) if $request_reload; + +exit($rc); + +############################################################################## + +sub myglob { + my $arg = shift; + + my @glob = map { + s{^$choicedir/}{}; + s{$sffx$}{}; + $_ + } glob("$choicedir/$arg$sffx"); + + return @glob; +} + +sub doit { + my $acton = shift; + + my ( $conftgt, $conflink ); + if ( $obj eq 'module' ) { + if ( $acton eq 'cgi' && threaded() ) { + print + "Your MPM seems to be threaded. Selecting cgid instead of cgi.\n"; + $acton = 'cgid'; + } + + $conftgt = "$availdir/$acton.conf"; + if ( -e $conftgt ) { + $conflink = "$enabldir/$acton.conf"; + } + } + + my $tgt = "$availdir/$acton$sffx"; + my $link = "$enabldir/$acton$sffx"; + + if ( !-e $tgt ) { + if ( -l $link && !-e $link ) { + if ( $act eq 'disable' ) { + info("removing dangling symlink $link\n"); + unlink($link); + + # force a .conf path. It may exist as dangling link, too + $conflink = "$enabldir/$acton.conf"; + + if ( -l $conflink && !-e $conflink ) { + info("removing dangling symlink $conflink\n"); + unlink($conflink); + } + + return 1; + } + else { + error("$link is a dangling symlink!\n"); + } + } + + if ( $purge ) { + switch_marker( $obj, $act, $acton ); + # exit silently, we are purging anyway + return 1; + } + + error("$name $acton does not exist!\n"); + return 0; + } + + # handle module dependencies + if ( $obj eq 'module' ) { + if ( $act eq 'enable' ) { + if ( $acton eq 'mpm_itk' ) { + warning( "MPM_ITK is a third party module that is not part " + . "of the official Apache HTTPD. It has seen less " + . "testing than the official MPM modules." ); + } + my @depends = get_deps("$availdir/$acton.load"); + do_deps( $acton, @depends ) or return 0; + + my @conflicts = get_deps( "$availdir/$acton.load", "Conflicts" ); + check_conflicts( $acton, @conflicts ) or return 0; + } + else { + my @depending; + foreach my $d ( glob("$enabldir/*.load") ) { + my @deps = get_deps($d); + if ( is_in( $acton, @deps ) ) { + $d =~ m,/([^/]+).load$,; + push @depending, $1; + } + } + if ( scalar @depending ) { + if ($force) { + do_deps( $acton, @depending ) or return 0; + } + else { + error( + "The following modules depend on $acton ", + "and need to be disabled first: @depending\n" + ); + return 0; + } + } + } + } + elsif ( $act eq 'enable' ) { + my @depends = get_deps("$availdir/$acton$sffx"); + warn_deps( $acton, @depends ) or return 0; + } + + if ( $act eq 'enable' ) { + my $check = check_link( $tgt, $link ); + if ( $check eq 'ok' ) { + if ($conflink) { + + # handle .conf file + my $confcheck = check_link( $conftgt, $conflink ); + if ( $confcheck eq 'ok' ) { + info("$name $acton already enabled\n"); + return 1; + } + elsif ( $confcheck eq 'missing' ) { + print "Enabling config file $acton.conf.\n"; + add_link( $conftgt, $conflink ) or return 0; + } + else { + error( + "Config file $acton.conf not properly enabled: $confcheck\n" + ); + return 0; + } + } + else { + info("$name $acton already enabled\n"); + return 1; + } + } + elsif ( $check eq 'missing' ) { + if ($conflink) { + + # handle .conf file + my $confcheck = check_link( $conftgt, $conflink ); + if ( $confcheck eq 'missing' ) { + add_link( $conftgt, $conflink ) or return 0; + } + elsif ( $confcheck ne 'ok' ) { + error( + "Config file $acton.conf not properly enabled: $confcheck\n" + ); + return 0; + } + } + + print "Enabling $obj $acton.\n"; + if ( $acton eq 'ssl' ) { + info( "See /usr/share/doc/apache2/README.Debian.gz on " + . "how to configure SSL and create self-signed certificates.\n" + ); + } + return add_link( $tgt, $link ) + && switch_marker( $obj, $act, $acton ); + } + else { + error("$name $acton not properly enabled: $check\n"); + return 0; + } + } + else { + if ( -e $link || -l $link ) { + remove_link($link); + if ( $conflink && -e $conflink ) { + remove_link($conflink); + } + switch_marker( $obj, $act, $acton ); + print "$name $acton disabled.\n"; + } + elsif ( $conflink && -e $conflink ) { + print "Disabling stale config file $acton.conf.\n"; + remove_link($conflink); + } + else { + info("$name $acton already disabled\n"); + if ( $purge ) { + switch_marker( $obj, $act, $acton ); + } + return 1; + } + } + + return 1; +} + +sub get_deps { + my $file = shift; + my $type = shift || "Depends"; + + my $fd; + if ( !open( $fd, '<', $file ) ) { + error("Can't open $file: $!"); + return; + } + my $line; + while ( defined( $line = <$fd> ) ) { + chomp $line; + if ( $line =~ /^# $type:\s+(.*?)\s*$/ ) { + my $deps = $1; + return split( /[\n\s]+/, $deps ); + } + + # only check until the first non-empty non-comment line + last if ( $line !~ /^\s*(?:#.*)?$/ ); + } + return; +} + +sub do_deps { + my $acton = shift; + foreach my $d (@_) { + info("Considering dependency $d for $acton:\n"); + if ( !doit($d) ) { + error("Could not $act dependency $d for $acton, aborting\n"); + return 0; + } + } + return 1; +} + +sub warn_deps { + my $acton = shift; + my $modsenabldir = $ENV{APACHE_MODS_ENABLED} || "$confdir/mods-enabled"; + foreach my $d (@_) { + info("Checking dependency $d for $acton:\n"); + if ( !-e "$modsenabldir/$d.load" ) { + warning( + "Module $d is not enabled, but $acton depends on it, aborting\n" + ); + return 0; + } + } + return 1; +} + +sub check_conflicts { + my $acton = shift; + my $haderror = 0; + foreach my $d (@_) { + info("Considering conflict $d for $acton:\n"); + + my $tgt = "$availdir/$d$sffx"; + my $link = "$enabldir/$d$sffx"; + + my $confcheck = check_link( $tgt, $link ); + if ( $confcheck eq 'ok' ) { + error( + "Module $d is enabled - cannot proceed due to conflicts. It needs to be disabled first!\n" + ); + + # Don't return immediately, there could be several conflicts + $haderror++; + } + } + + if ($haderror) { + return 0; + } + + return 1; +} + +sub add_link { + my ( $tgt, $link ) = @_; + + # create relative link + if ( !symlink( File::Spec->abs2rel( $tgt, dirname($link) ), $link ) ) { + die("Could not create $link: $!\n"); + } + $request_reload = 1; + return 1; +} + +sub check_link { + my ( $tgt, $link ) = @_; + + if ( !-e $link ) { + if ( -l $link ) { + + # points to nowhere + info("Removing dangling link $link"); + unlink($link) or die "Could not remove $link\n"; + } + return 'missing'; + } + + if ( -e $link && !-l $link ) { + return "$link is a real file, not touching it"; + } + if ( realpath($link) ne realpath($tgt) ) { + return "$link exists but does not point to $tgt, not touching it"; + } + return 'ok'; +} + +sub remove_link { + my ($link) = @_; + + if ( -l $link ) { + unlink($link) or die "Could not remove $link: $!\n"; + } + elsif ( -e $link ) { + error("$link is not a symbolic link, not deleting\n"); + return 0; + } + $request_reload = 1; + return 1; +} + +sub threaded { + my $result = ""; + $result = qx{<%= node['apache']['apachectl'] %> -V | grep 'threaded'} + if -x '<%= node['apache']['apachectl'] %>'; + if ( $? != 0 ) { + + # config doesn't work + if ( -e "$enabldir/mpm_prefork.load" || -e "$enabldir/mpm_itk.load" ) + { + return 0; + } + elsif (-e "$enabldir/mpm_worker.load" + || -e "$enabldir/mpm_event.load" ) + { + return 1; + } + else { + error("Can't determine enabled MPM"); + + # do what user requested + return 0; + } + } + if ( $result =~ / no/ ) { + return 0; + } + elsif ( $result =~ / yes/ ) { + return 1; + } + else { + die("Can't parse output from apache2ctl -V:\n$result\n"); + } +} + +sub info { + print @_ if !$quiet; +} + +sub error { + print STDERR 'ERROR: ', @_; +} + +sub warning { + print STDERR 'WARNING: ', @_; +} + +sub is_in { + my $needle = shift; + foreach my $e (@_) { + return 1 if $needle eq $e; + } + return 0; +} + +sub read_env_file { + my $file = shift; + + -r $file or return; + my @lines = qx{env - sh -c '. $file && env'}; + if ($?) { + die "Could not read $file\n"; + } + + foreach my $l (@lines) { + chomp $l; + $l =~ /^(.*)?=(.*)$/ or die "Could not parse $file\n"; + $ENV{$1} = $2; + } +} + +sub switch_marker { + die('usage: switch_marker([module|site|conf], [enable|disable], $name)') + if @_ != 3; + my $which = shift; + my $what = shift; + my $name = shift; + + my $mode = "admin"; + $mode = "maint" if $maintmode; + + #print("switch_marker $which $what $name\n"); + # TODO: get rid of the magic string(s) + my $state_marker_dir = "$statedir/$what" . "d" . "_by_$mode"; + my $state_marker = "$state_marker_dir/$name"; + if ( !-d $state_marker_dir ) { + File::Path::mkpath("$state_marker_dir") + || error( + "Failed to create marker directory: '$state_marker_dir'\n"); + } + + # XXX: swap find with perl alternative + my @markers = qx{find "$statedir" -type f -a -name "$name"}; + chomp(@markers); + foreach (@markers) { + unless ( unlink $_ ) { + error("Failed to remove old marker '$_'!\n") && return 0; + } + } + unless ($purge) { + qx{touch "$state_marker"}; + if ( $? != 0 ) { + error("Failed to create marker '$state_marker'!\n") && return 0; + } + return 1; + } +} + +# vim: syntax=perl sw=4 sts=4 sr et diff --git a/cookbooks/apache2/templates/default/a2ensite.erb b/cookbooks/apache2/templates/default/a2ensite.erb new file mode 100644 index 0000000..aec9f23 --- /dev/null +++ b/cookbooks/apache2/templates/default/a2ensite.erb @@ -0,0 +1,532 @@ +#!<%= node['platform_family'] == 'freebsd' ? '/usr/local/bin/perl' : '/usr/bin/perl'%> -w +# +# a2enmod by Stefan Fritsch +# Licensed under Apache License 2.0 +# +# The coding style is "perltidy -pbp" + +use strict; +use Cwd 'realpath'; +use File::Spec; +use File::Basename; +use File::Path; +use Getopt::Long; + +my $quiet; +my $force; +my $maintmode; +my $purge; + +Getopt::Long::Configure('bundling'); +GetOptions( + 'quiet|q' => \$quiet, + 'force|f' => \$force, + 'maintmode|m' => \$maintmode, + 'purge|p' => \$purge +) or exit 2; + +my $basename = basename($0); +$basename =~ /^a2(en|dis)(mod|site|conf)((?:-.+)?)$/ + or die "$basename call name unknown\n"; +my $act = $1; +my $obj = $2; +my $dir_suffix = $3; + +my $env_file = $ENV{APACHE_ENVVARS} + || ( + $ENV{APACHE_CONFDIR} + ? "$ENV{APACHE_CONFDIR}/envvars" + : "<%= node['apache']['dir'] %>$dir_suffix/envvars" + ); +$ENV{LANG} = 'C'; +read_env_file($env_file); + +$act .= 'able'; +my ( $name, $dir, $sffx, $reload ); +if ( $obj eq 'mod' ) { + $obj = 'module'; + $dir = 'mods'; + $sffx = '.load'; + $reload = 'restart'; +} +elsif ( $obj eq 'conf' ) { + $obj = 'conf'; + $dir = 'conf'; + $sffx = '.conf'; + $reload = 'reload'; +} +else { + $dir = 'sites'; + $sffx = '.conf'; + $reload = 'reload'; +} +$name = ucfirst($obj); + +my $confdir = $ENV{APACHE_CONFDIR} || "<%= node['apache']['dir'] %>$dir_suffix"; +my $availdir = $ENV{ uc("APACHE_${dir}_AVAILABLE") } + || "$confdir/$dir-available"; +my $enabldir = $ENV{ uc("APACHE_${dir}_ENABLED") } || "$confdir/$dir-enabled"; +my $statedir = $ENV{ uc("APACHE_STATE_DIRECTORY") } || "<%= node['apache']['lib_dir'] %>"; + +$statedir .= "/$obj"; + +my $choicedir = $act eq 'enable' ? $availdir : $enabldir; +my $linkdir = File::Spec->abs2rel( $availdir, $enabldir ); + +my $request_reload = 0; + +my $rc = 0; + +if ( !scalar @ARGV ) { + my @choices = myglob('*'); + print "Your choices are: @choices\n"; + print "Which ${obj}(s) do you want to $act (wildcards ok)?\n"; + my $input = <>; + @ARGV = split /\s+/, $input; + +} + +my @objs; +foreach my $arg (@ARGV) { + $arg =~ s/${sffx}$//; + my @glob = myglob($arg); + if ( !@glob ) { + error("No $obj found matching $arg!\n"); + $rc = 1; + } + else { + push @objs, @glob; + } +} + +foreach my $acton (@objs) { + doit($acton) or $rc = 1; +} + +info( + "To activate the new configuration, you need to run:\n service apache2 $reload\n" +) if $request_reload; + +exit($rc); + +############################################################################## + +sub myglob { + my $arg = shift; + + my @glob = map { + s{^$choicedir/}{}; + s{$sffx$}{}; + $_ + } glob("$choicedir/$arg$sffx"); + + return @glob; +} + +sub doit { + my $acton = shift; + + my ( $conftgt, $conflink ); + if ( $obj eq 'module' ) { + if ( $acton eq 'cgi' && threaded() ) { + print + "Your MPM seems to be threaded. Selecting cgid instead of cgi.\n"; + $acton = 'cgid'; + } + + $conftgt = "$availdir/$acton.conf"; + if ( -e $conftgt ) { + $conflink = "$enabldir/$acton.conf"; + } + } + + my $tgt = "$availdir/$acton$sffx"; + my $link = "$enabldir/$acton$sffx"; + + if ( !-e $tgt ) { + if ( -l $link && !-e $link ) { + if ( $act eq 'disable' ) { + info("removing dangling symlink $link\n"); + unlink($link); + + # force a .conf path. It may exist as dangling link, too + $conflink = "$enabldir/$acton.conf"; + + if ( -l $conflink && !-e $conflink ) { + info("removing dangling symlink $conflink\n"); + unlink($conflink); + } + + return 1; + } + else { + error("$link is a dangling symlink!\n"); + } + } + + if ( $purge ) { + switch_marker( $obj, $act, $acton ); + # exit silently, we are purging anyway + return 1; + } + + error("$name $acton does not exist!\n"); + return 0; + } + + # handle module dependencies + if ( $obj eq 'module' ) { + if ( $act eq 'enable' ) { + if ( $acton eq 'mpm_itk' ) { + warning( "MPM_ITK is a third party module that is not part " + . "of the official Apache HTTPD. It has seen less " + . "testing than the official MPM modules." ); + } + my @depends = get_deps("$availdir/$acton.load"); + do_deps( $acton, @depends ) or return 0; + + my @conflicts = get_deps( "$availdir/$acton.load", "Conflicts" ); + check_conflicts( $acton, @conflicts ) or return 0; + } + else { + my @depending; + foreach my $d ( glob("$enabldir/*.load") ) { + my @deps = get_deps($d); + if ( is_in( $acton, @deps ) ) { + $d =~ m,/([^/]+).load$,; + push @depending, $1; + } + } + if ( scalar @depending ) { + if ($force) { + do_deps( $acton, @depending ) or return 0; + } + else { + error( + "The following modules depend on $acton ", + "and need to be disabled first: @depending\n" + ); + return 0; + } + } + } + } + elsif ( $act eq 'enable' ) { + my @depends = get_deps("$availdir/$acton$sffx"); + warn_deps( $acton, @depends ) or return 0; + } + + if ( $act eq 'enable' ) { + my $check = check_link( $tgt, $link ); + if ( $check eq 'ok' ) { + if ($conflink) { + + # handle .conf file + my $confcheck = check_link( $conftgt, $conflink ); + if ( $confcheck eq 'ok' ) { + info("$name $acton already enabled\n"); + return 1; + } + elsif ( $confcheck eq 'missing' ) { + print "Enabling config file $acton.conf.\n"; + add_link( $conftgt, $conflink ) or return 0; + } + else { + error( + "Config file $acton.conf not properly enabled: $confcheck\n" + ); + return 0; + } + } + else { + info("$name $acton already enabled\n"); + return 1; + } + } + elsif ( $check eq 'missing' ) { + if ($conflink) { + + # handle .conf file + my $confcheck = check_link( $conftgt, $conflink ); + if ( $confcheck eq 'missing' ) { + add_link( $conftgt, $conflink ) or return 0; + } + elsif ( $confcheck ne 'ok' ) { + error( + "Config file $acton.conf not properly enabled: $confcheck\n" + ); + return 0; + } + } + + print "Enabling $obj $acton.\n"; + if ( $acton eq 'ssl' ) { + info( "See /usr/share/doc/apache2/README.Debian.gz on " + . "how to configure SSL and create self-signed certificates.\n" + ); + } + return add_link( $tgt, $link ) + && switch_marker( $obj, $act, $acton ); + } + else { + error("$name $acton not properly enabled: $check\n"); + return 0; + } + } + else { + if ( -e $link || -l $link ) { + remove_link($link); + if ( $conflink && -e $conflink ) { + remove_link($conflink); + } + switch_marker( $obj, $act, $acton ); + print "$name $acton disabled.\n"; + } + elsif ( $conflink && -e $conflink ) { + print "Disabling stale config file $acton.conf.\n"; + remove_link($conflink); + } + else { + info("$name $acton already disabled\n"); + if ( $purge ) { + switch_marker( $obj, $act, $acton ); + } + return 1; + } + } + + return 1; +} + +sub get_deps { + my $file = shift; + my $type = shift || "Depends"; + + my $fd; + if ( !open( $fd, '<', $file ) ) { + error("Can't open $file: $!"); + return; + } + my $line; + while ( defined( $line = <$fd> ) ) { + chomp $line; + if ( $line =~ /^# $type:\s+(.*?)\s*$/ ) { + my $deps = $1; + return split( /[\n\s]+/, $deps ); + } + + # only check until the first non-empty non-comment line + last if ( $line !~ /^\s*(?:#.*)?$/ ); + } + return; +} + +sub do_deps { + my $acton = shift; + foreach my $d (@_) { + info("Considering dependency $d for $acton:\n"); + if ( !doit($d) ) { + error("Could not $act dependency $d for $acton, aborting\n"); + return 0; + } + } + return 1; +} + +sub warn_deps { + my $acton = shift; + my $modsenabldir = $ENV{APACHE_MODS_ENABLED} || "$confdir/mods-enabled"; + foreach my $d (@_) { + info("Checking dependency $d for $acton:\n"); + if ( !-e "$modsenabldir/$d.load" ) { + warning( + "Module $d is not enabled, but $acton depends on it, aborting\n" + ); + return 0; + } + } + return 1; +} + +sub check_conflicts { + my $acton = shift; + my $haderror = 0; + foreach my $d (@_) { + info("Considering conflict $d for $acton:\n"); + + my $tgt = "$availdir/$d$sffx"; + my $link = "$enabldir/$d$sffx"; + + my $confcheck = check_link( $tgt, $link ); + if ( $confcheck eq 'ok' ) { + error( + "Module $d is enabled - cannot proceed due to conflicts. It needs to be disabled first!\n" + ); + + # Don't return immediately, there could be several conflicts + $haderror++; + } + } + + if ($haderror) { + return 0; + } + + return 1; +} + +sub add_link { + my ( $tgt, $link ) = @_; + + # create relative link + if ( !symlink( File::Spec->abs2rel( $tgt, dirname($link) ), $link ) ) { + die("Could not create $link: $!\n"); + } + $request_reload = 1; + return 1; +} + +sub check_link { + my ( $tgt, $link ) = @_; + + if ( !-e $link ) { + if ( -l $link ) { + + # points to nowhere + info("Removing dangling link $link"); + unlink($link) or die "Could not remove $link\n"; + } + return 'missing'; + } + + if ( -e $link && !-l $link ) { + return "$link is a real file, not touching it"; + } + if ( realpath($link) ne realpath($tgt) ) { + return "$link exists but does not point to $tgt, not touching it"; + } + return 'ok'; +} + +sub remove_link { + my ($link) = @_; + + if ( -l $link ) { + unlink($link) or die "Could not remove $link: $!\n"; + } + elsif ( -e $link ) { + error("$link is not a symbolic link, not deleting\n"); + return 0; + } + $request_reload = 1; + return 1; +} + +sub threaded { + my $result = ""; + $result = qx{<%= node['apache']['apachectl'] %> -V | grep 'threaded'} + if -x '<%= node['apache']['apachectl'] %>'; + if ( $? != 0 ) { + + # config doesn't work + if ( -e "$enabldir/mpm_prefork.load" || -e "$enabldir/mpm_itk.load" ) + { + return 0; + } + elsif (-e "$enabldir/mpm_worker.load" + || -e "$enabldir/mpm_event.load" ) + { + return 1; + } + else { + error("Can't determine enabled MPM"); + + # do what user requested + return 0; + } + } + if ( $result =~ / no/ ) { + return 0; + } + elsif ( $result =~ / yes/ ) { + return 1; + } + else { + die("Can't parse output from apache2ctl -V:\n$result\n"); + } +} + +sub info { + print @_ if !$quiet; +} + +sub error { + print STDERR 'ERROR: ', @_; +} + +sub warning { + print STDERR 'WARNING: ', @_; +} + +sub is_in { + my $needle = shift; + foreach my $e (@_) { + return 1 if $needle eq $e; + } + return 0; +} + +sub read_env_file { + my $file = shift; + + -r $file or return; + my @lines = qx{env - sh -c '. $file && env'}; + if ($?) { + die "Could not read $file\n"; + } + + foreach my $l (@lines) { + chomp $l; + $l =~ /^(.*)?=(.*)$/ or die "Could not parse $file\n"; + $ENV{$1} = $2; + } +} + +sub switch_marker { + die('usage: switch_marker([module|site|conf], [enable|disable], $name)') + if @_ != 3; + my $which = shift; + my $what = shift; + my $name = shift; + + my $mode = "admin"; + $mode = "maint" if $maintmode; + + #print("switch_marker $which $what $name\n"); + # TODO: get rid of the magic string(s) + my $state_marker_dir = "$statedir/$what" . "d" . "_by_$mode"; + my $state_marker = "$state_marker_dir/$name"; + if ( !-d $state_marker_dir ) { + File::Path::mkpath("$state_marker_dir") + || error( + "Failed to create marker directory: '$state_marker_dir'\n"); + } + + # XXX: swap find with perl alternative + my @markers = qx{find "$statedir" -type f -a -name "$name"}; + chomp(@markers); + foreach (@markers) { + unless ( unlink $_ ) { + error("Failed to remove old marker '$_'!\n") && return 0; + } + } + unless ($purge) { + qx{touch "$state_marker"}; + if ( $? != 0 ) { + error("Failed to create marker '$state_marker'!\n") && return 0; + } + return 1; + } +} + +# vim: syntax=perl sw=4 sts=4 sr et diff --git a/cookbooks/apache2/templates/default/apache2.conf.erb b/cookbooks/apache2/templates/default/apache2.conf.erb new file mode 100644 index 0000000..13d132d --- /dev/null +++ b/cookbooks/apache2/templates/default/apache2.conf.erb @@ -0,0 +1,260 @@ +# +# Generated by Chef +# +# Based on the Ubuntu apache2.conf + +ServerRoot "<%= node['apache']['dir'] %>" + +# +# The accept serialization lock file MUST BE STORED ON A LOCAL DISK. +# +<% if node['apache']['version'] == '2.2' -%> +LockFile <%= node['apache']['lock_dir'] %>/accept.lock +<% elsif node['apache']['version'] == '2.4' -%> +Mutex file:<%= node['apache']['lock_dir'] %> default +<% end -%> + +# +# PidFile: The file in which the server should record its process +# identification number when it starts. +# +PidFile <%= node['apache']['pid_file'] %> + +# +# Timeout: The number of seconds before receives and sends time out. +# +Timeout <%= node['apache']['timeout'] %> + +# +# KeepAlive: Whether or not to allow persistent connections (more than +# one request per connection). Set to "Off" to deactivate. +# +KeepAlive <%= node['apache']['keepalive'] %> + +# +# MaxKeepAliveRequests: The maximum number of requests to allow +# during a persistent connection. Set to 0 to allow an unlimited amount. +# We recommend you leave this number high, for maximum performance. +# +MaxKeepAliveRequests <%= node['apache']['keepaliverequests'] %> + +# +# KeepAliveTimeout: Number of seconds to wait for the next request from the +# same client on the same connection. +# +KeepAliveTimeout <%= node['apache']['keepalivetimeout'] %> + +# +User <%= node['apache']['user'] %> +Group <%= node['apache']['group'] %> +# + +<% if node['apache']['version'] == '2.4' -%> +# Sets the default security model of the Apache2 HTTPD server. It does +# not allow access to the root filesystem outside of /usr/share and <%= node['apache']['docroot_dir'] %>. +# If your system is serving content from a sub-directory in /srv you must allow +# access in conf-enabled, or in any related virtual host. e.g. +# +# +# Options Indexes FollowSymLinks +# AllowOverride None +# Require all granted +# +# + + Options FollowSymLinks + AllowOverride None + Require all denied + + + + AllowOverride None + Require all granted + + +> + Options Indexes FollowSymLinks + AllowOverride None + Require all granted + +<% end -%> + +# +# AccessFileName: The name of the file to look for in each directory +# for additional configuration directives. See also the AllowOverride +# directive. +# + +AccessFileName <%= node['apache']['access_file_name'] %> + +# +# The following lines prevent .htaccess and .htpasswd files from being +# viewed by Web clients. +# +<% access_file_name_prefix = node['apache']['access_file_name'][0..2] if !node['apache']['access_file_name'].empty? + if access_file_name_prefix != '.ht' + file_name_prefix = '(' + access_file_name_prefix + '|\.ht)' + else + file_name_prefix = '\.ht' + end +%> +"> + <% if node['apache']['version'] == '2.2' -%> + Order allow,deny + Deny from all + <% elsif node['apache']['version'] == '2.4' -%> + Require all denied + <% end -%> + + +<% if node['apache']['version'] == '2.2' -%> +# +# DefaultType is the default MIME type the server will use for a document +# if it cannot otherwise determine one, such as from filename extensions. +# If your server contains mostly text or HTML documents, "text/plain" is +# a good value. If most of your content is binary, such as applications +# or images, you may want to use "application/octet-stream" instead to +# keep browsers from trying to display binary files as though they are +# text. +# +DefaultType text/plain +<% end -%> + +# +# HostnameLookups: Log the names of clients or just their IP addresses +# e.g., www.apache.org (on) or 204.62.129.132 (off). +# The default is off because it'd be overall better for the net if people +# had to knowingly turn this feature on, since enabling it means that +# each client request will result in AT LEAST one lookup request to the +# nameserver. +# +HostnameLookups Off + +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a +# container, error messages relating to that virtual host will be +# logged here. If you *do* define an error logfile for a +# container, that host's errors will be logged there and not here. +# +<% if node['apache']['error_log'] =~ /^syslog:/ || node['apache']['error_log'] =~ /^\|/ %> +ErrorLog <%= node['apache']['error_log'] %> +<% else %> +ErrorLog <%= node['apache']['log_dir'] %>/<%= node['apache']['error_log'] %> +<% end %> + +# +# LogLevel: Control the number of messages logged to the error_log. +# Possible values include: debug, info, notice, warn, error, crit, +# alert, emerg. +# +LogLevel <%= node['apache']['log_level'] %> + +# COOK-1021: Dummy LoadModule directive to aid module installations +#LoadModule dummy_module modules/mod_dummy.so + +# Include module configuration: +<% if node['apache']['version'] == '2.2' -%> +Include <%= node['apache']['dir'] %>/mods-enabled/*.load +Include <%= node['apache']['dir'] %>/mods-enabled/*.conf +<% elsif node['apache']['version'] == '2.4' -%> +IncludeOptional <%= node['apache']['dir'] %>/mods-enabled/*.load +IncludeOptional <%= node['apache']['dir'] %>/mods-enabled/*.conf +<% end -%> + +<% if %w[freebsd].include?(node['platform_family']) -%> + + AcceptFilter http none + AcceptFilter https none + +<% end %> + +# Include ports listing +Include <%= node['apache']['dir'] %>/ports.conf + +# +# The following directives define some format nicknames for use with +# a CustomLog directive (see below). +# +LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined +LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined +LogFormat "%h %l %u %t \"%r\" %>s %b" common +LogFormat "%{Referer}i -> %U" referer +LogFormat "%{User-agent}i" agent +# +<% if node['apache']['version'] == '2.2' -%> +# Customizable error responses come in three flavors: +# 1) plain text 2) local redirects 3) external redirects +# +# Some examples: +#ErrorDocument 500 "The server made a boo boo." +#ErrorDocument 404 /missing.html +#ErrorDocument 404 "/cgi-bin/missing_handler.pl" +#ErrorDocument 402 http://www.example.com/subscription_info.html +# + +# +# Putting this all together, we can internationalize error responses. +# +# We use Alias to redirect any /error/HTTP_.html.var response to +# our collection of by-error message multi-language collections. We use +# includes to substitute the appropriate text. +# +# You can modify the messages' appearance without changing any of the +# default HTTP_.html.var files by adding the line: +# +# Alias /error/include/ "/your/include/path/" +# +# which allows you to create your own set of files by starting with the +# /usr/share/apache2/error/include/ files and copying them to /your/include/path/, +# even on a per-VirtualHost basis. The default include files will display +# your Apache version number and your ServerAdmin email address regardless +# of the setting of ServerSignature. +# +# The internationalized error documents require mod_alias, mod_include +# and mod_negotiation. To activate them, uncomment the following 30 lines. + +# Alias /error/ "/usr/share/apache2/error/" +# +# +# AllowOverride None +# Options IncludesNoExec +# AddOutputFilter Includes html +# AddHandler type-map var +# Order allow,deny +# Allow from all +# LanguagePriority en cs de es fr it nl sv pt-br ro +# ForceLanguagePriority Prefer Fallback +# +# +# ErrorDocument 400 /error/HTTP_BAD_REQUEST.html.var +# ErrorDocument 401 /error/HTTP_UNAUTHORIZED.html.var +# ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var +# ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var +# ErrorDocument 405 /error/HTTP_METHOD_NOT_ALLOWED.html.var +# ErrorDocument 408 /error/HTTP_REQUEST_TIME_OUT.html.var +# ErrorDocument 410 /error/HTTP_GONE.html.var +# ErrorDocument 411 /error/HTTP_LENGTH_REQUIRED.html.var +# ErrorDocument 412 /error/HTTP_PRECONDITION_FAILED.html.var +# ErrorDocument 413 /error/HTTP_REQUEST_ENTITY_TOO_LARGE.html.var +# ErrorDocument 414 /error/HTTP_REQUEST_URI_TOO_LARGE.html.var +# ErrorDocument 415 /error/HTTP_UNSUPPORTED_MEDIA_TYPE.html.var +# ErrorDocument 500 /error/HTTP_INTERNAL_SERVER_ERROR.html.var +# ErrorDocument 501 /error/HTTP_NOT_IMPLEMENTED.html.var +# ErrorDocument 502 /error/HTTP_BAD_GATEWAY.html.var +# ErrorDocument 503 /error/HTTP_SERVICE_UNAVAILABLE.html.var +# ErrorDocument 506 /error/HTTP_VARIANT_ALSO_VARIES.html.var +<% end -%> + +<% if node['apache']['version'] == '2.4' -%> +# Include generic snippets of statements +IncludeOptional <%= node['apache']['dir'] %>/conf-enabled/*.conf + +# Include the virtual host configurations: +IncludeOptional <%= node['apache']['dir'] %>/sites-enabled/*.conf +<% else -%> +# Include generic snippets of statements +Include <%= node['apache']['dir'] %>/conf-enabled/*.conf + +# Include the virtual host configurations: +Include <%= node['apache']['dir'] %>/sites-enabled/*.conf +<% end -%> diff --git a/cookbooks/apache2/templates/default/charset.conf.erb b/cookbooks/apache2/templates/default/charset.conf.erb new file mode 100644 index 0000000..40d7198 --- /dev/null +++ b/cookbooks/apache2/templates/default/charset.conf.erb @@ -0,0 +1,6 @@ +# Read the documentation before enabling AddDefaultCharset. +# In general, it is only a good idea if you know that all your files +# have this encoding. It will override any encoding given in the files +# in meta http-equiv or xml encoding tags. + +#AddDefaultCharset UTF-8 diff --git a/cookbooks/apache2/templates/default/default-site.conf.erb b/cookbooks/apache2/templates/default/default-site.conf.erb new file mode 100644 index 0000000..9ff1961 --- /dev/null +++ b/cookbooks/apache2/templates/default/default-site.conf.erb @@ -0,0 +1,74 @@ +<% if node['apache']['version'] != '2.4' -%> +NameVirtualHost *:<%= node['apache']['default_site_port'] %> +<% end -%> +> + ServerAdmin <%= node['apache']['contact'] %> + + DocumentRoot <%= node['apache']['docroot_dir'] %>/ + + Options FollowSymLinks + AllowOverride None + + + /> + Options Indexes FollowSymLinks MultiViews + AllowOverride None + <% if node['apache']['version'] == '2.4' -%> + Require all granted + # This directive allows us to have apache2's default start page + # in /apache2-default/, but still have / go to the right place + #RedirectMatch ^/$ /apache2-default/ + <% elsif node['apache']['version'] == '2.2' -%> + Order allow,deny + Allow from all + <% end -%> + + + ScriptAlias /cgi-bin/ <%= node['apache']['cgibin_dir'] %>/ + "> + AllowOverride None + Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch + <% if node['apache']['version'] == '2.4' -%> + Require all granted + <% elsif node['apache']['version'] == '2.2' -%> + Order allow,deny + Allow from all + <% end -%> + + + ErrorLog <%= node['apache']['log_dir'] %>/<%= node['apache']['error_log'] %> + + # Possible values include: debug, info, notice, warn, error, crit, + # alert, emerg. + LogLevel <%= node['apache']['log_level'] %> + + CustomLog <%= node['apache']['log_dir'] %>/<%= node['apache']['access_log'] %> combined + ServerSignature On + + Alias /doc/ "/usr/share/doc/" + + Options Indexes MultiViews FollowSymLinks + AllowOverride None + <% if node['apache']['version'] == '2.2' -%> + Order deny,allow + Deny from all + Allow from 127.0.0.0/255.0.0.0 ::1/128 + <% elsif node['apache']['version'] == '2.4' -%> + Require ip 127.0.0.0/255.0.0.0 + Require ip ::1/128 + <% end -%> + + + <% if %w{ rhel fedora amazon }.include?(node['platform_family']) -%> + # + # This configuration file enables the default "Welcome" + # page if there is no default index page present for + # the root URL. To disable the Welcome page, comment + # out all the lines below. + # + + Options -Indexes + ErrorDocument 403 /error/noindex.html + + <% end -%> + diff --git a/cookbooks/apache2/templates/default/envvars.erb b/cookbooks/apache2/templates/default/envvars.erb new file mode 100644 index 0000000..d0bc03c --- /dev/null +++ b/cookbooks/apache2/templates/default/envvars.erb @@ -0,0 +1,43 @@ +# envvars - default environment variables for apache2ctl + +# this won't be correct after changing uid +unset HOME + +# Since there is no sane way to get the parsed apache2 config in scripts, some +# settings are defined via environment variables and then used in apache2ctl, +# /etc/init.d/apache2, /etc/logrotate.d/apache2, etc. +export APACHE_RUN_USER=<%= node['apache']['user'] %> +export APACHE_RUN_GROUP=<%= node['apache']['group'] %> +# temporary state file location. This might be changed to /run in Wheezy+1 +export APACHE_PID_FILE=<%= node['apache']['pid_file'] %> +export APACHE_RUN_DIR=<%= node['apache']['run_dir'] %> +export APACHE_LOCK_DIR=<%= node['apache']['lock_dir'] %> +export APACHE_LOG_DIR=<%= node['apache']['log_dir'] %> + +## The locale used by some modules like mod_dav +<%- if node['apache']['locale'] != 'system' %> +export LANG=<%= node['apache']['locale'] %> +export LC_ALL=<%= node['apache']['locale'] %> +<%- else %> +## Uncomment the following line to use the system default locale instead: +. /etc/default/locale +export LANG +<%- end %> + + +## The command to get the status for 'apache2ctl status'. +## Some packages providing 'www-browser' need '--dump' instead of '-dump'. +#export APACHE_LYNX='www-browser -dump' + +## If you need a higher file descriptor limit, uncomment and adjust the +## following line (default is 8192): +#APACHE_ULIMIT_MAX_FILES='ulimit -n 65536' + +## If you would like to pass arguments to the web server, add them below +## to the APACHE_ARGUMENTS environment. +#export APACHE_ARGUMENTS='' + +## Enable the debug mode for maintainer scripts. +## This will produce a verbose output on package installations of web server modules and web application +## installations which interact with Apache +#export APACHE2_MAINTSCRIPT_DEBUG=1 diff --git a/cookbooks/apache2/templates/default/etc-sysconfig-httpd.erb b/cookbooks/apache2/templates/default/etc-sysconfig-httpd.erb new file mode 100644 index 0000000..71ae7cf --- /dev/null +++ b/cookbooks/apache2/templates/default/etc-sysconfig-httpd.erb @@ -0,0 +1,35 @@ +# This file is managed by Chef. Changes will be overwritten. + +# +# The default processing model (MPM) is the process-based +# 'prefork' model. A thread-based model, 'worker', is also +# available, but does not work with some modules (such as PHP). +# The service must be stopped before changing this variable. +# +HTTPD=<%= node['apache']['binary'] %> + +# +# To pass additional options (for instance, -D definitions) to the +# httpd binary at startup, set OPTIONS here. +# +#OPTIONS= + +# +# By default, the httpd process is started in the C locale; to +# change the locale in which the server runs, the HTTPD_LANG +# variable can be set. +# +HTTPD_LANG=<%= node['apache']['locale'] %> + +# +# By default, the httpd process will create the file +# /var/run/httpd/httpd.pid in which it records its process +# identification number when it starts. If an alternate location is +# specified in httpd.conf (via the PidFile directive), the new +# location needs to be reported in the PIDFILE. +# +PIDFILE=<%= node['apache']['pid_file'] %> + +<% node['apache']['sysconfig_additional_params'].each do |k,v| %> +<%= "#{k}=#{v}" %> +<% end %> diff --git a/cookbooks/apache2/templates/default/mods/README b/cookbooks/apache2/templates/default/mods/README new file mode 100644 index 0000000..df9f0bc --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/README @@ -0,0 +1,2 @@ +These configs are taken from a Debian apache2.2-common 2.2.11-3 install. They +work on CentOS 5.3 with a few conditions using erb. diff --git a/cookbooks/apache2/templates/default/mods/actions.conf.erb b/cookbooks/apache2/templates/default/mods/actions.conf.erb new file mode 100644 index 0000000..147a645 --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/actions.conf.erb @@ -0,0 +1,9 @@ + + # + # Action lets you define media types that will execute a script whenever + # a matching file is called. This eliminates the need for repeated URL + # pathnames for oft-used CGI file processors. + # Format: Action media/type /cgi-script/location + # Format: Action handler-name /cgi-script/location + # + diff --git a/cookbooks/apache2/templates/default/mods/alias.conf.erb b/cookbooks/apache2/templates/default/mods/alias.conf.erb new file mode 100644 index 0000000..80bef61 --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/alias.conf.erb @@ -0,0 +1,27 @@ + + # + # Aliases: Add here as many aliases as you need (with no limit). The format is + # Alias fakename realname + # + # Note that if you include a trailing / on fakename then the server will + # require it to be present in the URL. So "/icons" isn't aliased in this + # example, only "/icons/". If the fakename is slash-terminated, then the + # realname must also be slash terminated, and if the fakename omits the + # trailing slash, the realname must also omit it. + # + # We include the /icons/ alias for FancyIndexed directory listings. If + # you do not use FancyIndexing, you may comment this out. + # + Alias /icons/ "<%= node['apache']['icondir'] %>/" + + "> + Options Indexes MultiViews + AllowOverride None +<% if node['apache']['version'] == "2.4" -%> + Require all granted +<% else -%> + Order allow,deny + Allow from all +<% end -%> + + diff --git a/cookbooks/apache2/templates/default/mods/auth_cas.conf.erb b/cookbooks/apache2/templates/default/mods/auth_cas.conf.erb new file mode 100644 index 0000000..1f23f8e --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/auth_cas.conf.erb @@ -0,0 +1 @@ +CASCookiePath <%= node['apache']['cache_dir'] %>/mod_auth_cas/ diff --git a/cookbooks/apache2/templates/default/mods/auth_cas.load.erb b/cookbooks/apache2/templates/default/mods/auth_cas.load.erb new file mode 100644 index 0000000..5dc31a5 --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/auth_cas.load.erb @@ -0,0 +1 @@ +LoadModule auth_cas_module <%= node['apache']['libexec_dir'] %>/mod_auth_cas.so diff --git a/cookbooks/apache2/templates/default/mods/authopenid.load.erb b/cookbooks/apache2/templates/default/mods/authopenid.load.erb new file mode 100644 index 0000000..7042a7e --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/authopenid.load.erb @@ -0,0 +1 @@ +LoadModule authopenid_module <%= node['apache']['libexec_dir'] %>/mod_auth_openid.so diff --git a/cookbooks/apache2/templates/default/mods/autoindex.conf.erb b/cookbooks/apache2/templates/default/mods/autoindex.conf.erb new file mode 100644 index 0000000..5f86614 --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/autoindex.conf.erb @@ -0,0 +1,100 @@ + + # + # Directives controlling the display of server-generated directory listings. + # + + # + # IndexOptions: Controls the appearance of server-generated directory + # listings. + # Remove/replace the "Charset=UTF-8" if you don't use UTF-8 for your filenames. + # + IndexOptions FancyIndexing VersionSort HTMLTable NameWidth=* DescriptionWidth=* Charset=UTF-8 + + # + # AddIcon* directives tell the server which icon to show for different + # files or filename extensions. These are only displayed for + # FancyIndexed directories. + # + AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip x-bzip2 + + AddIconByType (TXT,/icons/text.gif) text/* + AddIconByType (IMG,/icons/image2.gif) image/* + AddIconByType (SND,/icons/sound2.gif) audio/* + AddIconByType (VID,/icons/movie.gif) video/* + + AddIcon /icons/binary.gif .bin .exe + AddIcon /icons/binhex.gif .hqx + AddIcon /icons/tar.gif .tar + AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv + AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip + AddIcon /icons/a.gif .ps .ai .eps + AddIcon /icons/layout.gif .html .shtml .htm .pdf + AddIcon /icons/text.gif .txt + AddIcon /icons/c.gif .c + AddIcon /icons/p.gif .pl .py + AddIcon /icons/f.gif .for + AddIcon /icons/dvi.gif .dvi + AddIcon /icons/uuencoded.gif .uu + AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl + AddIcon /icons/tex.gif .tex + # It's a suffix rule, so simply matching "core" matches "score" as well ! + AddIcon /icons/bomb.gif /core + AddIcon (SND,/icons/sound2.gif) .ogg + AddIcon (VID,/icons/movie.gif) .ogm + + AddIcon /icons/back.gif .. + AddIcon /icons/hand.right.gif README + AddIcon /icons/folder.gif ^^DIRECTORY^^ + AddIcon /icons/blank.gif ^^BLANKICON^^ + + # Default icons for OpenDocument format + AddIcon /icons/odf6odt-20x22.png .odt + AddIcon /icons/odf6ods-20x22.png .ods + AddIcon /icons/odf6odp-20x22.png .odp + AddIcon /icons/odf6odg-20x22.png .odg + AddIcon /icons/odf6odc-20x22.png .odc + AddIcon /icons/odf6odf-20x22.png .odf + AddIcon /icons/odf6odb-20x22.png .odb + AddIcon /icons/odf6odi-20x22.png .odi + AddIcon /icons/odf6odm-20x22.png .odm + + AddIcon /icons/odf6ott-20x22.png .ott + AddIcon /icons/odf6ots-20x22.png .ots + AddIcon /icons/odf6otp-20x22.png .otp + AddIcon /icons/odf6otg-20x22.png .otg + AddIcon /icons/odf6otc-20x22.png .otc + AddIcon /icons/odf6otf-20x22.png .otf + AddIcon /icons/odf6oti-20x22.png .oti + AddIcon /icons/odf6oth-20x22.png .oth + + # + # DefaultIcon is which icon to show for files which do not have an icon + # explicitly set. + # + DefaultIcon /icons/unknown.gif + + # + # AddDescription allows you to place a short description after a file in + # server-generated indexes. These are only displayed for FancyIndexed + # directories. + # Format: AddDescription "description" filename + # + #AddDescription "GZIP compressed document" .gz + #AddDescription "tar archive" .tar + #AddDescription "GZIP compressed tar archive" .tgz + + # + # ReadmeName is the name of the README file the server will look for by + # default, and append to directory listings. + # + # HeaderName is the name of a file which should be prepended to + # directory indexes. + ReadmeName README.html + HeaderName HEADER.html + + # + # IndexIgnore is a set of filenames which directory indexing should ignore + # and not include in the listing. Shell-style wildcarding is permitted. + # + IndexIgnore .??* *~ *# RCS CVS *,v *,t + diff --git a/cookbooks/apache2/templates/default/mods/cache_disk.conf.erb b/cookbooks/apache2/templates/default/mods/cache_disk.conf.erb new file mode 100644 index 0000000..87117b4 --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/cache_disk.conf.erb @@ -0,0 +1,23 @@ + + # cache cleaning is done by htcacheclean, which can be configured in + # /etc/default/apache2 + # + # For further information, see the comments in that file, + # /usr/share/doc/apache2/README.Debian, and the htcacheclean(8) + # man page. + + # This path must be the same as the one in /etc/default/apache2 + CacheRoot /var/cache/apache2/mod_cache_disk + + # This will also cache local documents. It usually makes more sense to + # put this into the configuration for just one virtual host. + CacheEnable disk / + + + # The result of CacheDirLevels * CacheDirLength must not be higher than + # 20. Moreover, pay attention on file system limits. Some file systems + # do not support more than a certain number of inodes and + # subdirectories (e.g. 32000 for ext3) + CacheDirLevels 2 + CacheDirLength 1 + diff --git a/cookbooks/apache2/templates/default/mods/cgid.conf.erb b/cookbooks/apache2/templates/default/mods/cgid.conf.erb new file mode 100644 index 0000000..355236c --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/cgid.conf.erb @@ -0,0 +1,3 @@ +# Socket for cgid communication +# +ScriptSock <%= node['apache']['run_dir'] %>/cgisock diff --git a/cookbooks/apache2/templates/default/mods/dav_fs.conf.erb b/cookbooks/apache2/templates/default/mods/dav_fs.conf.erb new file mode 100644 index 0000000..609b2f4 --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/dav_fs.conf.erb @@ -0,0 +1 @@ +DAVLockDB <%= node['apache']['lock_dir'] %>/DAVLock diff --git a/cookbooks/apache2/templates/default/mods/deflate.conf.erb b/cookbooks/apache2/templates/default/mods/deflate.conf.erb new file mode 100644 index 0000000..7dd016a --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/deflate.conf.erb @@ -0,0 +1,18 @@ + + + # these are known to be safe with MSIE 6 + AddOutputFilterByType DEFLATE text/html text/plain text/xml + + # everything else may cause problems with MSIE 6 + AddOutputFilterByType DEFLATE text/css + AddOutputFilterByType DEFLATE application/x-javascript application/javascript application/ecmascript + AddOutputFilterByType DEFLATE application/rss+xml + AddOutputFilterByType DEFLATE application/xml + AddOutputFilterByType DEFLATE application/xhtml+xml + AddOutputFilterByType DEFLATE image/svg+xml + AddOutputFilterByType DEFLATE application/atom_xml + AddOutputFilterByType DEFLATE application/x-httpd-php + AddOutputFilterByType DEFLATE application/x-httpd-fastphp + AddOutputFilterByType DEFLATE application/x-httpd-eruby + + diff --git a/cookbooks/apache2/templates/default/mods/dir.conf.erb b/cookbooks/apache2/templates/default/mods/dir.conf.erb new file mode 100644 index 0000000..dd6cea1 --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/dir.conf.erb @@ -0,0 +1,3 @@ + + DirectoryIndex index.html index.cgi index.pl index.php index.xhtml index.htm + diff --git a/cookbooks/apache2/templates/default/mods/fastcgi.conf.erb b/cookbooks/apache2/templates/default/mods/fastcgi.conf.erb new file mode 100644 index 0000000..add16d5 --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/fastcgi.conf.erb @@ -0,0 +1,5 @@ + + AddHandler fastcgi-script .fcgi + #FastCgiWrapper /usr/lib/apache2/suexec + FastCgiIpcDir <%= "#{node['apache']['lib_dir']}/fastcgi" %> + diff --git a/cookbooks/apache2/templates/default/mods/fcgid.conf.erb b/cookbooks/apache2/templates/default/mods/fcgid.conf.erb new file mode 100644 index 0000000..597b7dc --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/fcgid.conf.erb @@ -0,0 +1,10 @@ + + AddHandler fcgid-script .fcgi + IPCConnectTimeout 20 + + +<% if (node['platform_family'] == 'rhel') && (node['platform_version'].to_i == 6) -%> +# Sane place to put sockets and shared memory file +SocketPath run/mod_fcgid +SharememPath run/mod_fcgid/fcgid_shm +<% end -%> diff --git a/cookbooks/apache2/templates/default/mods/include.conf.erb b/cookbooks/apache2/templates/default/mods/include.conf.erb new file mode 100644 index 0000000..44f54e4 --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/include.conf.erb @@ -0,0 +1,4 @@ + + AddType text/html .shtml + AddOutputFilter INCLUDES .shtml + diff --git a/cookbooks/apache2/templates/default/mods/include.erb b/cookbooks/apache2/templates/default/mods/include.erb new file mode 100644 index 0000000..06c3e0a --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/include.erb @@ -0,0 +1,4 @@ + + AddType text/html .shtml + AddOutputFilter INCLUDES .shtml + diff --git a/cookbooks/apache2/templates/default/mods/info.conf.erb b/cookbooks/apache2/templates/default/mods/info.conf.erb new file mode 100644 index 0000000..a735ae5 --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/info.conf.erb @@ -0,0 +1,19 @@ + + # + # Allow server info reports generated by mod_info, + # with the URL of http://servername/server-info + # Uncomment and change the ".example.com" to allow + # access from other hosts. + # + + SetHandler server-info +<% if node['apache']['version'] == '2.4' -%> + Require local + Require ip <%= node['apache']['info_allow_list'] %> +<% else -%> + Order deny,allow + Deny from all + Allow from <%= node['apache']['info_allow_list'] %> +<% end -%> + + diff --git a/cookbooks/apache2/templates/default/mods/ldap.conf.erb b/cookbooks/apache2/templates/default/mods/ldap.conf.erb new file mode 100644 index 0000000..6333d06 --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/ldap.conf.erb @@ -0,0 +1,4 @@ + + SetHandler ldap-status + Require local + diff --git a/cookbooks/apache2/templates/default/mods/mime.conf.erb b/cookbooks/apache2/templates/default/mods/mime.conf.erb new file mode 100644 index 0000000..56d1fca --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/mime.conf.erb @@ -0,0 +1,199 @@ + + # + # TypesConfig points to the file containing the list of mappings from + # filename extension to MIME-type. + # + <% case node['platform_family'] -%> + <% when 'arch' -%> + TypesConfig <%= node['apache']['dir'] %>/conf/mime.types + <% when 'freebsd' -%> + TypesConfig <%= node['apache']['dir'] %>/mime.types + <% else -%> + TypesConfig /etc/mime.types + <% end -%> + + # + # AddType allows you to add to or override the MIME configuration + # file mime.types for specific file types. + # + #AddType application/x-gzip .tgz + # + # AddEncoding allows you to have certain browsers uncompress + # information on the fly. Note: Not all browsers support this. + # Despite the name similarity, the following Add* directives have + # nothing to do with the FancyIndexing customization directives above. + # + #AddEncoding x-compress .Z + #AddEncoding x-gzip .gz .tgz + #AddEncoding x-bzip2 .bz2 + # + # If the AddEncoding directives above are commented-out, then you + # probably should define those extensions to indicate media types: + # + AddType application/x-compress .Z + AddType application/x-gzip .gz .tgz + AddType application/x-bzip2 .bz2 + + AddType image/svg+xml svg svgz + AddEncoding gzip svgz + + # + # DefaultLanguage and AddLanguage allows you to specify the language of + # a document. You can then use content negotiation to give a browser a + # file in a language the user can understand. + # + # Specify a default language. This means that all data + # going out without a specific language tag (see below) will + # be marked with this one. You probably do NOT want to set + # this unless you are sure it is correct for all cases. + # + # * It is generally better to not mark a page as + # * being a certain language than marking it with the wrong + # * language! + # + # DefaultLanguage nl + # + # Note 1: The suffix does not have to be the same as the language + # keyword --- those with documents in Polish (whose net-standard + # language code is pl) may wish to use "AddLanguage pl .po" to + # avoid the ambiguity with the common suffix for perl scripts. + # + # Note 2: The example entries below illustrate that in some cases + # the two character 'Language' abbreviation is not identical to + # the two character 'Country' code for its country, + # E.g. 'Danmark/dk' versus 'Danish/da'. + # + # Note 3: In the case of 'ltz' we violate the RFC by using a three char + # specifier. There is 'work in progress' to fix this and get + # the reference data for rfc1766 cleaned up. + # + # Catalan (ca) - Croatian (hr) - Czech (cs) - Danish (da) - Dutch (nl) + # English (en) - Esperanto (eo) - Estonian (et) - French (fr) - German (de) + # Greek-Modern (el) - Hebrew (he) - Italian (it) - Japanese (ja) + # Korean (ko) - Luxembourgeois* (ltz) - Norwegian Nynorsk (nn) + # Norwegian (no) - Polish (pl) - Portugese (pt) + # Brazilian Portuguese (pt-BR) - Russian (ru) - Swedish (sv) + # Simplified Chinese (zh-CN) - Spanish (es) - Traditional Chinese (zh-TW) + # + AddLanguage ca .ca + AddLanguage cs .cz .cs + AddLanguage da .dk + AddLanguage de .de + AddLanguage el .el + AddLanguage en .en + AddLanguage eo .eo + # See README.Debian for Spanish + AddLanguage es .es + AddLanguage et .et + AddLanguage fr .fr + AddLanguage he .he + AddLanguage hr .hr + AddLanguage it .it + AddLanguage ja .ja + AddLanguage ko .ko + AddLanguage ltz .ltz + AddLanguage nl .nl + AddLanguage nn .nn + AddLanguage no .no + AddLanguage pl .po + AddLanguage pt .pt + AddLanguage pt-BR .pt-br + AddLanguage ru .ru + AddLanguage sv .sv + # See README.Debian for Turkish + AddLanguage tr .tr + AddLanguage zh-CN .zh-cn + AddLanguage zh-TW .zh-tw + + # + # Commonly used filename extensions to character sets. You probably + # want to avoid clashes with the language extensions, unless you + # are good at carefully testing your setup after each change. + # See http://www.iana.org/assignments/character-sets for the + # official list of charset names and their respective RFCs. + # + AddCharset us-ascii .ascii .us-ascii + AddCharset ISO-8859-1 .iso8859-1 .latin1 + AddCharset ISO-8859-2 .iso8859-2 .latin2 .cen + AddCharset ISO-8859-3 .iso8859-3 .latin3 + AddCharset ISO-8859-4 .iso8859-4 .latin4 + AddCharset ISO-8859-5 .iso8859-5 .cyr .iso-ru + AddCharset ISO-8859-6 .iso8859-6 .arb .arabic + AddCharset ISO-8859-7 .iso8859-7 .grk .greek + AddCharset ISO-8859-8 .iso8859-8 .heb .hebrew + AddCharset ISO-8859-9 .iso8859-9 .latin5 .trk + AddCharset ISO-8859-10 .iso8859-10 .latin6 + AddCharset ISO-8859-13 .iso8859-13 + AddCharset ISO-8859-14 .iso8859-14 .latin8 + AddCharset ISO-8859-15 .iso8859-15 .latin9 + AddCharset ISO-8859-16 .iso8859-16 .latin10 + AddCharset ISO-2022-JP .iso2022-jp .jis + AddCharset ISO-2022-KR .iso2022-kr .kis + AddCharset ISO-2022-CN .iso2022-cn .cis + AddCharset Big5 .Big5 .big5 .b5 + AddCharset cn-Big5 .cn-big5 + # For russian, more than one charset is used (depends on client, mostly): + AddCharset WINDOWS-1251 .cp-1251 .win-1251 + AddCharset CP866 .cp866 + AddCharset KOI8 .koi8 + AddCharset KOI8-E .koi8-e + AddCharset KOI8-r .koi8-r .koi8-ru + AddCharset KOI8-U .koi8-u + AddCharset KOI8-ru .koi8-uk .ua + AddCharset ISO-10646-UCS-2 .ucs2 + AddCharset ISO-10646-UCS-4 .ucs4 + AddCharset UTF-7 .utf7 + AddCharset UTF-8 .utf8 + AddCharset UTF-16 .utf16 + AddCharset UTF-16BE .utf16be + AddCharset UTF-16LE .utf16le + AddCharset UTF-32 .utf32 + AddCharset UTF-32BE .utf32be + AddCharset UTF-32LE .utf32le + AddCharset euc-cn .euc-cn + AddCharset euc-gb .euc-gb + AddCharset euc-jp .euc-jp + AddCharset euc-kr .euc-kr + #Not sure how euc-tw got in - IANA doesn't list it??? + AddCharset EUC-TW .euc-tw + AddCharset gb2312 .gb2312 .gb + AddCharset iso-10646-ucs-2 .ucs-2 .iso-10646-ucs-2 + AddCharset iso-10646-ucs-4 .ucs-4 .iso-10646-ucs-4 + AddCharset shift_jis .shift_jis .sjis + + # + # AddHandler allows you to map certain file extensions to "handlers": + # actions unrelated to filetype. These can be either built into the server + # or added with the Action directive (see below) + # + # To use CGI scripts outside of ScriptAliased directories: + # (You will also need to add "ExecCGI" to the "Options" directive.) + # + #AddHandler cgi-script .cgi + + # + # For files that include their own HTTP headers: + # + #AddHandler send-as-is asis + + # + # For server-parsed imagemap files: + # + #AddHandler imap-file map + + # + # For type maps (negotiated resources): + # (This is enabled by default to allow the Apache "It Worked" page + # to be distributed in multiple languages.) + # + AddHandler type-map var + + # + # Filters allow you to process content before it is sent to the client. + # + # To parse .shtml files for server-side includes (SSI): + # (You will also need to add "Includes" to the "Options" directive.) + # + AddType text/html .shtml + AddOutputFilter INCLUDES .shtml + diff --git a/cookbooks/apache2/templates/default/mods/mime_magic.conf.erb b/cookbooks/apache2/templates/default/mods/mime_magic.conf.erb new file mode 100644 index 0000000..bb31b1a --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/mime_magic.conf.erb @@ -0,0 +1,3 @@ + + MIMEMagicFile <%= node['apache']['dir'] %>/magic + diff --git a/cookbooks/apache2/templates/default/mods/mpm_event.conf.erb b/cookbooks/apache2/templates/default/mods/mpm_event.conf.erb new file mode 100644 index 0000000..5b85c96 --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/mpm_event.conf.erb @@ -0,0 +1,32 @@ +# event MPM + + <% if node['apache']['version'] == '2.4' -%> + # StartServers: initial number of server processes to start + # MinSpareThreads: minimum number of worker threads which are kept spare + # MaxSpareThreads: maximum number of worker threads which are kept spare + # ThreadsPerChild: constant number of worker threads in each server process + # MaxRequestWorkers: maximum number of worker threads + # MaxConnectionsPerChild: maximum number of requests a server process serves + StartServers <%= node['apache']['event']['startservers'] %> + MinSpareThreads <%= node['apache']['event']['minsparethreads'] %> + MaxSpareThreads <%= node['apache']['event']['maxsparethreads'] %> + ThreadsPerChild <%= node['apache']['event']['threadsperchild'] %> + MaxRequestWorkers <%= node['apache']['event']['maxrequestworkers'] %> + MaxConnectionsPerChild <%= node['apache']['event']['maxconnectionsperchild'] %> + ThreadLimit <%= node['apache']['event']['threadlimit'] %> + ServerLimit <%= node['apache']['event']['serverlimit'] %> + <% else -%> + # StartServers: number of server processes to start + # MinSpareServers: minimum number of server processes which are kept spare + # MaxSpareServers: maximum number of server processes which are kept spare + # MaxClients: maximum number of server processes allowed to start + # MaxRequestsPerChild: maximum number of requests a server process serves + StartServers <%= node['apache']['event']['startservers'] %> + MinSpareThreads <%= node['apache']['event']['minsparethreads'] %> + MaxSpareThreads <%= node['apache']['event']['maxsparethreads'] %> + MaxClients <%= node['apache']['event']['maxrequestworkers'] %> + MaxRequestsPerChild <%= node['apache']['event']['maxconnectionsperchild'] %> + ThreadLimit <%= node['apache']['event']['threadlimit'] %> + ServerLimit <%= node['apache']['event']['serverlimit'] %> + <% end -%> + diff --git a/cookbooks/apache2/templates/default/mods/mpm_prefork.conf.erb b/cookbooks/apache2/templates/default/mods/mpm_prefork.conf.erb new file mode 100644 index 0000000..e1d5dec --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/mpm_prefork.conf.erb @@ -0,0 +1,28 @@ +# prefork MPM + + <% if node['apache']['version'] == '2.4' -%> + # StartServers: number of server processes to start + # MinSpareServers: minimum number of server processes which are kept spare + # MaxSpareServers: maximum number of server processes which are kept spare + # MaxRequestWorkers: maximum number of server processes allowed to start + # MaxConnectionsPerChild: maximum number of requests a server process serves + StartServers <%= node['apache']['prefork']['startservers'] %> + MinSpareServers <%= node['apache']['prefork']['minspareservers'] %> + MaxSpareServers <%= node['apache']['prefork']['maxspareservers'] %> + ServerLimit <%= node['apache']['prefork']['serverlimit'] %> + MaxRequestWorkers <%= node['apache']['prefork']['maxrequestworkers'] %> + MaxConnectionsPerChild <%= node['apache']['prefork']['maxconnectionsperchild'] %> + <% else -%> + # StartServers: number of server processes to start + # MinSpareServers: minimum number of server processes which are kept spare + # MaxSpareServers: maximum number of server processes which are kept spare + # MaxClients: maximum number of server processes allowed to start + # MaxRequestsPerChild: maximum number of requests a server process serves + StartServers <%= node['apache']['prefork']['startservers'] %> + MinSpareServers <%= node['apache']['prefork']['minspareservers'] %> + MaxSpareServers <%= node['apache']['prefork']['maxspareservers'] %> + ServerLimit <%= node['apache']['prefork']['serverlimit'] %> + MaxClients <%= node['apache']['prefork']['maxrequestworkers'] %> + MaxRequestsPerChild <%= node['apache']['prefork']['maxconnectionsperchild'] %> + <% end -%> + diff --git a/cookbooks/apache2/templates/default/mods/mpm_worker.conf.erb b/cookbooks/apache2/templates/default/mods/mpm_worker.conf.erb new file mode 100644 index 0000000..d3eb5a6 --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/mpm_worker.conf.erb @@ -0,0 +1,20 @@ +# worker MPM +# StartServers: initial number of server processes to start +# MinSpareThreads: minimum number of worker threads which are kept spare +# MaxSpareThreads: maximum number of worker threads which are kept spare +# ThreadLimit: ThreadsPerChild can be changed to this maximum value during a +# graceful restart. ThreadLimit can only be changed by stopping +# and starting Apache. +# ThreadsPerChild: constant number of worker threads in each server process +# MaxRequestWorkers: maximum number of threads +# MaxConnectionsPerChild: maximum number of requests a server process serves + + StartServers <%= node['apache']['worker']['startservers'] %> + MinSpareThreads <%= node['apache']['worker']['minsparethreads'] %> + MaxSpareThreads <%= node['apache']['worker']['maxsparethreads'] %> + ThreadsPerChild <%= node['apache']['worker']['threadsperchild'] %> + MaxRequestWorkers <%= node['apache']['worker']['maxrequestworkers'] %> + MaxConnectionsPerChild <%= node['apache']['worker']['maxconnectionsperchild'] %> + ThreadLimit <%= node['apache']['worker']['threadlimit'] %> + ServerLimit <%= node['apache']['worker']['serverlimit'] %> + diff --git a/cookbooks/apache2/templates/default/mods/negotiation.conf.erb b/cookbooks/apache2/templates/default/mods/negotiation.conf.erb new file mode 100644 index 0000000..6bea05f --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/negotiation.conf.erb @@ -0,0 +1,17 @@ + + # + # LanguagePriority allows you to give precedence to some languages + # in case of a tie during content negotiation. + # + # Just list the languages in decreasing order of preference. We have + # more or less alphabetized them here. You probably want to change this. + # + LanguagePriority en ca cs da de el eo es et fr he hr it ja ko ltz nl nn no pl pt pt-BR ru sv tr zh-CN zh-TW + + # + # ForceLanguagePriority allows you to serve a result page rather than + # MULTIPLE CHOICES (Prefer) [in case of a tie] or NOT ACCEPTABLE (Fallback) + # [in case no accepted languages matched the available variants] + # + ForceLanguagePriority Prefer Fallback + diff --git a/cookbooks/apache2/templates/default/mods/pagespeed.conf.erb b/cookbooks/apache2/templates/default/mods/pagespeed.conf.erb new file mode 100644 index 0000000..6d5f3ce --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/pagespeed.conf.erb @@ -0,0 +1,293 @@ + + # Turn on mod_pagespeed. To completely disable mod_pagespeed, you + # can set this to "off". + ModPagespeed on + + # We want VHosts to inherit global configuration. + # If this is not included, they'll be independent (except for inherently + # global options), at least for backwards compatibility. + ModPagespeedInheritVHostConfig on + + # Direct Apache to send all HTML output to the mod_pagespeed + # output handler. + AddOutputFilterByType MOD_PAGESPEED_OUTPUT_FILTER text/html + + # If you want mod_pagespeed process XHTML as well, please uncomment this + # line. + # AddOutputFilterByType MOD_PAGESPEED_OUTPUT_FILTER application/xhtml+xml + + # The ModPagespeedFileCachePath directory must exist and be writable + # by the apache user (as specified by the User directive). + ModPagespeedFileCachePath "/var/cache/mod_pagespeed/" + + # Override the mod_pagespeed 'rewrite level'. The default level + # "CoreFilters" uses a set of rewrite filters that are generally + # safe for most web pages. Most sites should not need to change + # this value and can instead fine-tune the configuration using the + # ModPagespeedDisableFilters and ModPagespeedEnableFilters + # directives, below. Valid values for ModPagespeedRewriteLevel are + # PassThrough, CoreFilters and TestingCoreFilters. + # + # ModPagespeedRewriteLevel PassThrough + + # Explicitly disables specific filters. This is useful in + # conjuction with ModPagespeedRewriteLevel. For instance, if one + # of the filters in the CoreFilters needs to be disabled for a + # site, that filter can be added to + # ModPagespeedDisableFilters. This directive contains a + # comma-separated list of filter names, and can be repeated. + # + # ModPagespeedDisableFilters rewrite_images + + # Explicitly enables specific filters. This is useful in + # conjuction with ModPagespeedRewriteLevel. For instance, filters + # not included in the CoreFilters may be enabled using this + # directive. This directive contains a comma-separated list of + # filter names, and can be repeated. + # + # ModPagespeedEnableFilters rewrite_javascript,rewrite_css + # ModPagespeedEnableFilters collapse_whitespace,elide_attributes + + # ModPagespeedDomain + # authorizes rewriting of JS, CSS, and Image files found in this + # domain. By default only resources with the same origin as the + # HTML file are rewritten. For example: + # + # ModPagespeedDomain cdn.myhost.com + # + # This will allow resources found on http://cdn.myhost.com to be + # rewritten in addition to those in the same domain as the HTML. + # + # Wildcards (* and ?) are allowed in the domain specification. Be + # careful when using them as if you rewrite domains that do not + # send you traffic, then the site receiving the traffic will not + # know how to serve the rewritten content. + + # Other defaults (cache sizes and thresholds): + # + # ModPagespeedFileCacheSizeKb 102400 + # ModPagespeedFileCacheCleanIntervalMs 3600000 + # ModPagespeedLRUCacheKbPerProcess 1024 + # ModPagespeedLRUCacheByteLimit 16384 + # ModPagespeedCssFlattenMaxBytes 2048 + # ModPagespeedCssInlineMaxBytes 2048 + # ModPagespeedCssImageInlineMaxBytes 2048 + # ModPagespeedImageInlineMaxBytes 2048 + # ModPagespeedJsInlineMaxBytes 2048 + # ModPagespeedCssOutlineMinBytes 3000 + # ModPagespeedJsOutlineMinBytes 3000 + + # Limit the number of inodes in the file cache. Set to 0 for no limit. + # The default value if this paramater is not specified is 0 (no limit). + ModPagespeedFileCacheInodeLimit 500000 + + # Bound the number of images that can be rewritten at any one time; this + # avoids overloading the CPU. Set this to 0 to remove the bound. + # + # ModPagespeedImageMaxRewritesAtOnce 8 + + # You can also customize the number of threads per Apache process + # mod_pagespeed will use to do resource optimization. Plain + # "rewrite threads" are used to do short, latency-sensitive work, + # while "expensive rewrite threads" are used for actual optimization + # work that's more computationally expensive. If you live these unset, + # or use values <= 0 the defaults will be used, which is 1 for both + # values when using non-threaded MPMs (e.g. prefork) and 4 for both + # on threaded MPMs (e.g. worker and event). These settings can only + # be changed globally, and not per virtual host. + # + # ModPagespeedNumRewriteThreads 4 + # ModPagespeedNumExpensiveRewriteThreads 4 + + + # Settings for image optimization: + # + # Jpeg recompression quality (0 to 100, -1 strips metadata): + # ModPagespeedJpegRecompressionQuality -1 + # + # Percent of original image size below which optimized images are retained: + # ModPagespeedImageLimitOptimizedPercent 100 + # + # Percent of original image area below which image resizing will be + # attempted: + # ModPagespeedImageLimitResizeAreaPercent 100 + + # When Apache is set up as a browser proxy, mod_pagespeed can record + # web-sites as they are requested, so that an image of the web is built up + # in the directory of the proxy administrator's choosing. When ReadOnly is + # on, only files already present in the SlurpDirectory are served by the + # proxy. + # + # ModPagespeedSlurpDirectory ... + # ModPagespeedSlurpReadOnly on + + # The maximum URL size is generally limited to about 2k characters + # due to IE: See http://support.microsoft.com/kb/208427/EN-US. + # Apache servers by default impose a further limitation of about + # 250 characters per URL segment (text between slashes). + # mod_pagespeed circumvents this limitation, but if you employ + # proxy servers in your path you may need to re-impose it by + # overriding the setting here. The default setting is 1024 + # characters. + # + # ModPagespeedMaxSegmentLength 250 + + # Uncomment this if you want to prevent mod_pagespeed from combining files + # (e.g. CSS files) across paths + # + # ModPagespeedCombineAcrossPaths off + + # Renaming JavaScript URLs can sometimes break them. With this + # option enabled, mod_pagespeed uses a simple heuristic to decide + # not to rename JavaScript that it thinks is introspective. + # + # You can turn this off to let mod_pagespeed rename all JS files. + ModPagespeedAvoidRenamingIntrospectiveJavascript on + + # Certain common JavaScript libraries are available from Google, which acts + # as a CDN and allows you to benefit from browser caching if a new visitor + # to your site previously visited another site that makes use of the same + # libraries as you do. Enable the following filter to turn on this feature. + # + # ModPagespeedEnableFilters canonicalize_javascript_libraries + + # The following lines configure libraries that are recognized by + # canonicalize_javascript_libraries. These will have no effect unless you + # enable this filter (generally by uncommenting the last line in the + # previous stanza). It simply provides a sensible default configuration + # when the filter is switched on. + # The format is: + # ModPagespeedLibrary bytes md5 canonical_url + # Where bytes and md5 are with respect to the *minified* JS; use + # js_minify --print_size_and_hash to obtain this data. + # Note that we can register multiple hashes for the same canonical url; + # we do this if there are versions available that have already been minified + # with more sophisticated tools. + ModPagespeedLibrary 105527 ltVVzzYxo0 //ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js + ModPagespeedLibrary 92501 J8KF47pYOq //ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js + ModPagespeedLibrary 141547 GKjMUuF4PK //ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js + ModPagespeedLibrary 43 1o978_K0_L http://www.modpagespeed.com/rewrite_javascript.js + + # Explicitly tell mod_pagespeed to load some resources from disk. + # This will speed up load time and update frequency. + # + # This should only be used for static resources which do not need + # specific headers set or other processing by Apache. + # + # Both URL and filesystem path should specify directories and + # filesystem path must be absolute (for now). + # + # ModPagespeedLoadFromFile "http://example.com/static/" "/var/www/static/" + + + # Enables server-side instrumentation and statistics. If this rewriter is + # enabled, then each rewritten HTML page will have instrumentation javacript + # added that sends latency beacons to /mod_pagespeed_beacon. These + # statistics can be accessed at /mod_pagespeed_statistics. You must also + # enable the mod_pagespeed_statistics and mod_pagespeed_beacon handlers + # below. + # + # ModPagespeedEnableFilters add_instrumentation + + # The add_instrumentation filter sends a beacon after the page onload + # handler is called. The user might navigate to a new URL before this. If + # you enable the following directive, the beacon is sent as part of an + # onbeforeunload handler, for pages where navigation happens before the + # onload event. + # + # ModPagespeedReportUnloadTime on + + # Uncomment the following line so that ModPagespeed will not cache or + # rewrite resources with Vary: in the header, e.g. Vary: User-Agent. + # ModPagespeedRespectVary on + + # This handles the client-side instrumentation callbacks which are injected + # by the add_instrumentation filter. + # You can use a different location by adding the ModPagespeedBeaconUrl + # directive; see the documentation on add_instrumentation. + + SetHandler mod_pagespeed_beacon + + + # Uncomment the following line if you want to disable statistics entirely. + # + # ModPagespeedStatistics off + + # This page lets you view statistics about the mod_pagespeed module. + + Order allow,deny + # You may insert other "Allow from" lines to add hosts you want to + # allow to look at generated statistics. Another possibility is + # to comment out the "Order" and "Allow" options from the config + # file, to allow any client that can reach your server to examine + # statistics. This might be appropriate in an experimental setup or + # if the Apache server is protected by a reverse proxy that will + # filter URLs in some fashion. + Allow from localhost + Allow from 127.0.0.1 + SetHandler mod_pagespeed_statistics + + + # Uncomment the following line if you want to enable statistics logging. + # ModPagespeedStatistics is required to be enabled. + # + # ModPagespeedStatisticsLogging on + # + # The base filename to use to store logged statistics. + # Required if logging is enabled. + # + # ModPagespeedStatisticsLoggingFile "@@MOD_PAGESPEED_STATS_LOG@@" + # + # The interval at which statistics will be logged, in milliseconds. + # Optional; default is 3000. + # + # ModPagespeedStatisticsLoggingIntervalMs 3000 + + # If both of the below are set, the console will use offline copies of the + # files needed for the Google Chart Tools API rather than connecting to the + # Internet to obtain them. This is experimental, as the only supported + # loading mechanism for the Chart Tools API requires an Internet connexion. + # + # Where to find an offline copy of the CSS file required for the Google + # Chart Tools API. At the time of writing, the Google Chart Tools API CSS + # file can be found at: + # https://ajax.googleapis.com/ajax/static/modules/gviz/1.0/core/tooltip.css + # + # ModPagespeedStatisticsLoggingChartsCSS http://example.com/charts.css + # + # Where to find an offline copy of the JS file required for the Google + # Chart Tools API. At the time of writing, the Google Chart Tools API JS + # file can be found at: + # https://www.google.com/uds/api/visualization/1.0/d7d36793f7a886b687850d2813583db9/format+en,default,corechart.I.js + # + # ModPagespeedStatisticsLoggingChartsJS http://example.com/charts.js + + # This page lets you view a graphical console displaying statistics about + # the mod_pagespeed module. + + Order allow,deny + # This can be configured similarly to mod_pagespeed_statistics above. + Allow from localhost + Allow from 127.0.0.1 + SetHandler mod_pagespeed_console + + + # Page /mod_pagespeed_message lets you view the latest messages from + # mod_pagespeed, regardless of log-level in your httpd.conf + # ModPagespeedMessageBufferSize is the maximum number of bytes you would + # like to dump to your /mod_pagespeed_message page at one time, + # its default value is 100k bytes. + # Set it to 0 if you want to disable this feature. + ModPagespeedMessageBufferSize 100000 + + + Allow from localhost + Allow from 127.0.0.1 + SetHandler mod_pagespeed_message + + + Allow from localhost + Allow from 127.0.0.1 + SetHandler mod_pagespeed_referer_statistics + + diff --git a/cookbooks/apache2/templates/default/mods/php.conf.erb b/cookbooks/apache2/templates/default/mods/php.conf.erb new file mode 100644 index 0000000..bdf590b --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/php.conf.erb @@ -0,0 +1,35 @@ + + SetHandler application/x-httpd-php + + + SetHandler application/x-httpd-php-source + # Deny access to raw php sources by default + # To re-enable it's recommended to enable access to the files + # only in specific virtual host or directory +<% if node['apache']['version'] == '2.4' -%> + Require all denied +<% else -%> + Order Deny,Allow + Deny from all +<% end -%> + +# Deny access to files without filename (e.g. '.php') + +<% if node['apache']['version'] == '2.4' -%> + Require all denied +<% else -%> + Order Deny,Allow + Deny from all +<% end -%> + + +# Running PHP scripts in user directories is disabled by default +# +# To re-enable PHP in user directories comment the following lines +# (from to .) Do NOT set it to On as it +# prevents .htaccess files from disabling it. + + + php_admin_value engine Off + + diff --git a/cookbooks/apache2/templates/default/mods/proxy.conf.erb b/cookbooks/apache2/templates/default/mods/proxy.conf.erb new file mode 100644 index 0000000..4cb64af --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/proxy.conf.erb @@ -0,0 +1,23 @@ + + #turning ProxyRequests on and allowing proxying from all may allow + #spammers to use your proxy to send email. + + ProxyRequests Off + + + AddDefaultCharset off + <% if node['apache']['version'] == "2.4" -%> + Require <%= node['apache']['proxy']['require'] %> + <% else -%> + Order <%= node['apache']['proxy']['order'] %> + Deny from <%= node['apache']['proxy']['deny_from'] %> + Allow from <%= node['apache']['proxy']['allow_from'] %> + <% end -%> + + + # Enable/disable the handling of HTTP/1.1 "Via:" headers. + # ("Full" adds the server version; "Block" removes all outgoing Via: headers) + # Set to one of: Off | On | Full | Block + + ProxyVia On + diff --git a/cookbooks/apache2/templates/default/mods/proxy_balancer.conf.erb b/cookbooks/apache2/templates/default/mods/proxy_balancer.conf.erb new file mode 100644 index 0000000..4131537 --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/proxy_balancer.conf.erb @@ -0,0 +1,18 @@ + + # Balancer manager enables dynamic update of balancer members + # (needs mod_status). Uncomment to enable. + # + # + # + # SetHandler balancer-manager +<% if node['apache']['version'] == '2.4' -%> + # Require local +<% else -%> + # Order deny,allow + # Deny from all + # Allow from 127.0.0.1 ::1 + # Satisfy all +<% end -%> + # + # + diff --git a/cookbooks/apache2/templates/default/mods/proxy_ftp.conf.erb b/cookbooks/apache2/templates/default/mods/proxy_ftp.conf.erb new file mode 100644 index 0000000..548124b --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/proxy_ftp.conf.erb @@ -0,0 +1,4 @@ + + # Define the character set for proxied FTP listings. Default is ISO-8859-1 + ProxyFtpDirCharset UTF-8 + diff --git a/cookbooks/apache2/templates/default/mods/reqtimeout.conf.erb b/cookbooks/apache2/templates/default/mods/reqtimeout.conf.erb new file mode 100644 index 0000000..b64e9cf --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/reqtimeout.conf.erb @@ -0,0 +1,22 @@ + + # mod_reqtimeout limits the time waiting on the client to prevent an + # attacker from causing a denial of service by opening many connections + # but not sending requests. This file tries to give a sensible default + # configuration, but it may be necessary to tune the timeout values to + # the actual situation. Note that it is also possible to configure + # mod_reqtimeout per virtual host. + + # Wait max 20 seconds for the first byte of the request line+headers + # From then, require a minimum data rate of 500 bytes/s, but don't + # wait longer than 40 seconds in total. + # Note: Lower timeouts may make sense on non-ssl virtual hosts but can + # cause problem with ssl enabled virtual hosts: This timeout includes + # the time a browser may need to fetch the CRL for the certificate. If + # the CRL server is not reachable, it may take more than 10 seconds + # until the browser gives up. + RequestReadTimeout header=20-40,minrate=500 + + # Wait max 10 seconds for the first byte of the request body (if any) + # From then, require a minimum data rate of 500 bytes/s + RequestReadTimeout body=10,minrate=500 + diff --git a/cookbooks/apache2/templates/default/mods/setenvif.conf.erb b/cookbooks/apache2/templates/default/mods/setenvif.conf.erb new file mode 100644 index 0000000..24b5fd9 --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/setenvif.conf.erb @@ -0,0 +1,28 @@ + + # + # The following directives modify normal HTTP response behavior to + # handle known problems with browser implementations. + # + BrowserMatch "Mozilla/2" nokeepalive + BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0 + BrowserMatch "RealPlayer 4\.0" force-response-1.0 + BrowserMatch "Java/1\.0" force-response-1.0 + BrowserMatch "JDK/1\.0" force-response-1.0 + + # + # The following directive disables redirects on non-GET requests for + # a directory that does not include the trailing slash. This fixes a + # problem with Microsoft WebFolders which does not appropriately handle + # redirects for folders with DAV methods. + # Same deal with Apple's DAV filesystem and Gnome VFS support for DAV. + # + BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully + BrowserMatch "MS FrontPage" redirect-carefully + BrowserMatch "^WebDrive" redirect-carefully + BrowserMatch "^WebDAVFS/1.[012]" redirect-carefully + BrowserMatch "^gnome-vfs/1.0" redirect-carefully + BrowserMatch "^gvfs/1" redirect-carefully + BrowserMatch "^XML Spy" redirect-carefully + BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully + BrowserMatch " Konqueror/4" redirect-carefully + diff --git a/cookbooks/apache2/templates/default/mods/ssl.conf.erb b/cookbooks/apache2/templates/default/mods/ssl.conf.erb new file mode 100644 index 0000000..b5f9e49 --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/ssl.conf.erb @@ -0,0 +1,108 @@ + + # + # Pseudo Random Number Generator (PRNG): + # Configure one or more sources to seed the PRNG of the SSL library. + # The seed data should be of good random quality. + # WARNING! On some platforms /dev/random blocks if not enough entropy + # is available. This means you then cannot use the /dev/random device + # because it would lead to very long connection times (as long as + # it requires to make more entropy available). But usually those + # platforms additionally provide a /dev/urandom device which doesn't + # block. So, if available, use this one instead. Read the mod_ssl User + # Manual for more details. + # + SSLRandomSeed startup builtin + SSLRandomSeed startup file:/dev/urandom 512 + SSLRandomSeed connect builtin + SSLRandomSeed connect file:/dev/urandom 512 + + ## + ## SSL Global Context + ## + ## All SSL configuration in this context applies both to + ## the main server and all SSL-enabled virtual hosts. + ## + + # + # Some MIME-types for downloading Certificates and CRLs + # + AddType application/x-x509-ca-cert .crt + AddType application/x-pkcs7-crl .crl + + # Pass Phrase Dialog: + # Configure the pass phrase gathering process. + # The filtering dialog program (`builtin' is a internal + # terminal dialog) has to provide the pass phrase on stdout. + SSLPassPhraseDialog <%= node['apache']['mod_ssl']['pass_phrase_dialog'] %> + + # Inter-Process Session Cache: + # Configure the SSL Session Cache: First the mechanism + # to use and second the expiring timeout (in seconds). + SSLSessionCache <%= node['apache']['mod_ssl']['session_cache'] %> + SSLSessionCacheTimeout <%= node['apache']['mod_ssl']['session_cache_timeout'] %> + +<% if node['apache']['version'] != '2.4' -%> + # Semaphore: + # Configure the path to the mutual exclusion semaphore the + # SSL engine uses internally for inter-process synchronization. + SSLMutex <%= node['apache']['mod_ssl']['mutex'] %> +<% end -%> + + # SSL Cipher Suite: + # List the ciphers that the client is permitted to negotiate. + # See the mod_ssl documentation for a complete list. + # enable only secure ciphers: + SSLCipherSuite <%= node['apache']['mod_ssl']['cipher_suite'] %> + + # Speed-optimized SSL Cipher configuration: + # If speed is your main concern (on busy HTTPS servers e.g.), + # you might want to force clients to specific, performance + # optimized ciphers. In this case, prepend those ciphers + # to the SSLCipherSuite list, and enable SSLHonorCipherOrder. + # Caveat: by giving precedence to RC4-SHA and AES128-SHA + # (as in the example below), most connections will no longer + # have perfect forward secrecy - if the server's key is + # compromised, captures of past or future traffic must be + # considered compromised, too. + #SSLCipherSuite RC4-SHA:AES128-SHA:HIGH:MEDIUM:!aNULL:!MD5 + SSLHonorCipherOrder <%= node['apache']['mod_ssl']['honor_cipher_order'] %> + + # The protocols to enable. + # Available values: all, SSLv3, TLSv1, TLSv1.1, TLSv1.2 + # SSL v2 is no longer supported + SSLProtocol <%= node['apache']['mod_ssl']['protocol'] %> + + # Allow insecure renegotiation with clients which do not yet support the + # secure renegotiation protocol. Default: Off + SSLInsecureRenegotiation <%= node['apache']['mod_ssl']['insecure_renegotiation'] %> + +<% unless node['apache']['mod_ssl']['strict_sni_vhost_check'] == "Off"%> + # Whether to forbid non-SNI clients to access name based virtual hosts. + # Default: Off + SSLStrictSNIVHostCheck <%= node['apache']['mod_ssl']['strict_sni_vhost_check'] %> +<% end %> + +<% if node['apache']['version'] == '2.4' -%> + # Enable compression on the SSL level + # Enabling compression causes security issues in most setups (the so called CRIME attack). + # Default: Off + SSLCompression <%= node['apache']['mod_ssl']['compression'] %> + + # OCSP Stapling, only in httpd 2.3.3 and later + # This option enables OCSP stapling, as defined by the "Certificate Status Request" TLS + # extension specified in RFC 6066. If enabled (and requested by the client), mod_ssl will + # include an OCSP response for its own certificate in the TLS handshake. + # Configuring an SSLStaplingCache is a prerequisite for enabling OCSP stapling. + # Default: Off + <% if node['apache']['mod_ssl']['use_stapling'] == 'On' -%> + SSLUseStapling <%= node['apache']['mod_ssl']['use_stapling'] %> + SSLStaplingResponderTimeout <%= node['apache']['mod_ssl']['stapling_responder_timeout'] %> + SSLStaplingReturnResponderErrors <%= node['apache']['mod_ssl']['stapling_return_responder_errors'] %> + SSLStaplingCache <%= node['apache']['mod_ssl']['stapling_cache'] %> + <% end -%> +<% end -%> + + <% node['apache']['mod_ssl']['directives'].sort_by { |key, val| key }.each do |directive, value| -%> + <%= directive %> <%= value %> + <% end -%> + diff --git a/cookbooks/apache2/templates/default/mods/status.conf.erb b/cookbooks/apache2/templates/default/mods/status.conf.erb new file mode 100644 index 0000000..be79e4e --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/status.conf.erb @@ -0,0 +1,42 @@ + + # + # Allow server status reports generated by mod_status, + # with the URL of http://servername/server-status + # Uncomment and change the ".example.com" to allow + # access from other hosts. + # + + SetHandler server-status +<% if node['apache']['version'] == '2.4' -%> + Require local + Require ip <%=node['apache']['status_allow_list']%> +<% else -%> + Order deny,allow + Deny from all + Allow from <%= node['apache']['status_allow_list'] %> + <% end -%> + + + # + # ExtendedStatus controls whether Apache will generate "full" status + # information (ExtendedStatus On) or just basic information (ExtendedStatus + # Off) when the "server-status" handler is called. The default is Off. + # + <% if node['apache']['ext_status'] -%> + ExtendedStatus On + <% else -%> + ExtendedStatus Off + <% end -%> + +<% if node['apache']['version'] == '2.4' -%> + # Determine if mod_status displays the first 63 characters of a request or + # the last 63, assuming the request itself is greater than 63 chars. + # Default: Off + #SeeRequestTail On + + + # Show Proxy LoadBalancer status in mod_status + ProxyStatus On + +<% end -%> + diff --git a/cookbooks/apache2/templates/default/mods/userdir.conf.erb b/cookbooks/apache2/templates/default/mods/userdir.conf.erb new file mode 100644 index 0000000..5c5c25d --- /dev/null +++ b/cookbooks/apache2/templates/default/mods/userdir.conf.erb @@ -0,0 +1,17 @@ +<% if node['apache']['version'] == '2.4' -%> + + UserDir public_html + UserDir disabled root + + + AllowOverride FileInfo AuthConfig Limit Indexes + Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec + + Require all granted + + + Require all denied + + + +<% end -%> diff --git a/cookbooks/apache2/templates/default/port_apache.erb b/cookbooks/apache2/templates/default/port_apache.erb new file mode 100644 index 0000000..9ac7474 --- /dev/null +++ b/cookbooks/apache2/templates/default/port_apache.erb @@ -0,0 +1,3 @@ +<% node['apache']['listen'].values.map(&:to_a).flatten.uniq do |port| -%> +-A FWR -p tcp -m tcp --dport <%= port %> -j ACCEPT +<% end %> diff --git a/cookbooks/apache2/templates/default/ports.conf.erb b/cookbooks/apache2/templates/default/ports.conf.erb new file mode 100644 index 0000000..129d06a --- /dev/null +++ b/cookbooks/apache2/templates/default/ports.conf.erb @@ -0,0 +1,6 @@ +# This file was generated by Chef for <%= node['fqdn'] %>. +# Do NOT modify this file by hand! + +<% Apache2::Listen.merge_listen_attributes(node).each do |addr| -%> +Listen <%= addr %> +<% end -%> diff --git a/cookbooks/apache2/templates/default/security.conf.erb b/cookbooks/apache2/templates/default/security.conf.erb new file mode 100644 index 0000000..1913ad3 --- /dev/null +++ b/cookbooks/apache2/templates/default/security.conf.erb @@ -0,0 +1,32 @@ +# Changing the following options will not really affect the security of the +# server, but might make attacks slightly more difficult in some cases. + +# +# ServerTokens +# This directive configures what you return as the Server HTTP response +# Header. The default is 'Full' which sends information about the OS-Type +# and compiled in modules. +# Set to one of: Full | OS | Minimal | Minor | Major | Prod +# where Full conveys the most information, and Prod the least. +# +ServerTokens <%= node['apache']['servertokens'] %> + +# +# Optionally add a line containing the server version and virtual host +# name to server-generated pages (internal error documents, FTP directory +# listings, mod_status and mod_info output etc., but not CGI generated +# documents or custom error documents). +# Set to "EMail" to also include a mailto: link to the ServerAdmin. +# Set to one of: On | Off | EMail +# +ServerSignature <%= node['apache']['serversignature'] %> + +# +# Allow TRACE method +# +# Set to "extended" to also reflect the request body (only for testing and +# diagnostic purposes). +# +# Set to one of: On | Off | extended +# +TraceEnable <%= node['apache']['traceenable'] %> diff --git a/cookbooks/apache2/templates/default/web_app.conf.erb b/cookbooks/apache2/templates/default/web_app.conf.erb new file mode 100644 index 0000000..d007ee5 --- /dev/null +++ b/cookbooks/apache2/templates/default/web_app.conf.erb @@ -0,0 +1,64 @@ +<% if node['apache']['version'] != '2.4' -%> +NameVirtualHost *:<%= @params[:server_port] %> +<% end -%> +> + ServerName <%= @params[:server_name] %> + <% if @params[:server_aliases] -%> + ServerAlias <%= @params[:server_aliases].join " " %> + <% end -%> + DocumentRoot <%= @params[:docroot] %> + + > + Options <%= [@params[:directory_options] || "FollowSymLinks" ].flatten.join " " %> + AllowOverride <%= [@params[:allow_override] || "None" ].flatten.join " " %> + <% if node['apache']['version'] == '2.4' -%> + Require all granted + <% else -%> + Order allow,deny + Allow from all + <% end -%> + + + + Options FollowSymLinks + AllowOverride None + + + + SetHandler server-status + + <% if node['apache']['version'] == '2.4' -%> + Require local + <% else -%> + Order Deny,Allow + Deny from all + Allow from 127.0.0.1 + <% end -%> + + + + RewriteEngine On + <%- if node['apache']['version'] == '2.4' -%> + LogLevel info rewrite:trace1 + <%- else -%> + LogLevel info + RewriteLog <%= node['apache']['log_dir'] %>/<%= @application_name %>-rewrite.log + RewriteLogLevel 0 + <%- end -%> + + ErrorLog <%= node['apache']['log_dir'] %>/<%= @params[:name] %>-error.log + CustomLog <%= node['apache']['log_dir'] %>/<%= @params[:name] %>-access.log combined + + <% if @params[:directory_index] -%> + DirectoryIndex <%= [@params[:directory_index]].flatten.join " " %> + <% end -%> + + # Canonical host, <%= @params[:server_name] %> + RewriteCond %{HTTP_HOST} !^<%= @params[:server_name] %> [NC] + RewriteCond %{HTTP_HOST} !^$ + RewriteRule ^/(.*)$ http://<%= @params[:server_name] %>/$1 [L,R=301] + + RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f + RewriteCond %{SCRIPT_FILENAME} !maintenance.html + RewriteRule ^.*$ /system/maintenance.html [L,R=503] + diff --git a/cookbooks/application/CHANGELOG.md b/cookbooks/application/CHANGELOG.md new file mode 100644 index 0000000..74c8643 --- /dev/null +++ b/cookbooks/application/CHANGELOG.md @@ -0,0 +1,101 @@ +# Application Changelog + +## v5.2.0 + +* Add `application_directory` resource. +* Chef 13 compatibility. + +## v5.1.0 + +* Add `application_cookbook_file`, `application_file`, and `application_template` resources. + +## v5.0.0 + +* Massive rewrite on top of newer Chef patterns. See the 5.0 README for details. + +## v4.1.6 + +* Support for Chef 12. +* Add `strict_ssh` option to enable host key checking. +* Add `keep_releases` option to control number of releases to keep. +* Allow passing a path to a file for `deploy_key`. + +## v4.1.4 + +* [COOK-3343](https://tickets.opscode.com/browse/COOK-3343) - Can't parse release candidate version number. + +## v4.1.2 + +* [COOK-3343](https://tickets.opscode.com/browse/COOK-3343) - Can't parse release candidate version number. + +## v4.1.0 + +* [COOK-3343] - Can't parse release candidate version number. + +## v4.0.0 + +* Removes compatability with Chef 10. +* [COOK-3564](https://tickets.opscode.com/browse/COOK-3564) - Replace calls to `Chef::Mixin::RecipeDefinitionDSLCore`. + +## v3.0.0 + +* [COOK-3306]: Multiple Memory Leaks in Application Cookbook. + +## v2.0.4 + +* [COOK-2812]: application cookbook doesn't allow to specify a block as `restart_command`. + +## v2.0.2 + +* [COOK-2537]: Provide proper `respond_to` behavior when using `method_missing`. +* [COOK-2713]: application resource should Allow sub-resource attributes to propogate up. + +### Improvement +* [COOK-2597]: Allow customization for `shallow_clone` when doing a git deploy. + +## v2.0.0 + +This release is incompatible with previous releases (hence major version change). The recipes used in older versions are deprecated and completely removed. See README.md for further detail. + +* [COOK-1673] - `deploy_revision` in the application cookbook gives an argument error. +* [COOK-1820] - Application cookbook: remove deprecated recipes. + +## v1.0.4 + +* [COOK-1567] - Add git submodules to application cookbook. + +## v1.0.2 + +* [COOK-1312] - string callbacks fail with method not found (really included this time). +* [COOK-1332] - add `release_path` and `shared_path` methods. +* [COOK-1333] - add example for running migrations. +* [COOK-1360] - fix minor typos in README. +* [COOK-1374] - use runit attributes in unicorn run script. + +## v1.0.0 + +This release introduces the LWRP for application deployment, as well as other improvements. The recipes will be deprecated in August 2012 as indicated by their warning messages and in the README.md. + +* [COOK-634] - Implement LWRP for application deployment. +* [COOK-1116] - use other SCMs than git. +* [COOK-1252] - add `:force_deploy` that maps to corresponding action of deploy resource. +* [COOK-1253] - fix rollback error. +* [COOK-1312] - string callbacks fail with method not found. +* [COOK-1313] - implicit file based hooks aren't invoked. +* [COOK-1318] - Create `to_ary` method to resolve issue in resources() lookup on "application[foo]" resources. + +## v0.99.14 + +* [COOK-1065] - use pip in virtualenv during deploy. + +## v0.99.12 + +* [COOK-606] application cookbook deployment recipes should use ipaddress instead of fqdn. + +## v0.99.11 + +* make the `_default` `chef_environment` look like production rails env. + +## v0.99.10 + +* Use Chef 0.10's `node.chef_environment` instead of `node['app_environment']`. diff --git a/cookbooks/application/README.md b/cookbooks/application/README.md new file mode 100644 index 0000000..3696a6e --- /dev/null +++ b/cookbooks/application/README.md @@ -0,0 +1,260 @@ +# Application cookbook + +[![Build Status](https://img.shields.io/travis/poise/application.svg)](https://travis-ci.org/poise/application) +[![Gem Version](https://img.shields.io/gem/v/poise-application.svg)](https://rubygems.org/gems/poise-application) +[![Cookbook Version](https://img.shields.io/cookbook/v/application.svg)](https://supermarket.chef.io/cookbooks/application) +[![Coverage](https://img.shields.io/codeclimate/coverage/github/poise/application.svg)](https://codeclimate.com/github/poise/application) +[![Gemnasium](https://img.shields.io/gemnasium/poise/application.svg)](https://gemnasium.com/poise/application) +[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) + +A [Chef](https://www.chef.io/) cookbook to deploy applications. + +## Getting Started + +The application cookbook provides a central framework to deploy applications +using Chef. Generally this will be web applications using things like Rails, +Django, or NodeJS, but the framework makes no specific assumptions. The core +`application` resource provides DSL support and helpers, but the heavy lifting +is all done in specific plugins detailed below. Each deployment starts with +an `application` resource: + +```ruby +application '/path/to/deploy' do + owner 'root' + group 'root' + + # ... +end +``` + +The `application` resource uses the Poise subresource system for plugins. This +means you configure the steps of the deployment like normal recipe code inside +the `application` resource, with a few special additions: + +```ruby +application '/path/to/deploy' do + # Application resource properties. + owner 'root' + group 'root' + + # Subresources, like normal recipe code. + package 'ruby' + git '/path/to/deploy' do + repository 'https://github.com/example/myapp.git' + end + application_rails '/path/to/deploy' do + database 'mysql://dbhost/myapp' + end +end +``` + +When evaluating the recipe inside the `application` resource, it first checks +for `application_#{resource}`, as well as looking for an LWRP of the same name +in any cookbook starting with `application_`. This means that a resource named +`application_foo` can be used as `foo` inside the `application` resource: + +```ruby +application '/path/to/deploy' do + owner 'root' + group 'root' + + rails '/path/to/deploy' do + database 'mysql://dbhost/myapp' + end +end +``` + +Additionally if a resource inside the `application` block doesn't have a name, +it uses the same name as the application resource itself: + +```ruby +application '/path/to/deploy' do + owner 'root' + group 'root' + + rails do + database 'mysql://dbhost/myapp' + end +end +``` + +Other than those two special features, the recipe code inside the `application` +resource is processed just like any other recipe. + +## Available Plugins + +* [`application_git`](https://github.com/poise/application_git) – Deploy + application code from a git repository. +* [`application_ruby`](https://github.com/poise/application_ruby) – Manage Ruby + deployments, such as Rails or Sinatra applications. +* [`application_python`](https://github.com/poise/application_python) – Manage + Python deployments, such as Django or Flask applications. +* [`application_javascript`](https://github.com/poise/application_javascript) – + Manage server-side JavaScript deployments using Node.js or io.js. +* `application_java` – *Coming soon!* +* `application_go` – *Coming soon!* +* `application_erlang` – *Coming soon!* + +## Requirements + +Chef 12 or newer is required. + +## Resources + +### `application` + +The `application` resource has top-level configuration properties for each +deployment and acts as a container for other deployment plugin resources. + +```ruby +application '/opt/test_sinatra' do + git 'https://github.com/example/my_sinatra_app.git' + bundle_install do + deployment true + end + unicorn do + port 9000 + end +end +``` + +#### Actions + +* `:deploy` – Deploy the application. *(default)* +* `:start` - Run `:start` on all subresources that support it. +* `:stop` - Run `:stop` on all subresources that support it. +* `:restart` - Run `:restart` on all subresources that support it. +* `:reload` - Run `:reload` on all subresources that support it. + +#### Properties + +* `path` – Path to deploy the application to. *(name attribute)* +* `environment` – Environment variables for all application deployment steps. +* `group` – System group to deploy the application as. +* `owner` – System user to deploy the application as. +* `action_on_update` – Action to run on the application resource when any + subresource is updated. *(default: restart)* +* `action_on_update_immediately` – Run the `action_on_update` notification with + `:immediately`. *(default: false)* + +### `application_cookbook_file`, `application_directory`, `application_file`, `application_template` + +The `application_cookbook_file`, `application_directory`, `application_file`, and `application_template` +resources extend the core Chef resources to take some application-level +configuration in to account: + +```ruby +application '/opt/myapp' do + template 'myapp.conf' do + source 'myapp.conf.erb' + end + directory 'logs' +end +``` + +If the resource name is a relative path, it will be expanded relative to the +application path. If an owner or group is declared for the application, those +will be the default user and group for the resource. + +All other actions and properties are the same as the similar resource in core Chef. + +## Examples + +Some test recipes are available as examples for common application frameworks: + +* [Sinatra](https://github.com/poise/application_ruby/blob/master/test/cookbooks/application_ruby_test/recipes/sinatra.rb) +* [Rails](https://github.com/poise/application_ruby/blob/master/test/cookbooks/application_ruby_test/recipes/rails.rb) +* [Flask](https://github.com/poise/application_python/blob/master/test/cookbook/recipes/flask.rb) +* [Django](https://github.com/poise/application_python/blob/master/test/cookbook/recipes/django.rb) +* [Express](https://github.com/poise/application_javascript/blob/master/test/cookbook/recipes/express.rb) + +## Upgrading From 4.x + +While the overall design of the revamped application resource is similar to the +4.x version, some changes will need to be made. The `name` property no longer +exists, with the name attribute being used as the path to the deployment. +The `packages` property has been removed as this is more easily handled via +normal recipe code. + +The SCM-related properties like `repository` and `revision` are now handled by +normal plugins. If you were deploying from a private git repository you will +likely want to use the `application_git` cookbook, otherwise just use the +built-in `git` or `svn` resources as per normal. + +The properties related to the `deploy` resource like `strategy` and `symlinks` +have been removed. The `deploy` resource is no longer used so these aren't +relevant. As a side effect of this, you'll likely want to point the upgraded +deployment at a new folder or manually clean the `current` and `shared` folders +from the existing folder. The pseudo-Capistrano layout used by the `deploy` +resource has few benefits in a config-managed world and introduced a lot of +complexity and moving pieces that are no longer required. + +With the removal of the `deploy` resource, the callback properties and commands +are no longer used as well. Subresources no longer use the complex +actions-as-callbacks arrangement as existed before, instead following normal +Chef recipe flow. Individual subresources may need to be tweaked to work with +newer versions of the cookbooks they come from, though most have stayed similar +in overall approach. + +## Database Migrations and Chef + +Several of the web application deployment plugins include optional support to +run database migrations from Chef. For "toy" applications where the app and +database run together on a single machine, this is fine and is a nice time +saver. For anything more complex I highly recommend not running database +migrations from Chef. Some initial operations like creating the database and/or +database user are more reasonable as they tend to be done only once and by their +nature the application does not yet have users so some level of eventual +consistency is more acceptable. With migrations on a production application, I +encourage using Chef and the application cookbooks to handle deploying the code +and writing configuration files, but use something more specific to run the +actual migration task. [Fabric](http://www.fabfile.org/), +[Capistrano](http://capistranorb.com/), and [Rundeck](http://rundeck.org/) are +all good choices for this orchestration tooling. + +Migrations can generally be applied idempotently but they have unique +constraints (pun definitely intended) that make them tricky in a Chef-like, +convergence-based system. First and foremost is that many table alterations +lock the table for updating for at least some period of time. That can mean that +while staging the new code or configuration data can happen within a window, the +migration itself needs to be run in careful lockstep with the rest of the +deployment process (eg. moving things in and out of load balancers). Beyond +that, while most web frameworks have internal idempotence checks for migrations, +running the process on two servers at the same time can have unexpected effects. + +Overall migrations are best thought of as a procedural step rather than a +declaratively modeled piece of the system. + +## Application Signals and Updates + +The `application` resource exposes `start`, `stop`, `restart`, and `reload` +actions which will dispatch to any subresources attached to the application. +This allows for generic application-level restart or reload signals that will +work with any type of deployment. + +Additionally the `action_on_update` property is used to set a default +notification so any subresource that updates will trigger an application +restart or reload. This can be disabled by setting `action_on_update false` if +you want to take manual control of service restarts. + +## Sponsors + +Development sponsored by [Chef Software](https://www.chef.io/), [Symonds & Son](http://symondsandson.com/), and [Orion](https://www.orionlabs.co/). + +The Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/). + +## License + +Copyright 2015-2016, Noah Kantrowitz + +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/cookbooks/application/files/halite_gem/poise_application.rb b/cookbooks/application/files/halite_gem/poise_application.rb new file mode 100644 index 0000000..8d771c4 --- /dev/null +++ b/cookbooks/application/files/halite_gem/poise_application.rb @@ -0,0 +1,25 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + + +module PoiseApplication + autoload :AppMixin, 'poise_application/app_mixin' + autoload :Error, 'poise_application/error' + autoload :Resources, 'poise_application/resources' + autoload :ServiceMixin, 'poise_application/service_mixin' + autoload :Utils, 'poise_application/utils' + autoload :VERSION, 'poise_application/version' +end diff --git a/cookbooks/application/files/halite_gem/poise_application/app_file_mixin.rb b/cookbooks/application/files/halite_gem/poise_application/app_file_mixin.rb new file mode 100644 index 0000000..8ad14a9 --- /dev/null +++ b/cookbooks/application/files/halite_gem/poise_application/app_file_mixin.rb @@ -0,0 +1,64 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise/utils' + +require 'poise_application/app_mixin' + + +module PoiseApplication + # A helper mixin for `file`-like resources to make them take application + # resource data. Relative paths are expanded against the application path and + # the app owner/group are the default user/group for the resource. + # + # @api private + # @since 5.1.0 + module AppFileMixin + include Poise::Utils::ResourceProviderMixin + + module Resource + include PoiseApplication::AppMixin + + def initialize(*) + super + # So our lazy default below can work. Not needed on 12.7+. + remove_instance_variable(:@path) if instance_variable_defined?(:@path) + end + + # @!attribute path + # Override the default path to be relative to the app path. + # @return [String] + attribute(:path, kind_of: String, default: lazy { parent ? ::File.expand_path(name, parent.path) : name }) + + # @!attribute group + # Override the default group to be the app group if unspecified. + # @return [String, Integer] + attribute(:group, kind_of: [String, Integer, NilClass], default: lazy { parent && parent.group }) + + # @!attribute owner + # Override the default user to be the app owner if unspecified. + # @return [String, Integer] + attribute(:owner, kind_of: [String, Integer, NilClass], default: lazy { parent && parent.owner }) + + # For the forgetful. + alias_method :user, :owner + end + + module Provider + include PoiseApplication::AppMixin + end + end +end diff --git a/cookbooks/application/files/halite_gem/poise_application/app_mixin.rb b/cookbooks/application/files/halite_gem/poise_application/app_mixin.rb new file mode 100644 index 0000000..611d1f8 --- /dev/null +++ b/cookbooks/application/files/halite_gem/poise_application/app_mixin.rb @@ -0,0 +1,69 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/mash' +require 'poise/provider' +require 'poise/resource' +require 'poise/utils' + + +module PoiseApplication + # A helper mixin for application resources and providers. These are things + # intended to be used as subresources of the `application` resource. + # + # @since 5.0.0 + module AppMixin + include Poise::Utils::ResourceProviderMixin + + # A helper mixin for application resources. + module Resource + include Poise::Resource + + # Set the parent type and optional flag. + poise_subresource(:application, true) + + # @!attribute path + # Base path for the application. + # @return [String] + attribute(:path, kind_of: String, name_attribute: true) + + # A delegator for accessing the application state. If no application + # parent is found, the state will be tracked internally within the + # resource. + # + # @return [Hash] + def app_state + if parent + parent.app_state + else + # If there isn't a parent, just track within the resource. + @local_app_state ||= Mash.new + end + end + + # Environment variables stored in the application state. + # + # @return [Hash] + def app_state_environment + app_state[:environment] ||= Mash.new + end + end + + module Provider + include Poise::Provider + end + end +end diff --git a/cookbooks/application/files/halite_gem/poise_application/cheftie.rb b/cookbooks/application/files/halite_gem/poise_application/cheftie.rb new file mode 100644 index 0000000..52e47b2 --- /dev/null +++ b/cookbooks/application/files/halite_gem/poise_application/cheftie.rb @@ -0,0 +1,17 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise_application/resources' diff --git a/cookbooks/application/files/halite_gem/poise_application/error.rb b/cookbooks/application/files/halite_gem/poise_application/error.rb new file mode 100644 index 0000000..ed43760 --- /dev/null +++ b/cookbooks/application/files/halite_gem/poise_application/error.rb @@ -0,0 +1,24 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + + +module PoiseApplication + # Base exception class for poise-application errors. + # + # @since 5.0.0 + class Error < Exception + end +end diff --git a/cookbooks/application/files/halite_gem/poise_application/resources.rb b/cookbooks/application/files/halite_gem/poise_application/resources.rb new file mode 100644 index 0000000..31129bd --- /dev/null +++ b/cookbooks/application/files/halite_gem/poise_application/resources.rb @@ -0,0 +1,30 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise_application/resources/application' +require 'poise_application/resources/application_cookbook_file' +require 'poise_application/resources/application_directory' +require 'poise_application/resources/application_file' +require 'poise_application/resources/application_template' + + +module PoiseApplication + # Chef resources and providers for poise-application. + # + # @since 5.0.0 + module Resources + end +end diff --git a/cookbooks/application/files/halite_gem/poise_application/resources/application.rb b/cookbooks/application/files/halite_gem/poise_application/resources/application.rb new file mode 100644 index 0000000..524a124 --- /dev/null +++ b/cookbooks/application/files/halite_gem/poise_application/resources/application.rb @@ -0,0 +1,259 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/dsl/recipe' # On 12.4+ this will pull in chef/dsl/resources. +require 'chef/resource' +require 'chef/provider' +require 'poise' + + +module PoiseApplication + module Resources + # (see Application::Resource) + # @since 5.0.0 + module Application + # An `application` resource to manage application deployment. + # + # @since 5.0.0 + # @provides application + # @action deploy + # @action start + # @action stop + # @action restart + # @action reload + # @example + # application '/srv/myapp' do + # git '...' + # poise_service 'myapp' do + # command '/srv/myapp/main' + # end + # end + class Resource < Chef::Resource + include Poise(container: true, container_namespace: false) + provides(:application) + actions(:deploy, :start, :stop, :restart, :reload) + + # @!attribute path + # Application base path. + # @return [String] + attribute(:path, kind_of: String, name_attribute: true) + # @!attribute environment + # Environment variables to set for the whole application. + # @return [Hash] + attribute(:environment, kind_of: Hash, default: lazy { Mash.new }) + # @!attribute owner + # System user that will own the application. This can be overriden in + # individual subresources. + # @return [String] + attribute(:owner, kind_of: String) + # @!attribute group + # System group that will own the application. This can be overriden in + # individual subresources. + # @return [String] + attribute(:group, kind_of: String) + # @!attribute action_on_update + # Action to run when any subresource is updated. Defaults to `:restart`. + # @return [String, Symbol, nil, false] + attribute(:action_on_update, kind_of: [Symbol, String, NilClass, FalseClass], default: :restart) + # @!attribute action_on_update_immediately + # Run the {#action_on_update} notification with `:immediately`. + # @return [Boolean] + attribute(:action_on_update_immediately, equal_to: [true, false], default: false) + + # Run the DSL rewire when the resource object is created. + # @api private + def initialize(*args) + super + _rewire_dsl! if node + end + + # Application-specific state values used as a way to communicate between + # subresources. + # + # @return [Mash] + # @example + # if new_resource.parent && new_resource.parent.app_state['gemfile_path'] + def app_state + @app_state ||= Mash.new(environment: environment) + end + + # Override Container#register_subresource to add our action_on_update. + # + # @api private + def register_subresource(resource) + super.tap do |added| + if added && action_on_update + Chef::Log.debug("[#{self}] Registering #{action_on_update_immediately ? 'immediate ' : ''}#{action_on_update} notification from #{resource}") + resource.notifies action_on_update.to_sym, self, (action_on_update_immediately ? :immediately : :delayed) + end + end + end + + private + + # Find all resources that need to be rewired. This is anything with a + # name starting with application_. + # + # @return [Array] + def _rewire_resources + if defined?(Chef::DSL::Resources) + # Chef >= 12.4. + Chef::DSL::Resources.instance_methods + else + # Chef < 12.4 >= 12.0. + Chef::Resource.descendants.map do |klass| + klass.node_map.instance_variable_get(:@map).keys + if klass.dsl_name.include?('::') + # Probably not valid. + # :nocov: + [] + # :nocov: + else + # Needed for things that don't call provides(). + [klass.dsl_name] + end + end.flatten + end.map {|name| name.to_s }.select {|name| name.start_with?('application_') }.uniq + end + + # Find all cookbooks that might contain LWRPs matching our name scheme. + # + # @return [Array] + def _rewire_cookbooks + # Run context might be unset during test setup. + if run_context + run_context.cookbook_collection.keys.select {|cookbook_name| cookbook_name.start_with?('application_') } + else + [] + end + end + + # Build the mapping of new_name => old_name for each resource to rewire. + # + # @return [Hash] + def _rewire_map + application_cookbooks = _rewire_cookbooks + _rewire_resources.inject({}) do |memo, name| + # Grab the resource class to check if it is an LWRP. + klass = Chef::Resource.resource_for_node(name.to_sym, node) + # Find the part to trim. Check for LWRP first, then just application_. + trim = if klass < Chef::Resource::LWRPBase + application_cookbooks.find {|cookbook_name| name.start_with?(cookbook_name) && name != cookbook_name } || 'application' + else + # Non-LWRPs are assumed to have a better name. + 'application' + end + # Map trimmed to untrimmed. + memo[name[trim.length+1..-1]] = name + memo + end + end + + # Build new DSL methods to implement the foo -> application_foo behavior. + # + # @return [void] + def _rewire_dsl! + # Generate stub methods for all the rewiring. + _rewire_map.each do |new_name, old_name| + # This is defined as a singleton method on self so it looks like + # the DSL but is scoped to just this context. + define_singleton_method(new_name) do |name=nil, *args, &block| + # Store the caller to correct the source_line. + created_at = caller[0] + public_send(old_name, name, *args) do + # Set the declared type to be the native name. + self.declared_type = self.class.resource_name + # Fix the source location. For Chef 12.4 we could do this with the + # declared_at parameter on the initial send. + self.source_line = created_at + # Run the original block. + instance_exec(&block) if block + end + end + end + end + end + + # Provider for `application`. + # + # @since 5.0.0 + # @see Resource + # @provides application + class Provider < Chef::Provider + include Poise + provides(:application) + + # `deploy` action for `application`. Creates the application base folder. + # + # @return [void] + def action_deploy + notifying_block do + directory new_resource.path do + owner new_resource.owner + group new_resource.group + mode '755' + end + end + end + + # `start` action for `application`. Proxies to subresources. + # + # @return [void] + def action_start + proxy_action(:start) + end + + # `stop` action for `application`. Proxies to subresources. + # + # @return [void] + def action_stop + proxy_action(:stop) + end + + # `restart` action for `application`. Proxies to subresources. + # + # @return [void] + def action_restart + proxy_action(:restart) + end + + # `reload` action for `application`. Proxies to subresources. + # + # @return [void] + def action_reload + proxy_action(:reload) + end + + private + + # Proxy an action to any subresources that support it. + # + # @param action [Symbol] Action to proxy. + # @return [void] + def proxy_action(action) + Chef::Log.debug("[#{new_resource} Running proxied #{action} action") + new_resource.subresources.each do |r| + begin + r.run_action(action) if r.allowed_actions.include?(action) + rescue Chef::Exceptions::UnsupportedAction + # Don't care, just move on. + end + end + end + + end + end + end +end diff --git a/cookbooks/application/files/halite_gem/poise_application/resources/application_cookbook_file.rb b/cookbooks/application/files/halite_gem/poise_application/resources/application_cookbook_file.rb new file mode 100644 index 0000000..aeb6ead --- /dev/null +++ b/cookbooks/application/files/halite_gem/poise_application/resources/application_cookbook_file.rb @@ -0,0 +1,54 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise_application/app_file_mixin' + + +module PoiseApplication + module Resources + # (see ApplicationCookbookFile::Resource) + # @since 5.1.0 + module ApplicationCookbookFile + # An `application_cookbook_file` resource to manage Chef cookbook_files inside and + # Application cookbook deployment. + # + # @provides application_cookbook_file + # @action create + # @action create_if_missing + # @action delete + # @action touch + # @example + # application '/srv/myapp' do + # cookbook_file 'myapp.conf' do + # source 'myapp.conf' + # end + # end + class Resource < Chef::Resource::CookbookFile + include PoiseApplication::AppFileMixin + provides(:application_cookbook_file) + actions(:create, :create_if_missing, :delete, :touch) + subclass_providers! + + def initialize(*args) + super + # For older Chef. + @resource_name = :application_cookbook_file + end + end + + end + end +end diff --git a/cookbooks/application/files/halite_gem/poise_application/resources/application_directory.rb b/cookbooks/application/files/halite_gem/poise_application/resources/application_directory.rb new file mode 100644 index 0000000..a32bef5 --- /dev/null +++ b/cookbooks/application/files/halite_gem/poise_application/resources/application_directory.rb @@ -0,0 +1,50 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise_application/app_file_mixin' + + +module PoiseApplication + module Resources + # (see ApplicationDirectory::Resource) + # @since 5.1.0 + module ApplicationDirectory + # An `application_directory` resource to manage Chef files inside and + # Application cookbook deployment. + # + # @provides application_directory + # @action create + # @action delete + # @example + # application '/srv/myapp' do + # directory 'logs' + # end + class Resource < Chef::Resource::Directory + include PoiseApplication::AppFileMixin + provides(:application_directory) + actions(:create, :delete) + subclass_providers! + + def initialize(*args) + super + # For older Chef. + @resource_name = :application_directory + end + end + + end + end +end diff --git a/cookbooks/application/files/halite_gem/poise_application/resources/application_file.rb b/cookbooks/application/files/halite_gem/poise_application/resources/application_file.rb new file mode 100644 index 0000000..95eac83 --- /dev/null +++ b/cookbooks/application/files/halite_gem/poise_application/resources/application_file.rb @@ -0,0 +1,54 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise_application/app_file_mixin' + + +module PoiseApplication + module Resources + # (see ApplicationFile::Resource) + # @since 5.1.0 + module ApplicationFile + # An `application_file` resource to manage Chef files inside and + # Application cookbook deployment. + # + # @provides application_file + # @action create + # @action create_if_missing + # @action delete + # @action touch + # @example + # application '/srv/myapp' do + # file 'myapp.conf' do + # source 'myapp.conf.erb' + # end + # end + class Resource < Chef::Resource::File + include PoiseApplication::AppFileMixin + provides(:application_file) + actions(:create, :create_if_missing, :delete, :touch) + subclass_providers! + + def initialize(*args) + super + # For older Chef. + @resource_name = :application_file + end + end + + end + end +end diff --git a/cookbooks/application/files/halite_gem/poise_application/resources/application_template.rb b/cookbooks/application/files/halite_gem/poise_application/resources/application_template.rb new file mode 100644 index 0000000..dff0151 --- /dev/null +++ b/cookbooks/application/files/halite_gem/poise_application/resources/application_template.rb @@ -0,0 +1,54 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise_application/app_file_mixin' + + +module PoiseApplication + module Resources + # (see ApplicationTemplate::Resource) + # @since 5.1.0 + module ApplicationTemplate + # An `application_template` resource to manage Chef templates inside and + # Application cookbook deployment. + # + # @provides application_template + # @action create + # @action create_if_missing + # @action delete + # @action touch + # @example + # application '/srv/myapp' do + # template 'myapp.conf' do + # source 'myapp.conf.erb' + # end + # end + class Resource < Chef::Resource::Template + include PoiseApplication::AppFileMixin + provides(:application_template) + actions(:create, :create_if_missing, :delete, :touch) + subclass_providers! + + def initialize(*args) + super + # For older Chef. + @resource_name = :application_template + end + end + + end + end +end diff --git a/cookbooks/application/files/halite_gem/poise_application/service_mixin.rb b/cookbooks/application/files/halite_gem/poise_application/service_mixin.rb new file mode 100644 index 0000000..0649159 --- /dev/null +++ b/cookbooks/application/files/halite_gem/poise_application/service_mixin.rb @@ -0,0 +1,116 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/resource' +require 'chef/provider' +require 'poise/utils' +require 'poise_service/service_mixin' +require 'poise_service/utils' + +require 'poise_application/app_mixin' +require 'poise_application/utils' + + +module PoiseApplication + # Mixin for application services. This is any resource that will be part of + # an application deployment and involves running a persistent service. + # + # @api public + # @since 5.0.0 + # @example + # module MyApp + # class Resource < Chef::Resource + # include Poise + # provides(:my_app) + # include PoiseApplication::ServiceMixin + # end + # + # class Provider < Chef::Provider + # include Poise + # provides(:my_app) + # include PoiseApplication::ServiceMixin + # + # def action_enable + # notifying_block do + # template '/etc/myapp.conf' do + # # ... + # end + # end + # super + # end + # + # def service_options(r) + # super + # r.command('myapp --serve') + # end + # end + # end + module ServiceMixin + include Poise::Utils::ResourceProviderMixin + + # Mixin for application service resources. + # + # @see ServiceMixin + module Resource + include PoiseService::ServiceMixin::Resource + include PoiseApplication::AppMixin::Resource + + module ClassMethods + # @api private + def included(klass) + super + klass.extend(ClassMethods) + klass.class_exec do + attribute(:path, kind_of: String, name_attribute: true) + # Redefines from the PoiseService version so we get a better default. + attribute(:service_name, kind_of: String, default: lazy { PoiseService::Utils.parse_service_name(path) }) + attribute(:user, kind_of: [String, Integer], default: lazy { parent ? parent.owner : 'root' }) + end + end + end + + extend ClassMethods + end + + # Mixin for application service providers. + # + # @see ServiceMixin + module Provider + include PoiseService::ServiceMixin::Provider + include PoiseApplication::AppMixin::Provider + + private + + # Abstract hook to set parameters on {#service_resource} when it is + # created. This is required to set at least `resource.command`. + # + # @api public + # @param resource [Chef::Resource] Resource instance to set parameters on. + # @return [void] + # @example + # def service_options(resource) + # super + # resource.command('myapp --serve') + # end + def service_options(resource) + super + resource.directory(new_resource.path) + resource.user(new_resource.user) + resource.environment.update(new_resource.app_state_environment) if new_resource.parent + end + end + end +end diff --git a/cookbooks/application/files/halite_gem/poise_application/utils.rb b/cookbooks/application/files/halite_gem/poise_application/utils.rb new file mode 100644 index 0000000..0a93c77 --- /dev/null +++ b/cookbooks/application/files/halite_gem/poise_application/utils.rb @@ -0,0 +1,51 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'etc' + + +module PoiseApplication + # Utility methods for PoiseApplication. + # + # @api public + # @since 5.0.0 + module Utils + # Methods are also available as module-level methods as well as a mixin. + extend self + + # Try to find the primary group name for a given user. + # + # @param user [String, Integer] User to check, if given as an integer this + # is used as a UID, otherwise it is the username. + # @return [String] + # @example + # attribute(:group, kind_of: [String, Integer], default: lazy { PoiseApplication::Utils.primary_group_for(user) }) + def primary_group_for(user) + # Force a reload in case any users were created earlier in the run. + Etc.endpwent + Etc.endgrent + user = if user.is_a?(Integer) + Etc.getpwuid(user) + else + Etc.getpwnam(user.to_s) + end + Etc.getgrgid(user.gid).name + rescue ArgumentError + # One of the get* calls exploded. ¯\_(ツ)_/¯ + user.to_s + end + end +end diff --git a/cookbooks/application/files/halite_gem/poise_application/version.rb b/cookbooks/application/files/halite_gem/poise_application/version.rb new file mode 100644 index 0000000..02c4411 --- /dev/null +++ b/cookbooks/application/files/halite_gem/poise_application/version.rb @@ -0,0 +1,20 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + + +module PoiseApplication + VERSION = '5.2.0' +end diff --git a/cookbooks/application/libraries/default.rb b/cookbooks/application/libraries/default.rb new file mode 100644 index 0000000..21614d8 --- /dev/null +++ b/cookbooks/application/libraries/default.rb @@ -0,0 +1,19 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +raise 'Halite is not compatible with no_lazy_load false, please set no_lazy_load true in your Chef configuration file.' unless Chef::Config[:no_lazy_load] +$LOAD_PATH << File.expand_path('../../files/halite_gem', __FILE__) +require "poise_application/cheftie" diff --git a/cookbooks/application/metadata.json b/cookbooks/application/metadata.json new file mode 100644 index 0000000..02fb71f --- /dev/null +++ b/cookbooks/application/metadata.json @@ -0,0 +1 @@ +{"name":"application","version":"5.2.0","description":"A Chef cookbook for deploying application code.","long_description":"# Application cookbook\n\n[![Build Status](https://img.shields.io/travis/poise/application.svg)](https://travis-ci.org/poise/application)\n[![Gem Version](https://img.shields.io/gem/v/poise-application.svg)](https://rubygems.org/gems/poise-application)\n[![Cookbook Version](https://img.shields.io/cookbook/v/application.svg)](https://supermarket.chef.io/cookbooks/application)\n[![Coverage](https://img.shields.io/codeclimate/coverage/github/poise/application.svg)](https://codeclimate.com/github/poise/application)\n[![Gemnasium](https://img.shields.io/gemnasium/poise/application.svg)](https://gemnasium.com/poise/application)\n[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)\n\nA [Chef](https://www.chef.io/) cookbook to deploy applications.\n\n## Getting Started\n\nThe application cookbook provides a central framework to deploy applications\nusing Chef. Generally this will be web applications using things like Rails,\nDjango, or NodeJS, but the framework makes no specific assumptions. The core\n`application` resource provides DSL support and helpers, but the heavy lifting\nis all done in specific plugins detailed below. Each deployment starts with\nan `application` resource:\n\n```ruby\napplication '/path/to/deploy' do\n owner 'root'\n group 'root'\n\n # ...\nend\n```\n\nThe `application` resource uses the Poise subresource system for plugins. This\nmeans you configure the steps of the deployment like normal recipe code inside\nthe `application` resource, with a few special additions:\n\n```ruby\napplication '/path/to/deploy' do\n # Application resource properties.\n owner 'root'\n group 'root'\n\n # Subresources, like normal recipe code.\n package 'ruby'\n git '/path/to/deploy' do\n repository 'https://github.com/example/myapp.git'\n end\n application_rails '/path/to/deploy' do\n database 'mysql://dbhost/myapp'\n end\nend\n```\n\nWhen evaluating the recipe inside the `application` resource, it first checks\nfor `application_#{resource}`, as well as looking for an LWRP of the same name\nin any cookbook starting with `application_`. This means that a resource named\n`application_foo` can be used as `foo` inside the `application` resource:\n\n```ruby\napplication '/path/to/deploy' do\n owner 'root'\n group 'root'\n\n rails '/path/to/deploy' do\n database 'mysql://dbhost/myapp'\n end\nend\n```\n\nAdditionally if a resource inside the `application` block doesn't have a name,\nit uses the same name as the application resource itself:\n\n```ruby\napplication '/path/to/deploy' do\n owner 'root'\n group 'root'\n\n rails do\n database 'mysql://dbhost/myapp'\n end\nend\n```\n\nOther than those two special features, the recipe code inside the `application`\nresource is processed just like any other recipe.\n\n## Available Plugins\n\n* [`application_git`](https://github.com/poise/application_git) – Deploy\n application code from a git repository.\n* [`application_ruby`](https://github.com/poise/application_ruby) – Manage Ruby\n deployments, such as Rails or Sinatra applications.\n* [`application_python`](https://github.com/poise/application_python) – Manage\n Python deployments, such as Django or Flask applications.\n* [`application_javascript`](https://github.com/poise/application_javascript) –\n Manage server-side JavaScript deployments using Node.js or io.js.\n* `application_java` – *Coming soon!*\n* `application_go` – *Coming soon!*\n* `application_erlang` – *Coming soon!*\n\n## Requirements\n\nChef 12 or newer is required.\n\n## Resources\n\n### `application`\n\nThe `application` resource has top-level configuration properties for each\ndeployment and acts as a container for other deployment plugin resources.\n\n```ruby\napplication '/opt/test_sinatra' do\n git 'https://github.com/example/my_sinatra_app.git'\n bundle_install do\n deployment true\n end\n unicorn do\n port 9000\n end\nend\n```\n\n#### Actions\n\n* `:deploy` – Deploy the application. *(default)*\n* `:start` - Run `:start` on all subresources that support it.\n* `:stop` - Run `:stop` on all subresources that support it.\n* `:restart` - Run `:restart` on all subresources that support it.\n* `:reload` - Run `:reload` on all subresources that support it.\n\n#### Properties\n\n* `path` – Path to deploy the application to. *(name attribute)*\n* `environment` – Environment variables for all application deployment steps.\n* `group` – System group to deploy the application as.\n* `owner` – System user to deploy the application as.\n* `action_on_update` – Action to run on the application resource when any\n subresource is updated. *(default: restart)*\n* `action_on_update_immediately` – Run the `action_on_update` notification with\n `:immediately`. *(default: false)*\n\n### `application_cookbook_file`, `application_directory`, `application_file`, `application_template`\n\nThe `application_cookbook_file`, `application_directory`, `application_file`, and `application_template`\nresources extend the core Chef resources to take some application-level\nconfiguration in to account:\n\n```ruby\napplication '/opt/myapp' do\n template 'myapp.conf' do\n source 'myapp.conf.erb'\n end\n directory 'logs'\nend\n```\n\nIf the resource name is a relative path, it will be expanded relative to the\napplication path. If an owner or group is declared for the application, those\nwill be the default user and group for the resource.\n\nAll other actions and properties are the same as the similar resource in core Chef.\n\n## Examples\n\nSome test recipes are available as examples for common application frameworks:\n\n* [Sinatra](https://github.com/poise/application_ruby/blob/master/test/cookbooks/application_ruby_test/recipes/sinatra.rb)\n* [Rails](https://github.com/poise/application_ruby/blob/master/test/cookbooks/application_ruby_test/recipes/rails.rb)\n* [Flask](https://github.com/poise/application_python/blob/master/test/cookbook/recipes/flask.rb)\n* [Django](https://github.com/poise/application_python/blob/master/test/cookbook/recipes/django.rb)\n* [Express](https://github.com/poise/application_javascript/blob/master/test/cookbook/recipes/express.rb)\n\n## Upgrading From 4.x\n\nWhile the overall design of the revamped application resource is similar to the\n4.x version, some changes will need to be made. The `name` property no longer\nexists, with the name attribute being used as the path to the deployment.\nThe `packages` property has been removed as this is more easily handled via\nnormal recipe code.\n\nThe SCM-related properties like `repository` and `revision` are now handled by\nnormal plugins. If you were deploying from a private git repository you will\nlikely want to use the `application_git` cookbook, otherwise just use the\nbuilt-in `git` or `svn` resources as per normal.\n\nThe properties related to the `deploy` resource like `strategy` and `symlinks`\nhave been removed. The `deploy` resource is no longer used so these aren't\nrelevant. As a side effect of this, you'll likely want to point the upgraded\ndeployment at a new folder or manually clean the `current` and `shared` folders\nfrom the existing folder. The pseudo-Capistrano layout used by the `deploy`\nresource has few benefits in a config-managed world and introduced a lot of\ncomplexity and moving pieces that are no longer required.\n\nWith the removal of the `deploy` resource, the callback properties and commands\nare no longer used as well. Subresources no longer use the complex\nactions-as-callbacks arrangement as existed before, instead following normal\nChef recipe flow. Individual subresources may need to be tweaked to work with\nnewer versions of the cookbooks they come from, though most have stayed similar\nin overall approach.\n\n## Database Migrations and Chef\n\nSeveral of the web application deployment plugins include optional support to\nrun database migrations from Chef. For \"toy\" applications where the app and\ndatabase run together on a single machine, this is fine and is a nice time\nsaver. For anything more complex I highly recommend not running database\nmigrations from Chef. Some initial operations like creating the database and/or\ndatabase user are more reasonable as they tend to be done only once and by their\nnature the application does not yet have users so some level of eventual\nconsistency is more acceptable. With migrations on a production application, I\nencourage using Chef and the application cookbooks to handle deploying the code\nand writing configuration files, but use something more specific to run the\nactual migration task. [Fabric](http://www.fabfile.org/),\n[Capistrano](http://capistranorb.com/), and [Rundeck](http://rundeck.org/) are\nall good choices for this orchestration tooling.\n\nMigrations can generally be applied idempotently but they have unique\nconstraints (pun definitely intended) that make them tricky in a Chef-like,\nconvergence-based system. First and foremost is that many table alterations\nlock the table for updating for at least some period of time. That can mean that\nwhile staging the new code or configuration data can happen within a window, the\nmigration itself needs to be run in careful lockstep with the rest of the\ndeployment process (eg. moving things in and out of load balancers). Beyond\nthat, while most web frameworks have internal idempotence checks for migrations,\nrunning the process on two servers at the same time can have unexpected effects.\n\nOverall migrations are best thought of as a procedural step rather than a\ndeclaratively modeled piece of the system.\n\n## Application Signals and Updates\n\nThe `application` resource exposes `start`, `stop`, `restart`, and `reload`\nactions which will dispatch to any subresources attached to the application.\nThis allows for generic application-level restart or reload signals that will\nwork with any type of deployment.\n\nAdditionally the `action_on_update` property is used to set a default\nnotification so any subresource that updates will trigger an application\nrestart or reload. This can be disabled by setting `action_on_update false` if\nyou want to take manual control of service restarts.\n\n## Sponsors\n\nDevelopment sponsored by [Chef Software](https://www.chef.io/), [Symonds & Son](http://symondsandson.com/), and [Orion](https://www.orionlabs.co/).\n\nThe Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/).\n\n## License\n\nCopyright 2015-2016, Noah Kantrowitz\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","maintainer":"Noah Kantrowitz","maintainer_email":"noah@coderanger.net","license":"Apache-2.0","platforms":{"aix":">= 0.0.0","amazon":">= 0.0.0","arch":">= 0.0.0","centos":">= 0.0.0","chefspec":">= 0.0.0","debian":">= 0.0.0","dragonfly4":">= 0.0.0","fedora":">= 0.0.0","freebsd":">= 0.0.0","gentoo":">= 0.0.0","ios_xr":">= 0.0.0","mac_os_x":">= 0.0.0","nexus":">= 0.0.0","omnios":">= 0.0.0","openbsd":">= 0.0.0","opensuse":">= 0.0.0","oracle":">= 0.0.0","raspbian":">= 0.0.0","redhat":">= 0.0.0","slackware":">= 0.0.0","smartos":">= 0.0.0","solaris2":">= 0.0.0","suse":">= 0.0.0","ubuntu":">= 0.0.0","windows":">= 0.0.0"},"dependencies":{"poise":"~> 2.4","poise-service":"~> 1.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/poise/application","issues_url":"https://github.com/poise/application/issues","chef_version":[["< 14",">= 12"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/application_git/CHANGELOG.md b/cookbooks/application_git/CHANGELOG.md new file mode 100644 index 0000000..2cba57d --- /dev/null +++ b/cookbooks/application_git/CHANGELOG.md @@ -0,0 +1,10 @@ +# Application_Git Changelog + +## v1.1.0 + +* [#2](https://github.com/poise/application_git/issues/2) – Inherit user and group values from the parent `application` resource. +* [#3](https://github.com/poise/application_git/issues/3) – Fix usage with users created during the current Chef run. + +## v1.0.0 + +* Initial release. diff --git a/cookbooks/application_git/README.md b/cookbooks/application_git/README.md new file mode 100644 index 0000000..932fd3a --- /dev/null +++ b/cookbooks/application_git/README.md @@ -0,0 +1,108 @@ +# Application_Git Cookbook + +[![Build Status](https://img.shields.io/travis/poise/application_git.svg)](https://travis-ci.org/poise/application_git) +[![Gem Version](https://img.shields.io/gem/v/poise-application-git.svg)](https://rubygems.org/gems/poise-application-git) +[![Cookbook Version](https://img.shields.io/cookbook/v/application_git.svg)](https://supermarket.chef.io/cookbooks/application_git) +[![Coverage](https://img.shields.io/codecov/c/github/poise/application_git.svg)](https://codecov.io/github/poise/application_git) +[![Gemnasium](https://img.shields.io/gemnasium/poise/application_git.svg)](https://gemnasium.com/poise/application_git) +[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) + +A [Chef](https://www.chef.io/) cookbook to handle deploying code from git when +using the [application cookbook](https://github.com/poise/application). + +## Quick Start + +To deploy from a private GitHub repository: + +```ruby +application '/srv/myapp' do + git 'git@github.com:example/myapp.git' do + deploy_key chef_vault_item('deploy_keys', 'myapp')['key'] + end +end +``` + +## Requirements + +Chef 12 or newer is required. + +## Resources + +### `application_git` + +The `application_git` resource deploys code from git. It extends the core `git` +resource to support deploy keys and disabling strict host key verification. + +```ruby +application '/srv/myapp' do + git 'git@github.com:example/myapp.git' +end +``` + +#### Actions + +All actions work the same as the core `git` resource. + +* `:sync` – Clone and checkout the requested revision *(default)* +* `:checkout` – Checkout the request revision. If the repository isn't already + cloned, this action does nothing. +* `:export` – Export the repository without the `.git` folder. + +#### Properties + +All properties from the core `git` resource work the same way with the following +additions: + +* `deploy_key` – SSH key to use with git. Can be specified either as a path to + key file already created or as a string value containing the key directly. +* `strict_ssh` – Enable strict SSH host key checking. *(default: false)* + +### DSL Usage + +The `application_git` resource can be used directly as a replacement for the +core `git` resource: + +```ruby +application_git '/srv/myapp' do + repository 'git@github.com:example/myapp.git' + deploy_key chef_vault_item('deploy_keys', 'myapp')['key'] +end +``` + +Within the `application` resource, a simplified DSL is available. As with other +`application` plugins, the default name of the resource if unspecified is the +application path. The following two examples are equivalent: + +```ruby +application '/srv/myapp' do + git do + repository 'git@github.com:example/myapp.git' + end +end + +application '/srv/myapp' do + git 'git@github.com:example/myapp.git' +end +``` + +## Sponsors + +Development sponsored by [Chef Software](https://www.chef.io/), [Symonds & Son](http://symondsandson.com/), and [Orion](https://www.orionlabs.co/). + +The Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/). + +## License + +Copyright 2015-2016, Noah Kantrowitz + +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/cookbooks/application_git/files/halite_gem/poise-application-git.rb b/cookbooks/application_git/files/halite_gem/poise-application-git.rb new file mode 100644 index 0000000..bc97c9f --- /dev/null +++ b/cookbooks/application_git/files/halite_gem/poise-application-git.rb @@ -0,0 +1,17 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise_application_git' diff --git a/cookbooks/application_git/files/halite_gem/poise_application_git.rb b/cookbooks/application_git/files/halite_gem/poise_application_git.rb new file mode 100644 index 0000000..56cb8bb --- /dev/null +++ b/cookbooks/application_git/files/halite_gem/poise_application_git.rb @@ -0,0 +1,21 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise_application_git/resource' + + +module PoiseApplicationGit +end diff --git a/cookbooks/application_git/files/halite_gem/poise_application_git/cheftie.rb b/cookbooks/application_git/files/halite_gem/poise_application_git/cheftie.rb new file mode 100644 index 0000000..6fcd9c3 --- /dev/null +++ b/cookbooks/application_git/files/halite_gem/poise_application_git/cheftie.rb @@ -0,0 +1,17 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise_application_git/resource' diff --git a/cookbooks/application_git/files/halite_gem/poise_application_git/resource.rb b/cookbooks/application_git/files/halite_gem/poise_application_git/resource.rb new file mode 100644 index 0000000..ffcf3c2 --- /dev/null +++ b/cookbooks/application_git/files/halite_gem/poise_application_git/resource.rb @@ -0,0 +1,204 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'zlib' + +require 'chef/provider' +require 'chef/resource' +require 'poise_application/app_mixin' +require 'poise_application/resources/application' + +require 'poise_application_git/safe_string' + + +module PoiseApplicationGit + # An `application_git` resource to clone application code from git. + # + # @since 1.0.0 + # @provides application_git + # @action sync + # @action checkout + # @action export + # @example + # application '/srv/myapp' do + # git 'git@github.com:example/myapp.git' do + # deploy_key data_bag_item('deploy_keys', 'myapp')['key'] + # end + # end + class Resource < Chef::Resource::Git + include PoiseApplication::AppMixin + provides(:application_git) + + # @api private + def initialize(*args) + super + # Because the superclass declares this, we have to as well. Should be + # removable at some point when Chef makes everything use the provider + # resolver system instead. + @resource_name = :application_git + @provider = PoiseApplicationGit::Provider + # Clear defaults in older versions of Chef. + remove_instance_variable(:@group) if instance_variable_defined?(:@group) + remove_instance_variable(:@user) if instance_variable_defined?(:@user) + end + + # @!attribute group + # Group to run git as. Defaults to the application group. + # @return [String, Integer, nil, false] + attribute(:group, kind_of: [String, Integer, NilClass, FalseClass], default: lazy { parent && parent.group }) + # @!attribute strict_ssh + # Enable strict SSH host key checking. Defaults to false. + # @return [Boolean] + attribute(:strict_ssh, equal_to: [true, false], default: false) + # @!attribute user + # User to run git as. Defaults to the application owner. + # @return [String, Integer, nil, false] + attribute(:user, kind_of: [String, Integer, NilClass, FalseClass], default: lazy { parent && parent.owner }) + + # @api private + def after_created + # Allow using the repository as the name in an application block. + if parent && !repository + destination(parent.path) + repository(name) + end + end + + # @!attribute deploy_key + # SSH deploy key as either a string value or a path to a key file. + # @return [String] + def deploy_key(val=nil) + # Use a SafeString for literal deploy keys so they aren't shown. + val = SafeString.new(val) if val && !deploy_key_is_local?(val) + set_or_return(:deploy_key, val, kind_of: String) + end + + # Default SSH wrapper path. + # + # @api private + # @return [String] + def ssh_wrapper_path + @ssh_wrapper_path ||= ::File.expand_path("~#{user}/.ssh/ssh_wrapper_#{Zlib.crc32(name)}") + end + + # Guess if the deploy key is a local path or literal value. + # + # @api private + # @param key [String, nil] Key value to check. Defaults to self.key. + # @return [Boolean] + def deploy_key_is_local?(key=nil) + key ||= deploy_key + key && key[0] == '/' + end + + # Path to deploy key. + # + # @api private + # @return [String] + def deploy_key_path + @deploy_key_path ||= if deploy_key_is_local? + deploy_key + else + ::File.expand_path("~#{user}/.ssh/id_deploy_#{Zlib.crc32(name)}") + end + end + end + + # Provider for `application_git`. + # + # @since 1.0.0 + # @see Resource + # @provides application_git + class Provider < Chef::Provider::Git + include PoiseApplication::AppMixin + provides(:application_git) + + # @api private + def initialize(*args) + super + # Set the SSH wrapper path in a late-binding kind of way. This better + # supports situations where the user doesn't exist until Chef converges. + new_resource.ssh_wrapper(new_resource.ssh_wrapper_path) if new_resource.deploy_key + end + + # @api private + def whyrun_supported? + false # Just not dealing with this right now + end + + # Hack our special login in before load_current_resource runs because that + # needs access to the git remote. + # + # @api private + def load_current_resource + include_recipe('git') + notifying_block do + create_dotssh + write_deploy_key + write_ssh_wrapper + end if new_resource.deploy_key + super + end + + private + + # Create a .ssh folder for the user. + # + # @return [void] + def create_dotssh + directory ::File.expand_path("~#{new_resource.user}/.ssh") do + owner new_resource.user + group new_resource.group + mode '755' + end + end + + # Copy the deploy key to a file if needed. + # + # @return [void] + def write_deploy_key + # Check if we have a local path or some actual content + return if new_resource.deploy_key_is_local? + file new_resource.deploy_key_path do + owner new_resource.user + group new_resource.group + mode '600' + content new_resource.deploy_key + sensitive true + end + end + + # Create the SSH wrapper script. + # + # @return [void] + def write_ssh_wrapper + # Write out the GIT_SSH script, it should already be enabled above + file new_resource.ssh_wrapper_path do + owner new_resource.user + group new_resource.group + mode '700' + content %Q{#!/bin/sh\n/usr/bin/env ssh #{'-o "StrictHostKeyChecking=no" ' unless new_resource.strict_ssh}-i "#{new_resource.deploy_key_path}" $@\n} + end + end + + # Patch back in the `#git` from the git provider. This otherwise conflicts + # with the `#git` defined by the DSL, which gets included in such a way + # that the DSL takes priority. + def git(*args, &block) + Chef::Provider::Git.instance_method(:git).bind(self).call(*args, &block) + end + end +end diff --git a/cookbooks/application_git/files/halite_gem/poise_application_git/safe_string.rb b/cookbooks/application_git/files/halite_gem/poise_application_git/safe_string.rb new file mode 100644 index 0000000..c975c49 --- /dev/null +++ b/cookbooks/application_git/files/halite_gem/poise_application_git/safe_string.rb @@ -0,0 +1,25 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + + +module PoiseApplicationGit + # A string that won't be shown in Chef error output + class SafeString < String + def to_text + '"suppressed sensitive value"' + end + end +end diff --git a/cookbooks/application_git/files/halite_gem/poise_application_git/version.rb b/cookbooks/application_git/files/halite_gem/poise_application_git/version.rb new file mode 100644 index 0000000..0a67268 --- /dev/null +++ b/cookbooks/application_git/files/halite_gem/poise_application_git/version.rb @@ -0,0 +1,20 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + + +module PoiseApplicationGit + VERSION = '1.1.0' +end diff --git a/cookbooks/application_git/libraries/default.rb b/cookbooks/application_git/libraries/default.rb new file mode 100644 index 0000000..868f2a0 --- /dev/null +++ b/cookbooks/application_git/libraries/default.rb @@ -0,0 +1,19 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +raise 'Halite is not compatible with no_lazy_load false, please set no_lazy_load true in your Chef configuration file.' unless Chef::Config[:no_lazy_load] +$LOAD_PATH << File.expand_path('../../files/halite_gem', __FILE__) +require "poise_application_git/cheftie" diff --git a/cookbooks/application_git/metadata.json b/cookbooks/application_git/metadata.json new file mode 100644 index 0000000..32b4027 --- /dev/null +++ b/cookbooks/application_git/metadata.json @@ -0,0 +1 @@ +{"name":"application_git","version":"1.1.0","description":"A plugin for poise-application to deploy applications from git.","long_description":"# Application_Git Cookbook\n\n[![Build Status](https://img.shields.io/travis/poise/application_git.svg)](https://travis-ci.org/poise/application_git)\n[![Gem Version](https://img.shields.io/gem/v/poise-application-git.svg)](https://rubygems.org/gems/poise-application-git)\n[![Cookbook Version](https://img.shields.io/cookbook/v/application_git.svg)](https://supermarket.chef.io/cookbooks/application_git)\n[![Coverage](https://img.shields.io/codecov/c/github/poise/application_git.svg)](https://codecov.io/github/poise/application_git)\n[![Gemnasium](https://img.shields.io/gemnasium/poise/application_git.svg)](https://gemnasium.com/poise/application_git)\n[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)\n\nA [Chef](https://www.chef.io/) cookbook to handle deploying code from git when\nusing the [application cookbook](https://github.com/poise/application).\n\n## Quick Start\n\nTo deploy from a private GitHub repository:\n\n```ruby\napplication '/srv/myapp' do\n git 'git@github.com:example/myapp.git' do\n deploy_key chef_vault_item('deploy_keys', 'myapp')['key']\n end\nend\n```\n\n## Requirements\n\nChef 12 or newer is required.\n\n## Resources\n\n### `application_git`\n\nThe `application_git` resource deploys code from git. It extends the core `git`\nresource to support deploy keys and disabling strict host key verification.\n\n```ruby\napplication '/srv/myapp' do\n git 'git@github.com:example/myapp.git'\nend\n```\n\n#### Actions\n\nAll actions work the same as the core `git` resource.\n\n* `:sync` – Clone and checkout the requested revision *(default)*\n* `:checkout` – Checkout the request revision. If the repository isn't already\n cloned, this action does nothing.\n* `:export` – Export the repository without the `.git` folder.\n\n#### Properties\n\nAll properties from the core `git` resource work the same way with the following\nadditions:\n\n* `deploy_key` – SSH key to use with git. Can be specified either as a path to\n key file already created or as a string value containing the key directly.\n* `strict_ssh` – Enable strict SSH host key checking. *(default: false)*\n\n### DSL Usage\n\nThe `application_git` resource can be used directly as a replacement for the\ncore `git` resource:\n\n```ruby\napplication_git '/srv/myapp' do\n repository 'git@github.com:example/myapp.git'\n deploy_key chef_vault_item('deploy_keys', 'myapp')['key']\nend\n```\n\nWithin the `application` resource, a simplified DSL is available. As with other\n`application` plugins, the default name of the resource if unspecified is the\napplication path. The following two examples are equivalent:\n\n```ruby\napplication '/srv/myapp' do\n git do\n repository 'git@github.com:example/myapp.git'\n end\nend\n\napplication '/srv/myapp' do\n git 'git@github.com:example/myapp.git'\nend\n```\n\n## Sponsors\n\nDevelopment sponsored by [Chef Software](https://www.chef.io/), [Symonds & Son](http://symondsandson.com/), and [Orion](https://www.orionlabs.co/).\n\nThe Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/).\n\n## License\n\nCopyright 2015-2016, Noah Kantrowitz\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","maintainer":"Noah Kantrowitz","maintainer_email":"noah@coderanger.net","license":"Apache 2.0","platforms":{},"dependencies":{"git":">= 0.0.0","poise":"~> 2.0","application":"~> 5.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file diff --git a/cookbooks/application_javascript/CHANGELOG.md b/cookbooks/application_javascript/CHANGELOG.md new file mode 100644 index 0000000..ed8506a --- /dev/null +++ b/cookbooks/application_javascript/CHANGELOG.md @@ -0,0 +1,5 @@ +# Application_Javascript Changelog + +## v1.0.0 + +Initial release! diff --git a/cookbooks/application_javascript/README.md b/cookbooks/application_javascript/README.md new file mode 100644 index 0000000..57745f0 --- /dev/null +++ b/cookbooks/application_javascript/README.md @@ -0,0 +1,132 @@ +# Application_Javascript Cookbook + +[![Build Status](https://img.shields.io/travis/poise/application_javascript.svg)](https://travis-ci.org/poise/application_javascript) +[![Gem Version](https://img.shields.io/gem/v/poise-application-javascript.svg)](https://rubygems.org/gems/poise-application-javascript) +[![Cookbook Version](https://img.shields.io/cookbook/v/application_javascript.svg)](https://supermarket.chef.io/cookbooks/application_javascript) +[![Coverage](https://img.shields.io/codecov/c/github/poise/application_javascript.svg)](https://codecov.io/github/poise/application_javascript) +[![Gemnasium](https://img.shields.io/gemnasium/poise/application_javascript.svg)](https://gemnasium.com/poise/application_javascript) +[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) + +A [Chef](https://www.chef.io/) cookbook to deploy server-side JavaScript +applications using Node.js or io.js. + +## Quick Start + +To deploy an Express application from git: + +```ruby +application '/srv/myapp' do + git 'https://github.com/example/myapp.git' + npm_install + npm_start +end +``` + +## Requirements + +Chef 12 or newer is required. + +## Resources + +### `application_javascript` + +The `application_javascript` resource installs a JavaScript runtime for the +deployment. + +```ruby +application '/srv/myapp' do + javascript '3' +end +``` + +All actions and properties are the same as the [`javascript_runtime` resource](https://github.com/poise/poise-javascript#javascript_runtime). + +### `application_javascript_service` + +The `application_javascript_javascript_service` resource creates a service for a +JavaScript command. + +```ruby +application '/srv/myapp' do + javascript_service 'main.js' +end +``` + +#### Actions + +* `:enable` – Create, enable and start the service. *(default)* +* `:disable` – Stop, disable, and destroy the service. +* `:start` – Start the service. +* `:stop` – Stop the service. +* `:restart` – Stop and then start the service. +* `:reload` – Send the configured reload signal to the service. + +#### Properties + +* `command` – Command to run. *(name attribute)* +* `path` – Base path for the application. *(default: application path)* +* `service_name` – Name of the service to create. *(default: auto-detect)* +# `user` – User to run the service as. *(default: application owner)* + +### `application_node_package` + +The `application_node_package` resource installs NPM packages for the deployment. + +```ruby +application '/srv/myapp' do + node_package 'grunt-cli' +end +``` + +All actions and properties are the same as the [`node_package` resource](https://github.com/poise/poise-javascript#node_package), +except that the `group` and `user` properties default to the application-level +data if not specified. + +### `application_npm_start` + +The `application_npm_start` resource creates a service for a JavaScript +application using `npm start`. + +```ruby +application '/srv/myapp' do + npm_start +end +``` + +#### Actions + +* `:enable` – Create, enable and start the service. *(default)* +* `:disable` – Stop, disable, and destroy the service. +* `:start` – Start the service. +* `:stop` – Stop the service. +* `:restart` – Stop and then start the service. +* `:reload` – Send the configured reload signal to the service. + +#### Properties + +* `path` – Base path for the application. *(default: name attribute)* +* `command` – NPM subcommand to run. *(default: start)* +* `service_name` – Name of the service to create. *(default: auto-detect)* +# `user` – User to run the service as. *(default: application owner)* + +## Sponsors + +Development sponsored by [Chef Software](https://www.chef.io/), [Symonds & Son](http://symondsandson.com/), and [Orion](https://www.orionlabs.co/). + +The Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/). + +## License + +Copyright 2015, Noah Kantrowitz + +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/cookbooks/application_javascript/files/halite_gem/poise_application_javascript.rb b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript.rb new file mode 100644 index 0000000..d481a29 --- /dev/null +++ b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript.rb @@ -0,0 +1,23 @@ +# +# Copyright 2015, Noah Kantrowitz +# +# 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. +# + + +module PoiseApplicationJavascript + autoload :AppMixin, 'poise_application_javascript/app_mixin' + autoload :Error, 'poise_application_javascript/error' + autoload :Resources, 'poise_application_javascript/resources' + autoload :VERSION, 'poise_application_javascript/version' +end diff --git a/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/app_mixin.rb b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/app_mixin.rb new file mode 100644 index 0000000..06d4705 --- /dev/null +++ b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/app_mixin.rb @@ -0,0 +1,67 @@ +# +# Copyright 2015, Noah Kantrowitz +# +# 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. +# + +require 'poise/backports' +require 'poise/utils' +require 'poise_application/app_mixin' +require 'poise_javascript/javascript_command_mixin' + + +module PoiseApplicationJavascript + # A helper mixin for Javascript application resources and providers. + # + # @since 4.0.0 + module AppMixin + include Poise::Utils::ResourceProviderMixin + + # A helper mixin for Javascript application resources. + module Resource + include PoiseApplication::AppMixin::Resource + include PoiseJavascript::JavascriptCommandMixin::Resource + + # @!attribute parent_javascript + # Override the #parent_javascript from JavascriptCommandMixin to grok the + # application level parent as a default value. + # @return [PoiseJavascript::Resources::JavascriptRuntime::Resource, nil] + parent_attribute(:javascript, type: :javascript_runtime, optional: true, default: lazy { app_state_javascript.equal?(self) ? nil : app_state_javascript }) + + # @attribute app_state_javascript + # The application-level Javascript parent. + # @return [PoiseJavascript::Resources::JavascriptRuntime::Resource, nil] + def app_state_javascript(javascript=Poise::NOT_PASSED) + unless javascript == Poise::NOT_PASSED + app_state[:javascript] = javascript + end + app_state[:javascript] + end + + # A merged hash of environment variables for both the application state + # and parent javascript. + # + # @return [Hash] + def app_state_environment_javascript + env = app_state_environment + env = env.merge(parent_javascript.javascript_environment) if parent_javascript + env + end + end + + # A helper mixin for Javascript application providers. + module Provider + include PoiseApplication::AppMixin::Provider + end + end +end diff --git a/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/cheftie.rb b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/cheftie.rb new file mode 100644 index 0000000..01a8f69 --- /dev/null +++ b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/cheftie.rb @@ -0,0 +1,17 @@ +# +# Copyright 2015, Noah Kantrowitz +# +# 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. +# + +require 'poise_application_javascript/resources' diff --git a/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/error.rb b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/error.rb new file mode 100644 index 0000000..71fba33 --- /dev/null +++ b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/error.rb @@ -0,0 +1,25 @@ +# +# Copyright 2015, Noah Kantrowitz +# +# 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. +# + +require 'poise_application/error' + +module PoiseApplicationJavascript + # Base exception class for poise-application-javascript errors. + # + # @since 1.0.0 + class Error < PoiseApplication::Error + end +end diff --git a/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources.rb b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources.rb new file mode 100644 index 0000000..32a7cd3 --- /dev/null +++ b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources.rb @@ -0,0 +1,22 @@ +# +# Copyright 2015, Noah Kantrowitz +# +# 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. +# + +require 'poise_application_javascript/resources/javascript' +require 'poise_application_javascript/resources/javascript_execute' +require 'poise_application_javascript/resources/javascript_service' +require 'poise_application_javascript/resources/node_package' +require 'poise_application_javascript/resources/npm_install' +require 'poise_application_javascript/resources/npm_start' diff --git a/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources/javascript.rb b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources/javascript.rb new file mode 100644 index 0000000..e52aabd --- /dev/null +++ b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources/javascript.rb @@ -0,0 +1,64 @@ +# +# Copyright 2015, Noah Kantrowitz +# +# 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. +# + +require 'poise_javascript/resources/javascript_runtime' + +require 'poise_application_javascript/app_mixin' + + +module PoiseApplicationJavascript + module Resources + # (see Javascript::Resource) + # @since 1.0.0 + module Javascript + # An `application_javascript` resource to manage Javascript runtimes + # inside an Application cookbook deployment. + # + # @provides application_javascript + # @provides application_javascript_runtime + # @action install + # @action uninstall + # @example + # application '/app' do + # javascript '3' + # end + class Resource < PoiseJavascript::Resources::JavascriptRuntime::Resource + include PoiseApplicationJavascript::AppMixin + provides(:application_javascript) + # Need the double javascript for application resource rewriting. + provides(:application_javascript_runtime) + container_default(false) + subclass_providers! + + # We want to run the base class version of this, not the one from the + # mixin. HULK SMASH. + def npm_binary + self.class.superclass.instance_method(:npm_binary).bind(self).call + end + + # Set this resource as the app_state's parent javascript. + # + # @api private + def after_created + super.tap do |val| + app_state_javascript(self) + end + end + + end + end + end +end diff --git a/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources/javascript_execute.rb b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources/javascript_execute.rb new file mode 100644 index 0000000..f2d6656 --- /dev/null +++ b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources/javascript_execute.rb @@ -0,0 +1,88 @@ +# +# Copyright 2015, Noah Kantrowitz +# +# 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. +# + +require 'poise_javascript/resources/javascript_execute' + +require 'poise_application_javascript/app_mixin' + + +module PoiseApplicationJavascript + module Resources + # (see JavascriptExecute::Resource) + # @since 1.0.0 + module JavascriptExecute + # An `application_javascript_execute` resource to run Javascript commands inside an + # Application cookbook deployment. + # + # @provides application_javascript_execute + # @action run + # @example + # application '/srv/myapp' do + # javascript_execute 'setup.py install' + # end + class Resource < PoiseJavascript::Resources::JavascriptExecute::Resource + include PoiseApplicationJavascript::AppMixin + provides(:application_javascript_execute) + def initialize(*args) + super + # Clear some instance variables so my defaults work. + remove_instance_variable(:@cwd) + remove_instance_variable(:@group) + remove_instance_variable(:@user) + end + + # #!attribute cwd + # Override the default directory to be the app path if unspecified. + # @return [String] + attribute(:cwd, kind_of: [String, NilClass, FalseClass], default: lazy { parent && parent.path }) + + # #!attribute group + # Override the default group to be the app group if unspecified. + # @return [String, Integer] + attribute(:group, kind_of: [String, Integer, NilClass, FalseClass], default: lazy { parent && parent.group }) + + # #!attribute user + # Override the default user to be the app owner if unspecified. + # @return [String, Integer] + attribute(:user, kind_of: [String, Integer, NilClass, FalseClass], default: lazy { parent && parent.owner }) + end + + # The default provider for `application_javascript_execute`. + # + # @see Resource + # @provides application_javascript_execute + class Provider < PoiseJavascript::Resources::JavascriptExecute::Provider + provides(:application_javascript_execute) + + private + + # Override environment to add the application envivonrment instead. + # + # @return [Hash] + def environment + super.tap do |environment| + # Don't use the app_state_environment_javascript because we already have + # those values in place. + environment.update(new_resource.app_state_environment) + # Re-apply the resource environment for correct ordering. + environment.update(new_resource.environment) if new_resource.environment + end + end + end + + end + end +end diff --git a/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources/javascript_service.rb b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources/javascript_service.rb new file mode 100644 index 0000000..614b561 --- /dev/null +++ b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources/javascript_service.rb @@ -0,0 +1,59 @@ +# +# Copyright 2015, Noah Kantrowitz +# +# 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. +# + +require 'chef/provider' +require 'chef/resource' +require 'poise' + +require 'poise_application_javascript/service_mixin' + + +module PoiseApplicationJavascript + module Resources + # (see JavascriptService::Resource) + # @since 1.0.0 + module JavascriptService + class Resource < Chef::Resource + include PoiseApplicationJavascript::ServiceMixin + provides(:application_javascript_service) + + # @!attribute command + # Command to run. + # @return [String] + attribute(:command, kind_of: String, name_attribute: true) + # @!attribute path + # Override {PoiseApplicationJavascript::ServiceMixin#path} to make it + # not the name_attribute. + # @return [String] + attribute(:path, kind_of: String, default: lazy { parent && parent.path }) + end + + class Provider < Chef::Provider + include PoiseApplicationJavascript::ServiceMixin + provides(:application_javascript_service) + + private + + # (see PoiseApplication::ServiceMixin#service_options) + def service_options(resource) + super + resource.javascript_command(new_resource.command) + end + + end + end + end +end diff --git a/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources/node_package.rb b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources/node_package.rb new file mode 100644 index 0000000..6cad223 --- /dev/null +++ b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources/node_package.rb @@ -0,0 +1,63 @@ +# +# Copyright 2015, Noah Kantrowitz +# +# 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. +# + +require 'poise_javascript/resources/node_package' + +require 'poise_application_javascript/app_mixin' + + +module PoiseApplicationJavascript + module Resources + # (see NodePackage::Resource) + # @since 1.0.0 + module NodePackage + # An `application_node_package` resource to install NPM packages inside + # an Application cookbook deployment. + # + # @provides application_node_package + # @action install + # @action upgrade + # @action remove + # @example + # application '/app' do + # node_package %w{grunt-cli gulp} + # end + class Resource < PoiseJavascript::Resources::NodePackage::Resource + include PoiseApplicationJavascript::AppMixin + provides(:application_node_package) + subclass_providers! + + def initialize(*args) + super + # For older Chef. + @resource_name = :application_node_package + end + + # #!attribute group + # Override the default group to be the app group if unspecified. + # @return [String, Integer] + attribute(:group, kind_of: [String, Integer, NilClass], default: lazy { parent && parent.group }) + + # #!attribute user + # Override the default user to be the app owner if unspecified. + # @return [String, Integer] + attribute(:user, kind_of: [String, Integer, NilClass], default: lazy { parent && parent.owner }) + + # @todo This should handle relative paths against parent.path. + end + end + end +end diff --git a/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources/npm_install.rb b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources/npm_install.rb new file mode 100644 index 0000000..4527df0 --- /dev/null +++ b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources/npm_install.rb @@ -0,0 +1,45 @@ +# +# Copyright 2015, Noah Kantrowitz +# +# 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. +# + +require 'poise_javascript/resources/npm_install' + +require 'poise_application_javascript/app_mixin' + + +module PoiseApplicationJavascript + module Resources + # (see NpmInstall::Resource) + # @since 1.0.0 + module NpmInstall + # An `application_npm_install` resource to install package + # dependencies inside an Application cookbook deployment. + # + # @provides application_npm_install + # @action install + # @example + # application '/app' do + # npm_install + # end + class Resource < PoiseJavascript::Resources::NpmInstall::Resource + include PoiseApplicationJavascript::AppMixin + provides(:application_npm_install) + subclass_providers! + + # @todo This should handle relative paths against parent.path. + end + end + end +end diff --git a/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources/npm_start.rb b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources/npm_start.rb new file mode 100644 index 0000000..0cf803b --- /dev/null +++ b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/resources/npm_start.rb @@ -0,0 +1,78 @@ +# +# Copyright 2015, Noah Kantrowitz +# +# 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. +# + +require 'shellwords' + +require 'chef/provider' +require 'chef/resource' +require 'poise' + +require 'poise_application_javascript/service_mixin' + + +module PoiseApplicationJavascript + module Resources + # (see NpmStart::Resource) + # @since 1.0.0 + module NpmStart + # An `application_npm_start` resource to create a service for a Javascript + # application using `npm start`. + # + # @provides application_npm_start + # @action enable + # @action disable + # @action start + # @action stop + # @action restart + # @action reload + # @example + # application '/app' do + # npm_start + # end + class Resource < Chef::Resource + include PoiseApplicationJavascript::ServiceMixin + provides(:application_npm_start) + + # @!attribute command + # NPM sub-command to run. Defaults to `start`. + # @return [String, Array] + attribute(:command, kind_of: [String, Array], default: 'start') + end + + # The default provider for `application_npm_start`. + # + # @see Resource + # @provides application_npm_start + class Provider < Chef::Provider + include PoiseApplicationJavascript::ServiceMixin + provides(:application_npm_start) + + private + + # (see PoiseApplication::ServiceMixin#service_options) + def service_options(resource) + super + npm_cmd = [new_resource.npm_binary] + Array(new_resource.command) + resource.javascript_command(Shellwords.join(npm_cmd)) + # Make sure node is on $PATH because grrr. + new_path = [::File.dirname(new_resource.javascript), (new_resource.app_state_environment_javascript['PATH'] || ENV['PATH']).to_s].join(::File::PATH_SEPARATOR) + resource.environment['PATH'] = new_path + end + + end + end + end +end diff --git a/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/service_mixin.rb b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/service_mixin.rb new file mode 100644 index 0000000..f4359a1 --- /dev/null +++ b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/service_mixin.rb @@ -0,0 +1,57 @@ +# +# Copyright 2015, Noah Kantrowitz +# +# 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. +# + +require 'poise/utils' +require 'poise_application/service_mixin' +require 'poise_languages/utils' + +require 'poise_application_javascript/app_mixin' + + +module PoiseApplicationJavascript + # A helper mixin for Javascript service resources and providers. + # + # @since 1.0.0 + module ServiceMixin + include Poise::Utils::ResourceProviderMixin + + # A helper mixin for Javascript service resources. + module Resource + include PoiseApplication::ServiceMixin::Resource + include PoiseApplicationJavascript::AppMixin::Resource + end + + # A helper mixin for Javascript service providers. + module Provider + include PoiseApplication::ServiceMixin::Provider + include PoiseApplicationJavascript::AppMixin::Provider + + # Set up the service for running Javascript stuff. + def service_options(resource) + super + # Closure scoping for #javascript_command below. + self_ = self + # Create a new singleton method that fills in `node` for you. + resource.define_singleton_method(:javascript_command) do |val| + resource.command("#{self_.new_resource.javascript} #{PoiseLanguages::Utils.absolute_command(val, path: self_.new_resource.app_state_environment_javascript['PATH'])}") + end + # Include env vars as needed. + resource.environment.update(new_resource.parent_javascript.javascript_environment) if new_resource.parent_javascript + end + + end + end +end diff --git a/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/version.rb b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/version.rb new file mode 100644 index 0000000..4162872 --- /dev/null +++ b/cookbooks/application_javascript/files/halite_gem/poise_application_javascript/version.rb @@ -0,0 +1,19 @@ +# +# Copyright 2015, Noah Kantrowitz +# +# 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. +# + +module PoiseApplicationJavascript + VERSION = '1.0.0' +end diff --git a/cookbooks/application_javascript/libraries/default.rb b/cookbooks/application_javascript/libraries/default.rb new file mode 100644 index 0000000..2c3ee48 --- /dev/null +++ b/cookbooks/application_javascript/libraries/default.rb @@ -0,0 +1,19 @@ +# +# Copyright 2015, Noah Kantrowitz +# +# 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. +# + +raise 'Halite is not compatible with no_lazy_load false, please set no_lazy_load true in your Chef configuration file.' unless Chef::Config[:no_lazy_load] +$LOAD_PATH << File.expand_path('../../files/halite_gem', __FILE__) +require "poise_application_javascript/cheftie" diff --git a/cookbooks/application_javascript/metadata.json b/cookbooks/application_javascript/metadata.json new file mode 100644 index 0000000..c09bcbe --- /dev/null +++ b/cookbooks/application_javascript/metadata.json @@ -0,0 +1 @@ +{"name":"application_javascript","version":"1.0.0","description":"A Chef cookbook for deploying server-side JavaScript application code.","long_description":"# Application_Javascript Cookbook\n\n[![Build Status](https://img.shields.io/travis/poise/application_javascript.svg)](https://travis-ci.org/poise/application_javascript)\n[![Gem Version](https://img.shields.io/gem/v/poise-application-javascript.svg)](https://rubygems.org/gems/poise-application-javascript)\n[![Cookbook Version](https://img.shields.io/cookbook/v/application_javascript.svg)](https://supermarket.chef.io/cookbooks/application_javascript)\n[![Coverage](https://img.shields.io/codecov/c/github/poise/application_javascript.svg)](https://codecov.io/github/poise/application_javascript)\n[![Gemnasium](https://img.shields.io/gemnasium/poise/application_javascript.svg)](https://gemnasium.com/poise/application_javascript)\n[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)\n\nA [Chef](https://www.chef.io/) cookbook to deploy server-side JavaScript\napplications using Node.js or io.js.\n\n## Quick Start\n\nTo deploy an Express application from git:\n\n```ruby\napplication '/srv/myapp' do\n git 'https://github.com/example/myapp.git'\n npm_install\n npm_start\nend\n```\n\n## Requirements\n\nChef 12 or newer is required.\n\n## Resources\n\n### `application_javascript`\n\nThe `application_javascript` resource installs a JavaScript runtime for the\ndeployment.\n\n```ruby\napplication '/srv/myapp' do\n javascript '3'\nend\n```\n\nAll actions and properties are the same as the [`javascript_runtime` resource](https://github.com/poise/poise-javascript#javascript_runtime).\n\n### `application_javascript_service`\n\nThe `application_javascript_javascript_service` resource creates a service for a\nJavaScript command.\n\n```ruby\napplication '/srv/myapp' do\n javascript_service 'main.js'\nend\n```\n\n#### Actions\n\n* `:enable` – Create, enable and start the service. *(default)*\n* `:disable` – Stop, disable, and destroy the service.\n* `:start` – Start the service.\n* `:stop` – Stop the service.\n* `:restart` – Stop and then start the service.\n* `:reload` – Send the configured reload signal to the service.\n\n#### Properties\n\n* `command` – Command to run. *(name attribute)*\n* `path` – Base path for the application. *(default: application path)*\n* `service_name` – Name of the service to create. *(default: auto-detect)*\n# `user` – User to run the service as. *(default: application owner)*\n\n### `application_node_package`\n\nThe `application_node_package` resource installs NPM packages for the deployment.\n\n```ruby\napplication '/srv/myapp' do\n node_package 'grunt-cli'\nend\n```\n\nAll actions and properties are the same as the [`node_package` resource](https://github.com/poise/poise-javascript#node_package),\nexcept that the `group` and `user` properties default to the application-level\ndata if not specified.\n\n### `application_npm_start`\n\nThe `application_npm_start` resource creates a service for a JavaScript\napplication using `npm start`.\n\n```ruby\napplication '/srv/myapp' do\n npm_start\nend\n```\n\n#### Actions\n\n* `:enable` – Create, enable and start the service. *(default)*\n* `:disable` – Stop, disable, and destroy the service.\n* `:start` – Start the service.\n* `:stop` – Stop the service.\n* `:restart` – Stop and then start the service.\n* `:reload` – Send the configured reload signal to the service.\n\n#### Properties\n\n* `path` – Base path for the application. *(default: name attribute)*\n* `command` – NPM subcommand to run. *(default: start)*\n* `service_name` – Name of the service to create. *(default: auto-detect)*\n# `user` – User to run the service as. *(default: application owner)*\n\n## Sponsors\n\nDevelopment sponsored by [Chef Software](https://www.chef.io/), [Symonds & Son](http://symondsandson.com/), and [Orion](https://www.orionlabs.co/).\n\nThe Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/).\n\n## License\n\nCopyright 2015, Noah Kantrowitz\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","maintainer":"YOUR_COMPANY_NAME","maintainer_email":"YOUR_EMAIL","license":"none","platforms":{},"dependencies":{"poise":"~> 2.0","application":"~> 5.0","poise-javascript":"~> 1.0","poise-service":"~> 1.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file diff --git a/cookbooks/apt/CHANGELOG.md b/cookbooks/apt/CHANGELOG.md new file mode 100644 index 0000000..2d89fee --- /dev/null +++ b/cookbooks/apt/CHANGELOG.md @@ -0,0 +1,347 @@ +# apt Cookbook CHANGELOG + +This file is used to list changes made in each version of the apt cookbook. + +## 7.0.0 (2018-04-06) + +### Breaking Change + +- This cookbook no longer includes apt_preference as that resource was moved into Chef Client 13.3. The cookbook now also requires Chef 13.3 or later. If you require support for an older release of Chef you will need to pin to a 6.X release. + +## 6.1.4 (2017-08-31) + +- Restores ignore_failure true on compile time update. +- name_property vs name_attribute in the resource + +## 6.1.3 (2017-07-19) + +- Fixed typo in readme +- Fixed config namespace in the 10dpkg-options file + +## 6.1.2 (2017-06-20) + +- restore backwards compatability by respecting node['apt']['periodic_update_min_delay'] + +## 6.1.1 (2017-06-20) + +- Remove action_class.class_eval usage that caused failures +- Remove wrong warning logs generated by apt_preference +- Fix wrong warning log in cacher-client recipe + +## 6.1.0 (2017-04-11) + +- Test with local delivery and not Rake +- Use proper value type for bsd-mailx package only_if/not_if block +- Update apache2 license string +- Convert apt_preference to a custom resource + +## 6.0.1 (2017-02-27) + +- Update cookbook description +- Testing updates for Chef 13 and fixes to the cacher recipe + +## 6.0.0 (2017-02-08) + +### Breaking changes + +- apt_update and apt_repository resources have been removed from the cookbook. These resources were both added to the chef-client itself. Due to this we now require Chef 12.9 or later, which has both of these resources built in. If you require compatibility with older chef-client releases you will need to pin to the 5.X release. + +### Other changes + +- apt_preference resource now properly required a pin_priority, which prevents us from writing out bad preference files that must be manually removed + +## 5.1.0 (2017-02-01) + +- Convert integration tests to inspec +- Add management of the /etc/apt/apt.conf.d/10dpkg-options file with new attributes. This allows tuning of how dpkg will handle package prompts during package installation. Note that Chef 12.19+ will automatically suppress package prompts + +## 5.0.1 (2016-12-22) + +- Avoid CHEF-3694 in apt_preferences resource +- Cookstyle fixes + +## 5.0.0 (2016-10-14) + +- Remove search logic from the cacher client cookbook and rework attribute structure. See the attributes file and readme for new structure. Determining what servers to cache against is better handled in a wrapper cookbook where you can define the exact search syntax yourself +- Corrected readme examples for the cacher client setup +- Depend on the latest compat_resource +- Define matchers for ChefSpec +- Testing updates to better test the various recipes and providers in the cookbook on Travis + +## 4.0.2 (2016-08-13) + +- The cookbook requires Chef 12.1+ not 12.0\. Update docs +- Test on Chef 12.1 to ensure compatibility +- Restore compatibility with Chef < 12.4 + +## 4.0.1 (2016-06-21) + +- Fix bug that prevented adding the cookbook to non Debian/Ubuntu nodes without chef run failures + +## 4.0.0 (2016-06-02) + +This cookbook now requires Chef 12\. If you require Chef 11 compatibility you will need to pin to the 3.X cookbook version + +- The apt-get update logic in the default recipe has been converted to apt_update custom resource and compat_resource cookbook has been added for backwards compatibility with all Chef 12.X releases. In addition this resource is now included in core chef-client and the cookbook will use the built-in resource if available +- Added support for the unattended-upgrade RandomSleep configuration feature +- Added support for the unattended-upgrade Unattended-Upgrade::Origins-Pattern configuration feature +- Added Chefspec matchers for apt_update +- Fixed apt_repository documentation to correctly reflect the deb_src property + +## 3.0.0 (2016-03-01) + +- Removed Chef 10 compatibility code. This cookbook requires Chef 11 or greater now +- The default recipe will no longer create /etc/apt/ and other directories on non-Debian based systems +- Updated the autoremove command in the default recipe to run in non-interactive mode +- Added CentOS 7 to Test Kitchenwith tests to ensure we don't create any files on RHEL or other non-Debian hosts +- Updated Chefspec to 4.X format +- Properly mock the existence of apt for the Chefspec runs so they don't just skip over the resources +- Fixed lwrp test kitchen tests to pass +- Resolved or disabled all Rubocop warnings +- Enabled testing in Travis CI +- Removed Apt Cacher NG support for Ubuntu 10.04 and Debian 6.X as they are both deprecated +- Fixed + signs in packages names with the preference LWRP being rejected + +## v2.9.2 + +- # 168 Adding guard to package resource. + +## v2.9.1 + +- Adding package apt-transport-https to default.rb + +## v2.9.0 + +- Add `sensitive` flag for apt_repositories +- Enable installation of recommended or suggested packages +- Tidy up `apt-get update` logic +- Fixing not_if guard on ruby_block[validate-key #{key}] + +## v2.8.2 (2015-08-24) + +- Fix removal of apt_preferences + +## v2.8.1 (2015-08-18) + +- Handle keyservers as URLs and bare hostnames + +## v2.8.0 (2015-08-18) + +- Access keyservers on port 80 +- Adds key_proxy as LWRP attribute for apt_repository +- Fix wildcard glob preferences files +- Fix text output verification for non en_US locales +- Quote repo URLs to deal with spaces + +## v2.7.0 (2015-03-23) + +- Support Debian 8.0 +- Filename verification for LWRPs +- Support SSL enabled apt repositories + +## v2.6.1 (2014-12-29) + +- Remove old preference files without .pref extension from previous versions + +## v2.6.0 (2014-09-09) + +- Always update on first run - check +- Adding ppa support for apt_repository + +## v2.5.3 (2014-08-14) + +- # 87 - Improve default settings, account for non-linux platforms + +## v2.5.2 (2014-08-14) + +- Fully restore 2.3.10 behaviour + +## v2.5.1 (2014-08-14) + +- fix breakage introduced in apt 2.5.0 + +## v2.5.0 (2014-08-12) + +- Add unattended-upgrades recipe +- Only update the cache for the created repository +- Added ChefSpec matchers and default_action for resources +- Avoid cloning resource attributes +- Minor documentation updates + +## v2.4.0 (2014-05-15) + +- [COOK-4534]: Add option to update apt cache at compile time + +## v2.3.10 (2014-04-23) + +- [COOK-4512] Bugfix: Use empty PATH if PATH is nil + +## v2.3.8 (2014-02-14) + +### Bug + +- **[COOK-4287](https://tickets.opscode.com/browse/COOK-4287)** - Cleanup the Kitchen + +## v2.3.6 + +- [COOK-4154] - Add chefspec matchers.rb file to apt cookbook +- [COOK-4102] - Only index created repository + +## v2.3.6 + +- [COOK-4154] - Add chefspec matchers.rb file to apt cookbook +- [COOK-4102] - Only index created repository + +## v2.3.4 + +No change. Version bump for toolchain sanity + +## v2.3.2 + +- [COOK-3905] apt-get-update-periodic: configuration for the update period +- Updating style for rubocops +- Updating test-kitchen harness + +## v2.3.0 + +### Bug + +- **[COOK-3812](https://tickets.opscode.com/browse/COOK-3812)** - Add a way to bypass the apt existence check + +### Improvement + +- **[COOK-3567](https://tickets.opscode.com/browse/COOK-3567)** - Allow users to bypass apt-cache via attributes + +## v2.2.1 + +### Improvement + +- **[COOK-664](https://tickets.opscode.com/browse/COOK-664)** - Check platform before running apt-specific commands + +## v2.2.0 + +### Bug + +- **[COOK-3707](https://tickets.opscode.com/browse/COOK-3707)** - multiple nics confuse apt::cacher-client + +## v2.1.2 + +### Improvement + +- **[COOK-3551](https://tickets.opscode.com/browse/COOK-3551)** - Allow user to set up a trusted APT repository + +## v2.1.1 + +### Bug + +- **[COOK-1856](https://tickets.opscode.com/browse/COOK-1856)** - Match GPG keys without case sensitivity + +## v2.1.0 + +- [COOK-3426]: cacher-ng fails with restrict_environment set to true +- [COOK-2859]: cacher-client executes out of order +- [COOK-3052]: Long GPG keys are downloaded on every run +- [COOK-1856]: apt cookbook should match keys without case sensitivity +- [COOK-3255]: Attribute name incorrect in README +- [COOK-3225]: Call use_inline_resources only if defined +- [COOK-3386]: Cache dir for apt-cacher-ng +- [COOK-3291]: apt_repository: enable usage of a keyserver on port 80 +- Greatly expanded test coverage with ChefSpec and Test-Kitchen + +## v2.0.0 + +### Bug + +- [COOK-2258]: apt: LWRP results in error under why-run mode in apt 1.9.0 cookbook + +## v1.10.0 + +### Improvement + +- [COOK-2885]: Improvements for apt cache server search + +### Bug + +- [COOK-2441]: Apt recipe broken in new chef version +- [COOK-2660]: Create Debian 6.0 "squeeze" specific template for +- apt-cacher-ng + +## v1.9.2 + +- [COOK-2631] - Create Ubuntu 10.04 specific template for apt-cacher-ng + +## v1.9.0 + +- [COOK-2185] - Proxy for apt-key +- [COOK-2338] - Support pinning by glob() or regexp + +## v1.8.4 + +- [COOK-2171] - Update README to clarify required Chef version: 10.18.0 +- or higher. + +## v1.8.2 + +- [COOK-2112] - need [] around "arch" in sources.list entries +- [COOK-2171] - fixes a regression in the notification + +## v1.8.0 + +- [COOK-2143] - Allow for a custom cacher-ng port +- [COOK-2171] - On `apt_repository.run_action(:add)` the source file +- is not created. +- [COOK-2184] - apt::cacher-ng, use `cacher_port` attribute in +- acng.conf + +## v1.7.0 + +- [COOK-2082] - add "arch" parameter to apt_repository LWRP + +## v1.6.0 + +- [COOK-1893] - `apt_preference` use "`package_name`" resource instead of "name" +- [COOK-1894] - change filename for sources.list.d files +- [COOK-1914] - Wrong dir permissions for /etc/apt/preferences.d/ +- [COOK-1942] - README.md has wrong name for the keyserver attribute +- [COOK-2019] - create 01proxy before any other apt-get updates get executed + +## v1.5.2 + +- [COOK-1682] - use template instead of file resource in apt::cacher-client +- [COOK-1875] - cacher-client should be Environment-aware + +## V1.5.0 + +- [COOK-1500] - Avoid triggering apt-get update +- [COOK-1548] - Add execute commands for autoclean and autoremove +- [COOK-1591] - Setting up the apt proxy should leave https +- connections direct +- [COOK-1596] - execute[apt-get-update-periodic] never runs +- [COOK-1762] - create /etc/apt/preferences.d directory +- [COOK-1776] - apt key check isn't idempotent + +## v1.4.8 + +- Adds test-kitchen support +- [COOK-1435] - repository lwrp is not idempotent with http key + +## v1.4.6 + +- [COOK-1530] - apt_repository isn't aware of update-success-stamp +- file (also reverts COOK-1382 patch). + +## v1.4.4 + +- [COOK-1229] - Allow cacher IP to be set manually in non-Chef Solo +- environments +- [COOK-1530] - Immediately update apt-cache when sources.list file is dropped off + +## v1.4.2 + +- [COOK-1155] - LWRP for apt pinning + +## v1.4.0 + +- [COOK-889] - overwrite existing repo source files +- [COOK-921] - optionally use cookbook_file or remote_file for key +- [COOK-1032] - fixes problem with apt repository key installation diff --git a/cookbooks/apt/CONTRIBUTING.md b/cookbooks/apt/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/apt/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/cookbooks/apt/README.md b/cookbooks/apt/README.md new file mode 100644 index 0000000..3508386 --- /dev/null +++ b/cookbooks/apt/README.md @@ -0,0 +1,211 @@ +# apt Cookbook + +[![Build Status](https://img.shields.io/travis/chef-cookbooks/apt.svg)][travis] [![Cookbook Version](https://img.shields.io/cookbook/v/apt.svg)][cookbook] + +This cookbook includes recipes to execute apt-get update to ensure the local APT package cache is up to date. There are recipes for managing the apt-cacher-ng caching proxy and proxy clients. It also includes a custom resource for pinning packages via /etc/apt/preferences.d. + +## Requirements + +### Platforms + +- Ubuntu 12.04+ +- Debian 7+ + +May work with or without modification on other Debian derivatives. + +### Chef + +- Chef 13.3+ + +### Cookbooks + +- None + +## Recipes + +### default + +This recipe manually updates the timestamp file used to only run `apt-get update` if the cache is more than one day old. + +This recipe should appear first in the run list of Debian or Ubuntu nodes to ensure that the package cache is up to date before managing any `package` resources with Chef. + +This recipe also sets up a local cache directory for preseeding packages. + +**Including the default recipe on a node that does not support apt (such as Windows or RHEL) results in a noop.** + +### cacher-client + +Configures the node to use a `apt-cacher-ng` server to cache apt requests. Configuration of the server to use is located in `default['apt']['cacher_client']['cacher_server']` which is a hash containing `host`, `port`, `proxy_ssl`, and `bypass` keys. Example: + +```json +{ + "apt": { + "cacher_client": { + "cacher_server": { + "host": "cache_server.mycorp.dmz", + "port": 1234, + "proxy_ssl": true, + "cache_bypass": { + "download.oracle.com": "http" + } + } + } + } +} +``` + +#### Bypassing the cache + +Occasionally you may come across repositories that do not play nicely when the node is using an `apt-cacher-ng` server. You can configure `cacher-client` to bypass the server and connect directly to the repository with the `cache_bypass` attribute. + +To do this, you need to override the `cache_bypass` attribute with an hash of repositories, with each key as the repository URL and value as the protocol to use: + +```json +{ + "apt": { + "cacher_client": { + "cacher_server": { + "cache_bypass": { + "URL": "PROTOCOL" + } + } + } + } +} +``` + +For example, to prevent caching and directly connect to the repository at `download.oracle.com` via http and the repo at `nginx.org` via https + +```json +{ + "apt": { + "cacher_client": { + "cacher_server": { + "cache_bypass": { + "download.oracle.com": "http", + "nginx.org": "https" + } + } + } + } +} +``` + +### cacher-ng + +Installs the `apt-cacher-ng` package and service so the system can provide APT caching. You can check the usage report at . + +If you wish to help the `cacher-ng` recipe seed itself, you must now explicitly include the `cacher-client` recipe in your run list **after** `cacher-ng` or you will block your ability to install any packages (ie. `apt-cacher-ng`). + +### unattended-upgrades + +Installs and configures the `unattended-upgrades` package to provide automatic package updates. This can be configured to upgrade all packages or to just install security updates by setting `['apt']['unattended_upgrades']['allowed_origins']`. + +To pull just security updates, set `origins_patterns` to something like `["origin=Ubuntu,archive=trusty-security"]` (for Ubuntu trusty) or `["origin=Debian,label=Debian-Security"]` (for Debian). + +## Attributes + +### General + +- `['apt']['compile_time_update']` - force the default recipe to run `apt-get update` at compile time. +- `['apt']['periodic_update_min_delay']` - minimum delay (in seconds) between two actual executions of `apt-get update` by the `execute[apt-get-update-periodic]` resource, default is '86400' (24 hours) + +### Caching + +- `['apt']['cacher_client']['cacher_server']` - Hash containing server information used by clients for caching. See the example in the recipes section above for the full format of the hash. +- `['apt']['cacher_interface']` - interface to connect to the cacher-ng service, no default. +- `['apt']['cacher_port']` - port for the cacher-ng service (used by server recipe only), default is '3142' +- `['apt']['cacher_dir']` - directory used by cacher-ng service, default is '/var/cache/apt-cacher-ng' +- `['apt']['compiletime']` - force the `cacher-client` recipe to run before other recipes. It forces apt to use the proxy before other recipes run. Useful if your nodes have limited access to public apt repositories. This is overridden if the `cacher-ng` recipe is in your run list. Default is 'false' + +### Unattended Upgrades + +- `['apt']['unattended_upgrades']['enable']` - enables unattended upgrades, default is false +- `['apt']['unattended_upgrades']['update_package_lists']` - automatically update package list (`apt-get update`) daily, default is true +- `['apt']['unattended_upgrades']['allowed_origins']` - array of allowed apt origins from which to pull automatic upgrades, defaults to a guess at the system's main origin and should almost always be overridden +- `['apt']['unattended_upgrades']['origins_patterns']` - array of allowed apt origin patterns from which to pull automatic upgrades, defaults to none. +- `['apt']['unattended_upgrades']['package_blacklist']` - an array of package which should never be automatically upgraded, defaults to none +- `['apt']['unattended_upgrades']['auto_fix_interrupted_dpkg']` - attempts to repair dpkg state with `dpkg --force-confold --configure -a` if it exits uncleanly, defaults to false (contrary to the unattended-upgrades default) +- `['apt']['unattended_upgrades']['minimal_steps']` - Split the upgrade into the smallest possible chunks. This makes the upgrade a bit slower but it has the benefit that shutdown while a upgrade is running is possible (with a small delay). Defaults to false. +- `['apt']['unattended_upgrades']['install_on_shutdown']` - Install upgrades when the machine is shuting down instead of doing it in the background while the machine is running. This will (obviously) make shutdown slower. Defaults to false. +- `['apt']['unattended_upgrades']['mail']` - Send email to this address for problems or packages upgrades. Defaults to no email. +- `['apt']['unattended_upgrades']['mail_only_on_error']` - If set, email will only be set on upgrade errors. Otherwise, an email will be sent after each upgrade. Defaults to true. +- `['apt']['unattended_upgrades']['remove_unused_dependencies']` Do automatic removal of new unused dependencies after the upgrade. Defaults to false. +- `['apt']['unattended_upgrades']['automatic_reboot']` - Automatically reboots _without confirmation_ if a restart is required after the upgrade. Defaults to false. +- `['apt']['unattended_upgrades']['dl_limit']` - Limits the bandwidth used by apt to download packages. Value given as an integer in kb/sec. Defaults to nil (no limit). +- `['apt']['unattended_upgrades']['random_sleep']` - Wait a random number of seconds up to this value before running daily periodic apt actions. System default is 1800 seconds (30 minutes). + +### Configuration for APT + +- `['apt']['confd']['force_confask']` - Prompt when overwriting configuration files. (default: false) +- `['apt']['confd']['force_confdef']` - Don't prompt when overwriting configuration files. (default: false) +- `['apt']['confd']['force_confmiss']` - Install removed configuration files when upgrading packages. (default: false) +- `['apt']['confd']['force_confnew']` - Overwrite configuration files when installing packages. (default: false) +- `['apt']['confd']['force_confold']` - Keep modified configuration files when installing packages. (default: false) +- `['apt']['confd']['install_recommends']` - Consider recommended packages as a dependency for installing. (default: true) +- `['apt']['confd']['install_suggests']` - Consider suggested packages as a dependency for installing. (default: false) + +## Libraries + +There is an `interface_ipaddress` method that returns the IP address for a particular host and interface, used by the `cacher-client` recipe. To enable it on the server use the `['apt']['cacher_interface']` attribute. + +## Usage + +Put `recipe[apt]` first in the run list. If you have other recipes that you want to use to configure how apt behaves, like new sources, notify the execute resource to run, e.g.: + +```ruby +template '/etc/apt/sources.list.d/my_apt_sources.list' do + notifies :run, 'execute[apt-get update]', :immediately +end +``` + +The above will run during execution phase since it is a normal template resource, and should appear before other package resources that need the sources in the template. + +Put `recipe[apt::cacher-ng]` in the run_list for a server to provide APT caching and add `recipe[apt::cacher-client]` on the rest of the Debian-based nodes to take advantage of the caching server. + +If you want to cleanup unused packages, there is also the `apt-get autoclean` and `apt-get autoremove` resources provided for automated cleanup. + +## Resources + +### apt_preference + +The apt_preference resource has been moved into chef-client in Chef 13.3. + +See for usage details + +### apt_repository + +The apt_repository resource has been moved into chef-client in Chef 12.9. + +See for usage details + +### apt_update + +The apt_update resource has been moved into chef-client in Chef 12.7. + +See for usage details + +## Maintainers + +This cookbook is maintained by Chef's Community Cookbook Engineering team. Our goal is to improve cookbook quality and to aid the community in contributing to cookbooks. To learn more about our team, process, and design goals see our [team documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/COOKBOOK_TEAM.MD). To learn more about contributing to cookbooks like this see our [contributing documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD), or if you have general questions about this cookbook come chat with us in #cookbok-engineering on the [Chef Community Slack](http://community-slack.chef.io/) + +## License + +**Copyright:** 2009-2017, Chef Software, Inc. + +``` +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` + +[cookbook]: https://community.chef.io/cookbooks/apt +[travis]: https://travis-ci.org/chef-cookbooks/apt diff --git a/cookbooks/apt/attributes/default.rb b/cookbooks/apt/attributes/default.rb new file mode 100644 index 0000000..b382ab5 --- /dev/null +++ b/cookbooks/apt/attributes/default.rb @@ -0,0 +1,57 @@ +# +# Cookbook:: apt +# Attributes:: default +# +# Copyright:: 2009-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +default['apt']['cacher_dir'] = '/var/cache/apt-cacher-ng' +default['apt']['cacher_interface'] = nil +default['apt']['cacher_port'] = 3142 +default['apt']['compiletime'] = false +default['apt']['compile_time_update'] = false +default['apt']['key_proxy'] = '' +default['apt']['periodic_update_min_delay'] = 86_400 +default['apt']['launchpad_api_version'] = '1.0' +default['apt']['unattended_upgrades']['enable'] = false +default['apt']['unattended_upgrades']['update_package_lists'] = true +# this needs a good default +codename = node.attribute?('lsb') ? node['lsb']['codename'] : 'notlinux' +default['apt']['unattended_upgrades']['allowed_origins'] = [ + "#{node['platform'].capitalize} #{codename}", +] + +default['apt']['cacher_client']['cacher_server'] = {} + +default['apt']['unattended_upgrades']['origins_patterns'] = [] +default['apt']['unattended_upgrades']['package_blacklist'] = [] +default['apt']['unattended_upgrades']['auto_fix_interrupted_dpkg'] = false +default['apt']['unattended_upgrades']['minimal_steps'] = false +default['apt']['unattended_upgrades']['install_on_shutdown'] = false +default['apt']['unattended_upgrades']['mail'] = nil +default['apt']['unattended_upgrades']['mail_only_on_error'] = true +default['apt']['unattended_upgrades']['remove_unused_dependencies'] = false +default['apt']['unattended_upgrades']['automatic_reboot'] = false +default['apt']['unattended_upgrades']['automatic_reboot_time'] = 'now' +default['apt']['unattended_upgrades']['dl_limit'] = nil +default['apt']['unattended_upgrades']['random_sleep'] = nil + +default['apt']['confd']['force_confask'] = false +default['apt']['confd']['force_confdef'] = false +default['apt']['confd']['force_confmiss'] = false +default['apt']['confd']['force_confnew'] = false +default['apt']['confd']['force_confold'] = false +default['apt']['confd']['install_recommends'] = true +default['apt']['confd']['install_suggests'] = false diff --git a/cookbooks/apt/files/15update-stamp b/cookbooks/apt/files/15update-stamp new file mode 100644 index 0000000..14ead83 --- /dev/null +++ b/cookbooks/apt/files/15update-stamp @@ -0,0 +1 @@ +APT::Update::Post-Invoke-Success {"touch /var/lib/apt/periodic/update-success-stamp 2>/dev/null || true";}; diff --git a/cookbooks/apt/files/apt-proxy-v2.conf b/cookbooks/apt/files/apt-proxy-v2.conf new file mode 100644 index 0000000..6954004 --- /dev/null +++ b/cookbooks/apt/files/apt-proxy-v2.conf @@ -0,0 +1,50 @@ +[DEFAULT] +;; All times are in seconds, but you can add a suffix +;; for minutes(m), hours(h) or days(d) + +;; commented out address so apt-proxy will listen on all IPs +;; address = 127.0.0.1 +port = 9999 +cache_dir = /var/cache/apt-proxy + +;; Control files (Packages/Sources/Contents) refresh rate +min_refresh_delay = 1s +complete_clientless_downloads = 1 + +;; Debugging settings. +debug = all:4 db:0 + +time = 30 +passive_ftp = on + +;;-------------------------------------------------------------- +;; Cache housekeeping + +cleanup_freq = 1d +max_age = 120d +max_versions = 3 + +;;--------------------------------------------------------------- +;; Backend servers +;; +;; Place each server in its own [section] + +[ubuntu] +; Ubuntu archive +backends = + http://us.archive.ubuntu.com/ubuntu + +[ubuntu-security] +; Ubuntu security updates +backends = http://security.ubuntu.com/ubuntu + +[debian] +;; Backend servers, in order of preference +backends = + http://debian.osuosl.org/debian/ + +[security] +;; Debian security archive +backends = + http://security.debian.org/debian-security + http://ftp2.de.debian.org/debian-security diff --git a/cookbooks/apt/libraries/helpers.rb b/cookbooks/apt/libraries/helpers.rb new file mode 100644 index 0000000..6d98060 --- /dev/null +++ b/cookbooks/apt/libraries/helpers.rb @@ -0,0 +1,49 @@ +# +# Cookbook:: apt +# Library:: helpers +# +# Copyright:: 2013-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +module Apt + # Helpers for apt + module Helpers + # Determines if apt is installed on a system. + # + # @return [Boolean] + def apt_installed? + !which('apt-get').nil? + end + + # Finds a command in $PATH + # + # @return [String, nil] + def which(cmd) + ENV['PATH'] = '' if ENV['PATH'].nil? + paths = (ENV['PATH'].split(::File::PATH_SEPARATOR) + %w(/bin /usr/bin /sbin /usr/sbin)) + + paths.each do |path| + possible = File.join(path, cmd) + return possible if File.executable?(possible) + end + + nil + end + end +end + +Chef::Recipe.send(:include, ::Apt::Helpers) +Chef::Resource.send(:include, ::Apt::Helpers) +Chef::Provider.send(:include, ::Apt::Helpers) diff --git a/cookbooks/apt/metadata.json b/cookbooks/apt/metadata.json new file mode 100644 index 0000000..ce9957d --- /dev/null +++ b/cookbooks/apt/metadata.json @@ -0,0 +1 @@ +{"name":"apt","version":"7.0.0","description":"Configures apt and apt caching.","long_description":"# apt Cookbook\n\n[![Build Status](https://img.shields.io/travis/chef-cookbooks/apt.svg)][travis] [![Cookbook Version](https://img.shields.io/cookbook/v/apt.svg)][cookbook]\n\nThis cookbook includes recipes to execute apt-get update to ensure the local APT package cache is up to date. There are recipes for managing the apt-cacher-ng caching proxy and proxy clients. It also includes a custom resource for pinning packages via /etc/apt/preferences.d.\n\n## Requirements\n\n### Platforms\n\n- Ubuntu 12.04+\n- Debian 7+\n\nMay work with or without modification on other Debian derivatives.\n\n### Chef\n\n- Chef 13.3+\n\n### Cookbooks\n\n- None\n\n## Recipes\n\n### default\n\nThis recipe manually updates the timestamp file used to only run `apt-get update` if the cache is more than one day old.\n\nThis recipe should appear first in the run list of Debian or Ubuntu nodes to ensure that the package cache is up to date before managing any `package` resources with Chef.\n\nThis recipe also sets up a local cache directory for preseeding packages.\n\n**Including the default recipe on a node that does not support apt (such as Windows or RHEL) results in a noop.**\n\n### cacher-client\n\nConfigures the node to use a `apt-cacher-ng` server to cache apt requests. Configuration of the server to use is located in `default['apt']['cacher_client']['cacher_server']` which is a hash containing `host`, `port`, `proxy_ssl`, and `bypass` keys. Example:\n\n```json\n{\n \"apt\": {\n \"cacher_client\": {\n \"cacher_server\": {\n \"host\": \"cache_server.mycorp.dmz\",\n \"port\": 1234,\n \"proxy_ssl\": true,\n \"cache_bypass\": {\n \"download.oracle.com\": \"http\"\n }\n }\n }\n }\n}\n```\n\n#### Bypassing the cache\n\nOccasionally you may come across repositories that do not play nicely when the node is using an `apt-cacher-ng` server. You can configure `cacher-client` to bypass the server and connect directly to the repository with the `cache_bypass` attribute.\n\nTo do this, you need to override the `cache_bypass` attribute with an hash of repositories, with each key as the repository URL and value as the protocol to use:\n\n```json\n{\n \"apt\": {\n \"cacher_client\": {\n \"cacher_server\": {\n \"cache_bypass\": {\n \"URL\": \"PROTOCOL\"\n }\n }\n }\n }\n}\n```\n\nFor example, to prevent caching and directly connect to the repository at `download.oracle.com` via http and the repo at `nginx.org` via https\n\n```json\n{\n \"apt\": {\n \"cacher_client\": {\n \"cacher_server\": {\n \"cache_bypass\": {\n \"download.oracle.com\": \"http\",\n \"nginx.org\": \"https\" \n }\n }\n }\n }\n}\n```\n\n### cacher-ng\n\nInstalls the `apt-cacher-ng` package and service so the system can provide APT caching. You can check the usage report at .\n\nIf you wish to help the `cacher-ng` recipe seed itself, you must now explicitly include the `cacher-client` recipe in your run list **after** `cacher-ng` or you will block your ability to install any packages (ie. `apt-cacher-ng`).\n\n### unattended-upgrades\n\nInstalls and configures the `unattended-upgrades` package to provide automatic package updates. This can be configured to upgrade all packages or to just install security updates by setting `['apt']['unattended_upgrades']['allowed_origins']`.\n\nTo pull just security updates, set `origins_patterns` to something like `[\"origin=Ubuntu,archive=trusty-security\"]` (for Ubuntu trusty) or `[\"origin=Debian,label=Debian-Security\"]` (for Debian).\n\n## Attributes\n\n### General\n\n- `['apt']['compile_time_update']` - force the default recipe to run `apt-get update` at compile time.\n- `['apt']['periodic_update_min_delay']` - minimum delay (in seconds) between two actual executions of `apt-get update` by the `execute[apt-get-update-periodic]` resource, default is '86400' (24 hours)\n\n### Caching\n\n- `['apt']['cacher_client']['cacher_server']` - Hash containing server information used by clients for caching. See the example in the recipes section above for the full format of the hash.\n- `['apt']['cacher_interface']` - interface to connect to the cacher-ng service, no default.\n- `['apt']['cacher_port']` - port for the cacher-ng service (used by server recipe only), default is '3142'\n- `['apt']['cacher_dir']` - directory used by cacher-ng service, default is '/var/cache/apt-cacher-ng'\n- `['apt']['compiletime']` - force the `cacher-client` recipe to run before other recipes. It forces apt to use the proxy before other recipes run. Useful if your nodes have limited access to public apt repositories. This is overridden if the `cacher-ng` recipe is in your run list. Default is 'false'\n\n### Unattended Upgrades\n\n- `['apt']['unattended_upgrades']['enable']` - enables unattended upgrades, default is false\n- `['apt']['unattended_upgrades']['update_package_lists']` - automatically update package list (`apt-get update`) daily, default is true\n- `['apt']['unattended_upgrades']['allowed_origins']` - array of allowed apt origins from which to pull automatic upgrades, defaults to a guess at the system's main origin and should almost always be overridden\n- `['apt']['unattended_upgrades']['origins_patterns']` - array of allowed apt origin patterns from which to pull automatic upgrades, defaults to none.\n- `['apt']['unattended_upgrades']['package_blacklist']` - an array of package which should never be automatically upgraded, defaults to none\n- `['apt']['unattended_upgrades']['auto_fix_interrupted_dpkg']` - attempts to repair dpkg state with `dpkg --force-confold --configure -a` if it exits uncleanly, defaults to false (contrary to the unattended-upgrades default)\n- `['apt']['unattended_upgrades']['minimal_steps']` - Split the upgrade into the smallest possible chunks. This makes the upgrade a bit slower but it has the benefit that shutdown while a upgrade is running is possible (with a small delay). Defaults to false.\n- `['apt']['unattended_upgrades']['install_on_shutdown']` - Install upgrades when the machine is shuting down instead of doing it in the background while the machine is running. This will (obviously) make shutdown slower. Defaults to false.\n- `['apt']['unattended_upgrades']['mail']` - Send email to this address for problems or packages upgrades. Defaults to no email.\n- `['apt']['unattended_upgrades']['mail_only_on_error']` - If set, email will only be set on upgrade errors. Otherwise, an email will be sent after each upgrade. Defaults to true.\n- `['apt']['unattended_upgrades']['remove_unused_dependencies']` Do automatic removal of new unused dependencies after the upgrade. Defaults to false.\n- `['apt']['unattended_upgrades']['automatic_reboot']` - Automatically reboots _without confirmation_ if a restart is required after the upgrade. Defaults to false.\n- `['apt']['unattended_upgrades']['dl_limit']` - Limits the bandwidth used by apt to download packages. Value given as an integer in kb/sec. Defaults to nil (no limit).\n- `['apt']['unattended_upgrades']['random_sleep']` - Wait a random number of seconds up to this value before running daily periodic apt actions. System default is 1800 seconds (30 minutes).\n\n### Configuration for APT\n\n- `['apt']['confd']['force_confask']` - Prompt when overwriting configuration files. (default: false)\n- `['apt']['confd']['force_confdef']` - Don't prompt when overwriting configuration files. (default: false)\n- `['apt']['confd']['force_confmiss']` - Install removed configuration files when upgrading packages. (default: false)\n- `['apt']['confd']['force_confnew']` - Overwrite configuration files when installing packages. (default: false)\n- `['apt']['confd']['force_confold']` - Keep modified configuration files when installing packages. (default: false)\n- `['apt']['confd']['install_recommends']` - Consider recommended packages as a dependency for installing. (default: true)\n- `['apt']['confd']['install_suggests']` - Consider suggested packages as a dependency for installing. (default: false)\n\n## Libraries\n\nThere is an `interface_ipaddress` method that returns the IP address for a particular host and interface, used by the `cacher-client` recipe. To enable it on the server use the `['apt']['cacher_interface']` attribute.\n\n## Usage\n\nPut `recipe[apt]` first in the run list. If you have other recipes that you want to use to configure how apt behaves, like new sources, notify the execute resource to run, e.g.:\n\n```ruby\ntemplate '/etc/apt/sources.list.d/my_apt_sources.list' do\n notifies :run, 'execute[apt-get update]', :immediately\nend\n```\n\nThe above will run during execution phase since it is a normal template resource, and should appear before other package resources that need the sources in the template.\n\nPut `recipe[apt::cacher-ng]` in the run_list for a server to provide APT caching and add `recipe[apt::cacher-client]` on the rest of the Debian-based nodes to take advantage of the caching server.\n\nIf you want to cleanup unused packages, there is also the `apt-get autoclean` and `apt-get autoremove` resources provided for automated cleanup.\n\n## Resources\n\n### apt_preference\n\nThe apt_preference resource has been moved into chef-client in Chef 13.3.\n\nSee for usage details\n\n### apt_repository\n\nThe apt_repository resource has been moved into chef-client in Chef 12.9.\n\nSee for usage details\n\n### apt_update\n\nThe apt_update resource has been moved into chef-client in Chef 12.7.\n\nSee for usage details\n\n## Maintainers\n\nThis cookbook is maintained by Chef's Community Cookbook Engineering team. Our goal is to improve cookbook quality and to aid the community in contributing to cookbooks. To learn more about our team, process, and design goals see our [team documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/COOKBOOK_TEAM.MD). To learn more about contributing to cookbooks like this see our [contributing documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD), or if you have general questions about this cookbook come chat with us in #cookbok-engineering on the [Chef Community Slack](http://community-slack.chef.io/)\n\n## License\n\n**Copyright:** 2009-2017, Chef Software, Inc.\n\n```\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n\n[cookbook]: https://community.chef.io/cookbooks/apt\n[travis]: https://travis-ci.org/chef-cookbooks/apt\n","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"ubuntu":">= 0.0.0","debian":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{"apt::default":"Runs apt-get update during compile phase and sets up preseed directories","apt::cacher-ng":"Set up an apt-cacher-ng caching proxy","apt::cacher-client":"Client for the apt::cacher-ng caching proxy"},"source_url":"https://github.com/chef-cookbooks/apt","issues_url":"https://github.com/chef-cookbooks/apt/issues","chef_version":[[">= 13.3"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/apt/recipes/cacher-client.rb b/cookbooks/apt/recipes/cacher-client.rb new file mode 100644 index 0000000..1bbf92c --- /dev/null +++ b/cookbooks/apt/recipes/cacher-client.rb @@ -0,0 +1,52 @@ +# +# Cookbook:: apt +# Recipe:: cacher-client +# +# Copyright:: 2011-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# remove Acquire::http::Proxy lines from /etc/apt/apt.conf since we use 01proxy +# these are leftover from preseed installs +execute 'Remove proxy from /etc/apt/apt.conf' do + command "sed --in-place '/^Acquire::http::Proxy/d' /etc/apt/apt.conf" + only_if 'grep Acquire::http::Proxy /etc/apt/apt.conf' +end + +if node['apt']['cacher_client']['cacher_server'].empty? + Chef::Log.warn("No cache server defined in node['apt']['cacher_client']['cacher_server']. Not setting up caching") + f = file '/etc/apt/apt.conf.d/01proxy' do + action(node['apt']['compiletime'] ? :nothing : :delete) + end + f.run_action(:delete) if node['apt']['compiletime'] +else + apt_update 'update for notification' do + action :nothing + end + + t = template '/etc/apt/apt.conf.d/01proxy' do + source '01proxy.erb' + owner 'root' + group 'root' + mode '0644' + variables( + server: node['apt']['cacher_client']['cacher_server'] + ) + action(node['apt']['compiletime'] ? :nothing : :create) + notifies :update, 'apt_update[update for notification]', :immediately + end + t.run_action(:create) if node['apt']['compiletime'] +end + +include_recipe 'apt::default' diff --git a/cookbooks/apt/recipes/cacher-ng.rb b/cookbooks/apt/recipes/cacher-ng.rb new file mode 100644 index 0000000..5d7e846 --- /dev/null +++ b/cookbooks/apt/recipes/cacher-ng.rb @@ -0,0 +1,39 @@ +# +# Cookbook:: apt +# Recipe:: cacher-ng +# +# Copyright:: 2008-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the 'License'); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an 'AS IS' BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package 'apt-cacher-ng' + +directory node['apt']['cacher_dir'] do + owner 'apt-cacher-ng' + group 'apt-cacher-ng' + mode '0755' +end + +template '/etc/apt-cacher-ng/acng.conf' do + source 'acng.conf.erb' + owner 'root' + group 'root' + mode '0644' + notifies :restart, 'service[apt-cacher-ng]', :immediately +end + +service 'apt-cacher-ng' do + supports restart: true, status: false + action [:enable, :start] +end diff --git a/cookbooks/apt/recipes/default.rb b/cookbooks/apt/recipes/default.rb new file mode 100644 index 0000000..23e54a2 --- /dev/null +++ b/cookbooks/apt/recipes/default.rb @@ -0,0 +1,98 @@ +# +# Cookbook:: apt +# Recipe:: default +# +# Copyright:: 2008-2017, Chef Software, Inc. +# Copyright:: 2009-2017, Bryan McLellan +# +# 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. +# + +# On systems where apt is not installed, the resources in this recipe are not +# executed. However, they _must_ still be present in the resource collection +# or other cookbooks which notify these resources will fail on non-apt-enabled +# systems. + +file '/var/lib/apt/periodic/update-success-stamp' do + owner 'root' + group 'root' + action :nothing +end + +# If compile_time_update run apt-get update at compile time +if node['apt']['compile_time_update'] && apt_installed? + apt_update('compile time') do + frequency node['apt']['periodic_update_min_delay'] + ignore_failure true + end.run_action(:periodic) +end + +apt_update 'periodic' do + frequency node['apt']['periodic_update_min_delay'] +end + +# For other recipes to call to force an update +execute 'apt-get update' do + command 'apt-get update' + ignore_failure true + action :nothing + notifies :touch, 'file[/var/lib/apt/periodic/update-success-stamp]', :immediately + only_if { apt_installed? } +end + +# Automatically remove packages that are no longer needed for dependencies +execute 'apt-get autoremove' do + command 'apt-get -y autoremove' + environment( + 'DEBIAN_FRONTEND' => 'noninteractive' + ) + action :nothing + only_if { apt_installed? } +end + +# Automatically remove .deb files for packages no longer on your system +execute 'apt-get autoclean' do + command 'apt-get -y autoclean' + action :nothing + only_if { apt_installed? } +end + +%w(/var/cache/local /var/cache/local/preseeding).each do |dirname| + directory dirname do + owner 'root' + group 'root' + mode '0755' + action :create + only_if { apt_installed? } + end +end + +template '/etc/apt/apt.conf.d/10dpkg-options' do + owner 'root' + group 'root' + mode '0644' + source '10dpkg-options.erb' + only_if { apt_installed? } +end + +template '/etc/apt/apt.conf.d/10recommends' do + owner 'root' + group 'root' + mode '0644' + source '10recommends.erb' + only_if { apt_installed? } +end + +package 'apt-transport-https' do + only_if { apt_installed? } +end diff --git a/cookbooks/apt/recipes/unattended-upgrades.rb b/cookbooks/apt/recipes/unattended-upgrades.rb new file mode 100644 index 0000000..ee2cb6e --- /dev/null +++ b/cookbooks/apt/recipes/unattended-upgrades.rb @@ -0,0 +1,47 @@ +# +# Cookbook:: apt +# Recipe:: unattended-upgrades +# +# Copyright:: 2014-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the 'License'); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an 'AS IS' BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# On systems where apt is not installed, the resources in this recipe are not +# executed. However, they _must_ still be present in the resource collection +# or other cookbooks which notify these resources will fail on non-apt-enabled +# systems. +# + +package 'unattended-upgrades' do + response_file 'unattended-upgrades.seed.erb' + action :install +end + +package 'bsd-mailx' do + not_if { node['apt']['unattended_upgrades']['mail'].nil? } +end + +template '/etc/apt/apt.conf.d/20auto-upgrades' do + owner 'root' + group 'root' + mode '0644' + source '20auto-upgrades.erb' +end + +template '/etc/apt/apt.conf.d/50unattended-upgrades' do + owner 'root' + group 'root' + mode '0644' + source '50unattended-upgrades.erb' +end diff --git a/cookbooks/apt/templates/01proxy.erb b/cookbooks/apt/templates/01proxy.erb new file mode 100644 index 0000000..1ede9b3 --- /dev/null +++ b/cookbooks/apt/templates/01proxy.erb @@ -0,0 +1,11 @@ +Acquire::http::Proxy "http://<%= @server['host'] %>:<%= @server['port'] %>"; +<% if @server['proxy_ssl'] %> +Acquire::https::Proxy "http://<%= @server['host'] %>:<%= @server['port'] %>"; +<% else %> +Acquire::https::Proxy "DIRECT"; +<% end %> +<% unless @server['cache_bypass'].nil? %> +<% @server['cache_bypass'].each do |bypass, type| %> +Acquire::<%= type %>::Proxy::<%= bypass %> "DIRECT"; +<% end %> +<% end %> diff --git a/cookbooks/apt/templates/10dpkg-options.erb b/cookbooks/apt/templates/10dpkg-options.erb new file mode 100644 index 0000000..3111026 --- /dev/null +++ b/cookbooks/apt/templates/10dpkg-options.erb @@ -0,0 +1,8 @@ +# Managed by Chef +DPkg::Options { +<%= node['apt']['confd']['force_confask'] ? '"--force-confask";' : '' -%> +<%= node['apt']['confd']['force_confdef'] ? '"--force-confdef";' : '' -%> +<%= node['apt']['confd']['force_confmiss'] ? '"--force-confmiss";' : '' -%> +<%= node['apt']['confd']['force_confnew'] ? '"--force-confnew";' : '' -%> +<%= node['apt']['confd']['force_confold'] ? '"--force-confold";' : '' -%> +} diff --git a/cookbooks/apt/templates/10recommends.erb b/cookbooks/apt/templates/10recommends.erb new file mode 100644 index 0000000..16b3664 --- /dev/null +++ b/cookbooks/apt/templates/10recommends.erb @@ -0,0 +1,3 @@ +# Managed by Chef +APT::Install-Recommends "<%= node['apt']['confd']['install_recommends'] ? 1 : 0 %>"; +APT::Install-Suggests "<%= node['apt']['confd']['install_suggests'] ? 1 : 0 %>"; diff --git a/cookbooks/apt/templates/20auto-upgrades.erb b/cookbooks/apt/templates/20auto-upgrades.erb new file mode 100644 index 0000000..47b2f23 --- /dev/null +++ b/cookbooks/apt/templates/20auto-upgrades.erb @@ -0,0 +1,5 @@ +APT::Periodic::Update-Package-Lists "<%= node['apt']['unattended_upgrades']['update_package_lists'] ? 1 : 0 %>"; +APT::Periodic::Unattended-Upgrade "<%= node['apt']['unattended_upgrades']['enable'] ? 1 : 0 %>"; +<% if node['apt']['unattended_upgrades']['random_sleep'] -%> +APT::Periodic::RandomSleep "<%= node['apt']['unattended_upgrades']['random_sleep'] %>"; +<% end -%> diff --git a/cookbooks/apt/templates/50unattended-upgrades.erb b/cookbooks/apt/templates/50unattended-upgrades.erb new file mode 100644 index 0000000..9bf0380 --- /dev/null +++ b/cookbooks/apt/templates/50unattended-upgrades.erb @@ -0,0 +1,75 @@ +// Automatically upgrade packages from these (origin:archive) pairs +Unattended-Upgrade::Allowed-Origins { +<% unless node['apt']['unattended_upgrades']['allowed_origins'].empty? -%> +<% node['apt']['unattended_upgrades']['allowed_origins'].each do |origin| -%> + "<%= origin %>"; +<% end -%> +<% end -%> +}; + +<% unless node['apt']['unattended_upgrades']['origins_patterns'].empty? -%> +Unattended-Upgrade::Origins-Pattern { +<% node['apt']['unattended_upgrades']['origins_patterns'].each do |pattern| -%> + "<%= pattern %>"; +<% end -%> +}; + +<% end -%> +// List of packages to not update +Unattended-Upgrade::Package-Blacklist { +<% unless node['apt']['unattended_upgrades']['package_blacklist'].empty? -%> +<% node['apt']['unattended_upgrades']['package_blacklist'].each do |package| -%> + "<%= package %>"; +<% end -%> +<% end -%> +}; + +// This option allows you to control if on a unclean dpkg exit +// unattended-upgrades will automatically run +// dpkg --force-confold --configure -a +// The default is true, to ensure updates keep getting installed +Unattended-Upgrade::AutoFixInterruptedDpkg "<%= node['apt']['unattended_upgrades']['auto_fix_interrupted_dpkg'] ? 'true' : 'false' %>"; + +// Split the upgrade into the smallest possible chunks so that +// they can be interrupted with SIGUSR1. This makes the upgrade +// a bit slower but it has the benefit that shutdown while a upgrade +// is running is possible (with a small delay) +Unattended-Upgrade::MinimalSteps "<%= node['apt']['unattended_upgrades']['minimal_steps'] ? 'true' : 'false' %>"; + +// Install all unattended-upgrades when the machine is shuting down +// instead of doing it in the background while the machine is running +// This will (obviously) make shutdown slower +Unattended-Upgrade::InstallOnShutdown "<%= node['apt']['unattended_upgrades']['install_on_shutdown'] ? 'true' : 'false' %>"; + +// Send email to this address for problems or packages upgrades +// If empty or unset then no email is sent, make sure that you +// have a working mail setup on your system. A package that provides +// 'mailx' must be installed. +<% if node['apt']['unattended_upgrades']['mail'] -%> +Unattended-Upgrade::Mail "<%= node['apt']['unattended_upgrades']['mail'] %>"; +<% end -%> + +// Set this value to "true" to get emails only on errors. Default +// is to always send a mail if Unattended-Upgrade::Mail is set +Unattended-Upgrade::MailOnlyOnError "<%= node['apt']['unattended_upgrades']['mail_only_on_error'] ? 'true' : 'false' %>"; + +// Do automatic removal of new unused dependencies after the upgrade +// (equivalent to apt-get autoremove) +Unattended-Upgrade::Remove-Unused-Dependencies "<%= node['apt']['unattended_upgrades']['remove_unused_dependencies'] ? 'true' : 'false' %>"; + +// Automatically reboot *WITHOUT CONFIRMATION* if a +// the file /var/run/reboot-required is found after the upgrade +Unattended-Upgrade::Automatic-Reboot "<%= node['apt']['unattended_upgrades']['automatic_reboot'] ? 'true' : 'false' %>"; + +// If automatic reboot is enabled and needed, reboot at the specific +// time instead of immediately +// Default: "now" +<% if node['apt']['unattended_upgrades']['automatic_reboot'] -%> +Unattended-Upgrade::Automatic-Reboot-Time "<%= node['apt']['unattended_upgrades']['automatic_reboot_time'] %>"; +<% end %> + +// Use apt bandwidth limit feature, this example limits the download +// speed to 70kb/sec +<% if node['apt']['unattended_upgrades']['dl_limit'] -%> +Acquire::http::Dl-Limit "<%= node['apt']['unattended_upgrades']['dl_limit'] %>"; +<% end -%> diff --git a/cookbooks/apt/templates/acng.conf.erb b/cookbooks/apt/templates/acng.conf.erb new file mode 100644 index 0000000..3aa0c92 --- /dev/null +++ b/cookbooks/apt/templates/acng.conf.erb @@ -0,0 +1,275 @@ +# Letter case in directive names does not matter. Must be separated with colons. +# Valid boolean values are a zero number for false, non-zero numbers for true. + +CacheDir: <%= node['apt']['cacher_dir'] %> + +# set empty to disable logging +LogDir: /var/log/apt-cacher-ng + +# place to look for additional configuration and resource files if they are not +# found in the configuration directory +# SupportDir: /usr/lib/apt-cacher-ng + +# TCP (http) port +# Set to 9999 to emulate apt-proxy +Port:<%= node['apt']['cacher_port'] %> + +# Addresses or hostnames to listen on. Multiple addresses must be separated by +# spaces. Each entry must be an exact local address which is associated with a +# local interface. DNS resolution is performed using getaddrinfo(3) for all +# available protocols (IPv4, IPv6, ...). Using a protocol specific format will +# create binding(s) only on protocol specific socket(s) (e.g. 0.0.0.0 will listen +# only to IPv4). +# +# Default: not set, will listen on all interfaces and protocols +# +# BindAddress: localhost 192.168.7.254 publicNameOnMainInterface + +# The specification of another proxy which shall be used for downloads. +# Username and password are, and see manual for limitations. +# +#Proxy: http://www-proxy.example.net:80 +#proxy: username:proxypassword@proxy.example.net:3128 + +# Repository remapping. See manual for details. +# In this example, some backends files might be generated during package +# installation using information collected on the system. +Remap-debrep: file:deb_mirror*.gz /debian ; file:backends_debian # Debian Archives +Remap-uburep: file:ubuntu_mirrors /ubuntu ; file:backends_ubuntu # Ubuntu Archives +Remap-debvol: file:debvol_mirror*.gz /debian-volatile ; file:backends_debvol # Debian Volatile Archives +Remap-cygwin: file:cygwin_mirrors /cygwin # ; file:backends_cygwin # incomplete, please create this file or specify preferred mirrors here +Remap-sfnet: file:sfnet_mirrors # ; file:backends_sfnet # incomplete, please create this file or specify preferred mirrors here +Remap-alxrep: file:archlx_mirrors /archlinux # ; file:backend_archlx # Arch Linux +Remap-fedora: file:fedora_mirrors # Fedora Linux +Remap-epel: file:epel_mirrors # Fedora EPEL +Remap-slrep: file:sl_mirrors # Scientific Linux + +# This is usually not needed for security.debian.org because it's always the +# same DNS hostname. However, it might be enabled in order to use hooks, +# ForceManaged mode or special flags in this context. +# Remap-secdeb: security.debian.org + +# Virtual page accessible in a web browser to see statistics and status +# information, i.e. under http://localhost:3142/acng-report.html +ReportPage: acng-report.html + +# Socket file for accessing through local UNIX socket instead of TCP/IP. Can be +# used with inetd bridge or cron client. +# SocketPath:/var/run/apt-cacher-ng/socket + +# Forces log file to be written to disk after every line when set to 1. Default +# is 0, buffers are flushed when the client disconnects. +# +# (technically, alias to the Debug option, see its documentation for details) +# +# UnbufferLogs: 0 + +# Set to 0 to store only type, time and transfer sizes. +# 1 -> client IP and relative local path are logged too +# VerboseLog: 1 + +# Don't detach from the console +# ForeGround: 0 + +# Store the pid of the daemon process therein +# PidFile: /var/run/apt-cacher-ng/pid + +# Forbid outgoing connections, work around them or respond with 503 error +# offlinemode:0 + +# Forbid all downloads that don't run through preconfigured backends (.where) +#ForceManaged: 0 + +# Days before considering an unreferenced file expired (to be deleted). +# Warning: if the value is set too low and particular index files are not +# available for some days (mirror downtime) there is a risk of deletion of +# still useful package files. +ExTreshold: 4 + +# Stop expiration when a critical problem appeared. Currently only failed +# refresh of an index file is considered as critical. +# +# WARNING: don't touch this option or set to zero. +# Anything else is DANGEROUS and may cause data loss. +# +# ExAbortOnProblems: 1 + +# Replace some Windows/DOS-FS incompatible chars when storing +# StupidFs: 0 + +# Experimental feature for apt-listbugs: pass-through SOAP requests and +# responses to/from bugs.debian.org. If not set, default is true if +# ForceManaged is enabled and false otherwise. +# ForwardBtsSoap: 1 + +# The daemon has a small cache for DNS data, to speed up resolution. The +# expiration time of the DNS entries can be configured in seconds. +# DnsCacheSeconds: 3600 + +# Don't touch the following values without good consideration! +# +# Max. count of connection threads kept ready (for faster response in the +# future). Should be a sane value between 0 and average number of connections, +# and depend on the amount of spare RAM. +# MaxStandbyConThreads: 8 +# +# Hard limit of active thread count for incoming connections, i.e. operation +# is refused when this value is reached (below zero = unlimited). +# MaxConThreads: -1 +# +# Pigeonholing files with regular expressions (static/volatile). Can be +# overriden here but not should not be done permanently because future update +# of default settings would not be applied later. +# VfilePattern = (^|.*?/)(Index|Packages(\.gz|\.bz2|\.lzma|\.xz)?|InRelease|Release|Release\.gpg|Sources(\.gz|\.bz2|\.lzma|\.xz)?|release|index\.db-.*\.gz|Contents-[^/]*(\.gz|\.bz2|\.lzma|\.xz)?|pkglist[^/]*\.bz2|rclist[^/]*\.bz2|/meta-release[^/]*|Translation[^/]*(\.gz|\.bz2|\.lzma|\.xz)?|MD5SUMS|SHA1SUMS|((setup|setup-legacy)(\.ini|\.bz2|\.hint)(\.sig)?)|mirrors\.lst|repo(index|md)\.xml(\.asc|\.key)?|directory\.yast|products|content(\.asc|\.key)?|media|filelists\.xml\.gz|filelists\.sqlite\.bz2|repomd\.xml|packages\.[a-zA-Z][a-zA-Z]\.gz|info\.txt|license\.tar\.gz|license\.zip|.*\.db(\.tar\.gz)?|.*\.files\.tar\.gz|.*\.abs\.tar\.gz|metalink\?repo|.*prestodelta\.xml\.gz)$|/dists/.*/installer-[^/]+/[^0-9][^/]+/images/.* +# PfilePattern = .*(\.d?deb|\.rpm|\.dsc|\.tar(\.gz|\.bz2|\.lzma|\.xz)(\.gpg)?|\.diff(\.gz|\.bz2|\.lzma|\.xz)|\.jigdo|\.template|changelog|copyright|\.udeb|\.debdelta|\.diff/.*\.gz|(Devel)?ReleaseAnnouncement(\?.*)?|[a-f0-9]+-(susedata|updateinfo|primary|deltainfo).xml.gz|fonts/(final/)?[a-z]+32.exe(\?download.*)?|/dists/.*/installer-[^/]+/[0-9][^/]+/images/.*)$ +# Whitelist for expiration, file types not to be removed even when being +# unreferenced. Default: many parts from VfilePattern where no parent index +# exists or might be unknown. +# WfilePattern = (^|.*?/)(Release|InRelease|Release\.gpg|(Packages|Sources)(\.gz|\.bz2|\.lzma|\.xz)?|Translation[^/]*(\.gz|\.bz2|\.lzma|\.xz)?|MD5SUMS|SHA1SUMS|.*\.xml|.*\.db\.tar\.gz|.*\.files\.tar\.gz|.*\.abs\.tar\.gz|[a-z]+32.exe)$|/dists/.*/installer-.*/images/.* + +# Higher modes only working with the debug version +# Warning, writes a lot into apt-cacher.err logfile +# Value overwrites UnbufferLogs setting (aliased) +# Debug:3 + +# Usually, general purpose proxies like Squid expose the IP address of the +# client user to the remote server using the X-Forwarded-For HTTP header. This +# behaviour can be optionally turned on with the Expose-Origin option. +# ExposeOrigin: 0 + +# When logging the originating IP address, trust the information supplied by +# the client in the X-Forwarded-For header. +# LogSubmittedOrigin: 0 + +# The version string reported to the peer, to be displayed as HTTP client (and +# version) in the logs of the mirror. +# WARNING: some archives use this header to detect/guess capabilities of the +# client (i.e. redirection support) and change the behaviour accordingly, while +# ACNG might not support the expected features. Expect side effects. +# +# UserAgent: Yet Another HTTP Client/1.2.3p4 + +# In some cases the Import and Expiration tasks might create fresh volatile +# data for internal use by reconstructing them using patch files. This +# by-product might be recompressed with bzip2 and with some luck the resulting +# file becomes identical to the *.bz2 file on the server, usable for APT +# clients trying to fetch the full .bz2 compressed version. Injection of the +# generated files into the cache has however a disadvantage on underpowered +# servers: bzip2 compression can create high load on the server system and the +# visible download of the busy .bz2 files also becomes slower. +# +# RecompBz2: 0 + +# Network timeout for outgoing connections. +# NetworkTimeout: 60 + +# Sometimes it makes sense to not store the data in cache and just return the +# package data to client as it comes in. DontCache parameters can enable this +# behaviour for certain URL types. The tokens are extended regular expressions +# that URLs are matched against. +# +# DontCacheRequested is applied to the URL as it comes in from the client. +# Example: exclude packages built with kernel-package for x86 +# DontCacheRequested: linux-.*_10\...\.Custo._i386 +# Example usecase: exclude popular private IP ranges from caching +# DontCacheRequested: 192.168.0 ^10\..* 172.30 +# +# DontCacheResolved is applied to URLs after mapping to the target server. If +# multiple backend servers are specified then it's only matched against the +# download link for the FIRST possible source (due to implementation limits). +# Example usecase: all Ubuntu stuff comes from a local mirror (specified as +# backend), don't cache it again: +# DontCacheResolved: ubuntumirror.local.net +# +# DontCache directive sets (overrides) both, DontCacheResolved and +# DontCacheRequested. Provided for convenience, see those directives for +# details. +# +# Default permission set of freshly created files and directories, as octal +# numbers (see chmod(1) for details). +# Can by limited by the umask value (see umask(2) for details) if it's set in +# the environment of the starting shell, e.g. in apt-cacher-ng init script or +# in its configuration file. +# DirPerms: 00755 +# FilePerms: 00664 +# +# +# It's possible to use use apt-cacher-ng as a regular web server with limited +# feature set, i.e. +# including directory browsing and download of any file; +# excluding sorting, mime types/encodings, CGI execution, index page +# redirection and other funny things. +# To get this behavior, mappings between virtual directories and real +# directories on the server must be defined with the LocalDirs directive. +# Virtual and real dirs are separated by spaces, multiple pairs are separated +# by semi-colons. Real directories must be absolute paths. +# NOTE: Since the names of that key directories share the same namespace as +# repository names (see Remap-...) it's administrators job to avoid such +# collisions on them (unless created deliberately). +# +# LocalDirs: woo /data/debarchive/woody ; hamm /data/debarchive/hamm + +# Precache a set of files referenced by specified index files. This can be used +# to create a partial mirror usable for offline work. There are certain limits +# and restrictions on the path specification, see manual for details. A list of +# (maybe) relevant index files could be retrieved via +# "apt-get --print-uris update" on a client machine. +# +# PrecacheFor: debrep/dists/unstable/*/source/Sources* debrep/dists/unstable/*/binary-amd64/Packages* + +# Arbitrary set of data to append to request headers sent over the wire. Should +# be a well formated HTTP headers part including newlines (DOS style) which +# can be entered as escape sequences (\r\n). +# RequestAppendix: X-Tracking-Choice: do-not-track\r\n + +# Specifies the IP protocol families to use for remote connections. Order does +# matter, first specified are considered first. Possible combinations: +# v6 v4 +# v4 v6 +# v6 +# v4 +# (empty or not set: use system default) +# +# ConnectProto: v6 v4 + +# Regular expiration algorithm finds package files which are no longer listed +# in any index file and removes them of them after a safety period. +# This option allows to keep more versions of a package in the cache after +# safety period is over. +# KeepExtraVersions: 1 + +# Optionally uses TCP access control provided by libwrap, see hosts_access(5) +# for details. Daemon name is apt-cacher-ng. Default if not set: decided on +# startup by looking for explicit mentioning of apt-cacher-ng in +# /etc/hosts.allow or /etc/hosts.deny files. +# UseWrap: 0 + +# If many machines from the same local network attempt to update index files +# (apt-get update) at nearly the same time, the known state of these index file +# is temporarily frozen and multiple requests receive the cached response +# without contacting the server. This parameter (in seconds) specifies the +# length of this period before the files are considered outdated. +# Setting it too low transfers more data and increases remote server load, +# setting it too high (more than a couple of minutes) increases the risk of +# delivering inconsistent responses to the clients. +# FreshIndexMaxAge: 27 + +# Usually the users are not allowed to specify custom TCP ports of remote +# mirrors in the requests, only the default HTTP port can be used (instead, +# proxy administrator can create Remap- rules with custom ports). This +# restriction can be disabled by specifying a list of allowed ports or 0 for +# any port. +# +# AllowUserPorts: 80 + +# Normally the HTTP redirection responses are forwarded to the original caller +# (i.e. APT) which starts a new download attempt from the new URL. This +# solution is ok for client configurations with proxy mode but doesn't work +# well with configurations using URL prefixes. To work around this the server +# can restart its own download with another URL. However, this might be used to +# circumvent download source policies by malicious users. +# The RedirMax option specifies how many such redirects the server should +# follow per request, 0 disables the internal redirection. If not set, +# default value is 0 if ForceManaged is used and 5 otherwise. +# +# RedirMax: 5 diff --git a/cookbooks/apt/templates/unattended-upgrades.seed.erb b/cookbooks/apt/templates/unattended-upgrades.seed.erb new file mode 100644 index 0000000..5ee5e93 --- /dev/null +++ b/cookbooks/apt/templates/unattended-upgrades.seed.erb @@ -0,0 +1 @@ +unattended-upgrades unattended-upgrades/enable_auto_updates boolean <%= node['apt']['unattended_upgrades']['enable'] ? 'true' : 'false' %> diff --git a/cookbooks/ark/.foodcritic b/cookbooks/ark/.foodcritic new file mode 100644 index 0000000..b9f8767 --- /dev/null +++ b/cookbooks/ark/.foodcritic @@ -0,0 +1 @@ +~FC016 diff --git a/cookbooks/ark/CHANGELOG.md b/cookbooks/ark/CHANGELOG.md new file mode 100644 index 0000000..0639bc9 --- /dev/null +++ b/cookbooks/ark/CHANGELOG.md @@ -0,0 +1,252 @@ +# ark Cookbook CHANGELOG + +This file is used to list changes made in each version of the ark cookbook. + +## 3.1.0 (2017-05-06) + +- Ensure the dependencies get installed on Chef 13 Amazon Linux systems +- Require Chef 12.7+ and remove action_class.class_eval usage + +## 3.0.0 (2017-04-05) + +- Rewrite of resource to custom resources. +- Remove EOL platforms from testing. +- Update zlib URL +- +## 2.2.1 (2016-12-16) +- Use Ohai root_group attribute to avoid trying to set the group to root on BSD/macOS. +- Add missing accessor for owner property + +## 2.2.0 (2016-12-14) + +- Add detection of .7z file extensions +- Fix 7zip extraction using strip_components >= 1 to properly extract to the path instead of the user's home_dir +- Always quote the path to the 7zip and xcopy binaries as they may have spaces +- Clarified in the readme that the install_with_make action includes the configure action +- Fix files with very long paths failing to extract on Windows +- Fix default owner of 'root' failing on Windows +- Fix 7-zip extraction with long paths when strip_components is >= 1 +- Add the group attribute parameter to README +- Fix package installation failure on macOS systems +- Use x to extract with 7-zip, not e. Use e only for dump, which strips directories. + +## 2.1.0 (2016-11-15) + +- Move tar/7zip path logic out of attributes and into helpers to prevent failures when 7zip is not installed before the chef run starts +- Improve platform testing in Test Kitchen +- Recognize Windows as a supported platform in the readme +- Introduce a new attribute for overriding the 7-zip location: node['ark']['sevenzip_binary'] + +## 2.0.2 (2016-11-03) + +- Fix suse support and centos < 6 + +## 2.1.0 (2016-11-01) + +- Use multipackage installs to speed up installation +- Avoid installation package dependencies on Windows entirely +- Remove the testing bin stubs + +## 2.0.0 (2016-09-15) + +- Add CentOS 7.2, Fedora 23, and Suse specs +- Add centos 5, debian, and opensuse travis testing +- Add a contributing doc +- Fix cookstyle warnings +- Require Chef 12.1+ + +## [v1.2.0](https://github.com/chef-cookbooks/ark/tree/v1.2.0) (2016-07-03) + +[Full Changelog](https://github.com/chef-cookbooks/ark/compare/v1.1.0...v1.2.0) + +- Create seven_zip unpack command when strip_components is 0 [#155](https://github.com/chef-cookbooks/ark/pull/155) ([terkill](https://github.com/terkill)) +- Get 7zip path from the windows registry. [#153](https://github.com/chef-cookbooks/ark/pull/153) ([buri17](https://github.com/buri17)) +- Use fullpath for xcopy and icacls. [#152](https://github.com/chef-cookbooks/ark/pull/152) ([buri17](https://github.com/buri17)) +- Define custom matcher helper for notification testing, fixes #139 [#144](https://github.com/chef-cookbooks/ark/pull/144) ([szymonpk](https://github.com/szymonpk)) + +## v1.1.0 (2016-05-19) + +- Add support for RHEL 7 +- Fixes to the readme to clarify actions / properties +- Expose the backup property in remote file to the ark resource +- Transfer the cookbook back to Chef +- Resolve all rubocop warnings +- Add maintainers files and Chef contributing docs +- Test on the latest platforms in .kitchen.yml and update Travis to use kitchen-dokken with additional platforms + +## v1.0.1 (2016-02-16) + +- Remove a large number of zero byte archives that snuck into the repository +- Remove a Chef 10 compatibility check in the custom resource + +## v1.0.0 (2016-02-09) + +- Added the pkg-config package to the debian platform family +- Added tar, xz-lzma-compat, and bzip2 packages to the RHEL and fedora platform families +- Updated FreeBSD to install gmake instead of make +- Added OS X, SmartOS, and FreeBSD to the tar path attributes to support those platforms +- Removed the has_binaries attribute from put action documentation in the readme file since this isn't supported there +- Moved the libraries module locations to no longer be under Opscode:: and broke out libraries into more logical units +- Fixed issues with spaces in Windows paths that could cause failures +- Fixed a bad attribute for the 7zip home on windows. Instead of using a node attribute use the value directly to avoid computed attribute overiding issues +- Switched from the 7-zip cookbook to seven_zip since the 7-zip cookbook is now deprecated +- Changed unzip commands to not use -u so that a newer archive can overwrite an existing directory +- Added support for actions py_setup, py_setup_install, py_setup_build +- Fixed setting home_dir attribute +- Added source_url and issues_url to the metadata.rb +- Expanded the supported platforms in metadata.rb +- Removed all references to Opscode +- Improved error logging when an unknown extension is encountered +- Added support for .tar files +- Improved overall testing: + + - Removed the kitchen.cloud.yml file and gem dependencies + - Added integration testing in Travis with Kitchen-Docker and Travis tests now run using the nightly build of ChefDK + - Expanded platforms tested in the .kitchen.yml file + - Updated the Gemfile with the latest testing dependencies + - Added full Chefspec coverage + - Greatly expanded the ark_spec test cookbook + - Removed the original minitests + +- Added standard Chef .gitignore and chefignore files + +- Resolved a large number of rubocop warnings + +- Removed old Opscode contributing and testing docs + +- Added a cookbook version badge to the readme + +- Removed the Toftfile + +## v0.9.0 (2014-06-06) + +- [COOK-3642] Add Windows support + +## v0.8.2 (2014-04-23) + +- [COOK-4514] - Support for SLES with the Ark cookbook + +## v0.8.0 (2014-04-10) + +- [COOK-2771] - Add support for XZ compression + +## v0.7.2 (2014-03-28) + +- [COOK-4477] - Fix failing test suite +- [COOK-4484] - Replace strip_leading_dir attribute with more general strip_components + +## v0.7.0 (2014-03-18) + +- [COOK-4437] - configure and install_with_make should chown after unpack + +## v0.6.0 (2014-02-27) + +[COOK-3786] - Unable to install multiple versions of archive without duplication + +## v0.5.0 (2014-02-21) + +### Bug + +- **[COOK-4288](https://tickets.opscode.com/browse/COOK-4288)** - Cleanup the Kitchen + +### Improvement + +- **[COOK-4264](https://tickets.opscode.com/browse/COOK-4264)** - Add node['ark']['package_dependencies'] to allow tuning packages. + +## v0.4.2 + +### Improvement + +- **[COOK-3854](https://tickets.opscode.com/browse/COOK-3854)** - Capability with mac_os_x: '/bin/chown' - No such file or directory +- Cleaning up some style for rubucop +- Updating test harness + +## v0.4.0 + +### Improvement + +- **[COOK-3539](https://tickets.opscode.com/browse/COOK-3539)** - Allow dumping of bz2 and gzip files + +## v0.3.2 + +### Bug + +- **[COOK-3191](https://tickets.opscode.com/browse/COOK-3191)** - Propogate unzip failures +- **[COOK-3118](https://tickets.opscode.com/browse/COOK-3118)** - Set cookbook attribute in provider +- **[COOK-3055](https://tickets.opscode.com/browse/COOK-3055)** - Use proper scope in helper module +- **[COOK-3054](https://tickets.opscode.com/browse/COOK-3054)** - Fix notification resource updating + +### Improvement + +- **[COOK-3179](https://tickets.opscode.com/browse/COOK-3179)** - README updates and refactor + +## v0.3.0 + +### Improvement + +- [COOK-3087]: Can't use ark with chef < 11 + +### Bug + +- [COOK-3064]: `only_if` statements in ark's `install_with_make` and configure actions are not testing for file existence correctly. +- [COOK-3067]: ark kitchen test for `cherry_pick` is expecting the binary to be in the same parent folder as in the archive. + +## v0.2.4 + +### Bug + +- [COOK-3048]: Ark provider contains a `ruby_block` resource without a block attribute +- [COOK-3063]: Ark cookbook `cherry_pick` action's unzip command does not close if statement +- [COOK-3065]: Ark install action does not symlink binaries correctly + +## v0.2.2 + +- Update the README to reflect the requirement for Chef 11 to use the ark resource (`use_inline_resources`). +- Making this a release so it will also appear on the community site page. + +## v0.2.0 + +### Bug + +- [COOK-2772]: Ark cookbook has foodcritic failures in provides/default.rb + +### Improvement + +- [COOK-2520]: Refactor ark providers to use the '`use_inline_resources`' LWRP DSL feature + +## v0.1.0 + +- [COOK-2335] - ark resource broken on Chef 11 + +## v0.0.1 + +- [COOK-2026] - Allow `cherry_pick` action to be used for directories as well as files + +## v0.0.1 + +- [COOK-1593] - README formatting updates for better display on Community Site + +## v0.0.1 + +### Bug + +- dangling "unless" + +### Improvement + +- add `setup_py_*` actions +- add vagrantfile +- add foodcritic test +- travis.ci support + +## v0.0.10 (May 23, 2012 + +### Bug + +- `strip_leading_dir` not working for zip files + +### Improvement + +- use autogen.sh to generate configure script for configure action +- support more file extensions +- add extension attribute which allows you to download files which do not have the file extension as part of the URL diff --git a/cookbooks/ark/CONTRIBUTING.md b/cookbooks/ark/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/ark/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/cookbooks/ark/MAINTAINERS.md b/cookbooks/ark/MAINTAINERS.md new file mode 100644 index 0000000..645ed14 --- /dev/null +++ b/cookbooks/ark/MAINTAINERS.md @@ -0,0 +1,15 @@ + + +# Maintainers + +This file lists how this cookbook project is maintained. When making changes to the system, this file tells you who needs to review your patch - you need a review from an existing maintainer for the cookbook to provide a :+1: on your pull request. Additionally, you need to not receive a veto from a Lieutenant or the Project Lead. + +Check out [How Cookbooks are Maintained](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD) for details on the process and how to become a maintainer or the project lead. + +# Project Maintainer +* [Tim Smith](https://github.com/tas50) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) diff --git a/cookbooks/ark/README.md b/cookbooks/ark/README.md new file mode 100644 index 0000000..42f7cb6 --- /dev/null +++ b/cookbooks/ark/README.md @@ -0,0 +1,299 @@ +# ark cookbook + +[![Build Status](https://travis-ci.org/chef-cookbooks/ark.svg?branch=master)](https://travis-ci.org/chef-cookbooks/ark) [![Cookbook Version](https://img.shields.io/cookbook/v/ark.svg)](https://supermarket.chef.io/cookbooks/ark) + +## Overview + +This cookbook provides `ark`, a resource for managing software archives. It manages the fetch-unpack-configure-build-install process common to installing software from source, or from binary distributions that are not fully fledged OS packages. + +This cookbook started its life as a modified version of Infochimp's install_from cookbook. It has since been heavily refactored and extended to meet different use cases. + +Given a simple project archive available at a url: + +```ruby +ark 'pig' do + url 'http://apache.org/pig/pig-0.8.0.tar.gz' +end +``` + +The `ark` resource will: + +- fetch it to to `/var/cache/chef/` +- unpack it to the default path (`/usr/local/pig-0.8.0`) +- create a symlink for `:home_dir` (`/usr/local/pig`) pointing to path +- add specified binary commands to the environment `PATH` variable + +By default, the ark will not run again if the `:path` is not empty. Ark provides many actions to accommodate different use cases, such as `:dump`, `:cherry_pick`, `:put`, and `:install_with_make`. + +At this time ark only handles files available from URLs using the [remote_file](http://docs.chef.io/resource_remote_file.html) provider. It does handle local files using the `file://` protocol. + +## Requirements + +### Platforms + +- Debian/Ubuntu +- RHEL/CentOS/Scientific/Oracle +- Fedora +- FreeBSD +- SmartOS +- Mac OS X +- openSUSE / SUSE Linux Enterprises +- Windows + +Should work on common Unix/Linux systems with typical userland utilities like tar, gzip, etc. May require the installation of build tools for compiling from source, but that installation is outside the scope of this cookbook. + +### Chef + +- Chef 12.7+ + +### Cookbooks + +- build-essential +- seven_zip +- windows + +## Attributes + +Customize the attributes to suit site specific conventions and defaults. + +- `node['ark']['apache_mirror']` - if the URL is an apache mirror, use the attribute as the default. default: `http://apache.mirrors.tds.net` +- `node['ark']['prefix_root']` - default base location if the `prefix_root` is not passed into the resource. default: `/usr/local` +- `node['ark']['prefix_bin']` - default binary location if the `prefix_bin` is not passed into the resource. default: `/usr/local/bin` +- `node['ark']['prefix_home']` - default home location if the `prefix_home` is not passed into the resource. default: `/usr/local` +- `node['ark']['package_dependencies']` - prerequisite system packages that need to be installed to support ark. default: varies based on platform +- `node['ark']['tar']` - allows overriding the default path to the tar binary, which varies based on platform +- `node['ark']['sevenzip_binary']` - allows overriding the default path to the 7zip binary, which is determined based on registry key value + +## Resources + +- `ark` - does the extract/build/configure + +### Actions + +- `:install`: extracts the file and creates a 'friendly' symbolic link to the extracted directory path +- `:configure`: configure ahead of the install action +- `:install_with_make`: extracts the archive to a path, runs `configure`, `make`, and `make install`. +- `:dump`: strips all directories from the archive and dumps the contained files into a specified path +- `:cherry_pick`: extract a specified file from an archive and places in specified path +- `:put`: extract the archive to a specified path, does not create any symbolic links +- `:remove`: removes the extracted directory and related symlink #TODO +- `:setup_py`: runs the command "python setup.py" in the extracted directory +- `:setup_py_build`: runs the command "python setup.py build" in the extracted directory +- `:setup_py_install`: runs the command "python setup.py install" in the extracted directory + +### :cherry_pick + +Extract a specified file from an archive and places in specified path. + +#### Relevant Attribute Parameters for :cherry_pick + +- `path`: directory to place file in. +- `creates`: specific file to cherry-pick. + +### :dump + +Strips all directories from the archive and dumps the contained files into a specified path. + +NOTE: This currently only works for zip archives + +#### Attribute Parameters for :dump + +- `path`: path to dump files to. +- `mode`: file mode for `app_home`, as an integer. + + - Example: `0775` + +- `creates`: if you are appending files to a given directory, ark needs a condition to test whether the file has already been extracted. You can specify with creates, a file whose existence indicates the ark has previously been extracted and does not need to be extracted again. + +### :put + +Extract the archive to a specified path, does not create any symbolic links. + +#### Attribute Parameters for :put + +- `path`: path to extract to. + + - Default: `/usr/local` + +- `append_env_path`: boolean, if true, append the `./bin` directory of the extracted directory to the global `PATH` variable for all users. + +### Attribute Parameters + +- `name`: name of the package, defaults to the resource name. +- `url`: url for tarball, `.tar.gz`, `.bin` (oracle-specific), `.war`, and `.zip` currently supported. Also supports special syntax +- `:name:version:apache_mirror:` that will auto-magically construct download url from the apache mirrors site. +- `version`: software version, defaults to `1`. +- `mode`: file mode for `app_home`, is an integer. +- `prefix_root`: default `prefix_root`, for use with `:install*` actions. +- `prefix_home`: default directory prefix for a friendly symlink to the path. + + - Example: `/usr/local/maven` -> `/usr/local/maven-2.2.1` + +- `prefix_bin`: default directory to place a symlink to a binary command. + + - Example: `/opt/bin/mvn` -> `/opt/maven-2.2.1/bin/mvn`, where the `prefix_bin` is `/opt/bin` + +- `path`: path to extract the ark to. The `:install*` actions overwrite any user-provided values for `:path`. + + - Default: `/usr/local/-` for the `:install`, `:install_with_make` actions + +- `home_dir`: symbolic link to the path `:prefix_root/:name-:version`, does not apply to `:dump`, `:put`, or `:cherry_pick` actions. + + - Default: `:prefix_root/:name` + +- `has_binaries`: array of binary commands to symlink into `/usr/local/bin/`, you must specify the relative path. + + - Example: `[ 'bin/java', 'bin/javaws' ]` + +- `append_env_path`: boolean, similar to `has_binaries` but less granular. If true, append the `./bin` directory of the extracted directory to. the `PATH` environment variable for all users, by placing a file in `/etc/profile.d/`. The commands are symbolically linked into `/usr/bin/*`. This option provides more granularity than the boolean option. + + - Example: `mvn`, `java`, `javac`, etc. + +- `environment`: hash of environment variables to pass to invoked shell commands like `tar`, `unzip`, `configure`, and `make`. + +- `strip_components`: number of components in path to strip when extracting archive. With default value of `1`, ark strips the leading directory from an archive, which is the default for both `unzip` and `tar` commands. + +- `autoconf_opts`: an array of command line options for use with the GNU `autoconf` script. + + - Example: `[ '--include=/opt/local/include', '--force' ]` + +- `make_opts`: an array of command line options for use with `make`. + + - Example: `[ '--warn-undefined-variables', '--load-average=2' ]` + +- `owner`: owner of extracted directory. + + - Default: `root` + +- `group`: group of extracted directory. + + - Default: `root` + +- `backup`: The number of backups to be kept in /var/chef/backup (for UNIX- and Linux-based platforms) or C:/chef/backup (for the Microsoft Windows platform). Set to false to prevent backups from being kept. + + - Default: `5` + +#### Examples + +This example copies `ivy.tar.gz` to `/var/cache/chef/ivy-2.2.0.tar.gz`, unpacks its contents to `/usr/local/ivy-2.2.0/` -- stripping the leading directory, and symlinks `/usr/local/ivy` to `/usr/local/ivy-2.2.0` + +```ruby + # install Apache Ivy dependency resolution tool + ark "ivy" do + url 'http://someurl.example.com/ivy.tar.gz' + version '2.2.0' + checksum '89ba5fde0c596db388c3bbd265b63007a9cc3df3a8e6d79a46780c1a39408cb5' + action :install + end +``` + +This example copies `jdk-7u2-linux-x64.tar.gz` to `/var/cache/chef/jdk-7.2.tar.gz`, unpacks its contents to `/usr/local/jvm/jdk-7.2/` -- stripping the leading directory, symlinks `/usr/local/jvm/default` to `/usr/local/jvm/jdk-7.2`, and adds `/usr/local/jvm/jdk-7.2/bin/` to the global `PATH` for all users. The user 'foobar' is the owner of the `/usr/local/jvm/jdk-7.2` directory: + +```ruby + ark 'jdk' do + url 'http://download.example.com/jdk-7u2-linux-x64.tar.gz' + version '7.2' + path "/usr/local/jvm/" + home_dir "/usr/local/jvm/default" + checksum '89ba5fde0c596db388c3bbd265b63007a9cc3df3a8e6d79a46780c1a39408cb5' + append_env_path true + owner 'foobar' + end +``` + +Install Apache Ivy dependency resolution tool in `/resource_name` in this case `/usr/local/ivy`, do not symlink, and strip any leading directory if one exists in the tarball: + +```ruby + ark "ivy" do + url 'http://someurl.example.com/ivy.tar.gz' + checksum '89ba5fde0c596db388c3bbd265b63007a9cc3df3a8e6d79a46780c1a39408cb5' + action :put + end +``` + +Install Apache Ivy dependency resolution tool in `/home/foobar/ivy`, strip any leading directory if one exists, don't keep backup copies of `ivy.tar.gz`: + +```ruby + ark "ivy" do + path "/home/foobar" + url 'http://someurl.example.com/ivy.tar.gz' + checksum '89ba5fde0c596db388c3bbd265b63007a9cc3df3a8e6d79a46780c1a39408cb5' + action :put + backup false + end +``` + +Strip all directories and dump files into path specified by the path attribute. You must specify the `creates` attribute in order to keep the extraction from running every time. The directory path will be created if it doesn't already exist: + +```ruby + ark "my_jars" do + url "http://example.com/bunch_of_jars.zip" + path "/usr/local/tomcat/lib" + creates "mysql.jar" + owner "tomcat" + action :dump + end +``` + +Extract specific files from a tarball (currently only handles one named file): + +```ruby + ark 'mysql-connector-java' do + url 'http://oracle.com/mysql-connector.zip' + creates 'mysql-connector-java-5.0.8-bin.jar' + path '/usr/local/tomcat/lib' + action :cherry_pick + end +``` + +Build and install haproxy and use alternative values for `prefix_root`, `prefix_home`, and `prefix_bin`: + +```ruby + ark "haproxy" do + url "http://haproxy.1wt.eu/download/1.5/src/snapshot/haproxy-ss-20120403.tar.gz" + version "1.5" + checksum 'ba0424bf7d23b3a607ee24bbb855bb0ea347d7ffde0bec0cb12a89623cbaf911' + make_opts [ 'TARGET=linux26' ] + prefix_root '/opt' + prefix_home '/opt' + prefix_bin '/opt/bin' + action :install_with_make + end +``` + +You can also supply the file extension in case the file extension can not be determined by the URL: + +```ruby + ark "test_autogen" do + url 'https://github.com/zeromq/libzmq/tarball/master' + extension "tar.gz" + action :install_with_make + end +``` + +## License & Authors + +- Author: Philip (flip) Kromer - Infochimps, Inc([coders@infochimps.com](mailto:coders@infochimps.com)) +- Author: Bryan W. Berry ([bryan.berry@gmail.com](mailto:bryan.berry@gmail.com)) +- Author: Denis Barishev ([denis.barishev@gmail.com](mailto:denis.barishev@gmail.com)) +- Author: Sean OMeara ([someara@chef.io](mailto:someara@chef.io)) +- Author: John Bellone ([jbellone@bloomberg.net](mailto:jbellone@bloomberg.net)) +- Copyright: 2011, Philip (flip) Kromer - Infochimps, Inc +- Copyright: 2012, Bryan W. Berry +- Copyright: 2012, Denis Barishev +- Copyright: 2013-2017, Chef Software, Inc +- Copyright: 2014, Bloomberg L.P. + +``` +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/cookbooks/ark/attributes/default.rb b/cookbooks/ark/attributes/default.rb new file mode 100644 index 0000000..10b3e01 --- /dev/null +++ b/cookbooks/ark/attributes/default.rb @@ -0,0 +1,47 @@ +# +# Cookbook:: ark +# Attributes:: default +# +# +# 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. +# + +default['ark']['apache_mirror'] = 'http://apache.mirrors.tds.net' +default['ark']['prefix_root'] = '/usr/local' +default['ark']['prefix_bin'] = '/usr/local/bin' +default['ark']['prefix_home'] = '/usr/local' + +# the default path will be determined based on platform, but can be overridden here +default['ark']['tar'] = nil + +# the default path will be determined from the registry, but you may override here +default['ark']['sevenzip_binary'] = nil + +pkgs = %w(libtool autoconf) unless platform_family?('mac_os_x') +pkgs += %w(make) unless platform_family?('mac_os_x', 'freebsd') +pkgs += %w(unzip rsync gcc) unless platform_family?('mac_os_x') +pkgs += %w(autogen) unless platform_family?('rhel', 'fedora', 'mac_os_x', 'suse', 'amazon') +pkgs += %w(gtar) if platform?('freebsd') || platform?('smartos') +pkgs += %w(gmake) if platform?('freebsd') +if platform_family?('rhel', 'suse', 'amazon') + if node['platform_version'].to_i >= 7 + pkgs += %w(xz bzip2 tar) + elsif node['platform_version'].to_i < 7 + pkgs += %w(xz-lzma-compat bzip2 tar) + end +elsif platform_family?('fedora') + pkgs += %w(xz-lzma-compat bzip2 tar) +end +pkgs += %w(shtool pkg-config) if platform_family?('debian') + +default['ark']['package_dependencies'] = pkgs diff --git a/cookbooks/ark/files/default/foo.tar.gz b/cookbooks/ark/files/default/foo.tar.gz new file mode 100644 index 0000000..16aa5a7 Binary files /dev/null and b/cookbooks/ark/files/default/foo.tar.gz differ diff --git a/cookbooks/ark/files/default/foo.tbz b/cookbooks/ark/files/default/foo.tbz new file mode 100644 index 0000000..6f29777 Binary files /dev/null and b/cookbooks/ark/files/default/foo.tbz differ diff --git a/cookbooks/ark/files/default/foo.tgz b/cookbooks/ark/files/default/foo.tgz new file mode 100644 index 0000000..f78dd03 Binary files /dev/null and b/cookbooks/ark/files/default/foo.tgz differ diff --git a/cookbooks/ark/files/default/foo.txz b/cookbooks/ark/files/default/foo.txz new file mode 100644 index 0000000..7f742da Binary files /dev/null and b/cookbooks/ark/files/default/foo.txz differ diff --git a/cookbooks/ark/files/default/foo.zip b/cookbooks/ark/files/default/foo.zip new file mode 100644 index 0000000..d302b88 Binary files /dev/null and b/cookbooks/ark/files/default/foo.zip differ diff --git a/cookbooks/ark/files/default/foo_sub.tar.gz b/cookbooks/ark/files/default/foo_sub.tar.gz new file mode 100644 index 0000000..258d205 Binary files /dev/null and b/cookbooks/ark/files/default/foo_sub.tar.gz differ diff --git a/cookbooks/ark/files/default/foo_sub.zip b/cookbooks/ark/files/default/foo_sub.zip new file mode 100644 index 0000000..e648478 Binary files /dev/null and b/cookbooks/ark/files/default/foo_sub.zip differ diff --git a/cookbooks/ark/libraries/default.rb b/cookbooks/ark/libraries/default.rb new file mode 100644 index 0000000..24b09e6 --- /dev/null +++ b/cookbooks/ark/libraries/default.rb @@ -0,0 +1,113 @@ +require_relative 'platform_specific_builders' +require_relative 'resource_deprecations' +require_relative 'resource_defaults' +require_relative 'sevenzip_command_builder' +require_relative 'unzip_command_builder' +require_relative 'tar_command_builder' +require_relative 'general_owner' +require_relative 'windows_owner' + +module Ark + module ProviderHelpers + extend ::Ark::PlatformSpecificBuilders + + generates_archive_commands_for :seven_zip, + when_the: -> { node['platform_family'] == 'windows' }, + with_klass: ::Ark::SevenZipCommandBuilder + + generates_archive_commands_for :unzip, + when_the: -> { new_resource.extension =~ /zip|war|jar/ }, + with_klass: ::Ark::UnzipCommandBuilder + + generates_archive_commands_for :tar, + when_the: -> { true }, + with_klass: ::Ark::TarCommandBuilder + + generates_owner_commands_for :windows, + when_the: -> { node['platform_family'] == 'windows' }, + with_klass: ::Ark::WindowsOwner + + generates_owner_commands_for :all_other_platforms, + when_the: -> { true }, + with_klass: ::Ark::GeneralOwner + + def deprecations + ::Ark::ResourceDeprecations.on(new_resource) + end + + def show_deprecations + deprecations.each { |message| Chef::Log.warn("DEPRECATED: #{message}") } + end + + def defaults + @resource_defaults ||= ::Ark::ResourceDefaults.new(new_resource) + end + + def set_paths + new_resource.extension = defaults.extension + new_resource.prefix_bin = defaults.prefix_bin + new_resource.prefix_root = defaults.prefix_root + new_resource.home_dir = defaults.home_dir + new_resource.version = defaults.version + new_resource.owner = defaults.owner + + # TODO: what happens when the path is already set -- + # with the current logic we overwrite it + # if you are in windows we overwrite it + # otherwise we overwrite it with the root/name-version + new_resource.path = defaults.path + new_resource.release_file = defaults.release_file + end + # rubocop:enable Metrics/AbcSize + + def set_put_paths + new_resource.extension = defaults.extension + + # TODO: Should we be setting the prefix_root - + # as the prefix_root could be used in the path_with_version + # new_resource.prefix_root = default.prefix_root + new_resource.path = defaults.path_without_version + new_resource.release_file = defaults.release_file_without_version + end + + def set_dump_paths + new_resource.extension = defaults.extension + new_resource.release_file = defaults.release_file_without_version + end + + def unpack_command + archive_application.unpack + end + + def dump_command + archive_application.dump + end + + def cherry_pick_command + archive_application.cherry_pick + end + + def unzip_command + archive_application.unpack + end + + def owner_command + owner_builder_klass.new(new_resource).command + end + + private + + def archive_application + @archive_application ||= archive_builder_klass.new(new_resource) + end + + def archive_builder_klass + new_resource.extension ||= defaults.extension + Ark::ProviderHelpers.archive_command_generators.find { |condition, _klass| instance_exec(&condition) }.last + end + + def owner_builder_klass + Ark::ProviderHelpers.owner_command_generators.find { |condition, _klass| instance_exec(&condition) }.last + end + end +end diff --git a/cookbooks/ark/libraries/general_owner.rb b/cookbooks/ark/libraries/general_owner.rb new file mode 100644 index 0000000..f7591de --- /dev/null +++ b/cookbooks/ark/libraries/general_owner.rb @@ -0,0 +1,13 @@ +module Ark + class GeneralOwner + def initialize(resource) + @resource = resource + end + + attr_reader :resource + + def command + "chown -R #{resource.owner}:#{resource.group} #{resource.path}" + end + end +end diff --git a/cookbooks/ark/libraries/matchers.rb b/cookbooks/ark/libraries/matchers.rb new file mode 100644 index 0000000..aa8901b --- /dev/null +++ b/cookbooks/ark/libraries/matchers.rb @@ -0,0 +1,44 @@ + +if defined?(ChefSpec) + ChefSpec.define_matcher :ark + + def install_ark(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:ark, :install, resource_name) + end + + def dump_ark(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:ark, :dump, resource_name) + end + + def cherry_pick_ark(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:ark, :cherry_pick, resource_name) + end + + def put_ark(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:ark, :put, resource_name) + end + + def install_with_make_ark(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:ark, :install_with_make, resource_name) + end + + def configure_ark(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:ark, :configure, resource_name) + end + + def setup_py_build_ark(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:ark, :setup_py_build, resource_name) + end + + def setup_py_install_ark(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:ark, :setup_py_install, resource_name) + end + + def setup_py_ark(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:ark, :setup_py, resource_name) + end + + def unzip_ark(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:ark, :unzip, resource_name) + end +end diff --git a/cookbooks/ark/libraries/platform_specific_builders.rb b/cookbooks/ark/libraries/platform_specific_builders.rb new file mode 100644 index 0000000..b8bd6f0 --- /dev/null +++ b/cookbooks/ark/libraries/platform_specific_builders.rb @@ -0,0 +1,23 @@ +module Ark + module PlatformSpecificBuilders + def generates_archive_commands_for(_name, options) + condition = options[:when_the] + builder = options[:with_klass] + archive_command_generators.push [condition, builder] + end + + def archive_command_generators + @archive_command_generators ||= [] + end + + def generates_owner_commands_for(_name, options) + condition = options[:when_the] + builder = options[:with_klass] + owner_command_generators.push [condition, builder] + end + + def owner_command_generators + @owner_command_generators ||= [] + end + end +end diff --git a/cookbooks/ark/libraries/resource_defaults.rb b/cookbooks/ark/libraries/resource_defaults.rb new file mode 100644 index 0000000..9b5ac76 --- /dev/null +++ b/cookbooks/ark/libraries/resource_defaults.rb @@ -0,0 +1,119 @@ +module Ark + class ResourceDefaults + def extension + resource.extension || generate_extension_from_url(resource.url.clone) + end + + def prefix_bin + resource.prefix_bin || prefix_bin_from_node_in_run_context + end + + def prefix_root + resource.prefix_root || prefix_root_from_node_in_run_context + end + + def home_dir + if resource.home_dir.nil? || resource.home_dir.empty? + prefix_home = resource.prefix_home || prefix_home_from_node_in_run_context + ::File.join(prefix_home, resource.name) + else + resource.home_dir + end + end + + def version + resource.version || default_version + end + + def path + if windows? + resource.win_install_dir + else + ::File.join(resource.prefix_root, "#{resource.name}-#{resource.version}") + end + end + + def owner + resource.owner || default_owner + end + + def windows? + node_in_run_context['platform_family'] == 'windows' + end + + def path_without_version + partial_path = resource.path || prefix_root_from_node_in_run_context + ::File.join(partial_path, resource.name) + end + + def release_file + release_filename = "#{resource.name}-#{resource.version}.#{resource.extension}" + ::File.join(file_cache_path, release_filename) + end + + def release_file_without_version + release_filename = "#{resource.name}.#{resource.extension}" + ::File.join(file_cache_path, release_filename) + end + + def initialize(resource) + @resource = resource + end + + private + + attr_reader :resource + + def generate_extension_from_url(url) + # purge any trailing redirect + url =~ %r{^https?:\/\/.*(.bin|bz2|gz|jar|tbz|tgz|txz|war|xz|zip|7z)(\/.*\/)} + url.gsub!(Regexp.last_match(2), '') unless Regexp.last_match(2).nil? + # remove trailing query string + release_basename = ::File.basename(url.gsub(/\?.*\z/, '')).gsub(/-bin\b/, '') + # (\?.*)? accounts for a trailing querystring + Chef::Log.debug("DEBUG: release_basename is #{release_basename}") + release_basename =~ /^(.+?)\.(jar|tar\.bz2|tar\.gz|tar\.xz|tbz|tgz|txz|war|zip|tar|7z)(\?.*)?/ + Chef::Log.debug("DEBUG: file_extension is #{Regexp.last_match(2)}") + Regexp.last_match(2) + end + + def prefix_bin_from_node_in_run_context + node_in_run_context['ark']['prefix_bin'] + end + + def prefix_root_from_node_in_run_context + node_in_run_context['ark']['prefix_root'] + end + + def prefix_home_from_node_in_run_context + node_in_run_context['ark']['prefix_home'] + end + + def default_version + '1' + end + + def default_owner + if windows? + wmi_property_from_query(:name, "select * from Win32_UserAccount where sid like 'S-1-5-21-%-500' and LocalAccount=True") + else + 'root' + end + end + + def wmi_property_from_query(wmi_property, wmi_query) + @wmi = ::WIN32OLE.connect('winmgmts://') + result = @wmi.ExecQuery(wmi_query) + return nil unless result.each.count > 0 + result.each.next.send(wmi_property) + end + + def file_cache_path + Chef::Config[:file_cache_path] + end + + def node_in_run_context + resource.run_context.node + end + end +end diff --git a/cookbooks/ark/libraries/resource_deprecations.rb b/cookbooks/ark/libraries/resource_deprecations.rb new file mode 100644 index 0000000..9a4fc47 --- /dev/null +++ b/cookbooks/ark/libraries/resource_deprecations.rb @@ -0,0 +1,33 @@ +module Ark + class ResourceDeprecations + def self.on(resource) + new(resource).warnings + end + + def initialize(resource) + @resource = resource + end + + attr_reader :resource + + def warnings + applicable_deprecrations.map { |_, message| message } + end + + def applicable_deprecrations + deprecations.select { |condition, _| send(condition) } + end + + def deprecations + { strip_leading_dir_feature: strip_leading_dir_feature_message } + end + + def strip_leading_dir_feature + [true, false].include?(resource.strip_leading_dir) + end + + def strip_leading_dir_feature_message + 'strip_leading_dir attribute was deprecated. Use strip_components instead.' + end + end +end diff --git a/cookbooks/ark/libraries/sevenzip_command_builder.rb b/cookbooks/ark/libraries/sevenzip_command_builder.rb new file mode 100644 index 0000000..7319a0e --- /dev/null +++ b/cookbooks/ark/libraries/sevenzip_command_builder.rb @@ -0,0 +1,78 @@ +module Ark + class SevenZipCommandBuilder + def unpack + sevenzip_command + end + + def dump + sevenzip_command_builder(resource.path, 'e') + end + + def cherry_pick + "#{sevenzip_command_builder(resource.path, 'x')} -r #{resource.creates}" + end + + def initialize(resource) + @resource = resource + end + + private + + attr_reader :resource + + def node + resource.run_context.node + end + + def sevenzip_command + if resource.strip_components <= 0 + return sevenzip_command_builder(resource.path, 'x') + end + + tmpdir = make_temp_directory.tr('/', '\\') + cmd = sevenzip_command_builder(tmpdir, 'x') + + cmd += ' && ' + currdir = tmpdir + + 1.upto(resource.strip_components).each do |count| + cmd += "for /f %#{count} in ('dir /ad /b \"#{currdir}\"') do " + currdir += "\\%#{count}" + end + + cmd += "(\"#{ENV.fetch('SystemRoot')}\\System32\\robocopy\" \"#{currdir}\" \"#{resource.path}\" /s /e) ^& IF %ERRORLEVEL% LEQ 3 cmd /c exit 0" + end + + def sevenzip_binary + @tar_binary ||= "\"#{(node['ark']['sevenzip_binary'] || sevenzip_path_from_registry)}\"" + end + + def sevenzip_path_from_registry + begin + basepath = ::Win32::Registry::HKEY_LOCAL_MACHINE.open('SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\7zFM.exe').read_s('Path') + + # users like pretty errors + rescue ::Win32::Registry::Error + raise 'Failed to find the path of 7zip binary by searching checking HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\7zFM.exe\Path. Make sure to install 7zip before using this resource. If 7zip is installed and you still receive this message you can also specify the 7zip binary path by setting node["ark"]["sevenzip_binary"]' + end + "#{basepath}7z.exe" + end + + def sevenzip_command_builder(dir, command) + "#{sevenzip_binary} #{command} \"#{resource.release_file}\"#{extension_is_tar} -o\"#{dir}\" -uy" + end + + def extension_is_tar + if resource.extension =~ /tar.gz|tgz|tar.bz2|tbz|tar.xz|txz/ + " -so | #{sevenzip_binary} x -aoa -si -ttar" + else + ' -aoa' # force overwrite, Fixes #164 + end + end + + def make_temp_directory + require 'tmpdir' + Dir.mktmpdir + end + end +end diff --git a/cookbooks/ark/libraries/tar_command_builder.rb b/cookbooks/ark/libraries/tar_command_builder.rb new file mode 100644 index 0000000..291dbb9 --- /dev/null +++ b/cookbooks/ark/libraries/tar_command_builder.rb @@ -0,0 +1,56 @@ +module Ark + class TarCommandBuilder + def unpack + "#{tar_binary} #{args} #{resource.release_file}#{strip_args}" + end + + def dump + "tar -mxf \"#{resource.release_file}\" -C \"#{resource.path}\"" + end + + def cherry_pick + "#{tar_binary} #{args} #{resource.release_file} -C #{resource.path} #{resource.creates}#{strip_args}" + end + + def initialize(resource) + @resource = resource + end + + private + + attr_reader :resource + + def node + resource.run_context.node + end + + def tar_binary + @tar_binary ||= node['ark']['tar'] || case node['platform_family'] + when 'mac_os_x', 'freebsd' + '/usr/bin/tar' + when 'smartos' + '/bin/gtar' + else + '/bin/tar' + end + end + + def args + case resource.extension + when /^(tar)$/ then 'xf' + when /^(tar.gz|tgz)$/ then 'xzf' + when /^(tar.bz2|tbz)$/ then 'xjf' + when /^(tar.xz|txz)$/ then 'xJf' + else raise unsupported_extension + end + end + + def strip_args + resource.strip_components > 0 ? " --strip-components=#{resource.strip_components}" : '' + end + + def unsupported_extension + "Don't know how to expand #{resource.url} (extension: #{resource.extension})" + end + end +end diff --git a/cookbooks/ark/libraries/unzip_command_builder.rb b/cookbooks/ark/libraries/unzip_command_builder.rb new file mode 100644 index 0000000..7605f5c --- /dev/null +++ b/cookbooks/ark/libraries/unzip_command_builder.rb @@ -0,0 +1,48 @@ +module Ark + class UnzipCommandBuilder + def unpack + if resource.strip_components > 0 + unzip_with_strip_components + else + "unzip -q -o #{resource.release_file} -d #{resource.path}" + end + end + + def dump + "unzip -j -q -o \"#{resource.release_file}\" -d \"#{resource.path}\"" + end + + def cherry_pick + cmd = "unzip -t #{resource.release_file} \"*/#{resource.creates}\" ; stat=$? ;" + cmd += 'if [ $stat -eq 11 ] ; then ' + cmd += "unzip -j -o #{resource.release_file} \"#{resource.creates}\" -d #{resource.path} ;" + cmd += 'elif [ $stat -ne 0 ] ; then false ;' + cmd += 'else ' + cmd += "unzip -j -o #{resource.release_file} \"*/#{resource.creates}\" -d #{resource.path} ;" + cmd += 'fi' + cmd + end + + def initialize(resource) + @resource = resource + end + + private + + attr_reader :resource + + def unzip_with_strip_components + tmpdir = make_temp_directory + strip_dir = '*/' * resource.strip_components + cmd = "unzip -q -o #{resource.release_file} -d #{tmpdir}" + cmd += " && rsync -a #{tmpdir}/#{strip_dir} #{resource.path}" + cmd += " && rm -rf #{tmpdir}" + cmd + end + + def make_temp_directory + require 'tmpdir' + Dir.mktmpdir + end + end +end diff --git a/cookbooks/ark/libraries/windows_owner.rb b/cookbooks/ark/libraries/windows_owner.rb new file mode 100644 index 0000000..f548b34 --- /dev/null +++ b/cookbooks/ark/libraries/windows_owner.rb @@ -0,0 +1,13 @@ +module Ark + class WindowsOwner + def initialize(resource) + @resource = resource + end + + attr_reader :resource + + def command + "#{ENV.fetch('SystemRoot')}\\System32\\icacls \"#{resource.path}\\*\" /setowner \"#{resource.owner}\"" + end + end +end diff --git a/cookbooks/ark/metadata.json b/cookbooks/ark/metadata.json new file mode 100644 index 0000000..a531332 --- /dev/null +++ b/cookbooks/ark/metadata.json @@ -0,0 +1 @@ +{"name":"ark","version":"3.1.0","description":"Provides a custom resource for installing runtime artifacts in a predictable fashion","long_description":"# ark cookbook\n\n[![Build Status](https://travis-ci.org/chef-cookbooks/ark.svg?branch=master)](https://travis-ci.org/chef-cookbooks/ark) [![Cookbook Version](https://img.shields.io/cookbook/v/ark.svg)](https://supermarket.chef.io/cookbooks/ark)\n\n## Overview\n\nThis cookbook provides `ark`, a resource for managing software archives. It manages the fetch-unpack-configure-build-install process common to installing software from source, or from binary distributions that are not fully fledged OS packages.\n\nThis cookbook started its life as a modified version of Infochimp's install_from cookbook. It has since been heavily refactored and extended to meet different use cases.\n\nGiven a simple project archive available at a url:\n\n```ruby\nark 'pig' do\n url 'http://apache.org/pig/pig-0.8.0.tar.gz'\nend\n```\n\nThe `ark` resource will:\n\n- fetch it to to `/var/cache/chef/`\n- unpack it to the default path (`/usr/local/pig-0.8.0`)\n- create a symlink for `:home_dir` (`/usr/local/pig`) pointing to path\n- add specified binary commands to the environment `PATH` variable\n\nBy default, the ark will not run again if the `:path` is not empty. Ark provides many actions to accommodate different use cases, such as `:dump`, `:cherry_pick`, `:put`, and `:install_with_make`.\n\nAt this time ark only handles files available from URLs using the [remote_file](http://docs.chef.io/resource_remote_file.html) provider. It does handle local files using the `file://` protocol.\n\n## Requirements\n\n### Platforms\n\n- Debian/Ubuntu\n- RHEL/CentOS/Scientific/Oracle\n- Fedora\n- FreeBSD\n- SmartOS\n- Mac OS X\n- openSUSE / SUSE Linux Enterprises\n- Windows\n\nShould work on common Unix/Linux systems with typical userland utilities like tar, gzip, etc. May require the installation of build tools for compiling from source, but that installation is outside the scope of this cookbook.\n\n### Chef\n\n- Chef 12.7+\n\n### Cookbooks\n\n- build-essential\n- seven_zip\n- windows\n\n## Attributes\n\nCustomize the attributes to suit site specific conventions and defaults.\n\n- `node['ark']['apache_mirror']` - if the URL is an apache mirror, use the attribute as the default. default: `http://apache.mirrors.tds.net`\n- `node['ark']['prefix_root']` - default base location if the `prefix_root` is not passed into the resource. default: `/usr/local`\n- `node['ark']['prefix_bin']` - default binary location if the `prefix_bin` is not passed into the resource. default: `/usr/local/bin`\n- `node['ark']['prefix_home']` - default home location if the `prefix_home` is not passed into the resource. default: `/usr/local`\n- `node['ark']['package_dependencies']` - prerequisite system packages that need to be installed to support ark. default: varies based on platform\n- `node['ark']['tar']` - allows overriding the default path to the tar binary, which varies based on platform\n- `node['ark']['sevenzip_binary']` - allows overriding the default path to the 7zip binary, which is determined based on registry key value\n\n## Resources\n\n- `ark` - does the extract/build/configure \n\n### Actions\n\n- `:install`: extracts the file and creates a 'friendly' symbolic link to the extracted directory path\n- `:configure`: configure ahead of the install action\n- `:install_with_make`: extracts the archive to a path, runs `configure`, `make`, and `make install`.\n- `:dump`: strips all directories from the archive and dumps the contained files into a specified path\n- `:cherry_pick`: extract a specified file from an archive and places in specified path\n- `:put`: extract the archive to a specified path, does not create any symbolic links\n- `:remove`: removes the extracted directory and related symlink #TODO\n- `:setup_py`: runs the command \"python setup.py\" in the extracted directory\n- `:setup_py_build`: runs the command \"python setup.py build\" in the extracted directory\n- `:setup_py_install`: runs the command \"python setup.py install\" in the extracted directory\n\n### :cherry_pick\n\nExtract a specified file from an archive and places in specified path.\n\n#### Relevant Attribute Parameters for :cherry_pick\n\n- `path`: directory to place file in.\n- `creates`: specific file to cherry-pick.\n\n### :dump\n\nStrips all directories from the archive and dumps the contained files into a specified path.\n\nNOTE: This currently only works for zip archives\n\n#### Attribute Parameters for :dump\n\n- `path`: path to dump files to.\n- `mode`: file mode for `app_home`, as an integer.\n\n - Example: `0775`\n\n- `creates`: if you are appending files to a given directory, ark needs a condition to test whether the file has already been extracted. You can specify with creates, a file whose existence indicates the ark has previously been extracted and does not need to be extracted again.\n\n### :put\n\nExtract the archive to a specified path, does not create any symbolic links.\n\n#### Attribute Parameters for :put\n\n- `path`: path to extract to.\n\n - Default: `/usr/local`\n\n- `append_env_path`: boolean, if true, append the `./bin` directory of the extracted directory to the global `PATH` variable for all users.\n\n### Attribute Parameters\n\n- `name`: name of the package, defaults to the resource name.\n- `url`: url for tarball, `.tar.gz`, `.bin` (oracle-specific), `.war`, and `.zip` currently supported. Also supports special syntax\n- `:name:version:apache_mirror:` that will auto-magically construct download url from the apache mirrors site.\n- `version`: software version, defaults to `1`.\n- `mode`: file mode for `app_home`, is an integer.\n- `prefix_root`: default `prefix_root`, for use with `:install*` actions.\n- `prefix_home`: default directory prefix for a friendly symlink to the path.\n\n - Example: `/usr/local/maven` -> `/usr/local/maven-2.2.1`\n\n- `prefix_bin`: default directory to place a symlink to a binary command.\n\n - Example: `/opt/bin/mvn` -> `/opt/maven-2.2.1/bin/mvn`, where the `prefix_bin` is `/opt/bin`\n\n- `path`: path to extract the ark to. The `:install*` actions overwrite any user-provided values for `:path`.\n\n - Default: `/usr/local/-` for the `:install`, `:install_with_make` actions\n\n- `home_dir`: symbolic link to the path `:prefix_root/:name-:version`, does not apply to `:dump`, `:put`, or `:cherry_pick` actions.\n\n - Default: `:prefix_root/:name`\n\n- `has_binaries`: array of binary commands to symlink into `/usr/local/bin/`, you must specify the relative path.\n\n - Example: `[ 'bin/java', 'bin/javaws' ]`\n\n- `append_env_path`: boolean, similar to `has_binaries` but less granular. If true, append the `./bin` directory of the extracted directory to. the `PATH` environment variable for all users, by placing a file in `/etc/profile.d/`. The commands are symbolically linked into `/usr/bin/*`. This option provides more granularity than the boolean option.\n\n - Example: `mvn`, `java`, `javac`, etc.\n\n- `environment`: hash of environment variables to pass to invoked shell commands like `tar`, `unzip`, `configure`, and `make`.\n\n- `strip_components`: number of components in path to strip when extracting archive. With default value of `1`, ark strips the leading directory from an archive, which is the default for both `unzip` and `tar` commands.\n\n- `autoconf_opts`: an array of command line options for use with the GNU `autoconf` script.\n\n - Example: `[ '--include=/opt/local/include', '--force' ]`\n\n- `make_opts`: an array of command line options for use with `make`.\n\n - Example: `[ '--warn-undefined-variables', '--load-average=2' ]`\n\n- `owner`: owner of extracted directory.\n\n - Default: `root`\n\n- `group`: group of extracted directory.\n\n - Default: `root`\n\n- `backup`: The number of backups to be kept in /var/chef/backup (for UNIX- and Linux-based platforms) or C:/chef/backup (for the Microsoft Windows platform). Set to false to prevent backups from being kept.\n\n - Default: `5`\n\n#### Examples\n\nThis example copies `ivy.tar.gz` to `/var/cache/chef/ivy-2.2.0.tar.gz`, unpacks its contents to `/usr/local/ivy-2.2.0/` -- stripping the leading directory, and symlinks `/usr/local/ivy` to `/usr/local/ivy-2.2.0`\n\n```ruby\n # install Apache Ivy dependency resolution tool\n ark \"ivy\" do\n url 'http://someurl.example.com/ivy.tar.gz'\n version '2.2.0'\n checksum '89ba5fde0c596db388c3bbd265b63007a9cc3df3a8e6d79a46780c1a39408cb5'\n action :install\n end\n```\n\nThis example copies `jdk-7u2-linux-x64.tar.gz` to `/var/cache/chef/jdk-7.2.tar.gz`, unpacks its contents to `/usr/local/jvm/jdk-7.2/` -- stripping the leading directory, symlinks `/usr/local/jvm/default` to `/usr/local/jvm/jdk-7.2`, and adds `/usr/local/jvm/jdk-7.2/bin/` to the global `PATH` for all users. The user 'foobar' is the owner of the `/usr/local/jvm/jdk-7.2` directory:\n\n```ruby\n ark 'jdk' do\n url 'http://download.example.com/jdk-7u2-linux-x64.tar.gz'\n version '7.2'\n path \"/usr/local/jvm/\"\n home_dir \"/usr/local/jvm/default\"\n checksum '89ba5fde0c596db388c3bbd265b63007a9cc3df3a8e6d79a46780c1a39408cb5'\n append_env_path true\n owner 'foobar'\n end\n```\n\nInstall Apache Ivy dependency resolution tool in `/resource_name` in this case `/usr/local/ivy`, do not symlink, and strip any leading directory if one exists in the tarball:\n\n```ruby\n ark \"ivy\" do\n url 'http://someurl.example.com/ivy.tar.gz'\n checksum '89ba5fde0c596db388c3bbd265b63007a9cc3df3a8e6d79a46780c1a39408cb5'\n action :put\n end\n```\n\nInstall Apache Ivy dependency resolution tool in `/home/foobar/ivy`, strip any leading directory if one exists, don't keep backup copies of `ivy.tar.gz`:\n\n```ruby\n ark \"ivy\" do\n path \"/home/foobar\"\n url 'http://someurl.example.com/ivy.tar.gz'\n checksum '89ba5fde0c596db388c3bbd265b63007a9cc3df3a8e6d79a46780c1a39408cb5'\n action :put\n backup false\n end\n```\n\nStrip all directories and dump files into path specified by the path attribute. You must specify the `creates` attribute in order to keep the extraction from running every time. The directory path will be created if it doesn't already exist:\n\n```ruby\n ark \"my_jars\" do\n url \"http://example.com/bunch_of_jars.zip\"\n path \"/usr/local/tomcat/lib\"\n creates \"mysql.jar\"\n owner \"tomcat\"\n action :dump\n end\n```\n\nExtract specific files from a tarball (currently only handles one named file):\n\n```ruby\n ark 'mysql-connector-java' do\n url 'http://oracle.com/mysql-connector.zip'\n creates 'mysql-connector-java-5.0.8-bin.jar'\n path '/usr/local/tomcat/lib'\n action :cherry_pick\n end\n```\n\nBuild and install haproxy and use alternative values for `prefix_root`, `prefix_home`, and `prefix_bin`:\n\n```ruby\n ark \"haproxy\" do\n url \"http://haproxy.1wt.eu/download/1.5/src/snapshot/haproxy-ss-20120403.tar.gz\"\n version \"1.5\"\n checksum 'ba0424bf7d23b3a607ee24bbb855bb0ea347d7ffde0bec0cb12a89623cbaf911'\n make_opts [ 'TARGET=linux26' ]\n prefix_root '/opt'\n prefix_home '/opt'\n prefix_bin '/opt/bin'\n action :install_with_make\n end\n```\n\nYou can also supply the file extension in case the file extension can not be determined by the URL:\n\n```ruby\n ark \"test_autogen\" do\n url 'https://github.com/zeromq/libzmq/tarball/master'\n extension \"tar.gz\"\n action :install_with_make\n end\n```\n\n## License & Authors\n\n- Author: Philip (flip) Kromer - Infochimps, Inc([coders@infochimps.com](mailto:coders@infochimps.com))\n- Author: Bryan W. Berry ([bryan.berry@gmail.com](mailto:bryan.berry@gmail.com))\n- Author: Denis Barishev ([denis.barishev@gmail.com](mailto:denis.barishev@gmail.com))\n- Author: Sean OMeara ([someara@chef.io](mailto:someara@chef.io))\n- Author: John Bellone ([jbellone@bloomberg.net](mailto:jbellone@bloomberg.net))\n- Copyright: 2011, Philip (flip) Kromer - Infochimps, Inc\n- Copyright: 2012, Bryan W. Berry\n- Copyright: 2012, Denis Barishev\n- Copyright: 2013-2017, Chef Software, Inc\n- Copyright: 2014, Bloomberg L.P.\n\n```\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"ubuntu":">= 0.0.0","debian":">= 0.0.0","redhat":">= 0.0.0","centos":">= 0.0.0","suse":">= 0.0.0","opensuse":">= 0.0.0","opensuseleap":">= 0.0.0","scientific":">= 0.0.0","oracle":">= 0.0.0","amazon":">= 0.0.0","windows":">= 0.0.0","mac_os_x":">= 0.0.0","smartos":">= 0.0.0","freebsd":">= 0.0.0"},"dependencies":{"build-essential":">= 0.0.0","windows":">= 0.0.0","seven_zip":">= 0.0.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{"ark::default":"Installs packages needed by the custom resource"},"source_url":"https://github.com/chef-cookbooks/ark","issues_url":"https://github.com/chef-cookbooks/ark/issues","chef_version":[[">= 12.7"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/ark/recipes/default.rb b/cookbooks/ark/recipes/default.rb new file mode 100644 index 0000000..9a482aa --- /dev/null +++ b/cookbooks/ark/recipes/default.rb @@ -0,0 +1,23 @@ +# +# Cookbook:: ark +# Recipe:: default +# +# Author:: Bryan W. Berry +# Copyright:: 2012-2017, Bryan W. Berry +# +# 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. +# + +package node['ark']['package_dependencies'] unless %w(windows mac_os_x).include?(node['platform_family']) + +include_recipe 'seven_zip' if node['platform_family'] == 'windows' diff --git a/cookbooks/ark/resources/default.rb b/cookbooks/ark/resources/default.rb new file mode 100644 index 0000000..3bcb4c4 --- /dev/null +++ b/cookbooks/ark/resources/default.rb @@ -0,0 +1,528 @@ +# +# Cookbook:: ark +# Resource:: Ark +# +# Author:: Bryan W. Berry +# Copyright:: 2012-2017, Bryan W. Berry +# Copyright:: 2016-2017, Chef Software Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +property :owner, String +property :group, [String, Integer], default: 0 +property :url, String, required: true +property :path, String +property :full_path, String +property :append_env_path, [true, false], default: false +property :checksum, regex: /^[a-zA-Z0-9]{64}$/, default: nil +property :has_binaries, Array, default: [] +property :creates, String +property :release_file, String, default: '' +property :strip_leading_dir, [true, false, NilClass] +property :strip_components, Integer, default: 1 +property :mode, [Integer, String], default: 0755 +property :prefix_root, String +property :prefix_home, String +property :prefix_bin, String +property :version, String +property :home_dir, String +property :win_install_dir, String +property :environment, Hash, default: {} +property :autoconf_opts, Array, default: [] +property :make_opts, Array, default: [] +property :home_dir, String +property :autoconf_opts, Array, default: [] +property :extension, String +property :backup, [FalseClass, Integer], default: 5 + +################# +# action :install +################# +action :install do + show_deprecations + set_paths + + directory new_resource.path do + recursive true + action :create + notifies :run, "execute[unpack #{new_resource.release_file}]" + end + + remote_file new_resource.release_file do + Chef::Log.debug('DEBUG: new_resource.release_file') + source new_resource.url + checksum new_resource.checksum if new_resource.checksum + action :create + notifies :run, "execute[unpack #{new_resource.release_file}]" + backup new_resource.backup + end + + # unpack based on file extension + execute "unpack #{new_resource.release_file}" do + command unpack_command + cwd new_resource.path + environment new_resource.environment + notifies :run, "execute[set owner on #{new_resource.path}]" + action :nothing + end + + # set_owner + execute "set owner on #{new_resource.path}" do + command owner_command + action :nothing + end + + # usually on windows there is no central directory with executables where the applications are linked + unless node['platform_family'] == 'windows' + # symlink binaries + new_resource.has_binaries.each do |bin| + link ::File.join(new_resource.prefix_bin, ::File.basename(bin)) do + to ::File.join(new_resource.path, bin) + end + end + + # action_link_paths + link new_resource.home_dir do + to new_resource.path + end + + # Add to path for interactive bash sessions + template "/etc/profile.d/#{new_resource.name}.sh" do + cookbook 'ark' + source 'add_to_path.sh.erb' + owner 'root' + group node['root_group'] + mode '0755' + cookbook 'ark' + variables(directory: "#{new_resource.path}/bin") + only_if { new_resource.append_env_path } + end + end + + # Add to path for the current chef-client converge. + bin_path = ::File.join(new_resource.path, 'bin') + ruby_block "adding '#{bin_path}' to chef-client ENV['PATH']" do + block do + ENV['PATH'] = bin_path + ':' + ENV['PATH'] + end + only_if do + new_resource.append_env_path && ENV['PATH'].scan(bin_path).empty? + end + end +end + +############## +# action :put +############## +action :put do + show_deprecations + set_put_paths + + directory new_resource.path do + recursive true + action :create + notifies :run, "execute[unpack #{new_resource.release_file}]" + end + + # download + remote_file new_resource.release_file do + source new_resource.url + checksum new_resource.checksum if new_resource.checksum + action :create + notifies :run, "execute[unpack #{new_resource.release_file}]" + backup new_resource.backup + end + + # unpack based on file extension + execute "unpack #{new_resource.release_file}" do + command unpack_command + cwd new_resource.path + environment new_resource.environment + notifies :run, "execute[set owner on #{new_resource.path}]" + action :nothing + end + + # set_owner + execute "set owner on #{new_resource.path}" do + command owner_command + action :nothing + end +end + +########################### +# action :dump +########################### +action :dump do + show_deprecations + set_dump_paths + + directory new_resource.path do + recursive true + action :create + notifies :run, "execute[unpack #{new_resource.release_file}]" + end + + # download + remote_file new_resource.release_file do + Chef::Log.debug("DEBUG: new_resource.release_file #{new_resource.release_file}") + source new_resource.url + checksum new_resource.checksum if new_resource.checksum + action :create + notifies :run, "execute[unpack #{new_resource.release_file}]" + end + + # unpack based on file extension + execute "unpack #{new_resource.release_file}" do + command dump_command + cwd new_resource.path + environment new_resource.environment + notifies :run, "execute[set owner on #{new_resource.path}]" + action :nothing + end + + # set_owner + execute "set owner on #{new_resource.path}" do + command owner_command + action :nothing + end +end + +########################### +# action :unzip +########################### +action :unzip do + show_deprecations + set_dump_paths + + directory new_resource.path do + recursive true + action :create + notifies :run, "execute[unpack #{new_resource.release_file}]" + end + + # download + remote_file new_resource.release_file do + Chef::Log.debug("DEBUG: new_resource.release_file #{new_resource.release_file}") + source new_resource.url + checksum new_resource.checksum if new_resource.checksum + action :create + notifies :run, "execute[unpack #{new_resource.release_file}]" + end + + # unpack based on file extension + execute "unpack #{new_resource.release_file}" do + command unzip_command + cwd new_resource.path + environment new_resource.environment + notifies :run, "execute[set owner on #{new_resource.path}]" + action :nothing + end + + # set_owner + execute "set owner on #{new_resource.path}" do + command owner_command + action :nothing + end +end + +##################### +# action :cherry_pick +##################### +action :cherry_pick do + show_deprecations + set_dump_paths + Chef::Log.debug("DEBUG: new_resource.creates #{new_resource.creates}") + + directory new_resource.path do + recursive true + action :create + notifies :run, "execute[cherry_pick #{new_resource.creates} from #{new_resource.release_file}]" + end + + # download + remote_file new_resource.release_file do + source new_resource.url + checksum new_resource.checksum if new_resource.checksum + action :create + notifies :run, "execute[cherry_pick #{new_resource.creates} from #{new_resource.release_file}]" + end + + execute "cherry_pick #{new_resource.creates} from #{new_resource.release_file}" do + command cherry_pick_command + creates "#{new_resource.path}/#{new_resource.creates}" + notifies :run, "execute[set owner on #{new_resource.path}]" + action :nothing + end + + # set_owner + execute "set owner on #{new_resource.path}" do + command owner_command + action :nothing + end +end + +########################### +# action :install_with_make +########################### +action :install_with_make do + show_deprecations + set_paths + + directory new_resource.path do + recursive true + action :create + notifies :run, "execute[unpack #{new_resource.release_file}]" + end + + remote_file new_resource.release_file do + Chef::Log.debug('DEBUG: new_resource.release_file') + source new_resource.url + checksum new_resource.checksum if new_resource.checksum + action :create + notifies :run, "execute[unpack #{new_resource.release_file}]" + end + + # unpack based on file extension + execute "unpack #{new_resource.release_file}" do + command unpack_command + cwd new_resource.path + environment new_resource.environment + notifies :run, "execute[set owner on #{new_resource.path}]" + notifies :run, "execute[autogen #{new_resource.path}]" + notifies :run, "execute[configure #{new_resource.path}]" + notifies :run, "execute[make #{new_resource.path}]" + notifies :run, "execute[make install #{new_resource.path}]" + action :nothing + end + + # set_owner + execute "set owner on #{new_resource.path}" do + command owner_command + action :nothing + end + + execute "autogen #{new_resource.path}" do + command './autogen.sh' + only_if { ::File.exist? "#{new_resource.path}/autogen.sh" } + cwd new_resource.path + environment new_resource.environment + action :nothing + ignore_failure true + end + + execute "configure #{new_resource.path}" do + command "./configure #{new_resource.autoconf_opts.join(' ')}" + only_if { ::File.exist? "#{new_resource.path}/configure" } + cwd new_resource.path + environment new_resource.environment + action :nothing + end + + execute "make #{new_resource.path}" do + command "make #{new_resource.make_opts.join(' ')}" + cwd new_resource.path + environment new_resource.environment + action :nothing + end + + execute "make install #{new_resource.path}" do + command "make install #{new_resource.make_opts.join(' ')}" + cwd new_resource.path + environment new_resource.environment + action :nothing + end +end + +action :setup_py_build do + show_deprecations + set_paths + + directory new_resource.path do + recursive true + action :create + notifies :run, "execute[unpack #{new_resource.release_file}]" + end + + remote_file new_resource.release_file do + Chef::Log.debug('DEBUG: new_resource.release_file') + source new_resource.url + checksum new_resource.checksum if new_resource.checksum + action :create + notifies :run, "execute[unpack #{new_resource.release_file}]" + end + + # unpack based on file extension + execute "unpack #{new_resource.release_file}" do + command unpack_command + cwd new_resource.path + environment new_resource.environment + notifies :run, "execute[set owner on #{new_resource.path}]" + notifies :run, "execute[python setup.py build #{new_resource.path}]" + action :nothing + end + + # set_owner + execute "set owner on #{new_resource.path}" do + command owner_command + action :nothing + end + + execute "python setup.py build #{new_resource.path}" do + command "python setup.py build #{new_resource.make_opts.join(' ')}" + cwd new_resource.path + environment new_resource.environment + action :nothing + end +end + +action :setup_py_install do + show_deprecations + set_paths + + directory new_resource.path do + recursive true + action :create + notifies :run, "execute[unpack #{new_resource.release_file}]" + end + + remote_file new_resource.release_file do + Chef::Log.debug('DEBUG: new_resource.release_file') + source new_resource.url + checksum new_resource.checksum if new_resource.checksum + action :create + notifies :run, "execute[unpack #{new_resource.release_file}]" + end + + # unpack based on file extension + execute "unpack #{new_resource.release_file}" do + command unpack_command + cwd new_resource.path + environment new_resource.environment + notifies :run, "execute[set owner on #{new_resource.path}]" + notifies :run, "execute[python setup.py install #{new_resource.path}]" + action :nothing + end + + # set_owner + execute "set owner on #{new_resource.path}" do + command owner_command + action :nothing + end + + execute "python setup.py install #{new_resource.path}" do + command "python setup.py install #{new_resource.make_opts.join(' ')}" + cwd new_resource.path + environment new_resource.environment + action :nothing + end +end + +action :setup_py do + show_deprecations + set_paths + + directory new_resource.path do + recursive true + action :create + notifies :run, "execute[unpack #{new_resource.release_file}]" + end + + remote_file new_resource.release_file do + Chef::Log.debug('DEBUG: new_resource.release_file') + source new_resource.url + checksum new_resource.checksum if new_resource.checksum + action :create + notifies :run, "execute[unpack #{new_resource.release_file}]" + end + + # unpack based on file extension + execute "unpack #{new_resource.release_file}" do + command unpack_command + cwd new_resource.path + environment new_resource.environment + notifies :run, "execute[set owner on #{new_resource.path}]" + notifies :run, "execute[python setup.py #{new_resource.path}]" + action :nothing + end + + # set_owner + execute "set owner on #{new_resource.path}" do + command owner_command + action :nothing + end + + execute "python setup.py #{new_resource.path}" do + command "python setup.py #{new_resource.make_opts.join(' ')}" + cwd new_resource.path + environment new_resource.environment + action :nothing + end +end + +action :configure do + show_deprecations + set_paths + + directory new_resource.path do + recursive true + action :create + notifies :run, "execute[unpack #{new_resource.release_file}]" + end + + remote_file new_resource.release_file do + Chef::Log.debug('DEBUG: new_resource.release_file') + source new_resource.url + checksum new_resource.checksum if new_resource.checksum + action :create + notifies :run, "execute[unpack #{new_resource.release_file}]" + end + + # unpack based on file extension + execute "unpack #{new_resource.release_file}" do + command unpack_command + cwd new_resource.path + environment new_resource.environment + notifies :run, "execute[set owner on #{new_resource.path}]" + notifies :run, "execute[autogen #{new_resource.path}]" + notifies :run, "execute[configure #{new_resource.path}]" + action :nothing + end + + # set_owner + execute "set owner on #{new_resource.path}" do + command owner_command + action :nothing + end + + execute "autogen #{new_resource.path}" do + command './autogen.sh' + only_if { ::File.exist? "#{new_resource.path}/autogen.sh" } + cwd new_resource.path + environment new_resource.environment + action :nothing + ignore_failure true + end + + execute "configure #{new_resource.path}" do + command "./configure #{new_resource.autoconf_opts.join(' ')}" + only_if { ::File.exist? "#{new_resource.path}/configure" } + cwd new_resource.path + environment new_resource.environment + action :nothing + end +end + +action_class do + include ::Ark::ProviderHelpers +end diff --git a/cookbooks/ark/templates/default/add_to_path.sh.erb b/cookbooks/ark/templates/default/add_to_path.sh.erb new file mode 100644 index 0000000..ffc4e31 --- /dev/null +++ b/cookbooks/ark/templates/default/add_to_path.sh.erb @@ -0,0 +1 @@ +export PATH=<%= @directory -%>:$PATH diff --git a/cookbooks/build-essential/CHANGELOG.md b/cookbooks/build-essential/CHANGELOG.md new file mode 100644 index 0000000..95c1a29 --- /dev/null +++ b/cookbooks/build-essential/CHANGELOG.md @@ -0,0 +1,285 @@ +# build-essential Cookbook CHANGELOG + +This file is used to list changes made in each version of the build-essential cookbook. + +## 8.2.1 (2018-09-04) + +- Add a note that this cookbook is no longer maintained as the build_essential resource was moved directly into the chef-client making this cookbook no longer necessary. + +## 8.2.0 (2018-08-28) + +- Simplify the if installed logic for macos +- Remove support for FreeBSD < 10 which is VERY much EOL +- Avoid ChefSpec deprecation warnings +- Avoid deprecation warnings in Chef 14.3+ by not loading resources already in Chef + +## 8.1.1 (2018-03-17) + +- Make sure we install the last available xcode command line tool package so we get the latest version + +## 8.1.0 (2018-03-17) + +- Support Amazon Linux 2.0 +- Remove the ChefSpec matchers which are autogenerated now in recent ChefDK releaeses. If your specs fail because of this you need to update to a more recent ChefDK release. +- Swap Debian 7 testing for Amazon 2 & Ubuntu 18.04 testing since Debian 7 is EOL in May + +## 8.0.4 (2017-11-29) + +- Install gcc-c and gcc-c++ for solaris 11 +- Fix dokken's amazonlinux configuration +- Update chef dependency in metadata.rb to Chef 12.7 +- Clean up testing + +## 8.0.3 (2017-05-30) + +- Fix solaris metadata in metadata.rb +- Remove mac_os_x_server from metata as it's not a platform + +## 8.0.2 (2017-05-06) + +- Remove buggy action_class.class_eval usage + +## 8.0.1 (2017-04-14) + +- Test with local delivery and not Rake +- Ensure compatibility with Chef 12.5 +- Update apache2 license string +- Ensure compatibility with Amazon Linux on Chef 13 + +## 8.0.0 (2017-02-14) + +- Require 12.5 or later and remove compat_resource cookbook dependency + +## 7.0.3 (2016-12-22) + +- Require the latest compat_resource +- Cookstyle fixes + +## 7.0.2 (2016-11-07) + +- Fix softwareupdate issue from -v to --verbose + +## 7.0.1 (2016-10-06) + +- Install gcc 4.8 on SUSE < 12 + +## 7.0.0 (2016-09-30) + +- Remove support for OS X < 10.9 and add support for OS X 10.12 +- Refactor the xcode installer resource as a custom resource that does not require updates for each new OS X update +- Use a test recipe with apt_update to avoid needing apt + +## 6.0.6 (2016-09-19) + +- Remove chef 11 compatibility in the metadata +- Solaris 11 needs both make and gnu make + +## 6.0.5 (2016-09-07) + +- Testing updates +- Require the latest compat_resource + +## 6.0.4 (2016-08-19) + +- Install CLTools from dmg with -allowUntrusted on old OSX +- Switch to cookstyle for ruby linting +- Add OS X hosts to the kitchen config +- Remove chefdk included gems from the Gemfile +- Better handle kitchen failures in the Rakefile +- Perform all unit/linting in a single travis job + +## v6.0.3 (2016-07-26) + +- Fix how gcc version specified for Solaris 11 + +## v6.0.2 (2016-07-22) + +- Properly warn on Solaris 10 +- Specify the verson of gcc to install on Solaris 11 + +## v6.0.1 (2016-07-19) + +- Clarify that this cookbook actually required Chef 12.1 or later not 12.0 or later +- Add chef_version metadata + +## v6.0.0 (2016-06-03) + +This cookbook now uses the new msys2 based compiler toolchain on windows. Both 32-bit DW2 and 64-bit SEH based toolchains are available based on the gcc 5.3x series compiler. By default these are located in C:\msys2\mingw32 and C:\msys2\mingw64 + +## v5.0.0 (2016-06-03) + +The cookbook now ships with a 12.5+ style custom resource 'build_essential' which performs the same work that the existing default.rb recipe. The default.rb recipe has been converted to consume that resource to provide backwards compatibility for users that use build-essential::default in their run lists or cookbooks. In converting to this custom resource support for EOL omnios has been removed and warning messages for Solaris 10 users have been removed. See the readme for usage information on the new resource. + +## v4.0.0 (2016-05-12) + +### Breaking change + +This cookbook now requires Chef 12 or later as it includes the new mingw cookbook for installing Windows compilers. Mingw includes 12.5 style custom resources, which will fail to compile on Chef 11\. If you are not running Chef 12 you'll need to pin to 3.x in your environment. + +## v3.2.0 (2016-03-25) + +This version backs out a change in the 3.0 release which attempted to install the version of kernel-devel for the current running kernel on RHEL systems. This change had several unintended consequences and we believe the best solution is to back to change out until a better solution for the original problem is developed. Several of the issues could be resolved by code updates to build-essential, but not all, which complicates rolling forward vs. a roll back. The change caused issues which Chefspec runs on cookbooks where build-essential is a dependency as Fauxhai, used by Chefspec, does not mock out node['virtualization']. Fauxhai is being updated to mock out node['virtualization'], but we'd like to make sure a ChefDK release ships with this new Fauxhai before depending on that change. + +## v3.1.0 (2016-03-23) + +- Install GCC 4.8 if running on OmniOS >= 151008 + +## v3.0.0 (2016-03-23) + +- Install GCC 4.9 on FreeBSD < 10 +- Install the version of kernel-devel that matches the running Kernel on RHEL +- Remove suggests 'pkgutil' from the metadata as suggests does nothing +- Properly warn the user that build-essential does not support Solaris 10 instead of just silently continuing on +- Updated specs to run against more recent OS releases +- Removed the warning for OmniOS users from the Readme as the upstream issue has been resolved +- Switch from 7-zip to seven_zip cookbook as 7-zip has been deprecated +- Add 7-zip to the system path on Windows hosts so the recipe will work out of the box +- Switch from the deprecated 7-zip cookbook to seven_zip + +## v2.4.0 (2016-03-21) + +- Add gettext package to RHEL / FreeBSD to match other platforms +- Fix OS X version detection logic to properly detect OS X 10.10 and 10.11 + +## v2.3.1 (2016-02-18) + +- Restore Chef 11 compatibility and add Travis / Test Kitchen testing for Chef 11 + +## v2.3.0 (2016-02-17) + +- Add mingw/msys based build tools for Windows + +## v2.2.4 (2015-10-06) + +- Add patch package on Fedora systems +- Add additional platforms to Kitchen CI +- Use Chef standard Rubocop file and resolve several issues +- Update contributing and testing docs +- Update Gemfile with the latest testing and development deps +- Add maintainers.md and maintainers.toml files +- Add chefignore file to limit the files uploaded to the Chef server +- Add source_url and issues_url metadata for Supermarket + +## v2.2.3 (2015-04-15) + +- Don't install omnibus-build-essential on Solaris 10 - We decided it's easier to use the old GCC that ships with Solaris 10. +- Use ChefDK for all Travis testing. + +## v2.2.2 (2015-03-27) + +- Update Solar 10's omnibus-build-essential to 0.0.5 + +## v2.2.1 (2015-03-23) + +- Install GNU Patch on Solaris 11 + +## v2.2.0 (2015-03-18) + +- [solaris] Differentiate between Solaris 10 and 11 +- [solaris] Add ucb compat package +- [solaris] Solaris 10 build essential setup +- Fix metadata to use a string instead of a bool (see #56, #57) + +## v2.1.3 (2014-11-18) + +- Update metadata for supported versions of OS X (10.7+) as noted from +- v2.0.0 previously (#38) +- Clarify requirement to have apt package cache updated in README. (#41) +- Fix Xcode CLI installation on OS X (#50) + +## v2.1.2 (2014-10-14) + +- Mac OS X 10.10 Yosemite support + +## v2.1.0 (2014-10-14) + +- Use fully-qualified names when installing FreeBSD package + +## v2.0.6 (2014-08-11) + +- Use the resource form of `remote_file` to prevent context issues + +## v2.0.4 (2014-06-06) + +- [COOK-4661] added patch package to _rhel recipe + +## v2.0.2 (2014-05-02) + +- Updated documentation about older Chef versions +- Added new SVG badges to the README +- Fix a bug where `potentially_at_compile_time` fails on non-resources + +## v2.0.0 (2014-03-13) + +- Updated tested harnesses to use latest ecosystem tools +- Added support for FreeBSD +- Added support for installing XCode Command Line Tools on OSX (10.7, 10.8, 10.9) +- Created a DSL method for wrapping compile_time vs runtime execution +- Install additional developement tools on some platforms +- Add nicer log and warning messages with helpful information + +**Potentially Breaking Changes** + +- Dropped support for OSX 10.6 +- OSX no longer downloads OSX GCC and uses XCode CLI tools instead +- `build_essential` -> `build-essential` in node attributes +- `compiletime` -> `compile_time` in node attributes +- Cookbook version 2.x no longer supports Chef 10.x + +## v1.4.4 (2014-02-27) + +- [COOK-4245] Wrong package name used for developer tools on OS X 10.9 + +## v1.4.2 + +### Bug + +- **[COOK-3318](https://tickets.chef.io/browse/COOK-3318)** - Use Mixlib::ShellOut instead of Chef::ShellOut + +### New Feature + +- **[COOK-3093](https://tickets.chef.io/browse/COOK-3093)** - Add OmniOS support + +### Improvement + +- **[COOK-3024](https://tickets.chef.io/browse/COOK-3024)** - Use newer package on SmartOS + +## v1.4.0 + +This version splits up the default recipe into recipes included based on the node's platform_family. + +- [COOK-2505] - backport omnibus builder improvements + +## v1.3.4 + +- [COOK-2272] - Complete `platform_family` conversion in build-essential + +## v1.3.2 + +- [COOK-2069] - build-essential will install osx-gcc-installer when XCode is present + +## v1.3.0 + +- [COOK-1895] - support smartos + +## v1.2.0 + +- Add test-kitchen support (source repo only) +- [COOK-1677] - build-essential cookbook support for OpenSuse and SLES +- [COOK-1718] - build-essential cookbook metadata should include scientific +- [COOK-1768] - The apt-get update in build-essentials needs to be renamed + +## v1.1.2 + +- [COOK-1620] - support OS X 10.8 + +## v1.1.0 + +- [COOK-1098] - support amazon linux +- [COOK-1149] - support Mac OS X +- [COOK-1296] - allow for compile-time installation of packages through an attribute (see README) + +## v1.0.2 + +- [COOK-1098] - Add Amazon Linux platform support +- [COOK-1149] - Add OS X platform support diff --git a/cookbooks/build-essential/CONTRIBUTING.md b/cookbooks/build-essential/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/build-essential/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/cookbooks/build-essential/README.md b/cookbooks/build-essential/README.md new file mode 100644 index 0000000..10037ef --- /dev/null +++ b/cookbooks/build-essential/README.md @@ -0,0 +1,138 @@ +# build-essential Cookbook + +[![Cookbook Version](http://img.shields.io/cookbook/v/build-essential.svg)][cookbook] [![Build Status](https://travis-ci.org/chef-cookbooks/build-essential.svg?branch=master)](https://travis-ci.org/chef-cookbooks/build-essential) + +Installs packages required for compiling C software from source. Use this cookbook if you wish to compile C programs, or install RubyGems with native extensions. Contains a resource, 'build_essential', as as well as a default recipe that simply calls that same resource. + +Note: The functionality of this cookbook is now built into Chef 14+ in the [build_essential resource](https://docs.chef.io/resource_build_essential.html). This cookbook is no longer being maintained and all future changes will be done directly in the chef-client. We highly recommend you update your chef-client to the latest release and if possible migrate to using the build_essential resources instead of the recipe in this cookbook. + +## Requirements + +### Platforms + +- Debian/Ubuntu +- RHEL/CentOS/Scientific/Amazon/Oracle +- openSUSE / SUSE Enterprise Linux +- SmartOS +- Fedora +- Mac OS X 10.9+ +- FreeBSD + +### Chef + +- Chef 12.7+ + +### Cookbooks + +- seven_zip +- mingw + +**Note for Debian platform family:** On Debian platform-family systems, it is recommended that `apt-get update` be run, to ensure that the package cache is updated. It's not in the scope of this cookbook to do that, as it can [create a duplicate resource](https://tickets.chef.io/browse/CHEF-3694). We recommend using the [apt](https://supermarket.chef.io/cookbooks/apt) cookbook to do this. + +## Attributes + +Attribute | Default | Description +------------------------------------------ | :---------------------------: | ----------------------------------------------------- +`node['build-essential']['compile_time']` | `false` | Execute resources at compile time +`node['build-essential']['msys2']['path']` | `#{ENV['SYSTEMDRIVE']\\msys2` | Destination for msys2 build tool chain (Windows only) + +## Usage + +### Recipe Usage + +The recipe simply calls the build_essential resource, but it ideal for adding to roles or node run lists. + +Include the build-essential recipe in your run list: + +```sh +knife node run_list add NODE "recipe[build-essential::default]" +``` + +or add the build-essential recipe as a dependency and include it from inside another cookbook: + +```ruby +include_recipe 'build-essential::default' +``` + +### Gems with C extensions + +For RubyGems that include native C extensions you wish to use with Chef, you should do the following. + +- Set the `compile_time` attribute to true in your wrapper cookbook or role: + + ```ruby + # Wrapper attribute + default['build-essential']['compile_time'] = true + ``` + + ```ruby + # Role + default_attributes( + 'build-essential' => { + 'compile_time' => true + } + ) + ``` + +- Ensure that the C libraries, which include files and other assorted "dev" + + type packages, are installed in the compile phase after the build-essential + + recipe is executed. For example: + + ```ruby + include_recipe 'build-essential::default' + + package('mypackage-devel') { action :nothing }.run_action(:install) + ``` + +- Use the `chef_gem` resource in your recipe to install the gem with the native + + extension: + + ```ruby + chef_gem 'gem-with-native-extension' + ``` + +### Resource Usage + +The cookbook includes a resource 'build_essential' that can be included in your cookbook to install the necessary build-essential packages + +Simple package installation during the client run: + +```ruby +build_essential 'some name you choose' +``` + +Package installation during the compile phase: + +```ruby +build_essential 'some name you choose' do + compile_time false +end +``` + +## Maintainers + +This cookbook is maintained by Chef's Community Cookbook Engineering team. Our goal is to improve cookbook quality and to aid the community in contributing to cookbooks. To learn more about our team, process, and design goals see our [team documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/COOKBOOK_TEAM.MD). To learn more about contributing to cookbooks like this see our [contributing documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD), or if you have general questions about this cookbook come chat with us in #cookbok-engineering on the [Chef Community Slack](http://community-slack.chef.io/) + +## License + +**Copyright:** 2009-2016, Chef Software, Inc. + +``` +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` + +[cookbook]: https://supermarket.chef.io/cookbooks/build-essential +[travis]: http://travis-ci.org/chef-cookbooks/build-essential diff --git a/cookbooks/build-essential/attributes/default.rb b/cookbooks/build-essential/attributes/default.rb new file mode 100644 index 0000000..e2bf233 --- /dev/null +++ b/cookbooks/build-essential/attributes/default.rb @@ -0,0 +1,21 @@ +# +# Cookbook:: build-essential +# Attributes:: default +# +# Copyright:: 2008-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +default['build-essential']['compile_time'] = false +default['build-essential']['msys2']['path'] = "#{ENV['SYSTEMDRIVE']}\\msys2" diff --git a/cookbooks/build-essential/metadata.json b/cookbooks/build-essential/metadata.json new file mode 100644 index 0000000..ea34df1 --- /dev/null +++ b/cookbooks/build-essential/metadata.json @@ -0,0 +1 @@ +{"name":"build-essential","version":"8.2.1","description":"Installs C compiler / build tools","long_description":"# build-essential Cookbook\n\n[![Cookbook Version](http://img.shields.io/cookbook/v/build-essential.svg)][cookbook] [![Build Status](https://travis-ci.org/chef-cookbooks/build-essential.svg?branch=master)](https://travis-ci.org/chef-cookbooks/build-essential)\n\nInstalls packages required for compiling C software from source. Use this cookbook if you wish to compile C programs, or install RubyGems with native extensions. Contains a resource, 'build_essential', as as well as a default recipe that simply calls that same resource.\n\nNote: The functionality of this cookbook is now built into Chef 14+ in the [build_essential resource](https://docs.chef.io/resource_build_essential.html). This cookbook is no longer being maintained and all future changes will be done directly in the chef-client. We highly recommend you update your chef-client to the latest release and if possible migrate to using the build_essential resources instead of the recipe in this cookbook.\n\n## Requirements\n\n### Platforms\n\n- Debian/Ubuntu\n- RHEL/CentOS/Scientific/Amazon/Oracle\n- openSUSE / SUSE Enterprise Linux\n- SmartOS\n- Fedora\n- Mac OS X 10.9+\n- FreeBSD\n\n### Chef\n\n- Chef 12.7+\n\n### Cookbooks\n\n- seven_zip\n- mingw\n\n**Note for Debian platform family:** On Debian platform-family systems, it is recommended that `apt-get update` be run, to ensure that the package cache is updated. It's not in the scope of this cookbook to do that, as it can [create a duplicate resource](https://tickets.chef.io/browse/CHEF-3694). We recommend using the [apt](https://supermarket.chef.io/cookbooks/apt) cookbook to do this.\n\n## Attributes\n\nAttribute | Default | Description\n------------------------------------------ | :---------------------------: | -----------------------------------------------------\n`node['build-essential']['compile_time']` | `false` | Execute resources at compile time\n`node['build-essential']['msys2']['path']` | `#{ENV['SYSTEMDRIVE']\\\\msys2` | Destination for msys2 build tool chain (Windows only)\n\n## Usage\n\n### Recipe Usage\n\nThe recipe simply calls the build_essential resource, but it ideal for adding to roles or node run lists.\n\nInclude the build-essential recipe in your run list:\n\n```sh\nknife node run_list add NODE \"recipe[build-essential::default]\"\n```\n\nor add the build-essential recipe as a dependency and include it from inside another cookbook:\n\n```ruby\ninclude_recipe 'build-essential::default'\n```\n\n### Gems with C extensions\n\nFor RubyGems that include native C extensions you wish to use with Chef, you should do the following.\n\n- Set the `compile_time` attribute to true in your wrapper cookbook or role:\n\n ```ruby\n # Wrapper attribute\n default['build-essential']['compile_time'] = true\n ```\n\n ```ruby\n # Role\n default_attributes(\n 'build-essential' => {\n 'compile_time' => true\n }\n )\n ```\n\n- Ensure that the C libraries, which include files and other assorted \"dev\"\n\n type packages, are installed in the compile phase after the build-essential\n\n recipe is executed. For example:\n\n ```ruby\n include_recipe 'build-essential::default'\n\n package('mypackage-devel') { action :nothing }.run_action(:install)\n ```\n\n- Use the `chef_gem` resource in your recipe to install the gem with the native\n\n extension:\n\n ```ruby\n chef_gem 'gem-with-native-extension'\n ```\n\n### Resource Usage\n\nThe cookbook includes a resource 'build_essential' that can be included in your cookbook to install the necessary build-essential packages\n\nSimple package installation during the client run:\n\n```ruby\nbuild_essential 'some name you choose'\n```\n\nPackage installation during the compile phase:\n\n```ruby\nbuild_essential 'some name you choose' do\n compile_time false\nend\n```\n\n## Maintainers\n\nThis cookbook is maintained by Chef's Community Cookbook Engineering team. Our goal is to improve cookbook quality and to aid the community in contributing to cookbooks. To learn more about our team, process, and design goals see our [team documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/COOKBOOK_TEAM.MD). To learn more about contributing to cookbooks like this see our [contributing documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD), or if you have general questions about this cookbook come chat with us in #cookbok-engineering on the [Chef Community Slack](http://community-slack.chef.io/)\n\n## License\n\n**Copyright:** 2009-2016, Chef Software, Inc.\n\n```\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n\n[cookbook]: https://supermarket.chef.io/cookbooks/build-essential\n[travis]: http://travis-ci.org/chef-cookbooks/build-essential\n","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"amazon":">= 0.0.0","centos":">= 0.0.0","debian":">= 0.0.0","fedora":">= 0.0.0","freebsd":">= 0.0.0","mac_os_x":">= 10.9.0","opensuse":">= 0.0.0","opensuseleap":">= 0.0.0","oracle":">= 0.0.0","redhat":">= 0.0.0","scientific":">= 0.0.0","smartos":">= 0.0.0","solaris2":">= 0.0.0","suse":">= 0.0.0","ubuntu":">= 0.0.0","windows":">= 0.0.0","zlinux":">= 0.0.0"},"dependencies":{"seven_zip":">= 0.0.0","mingw":">= 1.1"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{"build-essential":"Installs packages required for compiling C software from source."},"source_url":"https://github.com/chef-cookbooks/build-essential","issues_url":"https://github.com/chef-cookbooks/build-essential/issues","chef_version":[[">= 12.7"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/build-essential/recipes/_windows.rb b/cookbooks/build-essential/recipes/_windows.rb new file mode 100644 index 0000000..6d317f9 --- /dev/null +++ b/cookbooks/build-essential/recipes/_windows.rb @@ -0,0 +1,53 @@ +# +# Cookbook:: build-essential +# Recipe:: _windows +# +# Copyright:: 2016-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +node.default['seven_zip']['syspath'] = true +include_recipe 'seven_zip::default' + +tool_path = node['build-essential']['msys2']['path'] + +directory tool_path do + action :create + recursive true +end + +[ + 'base-devel', # Brings down msys based bash/make/awk/patch/stuff.. + 'mingw-w64-x86_64-toolchain', # Puts 64-bit SEH mingw toolchain in msys2\mingw64 + 'mingw-w64-i686-toolchain' # Puts 32-bit DW2 mingw toolchain in msys2\ming32 +].each do |package| + msys2_package package do + root tool_path + end +end + +# Certain build steps assume that a tar command is available on the +# system path. The default tar present in msys2\usr\bin is an msys GNU tar +# that expects forward slashes and consider ':' to be a remote tape separator +# or something weird like that. We therefore drop bat file in msys2\bin that +# redirect to the underlying executables without mucking around with +# msys2's /usr/bin itself. +{ + 'bsdtar.exe' => 'tar.bat', + 'patch.exe' => 'patch.bat', +}.each do |reference, link| + file "#{tool_path}\\bin\\#{link}" do + content "@%~dp0..\\usr\\bin\\#{reference} %*" + end +end diff --git a/cookbooks/build-essential/recipes/default.rb b/cookbooks/build-essential/recipes/default.rb new file mode 100644 index 0000000..a5dfed3 --- /dev/null +++ b/cookbooks/build-essential/recipes/default.rb @@ -0,0 +1,24 @@ +# +# Cookbook:: build-essential +# Recipe:: default +# +# Copyright:: 2008-2018, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Call the build-essential custom resource +# This can also be called directly in your cookbooks anywhere you want +build_essential 'install_packages' do + compile_time node['build-essential']['compile_time'] +end diff --git a/cookbooks/build-essential/resources/build_essential.rb b/cookbooks/build-essential/resources/build_essential.rb new file mode 100644 index 0000000..21898a4 --- /dev/null +++ b/cookbooks/build-essential/resources/build_essential.rb @@ -0,0 +1,107 @@ +# +# Cookbook:: build-essential +# resource:: build_essential +# +# Copyright:: 2008-2018, Chef Software Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +chef_version_for_provides '< 14.0' if respond_to?(:chef_version_for_provides) +provides :build_essential +resource_name :build_essential + +property :compile_time, [true, false], default: false + +action :install do + case node['platform_family'] + when 'debian' + package %w( autoconf binutils-doc bison build-essential flex gettext ncurses-dev ) + when 'amazon', 'fedora', 'rhel' + package %w( autoconf bison flex gcc gcc-c++ gettext kernel-devel make m4 ncurses-devel patch ) + + # Ensure GCC 4 is available on older pre-6 EL + package %w( gcc44 gcc44-c++ ) if !platform?('amazon') && node['platform_version'].to_i < 6 + when 'freebsd' + package 'devel/gmake' + package 'devel/autoconf' + package 'devel/m4' + package 'devel/gettext' + when 'mac_os_x' + xcode_command_line_tools 'install' + when 'omnios' + package 'developer/gcc48' + package 'developer/object-file' + package 'developer/linker' + package 'developer/library/lint' + package 'developer/build/gnu-make' + package 'system/header' + package 'system/library/math/header-math' + + # Per OmniOS documentation, the gcc bin dir isn't in the default + # $PATH, so add it to the running process environment + # http://omnios.omniti.com/wiki.php/DevEnv + ENV['PATH'] = "#{ENV['PATH']}:/opt/gcc-4.7.2/bin" + when 'solaris2' + if node['platform_version'].to_f == 5.10 + Chef::Log.warn('build-essential does not support Solaris 10. You will need to install SUNWbison, SUNWgcc, SUNWggrp, SUNWgmake, and SUNWgtar from the Solaris DVD') + elsif node['platform_version'].to_f == 5.11 + package 'autoconf' + package 'automake' + package 'bison' + package 'gnu-coreutils' + package 'flex' + # lock gcc versions because we don't use 5 yet + %w(gcc gcc-c gcc-c++).each do |pkg| + package pkg do # ~FC009 + accept_license true + version '4.8.2' + end + end + package 'gnu-grep' + package 'gnu-make' + package 'gnu-patch' + package 'gnu-tar' + package 'make' + package 'pkg-config' + package 'ucb' + end + when 'smartos' + package 'autoconf' + package 'binutils' + package 'build-essential' + package 'gcc47' + package 'gmake' + package 'pkg-config' + when 'suse' + package %w( autoconf bison flex gcc gcc-c++ kernel-default-devel make m4 ) + package %w( gcc48 gcc48-c++ ) if node['platform_version'].to_i < 12 + when 'windows' + include_recipe 'build-essential::_windows' + else + Chef::Log.warn <<-EOH + A build-essential recipe does not exist for '#{node['platform_family']}'. This + means the build-essential cookbook does not have support for the + #{node['platform_family']} family. If you are not compiling gems with native + extensions or building packages from source, this will likely not affect you. + EOH + end +end + +# this resource forces itself to run at compile_time +def after_created + return unless compile_time + Array(action).each do |action| + run_action(action) + end +end diff --git a/cookbooks/build-essential/resources/xcode_command_line_tools.rb b/cookbooks/build-essential/resources/xcode_command_line_tools.rb new file mode 100644 index 0000000..44dbfae --- /dev/null +++ b/cookbooks/build-essential/resources/xcode_command_line_tools.rb @@ -0,0 +1,57 @@ +# +# Cookbook:: build-essential +# Resource:: xcode_command_line_tools +# +# Copyright:: 2014-2018, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +resource_name :xcode_command_line_tools + +action :install do + if installed? + Chef::Log.debug("#{new_resource} already installed - skipping") + else + converge_by("Install #{new_resource}") do + # This script was graciously borrowed and modified from Tim Sutton's + # osx-vm-templates at https://github.com/timsutton/osx-vm-templates/blob/b001475df54a9808d3d56d06e71b8fa3001fff42/scripts/xcode-cli-tools.sh + execute 'install XCode Command Line tools' do + command <<-EOH.gsub(/^ {14}/, '') + # create the placeholder file that's checked by CLI updates' .dist code + # in Apple's SUS catalog + touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress + # find the CLI Tools update + PROD=$(softwareupdate -l | grep "\*.*Command Line" | tail -n 1 | awk -F"*" '{print $2}' | sed -e 's/^ *//' | tr -d '\n') + # install it + softwareupdate -i "$PROD" --verbose + # Remove the placeholder to prevent perpetual appearance in the update utility + rm -f /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress + EOH + end + end + end +end + +action_class do + # + # Determine if the XCode Command Line Tools are installed + # + # @return [true, false] + # + def installed? + cmd = Mixlib::ShellOut.new('pkgutil --pkgs=com.apple.pkg.CLTools_Executables') + cmd.run_command + cmd.error? ? false : true + end +end diff --git a/cookbooks/chef-sugar/CHANGELOG.md b/cookbooks/chef-sugar/CHANGELOG.md new file mode 100644 index 0000000..1925309 --- /dev/null +++ b/cookbooks/chef-sugar/CHANGELOG.md @@ -0,0 +1,189 @@ +Chef Sugar Changelog +========================= +This file is used to list changes made in each version of the chef-sugar cookbook and gem. + +v3.3.0 (2016-01-11) +------------------- +### Improvements +- Break up `Chef::Sugar::Constraints` into a class and a dsl file +- Add `platform_version` method with full constraints comparison support + +v3.2.0 (2015-12-10) +------------------- +### Improvements +- Add platform matchers for `debian` and `fedora` +- Add `openvz` support under virtualization +- Add init system detection support +- Add support for `nexus`, `ios_xr` platforms and `wrlinux` platform_family +- Add additional `aix` helpers + +### Bug Fixes +- Properly expose `Architecture#i386?` in the DSL + +v3.1.1 (2015-06-23) +------------------- +### Improvements +- Update Intel CPU types based on existing Fauxhai data +- Update SPARC logic and 32/64-bit logic for x86 and i386 + +### Bug Fixes +- Fix 32-bit logic +- Fix default behavior to include chef-sugar at compile time +- Fix Chef 12.1.0 warnings for chef_gem compile time install +- Fix `redhat_enterprise_linux?` matcher + +v3.0.2 (2015-03-26) +------------------- +### Improvements +- Add helpers for `ppc64` and `ppc64le` architecture + +### Bug Fixes +- Adjustments to error message + +v3.0.1 (2015-03-20) +------------------- +### Breaking Changes +- Rename `compile_time` `to at_compile_time` - if your recipes are affected by + this breaking change, your Chef Client run will produce a verbose error + message with details on how to fix the error. + +v3.0.0 (2015-03-17) +------------------- +### Breaking Changes +- Drop support for Ruby 1.9 (it might still work, but it is no longer officially supported) + +### Improvements +- Remove accidentially committed gem source +- Bump development dependencies +- Add `digitalocean?` matcher +- Expose the `rhel` platform as `el` +- Add `ppc64le` platform +- Add helper for determining if architecture is SPARC +- Add helper for determining if architecture is Intel +- Add dynamic platform/version matchers for Solaris + +### Bug Fixes +- Reset namespace_options when reaching top-level resources + +v2.5.0 (2015-01-05) +------------------- +### Improvements +- Add `data_bag_item_for_environment` function +- Add `kvm?` matcher +- Add `virtualbox?` matcher + +### Bug Fixes +- Use `.key?` to check for hash key presence, raising an `AttributeDoesNotExist` + error sooner + +v2.4.1 (2014-10-12) +------------------- +- No changes from v2.4.0 - forced a new version upload to the Chef Supermarket + +v2.4.0 (2014-10-12) +------------------- +### Improvements +- Add `docker?` matcher + +v2.3.2 (2014-10-07) +------------------- +### Big Fixues +- Include `amd64` in `_64_bit?` check + +v2.3.1 (2014-10-07) +------------------- +### Improvements +- Check all 64-bit architectures that may be reported by Ohai + +### Bug Fixes +- Be more tolerant of `nil` values return from sub functions +- Check to make sure `node['domain']` is not `nil` before calling `#include?` + +v2.3.0 (2014-09-24) +------------------- +### Improvements +- Add `vmware?` matcher +- Allow the attribute DSL to access parent attributes + +### Bug Fixes +- Return `true` or `false` from all Boolean methods (instead of `nil` or truthy values) + +v2.2.0 (2014-08-20) +------------------- +### Improvements +- Add `smartos?` matcher +- Add `omnios?` matcher + +v2.1.0 (2014-06-26) +------------------- +### Improvements +- Add `solaris2?` matcher +- Add `aix?` matcher +- Add 'lxc?' matcher + +### Bug Fixes +- Fix a bug in namespace memoization during attribute initialization + +v2.0.0 (2014-06-16) +------------------- +### Breaking +- Remove `not_linux?` method +- Remove `not_windows?` method + +### Improvements +- Miscellaneous spelling fixes +- Update a failing unit test for `installed?` +- Add Mac OS X to the list of platforms (Yosemite) +- Upgrade to RSpec 3 +- Fix `which` (and `installed?` and `installed_at_version?`) when given an absolute path +- Fix `linux?` check to only return true on real linuxes + +v1.3.0 (2014-05-05) +------------------- +- Check both `$stdout` and `$stderr` in `version_for` +- Add additional platform versions +- Make `includes_recipe?` a top-level API (instead of just Node) +- Match on the highest version number instead of direct equality checking on platform versions +- Define `Object#blank?` as a core extension +- Define `String#flush` as a core extension +- Remove Stove + +v1.2.6 (2014-03-16) +------------------- +- Fix a bug in `vagrant?` returning false on newer Vagrant versions +- Remove Coveralls + +v1.2.4 (2014-03-13) +------------------- +- See (1.2.2), but I botched the release + +v1.2.2 (2014-03-13) +------------------- +- Fix a critical bug with `encrypted_data_bag_item` using the wrong key + +v1.2.0 (2014-03-09) +------------------- +- Add `namespace` functionality for specifying attributes in a DSL +- Add constraints helpers for comparing version strings +- Add `require_chef_gem` to safely require and degrade if a gem is not installed +- Add `deep_fetch` and `deep_fetch!` to fetch deeply nested keys +- Accept an optional secret key in `encrypted_data_bag_item` helper and raise a helpful error if one is not set (NOTE: this changes the airity of the method, but it's backward-compatible because Ruby is magic) +- Add Stove for releasing +- Updated copyrights for 2014 + +v1.1.0 (2013-12-10) +------------------- +- Add `cloudstack?` helper +- Add data bag helpers +- Remove foodcritic checks +- Upgrade development gem versions +- Randomize spec order + +v1.0.1 (2013-10-15) +------------------- +- Add development recipe +- Add `compile_time`, `before`, and `after` filters + +v1.0.0 (2013-10-15) +------------------- +- First public release diff --git a/cookbooks/chef-sugar/CONTRIBUTING.md b/cookbooks/chef-sugar/CONTRIBUTING.md new file mode 100644 index 0000000..fffb47e --- /dev/null +++ b/cookbooks/chef-sugar/CONTRIBUTING.md @@ -0,0 +1,20 @@ +Contributing to Chef Sugar +=============================== +The process for contributing to Chef sugar is rather straight-forward. It is unlikely that you'll need to modify the actual Chef recipe, so it's assumed that you want to work on the Gem itself. + +1. Fork the repository on GitHub. +2. Clone your fork. +3. Create a new, semantically-named branch: + + $ git checkout -b my_feature_branch + +4. Make any changes, ensuring you write adequate test coverage. +5. Document your changes (YARD). +6. Run the tests (make sure they pass). +7. Submit a Pull Request on GitHub. +8. (optional) Ping me on Twitter (@sethvargo) + +Additionally, please **DO NOT**: +- Modify the version of the cookbook or gem. +- Update the CHANGELOG +- Make unnecessary changes to the gemspec diff --git a/cookbooks/chef-sugar/README.md b/cookbooks/chef-sugar/README.md new file mode 100644 index 0000000..fd9785a --- /dev/null +++ b/cookbooks/chef-sugar/README.md @@ -0,0 +1,495 @@ +Chef Sugar +========== +[![Gem Version](http://img.shields.io/gem/v/chef-sugar.svg?style=flat-square)][gem] +[![Build Status](http://img.shields.io/travis/sethvargo/chef-sugar.svg?style=flat-square)][travis] + +[gem]: https://rubygems.org/gems/chef-sugar +[travis]: http://travis-ci.org/sethvargo/chef-sugar + +Chef Sugar is a Gem & Chef Recipe that includes series of helpful sugar of the Chef core and other resources to make a cleaner, more lean recipe DSL, enforce DRY principles, and make writing Chef recipes an awesome experience! + + +Installation +------------ +If you want to develop/hack on chef-sugar, please see the Contributing.md. + +If you are using Berkshelf, add `chef-sugar` to your `Berksfile`: + +```ruby +cookbook 'chef-sugar' +``` + +Otherwise, you can use `knife` or download the tarball directly from the community site: + +```ruby +knife cookbook site install chef-sugar +``` + + +Usage +----- +In order to use Chef Sugar in your Chef Recipes, you'll first need to include it: + +```ruby +include_recipe 'chef-sugar::default' +``` + +Alternatively you can put it in a base role or recipe and it will be included subsequently. + +Requiring the Chef Sugar Gem will automatically extend the Recipe DSL, `Chef::Resource`, and `Chef::Provider` with helpful convenience methods. + +### Module Method +If you are working outside of the Recipe DSL, you can use the module methods instead of the Recipe DSL. In general, the module methods have the same name as their Recipe-DSL counterparts, but require the node object as a parameter. For example: + +In a Recipe: + +```ruby +# cookbook/recipes/default.rb +do_something if windows? +``` + +In a Library as a singleton: + +```ruby +# cookbook/libraries/default.rb +def only_on_windows(&block) + yield if Chef::Sugar::PlatformFamily.windows?(@node) +end +``` + +In a Library as a Mixin: + +```ruby +# cookbook/libraries/default.rb +include Chef::Sugar::PlatformFamily + +def only_on_windows(&block) + yield if windows?(@node) +end +``` + + +API +--- +**Note:** For the most extensive API documentation, please see the YARD documentation. + +### Architecture +**Note:** Some of the architecture commands begin with an underscore (`_`) because Ruby does not permit methods to start with a numeric. + +- `_64_bit?` +- `_32_bit?` +- `intel?` +- `sparc?` +- `ppc64?` +- `ppc64le?` +- `powerpc?` + +#### Examples +```ruby +execute 'build[my binary]' do + command '...' + not_if { _64_bit? } +end +``` + +### Cloud +- `azure?` +- `cloud?` +- `digitalocean?` +- `ec2?` +- `eucalyptus?` +- `gce?` +- `linode?` +- `openstack?` +- `cloudstack?` +- `rackspace?` + +#### Examples +```ruby +template '/tmp/config' do + variables( + # See also: best_ip_for + ipaddress: cloud? ? node['local_ipv4'] : node['public_ipv4'] + ) +end +``` + +### Core Extensions +**Note:** Core extensions are **not** included by default. You must require the `chef/sugar/core_extensions` module manually to gain access to these APIs: + +```ruby +require 'chef/sugar/core_extensions' +``` + +- `String#satisfies?` +- `String#satisfied_by?` +- `Array#satisfied_by?` +- `Object#blank?` + +#### Examples +```ruby +# Checking version constraints +'1.0.0'.satisfies?('~> 1.0') #=> true +'~> 1.0'.satisfied_by?('1.0') #=> true +``` + +```ruby +# Check for an object's presence +''.blank? #=> true +['hello'].blank? #=> false +``` + +### Data Bag +- `encrypted_data_bag_item` - a handy DSL method for loading encrypted data bag items the same way you load a regular data bag item; this requires `Chef::Config[:encrypted_data_bag_secret]` is set! +- `encrypted_data_bag_item_for_environment` - find the encrypted data bag entry for the current node's Chef environment. +- `data_bag_item_for_environment` - find the data bag entry for the current node's Chef environment. + +#### Examples +```ruby +encrypted_data_bag_item('accounts', 'hipchat') +``` + +```ruby +encrypted_data_bag_item_for_environment('accounts', 'github') +``` + +```ruby +data_bag_item_for_environment('accounts', 'github') +``` + +### Docker +Chef Sugar looks for hints to see if the node being converged is a Docker container. When [Ohai supports checking other nodes](https://github.com/opscode/ohai/pull/428), Chef Sugar will automatically pick up the information. + +- `docker?` + +#### Examples +```ruby +template '/runme' do + only_if { docker?(node) } +end +``` + +### Attributes +Chef Sugar adds more Chef-like DSL to attribute definitions. Instead of using the Ruby hash syntax, you can define attributes using nested namespaces. This DSL may be more friendly to non-Ruby developers. It can safely be mixed-and-matched with the standard syntax. + +```ruby +# This is functionally the same as default['apache2']['config']['root'] = '/var/www' +namespace 'apache2' do + namespace 'config' do + root '/var/www' + end +end +``` + +```ruby +# Specify multiple keys instead of nesting namespaces +namespace 'apache2', 'config' do + root '/var/www' +end +``` + +```ruby +# Specify different nested precedence levels +namespace 'apache2', precedence: normal do + namespace 'config', precedence: override do + root '/var/www' #=> override['apache2']['config']['root'] = '/var/www' + end +end +``` + +### Constraints +- `constraints` - create a new constraint (or requirement) that can be used to test version validations. +- `chef_version` - (DSL only) a wrapper for `version(Chef::VERSION)` +- `version` - create a new version that can be used to test constraint validation. + +#### Examples +```ruby +# Check if a version is satisfied by a constraint +version('1.2.3').satisfies?('~> 1.2.0') +``` + +```ruby +# Check if a constraint is satisfied by a version +constraint('~> 1.2.0').satisfied_by?('1.2.3') +``` + +```ruby +# Support multiple constraints +version('1.2.3').satisfies?('> 1.2', '< 2.0') +constraint('> 1.2', '< 2.0').satisfied_by?('1.2.3') +``` + +```ruby +# Only perform an operation if Chef is at a certain version +package 'apache2' do + not_if { chef_version.satisfies?('~> 11.0') } # Ignore Chef 11 +end +``` + +### Kernel +- `require_chef_gem` - "safely" require a gem. Loading a gem with Chef is sometimes difficult and confusing. The errors that Chef produces are also sometimes not very intuitive. In the event you require a gem to exist on the system, you can use `require_chef_gem`, which will attempt to require the gem and then produce helpful output if the gem is not installed: + + Chef could not load the gem `#{name}'! You may need to install the gem + manually with `gem install #{name}', or include a recipe before you can + use this resource. Please consult the documentation for this cookbook + for proper usage. + +#### Examples +```ruby +# LWRP +require_chef_gem 'pry' +``` + +```ruby +class Chef + class Provider + class MyProvider > Provider + require_chef_gem 'pry' + end + end +end +``` + +### Init +- `systemd?` - detect if init system is systemd +- `upstart?` - detect if init system is upstart +- `runit?` - detect if init system is runit + +#### Examples +```ruby +systemd_service 'my-service' do + description 'My Service' + install do + wanted_by 'multi-user.target' + end + service do + exec_start '/usr/bin/myserviced' + end + action [:create, :enable, :start] + only_if { systemd? } +end + +cookbook_file '/etc/init/my-service.conf' do + source 'my-service.conf' + only_if { upstart? } +end +``` + +### IP +- `best_ip_for` - determine the best IP address for the given "other" node, preferring local IP addresses over public ones. + +#### Examples +```ruby +redis = search('node', 'role:redis').first + +template '/tmp/config' do + variables( + ipaddress: best_ip_for(redis) + ) +end +``` + +### Node + +Additional methods for the `node` object + +- `deep_fetch` - safely fetch a nested attribute. +- `deep_fetch!` - fetch a nested attribute, raising a more semantic error if the key does not exist. +- `in?` - determine if the node is in the given Chef environment. + +#### Examples +```ruby +credentials = if node.in?('production') + Chef::EncryptedDataBag.new('...') + else + data_bag('...') + end +``` + +```ruby +node.deep_fetch('apache2', 'config', 'root') => node['apache2']['config']['root'] +``` + +### Platform +- `amazon_linux?` +- `centos?` +- `linux_mint?` +- `oracle_linux?` +- `redhat_enterprise_linux?` +- `scientific_linux?` +- `ubuntu?` +- `solaris2?` +- `aix?` +- `smartos?` +- `omnios?` +- `raspbian?` +- `nexus?` +- `ios_xr?` + +There are also a series of dynamically defined matchers that map named operating system release versions and comparison operators in the form "#{platform}\_#{operator}\_#{name}?". For example: + +- `debian_after_squeeze?` +- `linuxmint_after_or_at_olivia?` +- `mac_os_x_lion?` +- `ubuntu_before_lucid?` +- `ubuntu_before_or_at_maverick?` +- `solaris_10?` +- `solaris_11?` + +To get a full list, run the following in IRB: + +```ruby +require 'chef/sugar' +puts Chef::Sugar::Platform.instance_methods +``` + +#### Examples +```ruby +if ubuntu? + execute 'apt-get update' +end +``` + +### Platform Family +- `arch_linux?` +- `debian?` +- `fedora?` +- `freebsd?` +- `gentoo?` +- `linux?` +- `mac_os_x?` +- `openbsd?` +- `rhel?` +- `slackware?` +- `suse?` +- `windows?` +- `wrlinux?` + +#### Examples +```ruby +node['attribute'] = if windows? + 'C:\Foo\BarDrive' + else + '/foo/bar_drive' + end +``` + +### Ruby +**Note:** The applies to the Ruby found at `node['languages']['ruby']`. + +- `ruby_20?` +- `ruby_19?` + +#### Examples +```ruby +log 'This has been known to fail on Ruby 2.0' if ruby_20? +``` + +### Run Context +- `includes_recipe?` - determines if the current run context includes the recipe + +```ruby +if includes_recipe?('apache2::default') + apache_module 'my_module' do + # ... + end +end +``` + +### Shell +- `which` +- `dev_null` +- `installed?` +- `installed_at_version?` +- `version_for` + +#### Examples +```ruby +log "Using `mongo` at `#{which('mongo')}`" + +if installed?('apt') + execute 'apt-get update' +end + +execute 'install[thing]' do + command "... 2>&1 #{dev_null}" + not_if { installed_at_version?('thing', node['thing']['version']) } +end + +log "Skipping git install, version is at #{version_for('mongo', '-v')}" +``` + +### Vagrant +- `vagrant?` + +#### Examples +```ruby +http_request 'http://...' do + not_if { vagrant? } +end +``` + +### Virtualization +- `kvm?` +- `lxc?` +- `virtualbox?` +- `vmware?` +- `openvz?` + +#### Examples +```ruby +service 'ntpd' do + action [:enable, :start] + not_if { lxc? } +end +``` + +### Filters +- `at_compile_time` - accepts a block of resources to run at compile time +- `before` - insert resource in the collection before the given resource +- `after` - insert resource in the collection after the given resource + +#### Examples +```ruby +at_compile_time do + package 'apache2' +end + +# This is equivalent to +package 'apache2' do + action :nothing +end.run_action(:install) +``` + +```ruby +before 'service[apache2]' do + log 'I am before the apache 2 service fires!' +end +``` + +```ruby +after 'service[apache2]' do + log 'I am after the apache 2 service fires!' +end +``` + + +License & Authors +----------------- +- Author: Seth Vargo (sethvargo@gmail.com) + +```text +Copyright 2013-2015 Seth Vargo + +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/cookbooks/chef-sugar/metadata.json b/cookbooks/chef-sugar/metadata.json new file mode 100644 index 0000000..21028c7 --- /dev/null +++ b/cookbooks/chef-sugar/metadata.json @@ -0,0 +1 @@ +{"name":"chef-sugar","version":"3.3.0","description":"Installs chef-sugar. Please see the chef-sugar Ruby gem for more information.","long_description":"Chef Sugar is a Gem & Chef Recipe that includes series of helpful syntactic\nsugars on top of the Chef core and other resources to make a cleaner, more lean\nrecipe DSL, enforce DRY principles, and make writing Chef recipes an awesome and\nfun experience!\n\nFor the most up-to-date information and documentation, please visit the [Chef\nSugar project page on GitHub](https://github.com/sethvargo/chef-sugar).\n","maintainer":"Seth Vargo","maintainer_email":"sethvargo@gmail.com","license":"Apache 2.0","platforms":{},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file diff --git a/cookbooks/chef-sugar/recipes/default.rb b/cookbooks/chef-sugar/recipes/default.rb new file mode 100644 index 0000000..93256c7 --- /dev/null +++ b/cookbooks/chef-sugar/recipes/default.rb @@ -0,0 +1,34 @@ +# +# Cookbook Name:: chef-sugar +# Recipe:: default +# +# Copyright 2013-2015, Seth Vargo +# +# 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. +# + +gem_version = run_context.cookbook_collection[cookbook_name].metadata.version + +if Chef::Resource::ChefGem.instance_methods(false).include?(:compile_time) + chef_gem 'chef-sugar' do + version gem_version + compile_time true + end +else + chef_gem 'chef-sugar' do + version gem_version + action :nothing + end.run_action(:install) +end + +require 'chef/sugar' diff --git a/cookbooks/compat_resource/CHANGELOG.md b/cookbooks/compat_resource/CHANGELOG.md new file mode 100644 index 0000000..7908196 --- /dev/null +++ b/cookbooks/compat_resource/CHANGELOG.md @@ -0,0 +1,53 @@ +# compat_resource Cookbook CHANGELOG + +This file is used to list changes made in each version of the compat_resource cookbook. + +## 12.19.0 (2017-04-17) + +- Suppress warning already initialized constant +- Backport yum/apt changes from 12.19 + +## 12.16.2 (2016-11-09) + +- Sync chef-client changes from Chef 12.16.42 + +## 12.16.1 (2016-10-20) + +- add delayed_action helper + +## 12.16.0 (2016-10-19) + +- Sync chef-client changes from Chef 12.16.14 + +## 12.14.7 (2016-09-26) + +- Update to 12.14.89 Chef +- Fix autoload by applying fix from #106 + +## 12.14.6 (2016-09-20) + +- Update backported codebase to Chef 12.14.77 which brings in yum_repository updates and why-run enabled by default in custom resources + +## 12.14.5 (2016-09-19) + +- Prevent spamming messages in Chefspec runs for cookbooks that depend on compat_resource + +## 12.14.4 (2016-09-19) + +- Fix delayed notifications cloning + +## 12.14.3 (2016-09-12) + +- Fix subscribes notifications + +## 12.14.2 (2016-09-09) + +- Improve documentation +- keep ChefCompat::Resource defined even if we don't load + +## 12.14.1 (2016-09-07) + +- add yum_repository resource from Chef 12.14 +- Update the minimum chef version in the metadata to 12.1 +- Added maintainers files +- suppress constant redef warnings when running chefspec diff --git a/cookbooks/compat_resource/CONTRIBUTING.md b/cookbooks/compat_resource/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/compat_resource/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/cookbooks/compat_resource/MAINTAINERS.md b/cookbooks/compat_resource/MAINTAINERS.md new file mode 100644 index 0000000..5ae0806 --- /dev/null +++ b/cookbooks/compat_resource/MAINTAINERS.md @@ -0,0 +1,16 @@ + + +# Maintainers + +This file lists how this cookbook project is maintained. When making changes to the system, this file tells you who needs to review your patch - you need a review from an existing maintainer for the cookbook to provide a :+1: on your pull request. Additionally, you need to not receive a veto from a Lieutenant or the Project Lead. + +Check out [How Cookbooks are Maintained](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD) for details on the process and how to become a maintainer or the project lead. + +# Project Maintainer +* [Lamont Granquist](https://github.com/lamont-granquist) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) +* [Lamont Granquist](https://github.com/lamont-granquist) diff --git a/cookbooks/compat_resource/README.md b/cookbooks/compat_resource/README.md new file mode 100644 index 0000000..f5c17e5 --- /dev/null +++ b/cookbooks/compat_resource/README.md @@ -0,0 +1,60 @@ +# compat_resource cookbook + +[![Build Status](https://travis-ci.org/chef-cookbooks/compat_resource.svg?branch=master)](https://travis-ci.org/chef-cookbooks/compat_resource) [![Cookbook Version](https://img.shields.io/cookbook/v/compat_resource.svg)](https://supermarket.chef.io/cookbooks/compat_resource) + +This cookbook backports functionality introduced in the latest chef-client releases to any chef-client from 12.1 onwards. This includes [Custom Resource](https://docs.chef.io/custom_resources.html) functionality, notification improvements, as well as new resources added to core chef. It allows for the usage of these new resources in cookbooks without requiring the very latest Chef client release. + +## Backported functionality + +- [Custom Resources](https://docs.chef.io/custom_resources.html) +- [apt_repository](https://docs.chef.io/resource_apt_repository.html) +- [apt_update](https://docs.chef.io/resource_apt_update.html) +- [systemd_unit](https://docs.chef.io/resource_systemd_unit.html) +- [yum_repository](https://docs.chef.io/resource_yum_repository.html) +- [:before notifications](https://docs.chef.io/resources.html#timers) + +## Requirements + +### Platforms + +- All platforms supported by Chef + +### Chef + +- Chef 12.1+ + +### Cookbooks + +- none + +## Usage + +To use this cookbook, put `depends 'compat_resource'` in the metadata.rb of your cookbook. Once this is done, you can use all the new custom resource features to define resources. It Just Works. + +## Custom Resources? + +Curious about how to use custom resources? + +- Docs: +- Slides: + +## License & Authors + +- Author:: Lamont Granquist ([lamont@chef.io](mailto:lamont@chef.io)) +- Author:: John Keiser ([jkeiser@chef.io](mailto:jkeiser@chef.io)) + +```text +Copyright:: 2015-2016 Chef Software, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef.rb new file mode 100644 index 0000000..219b05b --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef.rb @@ -0,0 +1,29 @@ +module ChefCompat + module CopiedFromChef + def self.extend_chef_module(chef_module, target) + target.instance_eval do + include chef_module + @chef_module = chef_module + def self.method_missing(name, *args, &block) + @chef_module.send(name, *args, &block) + end + def self.const_missing(name) + @chef_module.const_get(name) + end + end + end + + # This patch to CopiedFromChef's ActionClass is necessary for the include to work + require 'chef/resource' + class Chef < ::Chef + class Resource < ::Chef::Resource + module ActionClass + def self.use_inline_resources + end + def self.include_resource_dsl(include_resource_dsl) + end + end + end + end + end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/constants.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/constants.rb new file mode 100644 index 0000000..4acd742 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/constants.rb @@ -0,0 +1,47 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/constants' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: John Keiser +# Copyright:: Copyright 2015-2016, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# 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. + +class Chef < (defined?(::Chef) ? ::Chef : Object) + NOT_PASSED = Object.new + def NOT_PASSED.to_s + "NOT_PASSED" + end + + def NOT_PASSED.inspect + to_s + end + NOT_PASSED.freeze +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/delayed_evaluator.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/delayed_evaluator.rb new file mode 100644 index 0000000..4fb687e --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/delayed_evaluator.rb @@ -0,0 +1,40 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/delayed_evaluator' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: John Keiser +# Copyright:: Copyright 2015-2016, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# 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. + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class DelayedEvaluator < (defined?(::Chef::DelayedEvaluator) ? ::Chef::DelayedEvaluator : Proc) + end +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/core.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/core.rb new file mode 100644 index 0000000..8e30d30 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/core.rb @@ -0,0 +1,73 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/dsl/core' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +#-- +# Author:: Adam Jacob () +# Author:: Christopher Walters () +# Copyright:: Copyright 2008-2016 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +require "chef_compat/copied_from_chef/chef/dsl/declare_resource" +require "chef_compat/copied_from_chef/chef/dsl/universal" +require "chef_compat/copied_from_chef/chef/mixin/notifying_block" +require "chef_compat/copied_from_chef/chef/mixin/lazy_module_include" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + module DSL + CopiedFromChef.extend_chef_module(::Chef::DSL, self) if defined?(::Chef::DSL) + # Part of a family of DSL mixins. + # + # Chef::DSL::Recipe mixes into Recipes and LWRP Providers. + # - this does not target core chef resources and providers. + # - this is restricted to recipe/resource/provider context where a resource collection exists. + # - cookbook authors should typically include modules into here. + # + # Chef::DSL::Core mixes into Recipes, LWRP Providers and Core Providers + # - this adds cores providers on top of the Recipe DSL. + # - this is restricted to recipe/resource/provider context where a resource collection exists. + # - core chef authors should typically include modules into here. + # + # Chef::DSL::Universal mixes into Recipes, LWRP Resources+Providers, Core Resources+Providers, and Attributes files. + # - this adds resources and attributes files. + # - do not add helpers which manipulate the resource collection. + # - this is for general-purpose stuff that is useful nearly everywhere. + # - it also pollutes the namespace of nearly every context, watch out. + # + module Core + CopiedFromChef.extend_chef_module(::Chef::DSL::Core, self) if defined?(::Chef::DSL::Core) + include Chef::DSL::Universal + include Chef::DSL::DeclareResource + include Chef::Mixin::NotifyingBlock + extend Chef::Mixin::LazyModuleInclude + end + end +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/declare_resource.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/declare_resource.rb new file mode 100644 index 0000000..45e69dc --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/declare_resource.rb @@ -0,0 +1,315 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/dsl/declare_resource' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +#-- +# Author:: Adam Jacob () +# Author:: Christopher Walters +# Copyright:: Copyright 2008-2016 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + + +class Chef < (defined?(::Chef) ? ::Chef : Object) + module DSL + CopiedFromChef.extend_chef_module(::Chef::DSL, self) if defined?(::Chef::DSL) + module DeclareResource + CopiedFromChef.extend_chef_module(::Chef::DSL::DeclareResource, self) if defined?(::Chef::DSL::DeclareResource) + + # Helper for switching run_contexts. Allows for using :parent or :root in place of + # passing the run_context. Executes the block in the run_context. Returns the return + # value of the passed block. + # + # @param rc [Chef::RunContext,Symbol] Either :root, :parent or a Chef::RunContext + # + # @return return value of the block + # + # @example + # # creates/returns a 'service[foo]' resource in the root run_context + # resource = with_run_context(:root) + # edit_resource(:service, "foo") do + # action :nothing + # end + # end + # + def with_run_context(rc) + raise ArgumentError, "with_run_context is useless without a block" unless block_given? + old_run_context = @run_context + @run_context = + case rc + when Chef::RunContext + rc + when :root + run_context.root_run_context + when :parent + run_context.parent_run_context + else + raise ArgumentError, "bad argument to run_context helper, must be :root, :parent, or a Chef::RunContext" + end + yield + ensure + @run_context = old_run_context + end + + # Lookup a resource in the resource collection by name and delete it. This + # will raise Chef::Exceptions::ResourceNotFound if the resource is not found. + # + # @param type [Symbol] The type of resource (e.g. `:file` or `:package`) + # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2') + # @param run_context [Chef::RunContext] the run_context of the resource collection to operate on + # + # @return [Chef::Resource] The resource + # + # @example + # delete_resource!(:template, '/x/y.txy') + # + def delete_resource!(type, name, run_context: self.run_context) + run_context.resource_collection.delete("#{type}[#{name}]").tap do |resource| + # Purge any pending notifications too. This will not raise an exception + # if there are no notifications. + if resource + run_context.before_notification_collection.delete(resource.declared_key) + run_context.immediate_notification_collection.delete(resource.declared_key) + run_context.delayed_notification_collection.delete(resource.declared_key) + end + end + end + + # Lookup a resource in the resource collection by name and delete it. Returns + # nil if the resource is not found and should not fail. + # + # @param type [Symbol] The type of resource (e.g. `:file` or `:package`) + # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2') + # @param run_context [Chef::RunContext] the run_context of the resource collection to operate on + # + # @return [Chef::Resource] The resource + # + # @example + # delete_resource(:template, '/x/y.txy') + # + def delete_resource(type, name, run_context: self.run_context) + delete_resource!(type, name, run_context: run_context) + rescue Chef::Exceptions::ResourceNotFound + nil + end + + # Lookup a resource in the resource collection by name and edit the resource. If the resource is not + # found this will raise Chef::Exceptions::ResourceNotFound. This is the correct API to use for + # "chef_rewind" functionality. + # + # @param type [Symbol] The type of resource (e.g. `:file` or `:package`) + # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2') + # @param run_context [Chef::RunContext] the run_context of the resource collection to operate on + # @param resource_attrs_block A block that lets you set attributes of the + # resource (it is instance_eval'd on the resource instance). + # + # @return [Chef::Resource] The updated resource + # + # @example + # edit_resource!(:template, '/x/y.txy') do + # cookbook_name: cookbook_name + # end + # + def edit_resource!(type, name, created_at = nil, run_context: self.run_context, &resource_attrs_block) + resource = find_resource!(type, name, run_context: run_context) + if resource_attrs_block + if defined?(new_resource) + resource.instance_exec(new_resource, &resource_attrs_block) + else + resource.instance_exec(&resource_attrs_block) + end + end + resource + end + + # Lookup a resource in the resource collection by name. If it exists, + # return it. If it does not exist, create it. This is a useful function + # for accumulator patterns. In CRUD terminology this is an "upsert" operation and is + # used to assert that the resource must exist with the specified properties. + # + # @param type [Symbol] The type of resource (e.g. `:file` or `:package`) + # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2') + # @param created_at [String] The caller of the resource. Use `caller[0]` + # to get the caller of your function. Defaults to the caller of this + # function. + # @param run_context [Chef::RunContext] the run_context of the resource collection to operate on + # @param resource_attrs_block A block that lets you set attributes of the + # resource (it is instance_eval'd on the resource instance). + # + # @return [Chef::Resource] The updated or created resource + # + # @example + # resource = edit_resource(:template, '/x/y.txy') do + # source "y.txy.erb" + # variables {} + # end + # resource.variables.merge!({ home: "/home/klowns" }) + # + def edit_resource(type, name, created_at = nil, run_context: self.run_context, &resource_attrs_block) + edit_resource!(type, name, created_at, run_context: run_context, &resource_attrs_block) + rescue Chef::Exceptions::ResourceNotFound + declare_resource(type, name, created_at, run_context: run_context, &resource_attrs_block) + end + + # Lookup a resource in the resource collection by name. If the resource is not + # found this will raise Chef::Exceptions::ResourceNotFound. This API is identical to the + # resources() call and while it is a synonym it is not intended to deprecate that call. + # + # @param type [Symbol] The type of resource (e.g. `:file` or `:package`) + # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2') + # @param run_context [Chef::RunContext] the run_context of the resource collection to operate on + # + # @return [Chef::Resource] The updated resource + # + # @example + # resource = find_resource!(:template, '/x/y.txy') + # + def find_resource!(type, name, run_context: self.run_context) + raise ArgumentError, "find_resource! does not take a block" if block_given? + run_context.resource_collection.find(type => name) + end + + # Lookup a resource in the resource collection by name. If the resource is not found + # the will be no exception raised and the call will return nil. If a block is given and + # no resource is found it will create the resource using the block, if the resource is + # found then the block will not be applied. The block version is similar to create_if_missing + # + # @param type [Symbol] The type of resource (e.g. `:file` or `:package`) + # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2') + # @param run_context [Chef::RunContext] the run_context of the resource collection to operate on + # + # @return [Chef::Resource] The updated resource + # + # @example + # if ( find_resource(:template, '/x/y.txy') ) + # # do something + # else + # # don't worry about the error + # end + # + # @example + # # this API can be used to return a resource from an outer run context, and will only create + # # an action :nothing service if one does not already exist. + # resource = with_run_context(:root) do + # find_resource(:service, 'whatever') do + # action :nothing + # end + # end + # + def find_resource(type, name, created_at: nil, run_context: self.run_context, &resource_attrs_block) + find_resource!(type, name, run_context: run_context) + rescue Chef::Exceptions::ResourceNotFound + if resource_attrs_block + declare_resource(type, name, created_at, run_context: run_context, &resource_attrs_block) + end # returns nil otherwise + end + + # Instantiates a resource (via #build_resource), then adds it to the + # resource collection. Note that resource classes are looked up directly, + # so this will create the resource you intended even if the method name + # corresponding to that resource has been overridden. + # + # @param type [Symbol] The type of resource (e.g. `:file` or `:package`) + # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2') + # @param created_at [String] The caller of the resource. Use `caller[0]` + # to get the caller of your function. Defaults to the caller of this + # function. + # @param run_context [Chef::RunContext] the run_context of the resource collection to operate on + # @param resource_attrs_block A block that lets you set attributes of the + # resource (it is instance_eval'd on the resource instance). + # + # @return [Chef::Resource] The new resource. + # + # @example + # declare_resource(:file, '/x/y.txy', caller[0]) do + # action :delete + # end + # # Equivalent to + # file '/x/y.txt' do + # action :delete + # end + # + def declare_resource(type, name, created_at = nil, run_context: self.run_context, create_if_missing: false, &resource_attrs_block) + created_at ||= caller[0] + + if create_if_missing + Chef::Log.deprecation "build_resource with a create_if_missing flag is deprecated, use edit_resource instead" + # midly goofy since we call edit_resource only to re-call ourselves, but that's why its deprecated... + return edit_resource(type, name, created_at, run_context: run_context, &resource_attrs_block) + end + + resource = build_resource(type, name, created_at, &resource_attrs_block) + + run_context.resource_collection.insert(resource, resource_type: type, instance_name: name) + resource + end + + # Instantiate a resource of the given +type+ with the given +name+ and + # attributes as given in the +resource_attrs_block+. + # + # The resource is NOT added to the resource collection. + # + # @param type [Symbol] The type of resource (e.g. `:file` or `:package`) + # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2') + # @param created_at [String] The caller of the resource. Use `caller[0]` + # to get the caller of your function. Defaults to the caller of this + # function. + # @param run_context [Chef::RunContext] the run_context of the resource collection to operate on + # @param resource_attrs_block A block that lets you set attributes of the + # resource (it is instance_eval'd on the resource instance). + # + # @return [Chef::Resource] The new resource. + # + # @example + # build_resource(:file, '/x/y.txy', caller[0]) do + # action :delete + # end + # + def build_resource(type, name, created_at = nil, run_context: self.run_context, &resource_attrs_block) + created_at ||= caller[0] + + # this needs to be lazy in order to avoid circular dependencies since ResourceBuilder + # will requires the entire provider+resolver universe + require "chef_compat/copied_from_chef/chef/resource_builder" unless defined?(Chef::ResourceBuilder) + + Chef::ResourceBuilder.new( + type: type, + name: name, + created_at: created_at, + params: @params, + run_context: run_context, + cookbook_name: cookbook_name, + recipe_name: recipe_name, + enclosing_provider: self.is_a?(Chef::Provider) ? self : nil + ).build(&resource_attrs_block) + end + end + end +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/platform_introspection.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/platform_introspection.rb new file mode 100644 index 0000000..7886000 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/platform_introspection.rb @@ -0,0 +1,292 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/dsl/platform_introspection' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Adam Jacob () +# Copyright:: Copyright 2008-2016, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +class Chef < (defined?(::Chef) ? ::Chef : Object) + module DSL + CopiedFromChef.extend_chef_module(::Chef::DSL, self) if defined?(::Chef::DSL) + + # == Chef::DSL::PlatformIntrospection + # Provides the DSL for platform-dependent switch logic, such as + # #value_for_platform. + module PlatformIntrospection + CopiedFromChef.extend_chef_module(::Chef::DSL::PlatformIntrospection, self) if defined?(::Chef::DSL::PlatformIntrospection) + + # Implementation class for determining platform dependent values + class PlatformDependentValue < (defined?(::Chef::DSL::PlatformIntrospection::PlatformDependentValue) ? ::Chef::DSL::PlatformIntrospection::PlatformDependentValue : Object) + + # Create a platform dependent value object. + # === Arguments + # platform_hash (Hash) a hash of the same structure as Chef::Platform, + # like this: + # { + # :debian => {:default => 'the value for all debian'} + # [:centos, :redhat, :fedora] => {:default => "value for all EL variants"} + # :ubuntu => { :default => "default for ubuntu", '10.04' => "value for 10.04 only"}, + # :default => "the default when nothing else matches" + # } + # * platforms can be specified as Symbols or Strings + # * multiple platforms can be grouped by using an Array as the key + # * values for platforms need to be Hashes of the form: + # {platform_version => value_for_that_version} + # * the exception to the above is the default value, which is given as + # :default => default_value + def initialize(platform_hash) +super if defined?(::Chef::DSL::PlatformIntrospection::PlatformDependentValue) + @values = {} + platform_hash.each { |platforms, value| set(platforms, value) } + end + + def value_for_node(node) + platform, version = node[:platform].to_s, node[:platform_version].to_s + # Check if we match a version constraint via Chef::VersionConstraint::Platform and Chef::Version::Platform + matched_value = match_versions(node) + if @values.key?(platform) && @values[platform].key?(version) + @values[platform][version] + elsif matched_value + matched_value + elsif @values.key?(platform) && @values[platform].key?("default") + @values[platform]["default"] + elsif @values.key?("default") + @values["default"] + else + nil + end + end + + private + + def match_versions(node) + begin + platform, version = node[:platform].to_s, node[:platform_version].to_s + return nil unless @values.key?(platform) + node_version = Chef::Version::Platform.new(version) + key_matches = [] + keys = @values[platform].keys + keys.each do |k| + begin + if Chef::VersionConstraint::Platform.new(k).include?(node_version) + key_matches << k + end + rescue Chef::Exceptions::InvalidVersionConstraint => e + Chef::Log.debug "Caught InvalidVersionConstraint. This means that a key in value_for_platform cannot be interpreted as a Chef::VersionConstraint::Platform." + Chef::Log.debug(e) + end + end + return @values[platform][version] if key_matches.include?(version) + case key_matches.length + when 0 + return nil + when 1 + return @values[platform][key_matches.first] + else + raise "Multiple matches detected for #{platform} with values #{@values}. The matches are: #{key_matches}" + end + rescue Chef::Exceptions::InvalidCookbookVersion => e + # Lets not break because someone passes a weird string like 'default' :) + Chef::Log.debug(e) + Chef::Log.debug "InvalidCookbookVersion exceptions are common and expected here: the generic constraint matcher attempted to match something which is not a constraint. Moving on to next version or constraint" + return nil + rescue Chef::Exceptions::InvalidPlatformVersion => e + Chef::Log.debug "Caught InvalidPlatformVersion, this means that Chef::Version::Platform does not know how to turn #{node_version} into an x.y.z format" + Chef::Log.debug(e) + return nil + end + end + + def set(platforms, value) + if platforms.to_s == "default" + @values["default"] = value + else + assert_valid_platform_values!(platforms, value) + Array(platforms).each { |platform| @values[platform.to_s] = normalize_keys(value) } + value + end + end + + def normalize_keys(hash) + hash.inject({}) do |h, key_value| + keys, value = *key_value + Array(keys).each do |key| + h[key.to_s] = value + end + h + end + end + + def assert_valid_platform_values!(platforms, value) + unless value.kind_of?(Hash) + msg = "platform dependent values must be specified in the format :platform => {:version => value} " + msg << "you gave a value #{value.inspect} for platform(s) #{platforms}" + raise ArgumentError, msg + end + end + end + + # Given a hash similar to the one we use for Platforms, select a value from the hash. Supports + # per platform defaults, along with a single base default. Arrays may be passed as hash keys and + # will be expanded. + # + # === Parameters + # platform_hash:: A platform-style hash. + # + # === Returns + # value:: Whatever the most specific value of the hash is. + def value_for_platform(platform_hash) + PlatformDependentValue.new(platform_hash).value_for_node(node) + end + + # Given a list of platforms, returns true if the current recipe is being run on a node with + # that platform, false otherwise. + # + # === Parameters + # args:: A list of platforms. Each platform can be in string or symbol format. + # + # === Returns + # true:: If the current platform is in the list + # false:: If the current platform is not in the list + def platform?(*args) + has_platform = false + + args.flatten.each do |platform| + has_platform = true if platform.to_s == node[:platform] + end + + has_platform + end + + # Implementation class for determining platform family dependent values + class PlatformFamilyDependentValue < (defined?(::Chef::DSL::PlatformIntrospection::PlatformFamilyDependentValue) ? ::Chef::DSL::PlatformIntrospection::PlatformFamilyDependentValue : Object) + + # Create a platform family dependent value object. + # === Arguments + # platform_family_hash (Hash) a map of platform families to values. + # like this: + # { + # :rhel => "value for all EL variants" + # :fedora => "value for fedora variants fedora and amazon" , + # [:fedora, :rhel] => "value for all known redhat variants" + # :debian => "value for debian variants including debian, ubuntu, mint" , + # :default => "the default when nothing else matches" + # } + # * platform families can be specified as Symbols or Strings + # * multiple platform families can be grouped by using an Array as the key + # * values for platform families can be any object, with no restrictions. Some examples: + # - [:stop, :start] + # - "mysql-devel" + # - { :key => "value" } + def initialize(platform_family_hash) +super if defined?(::Chef::DSL::PlatformIntrospection::PlatformFamilyDependentValue) + @values = {} + @values["default"] = nil + platform_family_hash.each { |platform_families, value| set(platform_families, value) } + end + + def value_for_node(node) + if node.key?(:platform_family) + platform_family = node[:platform_family].to_s + if @values.key?(platform_family) + @values[platform_family] + else + @values["default"] + end + else + @values["default"] + end + end + + private + + def set(platform_family, value) + if platform_family.to_s == "default" + @values["default"] = value + else + Array(platform_family).each { |family| @values[family.to_s] = value } + value + end + end + end + + # Given a hash mapping platform families to values, select a value from the hash. Supports a single + # base default if platform family is not in the map. Arrays may be passed as hash keys and will be + # expanded + # + # === Parameters + # platform_family_hash:: A hash in the form { platform_family_name => value } + # + # === Returns + # value:: Whatever the most specific value of the hash is. + def value_for_platform_family(platform_family_hash) + PlatformFamilyDependentValue.new(platform_family_hash).value_for_node(node) + end + + # Given a list of platform families, returns true if the current recipe is being run on a + # node within that platform family, false otherwise. + # + # === Parameters + # args:: A list of platform families. Each platform family can be in string or symbol format. + # + # === Returns + # true:: if the current node platform family is in the list. + # false:: if the current node platform family is not in the list. + def platform_family?(*args) + args.flatten.any? do |platform_family| + platform_family.to_s == node[:platform_family] + end + end + + # Shamelessly stolen from https://github.com/sethvargo/chef-sugar/blob/master/lib/chef/sugar/docker.rb + # Given a node object, returns whether the node is a docker container. + # + # === Parameters + # node:: [Chef::Node] The node to check. + # + # === Returns + # true:: if the current node is a docker container + # false:: if the current node is not a docker container + def docker?(node = run_context.nil? ? nil : run_context.node) + # Using "File.exist?('/.dockerinit') || File.exist?('/.dockerenv')" makes Travis sad, + # and that makes us sad too. + node && node[:virtualization] && node[:virtualization][:systems] && + node[:virtualization][:systems][:docker] && node[:virtualization][:systems][:docker] == "guest" + end + + end + end +end + +# **DEPRECATED** +# This used to be part of chef/mixin/language. Load the file to activate the deprecation code. +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/recipe.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/recipe.rb new file mode 100644 index 0000000..f896ec7 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/recipe.rb @@ -0,0 +1,37 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/dsl/recipe' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +require "chef_compat/copied_from_chef/chef/dsl/core" +require "chef_compat/copied_from_chef/chef/mixin/lazy_module_include" +class Chef < (defined?(::Chef) ? ::Chef : Object) + module DSL + CopiedFromChef.extend_chef_module(::Chef::DSL, self) if defined?(::Chef::DSL) + module Recipe + CopiedFromChef.extend_chef_module(::Chef::DSL::Recipe, self) if defined?(::Chef::DSL::Recipe) + include Chef::DSL::Core + extend Chef::Mixin::LazyModuleInclude + module FullDSL + CopiedFromChef.extend_chef_module(::Chef::DSL::Recipe::FullDSL, self) if defined?(::Chef::DSL::Recipe::FullDSL) + include Chef::DSL::Recipe + extend Chef::Mixin::LazyModuleInclude + end + end + end +end +require "chef_compat/copied_from_chef/chef/resource" +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/universal.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/universal.rb new file mode 100644 index 0000000..7f529f1 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/universal.rb @@ -0,0 +1,70 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/dsl/universal' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +#-- +# Author:: Adam Jacob () +# Author:: Christopher Walters () +# Copyright:: Copyright 2008-2016 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +require "chef_compat/copied_from_chef/chef/dsl/platform_introspection" +require "chef_compat/copied_from_chef/chef/mixin/powershell_out" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + module DSL + CopiedFromChef.extend_chef_module(::Chef::DSL, self) if defined?(::Chef::DSL) + # Part of a family of DSL mixins. + # + # Chef::DSL::Recipe mixes into Recipes and LWRP Providers. + # - this does not target core chef resources and providers. + # - this is restricted to recipe/resource/provider context where a resource collection exists. + # - cookbook authors should typically include modules into here. + # + # Chef::DSL::Core mixes into Recipes, LWRP Providers and Core Providers + # - this adds cores providers on top of the Recipe DSL. + # - this is restricted to recipe/resource/provider context where a resource collection exists. + # - core chef authors should typically include modules into here. + # + # Chef::DSL::Universal mixes into Recipes, LWRP Resources+Providers, Core Resources+Providers, and Attributes files. + # - this adds resources and attributes files. + # - do not add helpers which manipulate the resource collection. + # - this is for general-purpose stuff that is useful nearly everywhere. + # - it also pollutes the namespace of nearly every context, watch out. + # + module Universal + CopiedFromChef.extend_chef_module(::Chef::DSL::Universal, self) if defined?(::Chef::DSL::Universal) + include Chef::DSL::PlatformIntrospection + include Chef::Mixin::PowershellOut + include Chef::Mixin::ShellOut + end + end +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/lazy_module_include.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/lazy_module_include.rb new file mode 100644 index 0000000..a6b5244 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/lazy_module_include.rb @@ -0,0 +1,98 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/mixin/lazy_module_include' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Copyright:: Copyright 2011-2016, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +class Chef < (defined?(::Chef) ? ::Chef : Object) + module Mixin + CopiedFromChef.extend_chef_module(::Chef::Mixin, self) if defined?(::Chef::Mixin) + # If you have: + # + # module A + # extend LazyModuleInclude + # end + # + # module B + # include A + # end + # + # module C + # include B + # end + # + # module Monkeypatches + # def monkey + # puts "monkey!" + # end + # end + # + # A.send(:include, Monkeypatches) + # + # Then B and C and any classes that they're included in will also get the #monkey method patched into them. + # + module LazyModuleInclude + CopiedFromChef.extend_chef_module(::Chef::Mixin::LazyModuleInclude, self) if defined?(::Chef::Mixin::LazyModuleInclude) + + # Most of the magick is in this hook which creates a closure over the parent class and then builds an + # "infector" module which infects all descendants and which is responsible for updating the list of + # descendants in the parent class. + def included(klass) + super + parent_klass = self + infector = Module.new do + define_method(:included) do |subklass| + super(subklass) + subklass.extend(infector) + parent_klass.descendants.push(subklass) + end + end + klass.extend(infector) + parent_klass.descendants.push(klass) + end + + def descendants + @descendants ||= [] + end + + def include(*classes) + super + classes.each do |klass| + descendants.each do |descendant| + descendant.send(:include, klass) + end + end + end + end + end +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/notifying_block.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/notifying_block.rb new file mode 100644 index 0000000..0b90e27 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/notifying_block.rb @@ -0,0 +1,74 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/mixin/notifying_block' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +#-- +# Author:: Lamont Granquist +# Copyright:: Copyright 2010-2016, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# 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. + +class Chef < (defined?(::Chef) ? ::Chef : Object) + module Mixin + CopiedFromChef.extend_chef_module(::Chef::Mixin, self) if defined?(::Chef::Mixin) + module NotifyingBlock + CopiedFromChef.extend_chef_module(::Chef::Mixin::NotifyingBlock, self) if defined?(::Chef::Mixin::NotifyingBlock) + + def notifying_block(&block) + begin + subcontext = subcontext_block(&block) + Chef::Runner.new(subcontext).converge + ensure + # recipes don't have a new_resource + if respond_to?(:new_resource) + if subcontext && subcontext.resource_collection.any?(&:updated?) + new_resource.updated_by_last_action(true) + end + end + end + end + + def subcontext_block(parent_context = nil, &block) + parent_context ||= @run_context + sub_run_context = parent_context.create_child + + begin + outer_run_context = @run_context + @run_context = sub_run_context + instance_eval(&block) + ensure + @run_context = outer_run_context + end + + sub_run_context + end + + end + end +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/params_validate.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/params_validate.rb new file mode 100644 index 0000000..0a16147 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/params_validate.rb @@ -0,0 +1,510 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/mixin/params_validate' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Adam Jacob () +# Copyright:: Copyright 2008-2016, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# 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. + +require "chef_compat/copied_from_chef/chef/constants" +require "chef_compat/copied_from_chef/chef/property" +require "chef_compat/copied_from_chef/chef/delayed_evaluator" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + module Mixin + CopiedFromChef.extend_chef_module(::Chef::Mixin, self) if defined?(::Chef::Mixin) + module ParamsValidate + CopiedFromChef.extend_chef_module(::Chef::Mixin::ParamsValidate, self) if defined?(::Chef::Mixin::ParamsValidate) + # Takes a hash of options, along with a map to validate them. Returns the original + # options hash, plus any changes that might have been made (through things like setting + # default values in the validation map) + # + # For example: + # + # validate({ :one => "neat" }, { :one => { :kind_of => String }}) + # + # Would raise an exception if the value of :one above is not a kind_of? string. Valid + # map options are: + # + # @param opts [Hash] Validation opts. + # @option opts [Object,Array] :is An object, or list of + # objects, that must match the value using Ruby's `===` operator + # (`opts[:is].any? { |v| v === value }`). (See #_pv_is.) + # @option opts [Object,Array] :equal_to An object, or list + # of objects, that must be equal to the value using Ruby's `==` + # operator (`opts[:is].any? { |v| v == value }`) (See #_pv_equal_to.) + # @option opts [Regexp,Array] :regex An object, or + # list of objects, that must match the value with `regex.match(value)`. + # (See #_pv_regex) + # @option opts [Class,Array] :kind_of A class, or + # list of classes, that the value must be an instance of. (See + # #_pv_kind_of.) + # @option opts [Hash] :callbacks A hash of + # messages -> procs, all of which match the value. The proc must + # return a truthy or falsey value (true means it matches). (See + # #_pv_callbacks.) + # @option opts [Symbol,Array] :respond_to A method + # name, or list of method names, the value must respond to. (See + # #_pv_respond_to.) + # @option opts [Symbol,Array] :cannot_be A property, + # or a list of properties, that the value cannot have (such as `:nil` or + # `:empty`). The method with a questionmark at the end is called on the + # value (e.g. `value.empty?`). If the value does not have this method, + # it is considered valid (i.e. if you don't respond to `empty?` we + # assume you are not empty). (See #_pv_cannot_be.) + # @option opts [Proc] :coerce A proc which will be called to + # transform the user input to canonical form. The value is passed in, + # and the transformed value returned as output. Lazy values will *not* + # be passed to this method until after they are evaluated. Called in the + # context of the resource (meaning you can access other properties). + # (See #_pv_coerce.) (See #_pv_coerce.) + # @option opts [Boolean] :required `true` if this property + # must be present and not `nil`; `false` otherwise. This is checked + # after the resource is fully initialized. (See #_pv_required.) + # @option opts [Boolean] :name_property `true` if this + # property defaults to the same value as `name`. Equivalent to + # `default: lazy { name }`, except that #property_is_set? will + # return `true` if the property is set *or* if `name` is set. (See + # #_pv_name_property.) + # @option opts [Boolean] :name_attribute Same as `name_property`. + # @option opts [Object] :default The value this property + # will return if the user does not set one. If this is `lazy`, it will + # be run in the context of the instance (and able to access other + # properties). (See #_pv_default.) + # + def validate(opts, map) + map = map.validation_options if map.is_a?(Property) + + #-- + # validate works by taking the keys in the validation map, assuming it's a hash, and + # looking for _pv_:symbol as methods. Assuming it find them, it calls the right + # one. + #++ + raise ArgumentError, "Options must be a hash" unless opts.kind_of?(Hash) + raise ArgumentError, "Validation Map must be a hash" unless map.kind_of?(Hash) + + map.each do |key, validation| + unless key.kind_of?(Symbol) || key.kind_of?(String) + raise ArgumentError, "Validation map keys must be symbols or strings!" + end + case validation + when true + _pv_required(opts, key) + when false + true + when Hash + validation.each do |check, carg| + check_method = "_pv_#{check}" + if self.respond_to?(check_method, true) + self.send(check_method, opts, key, carg) + else + raise ArgumentError, "Validation map has unknown check: #{check}" + end + end + end + end + opts + end + + def lazy(&block) + DelayedEvaluator.new(&block) + end + + def set_or_return(symbol, value, validation) + property = SetOrReturnProperty.new(name: symbol, **validation) + property.call(self, value) + end + + private + + def explicitly_allows_nil?(key, validation) + validation.has_key?(:is) && _pv_is({ key => nil }, key, validation[:is], raise_error: false) + end + + # Return the value of a parameter, or nil if it doesn't exist. + def _pv_opts_lookup(opts, key) + if opts.has_key?(key.to_s) + opts[key.to_s] + elsif opts.has_key?(key.to_sym) + opts[key.to_sym] + else + nil + end + end + + # Raise an exception if the parameter is not found. + def _pv_required(opts, key, is_required = true, explicitly_allows_nil = false) + if is_required + return true if opts.has_key?(key.to_s) && (explicitly_allows_nil || !opts[key.to_s].nil?) + return true if opts.has_key?(key.to_sym) && (explicitly_allows_nil || !opts[key.to_sym].nil?) + raise Exceptions::ValidationFailed, "Required argument #{key.inspect} is missing!" + end + true + end + + # + # List of things values must be equal to. + # + # Uses Ruby's `==` to evaluate (equal_to == value). At least one must + # match for the value to be valid. + # + # `nil` passes this validation automatically. + # + # @return [Array,nil] List of things values must be equal to, or nil if + # equal_to is unspecified. + # + def _pv_equal_to(opts, key, to_be) + value = _pv_opts_lookup(opts, key) + unless value.nil? + to_be = Array(to_be) + to_be.each do |tb| + return true if value == tb + end + raise Exceptions::ValidationFailed, "Option #{key} must be equal to one of: #{to_be.join(", ")}! You passed #{value.inspect}." + end + end + + # + # List of things values must be instances of. + # + # Uses value.kind_of?(kind_of) to evaluate. At least one must match for + # the value to be valid. + # + # `nil` automatically passes this validation. + # + def _pv_kind_of(opts, key, to_be) + value = _pv_opts_lookup(opts, key) + unless value.nil? + to_be = Array(to_be) + to_be.each do |tb| + return true if value.kind_of?(tb) + end + raise Exceptions::ValidationFailed, "Option #{key} must be a kind of #{to_be}! You passed #{value.inspect}." + end + end + + # + # List of method names values must respond to. + # + # Uses value.respond_to?(respond_to) to evaluate. At least one must match + # for the value to be valid. + # + def _pv_respond_to(opts, key, method_name_list) + value = _pv_opts_lookup(opts, key) + unless value.nil? + Array(method_name_list).each do |method_name| + unless value.respond_to?(method_name) + raise Exceptions::ValidationFailed, "Option #{key} must have a #{method_name} method!" + end + end + end + end + + # + # List of things that must not be true about the value. + # + # Calls `value.?` All responses must be false for the value to be + # valid. + # Values which do not respond to ? are considered valid (because if + # a value doesn't respond to `:readable?`, then it probably isn't + # readable.) + # + # @example + # ```ruby + # property :x, cannot_be: [ :nil, :empty ] + # x [ 1, 2 ] #=> valid + # x 1 #=> valid + # x [] #=> invalid + # x nil #=> invalid + # ``` + # + def _pv_cannot_be(opts, key, predicate_method_base_name) + value = _pv_opts_lookup(opts, key) + if !value.nil? + Array(predicate_method_base_name).each do |method_name| + predicate_method = :"#{method_name}?" + + if value.respond_to?(predicate_method) + if value.send(predicate_method) + raise Exceptions::ValidationFailed, "Option #{key} cannot be #{predicate_method_base_name}" + end + end + end + end + end + + # + # The default value for a property. + # + # When the property is not assigned, this will be used. + # + # If this is a lazy value, it will either be passed the resource as a value, + # or if the lazy proc does not take parameters, it will be run in the + # context of the instance with instance_eval. + # + # @example + # ```ruby + # property :x, default: 10 + # ``` + # + # @example + # ```ruby + # property :x + # property :y, default: lazy { x+2 } + # ``` + # + # @example + # ```ruby + # property :x + # property :y, default: lazy { |r| r.x+2 } + # ``` + # + def _pv_default(opts, key, default_value) + value = _pv_opts_lookup(opts, key) + if value.nil? + default_value = default_value.freeze if !default_value.is_a?(DelayedEvaluator) + opts[key] = default_value + end + end + + # + # List of regexes values that must match. + # + # Uses regex.match() to evaluate. At least one must match for the value to + # be valid. + # + # `nil` passes regex validation automatically. + # + # @example + # ```ruby + # property :x, regex: [ /abc/, /xyz/ ] + # ``` + # + def _pv_regex(opts, key, regex) + value = _pv_opts_lookup(opts, key) + if !value.nil? + Array(regex).flatten.each do |r| + return true if r.match(value.to_s) + end + raise Exceptions::ValidationFailed, "Option #{key}'s value #{value} does not match regular expression #{regex.inspect}" + end + end + + # + # List of procs we pass the value to. + # + # All procs must return true for the value to be valid. If any procs do + # not return true, the key will be used for the message: `"Property x's + # value :y "`. + # + # @example + # ```ruby + # property :x, callbacks: { "is bigger than 10" => proc { |v| v <= 10 }, "is not awesome" => proc { |v| !v.awesome }} + # ``` + # + def _pv_callbacks(opts, key, callbacks) + raise ArgumentError, "Callback list must be a hash!" unless callbacks.kind_of?(Hash) + value = _pv_opts_lookup(opts, key) + if !value.nil? + callbacks.each do |message, zeproc| + unless zeproc.call(value) + raise Exceptions::ValidationFailed, "Option #{key}'s value #{value} #{message}!" + end + end + end + end + + # + # Allows a parameter to default to the value of the resource name. + # + # @example + # ```ruby + # property :x, name_property: true + # ``` + # + def _pv_name_property(opts, key, is_name_property = true) + if is_name_property + if opts[key].nil? + raise CannotValidateStaticallyError, "name_property cannot be evaluated without a resource." if self == Chef::Mixin::ParamsValidate + opts[key] = self.instance_variable_get(:"@name") + end + end + end + alias :_pv_name_attribute :_pv_name_property + + # + # List of valid things values can be. + # + # Uses Ruby's `===` to evaluate (is === value). At least one must match + # for the value to be valid. + # + # If a proc is passed, it is instance_eval'd in the resource, passed the + # value, and must return a truthy or falsey value. + # + # @example Class + # ```ruby + # property :x, String + # x 'valid' #=> valid + # x 1 #=> invalid + # x nil #=> invalid + # + # @example Value + # ```ruby + # property :x, [ :a, :b, :c, nil ] + # x :a #=> valid + # x nil #=> valid + # ``` + # + # @example Regex + # ```ruby + # property :x, /bar/ + # x 'foobar' #=> valid + # x 'foo' #=> invalid + # x nil #=> invalid + # ``` + # + # @example Proc + # ```ruby + # property :x, proc { |x| x > y } + # property :y, default: 2 + # x 3 #=> valid + # x 1 #=> invalid + # ``` + # + # @example Property + # ```ruby + # type = Property.new(is: String) + # property :x, type + # x 'foo' #=> valid + # x 1 #=> invalid + # x nil #=> invalid + # ``` + # + # @example RSpec Matcher + # ```ruby + # include RSpec::Matchers + # property :x, a_string_matching /bar/ + # x 'foobar' #=> valid + # x 'foo' #=> invalid + # x nil #=> invalid + # ``` + # + def _pv_is(opts, key, to_be, raise_error: true) + return true if !opts.has_key?(key.to_s) && !opts.has_key?(key.to_sym) + value = _pv_opts_lookup(opts, key) + to_be = [ to_be ].flatten(1) + errors = [] + passed = to_be.any? do |tb| + case tb + when Proc + raise CannotValidateStaticallyError, "is: proc { } must be evaluated once for each resource" if self == Chef::Mixin::ParamsValidate + instance_exec(value, &tb) + when Property + begin + validate(opts, { key => tb.validation_options }) + true + rescue Exceptions::ValidationFailed + # re-raise immediately if there is only one "is" so we get a better stack + raise if to_be.size == 1 + errors << $! + false + end + else + tb === value + end + end + if passed + true + else + message = "Property #{key} must be one of: #{to_be.map { |v| v.inspect }.join(", ")}! You passed #{value.inspect}." + unless errors.empty? + message << " Errors:\n#{errors.map { |m| "- #{m}" }.join("\n")}" + end + raise Exceptions::ValidationFailed, message + end + end + + # + # Method to mess with a value before it is validated and stored. + # + # Allows you to transform values into a canonical form that is easy to + # work with. + # + # This is passed the value to transform, and is run in the context of the + # instance (so it has access to other resource properties). It must return + # the value that will be stored in the instance. + # + # @example + # ```ruby + # property :x, Integer, coerce: { |v| v.to_i } + # ``` + # + def _pv_coerce(opts, key, coercer) + if opts.has_key?(key.to_s) + raise CannotValidateStaticallyError, "coerce must be evaluated for each resource." if self == Chef::Mixin::ParamsValidate + opts[key.to_s] = instance_exec(opts[key], &coercer) + elsif opts.has_key?(key.to_sym) + raise CannotValidateStaticallyError, "coerce must be evaluated for each resource." if self == Chef::Mixin::ParamsValidate + opts[key.to_sym] = instance_exec(opts[key], &coercer) + end + end + + # We allow Chef::Mixin::ParamsValidate.validate(), but we will raise an + # error if you try to do anything requiring there to be an actual resource. + # This way, you can statically validate things if you have constant validation + # (which is the norm). + extend self + + # Used by #set_or_return to avoid emitting a deprecation warning for + # "value nil" and to keep default stickiness working exactly the same + # @api private + class SetOrReturnProperty < (defined?(::Chef::Mixin::ParamsValidate::SetOrReturnProperty) ? ::Chef::Mixin::ParamsValidate::SetOrReturnProperty : Chef::Property) + def get(resource, nil_set: false) + value = super + # All values are sticky, frozen or not + if !is_set?(resource) + set_value(resource, value) + end + value + end + + def call(resource, value = NOT_PASSED) + # setting to nil does a get + if value.nil? && !explicitly_accepts_nil?(resource) + get(resource, nil_set: true) + else + super + end + end + end + end + end +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/powershell_out.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/powershell_out.rb new file mode 100644 index 0000000..b6b56f9 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/powershell_out.rb @@ -0,0 +1,117 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/mixin/powershell_out' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +#-- +# Copyright:: Copyright 2015-2016, Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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. + + +class Chef < (defined?(::Chef) ? ::Chef : Object) + module Mixin + CopiedFromChef.extend_chef_module(::Chef::Mixin, self) if defined?(::Chef::Mixin) + module PowershellOut + CopiedFromChef.extend_chef_module(::Chef::Mixin::PowershellOut, self) if defined?(::Chef::Mixin::PowershellOut) + include Chef::Mixin::ShellOut + include Chef::Mixin::WindowsArchitectureHelper + + # Run a command under powershell with the same API as shell_out. The + # options hash is extended to take an "architecture" flag which + # can be set to :i386 or :x86_64 to force the windows architecture. + # + # @param script [String] script to run + # @param options [Hash] options hash + # @return [Mixlib::Shellout] mixlib-shellout object + def powershell_out(*command_args) + script = command_args.first + options = command_args.last.is_a?(Hash) ? command_args.last : nil + + run_command_with_os_architecture(script, options) + end + + # Run a command under powershell with the same API as shell_out! + # (raises exceptions on errors) + # + # @param script [String] script to run + # @param options [Hash] options hash + # @return [Mixlib::Shellout] mixlib-shellout object + def powershell_out!(*command_args) + cmd = powershell_out(*command_args) + cmd.error! + cmd + end + + private + + # Helper function to run shell_out and wrap it with the correct + # flags to possibly disable WOW64 redirection (which we often need + # because chef-client runs as a 32-bit app on 64-bit windows). + # + # @param script [String] script to run + # @param options [Hash] options hash + # @return [Mixlib::Shellout] mixlib-shellout object + def run_command_with_os_architecture(script, options) + options ||= {} + options = options.dup + arch = options.delete(:architecture) + + with_os_architecture(nil, architecture: arch) do + shell_out( + build_powershell_command(script), + options + ) + end + end + + # Helper to build a powershell command around the script to run. + # + # @param script [String] script to run + # @retrurn [String] powershell command to execute + def build_powershell_command(script) + flags = [ + # Hides the copyright banner at startup. + "-NoLogo", + # Does not present an interactive prompt to the user. + "-NonInteractive", + # Does not load the Windows PowerShell profile. + "-NoProfile", + # always set the ExecutionPolicy flag + # see http://technet.microsoft.com/en-us/library/ee176961.aspx + "-ExecutionPolicy Unrestricted", + # Powershell will hang if STDIN is redirected + # http://connect.microsoft.com/PowerShell/feedback/details/572313/powershell-exe-can-hang-if-stdin-is-redirected + "-InputFormat None", + ] + + "powershell.exe #{flags.join(' ')} -Command \"#{script.gsub('"', '\"')}\"" + end + end + end +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/properties.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/properties.rb new file mode 100644 index 0000000..bdf9f7e --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/properties.rb @@ -0,0 +1,328 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/mixin/properties' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +require "chef_compat/copied_from_chef/chef/delayed_evaluator" +require "chef_compat/copied_from_chef/chef/mixin/params_validate" +require "chef_compat/copied_from_chef/chef/property" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + module Mixin + CopiedFromChef.extend_chef_module(::Chef::Mixin, self) if defined?(::Chef::Mixin) + module Properties + CopiedFromChef.extend_chef_module(::Chef::Mixin::Properties, self) if defined?(::Chef::Mixin::Properties) + module ClassMethods + CopiedFromChef.extend_chef_module(::Chef::Mixin::Properties::ClassMethods, self) if defined?(::Chef::Mixin::Properties::ClassMethods) + # + # The list of properties defined on this resource. + # + # Everything defined with `property` is in this list. + # + # @param include_superclass [Boolean] `true` to include properties defined + # on superclasses; `false` or `nil` to return the list of properties + # directly on this class. + # + # @return [Hash] The list of property names and types. + # + def properties(include_superclass = true) + if include_superclass + result = {} + ancestors.reverse_each { |c| result.merge!(c.properties(false)) if c.respond_to?(:properties) } + result + else + @properties ||= {} + end + end + + # + # Create a property on this resource class. + # + # If a superclass has this property, or if this property has already been + # defined by this resource, this will *override* the previous value. + # + # @param name [Symbol] The name of the property. + # @param type [Object,Array] The type(s) of this property. + # If present, this is prepended to the `is` validation option. + # @param options [Hash] Validation options. + # @option options [Object,Array] :is An object, or list of + # objects, that must match the value using Ruby's `===` operator + # (`options[:is].any? { |v| v === value }`). + # @option options [Object,Array] :equal_to An object, or list + # of objects, that must be equal to the value using Ruby's `==` + # operator (`options[:is].any? { |v| v == value }`) + # @option options [Regexp,Array] :regex An object, or + # list of objects, that must match the value with `regex.match(value)`. + # @option options [Class,Array] :kind_of A class, or + # list of classes, that the value must be an instance of. + # @option options [Hash] :callbacks A hash of + # messages -> procs, all of which match the value. The proc must + # return a truthy or falsey value (true means it matches). + # @option options [Symbol,Array] :respond_to A method + # name, or list of method names, the value must respond to. + # @option options [Symbol,Array] :cannot_be A property, + # or a list of properties, that the value cannot have (such as `:nil` or + # `:empty`). The method with a questionmark at the end is called on the + # value (e.g. `value.empty?`). If the value does not have this method, + # it is considered valid (i.e. if you don't respond to `empty?` we + # assume you are not empty). + # @option options [Proc] :coerce A proc which will be called to + # transform the user input to canonical form. The value is passed in, + # and the transformed value returned as output. Lazy values will *not* + # be passed to this method until after they are evaluated. Called in the + # context of the resource (meaning you can access other properties). + # @option options [Boolean] :required `true` if this property + # must be present; `false` otherwise. This is checked after the resource + # is fully initialized. + # @option options [Boolean] :name_property `true` if this + # property defaults to the same value as `name`. Equivalent to + # `default: lazy { name }`, except that #property_is_set? will + # return `true` if the property is set *or* if `name` is set. + # @option options [Boolean] :name_attribute Same as `name_property`. + # @option options [Object] :default The value this property + # will return if the user does not set one. If this is `lazy`, it will + # be run in the context of the instance (and able to access other + # properties). + # @option options [Boolean] :desired_state `true` if this property is + # part of desired state. Defaults to `true`. + # @option options [Boolean] :identity `true` if this property + # is part of object identity. Defaults to `false`. + # @option options [Boolean] :sensitive `true` if this property could + # contain sensitive information and whose value should be redacted + # in any resource reporting / auditing output. Defaults to `false`. + # + # @example Bare property + # property :x + # + # @example With just a type + # property :x, String + # + # @example With just options + # property :x, default: 'hi' + # + # @example With type and options + # property :x, String, default: 'hi' + # + def property(name, type = NOT_PASSED, **options) + name = name.to_sym + + options = options.inject({}) { |memo, (key, value)| memo[key.to_sym] = value; memo } + + options[:instance_variable_name] = :"@#{name}" if !options.has_key?(:instance_variable_name) + options[:name] = name + options[:declared_in] = self + + if type == NOT_PASSED + # If a type is not passed, the property derives from the + # superclass property (if any) + if properties.has_key?(name) + property = properties[name].derive(**options) + else + property = property_type(**options) + end + + # If a Property is specified, derive a new one from that. + elsif type.is_a?(Property) || (type.is_a?(Class) && type <= Property) + property = type.derive(**options) + + # If a primitive type was passed, combine it with "is" + else + if options[:is] + options[:is] = ([ type ] + [ options[:is] ]).flatten(1) + else + options[:is] = type + end + property = property_type(**options) + end + + local_properties = properties(false) + local_properties[name] = property + + property.emit_dsl + end + + # + # Create a reusable property type that can be used in multiple properties + # in different resources. + # + # @param options [Hash] Validation options. see #property for + # the list of options. + # + # @example + # property_type(default: 'hi') + # + def property_type(**options) + Property.derive(**options) + end + + # + # Create a lazy value for assignment to a default value. + # + # @param block The block to run when the value is retrieved. + # + # @return [Chef::DelayedEvaluator] The lazy value + # + def lazy(&block) + DelayedEvaluator.new(&block) + end + + # + # Get or set the list of desired state properties for this resource. + # + # State properties are properties that describe the desired state + # of the system, such as file permissions or ownership. + # In general, state properties are properties that could be populated by + # examining the state of the system (e.g., File.stat can tell you the + # permissions on an existing file). Contrarily, properties that are not + # "state properties" usually modify the way Chef itself behaves, for example + # by providing additional options for a package manager to use when + # installing a package. + # + # This list is used by the Chef client auditing system to extract + # information from resources to describe changes made to the system. + # + # This method is unnecessary when declaring properties with `property`; + # properties are added to state_properties by default, and can be turned off + # with `desired_state: false`. + # + # ```ruby + # property :x # part of desired state + # property :y, desired_state: false # not part of desired state + # ``` + # + # @param names [Array] A list of property names to set as desired + # state. + # + # @return [Array] All properties in desired state. + # + def state_properties(*names) + if !names.empty? + names = names.map { |name| name.to_sym }.uniq + + local_properties = properties(false) + # Add new properties to the list. + names.each do |name| + property = properties[name] + if !property + self.property name, instance_variable_name: false, desired_state: true + elsif !property.desired_state? + self.property name, desired_state: true + end + end + + # If state_attrs *excludes* something which is currently desired state, + # mark it as desired_state: false. + local_properties.each do |name, property| + if property.desired_state? && !names.include?(name) + self.property name, desired_state: false + end + end + end + + properties.values.select { |property| property.desired_state? } + end + + # + # Set the identity of this resource to a particular set of properties. + # + # This drives #identity, which returns data that uniquely refers to a given + # resource on the given node (in such a way that it can be correlated + # across Chef runs). + # + # This method is unnecessary when declaring properties with `property`; + # properties can be added to identity during declaration with + # `identity: true`. + # + # ```ruby + # property :x, identity: true # part of identity + # property :y # not part of identity + # ``` + # + # If no properties are marked as identity, "name" is considered the identity. + # + # @param names [Array] A list of property names to set as the identity. + # + # @return [Array] All identity properties. + # + def identity_properties(*names) + if !names.empty? + names = names.map { |name| name.to_sym } + + # Add or change properties that are not part of the identity. + names.each do |name| + property = properties[name] + if !property + self.property name, instance_variable_name: false, identity: true + elsif !property.identity? + self.property name, identity: true + end + end + + # If identity_properties *excludes* something which is currently part of + # the identity, mark it as identity: false. + properties.each do |name, property| + if property.identity? && !names.include?(name) + + self.property name, identity: false + end + end + end + + result = properties.values.select { |property| property.identity? } + result = [ properties[:name] ] if result.empty? + result + end + + def included(other) + other.extend ClassMethods + end + end + + def self.included(other) + other.extend ClassMethods + end + + include Chef::Mixin::ParamsValidate + + # + # Whether this property has been set (or whether it has a default that has + # been retrieved). + # + # @param name [Symbol] The name of the property. + # @return [Boolean] `true` if the property has been set. + # + def property_is_set?(name) + property = self.class.properties[name.to_sym] + raise ArgumentError, "Property #{name} is not defined in class #{self}" if !property + property.is_set?(self) + end + + # + # Clear this property as if it had never been set. It will thereafter return + # the default. + # been retrieved). + # + # @param name [Symbol] The name of the property. + # + def reset_property(name) + property = self.class.properties[name.to_sym] + raise ArgumentError, "Property #{name} is not defined in class #{self}" if !property + property.reset(self) + end + end + end +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/property.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/property.rb new file mode 100644 index 0000000..3399596 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/property.rb @@ -0,0 +1,713 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/property' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: John Keiser +# Copyright:: Copyright 2015-2016, John Keiser. +# License:: Apache License, Version 2.0 +# +# 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. +# + +require "chef_compat/copied_from_chef/chef/delayed_evaluator" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + # + # Type and validation information for a property on a resource. + # + # A property named "x" manipulates the "@x" instance variable on a + # resource. The *presence* of the variable (`instance_variable_defined?(@x)`) + # tells whether the variable is defined; it may have any actual value, + # constrained only by validation. + # + # Properties may have validation, defaults, and coercion, and have full + # support for lazy values. + # + # @see Chef::Resource.property + # @see Chef::DelayedEvaluator + # + class Property < (defined?(::Chef::Property) ? ::Chef::Property : Object) + # + # Create a reusable property type that can be used in multiple properties + # in different resources. + # + # @param options [Hash] Validation options. See Chef::Resource.property for + # the list of options. + # + # @example + # Property.derive(default: 'hi') + # + def self.derive(**options) + new(**options) + end + + # + # Create a new property. + # + # @param options [Hash] Property options, including + # control options here, as well as validation options (see + # Chef::Mixin::ParamsValidate#validate for a description of validation + # options). + # @option options [Symbol] :name The name of this property. + # @option options [Class] :declared_in The class this property comes from. + # @option options [Symbol] :instance_variable_name The instance variable + # tied to this property. Must include a leading `@`. Defaults to `@`. + # `nil` means the property is opaque and not tied to a specific instance + # variable. + # @option options [Boolean] :desired_state `true` if this property is part of desired + # state. Defaults to `true`. + # @option options [Boolean] :identity `true` if this property is part of object + # identity. Defaults to `false`. + # @option options [Boolean] :name_property `true` if this + # property defaults to the same value as `name`. Equivalent to + # `default: lazy { name }`, except that #property_is_set? will + # return `true` if the property is set *or* if `name` is set. + # @option options [Boolean] :nillable `true` opt-in to Chef-13 style behavior where + # attempting to set a nil value will really set a nil value instead of issuing + # a warning and operating like a getter + # @option options [Object] :default The value this property + # will return if the user does not set one. If this is `lazy`, it will + # be run in the context of the instance (and able to access other + # properties) and cached. If not, the value will be frozen with Object#freeze + # to prevent users from modifying it in an instance. + # @option options [Proc] :coerce A proc which will be called to + # transform the user input to canonical form. The value is passed in, + # and the transformed value returned as output. Lazy values will *not* + # be passed to this method until after they are evaluated. Called in the + # context of the resource (meaning you can access other properties). + # @option options [Boolean] :required `true` if this property + # must be present; `false` otherwise. This is checked after the resource + # is fully initialized. + # + def initialize(**options) +super if defined?(::Chef::Property) + options = options.inject({}) { |memo, (key, value)| memo[key.to_sym] = value; memo } + @options = options + options[:name] = options[:name].to_sym if options[:name] + options[:instance_variable_name] = options[:instance_variable_name].to_sym if options[:instance_variable_name] + + # Replace name_attribute with name_property + if options.has_key?(:name_attribute) + # If we have both name_attribute and name_property and they differ, raise an error + if options.has_key?(:name_property) + raise ArgumentError, "Cannot specify both name_property and name_attribute together on property #{self}." + end + # replace name_property with name_attribute in place + options = Hash[options.map { |k, v| k == :name_attribute ? [ :name_property, v ] : [ k, v ] }] + @options = options + end + + # Only pick the first of :default, :name_property and :name_attribute if + # more than one is specified. + if options.has_key?(:default) && options[:name_property] + if options[:default].nil? || options.keys.index(:name_property) < options.keys.index(:default) + options.delete(:default) + preferred_default = :name_property + else + options.delete(:name_property) + preferred_default = :default + end + Chef.log_deprecation("Cannot specify both default and name_property together on property #{self}. Only one (#{preferred_default}) will be obeyed. In Chef 13, this will become an error. Please remove one or the other from the property.") + end + + # Validate the default early, so the user gets a good error message, and + # cache it so we don't do it again if so + begin + # If we can validate it all the way to output, do it. + @stored_default = input_to_stored_value(nil, default, is_default: true) + rescue Chef::Exceptions::CannotValidateStaticallyError + # If the validation is not static (i.e. has procs), we will have to + # coerce and validate the default each time we run + end + end + + def to_s + "#{name || ""}#{declared_in ? " of resource #{declared_in.resource_name}" : ""}" + end + + # + # The name of this property. + # + # @return [String] + # + def name + options[:name] + end + + # + # The class this property was defined in. + # + # @return [Class] + # + def declared_in + options[:declared_in] + end + + # + # The instance variable associated with this property. + # + # Defaults to `@` + # + # @return [Symbol] + # + def instance_variable_name + if options.has_key?(:instance_variable_name) + options[:instance_variable_name] + elsif name + :"@#{name}" + end + end + + # + # The raw default value for this resource. + # + # Does not coerce or validate the default. Does not evaluate lazy values. + # + # Defaults to `lazy { name }` if name_property is true; otherwise defaults to + # `nil` + # + def default + return options[:default] if options.has_key?(:default) + return Chef::DelayedEvaluator.new { name } if name_property? + nil + end + + # + # Whether this is part of the resource's natural identity or not. + # + # @return [Boolean] + # + def identity? + options[:identity] + end + + # + # Whether this is part of desired state or not. + # + # Defaults to true. + # + # @return [Boolean] + # + def desired_state? + return true if !options.has_key?(:desired_state) + options[:desired_state] + end + + # + # Whether this is name_property or not. + # + # @return [Boolean] + # + def name_property? + options[:name_property] + end + + # + # Whether this property has a default value. + # + # @return [Boolean] + # + def has_default? + options.has_key?(:default) || name_property? + end + + # + # Whether this property is required or not. + # + # @return [Boolean] + # + def required? + options[:required] + end + + # + # Whether this property is sensitive or not. + # + # Defaults to false. + # + # @return [Boolean] + # + def sensitive? + options.fetch(:sensitive, false) + end + + # + # Validation options. (See Chef::Mixin::ParamsValidate#validate.) + # + # @return [Hash] + # + def validation_options + @validation_options ||= options.reject do |k, v| + [:declared_in, :name, :instance_variable_name, :desired_state, :identity, :default, :name_property, :coerce, :required, :nillable, :sensitive].include?(k) + end + end + + # + # Handle the property being called. + # + # The base implementation does the property get-or-set: + # + # ```ruby + # resource.myprop # get + # resource.myprop value # set + # ``` + # + # Subclasses may implement this with any arguments they want, as long as + # the corresponding DSL calls it correctly. + # + # @param resource [Chef::Resource] The resource to get the property from. + # @param value The value to set (or NOT_PASSED if it is a get). + # + # @return The current value of the property. If it is a `set`, lazy values + # will be returned without running, validating or coercing. If it is a + # `get`, the non-lazy, coerced, validated value will always be returned. + # + def call(resource, value = NOT_PASSED) + if value == NOT_PASSED + return get(resource) + end + + if value.nil? && !nillable? + # In Chef 12, value(nil) does a *get* instead of a set, so we + # warn if the value would have been changed. In Chef 13, it will be + # equivalent to value = nil. + result = get(resource, nil_set: true) + + # Warn about this becoming a set in Chef 13. + begin + input_to_stored_value(resource, value) + # If nil is valid, and it would change the value, warn that this will change to a set. + if !result.nil? + Chef.log_deprecation("An attempt was made to change #{name} from #{result.inspect} to nil by calling #{name}(nil). In Chef 12, this does a get rather than a set. In Chef 13, this will change to set the value to nil.") + end + rescue Chef::Exceptions::DeprecatedFeatureError + raise + rescue + # If nil is invalid, warn that this will become an error. + Chef.log_deprecation("nil is an invalid value for #{self}. In Chef 13, this warning will change to an error. Error: #{$!}") + end + + result + else + # Anything else, such as myprop(value) is a set + set(resource, value) + end + end + + # + # Get the property value from the resource, handling lazy values, + # defaults, and validation. + # + # - If the property's value is lazy, it is evaluated, coerced and validated. + # - If the property has no value, and is required, raises ValidationFailed. + # - If the property has no value, but has a lazy default, it is evaluated, + # coerced and validated. If the evaluated value is frozen, the resulting + # - If the property has no value, but has a default, the default value + # will be returned and frozen. If the default value is lazy, it will be + # evaluated, coerced and validated, and the result stored in the property. + # - If the property has no value, but is name_property, `resource.name` + # is retrieved, coerced, validated and stored in the property. + # - Otherwise, `nil` is returned. + # + # @param resource [Chef::Resource] The resource to get the property from. + # + # @return The value of the property. + # + # @raise Chef::Exceptions::ValidationFailed If the value is invalid for + # this property, or if the value is required and not set. + # + def get(resource, nil_set: false) + # If it's set, return it (and evaluate any lazy values) + if is_set?(resource) + value = get_value(resource) + value = stored_value_to_output(resource, value) + + else + # We are getting the default value. + + # If the user does something like this: + # + # ``` + # class MyResource < Chef::Resource + # property :content + # action :create do + # file '/x.txt' do + # content content + # end + # end + # end + # ``` + # + # It won't do what they expect. This checks whether you try to *read* + # `content` while we are compiling the resource. + if !nil_set && + resource.respond_to?(:resource_initializing) && + resource.resource_initializing && + resource.respond_to?(:enclosing_provider) && + resource.enclosing_provider && + resource.enclosing_provider.new_resource && + resource.enclosing_provider.new_resource.respond_to?(name) + Chef::Log.warn("#{Chef::Log.caller_location}: property #{name} is declared in both #{resource} and #{resource.enclosing_provider}. Use new_resource.#{name} instead. At #{Chef::Log.caller_location}") + end + + if has_default? + # If we were able to cache the stored_default, grab it. + if defined?(@stored_default) + value = @stored_default + else + # Otherwise, we have to validate it now. + value = input_to_stored_value(resource, default, is_default: true) + end + value = stored_value_to_output(resource, value, is_default: true) + + # If the value is mutable (non-frozen), we set it on the instance + # so that people can mutate it. (All constant default values are + # frozen.) + if !value.frozen? && !value.nil? + set_value(resource, value) + end + + value + + elsif required? + raise Chef::Exceptions::ValidationFailed, "#{name} is required" + end + end + end + + # + # Set the value of this property in the given resource. + # + # Non-lazy values are coerced and validated before being set. Coercion + # and validation of lazy values is delayed until they are first retrieved. + # + # @param resource [Chef::Resource] The resource to set this property in. + # @param value The value to set. + # + # @return The value that was set, after coercion (if lazy, still returns + # the lazy value) + # + # @raise Chef::Exceptions::ValidationFailed If the value is invalid for + # this property. + # + def set(resource, value) + set_value(resource, input_to_stored_value(resource, value)) + end + + # + # Find out whether this property has been set. + # + # This will be true if: + # - The user explicitly set the value + # - The property has a default, and the value was retrieved. + # + # From this point of view, it is worth looking at this as "what does the + # user think this value should be." In order words, if the user grabbed + # the value, even if it was a default, they probably based calculations on + # it. If they based calculations on it and the value changes, the rest of + # the world gets inconsistent. + # + # @param resource [Chef::Resource] The resource to get the property from. + # + # @return [Boolean] + # + def is_set?(resource) + value_is_set?(resource) + end + + # + # Reset the value of this property so that is_set? will return false and the + # default will be returned in the future. + # + # @param resource [Chef::Resource] The resource to get the property from. + # + def reset(resource) + reset_value(resource) + end + + # + # Coerce an input value into canonical form for the property. + # + # After coercion, the value is suitable for storage in the resource. + # You must validate values after coercion, however. + # + # Does no special handling for lazy values. + # + # @param resource [Chef::Resource] The resource we're coercing against + # (to provide context for the coerce). + # @param value The value to coerce. + # + # @return The coerced value. + # + # @raise Chef::Exceptions::ValidationFailed If the value is invalid for + # this property. + # + def coerce(resource, value) + if options.has_key?(:coerce) + # If we have no default value, `nil` is never coerced or validated + unless !has_default? && value.nil? + value = exec_in_resource(resource, options[:coerce], value) + end + end + value + end + + # + # Validate a value. + # + # Calls Chef::Mixin::ParamsValidate#validate with #validation_options as + # options. + # + # @param resource [Chef::Resource] The resource we're validating against + # (to provide context for the validate). + # @param value The value to validate. + # + # @raise Chef::Exceptions::ValidationFailed If the value is invalid for + # this property. + # + def validate(resource, value) + # If we have no default value, `nil` is never coerced or validated + unless value.nil? && !has_default? + if resource + resource.validate({ name => value }, { name => validation_options }) + else + name = self.name || :property_type + Chef::Mixin::ParamsValidate.validate({ name => value }, { name => validation_options }) + end + end + end + + # + # Derive a new Property that is just like this one, except with some added or + # changed options. + # + # @param options [Hash] List of options that would be passed + # to #initialize. + # + # @return [Property] The new property type. + # + def derive(**modified_options) + # Since name_property, name_attribute and default override each other, + # if you specify one of them in modified_options it overrides anything in + # the original options. + options = self.options + if modified_options.has_key?(:name_property) || + modified_options.has_key?(:name_attribute) || + modified_options.has_key?(:default) + options = options.reject { |k, v| k == :name_attribute || k == :name_property || k == :default } + end + self.class.new(options.merge(modified_options)) + end + + # + # Emit the DSL for this property into the resource class (`declared_in`). + # + # Creates a getter and setter for the property. + # + def emit_dsl + # We don't create the getter/setter if it's a custom property; we will + # be using the existing getter/setter to manipulate it instead. + return if !instance_variable_name + + # We prefer this form because the property name won't show up in the + # stack trace if you use `define_method`. + declared_in.class_eval <<-EOM, __FILE__, __LINE__ + 1 + def #{name}(value=NOT_PASSED) + raise "Property `#{name}` of `\#{self}` was incorrectly passed a block. Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block_given? + self.class.properties[#{name.inspect}].call(self, value) + end + def #{name}=(value) + raise "Property `#{name}` of `\#{self}` was incorrectly passed a block. Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block_given? + self.class.properties[#{name.inspect}].set(self, value) + end + EOM + rescue SyntaxError + # If the name is not a valid ruby name, we use define_method. + declared_in.define_method(name) do |value = NOT_PASSED, &block| + raise "Property `#{name}` of `#{self}` was incorrectly passed a block! Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block + self.class.properties[name].call(self, value) + end + declared_in.define_method("#{name}=") do |value, &block| + raise "Property `#{name}` of `#{self}` was incorrectly passed a block! Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block + self.class.properties[name].set(self, value) + end + end + + # + # The options this Property will use for get/set behavior and validation. + # + # @see #initialize for a list of valid options. + # + attr_reader :options + + # + # Find out whether this type accepts nil explicitly. + # + # A type accepts nil explicitly if "is" allows nil, it validates as nil, *and* is not simply + # an empty type. + # + # A type is presumed to accept nil if it does coercion (which must handle nil). + # + # These examples accept nil explicitly: + # ```ruby + # property :a, [ String, nil ] + # property :a, [ String, NilClass ] + # property :a, [ String, proc { |v| v.nil? } ] + # ``` + # + # This does not (because the "is" doesn't exist or doesn't have nil): + # + # ```ruby + # property :x, String + # ``` + # + # These do not, even though nil would validate fine (because they do not + # have "is"): + # + # ```ruby + # property :a + # property :a, equal_to: [ 1, 2, 3, nil ] + # property :a, kind_of: [ String, NilClass ] + # property :a, respond_to: [ ] + # property :a, callbacks: { "a" => proc { |v| v.nil? } } + # ``` + # + # @param resource [Chef::Resource] The resource we're coercing against + # (to provide context for the coerce). + # + # @return [Boolean] Whether this value explicitly accepts nil. + # + # @api private + def explicitly_accepts_nil?(resource) + options.has_key?(:coerce) || + (options.has_key?(:is) && resource.send(:_pv_is, { name => nil }, name, options[:is], raise_error: false)) + end + + # @api private + def get_value(resource) + if instance_variable_name + resource.instance_variable_get(instance_variable_name) + else + resource.send(name) + end + end + + # @api private + def set_value(resource, value) + if instance_variable_name + resource.instance_variable_set(instance_variable_name, value) + else + resource.send(name, value) + end + end + + # @api private + def value_is_set?(resource) + if instance_variable_name + resource.instance_variable_defined?(instance_variable_name) + else + true + end + end + + # @api private + def reset_value(resource) + if instance_variable_name + if value_is_set?(resource) + resource.remove_instance_variable(instance_variable_name) + end + else + raise ArgumentError, "Property #{name} has no instance variable defined and cannot be reset" + end + end + + private + + def exec_in_resource(resource, proc, *args) + if resource + if proc.arity > args.size + value = proc.call(resource, *args) + else + value = resource.instance_exec(*args, &proc) + end + else + # If we don't have a resource yet, we can't exec in resource! + raise Chef::Exceptions::CannotValidateStaticallyError, "Cannot validate or coerce without a resource" + end + end + + def input_to_stored_value(resource, value, is_default: false) + unless value.is_a?(DelayedEvaluator) + value = coerce_and_validate(resource, value, is_default: is_default) + end + value + end + + def stored_value_to_output(resource, value, is_default: false) + # Crack open lazy values before giving the result to the user + if value.is_a?(DelayedEvaluator) + value = exec_in_resource(resource, value) + value = coerce_and_validate(resource, value, is_default: is_default) + end + value + end + + # Coerces and validates the value. If the value is a default, it will warn + # the user that invalid defaults are bad mmkay, and return it as if it were + # valid. + def coerce_and_validate(resource, value, is_default: false) + result = coerce(resource, value) + begin + # If the input is from a default, we need to emit an invalid default warning on validate. + validate(resource, result) + rescue Chef::Exceptions::CannotValidateStaticallyError + # This one gets re-raised + raise + rescue + # Anything else is just an invalid default: in those cases, we just + # warn and return the (possibly coerced) value to the user. + if is_default + if value.nil? + Chef.log_deprecation("Default value nil is invalid for property #{self}. Possible fixes: 1. Remove 'default: nil' if nil means 'undefined'. 2. Set a valid default value if there is a reasonable one. 3. Allow nil as a valid value of your property (for example, 'property #{name.inspect}, [ String, nil ], default: nil'). Error: #{$!}") + else + Chef.log_deprecation("Default value #{value.inspect} is invalid for property #{self}. In Chef 13 this will become an error: #{$!}.") + end + else + raise + end + end + + result + end + + def nillable? + !!options[:nillable] + end + end +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider.rb new file mode 100644 index 0000000..7ccf87b --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider.rb @@ -0,0 +1,164 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/provider' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +require "chef_compat/copied_from_chef/chef/dsl/core" +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Provider < (defined?(::Chef::Provider) ? ::Chef::Provider : Object) + include Chef::DSL::Core + attr_accessor :action + def initialize(new_resource, run_context) +super if defined?(::Chef::Provider) + @new_resource = new_resource + @action = action + @current_resource = nil + @run_context = run_context + @converge_actions = nil + + @recipe_name = nil + @cookbook_name = nil + self.class.include_resource_dsl_module(new_resource) + end + def converge_if_changed(*properties, &converge_block) + if !converge_block + raise ArgumentError, "converge_if_changed must be passed a block!" + end + + properties = new_resource.class.state_properties.map { |p| p.name } if properties.empty? + properties = properties.map { |p| p.to_sym } + if current_resource + # Collect the list of modified properties + specified_properties = properties.select { |property| new_resource.property_is_set?(property) } + modified = specified_properties.select { |p| new_resource.send(p) != current_resource.send(p) } + if modified.empty? + properties_str = if sensitive + specified_properties.join(", ") + else + specified_properties.map { |p| "#{p}=#{new_resource.send(p).inspect}" }.join(", ") + end + Chef::Log.debug("Skipping update of #{new_resource}: has not changed any of the specified properties #{properties_str}.") + return false + end + + # Print the pretty green text and run the block + property_size = modified.map { |p| p.size }.max + modified.map! do |p| + properties_str = if sensitive + "(suppressed sensitive property)" + else + "#{new_resource.send(p).inspect} (was #{current_resource.send(p).inspect})" + end + " set #{p.to_s.ljust(property_size)} to #{properties_str}" + end + converge_by([ "update #{current_resource.identity}" ] + modified, &converge_block) + + else + # The resource doesn't exist. Mark that we are *creating* this, and + # write down any properties we are setting. + property_size = properties.map { |p| p.size }.max + created = properties.map do |property| + default = " (default value)" unless new_resource.property_is_set?(property) + properties_str = if sensitive + "(suppressed sensitive property)" + else + new_resource.send(property).inspect + end + " set #{property.to_s.ljust(property_size)} to #{properties_str}#{default}" + end + + converge_by([ "create #{new_resource.identity}" ] + created, &converge_block) + end + true + end + def self.include_resource_dsl(include_resource_dsl) + @include_resource_dsl = include_resource_dsl + end + def self.include_resource_dsl_module(resource) + if @include_resource_dsl && !defined?(@included_resource_dsl_module) + provider_class = self + @included_resource_dsl_module = Module.new do + extend Forwardable + define_singleton_method(:to_s) { "forwarder module for #{provider_class}" } + define_singleton_method(:inspect) { to_s } + # Add a delegator for each explicit property that will get the *current* value + # of the property by default instead of the *actual* value. + resource.class.properties.each do |name, property| + class_eval(<<-EOM, __FILE__, __LINE__) + def #{name}(*args, &block) + # If no arguments were passed, we process "get" by defaulting + # the value to current_resource, not new_resource. This helps + # avoid issues where resources accidentally overwrite perfectly + # valid stuff with default values. + if args.empty? && !block + if !new_resource.property_is_set?(__method__) && current_resource + return current_resource.public_send(__method__) + end + end + new_resource.public_send(__method__, *args, &block) + end + EOM + end + dsl_methods = + resource.class.public_instance_methods + + resource.class.protected_instance_methods - + provider_class.instance_methods - + resource.class.properties.keys + def_delegators(:new_resource, *dsl_methods) + end + include @included_resource_dsl_module + end + end + def self.use_inline_resources + extend InlineResources::ClassMethods + include InlineResources + end + module InlineResources + CopiedFromChef.extend_chef_module(::Chef::Provider::InlineResources, self) if defined?(::Chef::Provider::InlineResources) + def compile_and_converge_action(&block) + old_run_context = run_context + @run_context = run_context.create_child + return_value = instance_eval(&block) + Chef::Runner.new(run_context).converge + return_value + ensure + if run_context.resource_collection.any? { |r| r.updated? } + new_resource.updated_by_last_action(true) + end + @run_context = old_run_context + end + module ClassMethods + CopiedFromChef.extend_chef_module(::Chef::Provider::InlineResources::ClassMethods, self) if defined?(::Chef::Provider::InlineResources::ClassMethods) + def action(name, &block) + # We need the block directly in a method so that `super` works + define_method("compile_action_#{name}", &block) + # We try hard to use `def` because define_method doesn't show the method name in the stack. + begin + class_eval <<-EOM + def action_#{name} + compile_and_converge_action { compile_action_#{name} } + end + EOM + rescue SyntaxError + define_method("action_#{name}") { send("compile_action_#{name}") } + end + end + end + end + protected + end +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/apt_repository.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/apt_repository.rb new file mode 100644 index 0000000..ccc07c4 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/apt_repository.rb @@ -0,0 +1,269 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/provider/apt_repository' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Thom May () +# Copyright:: Copyright (c) 2016 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +require "chef_compat/copied_from_chef/chef/resource" +require "chef_compat/copied_from_chef/chef/dsl/declare_resource" +require "chef_compat/copied_from_chef/chef/provider/noop" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Provider < (defined?(::Chef::Provider) ? ::Chef::Provider : Object) + class AptRepository < (defined?(::Chef::Provider::AptRepository) ? ::Chef::Provider::AptRepository : Chef::Provider) + use_inline_resources + + include Chef::Mixin::ShellOut + extend Chef::Mixin::Which + + provides :apt_repository do + which("apt-get") + end + + def whyrun_supported? + true + end + + def load_current_resource + end + + action :add do + unless new_resource.key.nil? + if is_key_id?(new_resource.key) && !has_cookbook_file?(new_resource.key) + install_key_from_keyserver + else + install_key_from_uri + end + end + + declare_resource(:execute, "apt-cache gencaches") do + ignore_failure true + action :nothing + end + + declare_resource(:apt_update, new_resource.name) do + ignore_failure true + action :nothing + end + + components = if is_ppa_url?(new_resource.uri) && new_resource.components.empty? + "main" + else + new_resource.components + end + + repo = build_repo( + new_resource.uri, + new_resource.distribution, + components, + new_resource.trusted, + new_resource.arch, + new_resource.deb_src + ) + + declare_resource(:file, "/etc/apt/sources.list.d/#{new_resource.name}.list") do + owner "root" + group "root" + mode "0644" + content repo + sensitive new_resource.sensitive + action :create + notifies :run, "execute[apt-cache gencaches]", :immediately + notifies :update, "apt_update[#{new_resource.name}]", :immediately if new_resource.cache_rebuild + end + end + + action :remove do + if ::File.exist?("/etc/apt/sources.list.d/#{new_resource.name}.list") + converge_by "Removing #{new_resource.name} repository from /etc/apt/sources.list.d/" do + declare_resource(:file, "/etc/apt/sources.list.d/#{new_resource.name}.list") do + sensitive new_resource.sensitive + action :delete + notifies :update, "apt_update[#{new_resource.name}]", :immediately if new_resource.cache_rebuild + end + + declare_resource(:apt_update, new_resource.name) do + ignore_failure true + action :nothing + end + + end + end + end + + def is_key_id?(id) + id = id[2..-1] if id.start_with?("0x") + id =~ /^\h+$/ && [8, 16, 40].include?(id.length) + end + + def extract_fingerprints_from_cmd(cmd) + so = shell_out(cmd) + so.run_command + so.stdout.split(/\n/).map do |t| + if z = t.match(/^ +Key fingerprint = ([0-9A-F ]+)/) + z[1].split.join + end + end.compact + end + + def key_is_valid?(cmd, key) + valid = true + + so = shell_out(cmd) + so.run_command + so.stdout.split(/\n/).map do |t| + if t =~ %r{^\/#{key}.*\[expired: .*\]$} + Chef::Log.debug "Found expired key: #{t}" + valid = false + break + end + end + + Chef::Log.debug "key #{key} #{valid ? "is valid" : "is not valid"}" + valid + end + + def cookbook_name + new_resource.cookbook || new_resource.cookbook_name + end + + def has_cookbook_file?(fn) + run_context.has_cookbook_file_in_cookbook?(cookbook_name, fn) + end + + def no_new_keys?(file) + installed_keys = extract_fingerprints_from_cmd("apt-key finger") + proposed_keys = extract_fingerprints_from_cmd("gpg --with-fingerprint #{file}") + (installed_keys & proposed_keys).sort == proposed_keys.sort + end + + def install_key_from_uri + key_name = new_resource.key.gsub(/[^0-9A-Za-z\-]/, "_") + cached_keyfile = ::File.join(Chef::Config[:file_cache_path], key_name) + type = if new_resource.key.start_with?("http") + :remote_file + elsif has_cookbook_file?(new_resource.key) + :cookbook_file + else + raise Chef::Exceptions::FileNotFound, "Cannot locate key file" + end + + declare_resource(type, cached_keyfile) do + source new_resource.key + mode "0644" + sensitive new_resource.sensitive + action :create + end + + raise "The key #{cached_keyfile} is invalid and cannot be used to verify an apt repository." unless key_is_valid?("gpg #{cached_keyfile}", "") + + declare_resource(:execute, "apt-key add #{cached_keyfile}") do + sensitive new_resource.sensitive + action :run + not_if do + no_new_keys?(cached_keyfile) + end + notifies :run, "execute[apt-cache gencaches]", :immediately + end + end + + def install_key_from_keyserver(key = new_resource.key, keyserver = new_resource.keyserver) + cmd = "apt-key adv --recv" + cmd << " --keyserver-options http-proxy=#{new_resource.key_proxy}" if new_resource.key_proxy + cmd << " --keyserver " + cmd << if keyserver.start_with?("hkp://") + keyserver + else + "hkp://#{keyserver}:80" + end + + cmd << " #{key}" + + declare_resource(:execute, "install-key #{key}") do + command cmd + sensitive new_resource.sensitive + not_if do + present = extract_fingerprints_from_cmd("apt-key finger").any? do |fp| + fp.end_with? key.upcase + end + present && key_is_valid?("apt-key list", key.upcase) + end + notifies :run, "execute[apt-cache gencaches]", :immediately + end + + raise "The key #{key} is invalid and cannot be used to verify an apt repository." unless key_is_valid?("apt-key list", key.upcase) + end + + def install_ppa_key(owner, repo) + url = "https://launchpad.net/api/1.0/~#{owner}/+archive/#{repo}" + key_id = Chef::HTTP::Simple.new(url).get("signing_key_fingerprint").delete('"') + install_key_from_keyserver(key_id, "keyserver.ubuntu.com") + rescue Net::HTTPServerException => e + raise "Could not access Launchpad ppa API: #{e.message}" + end + + def is_ppa_url?(url) + url.start_with?("ppa:") + end + + def make_ppa_url(ppa) + return unless is_ppa_url?(ppa) + owner, repo = ppa[4..-1].split("/") + repo ||= "ppa" + + install_ppa_key(owner, repo) + "http://ppa.launchpad.net/#{owner}/#{repo}/ubuntu" + end + + def build_repo(uri, distribution, components, trusted, arch, add_src = false) + uri = make_ppa_url(uri) if is_ppa_url?(uri) + + uri = '"' + uri + '"' unless uri.start_with?("'", '"') + components = Array(components).join(" ") + options = [] + options << "arch=#{arch}" if arch + options << "trusted=yes" if trusted + optstr = unless options.empty? + "[" + options.join(" ") + "]" + end + info = [ optstr, uri, distribution, components ].compact.join(" ") + repo = "deb #{info}\n" + repo << "deb-src #{info}\n" if add_src + repo + end + end + end +end + +Chef::Provider::Noop.provides :apt_repository +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/apt_update.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/apt_update.rb new file mode 100644 index 0000000..677cb57 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/apt_update.rb @@ -0,0 +1,105 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/provider/apt_update' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Thom May () +# Copyright:: Copyright (c) 2016 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +require "chef_compat/copied_from_chef/chef/provider" +require "chef_compat/copied_from_chef/chef/provider/noop" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Provider < (defined?(::Chef::Provider) ? ::Chef::Provider : Object) + class AptUpdate < (defined?(::Chef::Provider::AptUpdate) ? ::Chef::Provider::AptUpdate : Chef::Provider) + use_inline_resources + + extend Chef::Mixin::Which + + provides :apt_update do + which("apt-get") + end + + APT_CONF_DIR = "/etc/apt/apt.conf.d" + STAMP_DIR = "/var/lib/apt/periodic" + + def whyrun_supported? + true + end + + def load_current_resource + end + + action :periodic do + if !apt_up_to_date? + converge_by "update new lists of packages" do + do_update + end + end + end + + action :update do + converge_by "force update new lists of packages" do + do_update + end + end + + private + + # Determines whether we need to run `apt-get update` + # + # @return [Boolean] + def apt_up_to_date? + ::File.exist?("#{STAMP_DIR}/update-success-stamp") && + ::File.mtime("#{STAMP_DIR}/update-success-stamp") > Time.now - new_resource.frequency + end + + def do_update + [STAMP_DIR, APT_CONF_DIR].each do |d| + declare_resource(:directory, d) do + recursive true + end + end + + declare_resource(:file, "#{APT_CONF_DIR}/15update-stamp") do + content "APT::Update::Post-Invoke-Success {\"touch #{STAMP_DIR}/update-success-stamp 2>/dev/null || true\";};\n" + action :create_if_missing + end + + declare_resource(:execute, "apt-get -q update") + end + + end + end +end + +Chef::Provider::Noop.provides :apt_update +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/noop.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/noop.rb new file mode 100644 index 0000000..87c34e6 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/noop.rb @@ -0,0 +1,56 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/provider/noop' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Thom May () +# Copyright:: Copyright (c) 2016 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Provider < (defined?(::Chef::Provider) ? ::Chef::Provider : Object) + class Noop < (defined?(::Chef::Provider::Noop) ? ::Chef::Provider::Noop : Chef::Provider) + def load_current_resource; end + + def respond_to_missing?(method_sym, include_private = false) + method_sym.to_s.start_with?("action_") || super + end + + def method_missing(method_sym, *arguments, &block) + if method_sym.to_s =~ /^action_/ + Chef::Log.debug("NoOp-ing for #{method_sym}") + else + super + end + end + end + end +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/support/yum_repo.erb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/support/yum_repo.erb new file mode 100644 index 0000000..6f13255 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/support/yum_repo.erb @@ -0,0 +1,132 @@ +# This file was generated by Chef +# Do NOT modify this file by hand. + +[<%= @config.repositoryid %>] +name=<%= @config.description %> +<% if @config.baseurl %> +baseurl=<%= case @config.baseurl + when Array + @config.baseurl.join("\n") + else + @config.baseurl + end %> +<% end -%> +<% if @config.cost %> +cost=<%= @config.cost %> +<% end %> +<% if @config.enabled %> +enabled=1 +<% else %> +enabled=0 +<% end %> +<% if @config.enablegroups %> +enablegroups=1 +<% end %> +<% if @config.exclude %> +exclude=<%= @config.exclude %> +<% end %> +<% if @config.failovermethod %> +failovermethod=<%= @config.failovermethod %> +<% end %> +<% if @config.fastestmirror_enabled %> +fastestmirror_enabled=1 +<% else %> +fastestmirror_enabled=0 +<% end %> +<% if @config.gpgcheck %> +gpgcheck=1 +<% else %> +gpgcheck=0 +<% end %> +<% if @config.gpgkey %> +gpgkey=<%= case @config.gpgkey + when Array + @config.gpgkey.join("\n ") + else + @config.gpgkey + end %> +<% end -%> +<% if @config.http_caching %> +http_caching=<%= @config.http_caching %> +<% end %> +<% if @config.include_config %> +include=<%= @config.include_config %> +<% end %> +<% if @config.includepkgs %> +includepkgs=<%= @config.includepkgs %> +<% end %> +<% if @config.keepalive %> +keepalive=1 +<% end %> +<% if @config.metadata_expire %> +metadata_expire=<%= @config.metadata_expire %> +<% end %> +<% if @config.mirrorlist %> +mirrorlist=<%= @config.mirrorlist %> +<% end %> +<% if @config.mirror_expire %> +mirror_expire=<%= @config.mirror_expire %> +<% end %> +<% if @config.mirrorlist_expire %> +mirrorlist_expire=<%= @config.mirrorlist_expire %> +<% end %> +<% if @config.priority %> +priority=<%= @config.priority %> +<% end %> +<% if @config.proxy %> +proxy=<%= @config.proxy %> +<% end %> +<% if @config.proxy_username %> +proxy_username=<%= @config.proxy_username %> +<% end %> +<% if @config.proxy_password %> +proxy_password=<%= @config.proxy_password %> +<% end %> +<% if @config.username %> +username=<%= @config.username %> +<% end %> +<% if @config.password %> +password=<%= @config.password %> +<% end %> +<% if @config.repo_gpgcheck %> +repo_gpgcheck=1 +<% end %> +<% if @config.max_retries %> +retries=<%= @config.max_retries %> +<% end %> +<% if @config.report_instanceid %> +report_instanceid=<%= @config.report_instanceid %> +<% end %> +<% if @config.skip_if_unavailable %> +skip_if_unavailable=1 +<% end %> +<% if @config.sslcacert %> +sslcacert=<%= @config.sslcacert %> +<% end %> +<% if @config.sslclientcert %> +sslclientcert=<%= @config.sslclientcert %> +<% end %> +<% if @config.sslclientkey %> +sslclientkey=<%= @config.sslclientkey %> +<% end %> +<% unless @config.sslverify.nil? %> +sslverify=<%= ( @config.sslverify ) ? 'true' : 'false' %> +<% end %> +<% if @config.timeout %> +timeout=<%= @config.timeout %> +<% end %> +<% if @config.options -%> +<% @config.options.each do |key, value| -%> +<%= key %>=<%= + case value + when Array + value.join("\n ") + when TrueClass + '1' + when FalseClass + '0' + else + value + end %> +<% end -%> +<% end -%> diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/systemd_unit.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/systemd_unit.rb new file mode 100644 index 0000000..1024cb8 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/systemd_unit.rb @@ -0,0 +1,253 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/provider/systemd_unit' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Nathan Williams () +# Copyright:: Copyright 2016, Nathan Williams +# License:: Apache License, Version 2.0 +# +# 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. +# + +require "chef_compat/copied_from_chef/chef/provider" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Provider < (defined?(::Chef::Provider) ? ::Chef::Provider : Object) + class SystemdUnit < (defined?(::Chef::Provider::SystemdUnit) ? ::Chef::Provider::SystemdUnit : Chef::Provider) + include Chef::Mixin::Which + include Chef::Mixin::ShellOut + + provides :systemd_unit, os: "linux" + + def load_current_resource + @current_resource = Chef::Resource::SystemdUnit.new(new_resource.name) + + current_resource.content(::File.read(unit_path)) if ::File.exist?(unit_path) + current_resource.user(new_resource.user) + current_resource.enabled(enabled?) + current_resource.active(active?) + current_resource.masked(masked?) + current_resource.static(static?) + current_resource.triggers_reload(new_resource.triggers_reload) + + current_resource + end + + def define_resource_requirements + super + + requirements.assert(:create) do |a| + a.assertion { IniParse.parse(new_resource.to_ini) } + a.failure_message "Unit content is not valid INI text" + end + end + + def action_create + if current_resource.content != new_resource.to_ini + converge_by("creating unit: #{new_resource.name}") do + manage_unit_file(:create) + daemon_reload if new_resource.triggers_reload + end + end + end + + def action_delete + if ::File.exist?(unit_path) + converge_by("deleting unit: #{new_resource.name}") do + manage_unit_file(:delete) + daemon_reload if new_resource.triggers_reload + end + end + end + + def action_enable + if current_resource.static + Chef::Log.debug("#{new_resource.name} is a static unit, enabling is a NOP.") + end + + unless current_resource.enabled || current_resource.static + converge_by("enabling unit: #{new_resource.name}") do + systemctl_execute!(:enable, new_resource.name) + end + end + end + + def action_disable + if current_resource.static + Chef::Log.debug("#{new_resource.name} is a static unit, disabling is a NOP.") + end + + if current_resource.enabled && !current_resource.static + converge_by("disabling unit: #{new_resource.name}") do + systemctl_execute!(:disable, new_resource.name) + end + end + end + + def action_mask + unless current_resource.masked + converge_by("masking unit: #{new_resource.name}") do + systemctl_execute!(:mask, new_resource.name) + end + end + end + + def action_unmask + if current_resource.masked + converge_by("unmasking unit: #{new_resource.name}") do + systemctl_execute!(:unmask, new_resource.name) + end + end + end + + def action_start + unless current_resource.active + converge_by("starting unit: #{new_resource.name}") do + systemctl_execute!(:start, new_resource.name) + end + end + end + + def action_stop + if current_resource.active + converge_by("stopping unit: #{new_resource.name}") do + systemctl_execute!(:stop, new_resource.name) + end + end + end + + def action_restart + converge_by("restarting unit: #{new_resource.name}") do + systemctl_execute!(:restart, new_resource.name) + end + end + + def action_reload + if current_resource.active + converge_by("reloading unit: #{new_resource.name}") do + systemctl_execute!(:reload, new_resource.name) + end + else + Chef::Log.debug("#{new_resource.name} is not active, skipping reload.") + end + end + + def action_try_restart + converge_by("try-restarting unit: #{new_resource.name}") do + systemctl_execute!("try-restart", new_resource.name) + end + end + + def action_reload_or_restart + converge_by("reload-or-restarting unit: #{new_resource.name}") do + systemctl_execute!("reload-or-restart", new_resource.name) + end + end + + def action_reload_or_try_restart + converge_by("reload-or-try-restarting unit: #{new_resource.name}") do + systemctl_execute!("reload-or-try-restart", new_resource.name) + end + end + + def active? + systemctl_execute("is-active", new_resource.name).exitstatus == 0 + end + + def enabled? + systemctl_execute("is-enabled", new_resource.name).exitstatus == 0 + end + + def masked? + systemctl_execute(:status, new_resource.name).stdout.include?("masked") + end + + def static? + systemctl_execute("is-enabled", new_resource.name).stdout.include?("static") + end + + private + + def unit_path + if new_resource.user + "/etc/systemd/user/#{new_resource.name}" + else + "/etc/systemd/system/#{new_resource.name}" + end + end + + def manage_unit_file(action = :nothing) + Chef::Resource::File.new(unit_path, run_context).tap do |f| + f.owner "root" + f.group "root" + f.mode "0644" + f.content new_resource.to_ini + end.run_action(action) + end + + def daemon_reload + shell_out_with_systems_locale!("#{systemctl_path} daemon-reload") + end + + def systemctl_execute!(action, unit) + shell_out_with_systems_locale!("#{systemctl_cmd} #{action} #{unit}", systemctl_opts) + end + + def systemctl_execute(action, unit) + shell_out("#{systemctl_cmd} #{action} #{unit}", systemctl_opts) + end + + def systemctl_cmd + @systemctl_cmd ||= "#{systemctl_path} #{systemctl_args}" + end + + def systemctl_path + @systemctl_path ||= which("systemctl") + end + + def systemctl_args + @systemctl_args ||= new_resource.user ? "--user" : "--system" + end + + def systemctl_opts + @systemctl_opts ||= + if new_resource.user + { + :user => new_resource.user, + :environment => { + "DBUS_SESSION_BUS_ADDRESS" => "unix:path=/run/user/#{node['etc']['passwd'][new_resource.user]['uid']}/bus", + }, + } + else + {} + end + end + end + end +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/yum_repository.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/yum_repository.rb new file mode 100644 index 0000000..51453d2 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/yum_repository.rb @@ -0,0 +1,136 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/provider/yum_repository' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Thom May () +# Copyright:: Copyright (c) 2016 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +require "chef_compat/copied_from_chef/chef/resource" +require "chef_compat/copied_from_chef/chef/dsl/declare_resource" +require "chef_compat/copied_from_chef/chef/provider/noop" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Provider < (defined?(::Chef::Provider) ? ::Chef::Provider : Object) + class YumRepository < (defined?(::Chef::Provider::YumRepository) ? ::Chef::Provider::YumRepository : Chef::Provider) + use_inline_resources + + extend Chef::Mixin::Which + + provides :yum_repository do + which "yum" + end + + def whyrun_supported?; true; end + + def load_current_resource; end + + action :create do + declare_resource(:template, "/etc/yum.repos.d/#{new_resource.repositoryid}.repo") do + if template_available?(new_resource.source) + source new_resource.source + else + source ::File.expand_path("../support/yum_repo.erb", __FILE__) + local true + end + sensitive new_resource.sensitive + variables(config: new_resource) + mode new_resource.mode + if new_resource.make_cache + notifies :run, "execute[yum clean metadata #{new_resource.repositoryid}]", :immediately if new_resource.clean_metadata || new_resource.clean_headers + notifies :run, "execute[yum-makecache-#{new_resource.repositoryid}]", :immediately + notifies :create, "ruby_block[yum-cache-reload-#{new_resource.repositoryid}]", :immediately + end + end + + declare_resource(:execute, "yum clean metadata #{new_resource.repositoryid}") do + command "yum clean metadata --disablerepo=* --enablerepo=#{new_resource.repositoryid}" + action :nothing + end + + # get the metadata for this repo only + declare_resource(:execute, "yum-makecache-#{new_resource.repositoryid}") do + command "yum -q -y makecache --disablerepo=* --enablerepo=#{new_resource.repositoryid}" + action :nothing + only_if { new_resource.enabled } + end + + # reload internal Chef yum cache + declare_resource(:ruby_block, "yum-cache-reload-#{new_resource.repositoryid}") do + block { Chef::Provider::Package::Yum::YumCache.instance.reload } + action :nothing + end + end + + action :delete do + # clean the repo cache first + declare_resource(:execute, "yum clean all #{new_resource.repositoryid}") do + command "yum clean all --disablerepo=* --enablerepo=#{new_resource.repositoryid}" + only_if "yum repolist all | grep -P '^#{new_resource.repositoryid}([ \t]|$)'" + end + + declare_resource(:file, "/etc/yum.repos.d/#{new_resource.repositoryid}.repo") do + action :delete + notifies :create, "ruby_block[yum-cache-reload-#{new_resource.repositoryid}]", :immediately + end + + declare_resource(:ruby_block, "yum-cache-reload-#{new_resource.repositoryid}") do + block { Chef::Provider::Package::Yum::YumCache.instance.reload } + action :nothing + end + end + + action :makecache do + declare_resource(:execute, "yum-makecache-#{new_resource.repositoryid}") do + command "yum -q -y makecache --disablerepo=* --enablerepo=#{new_resource.repositoryid}" + action :run + only_if { new_resource.enabled } + end + + declare_resource(:ruby_block, "yum-cache-reload-#{new_resource.repositoryid}") do + block { Chef::Provider::Package::Yum::YumCache.instance.reload } + action :run + end + end + + alias_method :action_add, :action_create + alias_method :action_remove, :action_delete + + def template_available?(path) + !path.nil? && run_context.has_template_in_cookbook?(new_resource.cookbook_name, path) + end + + end + end +end + +Chef::Provider::Noop.provides :yum_repository +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource.rb new file mode 100644 index 0000000..e5c9a14 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource.rb @@ -0,0 +1,214 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/resource' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +require "chef_compat/copied_from_chef/chef/resource/action_class" +require "chef_compat/copied_from_chef/chef/provider" +require "chef_compat/copied_from_chef/chef/mixin/properties" +require "chef_compat/copied_from_chef/chef/dsl/universal" +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Resource < (defined?(::Chef::Resource) ? ::Chef::Resource : Object) + include Chef::Mixin::Properties + property :name, String, coerce: proc { |v| v.is_a?(Array) ? v.join(", ") : v.to_s }, desired_state: false + def initialize(name, run_context = nil) +super if defined?(::Chef::Resource) + name(name) unless name.nil? + @run_context = run_context + @noop = nil + @before = nil + @params = Hash.new + @provider = nil + @allowed_actions = self.class.allowed_actions.to_a + @action = self.class.default_action + @updated = false + @updated_by_last_action = false + @supports = {} + @ignore_failure = false + @retries = 0 + @retry_delay = 2 + @not_if = [] + @only_if = [] + @source_line = nil + # We would like to raise an error when the user gives us a guard + # interpreter and a ruby_block to the guard. In order to achieve this + # we need to understand when the user overrides the default guard + # interpreter. Therefore we store the default separately in a different + # attribute. + @guard_interpreter = nil + @default_guard_interpreter = :default + @elapsed_time = 0 + @sensitive = false + end + def action(arg = nil) + if arg + arg = Array(arg).map(&:to_sym) + arg.each do |action| + validate( + { action: action }, + { action: { kind_of: Symbol, equal_to: allowed_actions } } + ) + end + @action = arg + else + @action + end + end + alias_method :action=, :action + class UnresolvedSubscribes < (defined?(::Chef::Resource::UnresolvedSubscribes) ? ::Chef::Resource::UnresolvedSubscribes : self) + alias_method :to_s, :name + alias_method :declared_key, :name + end + def state_for_resource_reporter + state = {} + state_properties = self.class.state_properties + state_properties.each do |property| + if property.identity? || property.is_set?(self) + state[property.name] = property.sensitive? ? "*sensitive value suppressed*" : send(property.name) + end + end + state + end + alias_method :state, :state_for_resource_reporter + def identity + result = {} + identity_properties = self.class.identity_properties + identity_properties.each do |property| + result[property.name] = send(property.name) + end + return result.values.first if identity_properties.size == 1 + result + end + attr_reader :resource_initializing + def resource_initializing=(value) + if value + @resource_initializing = true + else + remove_instance_variable(:@resource_initializing) + end + end + def to_hash + # Grab all current state, then any other ivars (backcompat) + result = {} + self.class.state_properties.each do |p| + result[p.name] = p.get(self) + end + safe_ivars = instance_variables.map { |ivar| ivar.to_sym } - FORBIDDEN_IVARS + safe_ivars.each do |iv| + key = iv.to_s.sub(/^@/, "").to_sym + next if result.has_key?(key) + result[key] = instance_variable_get(iv) + end + result + end + def self.identity_property(name = nil) + result = identity_properties(*Array(name)) + if result.size > 1 + raise Chef::Exceptions::MultipleIdentityError, "identity_property cannot be called on an object with more than one identity property (#{result.map { |r| r.name }.join(", ")})." + end + result.first + end + attr_accessor :allowed_actions + def allowed_actions(value = NOT_PASSED) + if value != NOT_PASSED + self.allowed_actions = value + end + @allowed_actions + end + def resource_name + @resource_name || self.class.resource_name + end + def self.use_automatic_resource_name + automatic_name = convert_to_snake_case(self.name.split("::")[-1]) + resource_name automatic_name + end + def self.allowed_actions(*actions) + @allowed_actions ||= + if superclass.respond_to?(:allowed_actions) + superclass.allowed_actions.dup + else + [ :nothing ] + end + @allowed_actions |= actions.flatten + end + def self.allowed_actions=(value) + @allowed_actions = value.uniq + end + def self.default_action(action_name = NOT_PASSED) + unless action_name.equal?(NOT_PASSED) + @default_action = Array(action_name).map(&:to_sym) + self.allowed_actions |= @default_action + end + + if @default_action + @default_action + elsif superclass.respond_to?(:default_action) + superclass.default_action + else + [:nothing] + end + end + def self.default_action=(action_name) + default_action action_name + end + def self.action(action, &recipe_block) + action = action.to_sym + declare_action_class + action_class.action(action, &recipe_block) + self.allowed_actions += [ action ] + default_action action if Array(default_action) == [:nothing] + end + def self.load_current_value(&load_block) + define_method(:load_current_value!, &load_block) + end + def current_value_does_not_exist! + raise Chef::Exceptions::CurrentValueDoesNotExist + end + def self.action_class(&block) + return @action_class if @action_class && !block + # If the superclass needed one, then we need one as well. + if block || (superclass.respond_to?(:action_class) && superclass.action_class) + @action_class = declare_action_class(&block) + end + @action_class + end + def self.declare_action_class(&block) + @action_class ||= begin + if superclass.respond_to?(:action_class) + base_provider = superclass.action_class + end + base_provider ||= Chef::Provider + + resource_class = self + Class.new(base_provider) do + include ActionClass + self.resource_class = resource_class + end + end + @action_class.class_eval(&block) if block + @action_class + end + FORBIDDEN_IVARS = [:@run_context, :@not_if, :@only_if, :@enclosing_provider] + HIDDEN_IVARS = [:@allowed_actions, :@resource_name, :@source_line, :@run_context, :@name, :@not_if, :@only_if, :@elapsed_time, :@enclosing_provider] + class << self + end + @@sorted_descendants = nil + module DeprecatedLWRPClass + CopiedFromChef.extend_chef_module(::Chef::Resource::DeprecatedLWRPClass, self) if defined?(::Chef::Resource::DeprecatedLWRPClass) + end + end +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/action_class.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/action_class.rb new file mode 100644 index 0000000..20ff8e5 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/action_class.rb @@ -0,0 +1,114 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/resource/action_class' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: John Keiser ("} action #{action ? action.inspect : ""}" + end + + def whyrun_supported? + true + end + + # + # If load_current_value! is defined on the resource, use that. + # + def load_current_resource + if new_resource.respond_to?(:load_current_value!) + # dup the resource and then reset desired-state properties. + current_resource = new_resource.dup + + # We clear desired state in the copy, because it is supposed to be actual state. + # We keep identity properties and non-desired-state, which are assumed to be + # "control" values like `recurse: true` + current_resource.class.properties.each do |name, property| + if property.desired_state? && !property.identity? && !property.name_property? + property.reset(current_resource) + end + end + + # Call the actual load_current_value! method. If it raises + # CurrentValueDoesNotExist, set current_resource to `nil`. + begin + # If the user specifies load_current_value do |desired_resource|, we + # pass in the desired resource as well as the current one. + if current_resource.method(:load_current_value!).arity > 0 + current_resource.load_current_value!(new_resource) + else + current_resource.load_current_value! + end + rescue Chef::Exceptions::CurrentValueDoesNotExist + current_resource = nil + end + end + + @current_resource = current_resource + end + + def self.included(other) + other.extend(ClassMethods) + other.use_inline_resources + other.include_resource_dsl true + end + + module ClassMethods + CopiedFromChef.extend_chef_module(::Chef::Resource::ActionClass::ClassMethods, self) if defined?(::Chef::Resource::ActionClass::ClassMethods) + # + # The Chef::Resource class this ActionClass was declared against. + # + # @return [Class] The Chef::Resource class this ActionClass was declared against. + # + attr_accessor :resource_class + + def to_s + "#{resource_class} action provider" + end + + def inspect + to_s + end + end + end + end +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/apt_repository.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/apt_repository.rb new file mode 100644 index 0000000..bedfd3e --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/apt_repository.rb @@ -0,0 +1,65 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/resource/apt_repository' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Thom May () +# Copyright:: Copyright (c) 2016 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +require "chef_compat/copied_from_chef/chef/resource" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Resource < (defined?(::Chef::Resource) ? ::Chef::Resource : Object) + class AptRepository < (defined?(::Chef::Resource::AptRepository) ? ::Chef::Resource::AptRepository : Chef::Resource) + resource_name :apt_repository + provides :apt_repository + + property :repo_name, String, name_property: true + property :uri, String + property :distribution, [ String, nil, false ], default: lazy { node["lsb"]["codename"] }, nillable: true, coerce: proc { |x| x ? x : nil } + property :components, Array, default: [] + property :arch, [String, nil, false], default: nil, nillable: true, coerce: proc { |x| x ? x : nil } + property :trusted, [TrueClass, FalseClass], default: false + # whether or not to add the repository as a source repo, too + property :deb_src, [TrueClass, FalseClass], default: false + property :keyserver, [String, nil, false], default: "keyserver.ubuntu.com", nillable: true, coerce: proc { |x| x ? x : nil } + property :key, [String, nil, false], default: nil, nillable: true, coerce: proc { |x| x ? x : nil } + property :key_proxy, [String, nil, false], default: nil, nillable: true, coerce: proc { |x| x ? x : nil } + + property :cookbook, [String, nil, false], default: nil, desired_state: false, nillable: true, coerce: proc { |x| x ? x : nil } + property :cache_rebuild, [TrueClass, FalseClass], default: true, desired_state: false + + default_action :add + allowed_actions :add, :remove + end + end +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/apt_update.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/apt_update.rb new file mode 100644 index 0000000..9acd9ae --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/apt_update.rb @@ -0,0 +1,52 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/resource/apt_update' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Thom May () +# Copyright:: Copyright (c) 2016 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +require "chef_compat/copied_from_chef/chef/resource" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Resource < (defined?(::Chef::Resource) ? ::Chef::Resource : Object) + class AptUpdate < (defined?(::Chef::Resource::AptUpdate) ? ::Chef::Resource::AptUpdate : Chef::Resource) + resource_name :apt_update + provides :apt_update + + property :frequency, Integer, default: 86_400 + + default_action :periodic + allowed_actions :update, :periodic + end + end +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/systemd_unit.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/systemd_unit.rb new file mode 100644 index 0000000..5f9f458 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/systemd_unit.rb @@ -0,0 +1,81 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/resource/systemd_unit' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Nathan Williams () +# Copyright:: Copyright 2016, Nathan Williams +# License:: Apache License, Version 2.0 +# +# 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. +# + +require "chef_compat/copied_from_chef/chef/resource" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Resource < (defined?(::Chef::Resource) ? ::Chef::Resource : Object) + class SystemdUnit < (defined?(::Chef::Resource::SystemdUnit) ? ::Chef::Resource::SystemdUnit : Chef::Resource) + resource_name :systemd_unit + + default_action :nothing + allowed_actions :create, :delete, + :enable, :disable, + :mask, :unmask, + :start, :stop, + :restart, :reload, + :try_restart, :reload_or_restart, + :reload_or_try_restart + + property :enabled, [TrueClass, FalseClass] + property :active, [TrueClass, FalseClass] + property :masked, [TrueClass, FalseClass] + property :static, [TrueClass, FalseClass] + property :user, String, desired_state: false + property :content, [String, Hash] + property :triggers_reload, [TrueClass, FalseClass], + default: true, desired_state: false + + def to_ini + case content + when Hash + IniParse.gen do |doc| + content.each_pair do |sect, opts| + doc.section(sect) do |section| + opts.each_pair do |opt, val| + section.option(opt, val) + end + end + end + end.to_s + else + content.to_s + end + end + end + end +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/yum_repository.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/yum_repository.rb new file mode 100644 index 0000000..97cf23a --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/yum_repository.rb @@ -0,0 +1,97 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/resource/yum_repository' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Thom May () +# Copyright:: Copyright (c) 2016 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +require "chef_compat/copied_from_chef/chef/resource" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Resource < (defined?(::Chef::Resource) ? ::Chef::Resource : Object) + class YumRepository < (defined?(::Chef::Resource::YumRepository) ? ::Chef::Resource::YumRepository : Chef::Resource) + resource_name :yum_repository + provides :yum_repository + + # http://linux.die.net/man/5/yum.conf + property :baseurl, [String, Array], regex: /.*/ + property :cost, String, regex: /^\d+$/ + property :clean_headers, [TrueClass, FalseClass], default: false # deprecated + property :clean_metadata, [TrueClass, FalseClass], default: true + property :description, String, regex: /.*/, default: "Yum Repository" + property :enabled, [TrueClass, FalseClass], default: true + property :enablegroups, [TrueClass, FalseClass] + property :exclude, String, regex: /.*/ + property :failovermethod, String, equal_to: %w{priority roundrobin} + property :fastestmirror_enabled, [TrueClass, FalseClass] + property :gpgcheck, [TrueClass, FalseClass], default: true + property :gpgkey, [String, Array], regex: /.*/ + property :http_caching, String, equal_to: %w{packages all none} + property :include_config, String, regex: /.*/ + property :includepkgs, String, regex: /.*/ + property :keepalive, [TrueClass, FalseClass] + property :make_cache, [TrueClass, FalseClass], default: true + property :max_retries, [String, Integer] + property :metadata_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/, /never/] + property :mirrorexpire, String, regex: /.*/ + property :mirrorlist, String, regex: /.*/ + property :mirror_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/] + property :mirrorlist_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/] + property :mode, default: "0644" + property :priority, String, regex: /^(\d?[0-9]|[0-9][0-9])$/ + property :proxy, String, regex: /.*/ + property :proxy_username, String, regex: /.*/ + property :proxy_password, String, regex: /.*/ + property :username, String, regex: /.*/ + property :password, String, regex: /.*/ + property :repo_gpgcheck, [TrueClass, FalseClass] + property :report_instanceid, [TrueClass, FalseClass] + property :repositoryid, String, regex: /.*/, name_property: true + property :skip_if_unavailable, [TrueClass, FalseClass] + property :source, String, regex: /.*/ + property :sslcacert, String, regex: /.*/ + property :sslclientcert, String, regex: /.*/ + property :sslclientkey, String, regex: /.*/ + property :sslverify, [TrueClass, FalseClass] + property :timeout, String, regex: /^\d+$/ + property :options, Hash + + default_action :create + allowed_actions :create, :remove, :makecache, :add, :delete + + # provide compatibility with the yum cookbook < 3.0 properties + alias_method :url, :baseurl + alias_method :keyurl, :gpgkey + end + end +end +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource_builder.rb b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource_builder.rb new file mode 100644 index 0000000..688e856 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource_builder.rb @@ -0,0 +1,174 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/resource_builder' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Lamont Granquist () +# Copyright:: Copyright 2015-2016, Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +# NOTE: this was extracted from the Recipe DSL mixin, relevant specs are in spec/unit/recipe_spec.rb + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class ResourceBuilder < (defined?(::Chef::ResourceBuilder) ? ::Chef::ResourceBuilder : Object) + attr_reader :type + attr_reader :name + attr_reader :created_at + attr_reader :params + attr_reader :run_context + attr_reader :cookbook_name + attr_reader :recipe_name + attr_reader :enclosing_provider + attr_reader :resource + + # FIXME (ruby-2.1 syntax): most of these are mandatory + def initialize(type: nil, name: nil, created_at: nil, params: nil, run_context: nil, cookbook_name: nil, recipe_name: nil, enclosing_provider: nil) +super if defined?(::Chef::ResourceBuilder) + @type = type + @name = name + @created_at = created_at + @params = params + @run_context = run_context + @cookbook_name = cookbook_name + @recipe_name = recipe_name + @enclosing_provider = enclosing_provider + end + + def build(&block) + raise ArgumentError, "You must supply a name when declaring a #{type} resource" if name.nil? + + @resource = resource_class.new(name, run_context) + if resource.resource_name.nil? + raise Chef::Exceptions::InvalidResourceSpecification, "#{resource}.resource_name is `nil`! Did you forget to put `provides :blah` or `resource_name :blah` in your resource class?" + end + resource.source_line = created_at + resource.declared_type = type + + # If we have a resource like this one, we want to steal its state + # This behavior is very counter-intuitive and should be removed. + # See CHEF-3694, https://tickets.opscode.com/browse/CHEF-3694 + # Moved to this location to resolve CHEF-5052, https://tickets.opscode.com/browse/CHEF-5052 + if prior_resource + resource.load_from(prior_resource) + end + + resource.cookbook_name = cookbook_name + resource.recipe_name = recipe_name + # Determine whether this resource is being created in the context of an enclosing Provider + resource.enclosing_provider = enclosing_provider + + # XXX: this is required for definition params inside of the scope of a + # subresource to work correctly. + resource.params = params + + # Evaluate resource attribute DSL + if block_given? + resource.resource_initializing = true + begin + resource.instance_eval(&block) + ensure + resource.resource_initializing = false + end + end + + # emit a cloned resource warning if it is warranted + if prior_resource + if is_trivial_resource?(prior_resource) && identicalish_resources?(prior_resource, resource) + emit_harmless_cloning_debug + else + emit_cloned_resource_warning + end + end + + # Run optional resource hook + resource.after_created + + resource + end + + private + + def resource_class + # Checks the new platform => short_name => resource mapping initially + # then fall back to the older approach (Chef::Resource.const_get) for + # backward compatibility + @resource_class ||= Chef::Resource.resource_for_node(type, run_context.node) + end + + def is_trivial_resource?(resource) + trivial_resource = resource_class.new(name, run_context) + # force un-lazy the name property on the created trivial resource + name_property = resource_class.properties.find { |sym, p| p.name_property? } + trivial_resource.send(name_property[0]) unless name_property.nil? + identicalish_resources?(trivial_resource, resource) + end + + # this is an equality test specific to checking for 3694 cloning warnings + def identicalish_resources?(first, second) + skipped_ivars = [ :@source_line, :@cookbook_name, :@recipe_name, :@params, :@elapsed_time, :@declared_type ] + checked_ivars = ( first.instance_variables | second.instance_variables ) - skipped_ivars + non_matching_ivars = checked_ivars.reject do |iv| + if iv == :@action && ( [first.instance_variable_get(iv)].flatten == [:nothing] || [second.instance_variable_get(iv)].flatten == [:nothing] ) + # :nothing action on either side of the comparison always matches + true + else + first.instance_variable_get(iv) == second.instance_variable_get(iv) + end + end + Chef::Log.debug("ivars which did not match with the prior resource: #{non_matching_ivars}") + non_matching_ivars.empty? + end + + def emit_cloned_resource_warning + message = "Cloning resource attributes for #{resource} from prior resource (CHEF-3694)" + message << "\nPrevious #{prior_resource}: #{prior_resource.source_line}" if prior_resource.source_line + message << "\nCurrent #{resource}: #{resource.source_line}" if resource.source_line + Chef.log_deprecation(message) + end + + def emit_harmless_cloning_debug + Chef::Log.debug("Harmless resource cloning from #{prior_resource}:#{prior_resource.source_line} to #{resource}:#{resource.source_line}") + end + + def prior_resource + @prior_resource ||= + begin + key = "#{type}[#{name}]" + run_context.resource_collection.lookup_local(key) + rescue Chef::Exceptions::ResourceNotFound + nil + end + end + + end +end + +require "chef_compat/copied_from_chef/chef/resource" +end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/mixin/properties.rb b/cookbooks/compat_resource/files/lib/chef_compat/mixin/properties.rb new file mode 100644 index 0000000..a3920d1 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/mixin/properties.rb @@ -0,0 +1,8 @@ +require 'chef_compat/monkeypatches' +require 'chef_compat/copied_from_chef/chef/mixin/properties' + +module ChefCompat + module Mixin + Properties = ChefCompat::CopiedFromChef::Chef::Mixin::Properties + end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches.rb b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches.rb new file mode 100644 index 0000000..9ac83e8 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches.rb @@ -0,0 +1,41 @@ +class Chef + class RunContext + class ChildRunContext < RunContext + # magic that lets us re-parse the ChildRunContext without erroring due to + # cheffish and chef-provisioning hooks having been loaded (on old versions of + # chef-client without the lazy hooks for those gems) + @__skip_method_checking = true + end + end +end + +# fix to quiet constant redefined warnings +if defined?(Chef::RunContext::ChildRunContext::CHILD_STATE) + Chef::RunContext::ChildRunContext.send(:remove_const, :CHILD_STATE) +end + +require 'chef_compat/monkeypatches/chef' +require 'chef_compat/monkeypatches/chef/exceptions' +require 'chef_compat/monkeypatches/chef/log' +require 'chef_compat/monkeypatches/chef/node' +require 'chef_compat/monkeypatches/chef/mixin/params_validate' +require 'chef_compat/monkeypatches/chef/property' +require 'chef_compat/monkeypatches/chef/provider' +require 'chef_compat/monkeypatches/chef/recipe' # copied from chef +require 'chef_compat/monkeypatches/chef/recipe_hook' +require 'chef_compat/monkeypatches/chef/resource' +require 'chef_compat/monkeypatches/chef/resource_builder' +require 'chef_compat/monkeypatches/chef/resource/lwrp_base' +require 'chef_compat/monkeypatches/chef/resource_collection' +require 'chef_compat/monkeypatches/chef/resource_collection/resource_list' +require 'chef_compat/monkeypatches/chef/resource_collection/resource_set' +require 'chef_compat/monkeypatches/chef/run_context' # copied from chef +require 'chef_compat/monkeypatches/chef/runner' # copied from chef + +# fix for Chef::RunContext instance that has already been created +ObjectSpace.each_object(Chef::RunContext) do |run_context| + run_context.node.run_context = run_context + run_context.instance_variable_set(:@loaded_recipes_hash, {}) + run_context.instance_variable_set(:@loaded_attributes_hash, {}) + run_context.initialize_child_state +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef.rb b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef.rb new file mode 100644 index 0000000..9669f6a --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef.rb @@ -0,0 +1,33 @@ +class Chef + NOT_PASSED = Object.new if !defined?(NOT_PASSED) + # Earlier versions of Chef didn't have this message + module ChefCompatDeprecation + def log_deprecation(message, location=nil) + if !location + # Pick the first caller that is *not* part of the Chef or ChefCompat gem, + # that's the thing the user wrote. + chef_compat_gem_path = File.expand_path("../../..", __FILE__) + chef_gem_path = File.expand_path("../..",::Chef::Resource.instance_method(:initialize).source_location[0]) + caller(0..10).each do |c| + if !c.start_with?(chef_gem_path) && !c.start_with?(chef_compat_gem_path) + location = c + break + end + end + end + + begin + super + # Bleagh. `super_method` doesn't exist on older rubies and I haven't + # figured out a way to check for its existence otherwise. + rescue NoMethodError + Chef::Log.warn(message) + end + end + end + + class<= 12.5 && Chef::VERSION.to_f <= 12.8 + require 'chef/mixin/params_validate' + class Chef + module Mixin + module ParamsValidate + class SetOrReturnProperty < Chef::Property + # 12.9 introduced a new optional parameter to `get()` to avoid a nil-set warning. + # When their method gets called with 2 args, we need to ignore and call with 1. + alias_method :_original_get2, :get + def get(resource, *args) + _original_get2(resource) + end + end + end + end + end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/node.rb b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/node.rb new file mode 100644 index 0000000..93379b0 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/node.rb @@ -0,0 +1,9 @@ +class Chef + class Node + unless method_defined?(:set_cookbook_attribute) + def set_cookbook_attribute + # this implementation deliberately left blank - we don't need to do anything we just need to not fail + end + end + end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/property.rb b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/property.rb new file mode 100644 index 0000000..2308d32 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/property.rb @@ -0,0 +1,15 @@ +# 12.9 introduced a new optional parameter to `get()` to avoid a nil-set warning. +# We need to mimick it here. +if Chef::VERSION.to_f >= 12.5 && Chef::VERSION.to_f <= 12.8 + require 'chef/property' + class Chef + class Property + # 12.9 introduced a new optional parameter to `get()` to avoid a nil-set warning. + # When their method gets called with 2 args, we need to ignore and call with 1. + alias_method :_original_get, :get + def get(resource, *args) + _original_get(resource) + end + end + end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/provider.rb b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/provider.rb new file mode 100644 index 0000000..591cedb --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/provider.rb @@ -0,0 +1,65 @@ +require 'chef/provider' +require 'chef/provider/lwrp_base' + +class Chef::Provider + if !defined?(InlineResources) + InlineResources = Chef::Provider::LWRPBase::InlineResources + end + module InlineResources + require 'chef/dsl/recipe' + require 'chef/dsl/platform_introspection' + require 'chef/dsl/data_query' + require 'chef/dsl/include_recipe' + include Chef::DSL::Recipe + include Chef::DSL::PlatformIntrospection + include Chef::DSL::DataQuery + include Chef::DSL::IncludeRecipe + + unless Chef::Provider::InlineResources::ClassMethods.instance_method(:action).source_location[0] =~ /chefspec/ + # Don't override action if chefspec is doing its thing + module ::ChefCompat + module Monkeypatches + module InlineResources + module ClassMethods + def action(name, &block) + super(name) { send("compile_action_#{name}") } + # We put the action in its own method so that super() works. + define_method("compile_action_#{name}", &block) + end + end + end + end + end + module ClassMethods + prepend ChefCompat::Monkeypatches::InlineResources::ClassMethods + end + end + end +end + + +class Chef + class Provider + class LWRPBase < Provider + if defined?(InlineResources) + module InlineResources + # since we upgrade the Chef::Runner and Chef::RunContext globally to >= 12.14 style classes, we need to also + # fix the use_inline_resources LWRPBase wrapper that creates a sub-resource collection with the ugpraded code + # from the Chef::Provider subclasses that do similar things in post-12.5 chef. + def recipe_eval_with_update_check(&block) + old_run_context = run_context + @run_context = run_context.create_child + return_value = instance_eval(&block) + Chef::Runner.new(run_context).converge + return_value + ensure + if run_context.resource_collection.any? { |r| r.updated? } + new_resource.updated_by_last_action(true) + end + @run_context = old_run_context + end + end + end + end + end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/recipe.rb b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/recipe.rb new file mode 100644 index 0000000..7c4c8be --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/recipe.rb @@ -0,0 +1,118 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +if Gem::Requirement.new('< 12.16.42').satisfied_by?(Gem::Version.new(Chef::VERSION)) +#-- +# Author:: Adam Jacob () +# Author:: Christopher Walters () +# Copyright:: Copyright 2008-2016, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +require "chef/dsl/recipe" +require "chef/mixin/from_file" +require "chef/mixin/deprecation" + +class Chef + # == Chef::Recipe + # A Recipe object is the context in which Chef recipes are evaluated. + class Recipe + attr_accessor :cookbook_name, :recipe_name, :recipe, :params, :run_context + + include Chef::DSL::Recipe + + include Chef::Mixin::FromFile + include Chef::Mixin::Deprecation + + # Parses a potentially fully-qualified recipe name into its + # cookbook name and recipe short name. + # + # For example: + # "aws::elastic_ip" returns [:aws, "elastic_ip"] + # "aws" returns [:aws, "default"] + # "::elastic_ip" returns [ current_cookbook, "elastic_ip" ] + #-- + # TODO: Duplicates functionality of RunListItem + def self.parse_recipe_name(recipe_name, current_cookbook: nil) + case recipe_name + when /(.+?)::(.+)/ + [ $1.to_sym, $2 ] + when /^::(.+)/ + raise "current_cookbook is nil, cannot resolve #{recipe_name}" if current_cookbook.nil? + [ current_cookbook.to_sym, $1 ] + else + [ recipe_name.to_sym, "default" ] + end + end + + def initialize(cookbook_name, recipe_name, run_context) + @cookbook_name = cookbook_name + @recipe_name = recipe_name + @run_context = run_context + # TODO: 5/19/2010 cw/tim: determine whether this can be removed + @params = Hash.new + end + + # Used in DSL mixins + def node + run_context.node + end + + # Used by the DSL to look up resources when executing in the context of a + # recipe. + def resources(*args) + run_context.resource_collection.find(*args) + end + + # This was moved to Chef::Node#tag, redirecting here for compatibility + def tag(*tags) + run_context.node.tag(*tags) + end + + # Returns true if the node is tagged with *all* of the supplied +tags+. + # + # === Parameters + # tags:: A list of tags + # + # === Returns + # true:: If all the parameters are present + # false:: If any of the parameters are missing + def tagged?(*tags) + tags.each do |tag| + return false unless run_context.node.tags.include?(tag) + end + true + end + + # Removes the list of tags from the node. + # + # === Parameters + # tags:: A list of tags + # + # === Returns + # tags:: The current list of run_context.node.tags + def untag(*tags) + tags.each do |tag| + run_context.node.tags.delete(tag) + end + end + end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/recipe_hook.rb b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/recipe_hook.rb new file mode 100644 index 0000000..24aa20f --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/recipe_hook.rb @@ -0,0 +1,20 @@ +require 'chef/recipe' +require 'chef_compat/recipe' + +class Chef::Recipe + # If the cookbook depends on compat_resource, create a ChefCompat::Recipe object + # instead of Chef::Recipe, for the extra goodies. + def self.new(cookbook_name, recipe_name, run_context) + if run_context && + cookbook_name && + recipe_name && + run_context.cookbook_collection && + run_context.cookbook_collection[cookbook_name] && + run_context.cookbook_collection[cookbook_name].metadata.dependencies.has_key?('compat_resource') && + self != ::ChefCompat::Recipe + ::ChefCompat::Recipe.new(cookbook_name, recipe_name, run_context) + else + super + end + end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource.rb b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource.rb new file mode 100644 index 0000000..d61b60b --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource.rb @@ -0,0 +1,156 @@ +# this is NOT an AUTOGENERATED file + +require 'chef/resource' + +class Chef + class Resource + + class UnresolvedSubscribes < self + # The full key ise given as the name in {Resource#subscribes} + alias_method :to_s, :name + alias_method :declared_key, :name + end + + # + # Force a delayed notification into this resource's run_context. + # + # This should most likely be paired with action :nothing + # + # @param arg [Array[Symbol], Symbol] A list of actions (e.g. `:create`) + # + def delayed_action(arg) + arg = Array(arg).map(&:to_sym) + arg.map do |action| + validate( + { action: action }, + { action: { kind_of: Symbol, equal_to: allowed_actions } } + ) + # the resource effectively sends a delayed notification to itself + run_context.add_delayed_action(Notification.new(self, action, self)) + end + end + + def subscribes(action, resources, timing = :delayed) + resources = [resources].flatten + resources.each do |resource| + if resource.is_a?(String) + resource = UnresolvedSubscribes.new(resource, run_context) + end + if resource.run_context.nil? + resource.run_context = run_context + end + resource.notifies(action, self, timing) + end + true + end + + def notifies(action, resource_spec, timing = :delayed) + # when using old-style resources(:template => "/foo.txt") style, you + # could end up with multiple resources. + validate_resource_spec!(resource_spec) + + resources = [ resource_spec ].flatten + resources.each do |resource| + + case timing.to_s + when "delayed" + notifies_delayed(action, resource) + when "immediate", "immediately" + notifies_immediately(action, resource) + when "before" + notifies_before(action, resource) + else + raise ArgumentError, "invalid timing: #{timing} for notifies(#{action}, #{resources.inspect}, #{timing}) resource #{self} "\ + "Valid timings are: :delayed, :immediate, :immediately, :before" + end + end + + true + end + + # + # Iterates over all immediate and delayed notifications, calling + # resolve_resource_reference on each in turn, causing them to + # resolve lazy/forward references. + def resolve_notification_references + run_context.before_notifications(self).each { |n| + n.resolve_resource_reference(run_context.resource_collection) + } + run_context.immediate_notifications(self).each { |n| + n.resolve_resource_reference(run_context.resource_collection) + } + run_context.delayed_notifications(self).each {|n| + n.resolve_resource_reference(run_context.resource_collection) + } + end + + # Helper for #notifies + def notifies_before(action, resource_spec) + run_context.notifies_before(Notification.new(resource_spec, action, self)) + end + + # Helper for #notifies + def notifies_immediately(action, resource_spec) + run_context.notifies_immediately(Notification.new(resource_spec, action, self)) + end + + # Helper for #notifies + def notifies_delayed(action, resource_spec) + run_context.notifies_delayed(Notification.new(resource_spec, action, self)) + end + + # + # Get the current actual value of this resource. + # + # This does not cache--a new value will be returned each time. + # + # @return A new copy of the resource, with values filled in from the actual + # current value. + # + def current_value + provider = provider_for_action(Array(action).first) + if provider.whyrun_mode? && !provider.whyrun_supported? + raise "Cannot retrieve #{self.class.current_resource} in why-run mode: #{provider} does not support why-run" + end + provider.load_current_resource + provider.current_resource + end + + # These methods are necessary for new resources to initialize old ones properly + attr_reader :resource_initializing + def resource_initializing=(value) + if value + @resource_initializing = value + else + remove_instance_variable(:@resource_initializing) + end + end + + if !respond_to?(:resource_name) + def self.resource_name(name=Chef::NOT_PASSED) + # Setter + if name != Chef::NOT_PASSED + # remove_canonical_dsl + + # Set the resource_name and call provides + if name + name = name.to_sym + # If our class is not already providing this name, provide it. + # Commented out: use of resource_name and provides will need to be + # mutually exclusive in this world, generally. + # if !Chef::ResourceResolver.includes_handler?(name, self) + provides name#, canonical: true + # end + @resource_name = name + else + @resource_name = nil + end + end + @resource_name + end + def self.resource_name=(name) + resource_name(name) + end + end + end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource/lwrp_base.rb b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource/lwrp_base.rb new file mode 100644 index 0000000..5f098fd --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource/lwrp_base.rb @@ -0,0 +1,60 @@ +require 'chef_compat/resource/lwrp_base' +require 'chef/resource/lwrp_base' + +module ChefCompat + module Monkeypatches + # + # NOTE: LOTS OF METAPROGRAMMING HERE. NOT FOR FAINT OF HEART. + # + + # Add an empty module to Class so we can temporarily override it in build_from_file + module Class + end + class<<::Class + prepend(ChefCompat::Monkeypatches::Class) + end + + module Chef + module Resource + module LWRPBase + def build_from_file(cookbook_name, filename, run_context) + # If the cookbook this LWRP is from depends on compat_resource, fix its LWRPs up real good + if run_context.cookbook_collection[cookbook_name].metadata.dependencies.has_key?('compat_resource') + # All cookbooks do Class.new(Chef::Resource::LWRPBase). Change Class.new + # temporarily to translate Chef::Resource::LWRPBase to ChefCompat::Resource + ChefCompat::Monkeypatches::Class.module_eval do + def new(*args, &block) + # Trick it! Use ChefCompat::Resource instead of Chef::Resource::LWRPBase + if args == [ ::Chef::Resource::LWRPBase ] + ChefCompat::Monkeypatches::Class.module_eval do + remove_method(:new) if method_defined?(:new) + end + args = [ ChefCompat::Resource::LWRPBase ] + end + super(*args, &block) + end + end + + begin + + # Call the actual build_from_file + super + + ensure + class<) +# Copyright:: Copyright 2015-2016, Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +# XXX: we now have two copies of this file in the compat_resource cookbook. I'm uncertain if this is a +# bug or a feature, and I suspect it is actually a feature. The point of this file is that for all +# resources and cookbooks the global Chef::ResourceBuilder class must be upgraded to at least the +# 12.10.24 version. The point of the other copy is that for compat_resource cookbooks all their +# resources should be using the lastest version that has been sync'd. So these two files should +# diverge as times goes on. I believe that is the correct behavior and that we want to have both +# files in this cookbook. + +# NOTE: this was extracted from the Recipe DSL mixin, relevant specs are in spec/unit/recipe_spec.rb + +if Gem::Requirement.new("< 12.10.24").satisfied_by?(Gem::Version.new(Chef::VERSION)) + begin + require 'chef/resource_builder' + # we use the LoadError this creates on early 12.x to not monkeypatch chef client versions that don't have Chef::ResourceBuilder + # (it is lazily included and doesn't appear until compile time so we can't resolve the symbol during library loading) + + class Chef + class ResourceBuilder + attr_reader :type + attr_reader :name + attr_reader :created_at + attr_reader :params + attr_reader :run_context + attr_reader :cookbook_name + attr_reader :recipe_name + attr_reader :enclosing_provider + attr_reader :resource + + # FIXME (ruby-2.1 syntax): most of these are mandatory + def initialize(type:nil, name:nil, created_at: nil, params: nil, run_context: nil, cookbook_name: nil, recipe_name: nil, enclosing_provider: nil) + @type = type + @name = name + @created_at = created_at + @params = params + @run_context = run_context + @cookbook_name = cookbook_name + @recipe_name = recipe_name + @enclosing_provider = enclosing_provider + end + + def build(&block) + raise ArgumentError, "You must supply a name when declaring a #{type} resource" if name.nil? + + @resource = resource_class.new(name, run_context) + if resource.resource_name.nil? + raise Chef::Exceptions::InvalidResourceSpecification, "#{resource}.resource_name is `nil`! Did you forget to put `provides :blah` or `resource_name :blah` in your resource class?" + end + resource.source_line = created_at + resource.declared_type = type + + # If we have a resource like this one, we want to steal its state + # This behavior is very counter-intuitive and should be removed. + # See CHEF-3694, https://tickets.opscode.com/browse/CHEF-3694 + # Moved to this location to resolve CHEF-5052, https://tickets.opscode.com/browse/CHEF-5052 + if prior_resource + resource.load_from(prior_resource) + end + + resource.cookbook_name = cookbook_name + resource.recipe_name = recipe_name + # Determine whether this resource is being created in the context of an enclosing Provider + resource.enclosing_provider = enclosing_provider + + # XXX: this is required for definition params inside of the scope of a + # subresource to work correctly. + resource.params = params + + # Evaluate resource attribute DSL + if block_given? + resource.resource_initializing = true + begin + resource.instance_eval(&block) + ensure + resource.resource_initializing = false + end + end + + # emit a cloned resource warning if it is warranted + if prior_resource + if is_trivial_resource?(prior_resource) && identicalish_resources?(prior_resource, resource) + emit_harmless_cloning_debug + else + emit_cloned_resource_warning + end + end + + # Run optional resource hook + resource.after_created + + resource + end + + private + + def resource_class + # Checks the new platform => short_name => resource mapping initially + # then fall back to the older approach (Chef::Resource.const_get) for + # backward compatibility + @resource_class ||= Chef::Resource.resource_for_node(type, run_context.node) + end + + def is_trivial_resource?(resource) + identicalish_resources?(resource_class.new(name, run_context), resource) + end + + # this is an equality test specific to checking for 3694 cloning warnings + def identicalish_resources?(first, second) + skipped_ivars = [ :@source_line, :@cookbook_name, :@recipe_name, :@params, :@elapsed_time, :@declared_type ] + checked_ivars = ( first.instance_variables | second.instance_variables ) - skipped_ivars + non_matching_ivars = checked_ivars.reject do |iv| + if iv == :@action && ( [first.instance_variable_get(iv)].flatten == [:nothing] || [second.instance_variable_get(iv)].flatten == [:nothing] ) + # :nothing action on either side of the comparison always matches + true + else + first.instance_variable_get(iv) == second.instance_variable_get(iv) + end + end + Chef::Log.debug("ivars which did not match with the prior resource: #{non_matching_ivars}") + non_matching_ivars.empty? + end + + def emit_cloned_resource_warning + Chef::Log.warn("Cloning resource attributes for #{resource} from prior resource (CHEF-3694)") + Chef::Log.warn("Previous #{prior_resource}: #{prior_resource.source_line}") if prior_resource.source_line + Chef::Log.warn("Current #{resource}: #{resource.source_line}") if resource.source_line + end + + def emit_harmless_cloning_debug + Chef::Log.debug("Harmless resource cloning from #{prior_resource}:#{prior_resource.source_line} to #{resource}:#{resource.source_line}") + end + + def prior_resource + @prior_resource ||= + begin + key = "#{type}[#{name}]" + run_context.resource_collection.lookup_local(key) + rescue Chef::Exceptions::ResourceNotFound + nil + end + end + + end + end + rescue LoadError + # cool we're just on early chef 12.x, nothing to do -- we don't have to worry because there's also not parent_run_context pointer, so we don't have to + # use lookup_local to avoid resource cloning shit out of the parent run_context. the resource collection's lookup() method will always use lookup_local + # over lookup_recursive. + end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection.rb b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection.rb new file mode 100644 index 0000000..4f07489 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection.rb @@ -0,0 +1,103 @@ +# +# Author:: Adam Jacob () +# Author:: Christopher Walters () +# Copyright:: Copyright 2008-2016, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +require "chef/resource_collection/resource_set" +require "chef/resource_collection/resource_list" +require "chef/resource_collection" +require "chef/exceptions" + +module ChefCompat + module Monkeypatches + module Chef + module ResourceCollection + module RecursiveNotificationLookup + # + # Copied verbatim from Chef 12.10.24 + # + attr_accessor :run_context + + def initialize(run_context = nil) + super() + @run_context = run_context + end + + def lookup_local(key) + resource_set.lookup(key) + end + + def find_local(*args) + resource_set.find(*args) + end + + def lookup(key) + if run_context.nil? + lookup_local(key) + else + lookup_recursive(run_context, key) + end + end + + def find(*args) + if run_context.nil? + find_local(*args) + else + find_recursive(run_context, *args) + end + end + + private + + def lookup_recursive(rc, key) + rc.resource_collection.send(:resource_set).lookup(key) + rescue ::Chef::Exceptions::ResourceNotFound + raise if !rc.respond_to?(:parent_run_context) || rc.parent_run_context.nil? + lookup_recursive(rc.parent_run_context, key) + end + + def find_recursive(rc, *args) + rc.resource_collection.send(:resource_set).find(*args) + rescue ::Chef::Exceptions::ResourceNotFound + raise if !rc.respond_to?(:parent_run_context) || rc.parent_run_context.nil? + find_recursive(rc.parent_run_context, *args) + end + end + + module DeleteResources + # + # Copied verbatim from Chef 12.10.24 + # + def delete(key) + resource_list.delete(key) + resource_set.delete(key) + end + end + end + end + end +end + + +class Chef::ResourceCollection + unless method_defined?(:lookup_local) + prepend ChefCompat::Monkeypatches::Chef::ResourceCollection::RecursiveNotificationLookup + end + unless method_defined?(:delete) + prepend ChefCompat::Monkeypatches::Chef::ResourceCollection::DeleteResources + end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection/resource_list.rb b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection/resource_list.rb new file mode 100644 index 0000000..dfbd442 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection/resource_list.rb @@ -0,0 +1,49 @@ +# +# Author:: Tyler Ball () +# Copyright:: Copyright 2014-2016, Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +require "chef/resource_collection/resource_list" +require "chef/exceptions" + +module ChefCompat + module Monkeypatches + module Chef + module ResourceCollection + module ResourceList + module DeleteResource + # Copied verbatim from Chef 12.10.4 + def delete(key) + raise ArgumentError, "Must pass a Chef::Resource or String to delete" unless key.is_a?(String) || key.is_a?(Chef::Resource) + key = key.to_s + ret = @resources.reject! { |r| r.to_s == key } + if ret.nil? + raise ::Chef::Exceptions::ResourceNotFound, "Cannot find a resource matching #{key} (did you define it first?)" + end + ret + end + end + end + end + end + end +end + +class Chef::ResourceCollection::ResourceList + unless method_defined?(:delete) + prepend ChefCompat::Monkeypatches::Chef::ResourceCollection::ResourceList::DeleteResource + end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection/resource_set.rb b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection/resource_set.rb new file mode 100644 index 0000000..bcead10 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection/resource_set.rb @@ -0,0 +1,49 @@ +# +# Author:: Tyler Ball () +# Copyright:: Copyright 2014-2016, Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +require "chef/resource_collection/resource_list" +require "chef/exceptions" + +module ChefCompat + module Monkeypatches + module Chef + module ResourceCollection + module ResourceSet + module DeleteResource + def delete(key) + raise ArgumentError, "Must pass a Chef::Resource or String to delete" unless key.is_a?(String) || key.is_a?(Chef::Resource) + key = key.to_s + res = @resources_by_key.delete(key) + + if res == @resources_by_key.default + raise Chef::Exceptions::ResourceNotFound, "Cannot find a resource matching #{key} (did you define it first?)" + end + res + end + end + end + end + end + end +end + +class Chef::ResourceCollection::ResourceSet + unless method_defined?(:delete) + prepend ChefCompat::Monkeypatches::Chef::ResourceCollection::ResourceSet::DeleteResource + end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/run_context.rb b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/run_context.rb new file mode 100644 index 0000000..03c9d60 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/run_context.rb @@ -0,0 +1,691 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +if Gem::Requirement.new('< 12.16.42').satisfied_by?(Gem::Version.new(Chef::VERSION)) +# +# Author:: Adam Jacob () +# Author:: Christopher Walters () +# Author:: Tim Hinderliter () +# Copyright:: Copyright 2008-2016, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# 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. + +require "chef/resource_collection" +require "chef/cookbook_version" +require "chef/node" +require "chef/role" +require "chef/log" +require "chef/recipe" +require "chef/run_context/cookbook_compiler" +require "chef/event_dispatch/events_output_stream" +require "forwardable" + +class Chef + + # == Chef::RunContext + # Value object that loads and tracks the context of a Chef run + class RunContext + # + # Global state + # + + # + # The node for this run + # + # @return [Chef::Node] + # + attr_reader :node + + # + # The set of cookbooks involved in this run + # + # @return [Chef::CookbookCollection] + # + attr_reader :cookbook_collection + + # + # Resource Definitions for this run. Populated when the files in + # +definitions/+ are evaluated (this is triggered by #load). + # + # @return [Array[Chef::ResourceDefinition]] + # + attr_reader :definitions + + # + # Event dispatcher for this run. + # + # @return [Chef::EventDispatch::Dispatcher] + # + attr_reader :events + + # + # Hash of factoids for a reboot request. + # + # @return [Hash] + # + attr_accessor :reboot_info + + # + # Scoped state + # + + # + # The parent run context. + # + # @return [Chef::RunContext] The parent run context, or `nil` if this is the + # root context. + # + attr_reader :parent_run_context + + # + # The root run context. + # + # @return [Chef::RunContext] The root run context. + # + def root_run_context + rc = self + rc = rc.parent_run_context until rc.parent_run_context.nil? + rc + end + + # + # The collection of resources intended to be converged (and able to be + # notified). + # + # @return [Chef::ResourceCollection] + # + # @see CookbookCompiler + # + attr_reader :resource_collection + + # + # The list of control groups to execute during the audit phase + # + attr_reader :audits + + # + # Notification handling + # + + # + # A Hash containing the before notifications triggered by resources + # during the converge phase of the chef run. + # + # @return [Hash[String, Array[Chef::Resource::Notification]]] A hash from + # => + # + attr_reader :before_notification_collection + + # + # A Hash containing the immediate notifications triggered by resources + # during the converge phase of the chef run. + # + # @return [Hash[String, Array[Chef::Resource::Notification]]] A hash from + # => + # + attr_reader :immediate_notification_collection + + # + # A Hash containing the delayed (end of run) notifications triggered by + # resources during the converge phase of the chef run. + # + # @return [Hash[String, Array[Chef::Resource::Notification]]] A hash from + # => + # + attr_reader :delayed_notification_collection + + # + # An Array containing the delayed (end of run) notifications triggered by + # resources during the converge phase of the chef run. + # + # @return [Array[Chef::Resource::Notification]] An array of notification objects + # + attr_reader :delayed_actions + + # Creates a new Chef::RunContext object and populates its fields. This object gets + # used by the Chef Server to generate a fully compiled recipe list for a node. + # + # @param node [Chef::Node] The node to run against. + # @param cookbook_collection [Chef::CookbookCollection] The cookbooks + # involved in this run. + # @param events [EventDispatch::Dispatcher] The event dispatcher for this + # run. + # + def initialize(node, cookbook_collection, events) + @node = node + @cookbook_collection = cookbook_collection + @events = events + + node.run_context = self + node.set_cookbook_attribute + + @definitions = Hash.new + @loaded_recipes_hash = {} + @loaded_attributes_hash = {} + @reboot_info = {} + @cookbook_compiler = nil + @delayed_actions = [] + + initialize_child_state + end + + # + # Triggers the compile phase of the chef run. + # + # @param run_list_expansion [Chef::RunList::RunListExpansion] The run list. + # @see Chef::RunContext::CookbookCompiler + # + def load(run_list_expansion) + @cookbook_compiler = CookbookCompiler.new(self, run_list_expansion, events) + cookbook_compiler.compile + end + + # + # Initialize state that applies to both Chef::RunContext and Chef::ChildRunContext + # + def initialize_child_state + @audits = {} + @resource_collection = Chef::ResourceCollection.new(self) + @before_notification_collection = Hash.new { |h, k| h[k] = [] } + @immediate_notification_collection = Hash.new { |h, k| h[k] = [] } + @delayed_notification_collection = Hash.new { |h, k| h[k] = [] } + @delayed_actions = [] + end + + # + # Adds an before notification to the +before_notification_collection+. + # + # @param [Chef::Resource::Notification] The notification to add. + # + def notifies_before(notification) + # Note for the future, notification.notifying_resource may be an instance + # of Chef::Resource::UnresolvedSubscribes when calling {Resource#subscribes} + # with a string value. + before_notification_collection[notification.notifying_resource.declared_key] << notification + end + + # + # Adds an immediate notification to the +immediate_notification_collection+. + # + # @param [Chef::Resource::Notification] The notification to add. + # + def notifies_immediately(notification) + # Note for the future, notification.notifying_resource may be an instance + # of Chef::Resource::UnresolvedSubscribes when calling {Resource#subscribes} + # with a string value. + immediate_notification_collection[notification.notifying_resource.declared_key] << notification + end + + # + # Adds a delayed notification to the +delayed_notification_collection+. + # + # @param [Chef::Resource::Notification] The notification to add. + # + def notifies_delayed(notification) + # Note for the future, notification.notifying_resource may be an instance + # of Chef::Resource::UnresolvedSubscribes when calling {Resource#subscribes} + # with a string value. + delayed_notification_collection[notification.notifying_resource.declared_key] << notification + end + + # + # Adds a delayed action to the +delayed_actions+. + # + def add_delayed_action(notification) + if delayed_actions.any? { |existing_notification| existing_notification.duplicates?(notification) } + Chef::Log.info( "#{notification.notifying_resource} not queuing delayed action #{notification.action} on #{notification.resource}"\ + " (delayed), as it's already been queued") + else + delayed_actions << notification + end + end + + # + # Get the list of before notifications sent by the given resource. + # + # @return [Array[Notification]] + # + def before_notifications(resource) + return before_notification_collection[resource.declared_key] + end + + # + # Get the list of immediate notifications sent by the given resource. + # + # @return [Array[Notification]] + # + def immediate_notifications(resource) + return immediate_notification_collection[resource.declared_key] + end + + # + # Get the list of delayed (end of run) notifications sent by the given + # resource. + # + # @return [Array[Notification]] + # + def delayed_notifications(resource) + return delayed_notification_collection[resource.declared_key] + end + + # + # Cookbook and recipe loading + # + + # + # Evaluates the recipes +recipe_names+. Used by DSL::IncludeRecipe + # + # @param recipe_names [Array[String]] The list of recipe names (e.g. + # 'my_cookbook' or 'my_cookbook::my_resource'). + # @param current_cookbook The cookbook we are currently running in. + # + # @see DSL::IncludeRecipe#include_recipe + # + def include_recipe(*recipe_names, current_cookbook: nil) + result_recipes = Array.new + recipe_names.flatten.each do |recipe_name| + if result = load_recipe(recipe_name, current_cookbook: current_cookbook) + result_recipes << result + end + end + result_recipes + end + + # + # Evaluates the recipe +recipe_name+. Used by DSL::IncludeRecipe + # + # TODO I am sort of confused why we have both this and include_recipe ... + # I don't see anything different beyond accepting and returning an + # array of recipes. + # + # @param recipe_names [Array[String]] The recipe name (e.g 'my_cookbook' or + # 'my_cookbook::my_resource'). + # @param current_cookbook The cookbook we are currently running in. + # + # @return A truthy value if the load occurred; `false` if already loaded. + # + # @see DSL::IncludeRecipe#load_recipe + # + def load_recipe(recipe_name, current_cookbook: nil) + Chef::Log.debug("Loading recipe #{recipe_name} via include_recipe") + + cookbook_name, recipe_short_name = Chef::Recipe.parse_recipe_name(recipe_name, current_cookbook: current_cookbook) + + if unreachable_cookbook?(cookbook_name) # CHEF-4367 + Chef::Log.warn(<<-ERROR_MESSAGE) +MissingCookbookDependency: +Recipe `#{recipe_name}` is not in the run_list, and cookbook '#{cookbook_name}' +is not a dependency of any cookbook in the run_list. To load this recipe, +first add a dependency on cookbook '#{cookbook_name}' in the cookbook you're +including it from in that cookbook's metadata. +ERROR_MESSAGE + end + + if loaded_fully_qualified_recipe?(cookbook_name, recipe_short_name) + Chef::Log.debug("I am not loading #{recipe_name}, because I have already seen it.") + false + else + loaded_recipe(cookbook_name, recipe_short_name) + node.loaded_recipe(cookbook_name, recipe_short_name) + cookbook = cookbook_collection[cookbook_name] + cookbook.load_recipe(recipe_short_name, self) + end + end + + # + # Load the given recipe from a filename. + # + # @param recipe_file [String] The recipe filename. + # + # @return [Chef::Recipe] The loaded recipe. + # + # @raise [Chef::Exceptions::RecipeNotFound] If the file does not exist. + # + def load_recipe_file(recipe_file) + if !File.exist?(recipe_file) + raise Chef::Exceptions::RecipeNotFound, "could not find recipe file #{recipe_file}" + end + + Chef::Log.debug("Loading recipe file #{recipe_file}") + recipe = Chef::Recipe.new("@recipe_files", recipe_file, self) + recipe.from_file(recipe_file) + recipe + end + + # + # Look up an attribute filename. + # + # @param cookbook_name [String] The cookbook name of the attribute file. + # @param attr_file_name [String] The attribute file's name (not path). + # + # @return [String] The filename. + # + # @see DSL::IncludeAttribute#include_attribute + # + # @raise [Chef::Exceptions::CookbookNotFound] If the cookbook could not be found. + # @raise [Chef::Exceptions::AttributeNotFound] If the attribute file could not be found. + # + def resolve_attribute(cookbook_name, attr_file_name) + cookbook = cookbook_collection[cookbook_name] + raise Chef::Exceptions::CookbookNotFound, "could not find cookbook #{cookbook_name} while loading attribute #{name}" unless cookbook + + attribute_filename = cookbook.attribute_filenames_by_short_filename[attr_file_name] + raise Chef::Exceptions::AttributeNotFound, "could not find filename for attribute #{attr_file_name} in cookbook #{cookbook_name}" unless attribute_filename + + attribute_filename + end + + # + # A list of all recipes that have been loaded. + # + # This is stored internally as a Hash, so ordering is predictable. + # + # TODO is the above statement true in a 1.9+ ruby world? Is it relevant? + # + # @return [Array[String]] A list of recipes in fully qualified form, e.g. + # the recipe "nginx" will be given as "nginx::default". + # + # @see #loaded_recipe? To determine if a particular recipe has been loaded. + # + def loaded_recipes + loaded_recipes_hash.keys + end + + # + # A list of all attributes files that have been loaded. + # + # Stored internally using a Hash, so order is predictable. + # + # TODO is the above statement true in a 1.9+ ruby world? Is it relevant? + # + # @return [Array[String]] A list of attribute file names in fully qualified + # form, e.g. the "nginx" will be given as "nginx::default". + # + def loaded_attributes + loaded_attributes_hash.keys + end + + # + # Find out if a given recipe has been loaded. + # + # @param cookbook [String] Cookbook name. + # @param recipe [String] Recipe name. + # + # @return [Boolean] `true` if the recipe has been loaded, `false` otherwise. + # + def loaded_fully_qualified_recipe?(cookbook, recipe) + loaded_recipes_hash.has_key?("#{cookbook}::#{recipe}") + end + + # + # Find out if a given recipe has been loaded. + # + # @param recipe [String] Recipe name. "nginx" and "nginx::default" yield + # the same results. + # + # @return [Boolean] `true` if the recipe has been loaded, `false` otherwise. + # + def loaded_recipe?(recipe) + cookbook, recipe_name = Chef::Recipe.parse_recipe_name(recipe) + loaded_fully_qualified_recipe?(cookbook, recipe_name) + end + + # + # Mark a given recipe as having been loaded. + # + # @param cookbook [String] Cookbook name. + # @param recipe [String] Recipe name. + # + def loaded_recipe(cookbook, recipe) + loaded_recipes_hash["#{cookbook}::#{recipe}"] = true + end + + # + # Find out if a given attribute file has been loaded. + # + # @param cookbook [String] Cookbook name. + # @param attribute_file [String] Attribute file name. + # + # @return [Boolean] `true` if the recipe has been loaded, `false` otherwise. + # + def loaded_fully_qualified_attribute?(cookbook, attribute_file) + loaded_attributes_hash.has_key?("#{cookbook}::#{attribute_file}") + end + + # + # Mark a given attribute file as having been loaded. + # + # @param cookbook [String] Cookbook name. + # @param attribute_file [String] Attribute file name. + # + def loaded_attribute(cookbook, attribute_file) + loaded_attributes_hash["#{cookbook}::#{attribute_file}"] = true + end + + ## + # Cookbook File Introspection + + # + # Find out if the cookbook has the given template. + # + # @param cookbook [String] Cookbook name. + # @param template_name [String] Template name. + # + # @return [Boolean] `true` if the template is in the cookbook, `false` + # otherwise. + # @see Chef::CookbookVersion#has_template_for_node? + # + def has_template_in_cookbook?(cookbook, template_name) + cookbook = cookbook_collection[cookbook] + cookbook.has_template_for_node?(node, template_name) + end + + # + # Find out if the cookbook has the given file. + # + # @param cookbook [String] Cookbook name. + # @param cb_file_name [String] File name. + # + # @return [Boolean] `true` if the file is in the cookbook, `false` + # otherwise. + # @see Chef::CookbookVersion#has_cookbook_file_for_node? + # + def has_cookbook_file_in_cookbook?(cookbook, cb_file_name) + cookbook = cookbook_collection[cookbook] + cookbook.has_cookbook_file_for_node?(node, cb_file_name) + end + + # + # Find out whether the given cookbook is in the cookbook dependency graph. + # + # @param cookbook_name [String] Cookbook name. + # + # @return [Boolean] `true` if the cookbook is reachable, `false` otherwise. + # + # @see Chef::CookbookCompiler#unreachable_cookbook? + def unreachable_cookbook?(cookbook_name) + cookbook_compiler.unreachable_cookbook?(cookbook_name) + end + + # + # Open a stream object that can be printed into and will dispatch to events + # + # @param name [String] The name of the stream. + # @param options [Hash] Other options for the stream. + # + # @return [EventDispatch::EventsOutputStream] The created stream. + # + # @yield If a block is passed, it will be run and the stream will be closed + # afterwards. + # @yieldparam stream [EventDispatch::EventsOutputStream] The created stream. + # + def open_stream(name: nil, **options) + stream = EventDispatch::EventsOutputStream.new(events, name: name, **options) + if block_given? + begin + yield stream + ensure + stream.close + end + else + stream + end + end + + # there are options for how to handle multiple calls to these functions: + # 1. first call always wins (never change reboot_info once set). + # 2. last call always wins (happily change reboot_info whenever). + # 3. raise an exception on the first conflict. + # 4. disable reboot after this run if anyone ever calls :cancel. + # 5. raise an exception on any second call. + # 6. ? + def request_reboot(reboot_info) + Chef::Log.info "Changing reboot status from #{self.reboot_info.inspect} to #{reboot_info.inspect}" + @reboot_info = reboot_info + end + + def cancel_reboot + Chef::Log.info "Changing reboot status from #{reboot_info.inspect} to {}" + @reboot_info = {} + end + + def reboot_requested? + reboot_info.size > 0 + end + + # + # Create a child RunContext. + # + def create_child + ChildRunContext.new(self) + end + + # @api private + attr_writer :resource_collection + + protected + + attr_reader :cookbook_compiler + attr_reader :loaded_attributes_hash + attr_reader :loaded_recipes_hash + + module Deprecated + ### + # These need to be settable so deploy can run a resource_collection + # independent of any cookbooks via +recipe_eval+ + def audits=(value) + Chef.log_deprecation("Setting run_context.audits will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.") + @audits = value + end + + def immediate_notification_collection=(value) + Chef.log_deprecation("Setting run_context.immediate_notification_collection will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.") + @immediate_notification_collection = value + end + + def delayed_notification_collection=(value) + Chef.log_deprecation("Setting run_context.delayed_notification_collection will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.") + @delayed_notification_collection = value + end + end + prepend Deprecated + + # + # A child run context. Delegates all root context calls to its parent. + # + # @api private + # + class ChildRunContext < RunContext + extend Forwardable + def_delegators :parent_run_context, *%w{ + cancel_reboot + config + cookbook_collection + cookbook_compiler + definitions + events + has_cookbook_file_in_cookbook? + has_template_in_cookbook? + load + loaded_attribute + loaded_attributes + loaded_attributes_hash + loaded_fully_qualified_attribute? + loaded_fully_qualified_recipe? + loaded_recipe + loaded_recipe? + loaded_recipes + loaded_recipes_hash + node + open_stream + reboot_info + reboot_info= + reboot_requested? + request_reboot + resolve_attribute + unreachable_cookbook? + } + + def initialize(parent_run_context) + @parent_run_context = parent_run_context + + # We don't call super, because we don't bother initializing stuff we're + # going to delegate to the parent anyway. Just initialize things that + # every instance needs. + initialize_child_state + end + + CHILD_STATE = %w{ + audits + audits= + create_child + add_delayed_action + delayed_actions + delayed_notification_collection + delayed_notification_collection= + delayed_notifications + immediate_notification_collection + immediate_notification_collection= + immediate_notifications + before_notification_collection + before_notifications + include_recipe + initialize_child_state + load_recipe + load_recipe_file + notifies_before + notifies_immediately + notifies_delayed + parent_run_context + root_run_context + resource_collection + resource_collection= + }.map { |x| x.to_sym } + + # Verify that we didn't miss any methods + unless @__skip_method_checking # hook specifically for compat_resource + missing_methods = superclass.instance_methods(false) - instance_methods(false) - CHILD_STATE + if !missing_methods.empty? + raise "ERROR: not all methods of RunContext accounted for in ChildRunContext! All methods must be marked as child methods with CHILD_STATE or delegated to the parent_run_context. Missing #{missing_methods.join(", ")}." + end + end + end + end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/runner.rb b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/runner.rb new file mode 100644 index 0000000..9add7a8 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/runner.rb @@ -0,0 +1,153 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +if Gem::Requirement.new('< 12.16.42').satisfied_by?(Gem::Version.new(Chef::VERSION)) +#-- +# Author:: Adam Jacob () +# Author:: Christopher Walters () +# Author:: Tim Hinderliter () +# Copyright:: Copyright 2008-2016, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +require "chef/exceptions" +require "chef/mixin/params_validate" +require "chef/node" +require "chef/resource_collection" + +class Chef + # == Chef::Runner + # This class is responsible for executing the steps in a Chef run. + class Runner + + attr_reader :run_context + + include Chef::Mixin::ParamsValidate + + def initialize(run_context) + @run_context = run_context + end + + def delayed_actions + @run_context.delayed_actions + end + + def events + @run_context.events + end + + # Determine the appropriate provider for the given resource, then + # execute it. + def run_action(resource, action, notification_type = nil, notifying_resource = nil) + # If there are any before notifications, why-run the resource + # and notify anyone who needs notifying + before_notifications = run_context.before_notifications(resource) || [] + unless before_notifications.empty? + forced_why_run do + Chef::Log.info("#{resource} running why-run #{action} action to support before action") + resource.run_action(action, notification_type, notifying_resource) + end + + if resource.updated_by_last_action? + before_notifications.each do |notification| + Chef::Log.info("#{resource} sending #{notification.action} action to #{notification.resource} (before)") + run_action(notification.resource, notification.action, :before, resource) + end + resource.updated_by_last_action(false) + end + end + + # Actually run the action for realsies + resource.run_action(action, notification_type, notifying_resource) + + # Execute any immediate and queue up any delayed notifications + # associated with the resource, but only if it was updated *this time* + # we ran an action on it. + if resource.updated_by_last_action? + run_context.immediate_notifications(resource).each do |notification| + Chef::Log.info("#{resource} sending #{notification.action} action to #{notification.resource} (immediate)") + run_action(notification.resource, notification.action, :immediate, resource) + end + + run_context.delayed_notifications(resource).each do |notification| + # send the notification to the run_context of the receiving resource + notification.resource.run_context.add_delayed_action(notification) + end + end + end + + # Iterates over the +resource_collection+ in the +run_context+ calling + # +run_action+ for each resource in turn. + def converge + # Resolve all lazy/forward references in notifications + run_context.resource_collection.each do |resource| + resource.resolve_notification_references + end + + # Execute each resource. + run_context.resource_collection.execute_each_resource do |resource| + Array(resource.action).each { |action| run_action(resource, action) } + end + + rescue Exception => e + Chef::Log.info "Running queued delayed notifications before re-raising exception" + run_delayed_notifications(e) + else + run_delayed_notifications(nil) + true + end + + private + + # Run all our :delayed actions + def run_delayed_notifications(error = nil) + collected_failures = Exceptions::MultipleFailures.new + collected_failures.client_run_failure(error) unless error.nil? + delayed_actions.each do |notification| + result = run_delayed_notification(notification) + if result.kind_of?(Exception) + collected_failures.notification_failure(result) + end + end + collected_failures.raise! + end + + def run_delayed_notification(notification) + Chef::Log.info( "#{notification.notifying_resource} sending #{notification.action}"\ + " action to #{notification.resource} (delayed)") + # Struct of resource/action to call + run_action(notification.resource, notification.action, :delayed) + true + rescue Exception => e + e + end + + # helper to run a block of code with why_run forced to true and then restore it correctly + def forced_why_run + saved = Chef::Config[:why_run] + Chef::Config[:why_run] = true + yield + ensure + Chef::Config[:why_run] = saved + end + + end +end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/property.rb b/cookbooks/compat_resource/files/lib/chef_compat/property.rb new file mode 100644 index 0000000..be21113 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/property.rb @@ -0,0 +1,6 @@ +require 'chef_compat/copied_from_chef/chef/property' + +module ChefCompat + class Property < ChefCompat::CopiedFromChef::Chef::Property + end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/recipe.rb b/cookbooks/compat_resource/files/lib/chef_compat/recipe.rb new file mode 100644 index 0000000..86e39d9 --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/recipe.rb @@ -0,0 +1,8 @@ +require 'chef/recipe' +require 'chef_compat/copied_from_chef/chef/dsl/recipe' + +module ChefCompat + class Recipe < Chef::Recipe + include ChefCompat::CopiedFromChef::Chef::DSL::Recipe::FullDSL + end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/resource.rb b/cookbooks/compat_resource/files/lib/chef_compat/resource.rb new file mode 100644 index 0000000..bcf0fdb --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/resource.rb @@ -0,0 +1,56 @@ +require 'chef_compat/monkeypatches' +require 'chef_compat/copied_from_chef/chef/resource' + +# We do NOT want action defined if chefspec is engaged +if Chef::Provider::InlineResources::ClassMethods.instance_method(:action).source_location[0] =~ /chefspec/ + ChefCompat::CopiedFromChef::Chef::Provider::InlineResources::ClassMethods.instance_eval do + remove_method(:action) + end +end + +module ChefCompat + class Resource < ChefCompat::CopiedFromChef::Chef::Resource + def initialize(*args, &block) + super + # @resource_name is used in earlier Chef versions + @resource_name = self.class.resource_name + end + # Things we'll need to define ourselves: + # 1. provider + # 2. resource_name + + def provider(*args, &block) + super || self.class.action_class + end + def provider=(arg) + provider(arg) + end + + if !respond_to?(:resource_name) + def self.resource_name(name=Chef::NOT_PASSED) + # Setter + if name != Chef::NOT_PASSED + # remove_canonical_dsl + + # Set the resource_name and call provides + if name + name = name.to_sym + # If our class is not already providing this name, provide it. + # Commented out: use of resource_name and provides will need to be + # mutually exclusive in this world, generally. + # if !Chef::ResourceResolver.includes_handler?(name, self) + provides name#, canonical: true + # end + @resource_name = name + else + @resource_name = nil + end + end + @resource_name + end + def self.resource_name=(name) + resource_name(name) + end + end + end +end diff --git a/cookbooks/compat_resource/files/lib/chef_compat/resource/lwrp_base.rb b/cookbooks/compat_resource/files/lib/chef_compat/resource/lwrp_base.rb new file mode 100644 index 0000000..2ebb98f --- /dev/null +++ b/cookbooks/compat_resource/files/lib/chef_compat/resource/lwrp_base.rb @@ -0,0 +1,44 @@ +require 'chef_compat/resource' +require 'chef_compat/copied_from_chef/chef/resource' +require 'chef/mixin/convert_to_class_name' +require 'chef/mixin/from_file' + +module ChefCompat + class Resource < ChefCompat::CopiedFromChef::Chef::Resource + class LWRPBase < ChefCompat::Resource + class<= 12.0").satisfied_by?(Gem::Version.new(Chef::VERSION)) + + require 'chef_compat/resource' + require 'chef_compat/property' + require 'chef_compat/mixin/properties' + + resources_dir = File.expand_path("chef_compat/copied_from_chef/chef/resource", File.dirname(__FILE__)) + providers_dir = File.expand_path("chef_compat/copied_from_chef/chef/provider", File.dirname(__FILE__)) + Dir["#{resources_dir}/*.rb"].each {|file| require file } + Dir["#{providers_dir}/*.rb"].each {|file| require file } +else + + class Chef + class Resource + def self.property(args, &block) + raise_chef_11_error + end + + def self.resource_name(args, &block) + raise_chef_11_error + end + + def self.action(args, &block) + raise_chef_11_error + end + + def self.raise_chef_11_error + raise "This resource is written with Chef 12.5 custom resources, and requires at least Chef 12.0 used with the compat_resource cookbook, it will not work with Chef 11.x clients, and those users must pin their cookbooks to older versions or upgrade." + end + end + end + +end diff --git a/cookbooks/compat_resource/libraries/autoload.rb b/cookbooks/compat_resource/libraries/autoload.rb new file mode 100644 index 0000000..db52cfc --- /dev/null +++ b/cookbooks/compat_resource/libraries/autoload.rb @@ -0,0 +1,31 @@ +unless Gem::Requirement.new(">= 12.0").satisfied_by?(Gem::Version.new(Chef::VERSION)) + raise "This resource is written with Chef 12.5 custom resources, and requires at least Chef 12.0 used with the compat_resource cookbook, it will not work with Chef 11.x clients, and those users must pin their cookbooks to older versions or upgrade." +end + +# If users are on old verisons of ChefDK which activates an (old) gem via cheffish before this cookbook loads, then +# we just try to monkeypatch over the top of a monkeypatch. Its possible that we have checks in this cookbook which +# will defeat that purpose and fail to monkeypatch on top of monkeypatches -- in which case those checks should be +# removed -- this cookbook needs to win when it gets into a fight with the old gem versions. +if Gem.loaded_specs["compat_resource"] + Chef.log_deprecation "using compat_resource as a gem is deprecated; please update cheffish and chef-provisioning gems (or use the latest Chef/ChefDK packages) or else manually pin your compat_resource cookbook version to the same version as the gem you are using to remove this warning" +end + +# we want to not pollute the libpath with our files until after we've done the version check +require_relative '../files/lib/chef_upstream_version' + +# on any chef client later than the one we were based off of we just turn into a no-op +if Gem::Requirement.new("< #{ChefCompat::CHEF_UPSTREAM_VERSION}").satisfied_by?(Gem::Version.new(Chef::VERSION)) + Chef::Log.debug "loading compat_resource based on chef-version #{ChefCompat::CHEF_UPSTREAM_VERSION} over chef version #{Gem::Version.new(Chef::VERSION)}" + $LOAD_PATH.unshift(File.expand_path("../files/lib", File.dirname(__FILE__))) + require 'compat_resource' +else + Chef::Log.debug "NOT LOADING compat_resource based on chef-version #{ChefCompat::CHEF_UPSTREAM_VERSION} over chef version #{Gem::Version.new(Chef::VERSION)}" + unless defined?(ChefCompat::Resource) && defined?(ChefCompat::Mixin::Properties) + module ChefCompat + Resource = Chef::Resource + module Mixin + Properties = Chef::Mixin::Properties + end + end + end +end diff --git a/cookbooks/compat_resource/metadata.json b/cookbooks/compat_resource/metadata.json new file mode 100644 index 0000000..1df2f5d --- /dev/null +++ b/cookbooks/compat_resource/metadata.json @@ -0,0 +1 @@ +{"name":"compat_resource","version":"12.19.0","description":"Backports functionality introduced in the latest chef-client releases to any chef-client from 12.1 onwards","long_description":"# compat_resource cookbook\n\n[![Build Status](https://travis-ci.org/chef-cookbooks/compat_resource.svg?branch=master)](https://travis-ci.org/chef-cookbooks/compat_resource) [![Cookbook Version](https://img.shields.io/cookbook/v/compat_resource.svg)](https://supermarket.chef.io/cookbooks/compat_resource)\n\nThis cookbook backports functionality introduced in the latest chef-client releases to any chef-client from 12.1 onwards. This includes [Custom Resource](https://docs.chef.io/custom_resources.html) functionality, notification improvements, as well as new resources added to core chef. It allows for the usage of these new resources in cookbooks without requiring the very latest Chef client release.\n\n## Backported functionality\n\n- [Custom Resources](https://docs.chef.io/custom_resources.html)\n- [apt_repository](https://docs.chef.io/resource_apt_repository.html)\n- [apt_update](https://docs.chef.io/resource_apt_update.html)\n- [systemd_unit](https://docs.chef.io/resource_systemd_unit.html)\n- [yum_repository](https://docs.chef.io/resource_yum_repository.html)\n- [:before notifications](https://docs.chef.io/resources.html#timers)\n\n## Requirements\n\n### Platforms\n\n- All platforms supported by Chef\n\n### Chef\n\n- Chef 12.1+\n\n### Cookbooks\n\n- none\n\n## Usage\n\nTo use this cookbook, put `depends 'compat_resource'` in the metadata.rb of your cookbook. Once this is done, you can use all the new custom resource features to define resources. It Just Works.\n\n## Custom Resources?\n\nCurious about how to use custom resources?\n\n- Docs: \n- Slides: \n\n## License & Authors\n\n- Author:: Lamont Granquist ([lamont@chef.io](mailto:lamont@chef.io))\n- Author:: John Keiser ([jkeiser@chef.io](mailto:jkeiser@chef.io))\n\n```text\nCopyright:: 2015-2016 Chef Software, Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","maintainer":"Lamont Granquist","maintainer_email":"lamont@chef.io","license":"Apache 2.0","platforms":{},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/chef-cookbooks/compat_resource","issues_url":"https://github.com/chef-cookbooks/compat_resource/issues","chef_version":[[">= 12.1"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/composer/README.md b/cookbooks/composer/README.md new file mode 100644 index 0000000..d41686e --- /dev/null +++ b/cookbooks/composer/README.md @@ -0,0 +1,187 @@ +[![Build Status](https://travis-ci.org/djoos-cookbooks/composer.png)](https://travis-ci.org/djoos-cookbooks/composer) + +# composer cookbook + +## Description + +This cookbook provides an easy way to install Composer, a dependency manager for PHP. + +More information? +http://getcomposer.org/ + +## Requirements + +### Cookbooks: + +* php +* windows + +### Platforms: + +* Ubuntu +* Debian +* RHEL +* CentOS +* Fedora +* Windows + +## Attributes + +* `node['composer']['url']` - Location of the source +* `node['composer']['install_dir']` - Installation target directory (absolute or relative path) if installing locally +* `node['composer']['bin']` - bin directory +* `node['composer']['install_globally']` - Installation method, ':source' or ':package' - default true +* `node['composer']['mask']` - Mask for composer.phar - 0755 +* `node['composer']['link_type']` - link type for composer.phar link - default :symbolic +* `node['composer']['global_configs']` - Hash with global config options for users, eg. { "userX" => { "github-oauth" => { "github.com" => "userX_oauth_token" }, "vendor-dir" => "myvendordir" } } - default {} +* `node['composer']['home_dir']` - COMPOSER_HOME, defaults to nil (in which case install_dir will be used), please do read the [Composer documentation on COMPOSER_HOME](https://getcomposer.org/doc/03-cli.md#composer-home) when setting a custom home_dir +* `node['composer']['php_recipe']` - The php recipe to include, defaults to "php::default" +* `node['composer']['global_install']['install_dir']` - The default location to install the packages in for composer_install_global +* `node['composer']['global_install']['bin_dir']` - The default location to symlink the binaries when using composer_install_global + +## Resources / Providers +This cookbook includes an LWRP for managing a Composer project and one for a global installation of composer packages + +### `composer_project` + +#### Actions +- :install: Reads the composer.json file from the current directory, resolves the dependencies, and installs them into project directory - this is the default action +- :require Create composer.json file using specified package and version and installs it with the dependencies. +- :update: Gets the latest versions of the dependencies and updates the composer.lock file +- :dump_autoload: Updates the autoloader without having to go through an install or update (eg. because of new classes in a classmap package) +- :remove Removes package from composer.json and uninstalls it + +#### Attribute parameters +- project_dir: The directory where your project's composer.json can be found (name attribute) +- package: The package to require or remove when using those actions +- version: The version of the package to require or remove when using those actions, default *.*.* Be careful when uninstalling, the version has to match the installed package! +- vendor: Can be used to combine package and version, deprecated! +- dev: Install packages listed in require-dev, default false +- quiet: Do not output any message, default true +- optimize_autoloader: Optimize PSR0 packages to use classmaps, default false +- prefer_dist: use the dist installation method +- prefer_source: use the source installation method +- bin_dir, overwrites the composer bin dir +- user: the user to use when executing the composer commands +- group: the group to use when executing the composer commands +- umask: the umask to use when executing the composer commands +- environment: A hash of environment variables that will be available when running composer + +#### Examples +``` +# Install the project dependencies +composer_project "/path/to/project" do + dev false + quiet true + prefer_dist false + action :install +end + +# Require the package in the project dir +composer_project "/path/to/project" do + package 'vendor/package' + version '*.*.*' + dev false + quiet true + prefer_dist false + action :require +end + +# Update the project dependencies +composer_project "/path/to/project" do + dev false + quiet true + action :update +end + +# Dump-autoload in the project dir +composer_project "/path/to/project" do + dev false + quiet true + action :dump_autoload +end + +# Remove the package in the project dir +composer_project "/path/to/project" do + package 'vendor/package' + action :remove +end +``` + +### `composer_install_global` + +#### Actions +- :install: Installs the package in the preferred global composer directory, putting binary symlinks in the preferred global binary directory (see attributes) +- :update: Gets the latest versions of the dependencies and updates the composer.lock file for the globally installed composer packages +- :remove Removes package from the global composer.json and uninstalls it + +#### Attribute parameters +- package: The package to install or remove, name_attribute +- version: The version of the package to install or remove when using those actions, default *.*.* Be careful when uninstalling, the version has to match the installed package! +- install_dir: the directory in which to make the global installation, default: see the attributes +- bin_dir: the directory in which to make the symlinks to the binaries, default: see the attributes +- dev: Install packages listed in require-dev, default false +- quiet: Do not output any message, default true +- optimize_autoloader: Optimize PSR0 packages to use classmaps, default false +- prefer_dist: use the dist installation method +- prefer_source: use the source installation method + +#### Examples +``` +# Install a package globally +composer_install_global "package" do + version '~4.1' + action :install +end + +# Update the package +composer_install_global "package" do + action :update +end + +# Remove the package from the global installation +composer_install_global "package" do + action :remove +end +``` + +## Usage + +1. include `recipe[composer]` in a run list +2. tweak the attributes via attributes/default.rb +--- OR --- +[override the attribute on a higher level](http://wiki.opscode.com/display/chef/Attributes#Attributes-AttributesPrecedence) + +## References + +* [Composer home page] (http://getcomposer.org/) + +## License and Authors + +Author: David Joos +Copyright: 2016, David Joos + +Author: David Joos +Author: Escape Studios Development +Copyright: 2012-2015, Escape Studios + +Unless otherwise noted, all files are released under the MIT license, +possible exceptions will contain licensing information in them. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/cookbooks/composer/attributes/default.rb b/cookbooks/composer/attributes/default.rb new file mode 100644 index 0000000..bb99dca --- /dev/null +++ b/cookbooks/composer/attributes/default.rb @@ -0,0 +1,29 @@ +# +# Cookbook Name:: composer +# Attributes:: default +# +# Copyright (c) 2016, David Joos +# + +include_attribute 'php' + +if node['platform'] == 'windows' + default['composer']['url'] = 'https://getcomposer.org/Composer-Setup.exe' + default['composer']['install_dir'] = 'C:\\ProgramData\\ComposerSetup' + default['composer']['bin'] = "#{node['composer']['install_dir']}\\composer.bat" + default['composer']['global_install']['install_dir'] = 'C:\\Program\ Files\\Composer' + default['composer']['global_install']['bin_dir'] = 'C:\\ProgramData\\Composer' +else + default['composer']['url'] = 'http://getcomposer.org/composer.phar' + default['composer']['install_dir'] = '/usr/local/bin' + default['composer']['bin'] = "#{node['composer']['install_dir']}/composer" + default['composer']['install_globally'] = true + default['composer']['mask'] = '0755' + default['composer']['link_type'] = :symbolic + default['composer']['global_install']['install_dir'] = '/usr/local/composer' + default['composer']['global_install']['bin_dir'] = '/usr/local/bin' +end + +default['composer']['global_configs'] = {} +default['composer']['home_dir'] = nil +default['composer']['php_recipe'] = 'php::default' diff --git a/cookbooks/composer/libraries/composer.rb b/cookbooks/composer/libraries/composer.rb new file mode 100644 index 0000000..f9e3abc --- /dev/null +++ b/cookbooks/composer/libraries/composer.rb @@ -0,0 +1,10 @@ +# Composer module +module Composer + def self.install_dir(node) + node['composer']['install_dir'] + end + + def self.home_dir(node) + node['composer']['home_dir'] || install_dir(node) + end +end diff --git a/cookbooks/composer/metadata.json b/cookbooks/composer/metadata.json new file mode 100644 index 0000000..d86a891 --- /dev/null +++ b/cookbooks/composer/metadata.json @@ -0,0 +1,63 @@ +{ + "name": "composer", + "description": "Installs/Configures Composer", + "long_description": "[![Build Status](https://travis-ci.org/djoos-cookbooks/composer.png)](https://travis-ci.org/djoos-cookbooks/composer)\n\n# composer cookbook\n\n## Description\n\nThis cookbook provides an easy way to install Composer, a dependency manager for PHP.\n\nMore information?\nhttp://getcomposer.org/\n\n## Requirements\n\n### Cookbooks:\n\n* php\n* windows\n\n### Platforms:\n\n* Ubuntu\n* Debian\n* RHEL\n* CentOS\n* Fedora\n* Windows\n\n## Attributes\n\n* `node['composer']['url']` - Location of the source\n* `node['composer']['install_dir']` - Installation target directory (absolute or relative path) if installing locally\n* `node['composer']['bin']` - bin directory\n* `node['composer']['install_globally']` - Installation method, ':source' or ':package' - default true\n* `node['composer']['mask']` - Mask for composer.phar - 0755\n* `node['composer']['link_type']` - link type for composer.phar link - default :symbolic\n* `node['composer']['global_configs']` - Hash with global config options for users, eg. { \"userX\" => { \"github-oauth\" => { \"github.com\" => \"userX_oauth_token\" }, \"vendor-dir\" => \"myvendordir\" } } - default {}\n* `node['composer']['home_dir']` - COMPOSER_HOME, defaults to nil (in which case install_dir will be used), please do read the [Composer documentation on COMPOSER_HOME](https://getcomposer.org/doc/03-cli.md#composer-home) when setting a custom home_dir\n* `node['composer']['php_recipe']` - The php recipe to include, defaults to \"php::default\"\n* `node['composer']['global_install']['install_dir']` - The default location to install the packages in for composer_install_global\n* `node['composer']['global_install']['bin_dir']` - The default location to symlink the binaries when using composer_install_global\n\n## Resources / Providers\nThis cookbook includes an LWRP for managing a Composer project and one for a global installation of composer packages\n\n### `composer_project`\n\n#### Actions\n- :install: Reads the composer.json file from the current directory, resolves the dependencies, and installs them into project directory - this is the default action\n- :require Create composer.json file using specified package and version and installs it with the dependencies.\n- :update: Gets the latest versions of the dependencies and updates the composer.lock file\n- :dump_autoload: Updates the autoloader without having to go through an install or update (eg. because of new classes in a classmap package)\n- :remove Removes package from composer.json and uninstalls it\n\n#### Attribute parameters\n- project_dir: The directory where your project's composer.json can be found (name attribute)\n- package: The package to require or remove when using those actions\n- version: The version of the package to require or remove when using those actions, default *.*.* Be careful when uninstalling, the version has to match the installed package!\n- vendor: Can be used to combine package and version, deprecated!\n- dev: Install packages listed in require-dev, default false\n- quiet: Do not output any message, default true\n- optimize_autoloader: Optimize PSR0 packages to use classmaps, default false\n- prefer_dist: use the dist installation method\n- prefer_source: use the source installation method\n- bin_dir, overwrites the composer bin dir\n- user: the user to use when executing the composer commands\n- group: the group to use when executing the composer commands\n- umask: the umask to use when executing the composer commands\n- environment: A hash of environment variables that will be available when running composer\n\n#### Examples\n```\n# Install the project dependencies\ncomposer_project \"/path/to/project\" do\n dev false\n quiet true\n prefer_dist false\n action :install\nend\n\n# Require the package in the project dir\ncomposer_project \"/path/to/project\" do\n package 'vendor/package'\n version '*.*.*'\n dev false\n quiet true\n prefer_dist false\n action :require\nend\n\n# Update the project dependencies\ncomposer_project \"/path/to/project\" do\n dev false\n quiet true\n action :update\nend\n\n# Dump-autoload in the project dir\ncomposer_project \"/path/to/project\" do\n dev false\n quiet true\n action :dump_autoload\nend\n\n# Remove the package in the project dir\ncomposer_project \"/path/to/project\" do\n package 'vendor/package'\n action :remove\nend\n```\n\n### `composer_install_global`\n\n#### Actions\n- :install: Installs the package in the preferred global composer directory, putting binary symlinks in the preferred global binary directory (see attributes)\n- :update: Gets the latest versions of the dependencies and updates the composer.lock file for the globally installed composer packages\n- :remove Removes package from the global composer.json and uninstalls it\n\n#### Attribute parameters\n- package: The package to install or remove, name_attribute\n- version: The version of the package to install or remove when using those actions, default *.*.* Be careful when uninstalling, the version has to match the installed package!\n- install_dir: the directory in which to make the global installation, default: see the attributes\n- bin_dir: the directory in which to make the symlinks to the binaries, default: see the attributes\n- dev: Install packages listed in require-dev, default false\n- quiet: Do not output any message, default true\n- optimize_autoloader: Optimize PSR0 packages to use classmaps, default false\n- prefer_dist: use the dist installation method\n- prefer_source: use the source installation method\n\n#### Examples\n```\n# Install a package globally\ncomposer_install_global \"package\" do\n version '~4.1'\n action :install\nend\n\n# Update the package\ncomposer_install_global \"package\" do\n action :update\nend\n\n# Remove the package from the global installation\ncomposer_install_global \"package\" do\n action :remove\nend\n```\n\n## Usage\n\n1. include `recipe[composer]` in a run list\n2. tweak the attributes via attributes/default.rb\n--- OR ---\n[override the attribute on a higher level](http://wiki.opscode.com/display/chef/Attributes#Attributes-AttributesPrecedence)\n\n## References\n\n* [Composer home page] (http://getcomposer.org/)\n\n## License and Authors\n\nAuthor: David Joos \nCopyright: 2016, David Joos\n\nAuthor: David Joos \nAuthor: Escape Studios Development \nCopyright: 2012-2015, Escape Studios\n\nUnless otherwise noted, all files are released under the MIT license,\npossible exceptions will contain licensing information in them.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n", + "maintainer": "David Joos", + "maintainer_email": "development@davidjoos.com", + "license": "MIT", + "platforms": { + "debian": ">= 0.0.0", + "ubuntu": ">= 0.0.0", + "redhat": ">= 0.0.0", + "centos": ">= 0.0.0", + "fedora": ">= 0.0.0", + "scientific": ">= 0.0.0", + "amazon": ">= 0.0.0", + "windows": ">= 0.0.0" + }, + "dependencies": { + "apt": ">= 0.0.0", + "php": ">= 0.0.0", + "windows": ">= 0.0.0" + }, + "recommendations": { + + }, + "suggestions": { + + }, + "conflicting": { + + }, + "providing": { + + }, + "replacing": { + + }, + "attributes": { + + }, + "groupings": { + + }, + "recipes": { + "composer": "Installs (if applicable) and self-updates composer.", + "composer::install": "Installs composer.", + "composer::self_update": "Installs (if applicable) and self-updates composer.", + "composer::global_configs": "Sets up global config options via `composer config --global`" + }, + "version": "2.6.1", + "source_url": "https://github.com/djoos-cookbooks/composer", + "issues_url": "https://github.com/djoos-cookbooks/composer/issues", + "privacy": false, + "chef_versions": [ + + ], + "ohai_versions": [ + + ], + "gems": [ + + ] +} diff --git a/cookbooks/composer/metadata.rb b/cookbooks/composer/metadata.rb new file mode 100644 index 0000000..4cc7da0 --- /dev/null +++ b/cookbooks/composer/metadata.rb @@ -0,0 +1,23 @@ +name 'composer' +maintainer 'David Joos' +maintainer_email 'development@davidjoos.com' +license 'MIT' +description 'Installs/Configures Composer' +long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) +version '2.6.1' + +%w(debian ubuntu redhat centos fedora scientific amazon windows).each do |os| + supports os +end + +source_url 'https://github.com/djoos-cookbooks/composer' if respond_to?(:source_url) +issues_url 'https://github.com/djoos-cookbooks/composer/issues' if respond_to?(:issues_url) + +depends 'apt' +depends 'php' +depends 'windows' + +recipe 'composer', 'Installs (if applicable) and self-updates composer.' +recipe 'composer::install', 'Installs composer.' +recipe 'composer::self_update', 'Installs (if applicable) and self-updates composer.' +recipe 'composer::global_configs', 'Sets up global config options via `composer config --global`' diff --git a/cookbooks/composer/providers/install_global.rb b/cookbooks/composer/providers/install_global.rb new file mode 100644 index 0000000..8022a64 --- /dev/null +++ b/cookbooks/composer/providers/install_global.rb @@ -0,0 +1,78 @@ +# +# Cookbook Name:: composer +# Resource:: install_global +# +# Copyright 2012-2014, Escape Studios +# + +use_inline_resources if defined?(use_inline_resources) + +def whyrun_supported? + true +end + +action :install do + install_global_install + new_resource.updated_by_last_action(true) +end + +action :remove do + install_global_remove + new_resource.updated_by_last_action(true) +end + +action :update do + install_global_update + new_resource.updated_by_last_action(true) +end + +def install_global_install + install_dir = new_resource.install_dir ? new_resource.install_dir : node['composer']['global_install']['install_dir'] + bin_dir = new_resource.bin_dir ? new_resource.bin_dir : node['composer']['global_install']['bin_dir'] + directory install_dir + + composer_project install_dir do + package new_resource.package + version new_resource.version + bin_dir bin_dir + dev new_resource.dev + quiet new_resource.quiet + optimize_autoloader new_resource.optimize_autoloader + prefer_dist new_resource.prefer_dist + prefer_source new_resource.prefer_source + action :require + end +end + +def install_global_remove + install_dir = new_resource.install_dir ? new_resource.install_dir : node['composer']['global_install']['install_dir'] + + composer_project install_dir do + package new_resource.package + version new_resource.version + bin_dir bin_dir + dev new_resource.dev + quiet new_resource.quiet + optimize_autoloader new_resource.optimize_autoloader + prefer_dist new_resource.prefer_dist + prefer_source new_resource.prefer_source + action :remove + end +end + +def install_global_update + install_dir = new_resource.install_dir ? new_resource.install_dir : node['composer']['global_install']['install_dir'] + bin_dir = new_resource.bin_dir ? new_resource.bin_dir : node['composer']['global_install']['bin_dir'] + + composer_project install_dir do + package new_resource.package + version new_resource.version + bin_dir bin_dir + dev new_resource.dev + quiet new_resource.quiet + optimize_autoloader new_resource.optimize_autoloader + prefer_dist new_resource.prefer_dist + prefer_source new_resource.prefer_source + action :update + end +end diff --git a/cookbooks/composer/providers/project.rb b/cookbooks/composer/providers/project.rb new file mode 100644 index 0000000..11064ad --- /dev/null +++ b/cookbooks/composer/providers/project.rb @@ -0,0 +1,125 @@ +# +# Cookbook Name:: composer +# Resource:: project +# +# Copyright (c) 2016, David Joos +# + +use_inline_resources if defined?(use_inline_resources) + +def whyrun_supported? + true +end + +action :install do + make_execute 'install' + new_resource.updated_by_last_action(true) +end + +action :require do + make_require +end + +action :update do + make_execute 'update' + new_resource.updated_by_last_action(true) +end + +action :dump_autoload do + make_execute 'dump-autoload' + new_resource.updated_by_last_action(true) +end + +action :remove do + remove_package 'remove' +end + +def make_execute(cmd) + dev = new_resource.dev ? '--dev' : '--no-dev' + quiet = new_resource.quiet ? '--quiet' : '' + optimize = new_resource.optimize_autoloader ? optimize_flag(cmd) : '' + prefer_dist = new_resource.prefer_dist ? '--prefer-dist' : '' + prefer_source = new_resource.prefer_source ? '--prefer-source' : '' + environment = { + :COMPOSER_HOME => Composer.home_dir(node), + :COMPOSER_BIN_DIR => new_resource.bin_dir + } + + execute "#{cmd}-composer-for-project" do + cwd new_resource.project_dir + command "#{node['composer']['bin']} #{cmd} --no-interaction --no-ansi #{quiet} #{dev} #{optimize} #{prefer_dist} #{prefer_source}" + environment(environment.merge(new_resource.environment)) + action :run + user new_resource.user + group new_resource.group + umask new_resource.umask + end +end + +def make_require + dev = new_resource.dev ? '--dev' : '--update-no-dev' + package = new_resource.package + version = new_resource.version ? new_resource.version : '*.*.*' + package, version = vendor_package_identity(new_resource.vendor, package, version) + raise 'package is needed for composer_project with action require' if package.nil? + prefer_dist = new_resource.prefer_dist ? '--prefer-dist' : '' + environment = { + :COMPOSER_HOME => Composer.home_dir(node), + :COMPOSER_BIN_DIR => new_resource.bin_dir + } + + execute 'Install-composer-for-single-project' do + cwd new_resource.project_dir + command "#{node['composer']['bin']} require #{package}:#{version} #{dev} #{prefer_dist}" + environment(environment.merge(new_resource.environment)) + action :run + not_if do + !version.include?('*') && + shell_out("cd #{new_resource.project_dir} && #{node['composer']['bin']} show #{package} #{version}").exitstatus.zero? + end + user new_resource.user + group new_resource.group + umask new_resource.umask + end +end + +def remove_package(cmd) + package = new_resource.package + version = new_resource.version ? new_resource.version : '*.*.*' + package, version = vendor_package_identity(new_resource.vendor, package, version) + raise 'package is needed for composer_project with action require' if package.nil? + environment = { + :COMPOSER_HOME => Composer.home_dir(node), + :COMPOSER_BIN_DIR => new_resource.bin_dir + } + + execute "#{cmd}-composer-for-project" do + cwd new_resource.project_dir + command "#{node['composer']['bin']} remove #{package}" + environment(environment.merge(new_resource.environment)) + action :run + only_if "#{node['composer']['bin']} show #{package} #{version}" + end +end + +def optimize_flag(cmd) + %(install update).include?(cmd) ? '--optimize-autoloader' : '--optimize' +end + +def vendor_package_identity(vendor, package, version) + unless vendor.nil? + # @todo take out deprecated vendor logic + Chef::Log.warn('The vendor attribute is deprecated, please use package and version instead.') + + vendor_split = vendor.split(':') + package = vendor_split[0] + + version = if vendor_split[1].nil? + version + else + vendor_split[1] + end + end + + [package, version] +end diff --git a/cookbooks/composer/recipes/default.rb b/cookbooks/composer/recipes/default.rb new file mode 100644 index 0000000..d2981ca --- /dev/null +++ b/cookbooks/composer/recipes/default.rb @@ -0,0 +1,12 @@ +# +# Cookbook Name:: composer +# Recipe:: default +# +# Copyright (c) 2016, David Joos +# + +include_recipe 'composer::install' + +if node['composer']['install_globally'] + include_recipe 'composer::global_configs' +end diff --git a/cookbooks/composer/recipes/global_configs.rb b/cookbooks/composer/recipes/global_configs.rb new file mode 100644 index 0000000..6a92623 --- /dev/null +++ b/cookbooks/composer/recipes/global_configs.rb @@ -0,0 +1,45 @@ +# +# Cookbook Name:: composer +# Recipe:: global_configs +# +# Copyright (c) 2016, David Joos +# + +configs = node['composer']['global_configs'] + +unless configs.nil? + configs.each_pair do |user, user_configs| + user_composer_dir = "#{Dir.home(user)}/.composer" + + directory user_composer_dir do + owner user + group user + mode '0755' + action :create + end + + user_configs.nil? && next + + user_configs.each_pair do |option, value| + if value.respond_to?(:each_pair) + value.each_pair do |value_k, value_v| + execute "composer-config-for-#{user}" do + command "composer config --global #{option}.#{value_k} #{value_v}" + environment 'COMPOSER_HOME' => user_composer_dir + user user + group user + action :run + end + end + else + execute "composer-config-for-#{user}" do + command "composer config --global #{option} #{value}" + environment 'COMPOSER_HOME' => user_composer_dir + user user + group user + action :run + end + end + end + end +end diff --git a/cookbooks/composer/recipes/install.rb b/cookbooks/composer/recipes/install.rb new file mode 100755 index 0000000..477b418 --- /dev/null +++ b/cookbooks/composer/recipes/install.rb @@ -0,0 +1,36 @@ +# +# Cookbook Name:: composer +# Recipe:: install +# +# Copyright (c) 2016, David Joos +# + +include_recipe node['composer']['php_recipe'] + +if node['platform'] == 'windows' + windows_package 'Composer - PHP Dependency Manager' do + source node['composer']['url'] + options %w( + /VERYSILENT + ).join(' ') + end + + install_dir = "#{node['composer']['install_dir'].tr('/', '\\')}\\bin" + + ENV['PATH'] += ";#{install_dir}" + windows_path install_dir +else + log '[composer] phar (PHP archive) not supported' do + level :warn + not_if "php -m | grep 'Phar'" + end + + file = node['composer']['install_globally'] ? "#{node['composer']['install_dir']}/composer" : "#{node['composer']['install_dir']}/composer.phar" + + remote_file file do + source node['composer']['url'] + mode node['composer']['mask'] + action :create + not_if { ::File.exist?(file) } + end +end diff --git a/cookbooks/composer/recipes/self_update.rb b/cookbooks/composer/recipes/self_update.rb new file mode 100644 index 0000000..25d1bc1 --- /dev/null +++ b/cookbooks/composer/recipes/self_update.rb @@ -0,0 +1,16 @@ +# +# Cookbook Name:: composer +# Recipe:: self_update +# +# Copyright (c) 2016, David Joos +# + +include_recipe 'composer::install' + +execute 'composer-self_update' do + cwd node['composer']['install_dir'] + command 'composer self-update' + environment 'COMPOSER_HOME' => Composer.home_dir(node) + action :run + ignore_failure true +end diff --git a/cookbooks/composer/resources/install_global.rb b/cookbooks/composer/resources/install_global.rb new file mode 100644 index 0000000..93f259d --- /dev/null +++ b/cookbooks/composer/resources/install_global.rb @@ -0,0 +1,24 @@ +# +# Cookbook Name:: composer +# Resource:: install_global +# +# Copyright 2012-2014, Escape Studios +# + +actions :install, :update, :remove +default_action :install + +attribute :package, :kind_of => String, :name_attribute => true, :required => true +attribute :version, :kind_of => String, :default => '*.*.*' +attribute :install_dir, :kind_of => String, :default => nil +attribute :bin_dir, :kind_of => String, :default => nil +attribute :dev, :kind_of => [TrueClass, FalseClass], :default => false +attribute :quiet, :kind_of => [TrueClass, FalseClass], :default => true +attribute :optimize_autoloader, :kind_of => [TrueClass, FalseClass], :default => false +attribute :prefer_dist, :kind_of => [TrueClass, FalseClass], :default => false +attribute :prefer_source, :kind_of => [TrueClass, FalseClass], :default => false + +def initialize(*args) + super + @action = :install +end diff --git a/cookbooks/composer/resources/project.rb b/cookbooks/composer/resources/project.rb new file mode 100644 index 0000000..1780ef2 --- /dev/null +++ b/cookbooks/composer/resources/project.rb @@ -0,0 +1,29 @@ +# +# Cookbook Name:: composer +# Resource:: project +# +# Copyright (c) 2016, David Joos +# + +actions :install, :single, :require, :update, :dump_autoload, :remove +default_action :install + +attribute :project_dir, :kind_of => String, :name_attribute => true +attribute :vendor, :kind_of => String, :default => nil +attribute :package, :kind_of => String, :default => nil +attribute :version, :kind_of => String, :default => nil +attribute :dev, :kind_of => [TrueClass, FalseClass], :default => false +attribute :quiet, :kind_of => [TrueClass, FalseClass], :default => true +attribute :optimize_autoloader, :kind_of => [TrueClass, FalseClass], :default => false +attribute :prefer_dist, :kind_of => [TrueClass, FalseClass], :default => false +attribute :prefer_source, :kind_of => [TrueClass, FalseClass], :default => false +attribute :bin_dir, :kind_of => String, :default => 'vendor/bin' +attribute :user, :kind_of => String, :default => 'root' +attribute :group, :kind_of => String, :default => 'root' +attribute :umask, :kind_of => [String, Integer], :default => '0002' +attribute :environment, :kind_of => Hash, :default => {} + +def initialize(*args) + super + @action = :install +end diff --git a/cookbooks/dmg/CHANGELOG.md b/cookbooks/dmg/CHANGELOG.md new file mode 100644 index 0000000..a5f10e0 --- /dev/null +++ b/cookbooks/dmg/CHANGELOG.md @@ -0,0 +1,142 @@ +# dmg Cookbook CHANGELOG + +This file is used to list changes made in each version of the dmg cookbook. + +## 4.1.1 (2018-04-06) + +- The dmg_package resource is now included in Chef 14 and this cookbook has been deprecated. We highly recommend updating to Chef 14 so you can use this resource without the need for a cookbook dependency. +- Validate the type field in the resource +- Remove the now autogenerated ChefSpec matchers + +## 4.1.0 (2017-11-15) + +- Adds allow_untrusted property for older packages that aren't signed +- Resolve Chef 14 deprecation warnings +- Minor testing updates and cleanup + +## 4.0.0 (2017-04-27) + +- Converted the existing LWRP to a custom resource which increases the required chef-client release to 12.5+ +- Added Test Kitchen config with private atlas boxes for 10.10 and 10.11 +- Added a test recipe to installed Tunnelblick +- Added an Inspec test to confirm that Tunnelblick actually installs +- Remove unused attributes and the entire attributes file +- Add a warning if you include the default recipe on your runlist +- Update specs to run on 10.12 and against the test recipe since dmg::default is empty and the existing spec tested nothing + +## 3.1.1 (2017-04-11) + +- Cookstyle updates +- Test with Local Delivery and not Rake +- Update apache2 license string +- Remove foodcritic exclusions + +## 3.1.0 (2017-01-18) + +- Fixed pkg,mpkg installation when it was using mounted app name while it was actually mounted under different name for some applications +- Cookstyle fixes + +## 3.0.0 (2016-09-06) + +- Add chef_version metadata +- Run the specs against a mock of OS X +- Testing updates +- Require Chef 12+ + +## v2.4.0 (2016-04-26) + +- Added support for local .dmg files with the file property. See the readme for details +- Resolved all rubocop warnings + +## v2.3.0 (2015-10-20) + +- Add new headers property to the LWRP for custom http headers. See the readme for more information +- Removed pivotal tracker example in the readme +- Added travis and cookbook version badges to the readme +- Added a .foodcritic file to exclude rules +- Updated chefignore and .gitignore files +- Updated platforms in Test Kitchen +- Added standard Rubocop file +- Updated Travis to test using ChefDK for the latest deps +- Added a Berksfile +- Updated contributing and testing docs +- Updated Gemfile with the latest testing deps +- Added maintainers.md and maintainers.toml +- Added rakefile for simplified testing +- Added source_url and issues_url metadata +- Added basic converge chefspec + +## v2.2.2 (2014-11-12) + +- # 23, add chefspec matchers + +## v2.2.0 (2014-02-25) + +- [COOK-4285] Accept long EULAs + +## v2.1.4 (2014-01-26) + +- [COOK-4157] - dmg_package LWRP broken due to "puts" instead of "system" +- [COOK-4065] - dmg cookbook outputs the name of packages when checking if they are installed + +## v2.1.2 + +Cleaning up merge errors + +## v2.1.0 + +### Bug + +- **[COOK-3946](https://tickets.chef.io/browse/COOK-3946)** - Syntax error in resources/package.rb +- **[COOK-2672](https://tickets.chef.io/browse/COOK-2672)** - EULA for package is displayed instead accepted + +## v2.0.8 + +Adding a Chef 10 compatibility check in provider + +## v2.0.6 + +# BUG + +- [COOK-3302] - Sometimes hdiutil detach fails due to cfprefsd running in background + + # IMPROVEMENT + +- Adding foodcritic and rubocop to .travis.yml + +## v2.0.4 + +### Bug + +- **[COOK-3331](https://tickets.chef.io/browse/COOK-3331)** - Fix an issue where `dmg_package` with no source raises an exception + +## v2.0.2 + +### Bug + +- **[COOK-3578](https://tickets.chef.io/browse/COOK-3578)** - Support `package_id`s with spaces +- **[COOK-3302](https://tickets.chef.io/browse/COOK-3302)** - Fix an issue where `hdiutil detach` fails due to `cfprefsd` running in the background + +## v2.0.0 + +### Bug + +- **[COOK-3389](https://tickets.chef.io/browse/COOK-3389)** - Use `rsync` instead of `cp` (potentially a breaking change on some systems) + +## v1.1.0 + +- [COOK-1847] - accept owner parameter for installing packages + +## v1.0.0 + +- [COOK-852] - Support "pkg" in addition to "mpkg" package types + +## v0.7.0 + +- [COOK-854] - use `cp -R` instead of `cp -r` +- [COOK-855] - specify a file or directory to check for prior install + +## v0.6.0 + +- option to install software that is an .mpkg inside a .dmg +- ignore failure on chmod in case mode is already set, or is root owned diff --git a/cookbooks/dmg/CONTRIBUTING.md b/cookbooks/dmg/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/dmg/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/cookbooks/dmg/README.md b/cookbooks/dmg/README.md new file mode 100644 index 0000000..86f95aa --- /dev/null +++ b/cookbooks/dmg/README.md @@ -0,0 +1,149 @@ +The dmg_package resource is now included in Chef 14 and this cookbook has been deprecated. We highly recommend updating to Chef 14 so you can use this resource without the need for a cookbook dependency. + +# dmg Cookbook + +[![Build Status](https://travis-ci.org/chef-cookbooks/dmg.svg?branch=master)](https://travis-ci.org/chef-cookbooks/dmg) [![Cookbook Version](https://img.shields.io/cookbook/v/dmg.svg)](https://supermarket.chef.io/cookbooks/dmg) + +Resource to install OS X applications (.app) from dmg files. + +## Requirements + +### Platforms + +- macOS + +### Chef + +- Chef 12.5+ + +### Cookbooks + +- none + +## Resources/Providers + +### dmg_package + +This resource will install a DMG "Package". It will retrieve the DMG from a remote URL, mount it using OS X's `hdid`, copy the application (.app directory) to the specified destination (/Applications), and detach the image using `hdiutil`. The dmg file will be stored in the `Chef::Config[:file_cache_path]`. If you want to install an application that has already been downloaded (not using the `source` parameter), copy it to the appropriate location. You can find out what directory this is with the following command on the node to run chef: + +```bash +knife exec -E 'p Chef::Config[:file_cache_path]' -c /etc/chef/client.rb +``` + +Optionally, the LWRP can install an "mpkg" or "pkg" package using installer(8). + +#### Actions + +- :install - Installs the application. + +#### Parameter attributes: + +- `app` - This is the name of the application used by default for the /Volumes directory and the .app directory copied to /Applications. +- `source` - remote URL for the dmg to download if specified. Default is nil. +- `file` - local dmg full file path. Default is nil. +- `owner` - owner that should own the package installation. +- `destination` - directory to copy the .app into. Default is /Applications. +- `checksum` - sha256 checksum of the dmg to download. Default is nil. +- `type` - type of package, "app", "pkg" or "mpkg". Default is "app". When using "pkg" or "mpkg", the destination must be /Applications. +- `volumes_dir` - Directory under /Volumes where the dmg is mounted. Not all dmgs are mounted into a /Volumes location matching the name of the dmg. If not specified, this will use the name attribute. +- `package_id` - Package id registered with pkgutil when a pkg or mpkg is installed +- `dmg_name` - Specify the name of the dmg if it is not the same as `app`, or if the name has spaces. +- `dmg_passphrase` - Specify a passphrase to use to unencrypt the dmg while mounting. +- `accept_eula` - Specify whether to accept the EULA. Certain dmgs require acceptance of EULA before mounting. Can be true or false, defaults to false. +- `headers` - Allows custom HTTP headers (like cookies) to be set on the remote_file resource. +- `allow_untrusted` - Allows packages with untrusted certs to be installed. + +#### Examples + +Install `/Applications/Tunnelblick.app` from the primary download site. + +```ruby +dmg_package 'Tunnelblick' do + source 'https://tunnelblick.net/release/Tunnelblick_3.7.0_build_4790.dmg' + checksum '5053038aa8caf7dea66dcab11d6d240672216e6546eff4c2622e216c61af85e5' + action :install +end +``` + +Install Google Chrome. Uses the `dmg_name` because the application name has spaces. Installs in `/Applications/Google Chrome.app`. + +```ruby +dmg_package 'Google Chrome' do + dmg_name 'googlechrome' + source 'https://dl-ssl.google.com/chrome/mac/stable/GGRM/googlechrome.dmg' + checksum '7daa2dc5c46d9bfb14f1d7ff4b33884325e5e63e694810adc58f14795165c91a' + action :install +end +``` + +Install Dropbox. Uses `volumes_dir` because the mounted directory is different than the name of the application directory. Installs in `/Applications/Dropbox.app`. + +```ruby +dmg_package 'Dropbox' do + volumes_dir 'Dropbox Installer' + source 'http://www.dropbox.com/download?plat=mac' + checksum 'b4ea620ca22b0517b75753283ceb82326aca8bc3c86212fbf725de6446a96a13' + action :install +end +``` + +Install MacIrssi to `~/Applications` from the local file downloaded to the cache path into an Applications directory in the current user's home directory. Chef should run as a non-root user for this. + +```ruby +directory "#{ENV['HOME']}/Applications" + +dmg_package 'MacIrssi' do + destination "#{ENV['HOME']}/Applications" + action :install +end +``` + +Install Virtualbox to `/Applications` from the .mpkg: + +```ruby +dmg_package 'Virtualbox' do + source 'http://dlc.sun.com.edgesuite.net/virtualbox/4.0.8/VirtualBox-4.0.8-71778-OSX.dmg' + type 'mpkg' +end +``` + +Install pgAdmin to `/Applications` and automatically accept the EULA: + +```ruby +dmg_package 'pgAdmin3' do + source 'http://wwwmaster.postgresql.org/redir/198/h/pgadmin3/release/v1.12.3/osx/pgadmin3-1.12.3.dmg' + checksum '9435f79d5b52d0febeddfad392adf82db9df159196f496c1ab139a6957242ce9' + accept_eula true +end +``` + +Install Silverlight, with idempotence check based on pkgutil: + +```ruby +dmg_package 'Silerlight' do + source 'http://silverlight.dlservice.microsoft.com/download/D/C/2/DC2D5838-9138-4D25-AA92-52F61F7C51E6/runtime/Silverlight.dmg' + type 'pkg' + checksum '6d4a0ad4552d9815531463eb3f467fb8cf4bffcc' + package_id 'com.microsoft.installSilverlightPlugin' +end +``` + +## License & Authors + +**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io)) + +**Copyright:** 2011-2017, Chef Software, Inc. + +``` +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/cookbooks/dmg/metadata.json b/cookbooks/dmg/metadata.json new file mode 100644 index 0000000..7c3f674 --- /dev/null +++ b/cookbooks/dmg/metadata.json @@ -0,0 +1 @@ +{"name":"dmg","version":"4.1.1","description":"Resource for installing macOS applications from DMGs","long_description":"The dmg_package resource is now included in Chef 14 and this cookbook has been deprecated. We highly recommend updating to Chef 14 so you can use this resource without the need for a cookbook dependency.\n\n# dmg Cookbook\n\n[![Build Status](https://travis-ci.org/chef-cookbooks/dmg.svg?branch=master)](https://travis-ci.org/chef-cookbooks/dmg) [![Cookbook Version](https://img.shields.io/cookbook/v/dmg.svg)](https://supermarket.chef.io/cookbooks/dmg)\n\nResource to install OS X applications (.app) from dmg files.\n\n## Requirements\n\n### Platforms\n\n- macOS\n\n### Chef\n\n- Chef 12.5+\n\n### Cookbooks\n\n- none\n\n## Resources/Providers\n\n### dmg_package\n\nThis resource will install a DMG \"Package\". It will retrieve the DMG from a remote URL, mount it using OS X's `hdid`, copy the application (.app directory) to the specified destination (/Applications), and detach the image using `hdiutil`. The dmg file will be stored in the `Chef::Config[:file_cache_path]`. If you want to install an application that has already been downloaded (not using the `source` parameter), copy it to the appropriate location. You can find out what directory this is with the following command on the node to run chef:\n\n```bash\nknife exec -E 'p Chef::Config[:file_cache_path]' -c /etc/chef/client.rb\n```\n\nOptionally, the LWRP can install an \"mpkg\" or \"pkg\" package using installer(8).\n\n#### Actions\n\n- :install - Installs the application.\n\n#### Parameter attributes:\n\n- `app` - This is the name of the application used by default for the /Volumes directory and the .app directory copied to /Applications.\n- `source` - remote URL for the dmg to download if specified. Default is nil.\n- `file` - local dmg full file path. Default is nil.\n- `owner` - owner that should own the package installation.\n- `destination` - directory to copy the .app into. Default is /Applications.\n- `checksum` - sha256 checksum of the dmg to download. Default is nil.\n- `type` - type of package, \"app\", \"pkg\" or \"mpkg\". Default is \"app\". When using \"pkg\" or \"mpkg\", the destination must be /Applications.\n- `volumes_dir` - Directory under /Volumes where the dmg is mounted. Not all dmgs are mounted into a /Volumes location matching the name of the dmg. If not specified, this will use the name attribute.\n- `package_id` - Package id registered with pkgutil when a pkg or mpkg is installed\n- `dmg_name` - Specify the name of the dmg if it is not the same as `app`, or if the name has spaces.\n- `dmg_passphrase` - Specify a passphrase to use to unencrypt the dmg while mounting.\n- `accept_eula` - Specify whether to accept the EULA. Certain dmgs require acceptance of EULA before mounting. Can be true or false, defaults to false.\n- `headers` - Allows custom HTTP headers (like cookies) to be set on the remote_file resource.\n- `allow_untrusted` - Allows packages with untrusted certs to be installed.\n\n#### Examples\n\nInstall `/Applications/Tunnelblick.app` from the primary download site.\n\n```ruby\ndmg_package 'Tunnelblick' do\n source 'https://tunnelblick.net/release/Tunnelblick_3.7.0_build_4790.dmg'\n checksum '5053038aa8caf7dea66dcab11d6d240672216e6546eff4c2622e216c61af85e5'\n action :install\nend\n```\n\nInstall Google Chrome. Uses the `dmg_name` because the application name has spaces. Installs in `/Applications/Google Chrome.app`.\n\n```ruby\ndmg_package 'Google Chrome' do\n dmg_name 'googlechrome'\n source 'https://dl-ssl.google.com/chrome/mac/stable/GGRM/googlechrome.dmg'\n checksum '7daa2dc5c46d9bfb14f1d7ff4b33884325e5e63e694810adc58f14795165c91a'\n action :install\nend\n```\n\nInstall Dropbox. Uses `volumes_dir` because the mounted directory is different than the name of the application directory. Installs in `/Applications/Dropbox.app`.\n\n```ruby\ndmg_package 'Dropbox' do\n volumes_dir 'Dropbox Installer'\n source 'http://www.dropbox.com/download?plat=mac'\n checksum 'b4ea620ca22b0517b75753283ceb82326aca8bc3c86212fbf725de6446a96a13'\n action :install\nend\n```\n\nInstall MacIrssi to `~/Applications` from the local file downloaded to the cache path into an Applications directory in the current user's home directory. Chef should run as a non-root user for this.\n\n```ruby\ndirectory \"#{ENV['HOME']}/Applications\"\n\ndmg_package 'MacIrssi' do\n destination \"#{ENV['HOME']}/Applications\"\n action :install\nend\n```\n\nInstall Virtualbox to `/Applications` from the .mpkg:\n\n```ruby\ndmg_package 'Virtualbox' do\n source 'http://dlc.sun.com.edgesuite.net/virtualbox/4.0.8/VirtualBox-4.0.8-71778-OSX.dmg'\n type 'mpkg'\nend\n```\n\nInstall pgAdmin to `/Applications` and automatically accept the EULA:\n\n```ruby\ndmg_package 'pgAdmin3' do\n source 'http://wwwmaster.postgresql.org/redir/198/h/pgadmin3/release/v1.12.3/osx/pgadmin3-1.12.3.dmg'\n checksum '9435f79d5b52d0febeddfad392adf82db9df159196f496c1ab139a6957242ce9'\n accept_eula true\nend\n```\n\nInstall Silverlight, with idempotence check based on pkgutil:\n\n```ruby\ndmg_package 'Silerlight' do\n source 'http://silverlight.dlservice.microsoft.com/download/D/C/2/DC2D5838-9138-4D25-AA92-52F61F7C51E6/runtime/Silverlight.dmg'\n type 'pkg'\n checksum '6d4a0ad4552d9815531463eb3f467fb8cf4bffcc'\n package_id 'com.microsoft.installSilverlightPlugin'\nend\n```\n\n## License & Authors\n\n**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io))\n\n**Copyright:** 2011-2017, Chef Software, Inc.\n\n```\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"mac_os_x":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/chef-cookbooks/dmg","issues_url":"https://github.com/chef-cookbooks/dmg/issues","chef_version":[[">= 12.5"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/dmg/recipes/default.rb b/cookbooks/dmg/recipes/default.rb new file mode 100644 index 0000000..2690d0c --- /dev/null +++ b/cookbooks/dmg/recipes/default.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: dmg +# Recipe:: default +# +# Copyright:: 2011-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +Chef::Log.warn('The dmg::default recipe does not contain any resources and should not be applied to a node') diff --git a/cookbooks/dmg/resources/package.rb b/cookbooks/dmg/resources/package.rb new file mode 100644 index 0000000..71b5327 --- /dev/null +++ b/cookbooks/dmg/resources/package.rb @@ -0,0 +1,102 @@ +# +# Author:: Joshua Timberman () +# Cookbook:: dmg +# Resource:: package +# +# Copyright:: 2011-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +property :app, String, name_property: true +property :source, String +property :file, String +property :owner, String +property :destination, String, default: '/Applications' +property :checksum, String +property :volumes_dir, String +property :dmg_name, String +property :type, String, default: 'app', equal_to: %w(app pkg mpkg) +property :installed, [true, false], default: false, desired_state: false +property :package_id, String +property :dmg_passphrase, String +property :accept_eula, [true, false], default: false +property :headers, [Hash, nil], default: nil +property :allow_untrusted, [true, false], default: false + +load_current_value do |new_resource| + if ::File.directory?("#{new_resource.destination}/#{new_resource.app}.app") + Chef::Log.info "Already installed; to upgrade, remove \"#{new_resource.destination}/#{new_resource.app}.app\"" + installed true + elsif shell_out("pkgutil --pkgs='#{new_resource.package_id}'").exitstatus == 0 + Chef::Log.info "Already installed; to upgrade, try \"sudo pkgutil --forget '#{new_resource.package_id}'\"" + installed true + else + installed false + end +end + +action :install do + unless current_resource.installed + + volumes_dir = new_resource.volumes_dir ? new_resource.volumes_dir : new_resource.app + dmg_name = new_resource.dmg_name ? new_resource.dmg_name : new_resource.app + + dmg_file = if new_resource.file.nil? + "#{Chef::Config[:file_cache_path]}/#{dmg_name}.dmg" + else + new_resource.file + end + + remote_file "#{dmg_file} - #{new_resource.name}" do + path dmg_file + source new_resource.source + headers new_resource.headers if new_resource.headers + checksum new_resource.checksum if new_resource.checksum + end if new_resource.source + + passphrase_cmd = new_resource.dmg_passphrase ? "-passphrase #{new_resource.dmg_passphrase}" : '' + ruby_block "attach #{dmg_file}" do + block do + cmd = shell_out("hdiutil imageinfo #{passphrase_cmd} '#{dmg_file}' | grep -q 'Software License Agreement: true'") + software_license_agreement = cmd.exitstatus == 0 + raise "Requires EULA Acceptance; add 'accept_eula true' to package resource" if software_license_agreement && !new_resource.accept_eula + accept_eula_cmd = new_resource.accept_eula ? 'echo Y | PAGER=true' : '' + shell_out!("#{accept_eula_cmd} hdiutil attach #{passphrase_cmd} '#{dmg_file}' -mountpoint '/Volumes/#{volumes_dir}' -quiet") + end + not_if "hdiutil info #{passphrase_cmd} | grep -q 'image-path.*#{dmg_file}'" + end + + case new_resource.type + when 'app' + execute "rsync --force --recursive --links --perms --executability --owner --group --times '/Volumes/#{volumes_dir}/#{new_resource.app}.app' '#{new_resource.destination}'" do + user new_resource.owner if new_resource.owner + end + + declare_resource(:file, "#{new_resource.destination}/#{new_resource.app}.app/Contents/MacOS/#{new_resource.app}") do + mode '755' + ignore_failure true + end + when 'mpkg', 'pkg' + install_cmd = "installation_file=$(ls '/Volumes/#{volumes_dir}' | grep '.#{new_resource.type}$') && sudo installer -pkg \"/Volumes/#{volumes_dir}/$installation_file\" -target /" + install_cmd += ' -allowUntrusted' if new_resource.allow_untrusted + + execute install_cmd do + # Prevent cfprefsd from holding up hdiutil detach for certain disk images + environment('__CFPREFERENCES_AVOID_DAEMON' => '1') + end + end + + execute "hdiutil detach '/Volumes/#{volumes_dir}' || hdiutil detach '/Volumes/#{volumes_dir}' -force" + end +end diff --git a/cookbooks/elasticsearch/.foodcritic b/cookbooks/elasticsearch/.foodcritic new file mode 100644 index 0000000..cf9e43e --- /dev/null +++ b/cookbooks/elasticsearch/.foodcritic @@ -0,0 +1 @@ +~FC057 diff --git a/cookbooks/elasticsearch/CHANGELOG.md b/cookbooks/elasticsearch/CHANGELOG.md new file mode 100644 index 0000000..63df6f4 --- /dev/null +++ b/cookbooks/elasticsearch/CHANGELOG.md @@ -0,0 +1,587 @@ +# Change Log + +## [v4.2.0](https://github.com/elastic/cookbook-elasticsearch/tree/v4.2.0) (2019-08-02) +- Default to Elasticsearch 7.3.0 +- Some fixes for the version logic when selecting v7 or higher ES + +## [v4.1.0](https://github.com/elastic/cookbook-elasticsearch/tree/v4.1.0) (2019-08-02) +- Added support for ES 6.8.1, 6.8.2 and new default of 6.8.2 +- Added support for ES v7, with 7.0.0, 7.0.1, 7.1.0, 7.2.0, 7.2.1, 7.3.0 +- New URL format for ES v7 introduced, taught lib/helpers how to use it +- Bumped testing to use Chef v14 +- Modified testing with test-kitchen to stop using x-pack as a test plugin, now using analysis-icu +- Some minor tweaks to get chefspec tests working again + +## [v4.0.6](https://github.com/elastic/cookbook-elasticsearch/tree/v4.0.6) (2019-05-22) +- Lots of new hashes of more recent releases of ES, see PRs for full list (#715, #713, #710, #709, #705, #704, #701). +- Get Travis building again (#714). + +## [v4.0.5](https://github.com/elastic/cookbook-elasticsearch/tree/v4.0.5) (2019-01-02) +- Add hashes for 6.5.4 (#699), 6.5.3 (#697) + +## [v4.0.4](https://github.com/elastic/cookbook-elasticsearch/tree/v4.0.4) (2018-11-06) +- Add hashes for 6.4.2 (#687) + +## [v4.0.3](https://github.com/elastic/cookbook-elasticsearch/tree/v4.0.3) (2018-09-24) +- Add hashes for 6.4.1 (#682) + +## [v4.0.2](https://github.com/elastic/cookbook-elasticsearch/tree/v4.0.2) (2018-09-17) +- Add hashes for 6.3.0 (#669), 6.3.1 (#673), 6.4.0 (#677) + +## [v4.0.1](https://github.com/elastic/cookbook-elasticsearch/tree/v4.0.1) (2018-06-01) +- Add hashes for 6.2.4 (#665) +- Improve ES_USER / ES_GROUP logic for init script and package installs (#647) + +## [v4.0.0](https://github.com/elastic/cookbook-elasticsearch/tree/v4.0.0) (2018-03-25) +- Default to 6.0.0 and add sha256 checksums, drop old 5.x hashes +- Point to 6.x yum repo +- Introduce 6.0.0's JVM options for ES 6 +- ES_JVM_OPTIONS is no longer supported in v6.0.0 +- Correct tests with x-pack installation +- Remove test for config entry that is no longer valid +- Remove path.conf reference after testing +- Stop testing on Ubuntu 12.04 and earlier + +## [v3.4.5](https://github.com/elastic/cookbook-elasticsearch/tree/v3.4.5) (2018-03-25) +- Add documentation for Java "trust anchors" problem (#646) +- Add hashes for 5.6.8 (#649) + +## [v3.4.4](https://github.com/elastic/cookbook-elasticsearch/tree/v3.4.4) (2018-02-01) +- Add hashes for ES 5.6.6 (#638) and ES 5.6.7 (#640) + +## [v3.4.3](https://github.com/elastic/cookbook-elasticsearch/tree/v3.4.3) (2018-01-03) +- Add hashes for ES 5.6.5 (#632) + +## [v3.4.2](https://github.com/elastic/cookbook-elasticsearch/tree/v3.4.2) (2017-12-03) +- Add hashes for ES 5.6.4 (#622) + +## [v3.4.1](https://github.com/elastic/cookbook-elasticsearch/tree/v3.4.1) (2017-10-18) +- Add hashes for ES 5.6.3 (#616) + +## [v3.4.0](https://github.com/elastic/cookbook-elasticsearch/tree/v3.4.0) (2017-09-28) +- Add hashes for ES 5.6.1 and 5.6.2 (#613) +- Add the latest init scripts from .deb, .rpm, and systemd + +## [v3.3.1](https://github.com/elastic/cookbook-elasticsearch/tree/v3.3.1) (2017-09-15) +- Add hashes for ES 5.6.0 and 5.5.3 (#610) +- Workaround for support 'amazon' platform_family (#609) + +## [v3.3.0](https://github.com/elastic/cookbook-elasticsearch/tree/v3.3.0) (2017-08-30) +- nil templates skip startup scripts (#585) + +## [v3.2.2](https://github.com/elastic/cookbook-elasticsearch/tree/v3.2.2) (2017-08-29) +- Bump ES version to 5.5.2 (#606) + +## [v3.2.1](https://github.com/elastic/cookbook-elasticsearch/tree/v3.2.1) (2017-07-17) +- Bump ES version to 5.5.0, add 5.4.2 and 5.4.3 as well (#594) + +## [v3.2.0](https://github.com/elastic/cookbook-elasticsearch/tree/v3.2.0) (2017-05-21) +- Provide additional documentation about logging options, update template (#577) +- Allow others to read elasticsearch log dir (#570) +- Bump ES version to 5.4.0 (#569) + +## [v3.1.1](https://github.com/elastic/cookbook-elasticsearch/tree/v3.1.1) (2017-05-01) +- Add hashes for ES 5.3.1 (#562) +- Add hashes for ES 5.3.2 (#567) + +## [v3.1.0](https://github.com/elastic/cookbook-elasticsearch/tree/v3.1.0) (2017-04-18) +- Add Chef 13.x support for this cookbook (#561) +- Reintroduce chef_proxy settings (#557) + +## [v3.0.5](https://github.com/elastic/cookbook-elasticsearch/tree/v3.0.5) (2017-04-06) +- Bump ES version to 5.3.0 (#550) +- Fix permissions for elasticsearch.yml and log4j2.properties (#555) + +## [v3.0.4](https://github.com/elastic/cookbook-elasticsearch/tree/v3.0.4) (2017-03-02) +- Bump ES version to 5.2.2 (#550) + +## [v3.0.3](https://github.com/elastic/cookbook-elasticsearch/tree/v3.0.3) (2017-02-09) +- Fix URL support for plugins (#525) +- Add support for versions 5.0.2, 5.1.1, 5.1.2, 5.2.0 +- Make 5.2.0 the default version +- Add a note about upgrading to new versions (#527) +- Foodcritic/Rubocop style cleanup +- Fix ruby version build on travis +- remove tarball directory recursively + +## [v3.0.2](https://github.com/elastic/cookbook-elasticsearch/tree/v3.0.2) (2016-11-29) + +- Ensure bin/elasticsearch-plugin uses the proper environment (#523) +- Bump default Elasticsearch version from v5.0.0 to v5.0.1 + +## [v3.0.1](https://github.com/elastic/cookbook-elasticsearch/tree/v3.0.1) (2016-11-09) + +- Fix incorrect MAX_MAP_COUNT default to be '262144' to match init scripts (#516) + +## [v3.0.0](https://github.com/elastic/cookbook-elasticsearch/tree/v3.0.0) (2016-11-07) + +Breaking changes that were needed for v5.0.0 support (#497, #512, #424, #478, #503): + - We dropped the fancy logic for figuring out the requested version of Elasticsearch to be installed. You should pass it on the resource or in the recipe, but we no longer do a bunch of logic to figure out what you meant -- we favor being explicit now. + - We now start the service by default, instead of only `:enable` but not `:start`. + - Dropped `gc_options` parameter of elasticsearch_configure, and now have `jvm.options`. We've also dropped thread_stack_size and env_options, as they aren't used in the upstream packaging as defaults anymore. + - Install the tarball and package files into the same locations. There's no more `/usr/local`. + - Install types are now 'strings', not :symbols. `node['elasticsearch'][][]` sets any `elasticsearch::default` recipe. + +For more on breaking changes, read [3aa8740](https://github.com/elastic/cookbook-elasticsearch/commit/3aa8740da5182f4a29761e0ea350048764bc0752) and [1ccd013](https://github.com/elastic/cookbook-elasticsearch/commit/1ccd013821cbfe83197c1ebba7fdb3acadc3d88f). + +- Switch to the `manage_home false` property of newer Chef versions (#406) +- Use YAML library directly from now on for elasticsearch.yml (#470) +- Add support for Ubuntu 16.04 / CentOS 7.2, both using systemd (#501, #502) +- Support and use 'repository' type on `elasticsearch_install` by default (#476) +- Based on the latest v5.0.0 packages, tweak the permissions for some directories slightly (#513) +- Drop preferIPv4 test (#475), discovery.zen.ping settings (#437), and others. +- Add Java 8 testing by default (#510), bump newer Chef versions (#503, #505) +- Start using exact plugin names, case sensitive (#485) + +## [v2.4.0](https://github.com/elastic/cookbook-elasticsearch/tree/v2.4.0) (2016-09-15) + +- Update attributes for 2.3.5 and 2.4.0 versions. Use 2.4.0 version as default for installation and tests. [\#496](https://github.com/elastic/cookbook-elasticsearch/issues/496) and [\#490](https://github.com/elastic/cookbook-elasticsearch/issues/490) +- Added a LICENSE file (Apache 2), metadata, and linting +- Remove chef 11 compatibility from metadata, update cookstyle and Berkshelf, various Chef standards [\#481](https://github.com/elastic/cookbook-elasticsearch/issues/481) +- Improve environment file formatting: Remove quotes from vars that don't need it, strip superfluous spaces from ES_JAVA_OPTS [\#477](https://github.com/elastic/cookbook-elasticsearch/issues/477) + +## [v2.3.2](https://github.com/elastic/cookbook-elasticsearch/tree/v2.3.2) (2016-06-17) + +- Update init scripts and configs to latest [\#461](https://github.com/elastic/cookbook-elasticsearch/issues/461) +- Don't make environment file executable [\#474](https://github.com/elastic/cookbook-elasticsearch/issues/474) +- Don't make config YAML file executable [\#465](https://github.com/elastic/cookbook-elasticsearch/issues/465) +- Make latest Foodcritic rules pass [\#466](https://github.com/elastic/cookbook-elasticsearch/issues/466) +- ES 2.3.3 SHA256 sums and default version [\#464](https://github.com/elastic/cookbook-elasticsearch/issues/464) +- Point to determine_download_url instead of non-existent get_package_url [\#463](https://github.com/elastic/cookbook-elasticsearch/issues/463) + +## [v2.3.1](https://github.com/elastic/cookbook-elasticsearch/tree/v2.3.1) (2016-05-06) + +- Update documentation for dir in elasticsearch_install [\#453](https://github.com/elastic/cookbook-elasticsearch/issues/453) +- Define custom matchers helpers for notification testing [\#458](https://github.com/elastic/cookbook-elasticsearch/issues/458) +- Add checksums for version 2.3.2 [\#457](https://github.com/elastic/cookbook-elasticsearch/issues/457) +- Default ES version bump to 2.3.2 [\#459](https://github.com/elastic/cookbook-elasticsearch/issues/459) +- Fix quoting bug in plugin remove action [\#455](https://github.com/elastic/cookbook-elasticsearch/issues/455) +- Fix typo in README [\#456](https://github.com/elastic/cookbook-elasticsearch/issues/456) + +## [v2.3.0](https://github.com/elastic/cookbook-elasticsearch/tree/v2.3.0) (2016-04-07) + +- Add checksums for 2.3.1 [\#451](https://github.com/elastic/cookbook-elasticsearch/issues/451) + +## [v2.2.2](https://github.com/elastic/cookbook-elasticsearch/tree/v2.2.2) (2016-03-22) + +- elasticsearch_configure provider should not modify default resource parameters [\#445](https://github.com/elastic/cookbook-elasticsearch/issues/445) + +## [v2.2.1](https://github.com/elastic/cookbook-elasticsearch/tree/v2.2.1) (2016-03-04) + +- Incorrectly setting allocated memory in the `ES\_JAVA\_OPTS` variable [\#434](https://github.com/elastic/cookbook-elasticsearch/issues/434) +- elasticsearch_service/service_actions accepts (but does not support) Symbols [\#438](https://github.com/elastic/cookbook-elasticsearch/issues/438) + +## [v2.2.0](https://github.com/elastic/cookbook-elasticsearch/tree/v2.2.0) (2016-02-08) + +- Max heap size is too large [\#427](https://github.com/elastic/cookbook-elasticsearch/issues/427) +- How to define discovery.zen.ping.unicast.hosts [\#426](https://github.com/elastic/cookbook-elasticsearch/issues/426) +- elasticsearch\_plugin install lacks proxy support [\#415](https://github.com/elastic/cookbook-elasticsearch/issues/415) +- Default ES version needs upgrading \(2.1.0 \> 2.1.1\) [\#411](https://github.com/elastic/cookbook-elasticsearch/issues/411) +- config dirs/files and install dirs/files should be owned by root, not es\_user [\#405](https://github.com/elastic/cookbook-elasticsearch/issues/405) +- Reinstalls elasticserach every chef run [\#404](https://github.com/elastic/cookbook-elasticsearch/issues/404) +- Permission problem when installing Watcher or Shield [\#423](https://github.com/elastic/cookbook-elasticsearch/issues/423) +- Installing shield and watcher plugins fail with AccessDeniedException [\#421](https://github.com/elastic/cookbook-elasticsearch/issues/421) +- Plugin removal is broken [\#418](https://github.com/elastic/cookbook-elasticsearch/issues/418) +- elasticsearch\_configure documentation example missing path\_home [\#413](https://github.com/elastic/cookbook-elasticsearch/issues/413) +- Init script can't start [\#390](https://github.com/elastic/cookbook-elasticsearch/issues/390) +- ruby command not found [\#378](https://github.com/elastic/cookbook-elasticsearch/issues/378) +- ES 2.2.0 installation fails [\#429](https://github.com/elastic/cookbook-elasticsearch/issues/429) +- Can't install plugin twice [\#408](https://github.com/elastic/cookbook-elasticsearch/issues/408) +- Error running recipe on AWS Opsworks [\#403](https://github.com/elastic/cookbook-elasticsearch/issues/403) +- ES 2.1.0 support [\#402](https://github.com/elastic/cookbook-elasticsearch/issues/402) +- Any provision to make it Chef 11.10 compatible? [\#401](https://github.com/elastic/cookbook-elasticsearch/issues/401) +- gateway.expected\_nodes default should be 0 [\#399](https://github.com/elastic/cookbook-elasticsearch/issues/399) +- Add the defaults for slowlogs in logging.yml [\#398](https://github.com/elastic/cookbook-elasticsearch/issues/398) +- elasticsearch\_service resource doesn't work with short syntax [\#397](https://github.com/elastic/cookbook-elasticsearch/issues/397) +- What is supposed to happen when a config file is changed? [\#394](https://github.com/elastic/cookbook-elasticsearch/issues/394) +- Doc request - how to create data nodes vs master nodes [\#393](https://github.com/elastic/cookbook-elasticsearch/issues/393) +- Plugin install isn't idempotent [\#392](https://github.com/elastic/cookbook-elasticsearch/issues/392) +- Question - Are custom configs required everywhere? [\#391](https://github.com/elastic/cookbook-elasticsearch/issues/391) +- Is :tarball or :package the preferred installation type? [\#389](https://github.com/elastic/cookbook-elasticsearch/issues/389) +- Support Amazon platform for init scripts [\#387](https://github.com/elastic/cookbook-elasticsearch/issues/387) +- "ArgumentError: wrong number of arguments \(1 for 0\)" at resource\_configure.rb [\#386](https://github.com/elastic/cookbook-elasticsearch/issues/386) +- Do I need to do a Java Installation myself for this to work? [\#385](https://github.com/elastic/cookbook-elasticsearch/issues/385) +- Support ES 2.0 [\#384](https://github.com/elastic/cookbook-elasticsearch/issues/384) +- plugin install does not work [\#382](https://github.com/elastic/cookbook-elasticsearch/issues/382) +- Compile error w/ 1.0.3 and Chef Server 12 [\#379](https://github.com/elastic/cookbook-elasticsearch/issues/379) +- Allow template cookbook override in \_configure [\#376](https://github.com/elastic/cookbook-elasticsearch/issues/376) +- 1.0.2 Issues with pid files [\#374](https://github.com/elastic/cookbook-elasticsearch/issues/374) +- Consider using the resource name as a common shared set of resources [\#373](https://github.com/elastic/cookbook-elasticsearch/issues/373) +- elasticsearch\_install broken with v1.0.1 [\#371](https://github.com/elastic/cookbook-elasticsearch/issues/371) +- Compile Error [\#370](https://github.com/elastic/cookbook-elasticsearch/issues/370) +- wrong number of arguments \(1 for 0\) [\#369](https://github.com/elastic/cookbook-elasticsearch/issues/369) +- fixes typo in readme [\#428](https://github.com/elastic/cookbook-elasticsearch/pull/428) ([spuder](https://github.com/spuder)) +- Plugin removal functionality restored [\#420](https://github.com/elastic/cookbook-elasticsearch/pull/420) ([dbaggott](https://github.com/dbaggott)) +- Update to ES 2.1.1 [\#412](https://github.com/elastic/cookbook-elasticsearch/pull/412) ([dbaggott](https://github.com/dbaggott)) +- Makes code examples have color [\#396](https://github.com/elastic/cookbook-elasticsearch/pull/396) ([spuder](https://github.com/spuder)) +- Updates docs to show package are now default install [\#395](https://github.com/elastic/cookbook-elasticsearch/pull/395) ([spuder](https://github.com/spuder)) +- Update the README to remove a typo [\#381](https://github.com/elastic/cookbook-elasticsearch/pull/381) ([jtwarren](https://github.com/jtwarren)) +- Correct the full changelog links [\#375](https://github.com/elastic/cookbook-elasticsearch/pull/375) ([eheydrick](https://github.com/eheydrick)) +- add missing matchers [\#368](https://github.com/elastic/cookbook-elasticsearch/pull/368) ([thomasdziedzic](https://github.com/thomasdziedzic)) + +## [v2.1.1](https://github.com/elastic/cookbook-elasticsearch/tree/v2.1.1) (2016-01-08) + +- elasticsearch\_plugin install lacks proxy support [\#415](https://github.com/elastic/cookbook-elasticsearch/issues/415) +- Default ES version needs upgrading \(2.1.0 \> 2.1.1\) [\#411](https://github.com/elastic/cookbook-elasticsearch/issues/411) +- Reinstalls elasticserach every chef run [\#404](https://github.com/elastic/cookbook-elasticsearch/issues/404) +- Installing shield and watcher plugins fail with AccessDeniedException [\#421](https://github.com/elastic/cookbook-elasticsearch/issues/421) +- Plugin removal is broken [\#418](https://github.com/elastic/cookbook-elasticsearch/issues/418) +- elasticsearch\_configure documentation example missing path\_home [\#413](https://github.com/elastic/cookbook-elasticsearch/issues/413) +- Init script can't start [\#390](https://github.com/elastic/cookbook-elasticsearch/issues/390) +- ruby command not found [\#378](https://github.com/elastic/cookbook-elasticsearch/issues/378) +- Can't install plugin twice [\#408](https://github.com/elastic/cookbook-elasticsearch/issues/408) +- Error running recipe on AWS Opsworks [\#403](https://github.com/elastic/cookbook-elasticsearch/issues/403) +- ES 2.1.0 support [\#402](https://github.com/elastic/cookbook-elasticsearch/issues/402) +- Any provision to make it Chef 11.10 compatible? [\#401](https://github.com/elastic/cookbook-elasticsearch/issues/401) +- gateway.expected\_nodes default should be 0 [\#399](https://github.com/elastic/cookbook-elasticsearch/issues/399) +- Add the defaults for slowlogs in logging.yml [\#398](https://github.com/elastic/cookbook-elasticsearch/issues/398) +- elasticsearch\_service resource doesn't work with short syntax [\#397](https://github.com/elastic/cookbook-elasticsearch/issues/397) +- What is supposed to happen when a config file is changed? [\#394](https://github.com/elastic/cookbook-elasticsearch/issues/394) +- Doc request - how to create data nodes vs master nodes [\#393](https://github.com/elastic/cookbook-elasticsearch/issues/393) +- Plugin install isn't idempotent [\#392](https://github.com/elastic/cookbook-elasticsearch/issues/392) +- Question - Are custom configs required everywhere? [\#391](https://github.com/elastic/cookbook-elasticsearch/issues/391) +- Is :tarball or :package the preferred installation type? [\#389](https://github.com/elastic/cookbook-elasticsearch/issues/389) +- Support Amazon platform for init scripts [\#387](https://github.com/elastic/cookbook-elasticsearch/issues/387) +- "ArgumentError: wrong number of arguments \(1 for 0\)" at resource\_configure.rb [\#386](https://github.com/elastic/cookbook-elasticsearch/issues/386) +- Do I need to do a Java Installation myself for this to work? [\#385](https://github.com/elastic/cookbook-elasticsearch/issues/385) +- Support ES 2.0 [\#384](https://github.com/elastic/cookbook-elasticsearch/issues/384) +- plugin install does not work [\#382](https://github.com/elastic/cookbook-elasticsearch/issues/382) +- Compile error w/ 1.0.3 and Chef Server 12 [\#379](https://github.com/elastic/cookbook-elasticsearch/issues/379) +- Allow template cookbook override in \_configure [\#376](https://github.com/elastic/cookbook-elasticsearch/issues/376) +- 1.0.2 Issues with pid files [\#374](https://github.com/elastic/cookbook-elasticsearch/issues/374) +- Consider using the resource name as a common shared set of resources [\#373](https://github.com/elastic/cookbook-elasticsearch/issues/373) +- elasticsearch\_install broken with v1.0.1 [\#371](https://github.com/elastic/cookbook-elasticsearch/issues/371) +- Compile Error [\#370](https://github.com/elastic/cookbook-elasticsearch/issues/370) +- wrong number of arguments \(1 for 0\) [\#369](https://github.com/elastic/cookbook-elasticsearch/issues/369) +- missing chef resource expectations in specs in 1.0.1 [\#367](https://github.com/elastic/cookbook-elasticsearch/issues/367) +- Use predictable attributes/values for version, download URL, and checksum [\#366](https://github.com/elastic/cookbook-elasticsearch/issues/366) +- Rubocop & foodcritic cleanup [\#365](https://github.com/elastic/cookbook-elasticsearch/issues/365) +- elasticsearch\_plugin installs plugins with the wrong permissions [\#363](https://github.com/elastic/cookbook-elasticsearch/issues/363) +- Double-dependency on curl [\#360](https://github.com/elastic/cookbook-elasticsearch/issues/360) +- OS X Support [\#358](https://github.com/elastic/cookbook-elasticsearch/issues/358) +- Plugin removal functionality restored [\#420](https://github.com/elastic/cookbook-elasticsearch/pull/420) ([dbaggott](https://github.com/dbaggott)) +- Update to ES 2.1.1 [\#412](https://github.com/elastic/cookbook-elasticsearch/pull/412) ([dbaggott](https://github.com/dbaggott)) +- Makes code examples have color [\#396](https://github.com/elastic/cookbook-elasticsearch/pull/396) ([spuder](https://github.com/spuder)) +- Updates docs to show package are now default install [\#395](https://github.com/elastic/cookbook-elasticsearch/pull/395) ([spuder](https://github.com/spuder)) +- Update the README to remove a typo [\#381](https://github.com/elastic/cookbook-elasticsearch/pull/381) ([jtwarren](https://github.com/jtwarren)) +- Correct the full changelog links [\#375](https://github.com/elastic/cookbook-elasticsearch/pull/375) ([eheydrick](https://github.com/eheydrick)) +- add missing matchers [\#368](https://github.com/elastic/cookbook-elasticsearch/pull/368) ([thomasdziedzic](https://github.com/thomasdziedzic)) +- Adds integration test for plugins in default environment [\#361](https://github.com/elastic/cookbook-elasticsearch/pull/361) ([bwvoss](https://github.com/bwvoss)) + +## [2.1.0](https://github.com/elastic/cookbook-elasticsearch/tree/v2.1.0) (2015-12-01) + +- ES 2.1.0 support [\#402](https://github.com/elastic/cookbook-elasticsearch/issues/402) + +## [2.0.1](https://github.com/elastic/cookbook-elasticsearch/tree/v2.0.1) (2015-12-01) + +- Any provision to make it Chef 11.10 compatible? [\#401](https://github.com/elastic/cookbook-elasticsearch/issues/401) +- gateway.expected\_nodes default should be 0 [\#399](https://github.com/elastic/cookbook-elasticsearch/issues/399) +- Add the defaults for slowlogs in logging.yml [\#398](https://github.com/elastic/cookbook-elasticsearch/issues/398) + +## [2.0.0](https://github.com/elastic/cookbook-elasticsearch/tree/v2.0.0) (2015-11-23) + +- Upgrading by package needs cleanup [\#331](https://github.com/elastic/cookbook-elasticsearch/issues/331) +- Minimal init scripts, preferrably from the packaged versions of ES [\#321](https://github.com/elastic/cookbook-elasticsearch/issues/321) +- Remove extra env file, or follow packaged conventions [\#320](https://github.com/elastic/cookbook-elasticsearch/issues/320) +- Remove system limit adjustments [\#319](https://github.com/elastic/cookbook-elasticsearch/issues/319) +- Init script can't start [\#390](https://github.com/elastic/cookbook-elasticsearch/issues/390) +- elasticsearch\_service resource doesn't work with short syntax [\#397](https://github.com/elastic/cookbook-elasticsearch/issues/397) +- What is supposed to happen when a config file is changed? [\#394](https://github.com/elastic/cookbook-elasticsearch/issues/394) +- Doc request - how to create data nodes vs master nodes [\#393](https://github.com/elastic/cookbook-elasticsearch/issues/393) +- Plugin install isn't idempotent [\#392](https://github.com/elastic/cookbook-elasticsearch/issues/392) +- Question - Are custom configs required everywhere? [\#391](https://github.com/elastic/cookbook-elasticsearch/issues/391) +- Is :tarball or :package the preferred installation type? [\#389](https://github.com/elastic/cookbook-elasticsearch/issues/389) +- Support Amazon platform for init scripts [\#387](https://github.com/elastic/cookbook-elasticsearch/issues/387) +- "ArgumentError: wrong number of arguments \(1 for 0\)" at resource\_configure.rb [\#386](https://github.com/elastic/cookbook-elasticsearch/issues/386) +- Do I need to do a Java Installation myself for this to work? [\#385](https://github.com/elastic/cookbook-elasticsearch/issues/385) +- plugin install does not work [\#382](https://github.com/elastic/cookbook-elasticsearch/issues/382) +- Allow template cookbook override in \_configure [\#376](https://github.com/elastic/cookbook-elasticsearch/issues/376) +- Consider using the resource name as a common shared set of resources [\#373](https://github.com/elastic/cookbook-elasticsearch/issues/373) +- Recreate deploying-elasticsearch-with-chef tutorial [\#293](https://github.com/elastic/cookbook-elasticsearch/issues/293) +- Makes code examples have color [\#396](https://github.com/elastic/cookbook-elasticsearch/pull/396) ([spuder](https://github.com/spuder)) +- Updates docs to show package are now default install [\#395](https://github.com/elastic/cookbook-elasticsearch/pull/395) ([spuder](https://github.com/spuder)) + +## [1.2.0](https://github.com/elastic/cookbook-elasticsearch/tree/v1.2.0) (2015-10-16) + +- Compile error w/ 1.0.3 and Chef Server 12 [\#379](https://github.com/elastic/cookbook-elasticsearch/issues/379) +- OS X Support [\#358](https://github.com/elastic/cookbook-elasticsearch/issues/358) +- Dealing with plugin versions that don't match, Elasticsearch failing to start [\#330](https://github.com/elastic/cookbook-elasticsearch/issues/330) +- ruby command not found [\#378](https://github.com/elastic/cookbook-elasticsearch/issues/378) +- Update the README to remove a typo [\#381](https://github.com/elastic/cookbook-elasticsearch/pull/381) ([jtwarren](https://github.com/jtwarren)) +- Correct the full changelog links [\#375](https://github.com/elastic/cookbook-elasticsearch/pull/375) ([eheydrick](https://github.com/eheydrick)) + +## [1.0.3](https://github.com/elastic/cookbook-elasticsearch/tree/v1.0.3) (2015-09-20) + +- 1.0.2 Issues with pid files [\#374](https://github.com/elastic/cookbook-elasticsearch/issues/374) + +## [1.0.2](https://github.com/elastic/cookbook-elasticsearch/tree/v1.0.2) (2015-09-20) + +- enhancement : attribut path\_xxx and path.xxx [\#352](https://github.com/elastic/cookbook-elasticsearch/issues/352) +- It would be nice to be able to pass options to elasticsearch\_service [\#334](https://github.com/elastic/cookbook-elasticsearch/issues/334) +- elasticsearch\_install broken with v1.0.1 [\#371](https://github.com/elastic/cookbook-elasticsearch/issues/371) +- Compile Error [\#370](https://github.com/elastic/cookbook-elasticsearch/issues/370) +- wrong number of arguments \(1 for 0\) [\#369](https://github.com/elastic/cookbook-elasticsearch/issues/369) +- missing chef resource expectations in specs in 1.0.1 [\#367](https://github.com/elastic/cookbook-elasticsearch/issues/367) +- Rubocop & foodcritic cleanup [\#365](https://github.com/elastic/cookbook-elasticsearch/issues/365) +- add missing matchers [\#368](https://github.com/elastic/cookbook-elasticsearch/pull/368) ([thomasdziedzic](https://github.com/thomasdziedzic)) + +## [1.0.1](https://github.com/elastic/cookbook-elasticsearch/tree/v1.0.1) (2015-09-15) + +- Plugin resource's plugin\_dir should have a sensible default [\#345](https://github.com/elastic/cookbook-elasticsearch/issues/345) +- Elasticsearch user homedir deleted [\#328](https://github.com/elastic/cookbook-elasticsearch/issues/328) +- Use predictable attributes/values for version, download URL, and checksum [\#366](https://github.com/elastic/cookbook-elasticsearch/issues/366) +- elasticsearch\_plugin installs plugins with the wrong permissions [\#363](https://github.com/elastic/cookbook-elasticsearch/issues/363) +- Double-dependency on curl [\#360](https://github.com/elastic/cookbook-elasticsearch/issues/360) +- poise dependency not found [\#356](https://github.com/elastic/cookbook-elasticsearch/issues/356) +- Documentation for using JSON node configuration [\#355](https://github.com/elastic/cookbook-elasticsearch/issues/355) +- Hardcoded checksums in library helpers [\#350](https://github.com/elastic/cookbook-elasticsearch/issues/350) +- Document default values for all resources [\#348](https://github.com/elastic/cookbook-elasticsearch/issues/348) +- 1.0 should have sensible documentation [\#344](https://github.com/elastic/cookbook-elasticsearch/issues/344) +- Adds integration test for plugins in default environment [\#361](https://github.com/elastic/cookbook-elasticsearch/pull/361) ([bwvoss](https://github.com/bwvoss)) +- Clarify when overriding plugin\_dir is necessary [\#349](https://github.com/elastic/cookbook-elasticsearch/pull/349) ([michaelklishin](https://github.com/michaelklishin)) +- Remove duplicate node.max\_local\_storage\_nodes setting from the config template [\#346](https://github.com/elastic/cookbook-elasticsearch/pull/346) ([eheydrick](https://github.com/eheydrick)) + +## [v1.0.0](https://github.com/elastic/cookbook-elasticsearch/tree/v1.0.0) (2015-07-16) + +- Rename source method of install [\#332](https://github.com/elastic/cookbook-elasticsearch/issues/332) +- NEXT: Document the process for submitting PRs [\#270](https://github.com/elastic/cookbook-elasticsearch/issues/270) +- Travis CI not running on PRs from local branches [\#337](https://github.com/elastic/cookbook-elasticsearch/issues/337) +- Error executing action `install` on resource 'elasticsearch\_install' [\#335](https://github.com/elastic/cookbook-elasticsearch/issues/335) +- Document requirement on Chef 12+ [\#338](https://github.com/elastic/cookbook-elasticsearch/issues/338) +- Add lots of additional documentation [\#343](https://github.com/elastic/cookbook-elasticsearch/pull/343) ([martinb3](https://github.com/martinb3)) +- Add contribution guidelines [\#342](https://github.com/elastic/cookbook-elasticsearch/pull/342) ([martinb3](https://github.com/martinb3)) +- Run CI on master branch again, after rename [\#341](https://github.com/elastic/cookbook-elasticsearch/pull/341) ([martinb3](https://github.com/martinb3)) +- Rename provider source to tarball [\#340](https://github.com/elastic/cookbook-elasticsearch/pull/340) ([martinb3](https://github.com/martinb3)) + +## [v0.3.14](https://github.com/elastic/cookbook-elasticsearch/tree/v0.3.14) (2015-07-16) + +- NEXT: Model YML config after 'trim' config [\#322](https://github.com/elastic/cookbook-elasticsearch/issues/322) +- NEXT: Create a user resource and provider [\#269](https://github.com/elastic/cookbook-elasticsearch/issues/269) +- If bootstrap.mlockall is true, MAX\_LOCKED\_MEMORY should be set to unlimited in elasticsearch-env.sh [\#266](https://github.com/elastic/cookbook-elasticsearch/issues/266) +- Installation enhancement [\#222](https://github.com/elastic/cookbook-elasticsearch/issues/222) +- Plugins defined in databag do not get installed [\#89](https://github.com/elastic/cookbook-elasticsearch/issues/89) +- There is no customize recipe [\#326](https://github.com/elastic/cookbook-elasticsearch/issues/326) +- ES not starting when setting version to 1.5.2 or 1.6.0 [\#325](https://github.com/elastic/cookbook-elasticsearch/issues/325) +- Question - Does cookbook support rolling restarts? [\#315](https://github.com/elastic/cookbook-elasticsearch/issues/315) +- Loading attributes from the data DBI [\#313](https://github.com/elastic/cookbook-elasticsearch/issues/313) +- 0.3.13: service doesn't successfully start [\#312](https://github.com/elastic/cookbook-elasticsearch/issues/312) +- Restart doesn't work the first time if a stale PID exists [\#310](https://github.com/elastic/cookbook-elasticsearch/issues/310) +- Cannot install plugin 2.4.1 [\#308](https://github.com/elastic/cookbook-elasticsearch/issues/308) +- Proxy recipe should include nginx only based on configurabe attribute [\#307](https://github.com/elastic/cookbook-elasticsearch/issues/307) +- Queue capacity [\#301](https://github.com/elastic/cookbook-elasticsearch/issues/301) +- strange behavior with docker :bug: [\#300](https://github.com/elastic/cookbook-elasticsearch/issues/300) +- Vagrant: Undefined method 'provider' [\#298](https://github.com/elastic/cookbook-elasticsearch/issues/298) +- Error after upgrading the cookbook [\#297](https://github.com/elastic/cookbook-elasticsearch/issues/297) +- Setting version triggers java.lang.NoClassDefFoundError [\#296](https://github.com/elastic/cookbook-elasticsearch/issues/296) +- Elasticsearch running but not from service [\#290](https://github.com/elastic/cookbook-elasticsearch/issues/290) +- Elasticsearch throws ElasticsearchIllegalStateException on boot \(time based instance\) [\#288](https://github.com/elastic/cookbook-elasticsearch/issues/288) +- Prefix Definitions [\#285](https://github.com/elastic/cookbook-elasticsearch/issues/285) +- strange thinks happend if I override elasticsearch version [\#283](https://github.com/elastic/cookbook-elasticsearch/issues/283) +- Chef::Mixin::Template::TemplateError on new ssl attributes [\#281](https://github.com/elastic/cookbook-elasticsearch/issues/281) +- The 0.3.13 release is missing the metadata.rb file [\#279](https://github.com/elastic/cookbook-elasticsearch/issues/279) +- berks upload fails due to .DS\_Store files found in 0.3.12 package on supermarket.chef.io [\#278](https://github.com/elastic/cookbook-elasticsearch/issues/278) +- 0.3.11 release [\#277](https://github.com/elastic/cookbook-elasticsearch/issues/277) +- Berkshelf treats 'recommends' as 'depends' [\#275](https://github.com/elastic/cookbook-elasticsearch/issues/275) +- Init Script + Existing PID File [\#274](https://github.com/elastic/cookbook-elasticsearch/issues/274) +- Version change doesn't work [\#273](https://github.com/elastic/cookbook-elasticsearch/issues/273) +- Please add an option to specify the desired shell to pass to the su command [\#260](https://github.com/elastic/cookbook-elasticsearch/issues/260) +- Attaching EBS takes a very long time and doesn't finish? [\#259](https://github.com/elastic/cookbook-elasticsearch/issues/259) +- 1.3.4 startup hangs for 10min and fails [\#257](https://github.com/elastic/cookbook-elasticsearch/issues/257) +- Plugin installation skipping [\#252](https://github.com/elastic/cookbook-elasticsearch/issues/252) +- Can't get Rake task to work \(either dependencies or installing Berkshelf\) [\#244](https://github.com/elastic/cookbook-elasticsearch/issues/244) +- Don't include build-essential just to be sure apt is up to date [\#241](https://github.com/elastic/cookbook-elasticsearch/issues/241) +- how to specify max\_map\_count? [\#239](https://github.com/elastic/cookbook-elasticsearch/issues/239) +- Nginx HTTP, Basic Auth and multiple nodes [\#238](https://github.com/elastic/cookbook-elasticsearch/issues/238) +- Installing Marvel [\#237](https://github.com/elastic/cookbook-elasticsearch/issues/237) +- Need help with creating EBS Volume [\#223](https://github.com/elastic/cookbook-elasticsearch/issues/223) +- If elasticsearch fails to extract, it won't be installed later [\#221](https://github.com/elastic/cookbook-elasticsearch/issues/221) +- uninitialized constant Extensions during Vagrant provisioning [\#212](https://github.com/elastic/cookbook-elasticsearch/issues/212) +- config.vm.provider not recognised using Vagrant 1.5.4 [\#207](https://github.com/elastic/cookbook-elasticsearch/issues/207) +- The Vagrant installation instructions are outdated [\#206](https://github.com/elastic/cookbook-elasticsearch/issues/206) +- How to specify path.data and path.logs? [\#202](https://github.com/elastic/cookbook-elasticsearch/issues/202) +- Cannot upgrade from 0.0.92 to 1.0.1 [\#197](https://github.com/elastic/cookbook-elasticsearch/issues/197) +- install\_plugin fails to run on initial install [\#176](https://github.com/elastic/cookbook-elasticsearch/issues/176) +- EBS volume clean up [\#172](https://github.com/elastic/cookbook-elasticsearch/issues/172) +- Cookbook default attributes get lifted to normal priority [\#168](https://github.com/elastic/cookbook-elasticsearch/issues/168) +- Fog doesn't respect "delete\_on\_termination" option in elasticsearch::ebs [\#146](https://github.com/elastic/cookbook-elasticsearch/issues/146) +- Use package options on both providers [\#336](https://github.com/elastic/cookbook-elasticsearch/pull/336) ([martinb3](https://github.com/martinb3)) +- allow options passing to package provider [\#329](https://github.com/elastic/cookbook-elasticsearch/pull/329) ([scalp42](https://github.com/scalp42)) +- set default resource actions [\#327](https://github.com/elastic/cookbook-elasticsearch/pull/327) ([nathwill](https://github.com/nathwill)) +- Add a note about `next` branch [\#324](https://github.com/elastic/cookbook-elasticsearch/pull/324) ([martinb3](https://github.com/martinb3)) +- Introduce provider and resource for configure [\#316](https://github.com/elastic/cookbook-elasticsearch/pull/316) ([martinb3](https://github.com/martinb3)) +- First pass at install resource and two providers [\#309](https://github.com/elastic/cookbook-elasticsearch/pull/309) ([martinb3](https://github.com/martinb3)) + +## [v0.3.13](https://github.com/elastic/cookbook-elasticsearch/tree/v0.3.13) (2015-01-13) + +## [0.3.12](https://github.com/elastic/cookbook-elasticsearch/tree/0.3.12) (2015-01-13) + +- Guidance On Upgrading A Running ES Installation [\#271](https://github.com/elastic/cookbook-elasticsearch/issues/271) +- Supermarket release? [\#262](https://github.com/elastic/cookbook-elasticsearch/issues/262) +- version check always adds '-d' flag incorrectly. [\#255](https://github.com/elastic/cookbook-elasticsearch/issues/255) +- Version 0.3.11 not available on supermarket [\#250](https://github.com/elastic/cookbook-elasticsearch/issues/250) +- Missed multicast settings in template [\#248](https://github.com/elastic/cookbook-elasticsearch/issues/248) +- Data bags for test? [\#246](https://github.com/elastic/cookbook-elasticsearch/issues/246) +- Introduce user provider and resource [\#268](https://github.com/elastic/cookbook-elasticsearch/pull/268) ([martinb3](https://github.com/martinb3)) +- First pass at framework with testing, rake, etc [\#249](https://github.com/elastic/cookbook-elasticsearch/pull/249) ([martinb3](https://github.com/martinb3)) + +## [0.3.11](https://github.com/elastic/cookbook-elasticsearch/tree/0.3.11) (2014-10-13) + +- The init script should use the Chef embedded Ruby? [\#215](https://github.com/elastic/cookbook-elasticsearch/issues/215) +- Quick Fix for version update issues [\#178](https://github.com/elastic/cookbook-elasticsearch/issues/178) +- Don't seem to be able to change the version [\#100](https://github.com/elastic/cookbook-elasticsearch/issues/100) +- Multiple EBS mounting [\#232](https://github.com/elastic/cookbook-elasticsearch/issues/232) +- Just changing elasticsearch version attribute doesn't install intended version [\#225](https://github.com/elastic/cookbook-elasticsearch/issues/225) +- plugins not being loaded [\#171](https://github.com/elastic/cookbook-elasticsearch/issues/171) + +## [0.3.10](https://github.com/elastic/cookbook-elasticsearch/tree/0.3.10) (2014-06-19) + +- Single node cofiguration [\#220](https://github.com/elastic/cookbook-elasticsearch/issues/220) +- can we use apt\_repository resource to install a particular version [\#217](https://github.com/elastic/cookbook-elasticsearch/issues/217) +- Version attribute effect on download\_url is misleading [\#214](https://github.com/elastic/cookbook-elasticsearch/issues/214) +- Make config template configurable [\#153](https://github.com/elastic/cookbook-elasticsearch/issues/153) + +## [0.3.9](https://github.com/elastic/cookbook-elasticsearch/tree/0.3.9) (2014-05-22) + +- 1.1.1 doesn't work [\#210](https://github.com/elastic/cookbook-elasticsearch/issues/210) +- Why does this cookbook set the es max heap size to 60% of available memory? [\#209](https://github.com/elastic/cookbook-elasticsearch/issues/209) +- Failure when adding elasticsearch service [\#204](https://github.com/elastic/cookbook-elasticsearch/issues/204) +- New release? [\#203](https://github.com/elastic/cookbook-elasticsearch/issues/203) + +## [0.3.8](https://github.com/elastic/cookbook-elasticsearch/tree/0.3.8) (2014-03-27) + +- Avoid using `recommends "monit"` in metadata.rb [\#162](https://github.com/elastic/cookbook-elasticsearch/issues/162) +- Problem with ownership of pid in /var/run/ on restart of ubuntu [\#108](https://github.com/elastic/cookbook-elasticsearch/issues/108) +- SSL support with Nginx proxy [\#226](https://github.com/elastic/cookbook-elasticsearch/issues/226) +- Compatibility with 1.0.1 [\#195](https://github.com/elastic/cookbook-elasticsearch/issues/195) +- pid\_path is owned by elasticsearch [\#193](https://github.com/elastic/cookbook-elasticsearch/issues/193) +- \[Install plugin: merge!\] \(elasticsearch::plugins line 35\) [\#187](https://github.com/elastic/cookbook-elasticsearch/issues/187) +- Cookbook doesn't work with 1.0.0RCx versions - Startup broken based on behavior change [\#185](https://github.com/elastic/cookbook-elasticsearch/issues/185) +- Failure to locate 'elasticsearch.conf.erb' template [\#184](https://github.com/elastic/cookbook-elasticsearch/issues/184) +- Question on attributes "methodology" [\#180](https://github.com/elastic/cookbook-elasticsearch/issues/180) +- print\_value docs don't mention elasticsearch [\#169](https://github.com/elastic/cookbook-elasticsearch/issues/169) +- update readme file with default attributes [\#166](https://github.com/elastic/cookbook-elasticsearch/issues/166) +- Index template config files [\#164](https://github.com/elastic/cookbook-elasticsearch/issues/164) +- Issues configuring unicast cluster [\#158](https://github.com/elastic/cookbook-elasticsearch/issues/158) +- elasticsearch default /usr/local/elasticsearch is no good for elasticsearch-env.sh [\#157](https://github.com/elastic/cookbook-elasticsearch/issues/157) + +## [0.3.7](https://github.com/elastic/cookbook-elasticsearch/tree/0.3.7) (2013-10-28) + +## [0.3.5](https://github.com/elastic/cookbook-elasticsearch/tree/0.3.5) (2013-10-27) + +- ES Logging Not Working [\#151](https://github.com/elastic/cookbook-elasticsearch/issues/151) +- Adding Debian specific init script [\#98](https://github.com/elastic/cookbook-elasticsearch/pull/98) ([remkade](https://github.com/remkade)) + +## [0.3.4](https://github.com/elastic/cookbook-elasticsearch/tree/0.3.4) (2013-10-01) + +- first install with plugins fails [\#138](https://github.com/elastic/cookbook-elasticsearch/issues/138) +- Custom Params for init.d start [\#134](https://github.com/elastic/cookbook-elasticsearch/issues/134) +- elasticsearch-cloud-aws plugin - fails to install, restarts service anyway [\#131](https://github.com/elastic/cookbook-elasticsearch/issues/131) +- init script - improvements needed [\#130](https://github.com/elastic/cookbook-elasticsearch/issues/130) +- Configure HTTP port range [\#129](https://github.com/elastic/cookbook-elasticsearch/issues/129) +- Elasticsearch fails to start with 0.90.3 and cloud-aws 1.12.0 [\#126](https://github.com/elastic/cookbook-elasticsearch/issues/126) +- Install plugin failure does not stop script execution [\#124](https://github.com/elastic/cookbook-elasticsearch/issues/124) +- search\_discovery causes unnecessary restarts [\#122](https://github.com/elastic/cookbook-elasticsearch/issues/122) +- chef-solo needs the 'cookbook' folder to have the same name as the cookbook [\#121](https://github.com/elastic/cookbook-elasticsearch/issues/121) +- Plugins not working if aws recipe is used [\#105](https://github.com/elastic/cookbook-elasticsearch/issues/105) + +## [0.3.3](https://github.com/elastic/cookbook-elasticsearch/tree/0.3.3) (2013-08-01) + +- BREAKING: Fog version does not create EBS volumes properly [\#94](https://github.com/elastic/cookbook-elasticsearch/issues/94) +- ulimit settings not used with start-stop-daemon [\#109](https://github.com/elastic/cookbook-elasticsearch/issues/109) +- mismatch in aws endpoint attributes [\#106](https://github.com/elastic/cookbook-elasticsearch/issues/106) +- Elasticsearch service restart at each chef run [\#104](https://github.com/elastic/cookbook-elasticsearch/issues/104) +- Installation fails: Error executing action `start` on resource 'service\[elasticsearch\]' [\#96](https://github.com/elastic/cookbook-elasticsearch/issues/96) + +## [0.3.2](https://github.com/elastic/cookbook-elasticsearch/tree/0.3.2) (2013-08-01) + +- role attributes ignored? [\#112](https://github.com/elastic/cookbook-elasticsearch/issues/112) +- Mismatched Data Dir permissions [\#111](https://github.com/elastic/cookbook-elasticsearch/issues/111) +- Changing nofile attribute is not idempotent [\#101](https://github.com/elastic/cookbook-elasticsearch/issues/101) +- Configure unicast\_hosts dynamically on non-AWS clusters via `search` [\#40](https://github.com/elastic/cookbook-elasticsearch/issues/40) + +## [0.3.1](https://github.com/elastic/cookbook-elasticsearch/tree/0.3.1) (2013-06-18) + +## [0.3.0](https://github.com/elastic/cookbook-elasticsearch/tree/0.3.0) (2013-06-10) + +- Fog \>= 1.11.0 breaks run with elasticsearch::ebs [\#93](https://github.com/elastic/cookbook-elasticsearch/issues/93) +- elasticsearch::ebs fails if apt package cache is out of date [\#88](https://github.com/elastic/cookbook-elasticsearch/issues/88) +- Document bare minimum configuration for default recipe [\#87](https://github.com/elastic/cookbook-elasticsearch/issues/87) +- Centos 5 / RHEL 5 Support [\#86](https://github.com/elastic/cookbook-elasticsearch/issues/86) +- Proxy recipe has hardcoded localhost which fails if elasticsearch is not bound to that IP [\#85](https://github.com/elastic/cookbook-elasticsearch/issues/85) +- AJAX requests and nginx proxy [\#84](https://github.com/elastic/cookbook-elasticsearch/issues/84) +- Readme link to Chef-solo+elasticsearch tutorial doesn't work [\#83](https://github.com/elastic/cookbook-elasticsearch/issues/83) +- You must set ES\_CLASSPATH var [\#82](https://github.com/elastic/cookbook-elasticsearch/issues/82) +- Setting a custom installation directory doesn't work [\#79](https://github.com/elastic/cookbook-elasticsearch/issues/79) + +## [0.2.7](https://github.com/elastic/cookbook-elasticsearch/tree/0.2.7) (2013-03-18) + +## [0.2.6](https://github.com/elastic/cookbook-elasticsearch/tree/0.2.6) (2013-03-08) + +- Broken attempted aws plugin installation by default [\#76](https://github.com/elastic/cookbook-elasticsearch/issues/76) +- Using setup with ELB [\#70](https://github.com/elastic/cookbook-elasticsearch/issues/70) + +## [0.2.5](https://github.com/elastic/cookbook-elasticsearch/tree/0.2.5) (2013-03-01) + +- Elasticsearch with node.client set to true [\#71](https://github.com/elastic/cookbook-elasticsearch/issues/71) + +## [0.2.4](https://github.com/elastic/cookbook-elasticsearch/tree/0.2.4) (2013-02-27) + +## [0.2.3](https://github.com/elastic/cookbook-elasticsearch/tree/0.2.3) (2013-02-27) + +- When updating versions, the wrong version can be installed unless you manually clear node attributes \(chef server only\) [\#69](https://github.com/elastic/cookbook-elasticsearch/issues/69) +- The version of elasticsearch can only be set via elasticsearch/settings databag [\#68](https://github.com/elastic/cookbook-elasticsearch/issues/68) + +## [0.2.2](https://github.com/elastic/cookbook-elasticsearch/tree/0.2.2) (2013-02-26) + +## [0.2.1](https://github.com/elastic/cookbook-elasticsearch/tree/0.2.1) (2013-02-26) + +- Unable to change elasticsearch version via role and version tag [\#61](https://github.com/elastic/cookbook-elasticsearch/issues/61) +- Creating new ebs volume is taking forever [\#60](https://github.com/elastic/cookbook-elasticsearch/issues/60) + +## [0.2.0](https://github.com/elastic/cookbook-elasticsearch/tree/0.2.0) (2013-02-01) + +- Failing installation test on master [\#56](https://github.com/elastic/cookbook-elasticsearch/issues/56) +- Error message when running start script [\#48](https://github.com/elastic/cookbook-elasticsearch/issues/48) + +## [0.1.0](https://github.com/elastic/cookbook-elasticsearch/tree/0.1.0) (2013-01-28) + +## [0.0.1](https://github.com/elastic/cookbook-elasticsearch/tree/0.0.1) (2013-01-28) + +- Update Gists for Ark change [\#28](https://github.com/elastic/cookbook-elasticsearch/issues/28) +- Conflict with nginx cookbook [\#46](https://github.com/elastic/cookbook-elasticsearch/issues/46) +- version bump the metadata [\#42](https://github.com/elastic/cookbook-elasticsearch/issues/42) +- elasticsearch::test doesn't work in ec2 with chef server [\#41](https://github.com/elastic/cookbook-elasticsearch/issues/41) +- Nginx rpm install doesn't support chunkin module [\#38](https://github.com/elastic/cookbook-elasticsearch/issues/38) + +## [0.0.6](https://github.com/elastic/cookbook-elasticsearch/tree/0.0.6) (2013-01-15) + +- Cannot find a resource for create\_ebs on amazon version 2012.09 [\#44](https://github.com/elastic/cookbook-elasticsearch/issues/44) + +## [0.0.5](https://github.com/elastic/cookbook-elasticsearch/tree/0.0.5) (2012-12-20) + +- Add `discovery.ec2.tag` and similar to elasticsearch.yml [\#36](https://github.com/elastic/cookbook-elasticsearch/issues/36) +- Add support for setting cloud.aws.region using node.json [\#33](https://github.com/elastic/cookbook-elasticsearch/issues/33) +- Elasticsearch doesn't start after run 'sudo chef-client' over knife ssh [\#32](https://github.com/elastic/cookbook-elasticsearch/issues/32) +- Can't find Monit template? [\#29](https://github.com/elastic/cookbook-elasticsearch/issues/29) +- Monit doesn't start after machine reboot [\#14](https://github.com/elastic/cookbook-elasticsearch/issues/14) +- Probable bugs in install\_plugin.rb [\#12](https://github.com/elastic/cookbook-elasticsearch/issues/12) + +## [0.0.4](https://github.com/elastic/cookbook-elasticsearch/tree/0.0.4) (2012-10-15) + +## [0.0.3](https://github.com/elastic/cookbook-elasticsearch/tree/0.0.3) (2012-10-14) + +- min\_mem should be the same as max\_mem [\#35](https://github.com/elastic/cookbook-elasticsearch/issues/35) +- The `elasticsearch::proxy\_nginx` should declare dependency on `nginx` cookbook [\#24](https://github.com/elastic/cookbook-elasticsearch/issues/24) +- Appears to install nginx even in cases when it's not requested \(no proxy\) [\#23](https://github.com/elastic/cookbook-elasticsearch/issues/23) + +## [0.0.2](https://github.com/elastic/cookbook-elasticsearch/tree/0.0.2) (2012-08-18) + +- -Xss128k is too low [\#25](https://github.com/elastic/cookbook-elasticsearch/issues/25) +- Ubuntu Tests Failing [\#22](https://github.com/elastic/cookbook-elasticsearch/issues/22) +- getting an error trying to install plugin [\#21](https://github.com/elastic/cookbook-elasticsearch/issues/21) +- you must set ES\_CLASSPATH [\#20](https://github.com/elastic/cookbook-elasticsearch/issues/20) +- Need a more comprehensive max\_mem calculation [\#15](https://github.com/elastic/cookbook-elasticsearch/issues/15) +- Missing support for status command of the elasticsearch service [\#11](https://github.com/elastic/cookbook-elasticsearch/issues/11) +- Discovery settings in elasticsearch.yml.erb [\#9](https://github.com/elastic/cookbook-elasticsearch/issues/9) +- Monit issues \(template file name, internal issues\) [\#8](https://github.com/elastic/cookbook-elasticsearch/issues/8) +- Align elasticsearch-env.sh.erb with elasticsearch.in.sh [\#3](https://github.com/elastic/cookbook-elasticsearch/issues/3) diff --git a/cookbooks/elasticsearch/CONTRIBUTING.md b/cookbooks/elasticsearch/CONTRIBUTING.md new file mode 100644 index 0000000..8085cc4 --- /dev/null +++ b/cookbooks/elasticsearch/CONTRIBUTING.md @@ -0,0 +1,111 @@ +Contributing to cookbook-elasticsearch +====================================== + +### General philosophy + +We try, as much as possible, to mirror the upstream experience of installing, configuring, and running Elasticsearch. Sometimes, the upstream project won't expose certain settings, or provide defaults that everyone agrees with. Wherever possible, we will: + +- follow the upstream standards for specific config files +- include any files shipped with packages upstream in this cookbook as-is +- expose a template and cookbook setting for any file that you might want to modify +- recommend major changes to standard files be sent upstream first +- minimize the number of exceptions and maintained "workarounds" in this cookbook + +### Workflow for contributing + +1. Create a branch directly in this repo or a fork (if you don't have push access). Please name branches within this repository `/`. For example, something like karmi/install_from_deb. + +1. Create an issue or open a PR. If you aren't sure your PR will solve the issue, or may be controversial, we commend opening an issue separately and linking to it in your PR, so that if the PR is not accepted, the issue will remain and be tracked. + +1. Close (and reference) issues by the `closes #XXX` or `fixes #XXX` notation in the commit message. Please use a descriptive, useful commit message that could be used to understand why a particular change was made. + +1. Keep pushing commits to the initial branch, `--amend`-ing if necessary. Please don't mix fixing unrelated issues in a single branch. + +1. When everything is ready for merge, clean up the branch (rebase with master to synchronize, squash, edit commits, etc) to prepare for it to be merged. + +### Merging contributions + +1. After reviewing commits for documentation, passing CI tests, and good descriptive commit messages, merge it with --no-ff switch, so it's indicated in the Git history + +1. Do not use the Github "merge button", since it doesn't do a fast-forward merge (see previous item). + +### Testing + +This cookbook is equipped with both unit tests (chefspec) and integration tests +(test-kitchen and serverspec). It also comes with rubocop and foodcritic tasks +in the supplied Rakefile. Contributions to this cookbook should include tests +for new features or bugfixes, with a preference for unit tests over integration +tests to ensure speedy testing runs. ***All tests and most other commands here +should be run using bundler*** and our standard Gemfile. This ensures that +contributions and changes are made in a standardized way against the same +versions of gems. We recommend installing rubygems-bundler so that bundler is +automatically inserting `bundle exec` in front of commands run in a directory +that contains a Gemfile. + +A full test run of all tests and style checks would look like: +```bash +$ bundle exec rake style +$ bundle exec rake spec +$ bundle exec rake integration +$ bundle exec rake destroy +``` +The final destroy is intended to clean up any systems that failed a test, and is +mostly useful when running with kitchen drivers for cloud providers, so that no +machines are left orphaned and costing you money. + +#### Fixtures + +This cookbook supplies a few different test fixtures (under `test/fixtures/`) +that can be shared amongst any number of unit or integration tests: cookbooks, +environments, and nodes. Environments and nodes are automatically loaded into +chef-zero for both chefspec tests that run locally and serverspec tests that run +from test-kitchen. + +It also contains 'platform data' that can be used to drive unit testing, for +example, you might read `httpd` for some platforms and `apache2` for others, +allowing you to write a single test for the Apache webserver. Unfortunately, +without further modifications to `busser` and `busser-serverspec`, the platform +data will not be available to serverspec tests. + +#### Style and Best Practices + +Rubocop and Foodcritic evaluations may be made by running `rake style`. There +are no overrides for foodcritic rules, however the adjustments to +rubocop are made using the supplied `.rubocop.yml` file and have been documented +by comments within. Most notably, rubocop has been restricted to only apply to +`.rb` files. + +Rubocop and foodcritic tests can be executed using `rake style`. + +#### Unit testing + +Unit testing is done using the latest versions of Chefspec. The current default +test layout includes running against all supported platforms, as well as +stubbing data into chef-zero. This allows us to also test against chef search. +As is currently a best practice in the community, we will avoid the use of +chef-solo, but not create barriers to explicitly fail for chef-solo. + +Unit tests can be executed using `rake spec`. + +#### Integration testing + +Integration testing is accomplished using the latest versions of test-kitchen +and serverspec. Currently, this cookbook uses the busser-serverspec plugin for +copying serverspec files to the system being tested. There is some debate in the +community about whether this should be done using busser-rspec instead, and each +busser plugin has a slightly different feature set. + +While the default test-kitchen configuration uses the vagrant driver, you may +override this using `~/.kitchen/config.yml` or by placing a `.kitchen.local.yml` +in the current directory. This allows you to run these integration tests using +any supported test-kitchen driver (ec2, rackspace, docker, etc). + +Integration tests can be executed using `rake integration` or `kitchen test`. + +### Releasing + +1. Create/update the changelog. We are using the `github_changelog_generator` +gem. + +1. We highly recommend using the `stove` project, which pushes cookbooks to +Supermarket and tags to Github. diff --git a/cookbooks/elasticsearch/README.md b/cookbooks/elasticsearch/README.md new file mode 100644 index 0000000..fed8cf8 --- /dev/null +++ b/cookbooks/elasticsearch/README.md @@ -0,0 +1,394 @@ +# Elasticsearch Chef Cookbook + +[![Build Status](https://travis-ci.org/elastic/cookbook-elasticsearch.svg?branch=master)](https://travis-ci.org/elastic/cookbook-elasticsearch) [![Cookbook Version](https://img.shields.io/cookbook/v/elasticsearch.svg)](https://supermarket.chef.io/cookbooks/elasticsearch)[![Build Status](https://jenkins-01.eastus.cloudapp.azure.com/job/elasticsearch-cookbook/badge/icon)](https://jenkins-01.eastus.cloudapp.azure.com/job/elasticsearch-cookbook/) + +**Please** review the [frequently asked questions](FAQ.md) and [contributing guidelines](CONTRIBUTING.md) before opening issues or submitting pull requests. + +## Looking for Elasticsearch 5.x or 6.x? + +Please [check out the previous 3.x.x releases](https://github.com/elastic/cookbook-elasticsearch/tree/3.x.x) of this cookbook. Please consider pinning your cookbook to '~> 3.0' for support for Elasticsearch 6 and earlier, or '~> 4.0' release for Elasticsearch 6 and beyond. + +## Attributes + +Please consult [attributes/default.rb](attributes/default.rb) for a large list +of checksums for many different archives and package files of different +elasticsearch versions. Both recipes and resources/providers here use those +default values. + +You may use `%s` in your URL and this cookbook will use sprintf/format to insert +the version parameter as a string into your download_url. + +|Name|Default|Other values| +|----|-------|------------| +| For Elasticsearch < 7: || +|`default['elasticsearch']['download_urls']['debian']`|[See values](attributes/default.rb).|`%s` will be replaced with the version attribute above| +|`default['elasticsearch']['download_urls']['rhel']`|[See values](attributes/default.rb).|`%s` will be replaced with the version attribute above| +|`default['elasticsearch']['download_urls']['tarball']`|[See values](attributes/default.rb).|`%s` will be replaced with the version attribute above| +| For Elasticsearch >= 7: || +|`default['elasticsearch']['download_urls_v7']['debian']`|[See values](attributes/default.rb).|`%s` will be replaced with the version attribute above| +|`default['elasticsearch']['download_urls_v7']['rhel']`|[See values](attributes/default.rb).|`%s` will be replaced with the version attribute above| +|`default['elasticsearch']['download_urls_v7']['tarball']`|[See values](attributes/default.rb).|`%s` will be replaced with the version attribute above| + +This cookbook's `elasticsearch::default` recipe also supports setting any `elasticsearch_` resource using attributes: + +``` +default['elasticsearch']['user'] = {} +default['elasticsearch']['install'] = {} +default['elasticsearch']['configure'] = {} +default['elasticsearch']['service'] = {} +default['elasticsearch']['plugin'] = {} +``` + +For example, this will pass a username 'foo' to `elasticsearch_user` and set a uid to `1234`: +``` +default['elasticsearch']['user']['username'] = 'foo' +default['elasticsearch']['user']['uid'] = '1234' +``` + +## Recipes + +Resources are the intended way to consume this cookbook, however we have +provided a single recipe that configures Elasticsearch by downloading an archive +containing a distribution of Elasticsearch, and extracting that into `/usr/share`. + +See the attributes section above to for what defaults you can adjust. + +### default + +The default recipe creates an elasticsearch user, group, package installation, +configuration files, and service with all of the default options. + +Please note that there are [additional examples within the test fixtures](test/fixtures/cookbooks/elasticsearch_test), +including a demonstration of how to configure two instances of Elasticsearch on a single server. + +## Resources + +## Notifications and Service Start/Restart + +The resources provided in this cookbook **do not automatically restart** services when changes have occurred. They ***do start services by default when configuring a new service*** This has been done to protect you from accidental data loss and service outages, as nodes might restart simultaneously or may not restart at all when bad configuration values are supplied. + +elasticsearch_service has a special `service_actions` parameter you can use to specify what state the underlying service should be in on each chef run (defaults to `:enabled` and `:started`). It will also pass through all of the standard `service` resource +actions to the underlying service resource if you wish to notify it. + +You **must** supply your desired notifications when using each resource if you want Chef to automatically restart services. Again, we don't recommend this unless you know what you're doing. + +We are supporting whyrun mode in this cookbook, simply because we're using all builtin resources from core Chef, and these also already support whyrun. If you contribute to this cookbook, please be sure to maintain that or guard dangerous Ruby code with something like `if !whyrun_mode? || nested_resource.whyrun_supported?`. + +### Resource names + +Many of the resources provided in this cookbook need to share configuration +values. For example, the `elasticsearch_service` resource needs to know the path +to the configuration file(s) generated by `elasticsearch_configure` and the path +to the actual ES binary installed by `elasticsearch_install`. And they both need +to know the appropriate system user and group defined by `elasticsearch_user`. + +Search order: In order to make this easy, all resources in this cookbook use the following +search order to locate resources that apply to the same overall +Elasticsearch setup: + +1. Resources that share the same resource name +1. Resources that share the same value for `instance_name` +1. Resources named `default` or resources named `elasticsearch` + - This fails if both `default` and `elasticsearch` resources exist + +Examples of more complicated resource names are left to the reader, but here we +present a typical example that should work in most cases: + +```ruby +elasticsearch_user 'elasticsearch' +elasticsearch_install 'elasticsearch' +elasticsearch_configure 'elasticsearch' +elasticsearch_service 'elasticsearch' +elasticsearch_plugin 'x-pack' +``` + +### elasticsearch_user +Actions: `:create`, `:remove` + +Creates a user and group on the system for use by elasticsearch. Here is an +example with many of the default options and default values (all options except +a resource name may be omitted). + +Examples: + +```ruby +elasticsearch_user 'elasticsearch' +``` + +```ruby +elasticsearch_user 'elasticsearch' do + username 'elasticsearch' + groupname 'elasticsearch' + shell '/bin/bash' + comment 'Elasticsearch User' + + action :create +end +``` + +### elasticsearch_install +Actions: `:install`, `:remove` + +Downloads the elasticsearch software, and unpacks it on the system. There are +currently three ways to install -- `'repository'` (the default), which creates an +apt or yum repo and installs from there, `'package'`, which downloads the appropriate +package from elasticsearch.org and uses the package manager to install it, and +`'tarball'` which downloads a tarball from elasticsearch.org and unpacks it. +This resource also comes with a `:remove` action which will remove the package +or directory elasticsearch was unpacked into. + +You may always specify a download_url and/or download_checksum, and you may +include `%s` which will be replaced by the version parameter you supply. + +Please be sure to consult the above attribute section as that controls how +Elasticsearch version, download URL and checksum are determined if you omit +them. + +**NOTE**: The `:remove` action has not been implemented yet. Pull requests are +very much welcome & encouraged, if you'd like to see this feature. + +Examples: + +```ruby +elasticsearch_install 'elasticsearch' +``` + +```ruby +elasticsearch_install 'my_es_installation' do + type 'package' # type of install + version '7.3.0' + action :install # could be :remove as well +end +``` + +```ruby +elasticsearch_install 'my_es_installation' do + type 'tarball' # type of install + dir '/usr/local' # where to install + + download_url "https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.7.2.tar.gz" + # sha256 + download_checksum "6f81935e270c403681e120ec4395c28b2ddc87e659ff7784608b86beb5223dd2" + + action :install # could be :remove as well +end +``` + +```ruby +elasticsearch_install 'my_es_installation' do + type 'tarball' # type of install + version '7.3.0' + action :install # could be :remove as well +end +``` + +```ruby +elasticsearch_install 'my_es_installation' do + type 'package' # type of install + download_url "https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.7.2.deb" + # sha256 + download_checksum "791fb9f2131be2cf8c1f86ca35e0b912d7155a53f89c2df67467ca2105e77ec2" + instance_name 'elasticsearch' + action :install # could be :remove as well +end +``` + +### elasticsearch_configure +Actions: `:manage`, `:remove` + +Configures an elasticsearch instance; creates directories for configuration, +logs, and data. Writes files `log4j2.properties`, `elasticsearch.in.sh` and +`elasticsearch.yml`. + +The main attribute for this resource is `configuration`, +which is a hash of any elasticsearch configuration directives. The +other important attribute is `default_configuration` -- this contains the +minimal set of required defaults. + +Note that these are both _not_ a Chef mash, everything must be in a single level +of keys and values. Any settings you pass in configuration will be merged into +(and potentially overwrite) any default settings. + +See the examples, [as well as the attributes in the resource file](libraries/resource_configure.rb), +for more. + +Examples: + +With all defaults - +```ruby +elasticsearch_configure 'elasticsearch' +``` + +With mostly defaults - +```ruby +elasticsearch_configure 'elasticsearch' do + allocated_memory '512m' + configuration ({ + 'cluster.name' => 'escluster', + 'node.name' => 'node01', + 'http.port' => 9201 + }) +end +``` + +Very complicated - +```ruby +elasticsearch_configure 'my_elasticsearch' do + # if you override one of these, you probably want to override all + path_home "/opt/elasticsearch" + path_conf "/etc/opt/elasticsearch" + path_data "/var/opt/elasticsearch" + path_logs "/var/log/elasticsearch" + path_pid "/var/run/elasticsearch" + path_plugins "/opt/elasticsearch/plugins" + path_bin "/opt/elasticsearch/bin" + + # override logging parameters + cookbook_log4j2_properties "my_wrapper_cookbook" + template_log4j2_properties "my_log4j2.properties.erb" + + logging({:"action" => 'INFO'}) + + allocated_memory '123m' + + jvm_options %w( + -XX:+UseParNewGC + -XX:+UseConcMarkSweepGC + -XX:CMSInitiatingOccupancyFraction=75 + -XX:+UseCMSInitiatingOccupancyOnly + -XX:+HeapDumpOnOutOfMemoryError + -XX:+PrintGCDetails + ) + + configuration ({ + 'node.name' => 'crazy' + }) + + action :manage +end +``` + +### elasticsearch_service +Actions: `:configure`, `:remove` + +Writes out a system service configuration of the appropriate type, and enables +it to start on boot. You can override almost all of the relevant settings in +such a way that you may run multiple instances. Most settings will be taken from +a matching `elasticsearch_config` resource in the collection. + +```ruby +elasticsearch_service 'elasticsearch' +``` + +If you'd like to skip init scripts and systemd scripts, simply pass `nil` for +the template file (init_source or systemd_source) and this cookbook will +entirely skip trying to setup those scripts. Combined with changing the default +service actions, this will have the same effect as `action :nothing`. + +### elasticsearch_plugin +Actions: `:install`, `:remove` + +Installs or removes a plugin to a given elasticsearch instance and plugin +directory. Please note that there is currently no way to upgrade an existing +plugin using commandline tools, so we haven't exposed that feature here either. +Furthermore, there isn't a way to determine if a plugin is compatible with ES or +even what version it is. So once we install a plugin to a directory, we +generally assume that is the desired one and we don't touch it further. + +See https://github.com/elastic/cookbook-elasticsearch/issues/264 for more info. +NB: You [may encounter issues on certain distros](http://blog.backslasher.net/java-ssl-crash.html) with NSS 3.16.1 and OpenJDK 7.x. + +Officially supported or commercial plugins require just the plugin name: + +```ruby +elasticsearch_plugin 'analysis-icu' do + action :install +end +elasticsearch_plugin 'shield' do + action :install +end +``` + +Plugins from GitHub require a URL of 'username/repository' or 'username/repository/version': + +```ruby +elasticsearch_plugin 'kopf' do + url 'lmenezes/elasticsearch-kopf' + action :install +end + +elasticsearch_plugin 'kopf' do + url 'lmenezes/elasticsearch-kopf/1.5.7' + action :install +end +``` + +Plugins from Maven Central or Sonatype require 'groupId/artifactId/version': +```ruby +elasticsearch_plugin 'mapper-attachments' do + url 'org.elasticsearch/elasticsearch-mapper-attachments/2.6.0' + action :install +end +``` + +Plugins can be installed from a custom URL or file location as follows: +```ruby +elasticsearch_plugin 'mapper-attachments' do + url 'http://some.domain.name//my-plugin-1.0.0.zip' + action :install +end + +elasticsearch_plugin 'mapper-attachments' do + url 'file:/path/to/my-plugin-1.0.0.zip' + action :install +end +``` + +The plugin resource respects the `https_proxy` or `http_proxy` (non-SSL) +[Chef settings](https://docs.chef.io/config_rb_client.html) unless explicitly +disabled using `chef_proxy false`: +```ruby +elasticsearch_plugin 'kopf' do + url 'lmenezes/elasticsearch-kopf' + chef_proxy false + action :install +end +``` + +To run multiple instances per machine, an explicit `plugin_dir` location +has to be provided: + +```ruby +elasticsearch_plugin 'x-pack' do + plugin_dir '/usr/share/elasticsearch_foo/plugins' +end +``` + +If for some reason, you want to name the resource something else, you may +provide the true plugin name using the `plugin_name` parameter: + +```ruby +elasticsearch_plugin 'xyzzy' do + plugin_name 'kopf' + url 'lmenezes/elasticsearch-kopf' + action :install +end +``` + +## License + +This software is licensed under the Apache 2 license, quoted below. + + Copyright (c) 2015 Elasticsearch + + 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/cookbooks/elasticsearch/attributes/default.rb b/cookbooks/elasticsearch/attributes/default.rb new file mode 100644 index 0000000..be118ff --- /dev/null +++ b/cookbooks/elasticsearch/attributes/default.rb @@ -0,0 +1,169 @@ +# empty settings (populate these for the elasticsearch::default recipe) +# see the resources or README.md to see what you can pass here. +default['elasticsearch']['user'] = {} +default['elasticsearch']['install'] = {} +default['elasticsearch']['configure'] = {} +default['elasticsearch']['service'] = {} +default['elasticsearch']['plugin'] = {} + +# platform_family keyed download URLs +default['elasticsearch']['download_urls'] = { + 'debian' => 'https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-%s.deb', + 'rhel' => 'https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-%s.rpm', + 'tarball' => 'https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-%s.tar.gz', +} + +default['elasticsearch']['download_urls_v7'] = { + 'debian' => 'https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-%s-amd64.deb', + 'rhel' => 'https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-%s-x86_64.rpm', + 'tarball' => 'https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-%s-linux-x86_64.tar.gz', +} + +# platform_family keyed download sha256 checksums +default['elasticsearch']['checksums']['6.0.0']['debian'] = '28f38779156387c1db274d8d733429e574b54b4f518da6f0741f6276f8229939' +default['elasticsearch']['checksums']['6.0.0']['rhel'] = '823fa8aa24e9948dea30f0a468f0403b34a62180e02ed752443d5964334c29a1' +default['elasticsearch']['checksums']['6.0.0']['tarball'] = '0420e877a8b986485244f603770737e9e4e47186fdfa1093768a11e391e3d9f4' + +default['elasticsearch']['checksums']['6.0.1']['debian'] = 'ebe6c14638a4909155fe409fb46a7f52bcd3ad2151bfd2f400ab6f8f61c45b3e' +default['elasticsearch']['checksums']['6.0.1']['rhel'] = '25e7a8b152ea85886688398f48bc995d47cd2a12a7d98487748c6166f0732b85' +default['elasticsearch']['checksums']['6.0.1']['tarball'] = 'efaf32aba41e1b7fd086639c0f062c39e1f28b360a78d5c2b8deed797a4c5c57' + +default['elasticsearch']['checksums']['6.1.0']['debian'] = '102be4439b1df7f7606003b3c839dbf69d3827c3e996563c98c0d54560b4fc16' +default['elasticsearch']['checksums']['6.1.0']['rhel'] = 'ebac1b4e1fc8ae3f7266cba93ef113510cba13435ada2c92480506d16cf6b865' +default['elasticsearch']['checksums']['6.1.0']['tarball'] = 'c879fe2698635a2f132db4a02d84f657bc0ccdb5c5f68dda5102f9b2afa508d7' + +default['elasticsearch']['checksums']['6.1.1']['debian'] = '8b6e65dce742c733aa61da24f9c8c0d4d4b7f53ae11d7f4168e98b5a0ed58b45' +default['elasticsearch']['checksums']['6.1.1']['rhel'] = '9820555c72b61b54686bcf0697cdabace28b02315bb5a156999495a16b103d5a' +default['elasticsearch']['checksums']['6.1.1']['tarball'] = '0cadc90c2ab1bd941e3965eef96fbc2c08b12b832ae81f5882e81505333b74b6' + +default['elasticsearch']['checksums']['6.1.2']['debian'] = '64d8bd2bd895904bb91daff656764b10da93531f2011c94d7c779124e53dd5f5' +default['elasticsearch']['checksums']['6.1.2']['rhel'] = 'bfa6809ac94bda92a4ec1bf601c8266f82a4c7842a7702da4dede8f7d5c6a2ec' +default['elasticsearch']['checksums']['6.1.2']['tarball'] = '9c0eae0bdab78c59dac0ba3a9c054e6785dc0f5ce4666e284f42010a326abc0f' + +default['elasticsearch']['checksums']['6.2.0']['debian'] = 'eeb974247ea4360e37798888a5f49227d5ea33e11665a060c9b01b25140f9554' +default['elasticsearch']['checksums']['6.2.0']['rhel'] = '869b6506a35aad6b6d82fe987130402cef9b40c33ff7d98eeaa186eb2a628964' +default['elasticsearch']['checksums']['6.2.0']['tarball'] = '7be4a6580aca7d17b2fe1a1e589aa0a005b6240ef5dce6a5288a56f68021f8f6' + +default['elasticsearch']['checksums']['6.2.1']['debian'] = '2b145aa11bccd2fe99256b9715ff665fe091b62fc699bc77cd07c528dcbf2391' +default['elasticsearch']['checksums']['6.2.1']['rhel'] = '47b97342821cbd1805826a18a7559a59bd045b9aef66e45c3b293b02aeaaeba8' +default['elasticsearch']['checksums']['6.2.1']['tarball'] = '0ccd13c53d23dcb2aea5c0f71dcbe81283e1e31d6ae5d40dec03656852cb468b' + +default['elasticsearch']['checksums']['6.2.2']['debian'] = 'e0a694dcbbac993a4039978ca60e6c05b0bd78ec7eef20a1e95b98979579a47a' +default['elasticsearch']['checksums']['6.2.2']['rhel'] = 'a31277bb89b93da510bf40261882f710a448178ec5430c7a78ac77e91f733cf9' +default['elasticsearch']['checksums']['6.2.2']['tarball'] = 'b26e3546784b39ce3eacc10411e68ada427c5764bcda3064e9bb284eca907983' + +default['elasticsearch']['checksums']['6.2.3']['debian'] = 'b54a1b685656a1424d4956e48daed923752fc268b79bb1b8616cc91f6a78e3bb' +default['elasticsearch']['checksums']['6.2.3']['rhel'] = 'd513a6f82436914c35e774529686e5fdfed1af77264e39228e5d64eee22c78ce' +default['elasticsearch']['checksums']['6.2.3']['tarball'] = '01dd8dec5f0acf04336721e404bf4d075675a3acae9f2a9fdcdbb5ca11baca76' + +default['elasticsearch']['checksums']['6.2.4']['debian'] = 'f9c889bf1e2e897a881f624dab6a4aa3be5ec1f9d65b6d115021095496351969' +default['elasticsearch']['checksums']['6.2.4']['rhel'] = '9c13e0fb8bc90b7bd6e09c8ba922c2d89c2183bb6161047ec6549c0cbcccee72' +default['elasticsearch']['checksums']['6.2.4']['tarball'] = '91e6f1ea1e1dd39011e7a703d2751ca46ee374665b08b0bfe17e0c0c27000e8e' + +default['elasticsearch']['checksums']['6.3.0']['debian'] = '659c3f9a90ae5fe4568d5103de3bbd37e8a03143447118ee61fe72d514b8f4d6' +default['elasticsearch']['checksums']['6.3.0']['rhel'] = 'b6d7951b8ad72c06e7a23263227e1b90b8aa6e5d5ee798a6c849934516121109' +default['elasticsearch']['checksums']['6.3.0']['tarball'] = '0464127140820d82b24bd2830232131ea85bcd49267a8bc7365e4fa391dee2a3' + +default['elasticsearch']['checksums']['6.3.1']['debian'] = '350cc95201814ec39b1c80bbb8329faf1dae20a3386b28b626144c6f67ced333' +default['elasticsearch']['checksums']['6.3.1']['rhel'] = '073e2bc52a82bc099cca1534391a057c6506dbcb06e849e24ff4d60187ade4b3' +default['elasticsearch']['checksums']['6.3.1']['tarball'] = '0b4d1c3c66894c9bf54284b53c1448d0e6def89a09c9fe4446e7167e51b8040e' + +default['elasticsearch']['checksums']['6.4.0']['debian'] = 'dc7b4b5583ad4689f57369fb8bf8c9b708cfc278701c895762378b010460f658' +default['elasticsearch']['checksums']['6.4.0']['rhel'] = 'b7b8e6265ec4a3aec509fe1e3fb054e6c64256ce7f4ab64d1d5b1629b24883c2' +default['elasticsearch']['checksums']['6.4.0']['tarball'] = 'e9786efb5cecd12adee2807c7640ba9a1ab3b484d2e87497bb8d0b6df0e24f01' + +default['elasticsearch']['checksums']['6.4.1']['debian'] = 'ba71dbe16bfb6111dbe7d49ffd447ed1092a754636b30214067d31ff3059e100' +default['elasticsearch']['checksums']['6.4.1']['rhel'] = '2d63f9814ff67edc5c8a8e247ed359a8ef7e23cfbe3a438041a72b44b0be09b2' +default['elasticsearch']['checksums']['6.4.1']['tarball'] = '6fce529465975b2cd2f5aef09b459006636e4b903e623fd6361ae9feeebf1542' + +default['elasticsearch']['checksums']['6.4.2']['debian'] = '4ca2cc982db8e46743a98e2c3d678e60c24331b28f79ea424bb8a323e611f678' +default['elasticsearch']['checksums']['6.4.2']['rhel'] = '8987285d92d0d94f0e842e51ba8ed04fb9ad5e078cc68f63ef2ff8ca1986ad08' +default['elasticsearch']['checksums']['6.4.2']['tarball'] = '32a9c0305faed1cbd4e22c85a8c333ca2b6704f1d0006e92709fada10cec3f45' + +default['elasticsearch']['checksums']['6.4.3']['debian'] = 'cbf62cf228e556ca89d94562cb747127da69f5a4a04198d1a19230455671d0d4' +default['elasticsearch']['checksums']['6.4.3']['rhel'] = 'd059c695eadefc26788106a7d3d4c6b300bc50ede36dfbcb04b1caa9211d5bff' +default['elasticsearch']['checksums']['6.4.3']['tarball'] = '861bc4d4188ce65df34a8876f104bbb2cddff3586990e57233e0847eb961b15e' + +default['elasticsearch']['checksums']['6.5.0']['debian'] = '5fddd2759f7a96f884b0bfb863e04624ba50db39fa6455a87bef2b7bc4bff16e' +default['elasticsearch']['checksums']['6.5.0']['rhel'] = 'b78a6d3ddb59d086f0da28a2e25d9e5f0b5af61f0fd2898ce972f7ca9e84f961' +default['elasticsearch']['checksums']['6.5.0']['tarball'] = 'b158c02dddccc265d25855282015a7b09207c216be99c08114514ed283969b81' + +default['elasticsearch']['checksums']['6.5.1']['debian'] = '7de183122a9dbb7b07ee56e18edf0365dc27e413a5962363b944a9aa63ffbb4a' +default['elasticsearch']['checksums']['6.5.1']['rhel'] = 'fc38dcce176a96665c0801054794f62d8a9a23c9f930919248cfbe2622c7255e' +default['elasticsearch']['checksums']['6.5.1']['tarball'] = '17cf2f58c7cbb36c4419a8143321660defe2c492b3a6eaa9a6dcd5e36347d124' + +default['elasticsearch']['checksums']['6.5.2']['debian'] = '9cb0997dc6d2be16c988c0ee43ccafd19a8b2e757326af84f4cead40f74c614f' +default['elasticsearch']['checksums']['6.5.2']['rhel'] = 'ddab10c3be94fb89bc7057bdb20624b5e65e3ba8244d655e243119a5103e07c7' +default['elasticsearch']['checksums']['6.5.2']['tarball'] = 'b7b73b871957bdcff75d333eba8c1c6adf3731470f943b159365bde413e45dfc' + +default['elasticsearch']['checksums']['6.5.3']['debian'] = '38b30461201fe8d126d124f04d961e7c037bea7a6fb9ca485c08e681d8d30456' +default['elasticsearch']['checksums']['6.5.3']['rhel'] = '2f3eb7682e06211061bea90a0314a515f0c4ef683f45c8e57bfb1dfb14679c3a' +default['elasticsearch']['checksums']['6.5.3']['tarball'] = 'cee4340dfaadf27d73ccaef5a8019e177021e1ffea3b7e622ca5ab9267725cac' + +default['elasticsearch']['checksums']['6.5.4']['debian'] = 'c0a062ffb45f989cd3091c66f62605178c41c3735991d95506a6986a90924833' +default['elasticsearch']['checksums']['6.5.4']['rhel'] = 'aa4006f754bd1a0bfaa338ba40d93a1762917c1862951577c62b1f073026b5ba' +default['elasticsearch']['checksums']['6.5.4']['tarball'] = '762e25c036fa2e882cb7e91d83868fa15a1cad8549d279a8c5826a005bb31877' + +default['elasticsearch']['checksums']['6.6.0']['debian'] = '0f34cd050bc2a6b4f3a4a8ea71755a03c638e1d929141424a246792e067534a9' +default['elasticsearch']['checksums']['6.6.0']['rhel'] = '8fdaaefa22cef3370bdf353df09bf07695d0e3764ac0c9b6ad8a1412076f9566' +default['elasticsearch']['checksums']['6.6.0']['tarball'] = '4993a17b88268a053042510404bcb808f86d6438fec458be4e0ef1c412681655' + +default['elasticsearch']['checksums']['6.6.1']['debian'] = '505d5aae1c2ba66e36be41fe94ec9e4c444cbdd7926aaaa9392356a2c40d2102' +default['elasticsearch']['checksums']['6.6.1']['rhel'] = '3ba9ef562c951eccd070704db498dcf703f05b567d459f93f144e9189e1ee21a' +default['elasticsearch']['checksums']['6.6.1']['tarball'] = 'a4fd359facf03272013e3f2bffc846c1e1f8c60b7fb0daf856831f14947ed297' + +default['elasticsearch']['checksums']['6.6.2']['debian'] = 'e5aa8b1449fb08b56ec5d9a52324cadd7439c29533fa7662badede051a9a9778' +default['elasticsearch']['checksums']['6.6.2']['rhel'] = '8a42533764f0332e09cb6d2ed2af02a641766d73a3669458b20fe37615047872' +default['elasticsearch']['checksums']['6.6.2']['tarball'] = 'f32d6fa73b466e29f30a5b6e0bcc6352a5508329f765c948c80c242ddfb97770' + +default['elasticsearch']['checksums']['6.7.0']['debian'] = 'fdf31c8774b779cf5bf3c3f6e01371d11b5a3889ca3d9c3dbd2dc6142d96a633' +default['elasticsearch']['checksums']['6.7.0']['rhel'] = 'e09010ab7cbf5c81f8821e25a6617de29bcc658a3c79750e337471ef4711d8b4' +default['elasticsearch']['checksums']['6.7.0']['tarball'] = 'bed3587b892319d2e6b25d68c03930c95cf6d74210e3b368a638ca9f837a2315' + +default['elasticsearch']['checksums']['6.7.1']['debian'] = '807223a278ffd29630f01a1c21ff268aa5b51ff36c66a2c56a7a8e275d102831' +default['elasticsearch']['checksums']['6.7.1']['rhel'] = '88b6f4de17ea943ac996648783cd07471ee37b894d17bf17939d9a0cedb30237' +default['elasticsearch']['checksums']['6.7.1']['tarball'] = '7be3f94882130c769e5a6b95dbccdc3cab9f101cbc68edfa661f7188c78f06e2' + +default['elasticsearch']['checksums']['6.7.2']['debian'] = '8ad69655c22eabe94295ffb23434ae26ef4d839555ee9cb65261a6fe48e0dc12' +default['elasticsearch']['checksums']['6.7.2']['rhel'] = 'aabd389a4098fb99113907ae9665d454291dd32641cd33056f26ec713d017972' +default['elasticsearch']['checksums']['6.7.2']['tarball'] = 'd0ed638c825914d3c5fd8b34f69b5bcf9cfa5cf85af25145ea7a910ea8f708a9' + +default['elasticsearch']['checksums']['6.8.0']['debian'] = 'cb5556c6b75ef2e2d3b0399625aaabae0bbd84229ffc08e8475fdbec1e1b66c0' +default['elasticsearch']['checksums']['6.8.0']['rhel'] = '702bde8def4d51788b49477225d345b693e34ede35c1fbf6fd1421860d3451f5' +default['elasticsearch']['checksums']['6.8.0']['tarball'] = '92c67cf48a145a60579857f190ed03a56e3ae42e599d0c84fed0747af866fffd' + +default['elasticsearch']['checksums']['6.8.1']['debian'] = 'e7711bfb68e82f4538067da03634ef1937d71a1ab448d7d4eb3f20bc1c4854d1' +default['elasticsearch']['checksums']['6.8.1']['rhel'] = '4663f759cade5d1613842f86af3f78d064ce3c8e81de9615a353cc2eb413aed0' +default['elasticsearch']['checksums']['6.8.1']['tarball'] = 'ad33d463884acde2d8682cb46927f03603ea66133b84c12f53dc9edbc02447e3' + +default['elasticsearch']['checksums']['6.8.2']['debian'] = '9e6b591bef75d042abb4888d914e37aab19bf8afb6eda9efaa6b270ac7edd151' +default['elasticsearch']['checksums']['6.8.2']['rhel'] = '3561e6c1bbac324448928e752b9d6c0d2a413c569993625f6dd255b343f61a6c' +default['elasticsearch']['checksums']['6.8.2']['tarball'] = '2dc3107475659dfd21afa74612a43d5ccbcf4942ab679e8e4e77167cafe27c94' + +default['elasticsearch']['checksums']['7.0.0']['debian'] = '491d36af33bc896f8c44c46e1ed550e304220c9eedee991091864f5f3434e2f4' +default['elasticsearch']['checksums']['7.0.0']['rhel'] = '99ed1d22c128189ccb07c99babe7f437180e42c94af15782acf4b80d2520abc4' +default['elasticsearch']['checksums']['7.0.0']['tarball'] = '68deee5e9c961ad48cc83859970ac7a79029fe5f5e6de7e58ea0f7c7713f25ba' + +default['elasticsearch']['checksums']['7.0.1']['debian'] = 'b84419e213539f5af2a0b3d73ebc11cf2da7e7061e6308e83333a9282bf920e4' +default['elasticsearch']['checksums']['7.0.1']['rhel'] = '52aba98ea0165492fa899ed8487af5cab10f5e452611995ebac31b5f44facd50' +default['elasticsearch']['checksums']['7.0.1']['tarball'] = '33866cbc61383d1ead01622ff54cadacec0b9fe81224af9b77104be614a56eca' + +default['elasticsearch']['checksums']['7.1.0']['debian'] = '9cdb867ebfda5550590e2dc98e37020d9aa6bfd508b1b8be9f11f5683c807349' +default['elasticsearch']['checksums']['7.1.0']['rhel'] = '3facf261e9cbb88c8d792d2ff97e2aeb79c44d2df5fd83591ce4f2d5378eb7a4' +default['elasticsearch']['checksums']['7.1.0']['tarball'] = '91b4bd3722086e83dbe5ee7abf179de19b0cf9dc8a639438bde2721f184cc42e' + +default['elasticsearch']['checksums']['7.1.1']['debian'] = '2ef15cb7e37d32b93c51ad537959831bd72cac2627f255d22cc574cec5de6aef' +default['elasticsearch']['checksums']['7.1.1']['rhel'] = '7950c7d97407d8948ca164d81866b389fe734e3ec775452a3e407e49cbd0d5ed' +default['elasticsearch']['checksums']['7.1.1']['tarball'] = 'd8cd7df1232d931b9ff8fda1e960d94b03db21b7f33162d6865ebcbe69a45f95' + +default['elasticsearch']['checksums']['7.2.0']['debian'] = '1ff7b88c4bc38438a67719df499b17d4f7082a77eda89f39016f83414554ea95' +default['elasticsearch']['checksums']['7.2.0']['rhel'] = 'a854decb443631a0031a9492c1d5acbed00222381cb63cba68ae6d5deee3994c' +default['elasticsearch']['checksums']['7.2.0']['tarball'] = '24a2c31ff3ef34624752f266c39e40e84b103ab529dae7e062f1cb4b614cd1c5' + +default['elasticsearch']['checksums']['7.2.1']['debian'] = '41f507b83fc49a3da5109afd18cc626ec5458acf567f00a80ac3f1c34b6d4b7f' +default['elasticsearch']['checksums']['7.2.1']['rhel'] = '96fdac0a8e6c74182d920b39e3f4830b722731a646126222c189e12a95302e6e' +default['elasticsearch']['checksums']['7.2.1']['tarball'] = 'd5d660895a39755ad6af16ec32cff5e2b645d5faf7150c69acc0fe013c604ae7' + +default['elasticsearch']['checksums']['7.3.0']['debian'] = '72ae24cf0f5d97a307f35d116a41e1165e80f58f08b0ca4e6de3ec5228f06f9c' +default['elasticsearch']['checksums']['7.3.0']['rhel'] = 'f49dc809cf48369b70546f13dfb28b43e1a07387b681ca786c794762d52847ca' +default['elasticsearch']['checksums']['7.3.0']['tarball'] = '6cddb4d9a3c5e730f8e35e2155937c069d057129808ea135d31f0ed5f7f2ea22' diff --git a/cookbooks/elasticsearch/libraries/helpers.rb b/cookbooks/elasticsearch/libraries/helpers.rb new file mode 100644 index 0000000..b0af256 --- /dev/null +++ b/cookbooks/elasticsearch/libraries/helpers.rb @@ -0,0 +1,156 @@ +module ElasticsearchCookbook + # Helper methods included by various providers and passed to the template engine + module Helpers + def find_es_resource(run_context, resource_type, resource) + resource_name = resource.name + instance_name = resource.instance_name + + # if we are truly given a specific name to find + name_match = find_exact_resource(run_context, resource_type, resource_name) rescue nil + return name_match if name_match + + # first try by instance name attribute + name_instance = find_instance_name_resource(run_context, resource_type, instance_name) rescue nil + return name_instance if name_instance + + # otherwise try the defaults + name_default = find_exact_resource(run_context, resource_type, 'default') rescue nil + name_elasticsearch = find_exact_resource(run_context, resource_type, 'elasticsearch') rescue nil + + # if we found exactly one default name that matched + return name_default if name_default && !name_elasticsearch + return name_elasticsearch if name_elasticsearch && !name_default + + raise "Could not find exactly one #{resource_type} resource, and no specific resource or instance name was given" + end + + # find exactly the resource name and type, but raise if there's multiple matches + # see https://github.com/chef/chef/blob/master/lib/chef/resource_collection/resource_set.rb#L80 + def find_exact_resource(run_context, resource_type, resource_name) + rc = run_context.resource_collection + result = rc.find(resource_type => resource_name) + + if result && result.is_a?(Array) + str = '' + str << "more than one #{resource_type} was found, " + str << 'you must specify a precise resource name' + raise str + end + + result + end + + def find_instance_name_resource(run_context, resource_type, instance_name) + results = [] + rc = run_context.resource_collection + + rc.each do |r| + next unless r.resource_name == resource_type && r.instance_name == instance_name + results << r + end + + if !results.empty? && results.length > 1 + str = '' + str << "more than one #{resource_type} was found, " + str << 'you must specify a precise instance name' + raise str + elsif !results.empty? + return results.first + end + + nil # falsey + end + + def determine_download_url(new_resource, node) + platform_family = node['platform_family'] + + version_key = 'download_urls' + if Gem::Version.new(new_resource.version) >= Gem::Version.new('7.0.0') + version_key = 'download_urls_v7' + end + + url_string = nil + if new_resource.download_url + url_string = new_resource.download_url + elsif new_resource.type == 'tarball' + url_string = node['elasticsearch'][version_key]['tarball'] + elsif new_resource.type == 'package' && node['elasticsearch']['download_urls'][platform_family] + url_string = node['elasticsearch'][version_key][platform_family] + end + + if url_string && new_resource.version + return format(url_string, new_resource.version) + elsif url_string + return url_string + end + end + + def determine_download_checksum(new_resource, node) + platform_family = node['platform_family'] + + # for the sake of finding correct attribute data, use rhel for amazon too + # See https://github.com/elastic/cookbook-elasticsearch/issues/609 + platform_family = 'rhel' if platform_family == 'amazon' + + install_type = new_resource.type + version = new_resource.version + + if new_resource.download_checksum + new_resource.download_checksum + elsif install_type == 'tarball' + node && version && + node['elasticsearch'] && + node['elasticsearch']['checksums'] && + node['elasticsearch']['checksums'][version] && + node['elasticsearch']['checksums'][version]['tarball'] + elsif install_type == 'package' && node['elasticsearch']['checksums'][version] && node['elasticsearch']['checksums'][version][platform_family] + node && version && platform_family && + node['elasticsearch'] && + node['elasticsearch']['checksums'] && + node['elasticsearch']['checksums'][version] && + node['elasticsearch']['checksums'][version][platform_family] + end + end + + # proxy helper for chef sets JVM 8 proxy options + def get_java_proxy_arguments(enabled = true) + return '' unless enabled + require 'uri' + output = '' + + if Chef::Config[:http_proxy] && !Chef::Config[:http_proxy].empty? + parsed_uri = URI(Chef::Config[:http_proxy]) + output += "-Dhttp.proxyHost=#{parsed_uri.host} -Dhttp.proxyPort=#{parsed_uri.port} " + end + + if Chef::Config[:https_proxy] && !Chef::Config[:https_proxy].empty? + parsed_uri = URI(Chef::Config[:https_proxy]) + output += "-Dhttps.proxyHost=#{parsed_uri.host} -Dhttps.proxyPort=#{parsed_uri.port} " + end + + output + rescue + '' + end + end + + class HashAndMashBlender + attr_accessor :target + def initialize(hash_or_mash_or_whatever) + self.target = hash_or_mash_or_whatever + end + + def to_hash + target.each_with_object({}) do |(k, v), hsh| + hsh[k] = + if v.respond_to?(:to_hash) + self.class.new(v).to_hash + elsif v.respond_to?(:to_a) + v.to_a + else + v + end + end + end + end +end diff --git a/cookbooks/elasticsearch/libraries/matchers.rb b/cookbooks/elasticsearch/libraries/matchers.rb new file mode 100644 index 0000000..51e532f --- /dev/null +++ b/cookbooks/elasticsearch/libraries/matchers.rb @@ -0,0 +1,73 @@ +# ChefSpec is a tool to unit test cookbooks in conjunction with rspec +# Learn more on the README or at https://github.com/sethvargo/chefspec. +if defined?(ChefSpec) + ChefSpec.define_matcher(:elasticsearch_configure) + ChefSpec.define_matcher(:elasticsearch_install) + ChefSpec.define_matcher(:elasticsearch_plugin) + ChefSpec.define_matcher(:elasticsearch_service) + ChefSpec.define_matcher(:elasticsearch_user) + + def create_elasticsearch_user(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:elasticsearch_user, :create, resource_name) + end + + def remove_elasticsearch_user(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:elasticsearch_user, :remove, resource_name) + end + + def install_elasticsearch(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:elasticsearch_install, :install, resource_name) + end + + def remove_elasticsearch(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:elasticsearch_install, :remove, resource_name) + end + + def manage_elasticsearch_configure(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:elasticsearch_configure, :manage, resource_name) + end + + def remove_elasticsearch_configure(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:elasticsearch_configure, :remove, resource_name) + end + + def configure_elasticsearch_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:elasticsearch_service, :configure, resource_name) + end + + def remove_elasticsearch_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:elasticsearch_service, :remove, resource_name) + end + + def enable_elasticsearch_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:elasticsearch_service, :enable, resource_name) + end + + def disable_elasticsearch_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:elasticsearch_service, :disable, resource_name) + end + + def start_elasticsearch_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:elasticsearch_service, :start, resource_name) + end + + def stop_elasticsearch_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:elasticsearch_service, :stop, resource_name) + end + + def restart_elasticsearch_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:elasticsearch_service, :restart, resource_name) + end + + def status_elasticsearch_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:elasticsearch_service, :status, resource_name) + end + + def install_elasticsearch_plugin(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:elasticsearch_plugin, :install, resource_name) + end + + def remove_elasticsearch_plugin(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:elasticsearch_plugin, :remove, resource_name) + end +end diff --git a/cookbooks/elasticsearch/libraries/provider_configure.rb b/cookbooks/elasticsearch/libraries/provider_configure.rb new file mode 100644 index 0000000..1abfa3d --- /dev/null +++ b/cookbooks/elasticsearch/libraries/provider_configure.rb @@ -0,0 +1,164 @@ +# Chef Provider for configuring an elasticsearch instance +class ElasticsearchCookbook::ConfigureProvider < Chef::Provider::LWRPBase + include ElasticsearchCookbook::Helpers + + provides :elasticsearch_configure + + def whyrun_supported? + true # we only use core Chef resources that also support whyrun + end + + def action_manage + # lookup existing ES resources + es_user = find_es_resource(Chef.run_context, :elasticsearch_user, new_resource) + es_svc = find_es_resource(Chef.run_context, :elasticsearch_service, new_resource) + es_install = find_es_resource(Chef.run_context, :elasticsearch_install, new_resource) + + default_configuration = new_resource.default_configuration.dup + # if a subdir parameter is missing but dir is set, infer the subdir name + # then go and be sure it's also set in the YML hash if it wasn't given there + if new_resource.path_data && default_configuration['path.data'].nil? + default_configuration['path.data'] = new_resource.path_data + end + + if new_resource.path_logs && default_configuration['path.logs'].nil? + default_configuration['path.logs'] = new_resource.path_logs + end + + # calculation for memory allocation; 50% or 31g, whatever is smaller + unless new_resource.allocated_memory + half = ((node['memory']['total'].to_i * 0.5).floor / 1024) + malloc_str = (half > 30_500 ? '30500m' : "#{half}m") + new_resource.allocated_memory malloc_str + end + + # Create ES directories + # + [new_resource.path_conf, "#{new_resource.path_conf}/scripts"].each do |path| + d = directory path do + owner es_user.username + group es_user.groupname + mode '0750' + recursive true + action :nothing + end + d.run_action(:create) + new_resource.updated_by_last_action(true) if d.updated_by_last_action? + end + + # Create data path directories + # + data_paths = new_resource.path_data.is_a?(Array) ? new_resource.path_data : new_resource.path_data.split(',') + data_paths = data_paths << new_resource.path_logs + + data_paths.each do |path| + d = directory path.strip do + owner es_user.username + group es_user.groupname + mode '0755' + recursive true + action :nothing + end + d.run_action(:create) + new_resource.updated_by_last_action(true) if d.updated_by_last_action? + end + + # Create elasticsearch shell variables file + # + # Valid values in /etc/sysconfig/elasticsearch or /etc/default/elasticsearch + # ES_HOME JAVA_HOME ES_PATH_CONF DATA_DIR LOG_DIR PID_DIR ES_JAVA_OPTS + # RESTART_ON_UPGRADE ES_USER ES_GROUP ES_STARTUP_SLEEP_TIME MAX_OPEN_FILES + # MAX_LOCKED_MEMORY MAX_MAP_COUNT + # + # We provide these values as resource attributes/parameters directly + + params = {} + params[:ES_HOME] = new_resource.path_home + params[:JAVA_HOME] = new_resource.java_home + params[:ES_PATH_CONF] = new_resource.path_conf + params[:DATA_DIR] = new_resource.path_data + params[:LOG_DIR] = new_resource.path_logs + params[:PID_DIR] = new_resource.path_pid + params[:RESTART_ON_UPGRADE] = new_resource.restart_on_upgrade + params[:ES_USER] = es_user.username if es_install.type == 'tarball' + params[:ES_GROUP] = es_user.groupname if es_install.type == 'tarball' + params[:ES_STARTUP_SLEEP_TIME] = new_resource.startup_sleep_seconds.to_s + params[:MAX_OPEN_FILES] = new_resource.nofile_limit + params[:MAX_LOCKED_MEMORY] = new_resource.memlock_limit + params[:MAX_MAP_COUNT] = new_resource.max_map_count + + default_config_name = es_svc.service_name || es_svc.instance_name || new_resource.instance_name || 'elasticsearch' + + shell_template = template "elasticsearch.in.sh-#{default_config_name}" do + path %w[rhel amazon].include?(node['platform_family']) ? "/etc/sysconfig/#{default_config_name}" : "/etc/default/#{default_config_name}" + source new_resource.template_elasticsearch_env + cookbook new_resource.cookbook_elasticsearch_env + mode '0644' + variables(params: params) + action :nothing + end + shell_template.run_action(:create) + new_resource.updated_by_last_action(true) if shell_template.updated_by_last_action? + + # Create jvm.options file + # + jvm_options_template = template "jvm_options-#{default_config_name}" do + path "#{new_resource.path_conf}/jvm.options" + source new_resource.template_jvm_options + cookbook new_resource.cookbook_jvm_options + owner es_user.username + group es_user.groupname + mode '0644' + variables(jvm_options: [ + "-Xms#{new_resource.allocated_memory}", + "-Xmx#{new_resource.allocated_memory}", + new_resource.jvm_options, + ].flatten.join("\n")) + action :nothing + end + jvm_options_template.run_action(:create) + new_resource.updated_by_last_action(true) if jvm_options_template.updated_by_last_action? + + # Create ES logging file + # + logging_template = template "log4j2_properties-#{default_config_name}" do + path "#{new_resource.path_conf}/log4j2.properties" + source new_resource.template_log4j2_properties + cookbook new_resource.cookbook_log4j2_properties + owner es_user.username + group es_user.groupname + mode '0640' + variables(logging: new_resource.logging) + action :nothing + end + logging_template.run_action(:create) + new_resource.updated_by_last_action(true) if logging_template.updated_by_last_action? + + # Create ES elasticsearch.yml file + # + merged_configuration = default_configuration.merge(new_resource.configuration.dup) + + # warn if someone is using symbols. we don't support. + found_symbols = merged_configuration.keys.select { |s| s.is_a?(Symbol) } + unless found_symbols.empty? + Chef::Log.warn("Please change the following to strings in order to work with this Elasticsearch cookbook: #{found_symbols.join(',')}") + end + + # workaround for https://github.com/elastic/cookbook-elasticsearch/issues/590 + config_vars = ElasticsearchCookbook::HashAndMashBlender.new(merged_configuration).to_hash + + yml_template = template "elasticsearch.yml-#{default_config_name}" do + path "#{new_resource.path_conf}/elasticsearch.yml" + source new_resource.template_elasticsearch_yml + cookbook new_resource.cookbook_elasticsearch_yml + owner es_user.username + group es_user.groupname + mode '0640' + helpers(ElasticsearchCookbook::Helpers) + variables(config: config_vars) + action :nothing + end + yml_template.run_action(:create) + new_resource.updated_by_last_action(true) if yml_template.updated_by_last_action? + end +end diff --git a/cookbooks/elasticsearch/libraries/provider_install.rb b/cookbooks/elasticsearch/libraries/provider_install.rb new file mode 100644 index 0000000..bd2e2ac --- /dev/null +++ b/cookbooks/elasticsearch/libraries/provider_install.rb @@ -0,0 +1,238 @@ +# Chef Provider for installing or removing Elasticsearch from package or tarball +# downloaded from elasticsearch.org and installed by package manager or ark resource +class ElasticsearchCookbook::InstallProvider < Chef::Provider::LWRPBase + include ElasticsearchCookbook::Helpers + include Chef::DSL::IncludeRecipe + provides :elasticsearch_install + + def whyrun_supported? + true # we only use core Chef resources that also support whyrun + end + + def action_install + if new_resource.type == 'tarball' + install_tarball_wrapper_action + elsif new_resource.type == 'package' + install_package_wrapper_action + elsif new_resource.type == 'repository' + install_repo_wrapper_action + else + raise "#{install_type} is not a valid install type" + end + end + + def action_remove + if new_resource.type == 'tarball' + remove_tarball_wrapper_action + elsif new_resource.type == 'package' + remove_package_wrapper_action + elsif new_resource.type == 'repository' + remove_repo_wrapper_action + else + raise "#{install_type} is not a valid install type" + end + end + + protected + + def install_repo_wrapper_action + es_user = find_es_resource(Chef.run_context, :elasticsearch_user, new_resource) + unless es_user && es_user.username == 'elasticsearch' && es_user.groupname == 'elasticsearch' + raise 'Custom usernames/group names is not supported in Elasticsearch 6+ repository installation' + end + + if new_resource.enable_repository_actions + if node['platform_family'] == 'debian' + apt_r = apt_repo_resource + apt_r.run_action(:add) + new_resource.updated_by_last_action(true) if apt_r.updated_by_last_action? + else + yr_r = yum_repo_resource + yr_r.run_action(:create) + new_resource.updated_by_last_action(true) if yr_r.updated_by_last_action? + end + end + + if !new_resource.version.nil? && %w[rhel amazon].include?(node['platform_family']) && !new_resource.version.include?('-') + # NB: yum repo packages are broken in Chef if you don't specify a release + # https://github.com/chef/chef/issues/4103 + new_resource.version = "#{new_resource.version}-1" + end + + pkg_r = package 'elasticsearch' do + options new_resource.package_options + version new_resource.version + action :nothing + end + + pkg_r.run_action(:install) + new_resource.updated_by_last_action(true) if pkg_r.updated_by_last_action? + end + + def remove_repo_wrapper_action + if new_resource.enable_repository_actions + if node['platform_family'] == 'debian' + apt_r = apt_repo_resource + apt_r.run_action(:remove) + new_resource.updated_by_last_action(true) if apt_r.updated_by_last_action? + else + yr_r = yum_repo_resource + yr_r.run_action(:delete) + new_resource.updated_by_last_action(true) if yr_r.updated_by_last_action? + end + end + + pkg_r = package 'elasticsearch' do + options new_resource.package_options + version new_resource.version + action :nothing + end + pkg_r.run_action(:remove) + new_resource.updated_by_last_action(true) if pkg_r.updated_by_last_action? + end + + def install_package_wrapper_action + es_user = find_es_resource(Chef.run_context, :elasticsearch_user, new_resource) + unless es_user && es_user.username == 'elasticsearch' && es_user.groupname == 'elasticsearch' + raise 'Custom usernames/group names is not supported in Elasticsearch 6+ package installation' + end + + found_download_url = determine_download_url(new_resource, node) + unless found_download_url + raise 'Could not determine download url for package on this platform' + end + + filename = found_download_url.split('/').last + checksum = determine_download_checksum(new_resource, node) + package_options = new_resource.package_options + + unless checksum + Chef::Log.warn("No checksum was provided for #{found_download_url}, this may download a new package on every chef run!") + end + + remote_file_r = remote_file "#{Chef::Config[:file_cache_path]}/#{filename}" do + source found_download_url + checksum checksum + mode '0644' + action :nothing + end + remote_file_r.run_action(:create) + new_resource.updated_by_last_action(true) if remote_file_r.updated_by_last_action? + + pkg_r = if node['platform_family'] == 'debian' + dpkg_package "#{Chef::Config[:file_cache_path]}/#{filename}" do + options package_options + action :nothing + end + else + package "#{Chef::Config[:file_cache_path]}/#{filename}" do + options package_options + action :nothing + end + end + + pkg_r.run_action(:install) + new_resource.updated_by_last_action(true) if pkg_r.updated_by_last_action? + end + + def remove_package_wrapper_action + package_url = determine_download_url(new_resource, node) + filename = package_url.split('/').last + + pkg_r = if node['platform_family'] == 'debian' + dpkg_package "#{Chef::Config[:file_cache_path]}/#{filename}" do + action :nothing + end + else + package "#{Chef::Config[:file_cache_path]}/#{filename}" do + action :nothing + end + end + + pkg_r.run_action(:remove) + new_resource.updated_by_last_action(true) if pkg_r.updated_by_last_action? + end + + def install_tarball_wrapper_action + include_recipe 'ark' + + es_user = find_es_resource(Chef.run_context, :elasticsearch_user, new_resource) + found_download_url = determine_download_url(new_resource, node) + unless found_download_url + raise 'Could not determine download url for tarball on this platform' + end + + ark_r = ark 'elasticsearch' do + url found_download_url + owner es_user.username + group es_user.groupname + version new_resource.version + has_binaries ['bin/elasticsearch', 'bin/elasticsearch-plugin'] + checksum determine_download_checksum(new_resource, node) + prefix_root new_resource.dir + prefix_home new_resource.dir + + not_if do + link = "#{new_resource.dir}/elasticsearch" + target = "#{new_resource.dir}/elasticsearch-#{new_resource.version}" + binary = "#{target}/bin/elasticsearch" + + ::File.directory?(link) && ::File.symlink?(link) && ::File.readlink(link) == target && ::File.exist?(binary) + end + action :nothing + end + ark_r.run_action(:install) + new_resource.updated_by_last_action(true) if ark_r.updated_by_last_action? + + # destroy the sample config directory for tarball installs, or it will + # take precedence beyond the default stuff in /etc/elasticsearch and within + # /etc/sysconfig or /etc/default + sample_r = directory "#{new_resource.dir}/elasticsearch/config" do + action :nothing + recursive true + end + sample_r.run_action(:delete) + new_resource.updated_by_last_action(true) if sample_r.updated_by_last_action? + end + + def remove_tarball_wrapper_action + # remove the symlink to this version + link_r = link "#{new_resource.dir}/elasticsearch" do + only_if do + link = "#{new_resource.dir}/elasticsearch" + target = "#{new_resource.dir}/elasticsearch-#{new_resource.version}" + + ::File.directory?(link) && ::File.symlink?(link) && ::File.readlink(link) == target + end + action :nothing + end + link_r.run_action(:delete) + new_resource.updated_by_last_action(true) if link_r.updated_by_last_action? + + # remove the specific version + d_r = directory "#{new_resource.dir}/elasticsearch-#{new_resource.version}" do + recursive true + action :nothing + end + d_r.run_action(:delete) + new_resource.updated_by_last_action(true) if d_r.updated_by_last_action? + end + + def yum_repo_resource + yum_repository "elastic-#{new_resource.version.to_i}.x" do + baseurl "https://artifacts.elastic.co/packages/#{new_resource.version.to_i}.x/yum" + gpgkey 'https://artifacts.elastic.co/GPG-KEY-elasticsearch' + action :nothing # :add, remove + end + end + + def apt_repo_resource + apt_repository "elastic-#{new_resource.version.to_i}.x" do + uri "https://artifacts.elastic.co/packages/#{new_resource.version.to_i}.x/apt" + key 'https://artifacts.elastic.co/GPG-KEY-elasticsearch' + components ['main'] + distribution 'stable' + action :nothing # :create, :delete + end + end +end diff --git a/cookbooks/elasticsearch/libraries/provider_plugin.rb b/cookbooks/elasticsearch/libraries/provider_plugin.rb new file mode 100644 index 0000000..4f7e32e --- /dev/null +++ b/cookbooks/elasticsearch/libraries/provider_plugin.rb @@ -0,0 +1,108 @@ +# Chef Provider for installing an elasticsearch plugin +class ElasticsearchCookbook::PluginProvider < Chef::Provider::LWRPBase + include ElasticsearchCookbook::Helpers + include Chef::Mixin::ShellOut + + provides :elasticsearch_plugin + + def whyrun_supported? + true # we only use core Chef resources that also support whyrun, or guard + end + + def action_install + return if plugin_exists(new_resource.plugin_name) + + # since install can take a URL argument instead + url_or_name = new_resource.url || new_resource.plugin_name + manage_plugin("install #{url_or_name}") + end # action + + def action_remove + return unless plugin_exists(new_resource.plugin_name) + + manage_plugin("remove #{new_resource.plugin_name}") + end # action + + def manage_plugin(arguments) + es_user = find_es_resource(Chef.run_context, :elasticsearch_user, new_resource) + es_install = find_es_resource(Chef.run_context, :elasticsearch_install, new_resource) + es_conf = find_es_resource(Chef.run_context, :elasticsearch_configure, new_resource) + + assert_state_is_valid(es_user, es_install, es_conf) unless whyrun_mode? + + # shell_out! automatically raises on error, logs command output + # required for package installs that show up with parent dir owned by root + plugin_dir_exists = ::File.exist?(es_conf.path_plugins) + unless plugin_dir_exists + cmd_str = "mkdir -p #{es_conf.path_plugins}" + if whyrun_mode? + Chef::Log.info("Would run command: #{cmd_str}") + else + shell_out_as_user!(cmd_str, Chef.run_context) + new_resource.updated_by_last_action(true) + end + end + + unless plugin_exists(new_resource.plugin_name) + cmd_str = "#{es_conf.path_bin}/elasticsearch-plugin #{arguments.chomp(' ')} #{new_resource.options}".chomp(' ') + if whyrun_mode? + Chef::Log.info("Would run command: #{cmd_str}") + else + command_array = cmd_str.split(' ') + shell_out_as_user!(command_array, Chef.run_context) + new_resource.updated_by_last_action(true) + end + end + end + + def plugin_exists(name) + es_conf = find_es_resource(Chef.run_context, :elasticsearch_configure, new_resource) + path = es_conf.path_plugins + + Dir.entries(path).any? do |plugin| + next if plugin =~ /^\./ + name == plugin + end + rescue + false + end + + def assert_state_is_valid(_es_user, _es_install, es_conf) + unless es_conf.path_plugins # we do not check existence (may not exist if no plugins installed) + raise "Could not determine the plugin directory (#{es_conf.path_plugins}). Please check elasticsearch_configure[#{es_conf.name}]." + end + + unless es_conf.path_bin && ::File.exist?(es_conf.path_bin) + raise "Could not determine the binary directory (#{es_conf.path_bin}). Please check elasticsearch_configure[#{es_conf.name}]." + end + + true + end + + def shell_out_as_user!(command, run_ctx) + es_install = find_es_resource(run_ctx, :elasticsearch_install, new_resource) + es_conf = find_es_resource(run_ctx, :elasticsearch_configure, new_resource) + es_svc = find_es_resource(run_ctx, :elasticsearch_service, new_resource) + + # we need to figure out the env file path to set environment for plugins + default_config_name = es_svc.service_name || es_svc.instance_name || es_conf.instance_name || 'elasticsearch' + include_file_resource = find_exact_resource(run_ctx, :template, "elasticsearch.in.sh-#{default_config_name}") + env = { 'ES_INCLUDE' => include_file_resource.path } + + # Add HTTP Proxy vars unless explicitly told not to + if new_resource.chef_proxy + env['ES_JAVA_OPTS'] = "#{ENV['ES_JAVA_OPTS']} #{get_java_proxy_arguments}" + end + + # See this link for an explanation: + # https://www.elastic.co/guide/en/elasticsearch/plugins/2.1/plugin-management.html + if es_install.type == 'package' || es_install.type == 'repository' + # package installations should install plugins as root + shell_out!(command, :env => env, :timeout => 1200) + else + # non-package installations should install plugins as the ES user + es_user = find_es_resource(run_ctx, :elasticsearch_user, new_resource) + shell_out!(command, user: es_user.username, group: es_user.groupname, :env => env, :timeout => 1200) + end + end +end # provider diff --git a/cookbooks/elasticsearch/libraries/provider_service.rb b/cookbooks/elasticsearch/libraries/provider_service.rb new file mode 100644 index 0000000..e834d90 --- /dev/null +++ b/cookbooks/elasticsearch/libraries/provider_service.rb @@ -0,0 +1,140 @@ +# Chef Provider for configuring an elasticsearch service in the init system +class ElasticsearchCookbook::ServiceProvider < Chef::Provider::LWRPBase + provides :elasticsearch_service + include ElasticsearchCookbook::Helpers + + def whyrun_supported? + true # we only use core Chef resources that also support whyrun + end + + def action_remove + raise "#{new_resource} remove not currently implemented" + end + + def action_configure + es_user = find_es_resource(Chef.run_context, :elasticsearch_user, new_resource) + es_install = find_es_resource(Chef.run_context, :elasticsearch_install, new_resource) + es_conf = find_es_resource(Chef.run_context, :elasticsearch_configure, new_resource) + default_config_name = new_resource.service_name || new_resource.instance_name || es_conf.instance_name || 'elasticsearch' + + d_r = directory "#{es_conf.path_pid}-#{default_config_name}" do + path es_conf.path_pid + owner es_user.username + group es_user.groupname + mode '0755' + recursive true + action :nothing + end + d_r.run_action(:create) + new_resource.updated_by_last_action(true) if d_r.updated_by_last_action? + + # Create service for init and systemd + # + if new_resource.init_source + init_r = template "/etc/init.d/#{new_resource.service_name}" do + source new_resource.init_source + cookbook new_resource.init_cookbook + owner 'root' + mode '0755' + variables( + # we need to include something about #{progname} fixed in here. + program_name: new_resource.service_name, + install_type: es_install.type + ) + only_if { ::File.exist?('/etc/init.d') } + action :nothing + end + init_r.run_action(:create) + new_resource.updated_by_last_action(true) if init_r.updated_by_last_action? + end + + if new_resource.systemd_source + systemd_parent_r = directory "/usr/lib/systemd/system-#{default_config_name}" do + path '/usr/lib/systemd/system' + action :nothing + only_if { ::File.exist?('/usr/lib/systemd') } + end + systemd_parent_r.run_action(:create) + new_resource.updated_by_last_action(true) if systemd_parent_r.updated_by_last_action? + + default_conf_dir = %w[rhel amazon].include?(node['platform_family']) ? '/etc/sysconfig' : '/etc/default' + systemd_r = template "/usr/lib/systemd/system/#{new_resource.service_name}.service" do + source new_resource.systemd_source + cookbook new_resource.systemd_cookbook + owner 'root' + mode '0644' + variables( + # we need to include something about #{progname} fixed in here. + program_name: new_resource.service_name, + default_dir: default_conf_dir, + path_home: es_conf.path_home, + es_user: es_user.username, + es_group: es_user.groupname, + nofile_limit: es_conf.nofile_limit, + install_type: es_install.type + ) + only_if 'which systemctl' + action :nothing + end + systemd_r.run_action(:create) + # special case here -- must reload unit files if we modified one + if systemd_r.updated_by_last_action? + new_resource.updated_by_last_action(systemd_r.updated_by_last_action?) + + reload_r = execute "reload-systemd-#{new_resource.service_name}" do + command 'systemctl daemon-reload' + action :nothing + only_if 'which systemctl' + end + reload_r.run_action(:run) + end + end + + # flatten in an array here, in case the service_actions are a symbol vs. array + [new_resource.service_actions].flatten.each do |act| + passthrough_action(act) + end + end + + # Passthrough actions to service[service_name] + # + def action_enable + passthrough_action(:enable) + end + + def action_disable + passthrough_action(:disable) + end + + def action_start + passthrough_action(:start) + end + + def action_stop + passthrough_action(:stop) + end + + def action_restart + passthrough_action(:restart) + end + + def action_status + passthrough_action(:status) + end + + def passthrough_action(action) + svc_r = lookup_service_resource + svc_r.run_action(action) + new_resource.updated_by_last_action(true) if svc_r.updated_by_last_action? + end + + def lookup_service_resource + rc = Chef.run_context.resource_collection + rc.find("service[#{new_resource.service_name}]") + rescue + service new_resource.service_name do + supports status: true, restart: true + action :nothing + end + end +end diff --git a/cookbooks/elasticsearch/libraries/provider_user.rb b/cookbooks/elasticsearch/libraries/provider_user.rb new file mode 100644 index 0000000..59d4087 --- /dev/null +++ b/cookbooks/elasticsearch/libraries/provider_user.rb @@ -0,0 +1,48 @@ +# Chef Provider for creating a user and group for Elasticsearch +class ElasticsearchCookbook::UserProvider < Chef::Provider::LWRPBase + include ElasticsearchCookbook::Helpers + + provides :elasticsearch_user + + def whyrun_supported? + true # we only use core Chef resources that also support whyrun + end + + def action_create + group_r = group new_resource.groupname do + gid new_resource.gid + action :nothing + system true + end + group_r.run_action(:create) + new_resource.updated_by_last_action(true) if group_r.updated_by_last_action? + + user_r = user new_resource.username do + comment new_resource.comment + shell new_resource.shell + uid new_resource.uid + gid new_resource.groupname + + manage_home false + action :nothing + system true + end + user_r.run_action(:create) + new_resource.updated_by_last_action(true) if user_r.updated_by_last_action? + end + + def action_remove + # delete user before deleting the group + user_r = user new_resource.username do + action :nothing + end + user_r.run_action(:remove) + new_resource.updated_by_last_action(true) if user_r.updated_by_last_action? + + group_r = group new_resource.groupname do + action :nothing + end + group_r.run_action(:remove) + new_resource.updated_by_last_action(true) if group_r.updated_by_last_action? + end +end diff --git a/cookbooks/elasticsearch/libraries/resource_configure.rb b/cookbooks/elasticsearch/libraries/resource_configure.rb new file mode 100644 index 0000000..7062490 --- /dev/null +++ b/cookbooks/elasticsearch/libraries/resource_configure.rb @@ -0,0 +1,92 @@ +# Chef Resource for configuring an Elasticsearch node +class ElasticsearchCookbook::ConfigureResource < Chef::Resource::LWRPBase + resource_name :elasticsearch_configure + provides :elasticsearch_configure + + actions(:manage, :remove) + default_action :manage + + # this is what helps the various resources find each other + attribute(:instance_name, kind_of: String, default: nil) + + # if you override one of these, you should probably override them all + attribute(:path_home, kind_of: String, default: '/usr/share/elasticsearch') + attribute(:path_conf, kind_of: String, default: '/etc/elasticsearch') + attribute(:path_data, kind_of: String, default: '/var/lib/elasticsearch') + attribute(:path_logs, kind_of: String, default: '/var/log/elasticsearch') + attribute(:path_pid, kind_of: String, default: '/var/run/elasticsearch') + attribute(:path_plugins, kind_of: String, default: '/usr/share/elasticsearch/plugins') + attribute(:path_bin, kind_of: String, default: '/usr/share/elasticsearch/bin') + + attribute(:template_elasticsearch_env, kind_of: String, default: 'elasticsearch.in.sh.erb') + attribute(:cookbook_elasticsearch_env, kind_of: String, default: 'elasticsearch') + + attribute(:template_jvm_options, kind_of: String, default: 'jvm_options.erb') + attribute(:cookbook_jvm_options, kind_of: String, default: 'elasticsearch') + + attribute(:template_elasticsearch_yml, kind_of: String, default: 'elasticsearch.yml.erb') + attribute(:cookbook_elasticsearch_yml, kind_of: String, default: 'elasticsearch') + + attribute(:template_log4j2_properties, kind_of: String, default: 'log4j2.properties.erb') + attribute(:cookbook_log4j2_properties, kind_of: String, default: 'elasticsearch') + + attribute(:logging, kind_of: Hash, default: {}.freeze) + attribute(:java_home, kind_of: String, default: nil) + + # other settings in /etc/default or /etc/sysconfig + attribute(:memlock_limit, kind_of: String, default: 'unlimited') + attribute(:max_map_count, kind_of: String, default: '262144') + attribute(:nofile_limit, kind_of: String, default: '65536') + attribute(:startup_sleep_seconds, kind_of: [String, Integer], default: 5) + attribute(:restart_on_upgrade, kind_of: [TrueClass, FalseClass], default: false) + + # Calculations for this are done in the provider, as we can't do them in the + # resource definition. default is 50% of RAM or 31GB, which ever is smaller. + attribute(:allocated_memory, kind_of: String) + + attribute(:jvm_options, kind_of: Array, default: + %w( + -XX:+UseConcMarkSweepGC + -XX:CMSInitiatingOccupancyFraction=75 + -XX:+UseCMSInitiatingOccupancyOnly + -XX:+AlwaysPreTouch + -server + -Xss1m + -Djava.awt.headless=true + -Dfile.encoding=UTF-8 + -Djna.nosys=true + -XX:-OmitStackTraceInFastThrow + -Dio.netty.noUnsafe=true + -Dio.netty.noKeySetOptimization=true + -Dio.netty.recycler.maxCapacityPerThread=0 + -Dlog4j.shutdownHookEnabled=false + -Dlog4j2.disable.jmx=true + -XX:+HeapDumpOnOutOfMemoryError + ).freeze) + + # These are the default settings. Most of the time, you want to override + # the `configuration` attribute below. If you do override the defaults, you + # must supply ALL needed defaults, and don't use nil as a value in the hash. + attribute(:default_configuration, kind_of: Hash, default: { + # === NAMING + 'cluster.name' => 'elasticsearch', + # can't access node.name, so expect to have to set set this + 'node.name' => Chef::Config[:node_name], + + # if omitted or nil, these will be populated from attributes above + 'path.data' => nil, # see path_data above + 'path.logs' => nil, # see path_logs above + + # Refer to ES documentation on how to configure these to a + # specific node role/type instead of using the defaults + # + # 'node.data' => ?, + # 'node.master' => ?, + }.freeze) + + # These settings are merged with the `default_configuration` attribute, + # allowing you to override and set specific settings. Unless you intend to + # wipe out all default settings, your configuration items should go here. + # + attribute(:configuration, kind_of: Hash, default: {}.freeze) +end diff --git a/cookbooks/elasticsearch/libraries/resource_install.rb b/cookbooks/elasticsearch/libraries/resource_install.rb new file mode 100644 index 0000000..d20f839 --- /dev/null +++ b/cookbooks/elasticsearch/libraries/resource_install.rb @@ -0,0 +1,31 @@ +# Chef Resource for installing or removing Elasticsearch from package or source +class ElasticsearchCookbook::InstallResource < Chef::Resource::LWRPBase + resource_name :elasticsearch_install + provides :elasticsearch_install + + actions(:install, :remove) + default_action :install + + # this is what helps the various resources find each other + attribute(:instance_name, kind_of: String) + + # if this version parameter is not set by the caller, we look at + # `attributes/default.rb` for a default value to use, or we raise + attribute(:version, kind_of: String, default: '7.3.0') + + # we allow a string or symbol for this value + attribute(:type, kind_of: String, equal_to: %w(package tarball repository), default: 'repository') + + # these use `attributes/default.rb` for default values per platform and install type + attribute(:download_url, kind_of: String) + attribute(:download_checksum, kind_of: String) # sha256 + + # where to install? + attribute(:dir, kind_of: String, default: '/usr/share') + + # attributes used by the package-flavor provider + attribute(:package_options, kind_of: String) + + # attributes for the repository-option install + attribute(:enable_repository_actions, kind_of: [TrueClass, FalseClass], default: true) +end diff --git a/cookbooks/elasticsearch/libraries/resource_plugin.rb b/cookbooks/elasticsearch/libraries/resource_plugin.rb new file mode 100644 index 0000000..cf3e353 --- /dev/null +++ b/cookbooks/elasticsearch/libraries/resource_plugin.rb @@ -0,0 +1,19 @@ +# Chef Resource for installing an elasticsearch plugin +class ElasticsearchCookbook::PluginResource < Chef::Resource::LWRPBase + resource_name :elasticsearch_plugin + provides :elasticsearch_plugin + + include ElasticsearchCookbook::Helpers + + actions(:install, :remove) + default_action :install + + # if the name or url are different from the resource name + attribute(:plugin_name, kind_of: String, name_attribute: true) + attribute(:url, kind_of: String, default: nil) + attribute(:chef_proxy, kind_of: [TrueClass, FalseClass], default: false) + attribute(:options, kind_of: String, default: '') + + # this is what helps the various resources find each other + attribute(:instance_name, kind_of: String, default: nil) +end diff --git a/cookbooks/elasticsearch/libraries/resource_service.rb b/cookbooks/elasticsearch/libraries/resource_service.rb new file mode 100644 index 0000000..a73c529 --- /dev/null +++ b/cookbooks/elasticsearch/libraries/resource_service.rb @@ -0,0 +1,28 @@ +# Chef Resource for declaring a service for Elasticsearch +class ElasticsearchCookbook::ServiceResource < Chef::Resource::LWRPBase + resource_name :elasticsearch_service + provides :elasticsearch_service + + actions( + :configure, :remove, # our custom actions + :enable, :disable, :start, :stop, :restart, :status # passthrough to service resource + ) + default_action :configure + + # this is what helps the various resources find each other + attribute(:instance_name, kind_of: String, default: nil) + + attribute(:service_name, kind_of: String, name_attribute: true) + attribute(:args, kind_of: String, default: '-d') + + # service actions + attribute(:service_actions, kind_of: [Symbol, String, Array], default: [:enable, :start].freeze) + + # allow overridable init script + attribute(:init_source, kind_of: String, default: 'initscript.erb') + attribute(:init_cookbook, kind_of: String, default: 'elasticsearch') + + # allow overridable systemd unit + attribute(:systemd_source, kind_of: String, default: 'systemd_unit.erb') + attribute(:systemd_cookbook, kind_of: String, default: 'elasticsearch') +end diff --git a/cookbooks/elasticsearch/libraries/resource_user.rb b/cookbooks/elasticsearch/libraries/resource_user.rb new file mode 100644 index 0000000..dbba0a3 --- /dev/null +++ b/cookbooks/elasticsearch/libraries/resource_user.rb @@ -0,0 +1,19 @@ +# Chef Resource for declaring a user and group for Elasticsearch +class ElasticsearchCookbook::UserResource < Chef::Resource::LWRPBase + resource_name :elasticsearch_user + provides :elasticsearch_user + + actions(:create, :remove) + default_action :create + + # this is what helps the various resources find each other + attribute(:instance_name, kind_of: String, default: nil) + + attribute(:username, kind_of: String, name_attribute: true) # default to resource name + attribute(:uid, kind_of: Integer) + attribute(:shell, kind_of: String, default: '/bin/bash') + attribute(:comment, kind_of: String, default: 'Elasticsearch User') + + attribute(:groupname, kind_of: String, name_attribute: true) # default to resource name + attribute(:gid, kind_of: Integer) +end diff --git a/cookbooks/elasticsearch/metadata.json b/cookbooks/elasticsearch/metadata.json new file mode 100644 index 0000000..2d7d38b --- /dev/null +++ b/cookbooks/elasticsearch/metadata.json @@ -0,0 +1 @@ +{"name":"elasticsearch","version":"4.2.0","description":"Installs and configures Elasticsearch","long_description":"# Elasticsearch Chef Cookbook\n\n[![Build Status](https://travis-ci.org/elastic/cookbook-elasticsearch.svg?branch=master)](https://travis-ci.org/elastic/cookbook-elasticsearch) [![Cookbook Version](https://img.shields.io/cookbook/v/elasticsearch.svg)](https://supermarket.chef.io/cookbooks/elasticsearch)[![Build Status](https://jenkins-01.eastus.cloudapp.azure.com/job/elasticsearch-cookbook/badge/icon)](https://jenkins-01.eastus.cloudapp.azure.com/job/elasticsearch-cookbook/)\n\n**Please** review the [frequently asked questions](FAQ.md) and [contributing guidelines](CONTRIBUTING.md) before opening issues or submitting pull requests.\n\n## Looking for Elasticsearch 5.x or 6.x?\n\nPlease [check out the previous 3.x.x releases](https://github.com/elastic/cookbook-elasticsearch/tree/3.x.x) of this cookbook. Please consider pinning your cookbook to '~> 3.0' for support for Elasticsearch 6 and earlier, or '~> 4.0' release for Elasticsearch 6 and beyond.\n\n## Attributes\n\nPlease consult [attributes/default.rb](attributes/default.rb) for a large list\nof checksums for many different archives and package files of different\nelasticsearch versions. Both recipes and resources/providers here use those\ndefault values.\n\nYou may use `%s` in your URL and this cookbook will use sprintf/format to insert\nthe version parameter as a string into your download_url.\n\n|Name|Default|Other values|\n|----|-------|------------|\n| For Elasticsearch < 7: ||\n|`default['elasticsearch']['download_urls']['debian']`|[See values](attributes/default.rb).|`%s` will be replaced with the version attribute above|\n|`default['elasticsearch']['download_urls']['rhel']`|[See values](attributes/default.rb).|`%s` will be replaced with the version attribute above|\n|`default['elasticsearch']['download_urls']['tarball']`|[See values](attributes/default.rb).|`%s` will be replaced with the version attribute above|\n| For Elasticsearch >= 7: ||\n|`default['elasticsearch']['download_urls_v7']['debian']`|[See values](attributes/default.rb).|`%s` will be replaced with the version attribute above|\n|`default['elasticsearch']['download_urls_v7']['rhel']`|[See values](attributes/default.rb).|`%s` will be replaced with the version attribute above|\n|`default['elasticsearch']['download_urls_v7']['tarball']`|[See values](attributes/default.rb).|`%s` will be replaced with the version attribute above|\n\nThis cookbook's `elasticsearch::default` recipe also supports setting any `elasticsearch_` resource using attributes:\n\n```\ndefault['elasticsearch']['user'] = {}\ndefault['elasticsearch']['install'] = {}\ndefault['elasticsearch']['configure'] = {}\ndefault['elasticsearch']['service'] = {}\ndefault['elasticsearch']['plugin'] = {}\n```\n\nFor example, this will pass a username 'foo' to `elasticsearch_user` and set a uid to `1234`:\n```\ndefault['elasticsearch']['user']['username'] = 'foo'\ndefault['elasticsearch']['user']['uid'] = '1234'\n```\n\n## Recipes\n\nResources are the intended way to consume this cookbook, however we have\nprovided a single recipe that configures Elasticsearch by downloading an archive\ncontaining a distribution of Elasticsearch, and extracting that into `/usr/share`.\n\nSee the attributes section above to for what defaults you can adjust.\n\n### default\n\nThe default recipe creates an elasticsearch user, group, package installation,\nconfiguration files, and service with all of the default options.\n\nPlease note that there are [additional examples within the test fixtures](test/fixtures/cookbooks/elasticsearch_test),\nincluding a demonstration of how to configure two instances of Elasticsearch on a single server.\n\n## Resources\n\n## Notifications and Service Start/Restart\n\nThe resources provided in this cookbook **do not automatically restart** services when changes have occurred. They ***do start services by default when configuring a new service*** This has been done to protect you from accidental data loss and service outages, as nodes might restart simultaneously or may not restart at all when bad configuration values are supplied.\n\nelasticsearch_service has a special `service_actions` parameter you can use to specify what state the underlying service should be in on each chef run (defaults to `:enabled` and `:started`). It will also pass through all of the standard `service` resource\nactions to the underlying service resource if you wish to notify it.\n\nYou **must** supply your desired notifications when using each resource if you want Chef to automatically restart services. Again, we don't recommend this unless you know what you're doing.\n\nWe are supporting whyrun mode in this cookbook, simply because we're using all builtin resources from core Chef, and these also already support whyrun. If you contribute to this cookbook, please be sure to maintain that or guard dangerous Ruby code with something like `if !whyrun_mode? || nested_resource.whyrun_supported?`.\n\n### Resource names\n\nMany of the resources provided in this cookbook need to share configuration\nvalues. For example, the `elasticsearch_service` resource needs to know the path\nto the configuration file(s) generated by `elasticsearch_configure` and the path\nto the actual ES binary installed by `elasticsearch_install`. And they both need\nto know the appropriate system user and group defined by `elasticsearch_user`.\n\nSearch order: In order to make this easy, all resources in this cookbook use the following\nsearch order to locate resources that apply to the same overall\nElasticsearch setup:\n\n1. Resources that share the same resource name\n1. Resources that share the same value for `instance_name`\n1. Resources named `default` or resources named `elasticsearch`\n - This fails if both `default` and `elasticsearch` resources exist\n\nExamples of more complicated resource names are left to the reader, but here we\npresent a typical example that should work in most cases:\n\n```ruby\nelasticsearch_user 'elasticsearch'\nelasticsearch_install 'elasticsearch'\nelasticsearch_configure 'elasticsearch'\nelasticsearch_service 'elasticsearch'\nelasticsearch_plugin 'x-pack'\n```\n\n### elasticsearch_user\nActions: `:create`, `:remove`\n\nCreates a user and group on the system for use by elasticsearch. Here is an\nexample with many of the default options and default values (all options except\na resource name may be omitted).\n\nExamples:\n\n```ruby\nelasticsearch_user 'elasticsearch'\n```\n\n```ruby\nelasticsearch_user 'elasticsearch' do\n username 'elasticsearch'\n groupname 'elasticsearch'\n shell '/bin/bash'\n comment 'Elasticsearch User'\n\n action :create\nend\n```\n\n### elasticsearch_install\nActions: `:install`, `:remove`\n\nDownloads the elasticsearch software, and unpacks it on the system. There are\ncurrently three ways to install -- `'repository'` (the default), which creates an\napt or yum repo and installs from there, `'package'`, which downloads the appropriate\npackage from elasticsearch.org and uses the package manager to install it, and\n`'tarball'` which downloads a tarball from elasticsearch.org and unpacks it.\nThis resource also comes with a `:remove` action which will remove the package\nor directory elasticsearch was unpacked into.\n\nYou may always specify a download_url and/or download_checksum, and you may\ninclude `%s` which will be replaced by the version parameter you supply.\n\nPlease be sure to consult the above attribute section as that controls how\nElasticsearch version, download URL and checksum are determined if you omit\nthem.\n\n**NOTE**: The `:remove` action has not been implemented yet. Pull requests are\nvery much welcome & encouraged, if you'd like to see this feature.\n\nExamples:\n\n```ruby\nelasticsearch_install 'elasticsearch'\n```\n\n```ruby\nelasticsearch_install 'my_es_installation' do\n type 'package' # type of install\n version '7.3.0'\n action :install # could be :remove as well\nend\n```\n\n```ruby\nelasticsearch_install 'my_es_installation' do\n type 'tarball' # type of install\n dir '/usr/local' # where to install\n\n download_url \"https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.7.2.tar.gz\"\n # sha256\n download_checksum \"6f81935e270c403681e120ec4395c28b2ddc87e659ff7784608b86beb5223dd2\"\n\n action :install # could be :remove as well\nend\n```\n\n```ruby\nelasticsearch_install 'my_es_installation' do\n type 'tarball' # type of install\n version '7.3.0'\n action :install # could be :remove as well\nend\n```\n\n```ruby\nelasticsearch_install 'my_es_installation' do\n type 'package' # type of install\n download_url \"https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.7.2.deb\"\n # sha256\n download_checksum \"791fb9f2131be2cf8c1f86ca35e0b912d7155a53f89c2df67467ca2105e77ec2\"\n instance_name 'elasticsearch'\n action :install # could be :remove as well\nend\n```\n\n### elasticsearch_configure\nActions: `:manage`, `:remove`\n\nConfigures an elasticsearch instance; creates directories for configuration,\nlogs, and data. Writes files `log4j2.properties`, `elasticsearch.in.sh` and\n`elasticsearch.yml`.\n\nThe main attribute for this resource is `configuration`,\nwhich is a hash of any elasticsearch configuration directives. The\nother important attribute is `default_configuration` -- this contains the\nminimal set of required defaults.\n\nNote that these are both _not_ a Chef mash, everything must be in a single level\nof keys and values. Any settings you pass in configuration will be merged into\n(and potentially overwrite) any default settings.\n\nSee the examples, [as well as the attributes in the resource file](libraries/resource_configure.rb),\nfor more.\n\nExamples:\n\nWith all defaults -\n```ruby\nelasticsearch_configure 'elasticsearch'\n```\n\nWith mostly defaults -\n```ruby\nelasticsearch_configure 'elasticsearch' do\n allocated_memory '512m'\n configuration ({\n 'cluster.name' => 'escluster',\n 'node.name' => 'node01',\n 'http.port' => 9201\n })\nend\n```\n\nVery complicated -\n```ruby\nelasticsearch_configure 'my_elasticsearch' do\n # if you override one of these, you probably want to override all\n path_home \"/opt/elasticsearch\"\n path_conf \"/etc/opt/elasticsearch\"\n path_data \"/var/opt/elasticsearch\"\n path_logs \"/var/log/elasticsearch\"\n path_pid \"/var/run/elasticsearch\"\n path_plugins \"/opt/elasticsearch/plugins\"\n path_bin \"/opt/elasticsearch/bin\"\n\n # override logging parameters\n cookbook_log4j2_properties \"my_wrapper_cookbook\"\n template_log4j2_properties \"my_log4j2.properties.erb\"\n\n logging({:\"action\" => 'INFO'})\n\n allocated_memory '123m'\n\n jvm_options %w(\n -XX:+UseParNewGC\n -XX:+UseConcMarkSweepGC\n -XX:CMSInitiatingOccupancyFraction=75\n -XX:+UseCMSInitiatingOccupancyOnly\n -XX:+HeapDumpOnOutOfMemoryError\n -XX:+PrintGCDetails\n )\n\n configuration ({\n 'node.name' => 'crazy'\n })\n\n action :manage\nend\n```\n\n### elasticsearch_service\nActions: `:configure`, `:remove`\n\nWrites out a system service configuration of the appropriate type, and enables\nit to start on boot. You can override almost all of the relevant settings in\nsuch a way that you may run multiple instances. Most settings will be taken from\na matching `elasticsearch_config` resource in the collection.\n\n```ruby\nelasticsearch_service 'elasticsearch'\n```\n\nIf you'd like to skip init scripts and systemd scripts, simply pass `nil` for\nthe template file (init_source or systemd_source) and this cookbook will\nentirely skip trying to setup those scripts. Combined with changing the default\nservice actions, this will have the same effect as `action :nothing`.\n\n### elasticsearch_plugin\nActions: `:install`, `:remove`\n\nInstalls or removes a plugin to a given elasticsearch instance and plugin\ndirectory. Please note that there is currently no way to upgrade an existing\nplugin using commandline tools, so we haven't exposed that feature here either.\nFurthermore, there isn't a way to determine if a plugin is compatible with ES or\neven what version it is. So once we install a plugin to a directory, we\ngenerally assume that is the desired one and we don't touch it further.\n\nSee https://github.com/elastic/cookbook-elasticsearch/issues/264 for more info.\nNB: You [may encounter issues on certain distros](http://blog.backslasher.net/java-ssl-crash.html) with NSS 3.16.1 and OpenJDK 7.x.\n\nOfficially supported or commercial plugins require just the plugin name:\n\n```ruby\nelasticsearch_plugin 'analysis-icu' do\n action :install\nend\nelasticsearch_plugin 'shield' do\n action :install\nend\n```\n\nPlugins from GitHub require a URL of 'username/repository' or 'username/repository/version':\n\n```ruby\nelasticsearch_plugin 'kopf' do\n url 'lmenezes/elasticsearch-kopf'\n action :install\nend\n\nelasticsearch_plugin 'kopf' do\n url 'lmenezes/elasticsearch-kopf/1.5.7'\n action :install\nend\n```\n\nPlugins from Maven Central or Sonatype require 'groupId/artifactId/version':\n```ruby\nelasticsearch_plugin 'mapper-attachments' do\n url 'org.elasticsearch/elasticsearch-mapper-attachments/2.6.0'\n action :install\nend\n```\n\nPlugins can be installed from a custom URL or file location as follows:\n```ruby\nelasticsearch_plugin 'mapper-attachments' do\n url 'http://some.domain.name//my-plugin-1.0.0.zip'\n action :install\nend\n\nelasticsearch_plugin 'mapper-attachments' do\n url 'file:/path/to/my-plugin-1.0.0.zip'\n action :install\nend\n```\n\nThe plugin resource respects the `https_proxy` or `http_proxy` (non-SSL)\n[Chef settings](https://docs.chef.io/config_rb_client.html) unless explicitly\ndisabled using `chef_proxy false`:\n```ruby\nelasticsearch_plugin 'kopf' do\n url 'lmenezes/elasticsearch-kopf'\n chef_proxy false\n action :install\nend\n```\n\nTo run multiple instances per machine, an explicit `plugin_dir` location\nhas to be provided:\n\n```ruby\nelasticsearch_plugin 'x-pack' do\n plugin_dir '/usr/share/elasticsearch_foo/plugins'\nend\n```\n\nIf for some reason, you want to name the resource something else, you may\nprovide the true plugin name using the `plugin_name` parameter:\n\n```ruby\nelasticsearch_plugin 'xyzzy' do\n plugin_name 'kopf'\n url 'lmenezes/elasticsearch-kopf'\n action :install\nend\n```\n\n## License\n\nThis software is licensed under the Apache 2 license, quoted below.\n\n Copyright (c) 2015 Elasticsearch \n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n","maintainer":"Karel Minarik","maintainer_email":"karel.minarik@elasticsearch.org","license":"Apache-2.0","platforms":{"amazon":">= 0.0.0","centos":">= 0.0.0","debian":">= 0.0.0","fedora":">= 0.0.0","redhat":">= 0.0.0","ubuntu":">= 0.0.0"},"dependencies":{"apt":">= 0.0.0","yum":">= 0.0.0","chef-sugar":">= 0.0.0","ark":">= 0.0.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/elastic/cookbook-elasticsearch","issues_url":"https://github.com/elastic/cookbook-elasticsearch/issues","chef_version":[[">= 12.5"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/elasticsearch/metadata.rb b/cookbooks/elasticsearch/metadata.rb new file mode 100644 index 0000000..0c1ec35 --- /dev/null +++ b/cookbooks/elasticsearch/metadata.rb @@ -0,0 +1,25 @@ +# Encoding: utf-8 +name 'elasticsearch' +maintainer 'Karel Minarik' +maintainer_email 'karel.minarik@elasticsearch.org' +license 'Apache-2.0' +description 'Installs and configures Elasticsearch' +long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) +version '4.2.0' + +supports 'amazon' +supports 'centos' +supports 'debian' +supports 'fedora' +supports 'redhat' +supports 'ubuntu' + +depends 'apt' +depends 'yum' +depends 'chef-sugar' +depends 'ark' + +issues_url 'https://github.com/elastic/cookbook-elasticsearch/issues' +source_url 'https://github.com/elastic/cookbook-elasticsearch' + +chef_version '>= 12.5' if respond_to?(:chef_version) diff --git a/cookbooks/elasticsearch/recipes/default.rb b/cookbooks/elasticsearch/recipes/default.rb new file mode 100644 index 0000000..efc7a15 --- /dev/null +++ b/cookbooks/elasticsearch/recipes/default.rb @@ -0,0 +1,46 @@ +# Encoding: utf-8 +# +# Cookbook Name:: elasticsearch +# Recipe:: default +# + +include_recipe 'chef-sugar' + +# see README.md and test/fixtures/cookbooks for more examples! +elasticsearch_user 'elasticsearch' do + node['elasticsearch']['user'].each do |key, value| + # Skip nils, use false if you want to disable something. + send(key, value) unless value.nil? + end +end + +elasticsearch_install 'elasticsearch' do + node['elasticsearch']['install'].each do |key, value| + # Skip nils, use false if you want to disable something. + send(key, value) unless value.nil? + end +end + +elasticsearch_configure 'elasticsearch' do + node['elasticsearch']['configure'].each do |key, value| + # Skip nils, use false if you want to disable something. + send(key, value) unless value.nil? + end +end + +elasticsearch_service 'elasticsearch' do + node['elasticsearch']['service'].each do |key, value| + # Skip nils, use false if you want to disable something. + send(key, value) unless value.nil? + end +end + +# by default, no plugins +node['elasticsearch']['plugin'].each do |plugin_name, plugin_value| + elasticsearch_plugin plugin_name do + plugin_value.each do |key, value| + # Skip nils, use false if you want to disable something. + send(key, value) unless value.nil? + end + end +end diff --git a/cookbooks/elasticsearch/templates/amazon/initscript.erb b/cookbooks/elasticsearch/templates/amazon/initscript.erb new file mode 100644 index 0000000..27ffdaa --- /dev/null +++ b/cookbooks/elasticsearch/templates/amazon/initscript.erb @@ -0,0 +1,180 @@ +#!/bin/bash +# +# <%= @program_name %> +# +# chkconfig: 2345 80 20 +# description: Starts and stops a single elasticsearch instance on this system +# + +### BEGIN INIT INFO +# Provides: Elasticsearch +# Required-Start: $network $named +# Required-Stop: $network $named +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: This service manages the elasticsearch daemon +# Description: Elasticsearch is a very scalable, schema-free and high-performance search solution supporting multi-tenancy and near realtime search. +### END INIT INFO + +# +# init.d / servicectl compatibility (openSUSE) +# +if [ -f /etc/rc.status ]; then + . /etc/rc.status + rc_reset +fi + +# +# Source function library. +# +if [ -f /etc/rc.d/init.d/functions ]; then + . /etc/rc.d/init.d/functions +fi + +# Sets the default values for elasticsearch variables used in this script +ES_HOME="/usr/share/elasticsearch" +MAX_OPEN_FILES=65536 +MAX_MAP_COUNT=262144 +ES_PATH_CONF="/etc/elasticsearch" + +PID_DIR="/var/run/elasticsearch" + +# Source the default env file +ES_ENV_FILE="/etc/sysconfig/<%= @program_name %>" +if [ -f "$ES_ENV_FILE" ]; then + . "$ES_ENV_FILE" +fi + +<% if @install_type != 'tarball' %> +# ES_USER and ES_GROUP settings were removed +if [ ! -z "$ES_USER" ] || [ ! -z "$ES_GROUP" ]; then + echo "ES_USER and ES_GROUP settings are no longer supported. To run as a custom user/group use the archive distribution of Elasticsearch." + exit 1 +fi +<% end %> + +exec="$ES_HOME/bin/elasticsearch" +prog="elasticsearch" +pidfile="$PID_DIR/${prog}.pid" + +export ES_JAVA_OPTS +export JAVA_HOME +export ES_PATH_CONF +export ES_STARTUP_SLEEP_TIME + +lockfile=/var/lock/subsys/$prog + +if [ ! -x "$exec" ]; then + echo "The elasticsearch startup script does not exists or it is not executable, tried: $exec" + exit 1 +fi + +checkJava() { + if [ -x "$JAVA_HOME/bin/java" ]; then + JAVA="$JAVA_HOME/bin/java" + else + JAVA=`which java` + fi + + if [ ! -x "$JAVA" ]; then + echo "Could not find any executable java binary. Please install java in your PATH or set JAVA_HOME" + exit 1 + fi +} + +start() { + checkJava + [ -x $exec ] || exit 5 + + if [ -n "$MAX_OPEN_FILES" ]; then + ulimit -n $MAX_OPEN_FILES + fi + if [ -n "$MAX_LOCKED_MEMORY" ]; then + ulimit -l $MAX_LOCKED_MEMORY + fi + if [ -n "$MAX_MAP_COUNT" -a -f /proc/sys/vm/max_map_count ]; then + sysctl -q -w vm.max_map_count=$MAX_MAP_COUNT + fi + + # Ensure that the PID_DIR exists (it is cleaned at OS startup time) + if [ -n "$PID_DIR" ] && [ ! -e "$PID_DIR" ]; then + mkdir -p "$PID_DIR" && chown elasticsearch:elasticsearch "$PID_DIR" + fi + if [ -n "$pidfile" ] && [ ! -e "$pidfile" ]; then + touch "$pidfile" && chown elasticsearch:elasticsearch "$pidfile" + fi + + cd $ES_HOME + echo -n $"Starting $prog: " + # if not running, start it up here, usually something like "daemon $exec" + daemon --user elasticsearch --pidfile $pidfile $exec -p $pidfile -d + retval=$? + echo + [ $retval -eq 0 ] && touch $lockfile + return $retval +} + +stop() { + echo -n $"Stopping $prog: " + # stop it here, often "killproc $prog" + killproc -p $pidfile -d 86400 $prog + retval=$? + echo + [ $retval -eq 0 ] && rm -f $lockfile + return $retval +} + +restart() { + stop + start +} + +reload() { + restart +} + +force_reload() { + restart +} + +rh_status() { + # run checks to determine if the service is running or use generic status + status -p $pidfile $prog +} + +rh_status_q() { + rh_status >/dev/null 2>&1 +} + + +case "$1" in + start) + rh_status_q && exit 0 + $1 + ;; + stop) + rh_status_q || exit 0 + $1 + ;; + restart) + $1 + ;; + reload) + rh_status_q || exit 7 + $1 + ;; + force-reload) + force_reload + ;; + status) + rh_status + ;; + condrestart|try-restart) + rh_status_q || exit 0 + restart + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}" + exit 2 +esac +exit $? diff --git a/cookbooks/elasticsearch/templates/centos/initscript.erb b/cookbooks/elasticsearch/templates/centos/initscript.erb new file mode 100755 index 0000000..27ffdaa --- /dev/null +++ b/cookbooks/elasticsearch/templates/centos/initscript.erb @@ -0,0 +1,180 @@ +#!/bin/bash +# +# <%= @program_name %> +# +# chkconfig: 2345 80 20 +# description: Starts and stops a single elasticsearch instance on this system +# + +### BEGIN INIT INFO +# Provides: Elasticsearch +# Required-Start: $network $named +# Required-Stop: $network $named +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: This service manages the elasticsearch daemon +# Description: Elasticsearch is a very scalable, schema-free and high-performance search solution supporting multi-tenancy and near realtime search. +### END INIT INFO + +# +# init.d / servicectl compatibility (openSUSE) +# +if [ -f /etc/rc.status ]; then + . /etc/rc.status + rc_reset +fi + +# +# Source function library. +# +if [ -f /etc/rc.d/init.d/functions ]; then + . /etc/rc.d/init.d/functions +fi + +# Sets the default values for elasticsearch variables used in this script +ES_HOME="/usr/share/elasticsearch" +MAX_OPEN_FILES=65536 +MAX_MAP_COUNT=262144 +ES_PATH_CONF="/etc/elasticsearch" + +PID_DIR="/var/run/elasticsearch" + +# Source the default env file +ES_ENV_FILE="/etc/sysconfig/<%= @program_name %>" +if [ -f "$ES_ENV_FILE" ]; then + . "$ES_ENV_FILE" +fi + +<% if @install_type != 'tarball' %> +# ES_USER and ES_GROUP settings were removed +if [ ! -z "$ES_USER" ] || [ ! -z "$ES_GROUP" ]; then + echo "ES_USER and ES_GROUP settings are no longer supported. To run as a custom user/group use the archive distribution of Elasticsearch." + exit 1 +fi +<% end %> + +exec="$ES_HOME/bin/elasticsearch" +prog="elasticsearch" +pidfile="$PID_DIR/${prog}.pid" + +export ES_JAVA_OPTS +export JAVA_HOME +export ES_PATH_CONF +export ES_STARTUP_SLEEP_TIME + +lockfile=/var/lock/subsys/$prog + +if [ ! -x "$exec" ]; then + echo "The elasticsearch startup script does not exists or it is not executable, tried: $exec" + exit 1 +fi + +checkJava() { + if [ -x "$JAVA_HOME/bin/java" ]; then + JAVA="$JAVA_HOME/bin/java" + else + JAVA=`which java` + fi + + if [ ! -x "$JAVA" ]; then + echo "Could not find any executable java binary. Please install java in your PATH or set JAVA_HOME" + exit 1 + fi +} + +start() { + checkJava + [ -x $exec ] || exit 5 + + if [ -n "$MAX_OPEN_FILES" ]; then + ulimit -n $MAX_OPEN_FILES + fi + if [ -n "$MAX_LOCKED_MEMORY" ]; then + ulimit -l $MAX_LOCKED_MEMORY + fi + if [ -n "$MAX_MAP_COUNT" -a -f /proc/sys/vm/max_map_count ]; then + sysctl -q -w vm.max_map_count=$MAX_MAP_COUNT + fi + + # Ensure that the PID_DIR exists (it is cleaned at OS startup time) + if [ -n "$PID_DIR" ] && [ ! -e "$PID_DIR" ]; then + mkdir -p "$PID_DIR" && chown elasticsearch:elasticsearch "$PID_DIR" + fi + if [ -n "$pidfile" ] && [ ! -e "$pidfile" ]; then + touch "$pidfile" && chown elasticsearch:elasticsearch "$pidfile" + fi + + cd $ES_HOME + echo -n $"Starting $prog: " + # if not running, start it up here, usually something like "daemon $exec" + daemon --user elasticsearch --pidfile $pidfile $exec -p $pidfile -d + retval=$? + echo + [ $retval -eq 0 ] && touch $lockfile + return $retval +} + +stop() { + echo -n $"Stopping $prog: " + # stop it here, often "killproc $prog" + killproc -p $pidfile -d 86400 $prog + retval=$? + echo + [ $retval -eq 0 ] && rm -f $lockfile + return $retval +} + +restart() { + stop + start +} + +reload() { + restart +} + +force_reload() { + restart +} + +rh_status() { + # run checks to determine if the service is running or use generic status + status -p $pidfile $prog +} + +rh_status_q() { + rh_status >/dev/null 2>&1 +} + + +case "$1" in + start) + rh_status_q && exit 0 + $1 + ;; + stop) + rh_status_q || exit 0 + $1 + ;; + restart) + $1 + ;; + reload) + rh_status_q || exit 7 + $1 + ;; + force-reload) + force_reload + ;; + status) + rh_status + ;; + condrestart|try-restart) + rh_status_q || exit 0 + restart + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}" + exit 2 +esac +exit $? diff --git a/cookbooks/elasticsearch/templates/debian/initscript.erb b/cookbooks/elasticsearch/templates/debian/initscript.erb new file mode 100644 index 0000000..c149ebb --- /dev/null +++ b/cookbooks/elasticsearch/templates/debian/initscript.erb @@ -0,0 +1,187 @@ +#!/bin/bash +# +# /etc/init.d/<%= @program_name %> -- startup script for Elasticsearch +# +### BEGIN INIT INFO +# Provides: <%= @program_name %> +# Required-Start: $network $remote_fs $named +# Required-Stop: $network $remote_fs $named +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Starts elasticsearch +# Description: Starts elasticsearch using start-stop-daemon +### END INIT INFO + +PATH=/bin:/usr/bin:/sbin:/usr/sbin +NAME=<%= @program_name %> +DESC="Elasticsearch Server" +DEFAULT=/etc/default/$NAME + +if [ `id -u` -ne 0 ]; then + echo "You need root privileges to run this script" + exit 1 +fi + + +. /lib/lsb/init-functions + +if [ -r /etc/default/rcS ]; then + . /etc/default/rcS +fi + + +# The following variables can be overwritten in $DEFAULT + +# Directory where the Elasticsearch binary distribution resides +ES_HOME=/usr/share/$NAME + +# Additional Java OPTS +#ES_JAVA_OPTS= + +# Maximum number of open files +MAX_OPEN_FILES=65536 + +# Maximum amount of locked memory +#MAX_LOCKED_MEMORY= + +# Elasticsearch configuration directory +ES_PATH_CONF=/etc/$NAME + +# Maximum number of VMA (Virtual Memory Areas) a process can own +MAX_MAP_COUNT=262144 + +# Elasticsearch PID file directory +PID_DIR="/var/run/elasticsearch" + +# End of variables that can be overwritten in $DEFAULT + +# overwrite settings from default file +if [ -f "$DEFAULT" ]; then + . "$DEFAULT" +fi + +<% if @install_type != 'tarball' %> +# ES_USER and ES_GROUP settings were removed +if [ ! -z "$ES_USER" ] || [ ! -z "$ES_GROUP" ]; then + echo "ES_USER and ES_GROUP settings are no longer supported. To run as a custom user/group use the archive distribution of Elasticsearch." + exit 1 +fi +<% end %> + +# Define other required variables +PID_FILE="$PID_DIR/$NAME.pid" +DAEMON=$ES_HOME/bin/elasticsearch +DAEMON_OPTS="-d -p $PID_FILE" + +export ES_JAVA_OPTS +export JAVA_HOME +export ES_PATH_CONF + +if [ ! -x "$DAEMON" ]; then + echo "The elasticsearch startup script does not exists or it is not executable, tried: $DAEMON" + exit 1 +fi + +checkJava() { + if [ -x "$JAVA_HOME/bin/java" ]; then + JAVA="$JAVA_HOME/bin/java" + else + JAVA=`which java` + fi + + if [ ! -x "$JAVA" ]; then + echo "Could not find any executable java binary. Please install java in your PATH or set JAVA_HOME" + exit 1 + fi +} + +case "$1" in + start) + checkJava + + log_daemon_msg "Starting $DESC" + + pid=`pidofproc -p $PID_FILE elasticsearch` + if [ -n "$pid" ] ; then + log_begin_msg "Already running." + log_end_msg 0 + exit 0 + fi + + # Ensure that the PID_DIR exists (it is cleaned at OS startup time) + if [ -n "$PID_DIR" ] && [ ! -e "$PID_DIR" ]; then + mkdir -p "$PID_DIR" && chown elasticsearch:elasticsearch "$PID_DIR" + fi + if [ -n "$PID_FILE" ] && [ ! -e "$PID_FILE" ]; then + touch "$PID_FILE" && chown elasticsearch:elasticsearch "$PID_FILE" + fi + + if [ -n "$MAX_OPEN_FILES" ]; then + ulimit -n $MAX_OPEN_FILES + fi + + if [ -n "$MAX_LOCKED_MEMORY" ]; then + ulimit -l $MAX_LOCKED_MEMORY + fi + + if [ -n "$MAX_MAP_COUNT" -a -f /proc/sys/vm/max_map_count ]; then + sysctl -q -w vm.max_map_count=$MAX_MAP_COUNT + fi + + # Start Daemon + start-stop-daemon -d $ES_HOME --start --user elasticsearch -c elasticsearch --pidfile "$PID_FILE" --exec $DAEMON -- $DAEMON_OPTS + return=$? + if [ $return -eq 0 ]; then + i=0 + timeout=10 + # Wait for the process to be properly started before exiting + until { kill -0 `cat "$PID_FILE"`; } >/dev/null 2>&1 + do + sleep 1 + i=$(($i + 1)) + if [ $i -gt $timeout ]; then + log_end_msg 1 + exit 1 + fi + done + fi + log_end_msg $return + exit $return + ;; + stop) + log_daemon_msg "Stopping $DESC" + + if [ -f "$PID_FILE" ]; then + start-stop-daemon --stop --pidfile "$PID_FILE" \ + --user elasticsearch \ + --quiet \ + --retry forever/TERM/20 > /dev/null + if [ $? -eq 1 ]; then + log_progress_msg "$DESC is not running but pid file exists, cleaning up" + elif [ $? -eq 3 ]; then + PID="`cat $PID_FILE`" + log_failure_msg "Failed to stop $DESC (pid $PID)" + exit 1 + fi + rm -f "$PID_FILE" + else + log_progress_msg "(not running)" + fi + log_end_msg 0 + ;; + status) + status_of_proc -p $PID_FILE elasticsearch elasticsearch && exit 0 || exit $? + ;; + restart|force-reload) + if [ -f "$PID_FILE" ]; then + $0 stop + fi + $0 start + ;; + *) + log_success_msg "Usage: $0 {start|stop|restart|force-reload|status}" + exit 1 + ;; +esac + +exit 0 diff --git a/cookbooks/elasticsearch/templates/default/elasticsearch.in.sh.erb b/cookbooks/elasticsearch/templates/default/elasticsearch.in.sh.erb new file mode 100644 index 0000000..997ec71 --- /dev/null +++ b/cookbooks/elasticsearch/templates/default/elasticsearch.in.sh.erb @@ -0,0 +1,13 @@ +################################ +# THIS FILE IS MANAGED BY CHEF +################################ +# Elasticsearch +################################ +# CHANGES MAY BE OVERWRITTEN +################################ + +<% +@params.sort.each do |key, value| + next if key.nil? || value.nil? + %><%= key.to_s %>=<%= value.to_s %> +<% end %> diff --git a/cookbooks/elasticsearch/templates/default/elasticsearch.yml.erb b/cookbooks/elasticsearch/templates/default/elasticsearch.yml.erb new file mode 100644 index 0000000..2b3b5ef --- /dev/null +++ b/cookbooks/elasticsearch/templates/default/elasticsearch.yml.erb @@ -0,0 +1,8 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# THIS FILE IS MANAGED BY CHEF, DO NOT EDIT MANUALLY, YOUR CHANGES WILL BE OVERWRITTEN! +# +# Please see the documentation for further information on configuration options: +# +# +<% require 'yaml' %> +<%= @config.to_yaml.to_s %> diff --git a/cookbooks/elasticsearch/templates/default/jvm_options.erb b/cookbooks/elasticsearch/templates/default/jvm_options.erb new file mode 100644 index 0000000..35d710c --- /dev/null +++ b/cookbooks/elasticsearch/templates/default/jvm_options.erb @@ -0,0 +1,3 @@ +## JVM configuration + +<%= @jvm_options %> diff --git a/cookbooks/elasticsearch/templates/default/log4j2.properties.erb b/cookbooks/elasticsearch/templates/default/log4j2.properties.erb new file mode 100644 index 0000000..b84cb77 --- /dev/null +++ b/cookbooks/elasticsearch/templates/default/log4j2.properties.erb @@ -0,0 +1,88 @@ +status = error + +# log action execution errors for easier debugging +logger.action.name = org.elasticsearch.action +logger.action.level = debug + +appender.console.type = Console +appender.console.name = console +appender.console.layout.type = PatternLayout +appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%m%n + +appender.rolling.type = RollingFile +appender.rolling.name = rolling +appender.rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log +appender.rolling.layout.type = PatternLayout +appender.rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%.-10000m%n +appender.rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}-%d{yyyy-MM-dd}-%i.log.gz +appender.rolling.policies.type = Policies +appender.rolling.policies.time.type = TimeBasedTriggeringPolicy +appender.rolling.policies.time.interval = 1 +appender.rolling.policies.time.modulate = true +appender.rolling.policies.size.type = SizeBasedTriggeringPolicy +appender.rolling.policies.size.size = 128MB +appender.rolling.strategy.type = DefaultRolloverStrategy +appender.rolling.strategy.fileIndex = nomax +appender.rolling.strategy.action.type = Delete +appender.rolling.strategy.action.basepath = ${sys:es.logs.base_path} +appender.rolling.strategy.action.condition.type = IfFileName +appender.rolling.strategy.action.condition.glob = ${sys:es.logs.cluster_name}-* +appender.rolling.strategy.action.condition.nested_condition.type = IfAccumulatedFileSize +appender.rolling.strategy.action.condition.nested_condition.exceeds = 2GB + +rootLogger.level = info +rootLogger.appenderRef.console.ref = console +rootLogger.appenderRef.rolling.ref = rolling + +appender.deprecation_rolling.type = RollingFile +appender.deprecation_rolling.name = deprecation_rolling +appender.deprecation_rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_deprecation.log +appender.deprecation_rolling.layout.type = PatternLayout +appender.deprecation_rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%.-10000m%n +appender.deprecation_rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_deprecation-%i.log.gz +appender.deprecation_rolling.policies.type = Policies +appender.deprecation_rolling.policies.size.type = SizeBasedTriggeringPolicy +appender.deprecation_rolling.policies.size.size = 1GB +appender.deprecation_rolling.strategy.type = DefaultRolloverStrategy +appender.deprecation_rolling.strategy.max = 4 + +logger.deprecation.name = org.elasticsearch.deprecation +logger.deprecation.level = warn +logger.deprecation.appenderRef.deprecation_rolling.ref = deprecation_rolling +logger.deprecation.additivity = false + +appender.index_search_slowlog_rolling.type = RollingFile +appender.index_search_slowlog_rolling.name = index_search_slowlog_rolling +appender.index_search_slowlog_rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_index_search_slowlog.log +appender.index_search_slowlog_rolling.layout.type = PatternLayout +appender.index_search_slowlog_rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%.-10000m%n +appender.index_search_slowlog_rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_index_search_slowlog-%d{yyyy-MM-dd}.log +appender.index_search_slowlog_rolling.policies.type = Policies +appender.index_search_slowlog_rolling.policies.time.type = TimeBasedTriggeringPolicy +appender.index_search_slowlog_rolling.policies.time.interval = 1 +appender.index_search_slowlog_rolling.policies.time.modulate = true + +logger.index_search_slowlog_rolling.name = index.search.slowlog +logger.index_search_slowlog_rolling.level = trace +logger.index_search_slowlog_rolling.appenderRef.index_search_slowlog_rolling.ref = index_search_slowlog_rolling +logger.index_search_slowlog_rolling.additivity = false + +appender.index_indexing_slowlog_rolling.type = RollingFile +appender.index_indexing_slowlog_rolling.name = index_indexing_slowlog_rolling +appender.index_indexing_slowlog_rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_index_indexing_slowlog.log +appender.index_indexing_slowlog_rolling.layout.type = PatternLayout +appender.index_indexing_slowlog_rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%.-10000m%n +appender.index_indexing_slowlog_rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_index_indexing_slowlog-%d{yyyy-MM-dd}.log +appender.index_indexing_slowlog_rolling.policies.type = Policies +appender.index_indexing_slowlog_rolling.policies.time.type = TimeBasedTriggeringPolicy +appender.index_indexing_slowlog_rolling.policies.time.interval = 1 +appender.index_indexing_slowlog_rolling.policies.time.modulate = true + +logger.index_indexing_slowlog.name = index.indexing.slowlog.index +logger.index_indexing_slowlog.level = trace +logger.index_indexing_slowlog.appenderRef.index_indexing_slowlog_rolling.ref = index_indexing_slowlog_rolling +logger.index_indexing_slowlog.additivity = false + +<% @logging.each do |k,v| %> +<%= k %>=<%= v %> +<% end %> diff --git a/cookbooks/elasticsearch/templates/default/sysctl.d-elasticsearch.conf.erb b/cookbooks/elasticsearch/templates/default/sysctl.d-elasticsearch.conf.erb new file mode 100644 index 0000000..62ea54d --- /dev/null +++ b/cookbooks/elasticsearch/templates/default/sysctl.d-elasticsearch.conf.erb @@ -0,0 +1 @@ +vm.max_map_count=262144 diff --git a/cookbooks/elasticsearch/templates/default/systemd_unit.erb b/cookbooks/elasticsearch/templates/default/systemd_unit.erb new file mode 100644 index 0000000..8919a92 --- /dev/null +++ b/cookbooks/elasticsearch/templates/default/systemd_unit.erb @@ -0,0 +1,60 @@ +[Unit] +Description=Elasticsearch +Documentation=http://www.elastic.co +Wants=network-online.target +After=network-online.target + +[Service] +RuntimeDirectory=elasticsearch +Environment=ES_HOME=/usr/share/elasticsearch +Environment=ES_PATH_CONF=/etc/elasticsearch +Environment=PID_DIR=/var/run/elasticsearch +EnvironmentFile=-<%= @default_dir %>/<%= @program_name %> + +WorkingDirectory=<%= @path_home %> + +User=elasticsearch +Group=elasticsearch + +ExecStart=<%= @path_home %>/bin/elasticsearch -p ${PID_DIR}/elasticsearch.pid --quiet + +# StandardOutput is configured to redirect to journalctl since +# some error messages may be logged in standard output before +# elasticsearch logging system is initialized. Elasticsearch +# stores its logs in /var/log/elasticsearch and does not use +# journalctl by default. If you also want to enable journalctl +# logging, you can simply remove the "quiet" option from ExecStart. +StandardOutput=journal +StandardError=inherit + +# Specifies the maximum file descriptor number that can be opened by this process +LimitNOFILE=65536 + +# Specifies the maximum number of processes +LimitNPROC=4096 + +# Specifies the maximum size of virtual memory +LimitAS=infinity + +# Specifies the maximum file size +LimitFSIZE=infinity + +# Disable timeout logic and wait until process is stopped +TimeoutStopSec=0 + +# SIGTERM signal is used to stop the Java process +KillSignal=SIGTERM + +# Send the signal only to the JVM rather than its control group +KillMode=process + +# Java process is never killed +SendSIGKILL=no + +# When a JVM receives a SIGTERM signal it exits with code 143 +SuccessExitStatus=143 + +[Install] +WantedBy=multi-user.target + +# Built for distribution-6.0.0 (distribution) diff --git a/cookbooks/elasticsearch/templates/default/tmpfiles.d-elasticsearch.conf.erb b/cookbooks/elasticsearch/templates/default/tmpfiles.d-elasticsearch.conf.erb new file mode 100644 index 0000000..d079f28 --- /dev/null +++ b/cookbooks/elasticsearch/templates/default/tmpfiles.d-elasticsearch.conf.erb @@ -0,0 +1 @@ +d /var/run/elasticsearch 0755 elasticsearch elasticsearch - - diff --git a/cookbooks/elasticsearch/templates/oracle/initscript.erb b/cookbooks/elasticsearch/templates/oracle/initscript.erb new file mode 100755 index 0000000..27ffdaa --- /dev/null +++ b/cookbooks/elasticsearch/templates/oracle/initscript.erb @@ -0,0 +1,180 @@ +#!/bin/bash +# +# <%= @program_name %> +# +# chkconfig: 2345 80 20 +# description: Starts and stops a single elasticsearch instance on this system +# + +### BEGIN INIT INFO +# Provides: Elasticsearch +# Required-Start: $network $named +# Required-Stop: $network $named +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: This service manages the elasticsearch daemon +# Description: Elasticsearch is a very scalable, schema-free and high-performance search solution supporting multi-tenancy and near realtime search. +### END INIT INFO + +# +# init.d / servicectl compatibility (openSUSE) +# +if [ -f /etc/rc.status ]; then + . /etc/rc.status + rc_reset +fi + +# +# Source function library. +# +if [ -f /etc/rc.d/init.d/functions ]; then + . /etc/rc.d/init.d/functions +fi + +# Sets the default values for elasticsearch variables used in this script +ES_HOME="/usr/share/elasticsearch" +MAX_OPEN_FILES=65536 +MAX_MAP_COUNT=262144 +ES_PATH_CONF="/etc/elasticsearch" + +PID_DIR="/var/run/elasticsearch" + +# Source the default env file +ES_ENV_FILE="/etc/sysconfig/<%= @program_name %>" +if [ -f "$ES_ENV_FILE" ]; then + . "$ES_ENV_FILE" +fi + +<% if @install_type != 'tarball' %> +# ES_USER and ES_GROUP settings were removed +if [ ! -z "$ES_USER" ] || [ ! -z "$ES_GROUP" ]; then + echo "ES_USER and ES_GROUP settings are no longer supported. To run as a custom user/group use the archive distribution of Elasticsearch." + exit 1 +fi +<% end %> + +exec="$ES_HOME/bin/elasticsearch" +prog="elasticsearch" +pidfile="$PID_DIR/${prog}.pid" + +export ES_JAVA_OPTS +export JAVA_HOME +export ES_PATH_CONF +export ES_STARTUP_SLEEP_TIME + +lockfile=/var/lock/subsys/$prog + +if [ ! -x "$exec" ]; then + echo "The elasticsearch startup script does not exists or it is not executable, tried: $exec" + exit 1 +fi + +checkJava() { + if [ -x "$JAVA_HOME/bin/java" ]; then + JAVA="$JAVA_HOME/bin/java" + else + JAVA=`which java` + fi + + if [ ! -x "$JAVA" ]; then + echo "Could not find any executable java binary. Please install java in your PATH or set JAVA_HOME" + exit 1 + fi +} + +start() { + checkJava + [ -x $exec ] || exit 5 + + if [ -n "$MAX_OPEN_FILES" ]; then + ulimit -n $MAX_OPEN_FILES + fi + if [ -n "$MAX_LOCKED_MEMORY" ]; then + ulimit -l $MAX_LOCKED_MEMORY + fi + if [ -n "$MAX_MAP_COUNT" -a -f /proc/sys/vm/max_map_count ]; then + sysctl -q -w vm.max_map_count=$MAX_MAP_COUNT + fi + + # Ensure that the PID_DIR exists (it is cleaned at OS startup time) + if [ -n "$PID_DIR" ] && [ ! -e "$PID_DIR" ]; then + mkdir -p "$PID_DIR" && chown elasticsearch:elasticsearch "$PID_DIR" + fi + if [ -n "$pidfile" ] && [ ! -e "$pidfile" ]; then + touch "$pidfile" && chown elasticsearch:elasticsearch "$pidfile" + fi + + cd $ES_HOME + echo -n $"Starting $prog: " + # if not running, start it up here, usually something like "daemon $exec" + daemon --user elasticsearch --pidfile $pidfile $exec -p $pidfile -d + retval=$? + echo + [ $retval -eq 0 ] && touch $lockfile + return $retval +} + +stop() { + echo -n $"Stopping $prog: " + # stop it here, often "killproc $prog" + killproc -p $pidfile -d 86400 $prog + retval=$? + echo + [ $retval -eq 0 ] && rm -f $lockfile + return $retval +} + +restart() { + stop + start +} + +reload() { + restart +} + +force_reload() { + restart +} + +rh_status() { + # run checks to determine if the service is running or use generic status + status -p $pidfile $prog +} + +rh_status_q() { + rh_status >/dev/null 2>&1 +} + + +case "$1" in + start) + rh_status_q && exit 0 + $1 + ;; + stop) + rh_status_q || exit 0 + $1 + ;; + restart) + $1 + ;; + reload) + rh_status_q || exit 7 + $1 + ;; + force-reload) + force_reload + ;; + status) + rh_status + ;; + condrestart|try-restart) + rh_status_q || exit 0 + restart + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}" + exit 2 +esac +exit $? diff --git a/cookbooks/elasticsearch/templates/redhat/initscript.erb b/cookbooks/elasticsearch/templates/redhat/initscript.erb new file mode 100644 index 0000000..27ffdaa --- /dev/null +++ b/cookbooks/elasticsearch/templates/redhat/initscript.erb @@ -0,0 +1,180 @@ +#!/bin/bash +# +# <%= @program_name %> +# +# chkconfig: 2345 80 20 +# description: Starts and stops a single elasticsearch instance on this system +# + +### BEGIN INIT INFO +# Provides: Elasticsearch +# Required-Start: $network $named +# Required-Stop: $network $named +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: This service manages the elasticsearch daemon +# Description: Elasticsearch is a very scalable, schema-free and high-performance search solution supporting multi-tenancy and near realtime search. +### END INIT INFO + +# +# init.d / servicectl compatibility (openSUSE) +# +if [ -f /etc/rc.status ]; then + . /etc/rc.status + rc_reset +fi + +# +# Source function library. +# +if [ -f /etc/rc.d/init.d/functions ]; then + . /etc/rc.d/init.d/functions +fi + +# Sets the default values for elasticsearch variables used in this script +ES_HOME="/usr/share/elasticsearch" +MAX_OPEN_FILES=65536 +MAX_MAP_COUNT=262144 +ES_PATH_CONF="/etc/elasticsearch" + +PID_DIR="/var/run/elasticsearch" + +# Source the default env file +ES_ENV_FILE="/etc/sysconfig/<%= @program_name %>" +if [ -f "$ES_ENV_FILE" ]; then + . "$ES_ENV_FILE" +fi + +<% if @install_type != 'tarball' %> +# ES_USER and ES_GROUP settings were removed +if [ ! -z "$ES_USER" ] || [ ! -z "$ES_GROUP" ]; then + echo "ES_USER and ES_GROUP settings are no longer supported. To run as a custom user/group use the archive distribution of Elasticsearch." + exit 1 +fi +<% end %> + +exec="$ES_HOME/bin/elasticsearch" +prog="elasticsearch" +pidfile="$PID_DIR/${prog}.pid" + +export ES_JAVA_OPTS +export JAVA_HOME +export ES_PATH_CONF +export ES_STARTUP_SLEEP_TIME + +lockfile=/var/lock/subsys/$prog + +if [ ! -x "$exec" ]; then + echo "The elasticsearch startup script does not exists or it is not executable, tried: $exec" + exit 1 +fi + +checkJava() { + if [ -x "$JAVA_HOME/bin/java" ]; then + JAVA="$JAVA_HOME/bin/java" + else + JAVA=`which java` + fi + + if [ ! -x "$JAVA" ]; then + echo "Could not find any executable java binary. Please install java in your PATH or set JAVA_HOME" + exit 1 + fi +} + +start() { + checkJava + [ -x $exec ] || exit 5 + + if [ -n "$MAX_OPEN_FILES" ]; then + ulimit -n $MAX_OPEN_FILES + fi + if [ -n "$MAX_LOCKED_MEMORY" ]; then + ulimit -l $MAX_LOCKED_MEMORY + fi + if [ -n "$MAX_MAP_COUNT" -a -f /proc/sys/vm/max_map_count ]; then + sysctl -q -w vm.max_map_count=$MAX_MAP_COUNT + fi + + # Ensure that the PID_DIR exists (it is cleaned at OS startup time) + if [ -n "$PID_DIR" ] && [ ! -e "$PID_DIR" ]; then + mkdir -p "$PID_DIR" && chown elasticsearch:elasticsearch "$PID_DIR" + fi + if [ -n "$pidfile" ] && [ ! -e "$pidfile" ]; then + touch "$pidfile" && chown elasticsearch:elasticsearch "$pidfile" + fi + + cd $ES_HOME + echo -n $"Starting $prog: " + # if not running, start it up here, usually something like "daemon $exec" + daemon --user elasticsearch --pidfile $pidfile $exec -p $pidfile -d + retval=$? + echo + [ $retval -eq 0 ] && touch $lockfile + return $retval +} + +stop() { + echo -n $"Stopping $prog: " + # stop it here, often "killproc $prog" + killproc -p $pidfile -d 86400 $prog + retval=$? + echo + [ $retval -eq 0 ] && rm -f $lockfile + return $retval +} + +restart() { + stop + start +} + +reload() { + restart +} + +force_reload() { + restart +} + +rh_status() { + # run checks to determine if the service is running or use generic status + status -p $pidfile $prog +} + +rh_status_q() { + rh_status >/dev/null 2>&1 +} + + +case "$1" in + start) + rh_status_q && exit 0 + $1 + ;; + stop) + rh_status_q || exit 0 + $1 + ;; + restart) + $1 + ;; + reload) + rh_status_q || exit 7 + $1 + ;; + force-reload) + force_reload + ;; + status) + rh_status + ;; + condrestart|try-restart) + rh_status_q || exit 0 + restart + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}" + exit 2 +esac +exit $? diff --git a/cookbooks/elasticsearch/templates/ubuntu/initscript.erb b/cookbooks/elasticsearch/templates/ubuntu/initscript.erb new file mode 100755 index 0000000..c149ebb --- /dev/null +++ b/cookbooks/elasticsearch/templates/ubuntu/initscript.erb @@ -0,0 +1,187 @@ +#!/bin/bash +# +# /etc/init.d/<%= @program_name %> -- startup script for Elasticsearch +# +### BEGIN INIT INFO +# Provides: <%= @program_name %> +# Required-Start: $network $remote_fs $named +# Required-Stop: $network $remote_fs $named +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Starts elasticsearch +# Description: Starts elasticsearch using start-stop-daemon +### END INIT INFO + +PATH=/bin:/usr/bin:/sbin:/usr/sbin +NAME=<%= @program_name %> +DESC="Elasticsearch Server" +DEFAULT=/etc/default/$NAME + +if [ `id -u` -ne 0 ]; then + echo "You need root privileges to run this script" + exit 1 +fi + + +. /lib/lsb/init-functions + +if [ -r /etc/default/rcS ]; then + . /etc/default/rcS +fi + + +# The following variables can be overwritten in $DEFAULT + +# Directory where the Elasticsearch binary distribution resides +ES_HOME=/usr/share/$NAME + +# Additional Java OPTS +#ES_JAVA_OPTS= + +# Maximum number of open files +MAX_OPEN_FILES=65536 + +# Maximum amount of locked memory +#MAX_LOCKED_MEMORY= + +# Elasticsearch configuration directory +ES_PATH_CONF=/etc/$NAME + +# Maximum number of VMA (Virtual Memory Areas) a process can own +MAX_MAP_COUNT=262144 + +# Elasticsearch PID file directory +PID_DIR="/var/run/elasticsearch" + +# End of variables that can be overwritten in $DEFAULT + +# overwrite settings from default file +if [ -f "$DEFAULT" ]; then + . "$DEFAULT" +fi + +<% if @install_type != 'tarball' %> +# ES_USER and ES_GROUP settings were removed +if [ ! -z "$ES_USER" ] || [ ! -z "$ES_GROUP" ]; then + echo "ES_USER and ES_GROUP settings are no longer supported. To run as a custom user/group use the archive distribution of Elasticsearch." + exit 1 +fi +<% end %> + +# Define other required variables +PID_FILE="$PID_DIR/$NAME.pid" +DAEMON=$ES_HOME/bin/elasticsearch +DAEMON_OPTS="-d -p $PID_FILE" + +export ES_JAVA_OPTS +export JAVA_HOME +export ES_PATH_CONF + +if [ ! -x "$DAEMON" ]; then + echo "The elasticsearch startup script does not exists or it is not executable, tried: $DAEMON" + exit 1 +fi + +checkJava() { + if [ -x "$JAVA_HOME/bin/java" ]; then + JAVA="$JAVA_HOME/bin/java" + else + JAVA=`which java` + fi + + if [ ! -x "$JAVA" ]; then + echo "Could not find any executable java binary. Please install java in your PATH or set JAVA_HOME" + exit 1 + fi +} + +case "$1" in + start) + checkJava + + log_daemon_msg "Starting $DESC" + + pid=`pidofproc -p $PID_FILE elasticsearch` + if [ -n "$pid" ] ; then + log_begin_msg "Already running." + log_end_msg 0 + exit 0 + fi + + # Ensure that the PID_DIR exists (it is cleaned at OS startup time) + if [ -n "$PID_DIR" ] && [ ! -e "$PID_DIR" ]; then + mkdir -p "$PID_DIR" && chown elasticsearch:elasticsearch "$PID_DIR" + fi + if [ -n "$PID_FILE" ] && [ ! -e "$PID_FILE" ]; then + touch "$PID_FILE" && chown elasticsearch:elasticsearch "$PID_FILE" + fi + + if [ -n "$MAX_OPEN_FILES" ]; then + ulimit -n $MAX_OPEN_FILES + fi + + if [ -n "$MAX_LOCKED_MEMORY" ]; then + ulimit -l $MAX_LOCKED_MEMORY + fi + + if [ -n "$MAX_MAP_COUNT" -a -f /proc/sys/vm/max_map_count ]; then + sysctl -q -w vm.max_map_count=$MAX_MAP_COUNT + fi + + # Start Daemon + start-stop-daemon -d $ES_HOME --start --user elasticsearch -c elasticsearch --pidfile "$PID_FILE" --exec $DAEMON -- $DAEMON_OPTS + return=$? + if [ $return -eq 0 ]; then + i=0 + timeout=10 + # Wait for the process to be properly started before exiting + until { kill -0 `cat "$PID_FILE"`; } >/dev/null 2>&1 + do + sleep 1 + i=$(($i + 1)) + if [ $i -gt $timeout ]; then + log_end_msg 1 + exit 1 + fi + done + fi + log_end_msg $return + exit $return + ;; + stop) + log_daemon_msg "Stopping $DESC" + + if [ -f "$PID_FILE" ]; then + start-stop-daemon --stop --pidfile "$PID_FILE" \ + --user elasticsearch \ + --quiet \ + --retry forever/TERM/20 > /dev/null + if [ $? -eq 1 ]; then + log_progress_msg "$DESC is not running but pid file exists, cleaning up" + elif [ $? -eq 3 ]; then + PID="`cat $PID_FILE`" + log_failure_msg "Failed to stop $DESC (pid $PID)" + exit 1 + fi + rm -f "$PID_FILE" + else + log_progress_msg "(not running)" + fi + log_end_msg 0 + ;; + status) + status_of_proc -p $PID_FILE elasticsearch elasticsearch && exit 0 || exit $? + ;; + restart|force-reload) + if [ -f "$PID_FILE" ]; then + $0 stop + fi + $0 start + ;; + *) + log_success_msg "Usage: $0 {start|stop|restart|force-reload|status}" + exit 1 + ;; +esac + +exit 0 diff --git a/cookbooks/firewall/.foodcritic b/cookbooks/firewall/.foodcritic new file mode 100644 index 0000000..b56b353 --- /dev/null +++ b/cookbooks/firewall/.foodcritic @@ -0,0 +1,3 @@ +~FC001 +~FC057 +~FC019 diff --git a/cookbooks/firewall/CHANGELOG.md b/cookbooks/firewall/CHANGELOG.md new file mode 100644 index 0000000..92cd7f7 --- /dev/null +++ b/cookbooks/firewall/CHANGELOG.md @@ -0,0 +1,291 @@ +firewall Cookbook CHANGELOG +======================= +This file is used to list changes made in each version of the firewall cookbook. + +## 2.6.5 (2018-07-24) + +- use platform_family instead of platform to include all rhels + +v2.6.4 (2018-07-01) +------------------- +* Stop including chef-sugar when it's >= 4.0.0 (#197) + +v2.6.3 (2018-02-01) +------------------- +* Fix issue with deep merging of hashes and arrays in recent chef release (#185) + +v2.6.2 (2017-06-01) +------------------- +* Incorrect file checking on Ubuntu, double file write (#173) +* Added testing on CentOS 6.9 +* Clarify metadata that we're not working on Amazon Linux (#172) + +v2.6.1 (2017-04-21) +------------------- +* Add recipe to disable firewall (#164) + +v2.6.0 (2017-04-17) +------------------- +* Initial Chef 13.x support (#160, #159) +* Allow loopback and icmp, when enabled (#161) +* Address various newer rubocop and foodcritic complaints +* Convert rule provider away from DSL (#159) + +v2.5.4 (2017-02-13) +------------------- +* Update Test Kitchen platforms to the latest +* Update copyright headers +* Allow package options to be passed through to the package install for firewall +* Define policy for Windows Firewall and use the attributes to set desired policy + +v2.5.3 (2016-10-26) +------------------- +* Don't show firewall resource as updated (#133) +* Add :off as a valid logging level (#129) +* Add support for Ubuntu 16.04 (#149) + +v2.5.2 (2016-06-02) +------------------- +* Don't issue commands when firewalld isn't active (#140) +* Install iptables-services on CentOS >= 7 (#131) +* Update Ruby version on Travis for listen gem + +v2.5.1 (2016-05-31) +------------------- +* Protocol guard incorrectly prevents "none" protocol type on UFW helper (#128) +* Fix wrongly ordered conditional for converting ports to strings using port_to_s +* Fix notify_firewall attribute crashing firewall_rule provider (#130) +* Add warning if firewall rule opens all traffic (#132) +* Add ipv6 attribute respect to Ubuntu iptables (#138) + +v2.5.0 (2016-03-08) +------------------- +* Don't modify parameter for port (#120) +* Remove a reference to the wrong variable name under windows (#123) +* Add support for mobile shell default firewall rule (#121) +* New rubocop rules and style fixes +* Correct a README.md example for `action :allow` + +v2.4.0 (2016-01-28) +------------------- +* Expose default iptables ruleset so that raw rules can be used in conjunction +with rulesets for other tables (#101). + +v2.3.1 (2016-01-08) +------------------- +* Add raw rule support to the ufw firewall provider (#113). + +v2.3.0 (2015-12-23) +------------------- +* Refactor logic so that firewall rules don't add a string rule to the firewall +when their actions run. Just run the action once on the firewall itself. This is +designed to prevent partial application of rules (#106) + +* Switch to "enabled" (positive logic) instead of "disabled" (negative logic) on +the firewall resource. It was difficult to reason with "disabled false" for some +complicated recipes using firewall downstream. `disabled` is now deprecated. + +* Add proper Windows testing and serverspec tests back into this cookbook. + +* Fix the `port_to_s` function so it also works for Windows (#111) + +* Fix typo checking action instead of command in iptables helper (#112) + +* Remove testing ranges of ports on CentOS 5.x, as it's broken there. + +v2.2.0 (2015-11-02) +------------------- +Added permanent as default option for RHEL 7 based systems using firewall-cmd. +This defaults to turned off, but it will be enabled by default on the next major version bump. + +v2.1.0 (2015-10-15) +------------------- +Minor feature release. +* Ensure ICMPv6 is open when `['firewall']['allow_established']` is set to true (the default). ICMPv6 is critical for most IPv6 operations. + +v2.0.5 (2015-10-05) +------------------- +Minor bugfix release. +* Ensure provider filtering always yields 1 and only 1 provider, #97 & #98 +* Documentation update #96 + +v2.0.4 (2015-09-23) +------------------- +Minor bugfix release. +* Allow override of filter chain policies, #94 +* Fix foodcrtitic and chefspec errors + +v2.0.3 (2015-09-14) +------------------- +Minor bugfix release. +* Fix wrong conditional for firewalld ports, #93 +* Fix ipv6 command logic under iptables, #91 + +v2.0.2 (2015-09-08) +------------------- +* Release with working CI, Chefspec matchers. + +v2.0.1 (2015-09-01) +------------------- +* Add default related/established rule for iptables + +v2.0.0 (2015-08-31) +------------------- +* #84, major rewrite: + - Allow relative positioning of rules + - Use delayed notifications to create one firewall ruleset instead of incremental changes + - Remove poise dependency +* #82 - Introduce Windows firewall support and test-kitchen platform. +* #73 - Add the option to disable ipv6 commands on iptables +* #78 - Use Chef-12 style `provides` to address provider mapping issues +* Rubocop and foodcritic cleanup + +v1.6.1 (2015-07-24) +------------------- +* #80 - Remove an extra space in port range + +v1.6.0 (2015-07-15) +------------------- +* #68 - Install firewalld when it does not exist +* #72 - Fix symbol that was a string, breaking comparisons + +v1.5.2 (2015-07-15) +------------------- +* #75 - Use correct service in iptables save action, Add serverspec tests for iptables suite + +v1.5.1 (2015-07-13) +------------------- +* #74 - add :save matcher for Chefspec + +v1.5.0 (2015-07-06) +------------------- + +* #70 - Add chef service resource to ensure firewall-related services are enabled/disabled +* - Add testing and support for iptables on ubuntu in iptables provider + +v1.4.0 (2015-06-30) +------------------- + +* #69 - Support for CentOS/RHEL 5.x + +v1.3.0 (2015-06-09) +------------------- +* #63 - Add support for protocol numbers + +v1.2.0 (2015-05-28) +------------------- +* #64 - Support the newer version of poise + +v1.1.2 (2015-05-19) +------------------- +* #60 - Always add /32 or /128 to ipv4 or ipv6 addresses, respectively. + - Make comment quoting optional; iptables on Ubuntu strips quotes on strings without any spaces + +v1.1.1 (2015-05-11) +------------------- +* #57 - Suppress warning: already initialized constant XXX while Chefspec + +v1.1.0 (2015-04-27) +------------------- +* #56 - Better ipv6 support for firewalld and iptables +* #54 - Document raw parameter + +v1.0.2 (2015-04-03) +------------------- +* #52 - Typo in :masquerade action name + +v1.0.1 (2015-03-28) +------------------- +* #49 - Fix position attribute of firewall_rule providers to be correctly used as a string in commands + +v1.0.0 (2015-03-25) +------------------- +* Major upgrade and rewrite as HWRP using poise +* Adds support for iptables and firewalld +* Modernize tests and other files +* Fix many bugs from ufw defaults to multiport suppot + +v0.11.8 (2014-05-20) +-------------------- +* Corrects issue where on a secondary converge would not distinguish between inbound and outbound rules + + +v0.11.6 (2014-02-28) +-------------------- +[COOK-4385] - UFW provider is broken + + +v0.11.4 (2014-02-25) +-------------------- +[COOK-4140] Only notify when a rule is actually added + + +v0.11.2 +------- +### Bug +- **[COOK-3615](https://tickets.opscode.com/browse/COOK-3615)** - Install required UFW package on Debian + +v0.11.0 +------- +### Improvement +- [COOK-2932]: ufw providers work on debian but cannot be used + +v0.10.2 +------- +- [COOK-2250] - improve readme + +v0.10.0 +------ +- [COOK-1234] - allow multiple ports per rule + +v0.9.2 +------ +- [COOK-1615] - Firewall example docs have incorrect direction syntax + +v0.9.0 +------ +The default action for firewall LWRP is now :enable, the default action for firewall_rule LWRP is now :reject. This is in line with a "default deny" policy. + +- [COOK-1429] - resolve foodcritic warnings + +v0.8.0 +------ +- refactor all resources and providers into LWRPs +- removed :reset action from firewall resource (couldn't find a good way to make it idempotent) +- removed :logging action from firewall resource...just set desired level via the log_level attribute + +v0.6.0 +------ +- [COOK-725] Firewall cookbook firewall_rule LWRP needs to support logging attribute. +- Firewall cookbook firewall LWRP needs to support :logging + +v0.5.7 +------ +- [COOK-696] Firewall cookbook firewall_rule LWRP needs to support interface +- [COOK-697] Firewall cookbook firewall_rule LWRP needs to support the direction for the rules + +v0.5.6 +------ +- [COOK-695] Firewall cookbook firewall_rule LWRP needs to support destination port + +v0.5.5 +------ +- [COOK-709] fixed :nothing action for the 'firewall_rule' resource. + +v0.5.4 +------ +- [COOK-694] added :reject action to the 'firewall_rule' resource. + +v0.5.3 +------ +- [COOK-698] added :reset action to the 'firewall' resource. + +v0.5.2 +------ +- Add missing 'requires' statements. fixes 'NameError: uninitialized constant' error. +thanks to Ernad Husremović for the fix. + +v0.5.0 +------ +- [COOK-686] create firewall and firewall_rule resources +- [COOK-687] create UFW providers for all resources diff --git a/cookbooks/firewall/CONTRIBUTING.md b/cookbooks/firewall/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/firewall/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/cookbooks/firewall/MAINTAINERS.md b/cookbooks/firewall/MAINTAINERS.md new file mode 100644 index 0000000..5db5fac --- /dev/null +++ b/cookbooks/firewall/MAINTAINERS.md @@ -0,0 +1,19 @@ + + +# Maintainers +This file lists how this cookbook project is maintained. When making changes to the system, this +file tells you who needs to review your patch - you need a simple majority of maintainers +for the relevant subsystems to provide a :+1: on your pull request. Additionally, you need +to not receive a veto from a Lieutenant or the Project Lead. + +Check out [How Cookbooks are Maintained](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD) +for details on the process and how to become a maintainer or the project lead. + +# Project Maintainer +* [Martin Smith](https://github.com/martinb3) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) +* [Martin Smith](https://github.com/martinb3) diff --git a/cookbooks/firewall/README.md b/cookbooks/firewall/README.md new file mode 100644 index 0000000..4a12805 --- /dev/null +++ b/cookbooks/firewall/README.md @@ -0,0 +1,338 @@ +firewall Cookbook +================= + +[![Build Status](https://travis-ci.org/chef-cookbooks/firewall.svg?branch=master)](http://travis-ci.org/chef-cookbooks/firewall) +[![Cookbook Version](https://img.shields.io/cookbook/v/firewall.svg)](https://supermarket.chef.io/cookbooks/firewall) + +Provides a set of primitives for managing firewalls and associated rules. + +PLEASE NOTE - The resource/providers in this cookbook are under heavy development. An attempt is being made to keep the resource simple/stupid by starting with less sophisticated firewall implementations first and refactor/vet the resource definition with each successive provider. + +Requirements +------------ +**Chef 12.5.x+** is required. We are currently testing against Chef 13. If you need Chef 11 support, please try pinning back to a version less than 2.0, e.g.: +``` +depends 'firewall', '< 2.0' +``` + +### Supported firewalls and platforms +* UFW - Ubuntu, Debian +* IPTables - Red Hat & CentOS, Ubuntu +* FirewallD - Red Hat & CentOS >= 7.0 (IPv4 only support, [needs contributions/testing](https://github.com/chef-cookbooks/firewall/issues/86)) +* Windows Advanced Firewall - 2012 R2 + +Tested on: +* Ubuntu 14.04, 16.04 with iptables, ufw +* Debian 7, 8 with ufw +* CentOS 6 with iptables +* CentOS 7.1 with firewalld +* Windows Server 2012r2 with Windows Advanced Firewall + +By default, Ubuntu chooses ufw. To switch to iptables, set this in an attribute file: +``` +default['firewall']['ubuntu_iptables'] = true +``` + +By default, Red Hat & CentOS >= 7.0 chooses firewalld. To switch to iptables, set this in an attribute file: +``` +default['firewall']['redhat7_iptables'] = true +``` + +# Considerations that apply to all firewall providers and resources + +This cookbook comes with two resources, firewall and firewall rule. The typical usage scenario is as follows: + +- run the `:install` action on the `firewall` resource named 'default', which installs appropriate packages and configures services to start on boot and starts them + +- run the `:create` action on every `firewall_rule` resource, which adds to the list of rules that should be configured on the firewall. `firewall_rule` then automatically sends a delayed notification to the `firewall['default']` resource to run the `:restart` action. + +- run the delayed notification with action `:restart` on the `firewall` resource. if any rules are different than the last run, the provider will update the current state of the firewall rules to match the expected rules. + +There is a fundamental mismatch between the idea of a chef action and the action that should be taken on a firewall rule. For this reason, the chef action for a firewall_rule may be `:nothing` (the rule should not be present in the firewall) or `:create` (the rule should be present in the firewall), but the action taken on a packet in a firewall (`DROP`, `ACCEPT`, etc) is denoted as a `command` parameter on the `firewall_rule` resource. + +# iptables considerations + +If you need to use a table other than `*filter`, the best way to do so is like so: +``` +node.default['firewall']['iptables']['defaults'][:ruleset] = { + '*filter' => 1, + ':INPUT DROP' => 2, + ':FORWARD DROP' => 3, + ':OUTPUT ACCEPT_FILTER' => 4, + 'COMMIT_FILTER' => 100, + '*nat' => 101, + ':PREROUTING DROP' => 102, + ':POSTROUTING DROP' => 103, + ':OUTPUT ACCEPT_NAT' => 104, + 'COMMIT_NAT' => 200 +} +``` + +Note -- in order to support multiple hash keys containing the same rule, anything found after the underscore will be stripped for: `:OUTPUT :INPUT :POSTROUTING :PREROUTING COMMIT`. This allows an example like the above to be reduced to just repeated lines of `COMMIT` and `:OUTPUT ACCEPT` while still avoiding duplication of other things. + +Then it's trivial to add additional rules to the `*nat` table using the raw parameter: +``` +firewall_rule "postroute" do + raw "-A POSTROUTING -o eth1 -p tcp -d 172.28.128.21 -j SNAT --to-source 172.28.128.6" + position 150 +end +``` + +Note that any line starting with `COMMIT` will become just `COMMIT`, as hash +keys must be unique but we need multiple commit lines. + +# Recipes + +### default +The default recipe creates a firewall resource with action install. + +### disable_firewall +Used to disable platform specific firewall. Many clouds have their own firewall configured outside of the OS instance such as AWS Security Groups. + +# Attributes + +* `default['firewall']['allow_ssh'] = false`, set true to open port 22 for SSH when the default recipe runs +* `default['firewall']['allow_mosh'] = false`, set to true to open UDP ports 60000 - 61000 for [Mosh][0] when the default recipe runs +* `default['firewall']['allow_winrm'] = false`, set true to open port 5989 for WinRM when the default recipe runs +* `default['firewall']['allow_loopback'] = false`, set to true to allow all traffic on the loopback interface +* `default['firewall']['allow_icmp'] = false`, set true to allow icmp protocol on supported OSes (note: ufw and windows implementations don't support this) + +* `default['firewall']['ubuntu_iptables'] = false`, set to true to use iptables on Ubuntu / Debian when using the default recipe +* `default['firewall']['redhat7_iptables'] = false`, set to true to use iptables on Red Hat / CentOS 7 when using the default recipe + +* `default['firewall']['ufw']['defaults']` hash for template `/etc/default/ufw` +* `default['firewall']['iptables']['defaults']` hash for default policies for 'filter' table's chains` + +* `default['firewall']['windows']['defaults']` hash to define inbound / outbound firewall policy on Windows platform + +* `default['firewall']['allow_established'] = true`, set to false if you don't want a related/established default rule on iptables +* `default['firewall']['ipv6_enabled'] = true`, set to false if you don't want IPv6 related/established default rule on iptables (this enables ICMPv6, which is required for much of IPv6 communication) + +* `default['firewall']['firewalld']['permanent'] = false`, set to true if you want firewalld rules to be added with `--permanent` so they survive a reboot. This will be changed to `true` by default in a future major version release. + +# Resources + +### firewall + +***NB***: The name 'default' of this resource is important as it is used for firewall_rule providers to locate the firewall resource. If you change it, you must also supply the same value to any firewall_rule resources using the `firewall_name` parameter. + +#### Actions +- `:install` (*default action*): Install and Enable the firewall. This will ensure the appropriate packages are installed and that any services have been started. +- `:disable`: Disable the firewall. Drop any rules and put the node in an unprotected state. Flush all current rules. Also erase any internal state used to detect when rules should be applied. +- `:flush`: Flush all current rules. Also erase any internal state used to detect when rules should be applied. +- `:save`: Ensure all rules are added permanently under firewalld using `--permanent`. Not supported on ufw, iptables. You must notify this action at the end of the chef run if you want permanent firewalld rules (they are not persistent by default). + +#### Parameters + +- `disabled` (default to `false`): If set to true, all actions will no-op on this resource. This is a way to prevent included cookbooks from configuring a firewall. +- `ipv6_enabled` (default to `true`): If set to false, firewall will not perform any ipv6 related work. Currently only supported in iptables. +- `log_level`: UFW only. Level of verbosity the firewall should log at. valid values are: :low, :medium, :high, :full, :off. default is :low. +- `rules`: This is used internally for firewall_rule resources to append their rules. You should NOT touch this value unless you plan to supply an entire firewall ruleset at once, and skip using firewall_rule resources. +- `disabled_zone` (firewalld only): The zone to set on firewalld when the firewall should be disabled. Can be any string in symbol form, e.g. :public, :drop, etc. Defaults to `:public.` +- `enabled_zone` (firewalld only): The zone to set on firewalld when the firewall should be enabled. Can be any string in symbol form, e.g. :public, :drop, etc. Defaults to `:drop.` +- `package_options`: Used to pass options to the package install of firewall + +#### Examples + +```ruby +# all defaults +firewall 'default' + +# enable platform default firewall +firewall 'default' do + action :install +end + +# increase logging past default of 'low' +firewall 'default' do + log_level :high + action :install +end +``` + +### firewall_rule + +#### Actions +- `:create` (_default action_): If a firewall_rule runs this action, the rule will be recorded in a chef resource's internal state, and applied when providers automatically notify the firewall resource with action `:reload`. The notification happens automatically. + +#### Parameters + +- `firewall_name`: the matching firewall resource that this rule applies to. Default value: `default` + +- `raw`: Used to pass an entire rule as a string, omitting all other parameters. This line will be directly loaded by `iptables-restore`, fed directly into `ufw` on the command line, or run using `firewall-cmd`. + +- `description` (_default: same as rule name_): Used to provide a comment that will be included when adding the firewall rule. + +- `include_comment` (_default: true_): Used to optionally exclude the comment in the rule. + +- `position` (_default: 50_): **relative** position to insert rule at. Position may be any integer between 0 < n < 100 (exclusive), and more than one rule may specify the same position. + +- `command`: What action to take on a particular packet + + - `:allow` (_default action_): the rule should allow matching packets + - `:deny`: the rule should deny matching packets + - `:reject`: the rule should reject matching packets + - `:masqerade`: Masquerade the matching packets + - `:redirect`: Redirect the matching packets + - `:log`: Configure logging + +- `stateful`: a symbol or array of symbols, such as ``[:related, :established]` that will be passed to the state module in iptables or firewalld. + +- `protocol`: `:tcp` (_default_), `:udp`, `:icmp`, `:none` or protocol number. Using protocol numbers is not supported using the ufw provider (default for debian/ubuntu systems). + +- `direction`: For ufw, direction of the rule. valid values are: `:in` (_default_), `:out`, `:pre`, `:post`. + +- `source` (_Default is `0.0.0.0/0` or `Anywhere`_): source ip address or subnet to filter. + +- `source_port` (_Default is nil_): source port for filtering packets. + +- `destination`: ip address or subnet to filter on packet destination, must be a valid IP + +- `port` or `dest_port`: target port number (ie. 22 to allow inbound SSH), or an array of incoming port numbers (ie. [80,443] to allow inbound HTTP & HTTPS). + + NOTE: `protocol` attribute is required with multiple ports, or a range of incoming port numbers (ie. 60000..61000 to allow inbound mobile-shell. NOTE: `protocol`, or an attribute is required with a range of ports. + +- `interface`: (source) interface to apply rule (ie. `eth0`). + +- `dest_interface`: interface where packets may be destined to go + +- `redirect_port`: redirected port for rules with command `:redirect` + +- `logging`: may be added to enable logging for a particular rule. valid values are: `:connections`, `:packets`. In the ufw provider, `:connections` logs new connections while `:packets` logs all packets. + +#### Examples + +```ruby +# open standard ssh port +firewall_rule 'ssh' do + port 22 + command :allow +end + +# open standard http port to tcp traffic only; insert as first rule +firewall_rule 'http' do + port 80 + protocol :tcp + position 1 + command :allow +end + +# restrict port 13579 to 10.0.111.0/24 on eth0 +firewall_rule 'myapplication' do + port 13579 + source '10.0.111.0/24' + direction :in + interface 'eth0' + command :allow +end + +# specify a protocol number (supported on centos/redhat) +firewall_rule 'vrrp' do + protocol 112 + command :allow +end + +# use the iptables provider to specify protocol number on debian/ubuntu +firewall_rule 'vrrp' do + provider Chef::Provider::FirewallRuleIptables + protocol 112 + command :allow +end + +# can use :raw command with UFW provider for VRRP +firewall_rule "VRRP" do + command :allow + raw "allow to 224.0.0.18" +end + +# open UDP ports 60000..61000 for mobile shell (mosh.mit.edu), note +# that the protocol attribute is required when using port_range +firewall_rule 'mosh' do + protocol :udp + port 60000..61000 + command :allow +end + +# open multiple ports for http/https, note that the protocol +# attribute is required when using ports +firewall_rule 'http/https' do + protocol :tcp + port [80, 443] + command :allow +end + +firewall 'default' do + enabled false + action :nothing +end +``` + +#### Providers + +- See `libraries/z_provider_mapping.rb` for a full list of providers for each platform and version. + +Different providers will determine the current state of the rules differently -- parsing the output of a command, maintaining the state in a file, or some other way. If the firewall is adjusted from outside of chef (non-idempotent), it's possible that chef may be caught unaware of the current state of the firewall. The best workaround is to add a `:flush` action to the firewall resource as early as possible in the chef run, if you plan to modify the firewall state outside of chef. + +# Troubleshooting + +To figure out what the position values are for current rules, print the hash that contains the weights: +``` +require pp +default_firewall = resources(:firewall, 'default') +pp default_firewall.rules +``` + +# Development +This section details "quick development" steps. For a detailed explanation, see [[Contributing.md]]. + +1. Clone this repository from GitHub: + + $ git clone git@github.com:chef-cookbooks/firewall.git + +2. Create a git branch + + $ git checkout -b my_bug_fix + +3. Install dependencies: + + $ bundle install + +4. Make your changes/patches/fixes, committing appropiately +5. **Write tests** +6. Run the tests: + - `bundle exec foodcritic -f any .` + - `bundle exec rspec` + - `bundle exec rubocop` + - `bundle exec kitchen test` + + In detail: + - Foodcritic will catch any Chef-specific style errors + - RSpec will run the unit tests + - Rubocop will check for Ruby-specific style errors + - Test Kitchen will run and converge the recipes + + +# License & Authors + +- Author:: Seth Chisamore () +- Author:: Ronald Doorn () +- Author:: Martin Smith () +- Author:: Sander van Harmelen () + +```text +Copyright:: 2011-2015, Chef Software, Inc + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` + +[0]: https://mosh.mit.edu/ diff --git a/cookbooks/firewall/attributes/default.rb b/cookbooks/firewall/attributes/default.rb new file mode 100644 index 0000000..7f72dcf --- /dev/null +++ b/cookbooks/firewall/attributes/default.rb @@ -0,0 +1,5 @@ +default['firewall']['allow_ssh'] = false +default['firewall']['allow_winrm'] = false +default['firewall']['allow_mosh'] = false +default['firewall']['allow_loopback'] = false +default['firewall']['allow_icmp'] = false diff --git a/cookbooks/firewall/attributes/firewalld.rb b/cookbooks/firewall/attributes/firewalld.rb new file mode 100644 index 0000000..bc26d60 --- /dev/null +++ b/cookbooks/firewall/attributes/firewalld.rb @@ -0,0 +1 @@ +default['firewall']['firewalld']['permanent'] = false diff --git a/cookbooks/firewall/attributes/iptables.rb b/cookbooks/firewall/attributes/iptables.rb new file mode 100644 index 0000000..f26ac55 --- /dev/null +++ b/cookbooks/firewall/attributes/iptables.rb @@ -0,0 +1,17 @@ +default['firewall']['iptables']['defaults'][:policy] = { + input: 'DROP', + forward: 'DROP', + output: 'ACCEPT', +} +default['firewall']['iptables']['defaults'][:ruleset] = { + '*filter' => 1, + ":INPUT #{node['firewall']['iptables']['defaults'][:policy][:input]}" => 2, + ":FORWARD #{node['firewall']['iptables']['defaults'][:policy][:forward]}" => 3, + ":OUTPUT #{node['firewall']['iptables']['defaults'][:policy][:output]}" => 4, + 'COMMIT_FILTER' => 100, +} + +default['firewall']['ubuntu_iptables'] = false +default['firewall']['redhat7_iptables'] = false +default['firewall']['allow_established'] = true +default['firewall']['ipv6_enabled'] = true diff --git a/cookbooks/firewall/attributes/ufw.rb b/cookbooks/firewall/attributes/ufw.rb new file mode 100644 index 0000000..35c8366 --- /dev/null +++ b/cookbooks/firewall/attributes/ufw.rb @@ -0,0 +1,12 @@ +default['firewall']['ufw']['defaults'] = { + ipv6: 'yes', + manage_builtins: 'no', + ipt_sysctl: '/etc/ufw/sysctl.conf', + ipt_modules: 'nf_conntrack_ftp nf_nat_ftp nf_conntrack_netbios_ns', + policy: { + input: 'DROP', + output: 'ACCEPT', + forward: 'DROP', + application: 'SKIP', + }, +} diff --git a/cookbooks/firewall/attributes/windows.rb b/cookbooks/firewall/attributes/windows.rb new file mode 100644 index 0000000..382dd82 --- /dev/null +++ b/cookbooks/firewall/attributes/windows.rb @@ -0,0 +1,8 @@ +# Windows platform defult settings: block undefined inbould traffic, allow all outgoing traffic + +default['firewall']['windows']['defaults'] = { + policy: { + input: 'blockinbound', + output: 'allowoutbound', + }, +} diff --git a/cookbooks/firewall/libraries/helpers.rb b/cookbooks/firewall/libraries/helpers.rb new file mode 100644 index 0000000..38a8fad --- /dev/null +++ b/cookbooks/firewall/libraries/helpers.rb @@ -0,0 +1,100 @@ +module FirewallCookbook + module Helpers + def dport_calc(new_resource) + new_resource.dest_port || new_resource.port + end + + def port_to_s(p) + if p.is_a?(String) + p + elsif p && p.is_a?(Integer) + p.to_s + elsif p && p.is_a?(Array) + p_strings = p.map { |o| port_to_s(o) } + p_strings.sort.join(',') + elsif p && p.is_a?(Range) + if platform_family?('windows') + "#{p.first}-#{p.last}" + else + "#{p.first}:#{p.last}" + end + end + end + + def ipv6_enabled?(new_resource) + new_resource.ipv6_enabled + end + + def disabled?(new_resource) + # if either flag is found in the non-default boolean state + disable_flag = !(new_resource.enabled && !new_resource.disabled) + + Chef::Log.warn("#{new_resource} has been disabled, not proceeding") if disable_flag + disable_flag + end + + def ip_with_mask(new_resource, ip) + if ip.include?('/') + ip + elsif ipv4_rule?(new_resource) + "#{ip}/32" + elsif ipv6_rule?(new_resource) + "#{ip}/128" + else + ip + end + end + + # ipv4-specific rule? + def ipv4_rule?(new_resource) + if (new_resource.source && IPAddr.new(new_resource.source).ipv4?) || + (new_resource.destination && IPAddr.new(new_resource.destination).ipv4?) + true + else + false + end + end + + # ipv6-specific rule? + def ipv6_rule?(new_resource) + if (new_resource.source && IPAddr.new(new_resource.source).ipv6?) || + (new_resource.destination && IPAddr.new(new_resource.destination).ipv6?) || + new_resource.protocol =~ /ipv6/ || + new_resource.protocol =~ /icmpv6/ + true + else + false + end + end + + def ubuntu?(current_node) + current_node['platform'] == 'ubuntu' + end + + def build_rule_file(rules) + contents = [] + sorted_values = rules.values.sort.uniq + sorted_values.each do |sorted_value| + contents << "# position #{sorted_value}" + rules.each do |k, v| + next unless v == sorted_value + + contents << if repeatable_directives(k) + k[/[^_]+/] + else + k + end + end + end + "#{contents.join("\n")}\n" + end + + def repeatable_directives(s) + %w(:OUTPUT :INPUT :POSTROUTING :PREROUTING COMMIT).each do |special| + return true if s.start_with?(special) + end + + false + end + end +end diff --git a/cookbooks/firewall/libraries/helpers_firewalld.rb b/cookbooks/firewall/libraries/helpers_firewalld.rb new file mode 100644 index 0000000..ceb8bd2 --- /dev/null +++ b/cookbooks/firewall/libraries/helpers_firewalld.rb @@ -0,0 +1,116 @@ +module FirewallCookbook + module Helpers + module Firewalld + include FirewallCookbook::Helpers + include Chef::Mixin::ShellOut + + def firewalld_rules_filename + '/etc/sysconfig/firewalld-chef.rules' + end + + def firewalld_rule!(cmd) + shell_out!(cmd, input: 'yes') + end + + def firewalld_active? + cmd = shell_out('firewall-cmd', '--state') + cmd.stdout =~ /^running$/ + end + + def firewalld_default_zone?(z) + return false unless firewalld_active? + + cmd = shell_out('firewall-cmd', '--get-default-zone') + cmd.stdout =~ /^#{z.to_s}$/ + end + + def firewalld_default_zone!(z) + raise 'firewalld not active' unless firewalld_active? + + shell_out!('firewall-cmd', "--set-default-zone=#{z}") + end + + def log_current_firewalld + shell_out!('firewall-cmd --direct --get-all-rules') + end + + def firewalld_flush! + raise 'firewall not active' unless firewalld_active? + + shell_out!('firewall-cmd', '--direct', '--remove-rules', 'ipv4', 'filter', 'INPUT') + shell_out!('firewall-cmd', '--direct', '--remove-rules', 'ipv4', 'filter', 'OUTPUT') + shell_out!('firewall-cmd', '--direct', '--permanent', '--remove-rules', 'ipv4', 'filter', 'INPUT') + shell_out!('firewall-cmd', '--direct', '--permanent', '--remove-rules', 'ipv4', 'filter', 'OUTPUT') + end + + def firewalld_all_rules_permanent! + raise 'firewall not active' unless firewalld_active? + + rules = shell_out!('firewall-cmd', '--direct', '--get-all-rules').stdout + perm_rules = shell_out!('firewall-cmd', '--direct', '--permanent', '--get-all-rules').stdout + rules == perm_rules + end + + def firewalld_save! + raise 'firewall not active' unless firewalld_active? + + shell_out!('firewall-cmd', '--direct', '--permanent', '--remove-rules', 'ipv4', 'filter', 'INPUT') + shell_out!('firewall-cmd', '--direct', '--permanent', '--remove-rules', 'ipv4', 'filter', 'OUTPUT') + shell_out!('firewall-cmd', '--direct', '--get-all-rules').stdout.lines do |line| + shell_out!("firewall-cmd --direct --permanent --add-rule #{line}") + end + end + + def ip_versions(resource) + if ipv4_rule?(resource) + %w(ipv4) + elsif ipv6_rule?(resource) + %w(ipv6) + else # no source or destination address, add rules for both ipv4 and ipv6 + %w(ipv4 ipv6) + end + end + + CHAIN = { in: 'INPUT', out: 'OUTPUT', pre: 'PREROUTING', post: 'POSTROUTING' }.freeze unless defined? CHAIN # , nil => "FORWARD"} + TARGET = { allow: 'ACCEPT', reject: 'REJECT', deny: 'DROP', masquerade: 'MASQUERADE', redirect: 'REDIRECT', log: 'LOG --log-prefix \'iptables: \' --log-level 7' }.freeze unless defined? TARGET + + def build_firewall_rule(new_resource, ip_version = 'ipv4') + return new_resource.raw.strip if new_resource.raw + + type = new_resource.command + firewall_rule = if new_resource.direction + "#{ip_version} filter #{CHAIN[new_resource.direction.to_sym]} " + else + "#{ip_version} filter FORWARD " + end + firewall_rule << "#{new_resource.position} " + + if [:pre, :post].include?(new_resource.direction) + firewall_rule << '-t nat ' + end + + # Firewalld order of prameters is important here see example output below: + # ipv4 filter INPUT 1 -s 1.2.3.4/32 -d 5.6.7.8/32 -i lo -p tcp -m tcp -m state --state NEW -m comment --comment "hello" -j DROP + firewall_rule << "-s #{ip_with_mask(new_resource, new_resource.source)} " if new_resource.source && new_resource.source != '0.0.0.0/0' + firewall_rule << "-d #{new_resource.destination} " if new_resource.destination + + firewall_rule << "-i #{new_resource.interface} " if new_resource.interface + firewall_rule << "-o #{new_resource.dest_interface} " if new_resource.dest_interface + + firewall_rule << "-p #{new_resource.protocol} " if new_resource.protocol && new_resource.protocol.to_s.to_sym != :none + firewall_rule << '-m tcp ' if new_resource.protocol && new_resource.protocol.to_s.to_sym == :tcp + + # using multiport here allows us to simplify our greps and rule building + firewall_rule << "-m multiport --sports #{port_to_s(new_resource.source_port)} " if new_resource.source_port + firewall_rule << "-m multiport --dports #{port_to_s(dport_calc(new_resource))} " if dport_calc(new_resource) + + firewall_rule << "-m state --state #{new_resource.stateful.is_a?(Array) ? new_resource.stateful.join(',').upcase : new_resource.stateful.to_s.upcase} " if new_resource.stateful + firewall_rule << "-m comment --comment '#{new_resource.description}' " if new_resource.include_comment + firewall_rule << "-j #{TARGET[type]} " + firewall_rule << "--to-ports #{new_resource.redirect_port} " if type == :redirect + firewall_rule.strip! + firewall_rule + end + end + end +end diff --git a/cookbooks/firewall/libraries/helpers_iptables.rb b/cookbooks/firewall/libraries/helpers_iptables.rb new file mode 100644 index 0000000..9f6ea49 --- /dev/null +++ b/cookbooks/firewall/libraries/helpers_iptables.rb @@ -0,0 +1,112 @@ +module FirewallCookbook + module Helpers + module Iptables + include FirewallCookbook::Helpers + include Chef::Mixin::ShellOut + + CHAIN = { in: 'INPUT', out: 'OUTPUT', pre: 'PREROUTING', post: 'POSTROUTING' }.freeze unless defined? CHAIN # , nil => "FORWARD"} + TARGET = { allow: 'ACCEPT', reject: 'REJECT', deny: 'DROP', masquerade: 'MASQUERADE', redirect: 'REDIRECT', log: 'LOG --log-prefix "iptables: " --log-level 7' }.freeze unless defined? TARGET + + def build_firewall_rule(current_node, rule_resource, ipv6 = false) + el5 = current_node['platform_family'] == 'rhel' && Gem::Dependency.new('', '~> 5.0').match?('', current_node['platform_version']) + + return rule_resource.raw.strip if rule_resource.raw + firewall_rule = if rule_resource.direction + "-A #{CHAIN[rule_resource.direction.to_sym]} " + else + '-A FORWARD ' + end + + if [:pre, :post].include?(rule_resource.direction) + firewall_rule << '-t nat ' + end + + # Iptables order of prameters is important here see example output below: + # -A INPUT -s 1.2.3.4/32 -d 5.6.7.8/32 -i lo -p tcp -m tcp -m state --state NEW -m comment --comment "hello" -j DROP + firewall_rule << "-s #{ip_with_mask(rule_resource, rule_resource.source)} " if rule_resource.source && rule_resource.source != '0.0.0.0/0' + firewall_rule << "-d #{rule_resource.destination} " if rule_resource.destination + + firewall_rule << "-i #{rule_resource.interface} " if rule_resource.interface + firewall_rule << "-o #{rule_resource.dest_interface} " if rule_resource.dest_interface + + firewall_rule << "-p #{rule_resource.protocol} " if rule_resource.protocol && rule_resource.protocol.to_s.to_sym != :none + firewall_rule << '-m tcp ' if rule_resource.protocol && rule_resource.protocol.to_s.to_sym == :tcp + + # using multiport here allows us to simplify our greps and rule building + firewall_rule << "-m multiport --sports #{port_to_s(rule_resource.source_port)} " if rule_resource.source_port + firewall_rule << "-m multiport --dports #{port_to_s(dport_calc(rule_resource))} " if dport_calc(rule_resource) + + firewall_rule << "-m state --state #{rule_resource.stateful.is_a?(Array) ? rule_resource.stateful.join(',').upcase : rule_resource.stateful.upcase} " if rule_resource.stateful + # the comments extension is not available for ip6tables on rhel/centos 5 + unless el5 && ipv6 + firewall_rule << "-m comment --comment \"#{rule_resource.description}\" " if rule_resource.include_comment + end + + firewall_rule << "-j #{TARGET[rule_resource.command.to_sym]} " + firewall_rule << "--to-ports #{rule_resource.redirect_port} " if rule_resource.command == :redirect + firewall_rule.strip! + firewall_rule + end + + def iptables_packages(new_resource) + packages = if ipv6_enabled?(new_resource) + %w(iptables iptables-ipv6) + else + %w(iptables) + end + + # centos 7 requires extra service + if !ubuntu?(node) && node['platform_version'].to_i >= 7 + packages << %w(iptables-services) + end + + packages.flatten + end + + def iptables_commands(new_resource) + if ipv6_enabled?(new_resource) + %w(iptables ip6tables) + else + %w(iptables) + end + end + + def log_iptables(new_resource) + iptables_commands(new_resource).each do |cmd| + shell_out!("#{cmd} -L -n") + end + rescue + Chef::Log.info('log_iptables failed!') + end + + def iptables_flush!(new_resource) + iptables_commands(new_resource).each do |cmd| + shell_out!("#{cmd} -F") + end + end + + def iptables_default_allow!(new_resource) + iptables_commands(new_resource).each do |cmd| + shell_out!("#{cmd} -P INPUT ACCEPT") + shell_out!("#{cmd} -P OUTPUT ACCEPT") + shell_out!("#{cmd} -P FORWARD ACCEPT") + end + end + + def default_ruleset(current_node) + current_node['firewall']['iptables']['defaults'][:ruleset].to_h + end + + def ensure_default_rules_exist(current_node, new_resource) + input = new_resource.rules + + # don't use iptables_commands here since we do populate the + # hash regardless of ipv6 status + %w(iptables ip6tables).each do |name| + input[name] = {} unless input[name] + input[name].merge!(default_ruleset(current_node).to_h) + end + end + end + end +end diff --git a/cookbooks/firewall/libraries/helpers_ufw.rb b/cookbooks/firewall/libraries/helpers_ufw.rb new file mode 100644 index 0000000..9e035c5 --- /dev/null +++ b/cookbooks/firewall/libraries/helpers_ufw.rb @@ -0,0 +1,135 @@ +module FirewallCookbook + module Helpers + module Ufw + include FirewallCookbook::Helpers + include Chef::Mixin::ShellOut + + def ufw_rules_filename + '/etc/default/ufw-chef.rules' + end + + def ufw_active? + cmd = shell_out!('ufw', 'status') + cmd.stdout =~ /^Status:\sactive/ + end + + def ufw_disable! + shell_out!('ufw', 'disable', input: 'yes') + end + + def ufw_enable! + shell_out!('ufw', 'enable', input: 'yes') + end + + def ufw_reset! + shell_out!('ufw', 'reset', input: 'yes') + end + + def ufw_logging!(param) + shell_out!('ufw', 'logging', param.to_s) + end + + def ufw_rule!(cmd) + shell_out!(cmd, input: 'yes') + end + + def build_rule(new_resource) + Chef::Log.info("#{new_resource.name} apply_rule #{new_resource.command}") + + # if we don't do this, we may see some bugs where traffic is opened on all ports to all hosts when only RELATED,ESTABLISHED was intended + if new_resource.stateful + msg = '' + msg << "firewall_rule[#{new_resource.name}] was asked to " + msg << "#{new_resource.command} a stateful rule using #{new_resource.stateful} " + msg << 'but ufw does not support this kind of rule. Consider guarding by platform_family.' + raise msg + end + + # if we don't do this, ufw will fail as it does not support protocol numbers, so we'll only allow it to run if specifying icmp/tcp/udp protocol types + if new_resource.protocol && !new_resource.protocol.to_s.downcase.match('^(tcp|udp|esp|ah|ipv6|none)$') + msg = '' + msg << "firewall_rule[#{new_resource.name}] was asked to " + msg << "#{new_resource.command} a rule using protocol #{new_resource.protocol} " + msg << 'but ufw does not support this kind of rule. Consider guarding by platform_family.' + raise msg + end + + # some examples: + # ufw allow from 192.168.0.4 to any port 22 + # ufw deny proto tcp from 10.0.0.0/8 to 192.168.0.1 port 25 + # ufw insert 1 allow proto tcp from 0.0.0.0/0 to 192.168.0.1 port 25 + + if new_resource.raw + "ufw #{new_resource.raw.strip}" + else + "ufw #{rule(new_resource)}" + end + end + + def rule(new_resource) + rule = '' + rule << "#{new_resource.command} " + rule << rule_interface(new_resource) + rule << rule_logging(new_resource) + rule << rule_proto(new_resource) + rule << rule_dest_port(new_resource) + rule << rule_source_port(new_resource) + rule = rule.strip + + if rule == 'ufw allow in proto tcp to any from any' + Chef::Log.warn("firewall_rule[#{new_resource.name}] produced a rule that opens all traffic. This may be a logic error in your cookbook.") + end + + rule + end + + def rule_interface(new_resource) + rule = '' + rule << "#{new_resource.direction} " if new_resource.direction + rule << "on #{new_resource.interface} " if new_resource.interface && new_resource.direction + rule << "in on #{new_resource.interface} " if new_resource.interface && !new_resource.direction + rule + end + + def rule_proto(new_resource) + rule = '' + rule << "proto #{new_resource.protocol} " if new_resource.protocol && new_resource.protocol.to_s.to_sym != :none + rule + end + + def rule_dest_port(new_resource) + rule = if new_resource.destination + "to #{new_resource.destination} " + else + 'to any ' + end + rule << "port #{port_to_s(dport_calc(new_resource))} " if dport_calc(new_resource) + rule + end + + def rule_source_port(new_resource) + rule = if new_resource.source + "from #{new_resource.source} " + else + 'from any ' + end + + if new_resource.source_port + rule << "port #{port_to_s(new_resource.source_port)} " + end + rule + end + + def rule_logging(new_resource) + case new_resource.logging && new_resource.logging.to_sym + when :connections + 'log ' + when :packets + 'log-all ' + else + '' + end + end + end + end +end diff --git a/cookbooks/firewall/libraries/helpers_windows.rb b/cookbooks/firewall/libraries/helpers_windows.rb new file mode 100644 index 0000000..391581b --- /dev/null +++ b/cookbooks/firewall/libraries/helpers_windows.rb @@ -0,0 +1,130 @@ +module FirewallCookbook + module Helpers + module Windows + include FirewallCookbook::Helpers + include Chef::Mixin::ShellOut + + def fixup_cidr(str) + newstr = str.clone + newstr.gsub!('0.0.0.0/0', 'any') if newstr.include?('0.0.0.0/0') + newstr.gsub!('/0', '') if newstr.include?('/0') + newstr + end + + def windows_rules_filename + "#{ENV['HOME']}/windows-chef.rules" + end + + def active? + @active ||= begin + cmd = shell_out!('netsh advfirewall show currentprofile') + cmd.stdout =~ /^State\sON/ + end + end + + def enable! + shell_out!('netsh advfirewall set currentprofile state on') + end + + def disable! + shell_out!('netsh advfirewall set currentprofile state off') + end + + def reset! + shell_out!('netsh advfirewall reset') + end + + def add_rule!(params) + shell_out!("netsh advfirewall #{params}") + end + + def delete_all_rules! + shell_out!('netsh advfirewall firewall delete rule name=all') + end + + def to_type(new_resource) + cmd = new_resource.command + type = if cmd == :reject || cmd == :deny + :block + else + :allow + end + type + end + + def build_rule(new_resource) + type = to_type(new_resource) + parameters = {} + + parameters['description'] = "\"#{new_resource.description}\"" + parameters['dir'] = new_resource.direction + + new_resource.program && parameters['program'] = new_resource.program + new_resource.service && parameters['service'] = new_resource.service + parameters['protocol'] = new_resource.protocol + + if new_resource.direction.to_sym == :out + parameters['localip'] = new_resource.source ? fixup_cidr(new_resource.source) : 'any' + parameters['localport'] = new_resource.source_port ? port_to_s(new_resource.source_port) : 'any' + parameters['interfacetype'] = new_resource.interface ? new_resource.interface : 'any' + parameters['remoteip'] = new_resource.destination ? fixup_cidr(new_resource.destination) : 'any' + parameters['remoteport'] = new_resource.dest_port ? port_to_s(new_resource.dest_port) : 'any' + else + parameters['localip'] = new_resource.destination ? new_resource.destination : 'any' + parameters['localport'] = dport_calc(new_resource) ? port_to_s(dport_calc(new_resource)) : 'any' + parameters['interfacetype'] = new_resource.dest_interface ? new_resource.dest_interface : 'any' + parameters['remoteip'] = new_resource.source ? fixup_cidr(new_resource.source) : 'any' + parameters['remoteport'] = new_resource.source_port ? port_to_s(new_resource.source_port) : 'any' + end + + parameters['action'] = type.to_s + + partial_command = parameters.map { |k, v| "#{k}=#{v}" }.join(' ') + "firewall add rule name=\"#{new_resource.name}\" #{partial_command}" + end + + def rule_exists?(name) + @exists ||= begin + cmd = shell_out!("netsh advfirewall firewall show rule name=\"#{name}\"", returns: [0, 1]) + cmd.stdout !~ /^No rules match the specified criteria/ + end + end + + def show_all_rules! + cmd = shell_out!('netsh advfirewall firewall show rule name=all') + cmd.stdout.each_line do |line| + Chef::Log.warn(line) + end + end + + def rule_up_to_date?(name, type) + @up_to_date ||= begin + desired_parameters = rule_parameters(type) + current_parameters = {} + + cmd = shell_out!("netsh advfirewall firewall show rule name=\"#{name}\" verbose") + cmd.stdout.each_line do |line| + current_parameters['description'] = "\"#{Regexp.last_match(1).chomp}\"" if line =~ /^Description:\s+(.*)$/ + current_parameters['dir'] = Regexp.last_match(1).chomp if line =~ /^Direction:\s+(.*)$/ + current_parameters['program'] = Regexp.last_match(1).chomp if line =~ /^Program:\s+(.*)$/ + current_parameters['service'] = Regexp.last_match(1).chomp if line =~ /^Service:\s+(.*)$/ + current_parameters['protocol'] = Regexp.last_match(1).chomp if line =~ /^Protocol:\s+(.*)$/ + current_parameters['localip'] = Regexp.last_match(1).chomp if line =~ /^LocalIP:\s+(.*)$/ + current_parameters['localport'] = Regexp.last_match(1).chomp if line =~ /^LocalPort:\s+(.*)$/ + current_parameters['interfacetype'] = Regexp.last_match(1).chomp if line =~ /^InterfaceTypes:\s+(.*)$/ + current_parameters['remoteip'] = Regexp.last_match(1).chomp if line =~ /^RemoteIP:\s+(.*)$/ + current_parameters['remoteport'] = Regexp.last_match(1).chomp if line =~ /^RemotePort:\s+(.*)$/ + current_parameters['action'] = Regexp.last_match(1).chomp if line =~ /^Action:\s+(.*)$/ + end + + up_to_date = true + desired_parameters.each do |k, v| + up_to_date = false if current_parameters[k] !~ /^["]?#{v}["]?$/i + end + + up_to_date + end + end + end + end +end diff --git a/cookbooks/firewall/libraries/matchers.rb b/cookbooks/firewall/libraries/matchers.rb new file mode 100644 index 0000000..474b3c2 --- /dev/null +++ b/cookbooks/firewall/libraries/matchers.rb @@ -0,0 +1,30 @@ +if defined?(ChefSpec) + ChefSpec.define_matcher(:firewall) + ChefSpec.define_matcher(:firewall_rule) + + # actions(:install, :restart, :disable, :flush, :save) + + def install_firewall(resource) + ChefSpec::Matchers::ResourceMatcher.new(:firewall, :install, resource) + end + + def restart_firewall(resource) + ChefSpec::Matchers::ResourceMatcher.new(:firewall, :restart, resource) + end + + def disable_firewall(resource) + ChefSpec::Matchers::ResourceMatcher.new(:firewall, :disable, resource) + end + + def flush_firewall(resource) + ChefSpec::Matchers::ResourceMatcher.new(:firewall, :flush, resource) + end + + def save_firewall(resource) + ChefSpec::Matchers::ResourceMatcher.new(:firewall, :save, resource) + end + + def create_firewall_rule(resource) + ChefSpec::Matchers::ResourceMatcher.new(:firewall_rule, :create, resource) + end +end diff --git a/cookbooks/firewall/libraries/provider_firewall_firewalld.rb b/cookbooks/firewall/libraries/provider_firewall_firewalld.rb new file mode 100644 index 0000000..b8fc8c5 --- /dev/null +++ b/cookbooks/firewall/libraries/provider_firewall_firewalld.rb @@ -0,0 +1,179 @@ +# +# Author:: Ronald Doorn () +# Cookbook:: firewall +# Resource:: default +# +# 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. +# +class Chef + class Provider::FirewallFirewalld < Chef::Provider::LWRPBase + include FirewallCookbook::Helpers::Firewalld + + provides :firewall, os: 'linux', platform_family: %w(rhel fedora) do |node| + node['platform_version'].to_f >= 7.0 && !node['firewall']['redhat7_iptables'] + end + + def whyrun_supported? + false + end + + def action_install + return if disabled?(new_resource) + + firewalld_package = package 'firewalld' do + action :nothing + options new_resource.package_options + end + firewalld_package.run_action(:install) + new_resource.updated_by_last_action(firewalld_package.updated_by_last_action?) + + unless ::File.exist?(firewalld_rules_filename) + rules_file = lookup_or_create_rulesfile + rules_file.content '# created by chef to allow service to start' + rules_file.run_action(:create) + new_resource.updated_by_last_action(rules_file.updated_by_last_action?) + end + + firewalld_service = lookup_or_create_service + [:enable, :start].each do |a| + firewalld_service.run_action(a) + new_resource.updated_by_last_action(firewalld_service.updated_by_last_action?) + end + end + + def action_restart + return if disabled?(new_resource) + + # ensure it's initialized + new_resource.rules({}) unless new_resource.rules + new_resource.rules['firewalld'] = {} unless new_resource.rules['firewalld'] + + # this populates the hash of rules from firewall_rule resources + firewall_rules = Chef.run_context.resource_collection.select { |item| item.is_a?(Chef::Resource::FirewallRule) } + firewall_rules.each do |firewall_rule| + next unless firewall_rule.action.include?(:create) && !firewall_rule.should_skip?(:create) + + ip_versions(firewall_rule).each do |ip_version| + # build rules to apply with weight + k = "firewall-cmd --direct --add-rule #{build_firewall_rule(firewall_rule, ip_version)}" + v = firewall_rule.position + + # unless we're adding them for the first time.... bail out. + next if new_resource.rules['firewalld'].key?(k) && new_resource.rules['firewalld'][k] == v + new_resource.rules['firewalld'][k] = v + + # If persistent rules is enabled (default) make sure we add a permanent rule at the same time + perm_rules = node && node['firewall'] && node['firewall']['firewalld'] && node['firewall']['firewalld']['permanent'] + if firewall_rule.permanent || perm_rules + k = "firewall-cmd --permanent --direct --add-rule #{build_firewall_rule(firewall_rule, ip_version)}" + new_resource.rules['firewalld'][k] = v + end + end + end + + # ensure a file resource exists with the current firewalld rules + rules_file = lookup_or_create_rulesfile + rules_file.content build_rule_file(new_resource.rules['firewalld']) + rules_file.run_action(:create) + + # ensure the service is running without waiting. + firewalld_service = lookup_or_create_service + [:enable, :start].each do |a| + firewalld_service.run_action(a) + new_resource.updated_by_last_action(firewalld_service.updated_by_last_action?) + end + + # mark updated if we changed the zone + unless firewalld_default_zone?(new_resource.enabled_zone) + firewalld_default_zone!(new_resource.enabled_zone) + new_resource.updated_by_last_action(true) + end + + # if the file was changed, load new ruleset + return unless rules_file.updated_by_last_action? + firewalld_flush! + # TODO: support logging + + new_resource.rules['firewalld'].sort_by { |_k, v| v }.map { |k, _v| k }.each do |cmd| + firewalld_rule!(cmd) + end + + new_resource.updated_by_last_action(true) + end + + def action_disable + return if disabled?(new_resource) + + if firewalld_active? + firewalld_flush! + firewalld_default_zone!(new_resource.disabled_zone) + new_resource.updated_by_last_action(true) + end + + # ensure the service is stopped without waiting. + firewalld_service = lookup_or_create_service + [:disable, :stop].each do |a| + firewalld_service.run_action(a) + new_resource.updated_by_last_action(firewalld_service.updated_by_last_action?) + end + + rules_file = lookup_or_create_rulesfile + rules_file.content '# created by chef to allow service to start' + rules_file.run_action(:create) + new_resource.updated_by_last_action(rules_file.updated_by_last_action?) + end + + def action_flush + return if disabled?(new_resource) + return unless firewalld_active? + + firewalld_flush! + new_resource.updated_by_last_action(true) + + rules_file = lookup_or_create_rulesfile + rules_file.content '# created by chef to allow service to start' + rules_file.run_action(:create) + new_resource.updated_by_last_action(rules_file.updated_by_last_action?) + end + + def action_save + return if disabled?(new_resource) + return if firewalld_all_rules_permanent! + + firewalld_save! + new_resource.updated_by_last_action(true) + end + + def lookup_or_create_service + begin + firewalld_service = Chef.run_context.resource_collection.find(service: 'firewalld') + rescue + firewalld_service = service 'firewalld' do + action :nothing + end + end + firewalld_service + end + + def lookup_or_create_rulesfile + begin + firewalld_file = Chef.run_context.resource_collection.find(file: firewalld_rules_filename) + rescue + firewalld_file = file firewalld_rules_filename do + action :nothing + end + end + firewalld_file + end + end +end diff --git a/cookbooks/firewall/libraries/provider_firewall_iptables.rb b/cookbooks/firewall/libraries/provider_firewall_iptables.rb new file mode 100644 index 0000000..6c1cb81 --- /dev/null +++ b/cookbooks/firewall/libraries/provider_firewall_iptables.rb @@ -0,0 +1,171 @@ +# +# Author:: Seth Chisamore () +# Cookbook:: firewall +# Resource:: default +# +# Copyright:: 2011-2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +class Chef + class Provider::FirewallIptables < Chef::Provider::LWRPBase + include FirewallCookbook::Helpers + include FirewallCookbook::Helpers::Iptables + + provides :firewall, os: 'linux', platform_family: %w(rhel fedora) do |node| + node['platform_version'].to_f < 7.0 || node['firewall']['redhat7_iptables'] + end + + def whyrun_supported? + false + end + + def action_install + return if disabled?(new_resource) + + # Ensure the package is installed + iptables_packages(new_resource).each do |p| + iptables_pkg = package p do + action :nothing + end + iptables_pkg.run_action(:install) + new_resource.updated_by_last_action(true) if iptables_pkg.updated_by_last_action? + end + + iptables_commands(new_resource).each do |svc| + # must create empty file for service to start + unless ::File.exist?("/etc/sysconfig/#{svc}") + # must create empty file for service to start + iptables_file = lookup_or_create_rulesfile(svc) + iptables_file.content '# created by chef to allow service to start' + iptables_file.run_action(:create) + new_resource.updated_by_last_action(true) if iptables_file.updated_by_last_action? + end + + iptables_service = lookup_or_create_service(svc) + [:enable, :start].each do |a| + iptables_service.run_action(a) + new_resource.updated_by_last_action(true) if iptables_service.updated_by_last_action? + end + end + end + + def action_restart + return if disabled?(new_resource) + + # prints all the firewall rules + log_iptables(new_resource) + + # ensure it's initialized + new_resource.rules({}) unless new_resource.rules + ensure_default_rules_exist(node, new_resource) + + # this populates the hash of rules from firewall_rule resources + firewall_rules = Chef.run_context.resource_collection.select { |item| item.is_a?(Chef::Resource::FirewallRule) } + firewall_rules.each do |firewall_rule| + next unless firewall_rule.action.include?(:create) && !firewall_rule.should_skip?(:create) + + types = if ipv6_rule?(firewall_rule) # an ip4 specific rule + %w(ip6tables) + elsif ipv4_rule?(firewall_rule) # an ip6 specific rule + %w(iptables) + else # or not specific + %w(iptables ip6tables) + end + + types.each do |iptables_type| + # build rules to apply with weight + k = build_firewall_rule(node, firewall_rule, iptables_type == 'ip6tables') + v = firewall_rule.position + + # unless we're adding them for the first time.... bail out. + next if new_resource.rules[iptables_type].key?(k) && new_resource.rules[iptables_type][k] == v + new_resource.rules[iptables_type][k] = v + end + end + + iptables_commands(new_resource).each do |iptables_type| + # this takes the commands in each hash entry and builds a rule file + iptables_file = lookup_or_create_rulesfile(iptables_type) + iptables_file.content build_rule_file(new_resource.rules[iptables_type]) + iptables_file.run_action(:create) + + # if the file was unchanged, skip loop iteration, otherwise restart iptables + next unless iptables_file.updated_by_last_action? + + iptables_service = lookup_or_create_service(iptables_type) + new_resource.notifies(:restart, iptables_service, :delayed) + new_resource.updated_by_last_action(true) + end + end + + def action_disable + return if disabled?(new_resource) + + iptables_flush!(new_resource) + iptables_default_allow!(new_resource) + new_resource.updated_by_last_action(true) + + iptables_commands(new_resource).each do |svc| + iptables_service = lookup_or_create_service(svc) + [:disable, :stop].each do |a| + iptables_service.run_action(a) + new_resource.updated_by_last_action(true) if iptables_service.updated_by_last_action? + end + + # must create empty file for service to start + iptables_file = lookup_or_create_rulesfile(svc) + iptables_file.content '# created by chef to allow service to start' + iptables_file.run_action(:create) + new_resource.updated_by_last_action(true) if iptables_file.updated_by_last_action? + end + end + + def action_flush + return if disabled?(new_resource) + + iptables_flush!(new_resource) + new_resource.updated_by_last_action(true) + + iptables_commands(new_resource).each do |svc| + # must create empty file for service to start + iptables_file = lookup_or_create_rulesfile(svc) + iptables_file.content '# created by chef to allow service to start' + iptables_file.run_action(:create) + new_resource.updated_by_last_action(true) if iptables_file.updated_by_last_action? + end + end + + def lookup_or_create_service(name) + begin + iptables_service = Chef.run_context.resource_collection.find(service: svc) + rescue + iptables_service = service name do + action :nothing + end + end + iptables_service + end + + def lookup_or_create_rulesfile(name) + begin + iptables_file = Chef.run_context.resource_collection.find(file: name) + rescue + iptables_file = file "/etc/sysconfig/#{name}" do + action :nothing + end + end + iptables_file + end + end +end diff --git a/cookbooks/firewall/libraries/provider_firewall_iptables_ubuntu.rb b/cookbooks/firewall/libraries/provider_firewall_iptables_ubuntu.rb new file mode 100644 index 0000000..d6be1cd --- /dev/null +++ b/cookbooks/firewall/libraries/provider_firewall_iptables_ubuntu.rb @@ -0,0 +1,195 @@ +# +# Author:: Seth Chisamore () +# Cookbook:: firewall +# Resource:: default +# +# Copyright:: 2011-2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +class Chef + class Provider::FirewallIptablesUbuntu < Chef::Provider::LWRPBase + include FirewallCookbook::Helpers + include FirewallCookbook::Helpers::Iptables + + provides :firewall, os: 'linux', platform_family: %w(debian) do |node| + node['platform_version'].to_f > 14.04 && node['firewall'] && node['firewall']['ubuntu_iptables'] + end + + def whyrun_supported? + false + end + + def action_install + return if disabled?(new_resource) + + # Ensure the package is installed + pkg = package 'iptables-persistent' do + action :nothing + end + pkg.run_action(:install) + new_resource.updated_by_last_action(true) if pkg.updated_by_last_action? + + rule_files = %w(rules.v4) + rule_files << 'rules.v6' if ipv6_enabled?(new_resource) + rule_files.each do |svc| + next if ::File.exist?("/etc/iptables/#{svc}") + + # must create empty file for service to start + f = lookup_or_create_rulesfile(svc) + f.content '# created by chef to allow service to start' + f.run_action(:create) + + new_resource.updated_by_last_action(true) if f.updated_by_last_action? + end + + iptables_service = lookup_or_create_service('netfilter-persistent') + [:enable, :start].each do |act| + # iptables-persistent isn't a real service + iptables_service.status_command 'true' + + iptables_service.run_action(act) + new_resource.updated_by_last_action(true) if iptables_service.updated_by_last_action? + end + end + + def action_restart + return if disabled?(new_resource) + + # prints all the firewall rules + log_iptables(new_resource) + + # ensure it's initialized + new_resource.rules({}) unless new_resource.rules + ensure_default_rules_exist(node, new_resource) + + # this populates the hash of rules from firewall_rule resources + firewall_rules = Chef.run_context.resource_collection.select { |item| item.is_a?(Chef::Resource::FirewallRule) } + firewall_rules.each do |firewall_rule| + next unless firewall_rule.action.include?(:create) && !firewall_rule.should_skip?(:create) + + types = if ipv6_rule?(firewall_rule) # an ip4 specific rule + %w(ip6tables) + elsif ipv4_rule?(firewall_rule) # an ip6 specific rule + %w(iptables) + else # or not specific + %w(iptables ip6tables) + end + + types.each do |iptables_type| + # build rules to apply with weight + k = build_firewall_rule(node, firewall_rule, iptables_type == 'ip6tables') + v = firewall_rule.position + + # unless we're adding them for the first time.... bail out. + next if new_resource.rules[iptables_type].key?(k) && new_resource.rules[iptables_type][k] == v + new_resource.rules[iptables_type][k] = v + end + end + + rule_files = %w(iptables) + rule_files << 'ip6tables' if ipv6_enabled?(new_resource) + + rule_files.each do |iptables_type| + iptables_filename = if iptables_type == 'ip6tables' + '/etc/iptables/rules.v6' + else + '/etc/iptables/rules.v4' + end + + # ensure a file resource exists with the current iptables rules + begin + iptables_file = Chef.run_context.resource_collection.find(file: iptables_filename) + rescue + iptables_file = file iptables_filename do + action :nothing + end + end + iptables_file.content build_rule_file(new_resource.rules[iptables_type]) + iptables_file.run_action(:create) + + # if the file was changed, restart iptables + next unless iptables_file.updated_by_last_action? + service_affected = service 'netfilter-persistent' do + action :nothing + end + + new_resource.notifies(:restart, service_affected, :delayed) + new_resource.updated_by_last_action(true) + end + end + + def action_disable + return if disabled?(new_resource) + + iptables_flush!(new_resource) + iptables_default_allow!(new_resource) + new_resource.updated_by_last_action(true) + + iptables_service = lookup_or_create_service('netfilter-persistent') + [:disable, :stop].each do |act| + iptables_service.run_action(act) + new_resource.updated_by_last_action(true) if iptables_service.updated_by_last_action? + end + + %w(rules.v4 rules.v6).each do |svc| + # must create empty file for service to start + f = lookup_or_create_rulesfile(svc) + f.content '# created by chef to allow service to start' + f.run_action(:create) + + new_resource.updated_by_last_action(true) if f.updated_by_last_action? + end + end + + def action_flush + return if disabled?(new_resource) + + iptables_flush!(new_resource) + new_resource.updated_by_last_action(true) + + rule_files = %w(rules.v4) + rule_files << 'rules.v6' if ipv6_enabled?(new_resource) + rule_files.each do |svc| + # must create empty file for service to start + f = lookup_or_create_rulesfile(svc) + f.content '# created by chef to allow service to start' + f.run_action(:create) + + new_resource.updated_by_last_action(true) if f.updated_by_last_action? + end + end + + def lookup_or_create_service(name) + begin + iptables_service = Chef.run_context.resource_collection.find(service: svc) + rescue + iptables_service = service name do + action :nothing + end + end + iptables_service + end + + def lookup_or_create_rulesfile(name) + begin + iptables_file = Chef.run_context.resource_collection.find(file: name) + rescue + iptables_file = file "/etc/iptables/#{name}" do + action :nothing + end + end + iptables_file + end + end +end diff --git a/cookbooks/firewall/libraries/provider_firewall_iptables_ubuntu1404.rb b/cookbooks/firewall/libraries/provider_firewall_iptables_ubuntu1404.rb new file mode 100644 index 0000000..d2c3d74 --- /dev/null +++ b/cookbooks/firewall/libraries/provider_firewall_iptables_ubuntu1404.rb @@ -0,0 +1,195 @@ +# +# Author:: Seth Chisamore () +# Cookbook Name:: firewall +# Resource:: default +# +# Copyright:: 2011, Opscode, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +class Chef + class Provider::FirewallIptablesUbuntu1404 < Chef::Provider::LWRPBase + include FirewallCookbook::Helpers + include FirewallCookbook::Helpers::Iptables + + provides :firewall, os: 'linux', platform_family: %w(debian) do |node| + node['platform_version'].to_f <= 14.04 && node['firewall'] && node['firewall']['ubuntu_iptables'] + end + + def whyrun_supported? + false + end + + def action_install + return if disabled?(new_resource) + + # Ensure the package is installed + pkg = package 'iptables-persistent' do + action :nothing + end + pkg.run_action(:install) + new_resource.updated_by_last_action(true) if pkg.updated_by_last_action? + + rule_files = %w(rules.v4) + rule_files << 'rules.v6' if ipv6_enabled?(new_resource) + rule_files.each do |svc| + next if ::File.exist?("/etc/iptables/#{svc}") + + # must create empty file for service to start + f = lookup_or_create_rulesfile(svc) + f.content '# created by chef to allow service to start' + f.run_action(:create) + + new_resource.updated_by_last_action(true) if f.updated_by_last_action? + end + + iptables_service = lookup_or_create_service('iptables-persistent') + [:enable, :start].each do |act| + # iptables-persistent isn't a real service + iptables_service.status_command 'true' + + iptables_service.run_action(act) + new_resource.updated_by_last_action(true) if iptables_service.updated_by_last_action? + end + end + + def action_restart + return if disabled?(new_resource) + + # prints all the firewall rules + log_iptables(new_resource) + + # ensure it's initialized + new_resource.rules({}) unless new_resource.rules + ensure_default_rules_exist(node, new_resource) + + # this populates the hash of rules from firewall_rule resources + firewall_rules = Chef.run_context.resource_collection.select { |item| item.is_a?(Chef::Resource::FirewallRule) } + firewall_rules.each do |firewall_rule| + next unless firewall_rule.action.include?(:create) && !firewall_rule.should_skip?(:create) + + types = if ipv6_rule?(firewall_rule) # an ip4 specific rule + %w(ip6tables) + elsif ipv4_rule?(firewall_rule) # an ip6 specific rule + %w(iptables) + else # or not specific + %w(iptables ip6tables) + end + + types.each do |iptables_type| + # build rules to apply with weight + k = build_firewall_rule(node, firewall_rule, iptables_type == 'ip6tables') + v = firewall_rule.position + + # unless we're adding them for the first time.... bail out. + next if new_resource.rules[iptables_type].key?(k) && new_resource.rules[iptables_type][k] == v + new_resource.rules[iptables_type][k] = v + end + end + + rule_files = %w(iptables) + rule_files << 'ip6tables' if ipv6_enabled?(new_resource) + + rule_files.each do |iptables_type| + iptables_filename = if iptables_type == 'ip6tables' + '/etc/iptables/rules.v6' + else + '/etc/iptables/rules.v4' + end + + # ensure a file resource exists with the current iptables rules + begin + iptables_file = Chef.run_context.resource_collection.find(file: iptables_filename) + rescue + iptables_file = file iptables_filename do + action :nothing + end + end + iptables_file.content build_rule_file(new_resource.rules[iptables_type]) + iptables_file.run_action(:create) + + # if the file was changed, restart iptables + next unless iptables_file.updated_by_last_action? + service_affected = service 'iptables-persistent' do + action :nothing + end + + new_resource.notifies(:restart, service_affected, :delayed) + new_resource.updated_by_last_action(true) + end + end + + def action_disable + return if disabled?(new_resource) + + iptables_flush!(new_resource) + iptables_default_allow!(new_resource) + new_resource.updated_by_last_action(true) + + iptables_service = lookup_or_create_service('iptables-persistent') + [:disable, :stop].each do |act| + iptables_service.run_action(act) + new_resource.updated_by_last_action(true) if iptables_service.updated_by_last_action? + end + + %w(rules.v4 rules.v6).each do |svc| + # must create empty file for service to start + f = lookup_or_create_rulesfile(svc) + f.content '# created by chef to allow service to start' + f.run_action(:create) + + new_resource.updated_by_last_action(true) if f.updated_by_last_action? + end + end + + def action_flush + return if disabled?(new_resource) + + iptables_flush!(new_resource) + new_resource.updated_by_last_action(true) + + rule_files = %w(rules.v4) + rule_files << 'rules.v6' if ipv6_enabled?(new_resource) + rule_files.each do |svc| + # must create empty file for service to start + f = lookup_or_create_rulesfile(svc) + f.content '# created by chef to allow service to start' + f.run_action(:create) + + new_resource.updated_by_last_action(true) if f.updated_by_last_action? + end + end + + def lookup_or_create_service(name) + begin + iptables_service = Chef.run_context.resource_collection.find(service: svc) + rescue + iptables_service = service name do + action :nothing + end + end + iptables_service + end + + def lookup_or_create_rulesfile(name) + begin + iptables_file = Chef.run_context.resource_collection.find(file: name) + rescue + iptables_file = file "/etc/iptables/#{name}" do + action :nothing + end + end + iptables_file + end + end +end diff --git a/cookbooks/firewall/libraries/provider_firewall_rule.rb b/cookbooks/firewall/libraries/provider_firewall_rule.rb new file mode 100644 index 0000000..85a27c5 --- /dev/null +++ b/cookbooks/firewall/libraries/provider_firewall_rule.rb @@ -0,0 +1,34 @@ +# +# Author:: Ronald Doorn () +# Cookbook:: firewall +# Provider:: rule_iptables +# +# Copyright:: 2015-2016, computerlyrik +# +# 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. +# +class Chef + class Provider::FirewallRuleGeneric < Chef::Provider::LWRPBase + provides :firewall_rule + + def action_create + return unless new_resource.notify_firewall + + firewall_resource = Chef.run_context.resource_collection.find(firewall: new_resource.firewall_name) + raise 'could not find a firewall resource' unless firewall_resource + + new_resource.notifies(:restart, firewall_resource, :delayed) + new_resource.updated_by_last_action(true) + end + end +end diff --git a/cookbooks/firewall/libraries/provider_firewall_ufw.rb b/cookbooks/firewall/libraries/provider_firewall_ufw.rb new file mode 100644 index 0000000..cc1aeb7 --- /dev/null +++ b/cookbooks/firewall/libraries/provider_firewall_ufw.rb @@ -0,0 +1,138 @@ +# +# Author:: Seth Chisamore () +# Cookbook:: firewall +# Resource:: default +# +# Copyright:: 2011-2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +class Chef + class Provider::FirewallUfw < Chef::Provider::LWRPBase + include FirewallCookbook::Helpers::Ufw + + provides :firewall, os: 'linux', platform_family: %w(debian) do |node| + !(node['firewall'] && node['firewall']['ubuntu_iptables']) + end + + def whyrun_supported? + false + end + + def action_install + return if disabled?(new_resource) + + pkg_ufw = package 'ufw' do + action :nothing + end + pkg_ufw.run_action(:install) + new_resource.updated_by_last_action(true) if pkg_ufw.updated_by_last_action? + + defaults_ufw = template '/etc/default/ufw' do + action :nothing + owner 'root' + group 'root' + mode '0644' + source 'ufw/default.erb' + cookbook 'firewall' + end + defaults_ufw.run_action(:create) + new_resource.updated_by_last_action(true) if defaults_ufw.updated_by_last_action? + + return if ::File.exist?(ufw_rules_filename) + + ufw_file = lookup_or_create_rulesfile + ufw_file.content '# created by chef to allow service to start' + ufw_file.run_action(:create) + + new_resource.updated_by_last_action(true) if ufw_file.updated_by_last_action? + end + + def action_restart + return if disabled?(new_resource) + + # ensure it's initialized + new_resource.rules({}) unless new_resource.rules + new_resource.rules['ufw'] = {} unless new_resource.rules['ufw'] + + # this populates the hash of rules from firewall_rule resources + firewall_rules = Chef.run_context.resource_collection.select { |item| item.is_a?(Chef::Resource::FirewallRule) } + firewall_rules.each do |firewall_rule| + next unless firewall_rule.action.include?(:create) && !firewall_rule.should_skip?(:create) + + # build rules to apply with weight + k = build_rule(firewall_rule) + v = firewall_rule.position + + # unless we're adding them for the first time.... bail out. + unless new_resource.rules['ufw'].key?(k) && new_resource.rules['ufw'][k] == v + new_resource.rules['ufw'][k] = v + end + end + + # ensure a file resource exists with the current ufw rules + ufw_file = lookup_or_create_rulesfile + ufw_file.content build_rule_file(new_resource.rules['ufw']) + ufw_file.run_action(:create) + + # if the file was changed, restart iptables + return unless ufw_file.updated_by_last_action? + ufw_reset! + ufw_logging!(new_resource.log_level) if new_resource.log_level + + new_resource.rules['ufw'].sort_by { |_k, v| v }.map { |k, _v| k }.each do |cmd| + ufw_rule!(cmd) + end + + # ensure it's enabled _after_ rules are inputted, to catch malformed rules + ufw_enable! unless ufw_active? + new_resource.updated_by_last_action(true) + end + + def action_disable + return if disabled?(new_resource) + + ufw_file = lookup_or_create_rulesfile + ufw_file.content '# created by chef to allow service to start' + ufw_file.run_action(:create) + new_resource.updated_by_last_action(true) if ufw_file.updated_by_last_action? + + return unless ufw_active? + ufw_disable! + new_resource.updated_by_last_action(true) + end + + def action_flush + return if disabled?(new_resource) + + ufw_reset! + new_resource.updated_by_last_action(true) + + ufw_file = lookup_or_create_rulesfile + ufw_file.content '# created by chef to allow service to start' + ufw_file.run_action(:create) + new_resource.updated_by_last_action(true) if ufw_file.updated_by_last_action? + end + + def lookup_or_create_rulesfile + begin + ufw_file = Chef.run_context.resource_collection.find(file: ufw_rules_filename) + rescue + ufw_file = file ufw_rules_filename do + action :nothing + end + end + ufw_file + end + end +end diff --git a/cookbooks/firewall/libraries/provider_firewall_windows.rb b/cookbooks/firewall/libraries/provider_firewall_windows.rb new file mode 100644 index 0000000..d261f03 --- /dev/null +++ b/cookbooks/firewall/libraries/provider_firewall_windows.rb @@ -0,0 +1,126 @@ +# +# Author:: Sander van Harmelen () +# Cookbook:: firewall +# Provider:: windows +# +# 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. +# + +class Chef + class Provider::FirewallWindows < Chef::Provider::LWRPBase + include FirewallCookbook::Helpers::Windows + + provides :firewall, os: 'windows' + + def whyrun_supported? + false + end + + def action_install + return if disabled?(new_resource) + + svc = service 'MpsSvc' do + action :nothing + end + + [:enable, :start].each do |act| + svc.run_action(act) + new_resource.updated_by_last_action(true) if svc.updated_by_last_action? + end + end + + def action_restart + return if disabled?(new_resource) + + # ensure it's initialized + new_resource.rules({}) unless new_resource.rules + new_resource.rules['windows'] = {} unless new_resource.rules['windows'] + + firewall_rules = Chef.run_context.resource_collection.select { |item| item.is_a?(Chef::Resource::FirewallRule) } + firewall_rules.each do |firewall_rule| + next unless firewall_rule.action.include?(:create) && !firewall_rule.should_skip?(:create) + + # build rules to apply with weight + k = build_rule(firewall_rule) + v = firewall_rule.position + + # unless we're adding them for the first time.... bail out. + unless new_resource.rules['windows'].key?(k) && new_resource.rules['windows'][k] == v + new_resource.rules['windows'][k] = v + end + end + + input_policy = node['firewall']['windows']['defaults']['policy']['input'] + output_policy = node['firewall']['windows']['defaults']['policy']['output'] + unless new_resource.rules['windows'].key?("set currentprofile firewallpolicy #{input_policy},#{output_policy}") + # Make this the possible last rule in the list + new_resource.rules['windows']["set currentprofile firewallpolicy #{input_policy},#{output_policy}"] = 99999 + end + + # ensure a file resource exists with the current rules + begin + windows_file = Chef.run_context.resource_collection.find(file: windows_rules_filename) + rescue + windows_file = file windows_rules_filename do + action :nothing + end + end + windows_file.content build_rule_file(new_resource.rules['windows']) + windows_file.run_action(:create) + + # if the file was changed, restart iptables + return unless windows_file.updated_by_last_action? + + disable! if active? + delete_all_rules! # clear entirely + reset! # populate default rules + + new_resource.rules['windows'].sort_by { |_k, v| v }.map { |k, _v| k }.each do |cmd| + add_rule!(cmd) + end + # ensure it's enabled _after_ rules are inputted, to catch malformed rules + enable! unless active? + + new_resource.updated_by_last_action(true) + end + + def action_disable + return if disabled?(new_resource) + + if active? + disable! + Chef::Log.info("#{new_resource} disabled.") + new_resource.updated_by_last_action(true) + else + Chef::Log.debug("#{new_resource} already disabled.") + end + + svc = service 'MpsSvc' do + action :nothing + end + + [:disable, :stop].each do |act| + svc.run_action(act) + new_resource.updated_by_last_action(true) if svc.updated_by_last_action? + end + end + + def action_flush + return if disabled?(new_resource) + + reset! + Chef::Log.info("#{new_resource} reset.") + new_resource.updated_by_last_action(true) + end + end +end diff --git a/cookbooks/firewall/libraries/resource_firewall.rb b/cookbooks/firewall/libraries/resource_firewall.rb new file mode 100644 index 0000000..3920f8f --- /dev/null +++ b/cookbooks/firewall/libraries/resource_firewall.rb @@ -0,0 +1,26 @@ +class Chef + class Resource::Firewall < Chef::Resource::LWRPBase + resource_name(:firewall) + provides(:firewall) + actions(:install, :restart, :disable, :flush, :save) + default_action(:install) + + # allow both kinds of logic -- eventually remove the :disabled one. + # the positive logic is much easier to follow. + attribute(:disabled, kind_of: [TrueClass, FalseClass], default: false) + attribute(:enabled, kind_of: [TrueClass, FalseClass], default: true) + + attribute(:log_level, kind_of: Symbol, equal_to: [:low, :medium, :high, :full, :off], default: :low) + attribute(:rules, kind_of: Hash) + + # for firewalld, specify the zone when firewall is disable and enabled + attribute(:disabled_zone, kind_of: Symbol, default: :public) + attribute(:enabled_zone, kind_of: Symbol, default: :drop) + + # for firewall implementations where ipv6 can be skipped (currently iptables-specific) + attribute(:ipv6_enabled, kind_of: [TrueClass, FalseClass], default: true) + + # allow override of package options for firewalld package + attribute(:package_options, kind_of: String, default: nil) + end +end diff --git a/cookbooks/firewall/libraries/resource_firewall_rule.rb b/cookbooks/firewall/libraries/resource_firewall_rule.rb new file mode 100644 index 0000000..575deef --- /dev/null +++ b/cookbooks/firewall/libraries/resource_firewall_rule.rb @@ -0,0 +1,52 @@ +require 'ipaddr' + +class Chef + class Resource::FirewallRule < Chef::Resource::LWRPBase + include FirewallCookbook::Helpers + + resource_name(:firewall_rule) + provides(:firewall_rule) + actions(:create) + default_action(:create) + + attribute(:firewall_name, kind_of: String, default: 'default') + + attribute(:command, kind_of: Symbol, equal_to: [:reject, :allow, :deny, :masquerade, :redirect, :log], default: :allow) + + attribute(:protocol, kind_of: [Integer, Symbol], default: :tcp, + callbacks: { 'must be either :tcp, :udp, :icmp, :\'ipv6-icmp\', :icmpv6, :none, or a valid IP protocol number' => lambda do |p| + !!(p.to_s =~ /(udp|tcp|icmp|icmpv6|ipv6-icmp|esp|ah|ipv6|none)/ || (p.to_s =~ /^\d+$/ && p.between?(0, 142))) + end }) + attribute(:direction, kind_of: Symbol, equal_to: [:in, :out, :pre, :post], default: :in) + attribute(:logging, kind_of: Symbol, equal_to: [:connections, :packets]) + + attribute(:source, callbacks: { 'must be a valid ip address' => ->(ip) { !!IPAddr.new(ip) } }) + attribute(:source_port, kind_of: [Integer, Array, Range]) # source port + attribute(:interface, kind_of: String) + + attribute(:port, kind_of: [Integer, Array, Range]) # shorthand for dest_port + attribute(:destination, callbacks: { 'must be a valid ip address' => ->(ip) { !!IPAddr.new(ip) } }) + attribute(:dest_port, kind_of: [Integer, Array, Range]) + attribute(:dest_interface, kind_of: String) + + attribute(:position, kind_of: Integer, default: 50) + attribute(:stateful, kind_of: [Symbol, Array]) + attribute(:redirect_port, kind_of: Integer) + attribute(:description, kind_of: String, name_attribute: true) + attribute(:include_comment, kind_of: [TrueClass, FalseClass], default: true) + + # only used for firewalld + attribute(:permanent, kind_of: [TrueClass, FalseClass], default: false) + + # only used for Windows Firewalls + attribute(:program, kind_of: String) + attribute(:service, kind_of: String) + + # for when you just want to pass a raw rule + attribute(:raw, kind_of: String) + + # do you want this rule to notify the firewall to recalculate + # (and potentially reapply) the firewall_rule(s) it finds? + attribute(:notify_firewall, kind_of: [TrueClass, FalseClass], default: true) + end +end diff --git a/cookbooks/firewall/metadata.json b/cookbooks/firewall/metadata.json new file mode 100644 index 0000000..f58eaa1 --- /dev/null +++ b/cookbooks/firewall/metadata.json @@ -0,0 +1 @@ +{"name":"firewall","version":"2.6.5","description":"Provides a set of primitives for managing firewalls and associated rules.","long_description":"firewall Cookbook\n=================\n\n[![Build Status](https://travis-ci.org/chef-cookbooks/firewall.svg?branch=master)](http://travis-ci.org/chef-cookbooks/firewall)\n[![Cookbook Version](https://img.shields.io/cookbook/v/firewall.svg)](https://supermarket.chef.io/cookbooks/firewall)\n\nProvides a set of primitives for managing firewalls and associated rules.\n\nPLEASE NOTE - The resource/providers in this cookbook are under heavy development. An attempt is being made to keep the resource simple/stupid by starting with less sophisticated firewall implementations first and refactor/vet the resource definition with each successive provider.\n\nRequirements\n------------\n**Chef 12.5.x+** is required. We are currently testing against Chef 13. If you need Chef 11 support, please try pinning back to a version less than 2.0, e.g.:\n```\ndepends 'firewall', '< 2.0'\n```\n\n### Supported firewalls and platforms\n* UFW - Ubuntu, Debian\n* IPTables - Red Hat & CentOS, Ubuntu\n* FirewallD - Red Hat & CentOS >= 7.0 (IPv4 only support, [needs contributions/testing](https://github.com/chef-cookbooks/firewall/issues/86))\n* Windows Advanced Firewall - 2012 R2\n\nTested on:\n* Ubuntu 14.04, 16.04 with iptables, ufw\n* Debian 7, 8 with ufw\n* CentOS 6 with iptables\n* CentOS 7.1 with firewalld\n* Windows Server 2012r2 with Windows Advanced Firewall\n\nBy default, Ubuntu chooses ufw. To switch to iptables, set this in an attribute file:\n```\ndefault['firewall']['ubuntu_iptables'] = true\n```\n\nBy default, Red Hat & CentOS >= 7.0 chooses firewalld. To switch to iptables, set this in an attribute file:\n```\ndefault['firewall']['redhat7_iptables'] = true\n```\n\n# Considerations that apply to all firewall providers and resources\n\nThis cookbook comes with two resources, firewall and firewall rule. The typical usage scenario is as follows:\n\n- run the `:install` action on the `firewall` resource named 'default', which installs appropriate packages and configures services to start on boot and starts them\n\n- run the `:create` action on every `firewall_rule` resource, which adds to the list of rules that should be configured on the firewall. `firewall_rule` then automatically sends a delayed notification to the `firewall['default']` resource to run the `:restart` action.\n\n- run the delayed notification with action `:restart` on the `firewall` resource. if any rules are different than the last run, the provider will update the current state of the firewall rules to match the expected rules.\n\nThere is a fundamental mismatch between the idea of a chef action and the action that should be taken on a firewall rule. For this reason, the chef action for a firewall_rule may be `:nothing` (the rule should not be present in the firewall) or `:create` (the rule should be present in the firewall), but the action taken on a packet in a firewall (`DROP`, `ACCEPT`, etc) is denoted as a `command` parameter on the `firewall_rule` resource.\n\n# iptables considerations\n\nIf you need to use a table other than `*filter`, the best way to do so is like so:\n```\nnode.default['firewall']['iptables']['defaults'][:ruleset] = {\n '*filter' => 1,\n ':INPUT DROP' => 2,\n ':FORWARD DROP' => 3,\n ':OUTPUT ACCEPT_FILTER' => 4,\n 'COMMIT_FILTER' => 100,\n '*nat' => 101,\n ':PREROUTING DROP' => 102,\n ':POSTROUTING DROP' => 103,\n ':OUTPUT ACCEPT_NAT' => 104,\n 'COMMIT_NAT' => 200\n}\n```\n\nNote -- in order to support multiple hash keys containing the same rule, anything found after the underscore will be stripped for: `:OUTPUT :INPUT :POSTROUTING :PREROUTING COMMIT`. This allows an example like the above to be reduced to just repeated lines of `COMMIT` and `:OUTPUT ACCEPT` while still avoiding duplication of other things.\n\nThen it's trivial to add additional rules to the `*nat` table using the raw parameter:\n```\nfirewall_rule \"postroute\" do\n raw \"-A POSTROUTING -o eth1 -p tcp -d 172.28.128.21 -j SNAT --to-source 172.28.128.6\"\n position 150\nend\n```\n\nNote that any line starting with `COMMIT` will become just `COMMIT`, as hash\nkeys must be unique but we need multiple commit lines.\n\n# Recipes\n\n### default\nThe default recipe creates a firewall resource with action install.\n\n### disable_firewall\nUsed to disable platform specific firewall. Many clouds have their own firewall configured outside of the OS instance such as AWS Security Groups.\n\n# Attributes\n\n* `default['firewall']['allow_ssh'] = false`, set true to open port 22 for SSH when the default recipe runs\n* `default['firewall']['allow_mosh'] = false`, set to true to open UDP ports 60000 - 61000 for [Mosh][0] when the default recipe runs\n* `default['firewall']['allow_winrm'] = false`, set true to open port 5989 for WinRM when the default recipe runs\n* `default['firewall']['allow_loopback'] = false`, set to true to allow all traffic on the loopback interface\n* `default['firewall']['allow_icmp'] = false`, set true to allow icmp protocol on supported OSes (note: ufw and windows implementations don't support this)\n\n* `default['firewall']['ubuntu_iptables'] = false`, set to true to use iptables on Ubuntu / Debian when using the default recipe\n* `default['firewall']['redhat7_iptables'] = false`, set to true to use iptables on Red Hat / CentOS 7 when using the default recipe\n\n* `default['firewall']['ufw']['defaults']` hash for template `/etc/default/ufw`\n* `default['firewall']['iptables']['defaults']` hash for default policies for 'filter' table's chains`\n\n* `default['firewall']['windows']['defaults']` hash to define inbound / outbound firewall policy on Windows platform\n\n* `default['firewall']['allow_established'] = true`, set to false if you don't want a related/established default rule on iptables\n* `default['firewall']['ipv6_enabled'] = true`, set to false if you don't want IPv6 related/established default rule on iptables (this enables ICMPv6, which is required for much of IPv6 communication)\n\n* `default['firewall']['firewalld']['permanent'] = false`, set to true if you want firewalld rules to be added with `--permanent` so they survive a reboot. This will be changed to `true` by default in a future major version release.\n\n# Resources\n\n### firewall\n\n***NB***: The name 'default' of this resource is important as it is used for firewall_rule providers to locate the firewall resource. If you change it, you must also supply the same value to any firewall_rule resources using the `firewall_name` parameter.\n\n#### Actions\n- `:install` (*default action*): Install and Enable the firewall. This will ensure the appropriate packages are installed and that any services have been started.\n- `:disable`: Disable the firewall. Drop any rules and put the node in an unprotected state. Flush all current rules. Also erase any internal state used to detect when rules should be applied.\n- `:flush`: Flush all current rules. Also erase any internal state used to detect when rules should be applied.\n- `:save`: Ensure all rules are added permanently under firewalld using `--permanent`. Not supported on ufw, iptables. You must notify this action at the end of the chef run if you want permanent firewalld rules (they are not persistent by default).\n\n#### Parameters\n\n- `disabled` (default to `false`): If set to true, all actions will no-op on this resource. This is a way to prevent included cookbooks from configuring a firewall.\n- `ipv6_enabled` (default to `true`): If set to false, firewall will not perform any ipv6 related work. Currently only supported in iptables.\n- `log_level`: UFW only. Level of verbosity the firewall should log at. valid values are: :low, :medium, :high, :full, :off. default is :low.\n- `rules`: This is used internally for firewall_rule resources to append their rules. You should NOT touch this value unless you plan to supply an entire firewall ruleset at once, and skip using firewall_rule resources.\n- `disabled_zone` (firewalld only): The zone to set on firewalld when the firewall should be disabled. Can be any string in symbol form, e.g. :public, :drop, etc. Defaults to `:public.`\n- `enabled_zone` (firewalld only): The zone to set on firewalld when the firewall should be enabled. Can be any string in symbol form, e.g. :public, :drop, etc. Defaults to `:drop.`\n- `package_options`: Used to pass options to the package install of firewall\n\n#### Examples\n\n```ruby\n# all defaults\nfirewall 'default'\n\n# enable platform default firewall\nfirewall 'default' do\n action :install\nend\n\n# increase logging past default of 'low'\nfirewall 'default' do\n log_level :high\n action :install\nend\n```\n\n### firewall_rule\n\n#### Actions\n- `:create` (_default action_): If a firewall_rule runs this action, the rule will be recorded in a chef resource's internal state, and applied when providers automatically notify the firewall resource with action `:reload`. The notification happens automatically.\n\n#### Parameters\n\n- `firewall_name`: the matching firewall resource that this rule applies to. Default value: `default`\n\n- `raw`: Used to pass an entire rule as a string, omitting all other parameters. This line will be directly loaded by `iptables-restore`, fed directly into `ufw` on the command line, or run using `firewall-cmd`.\n\n- `description` (_default: same as rule name_): Used to provide a comment that will be included when adding the firewall rule.\n\n- `include_comment` (_default: true_): Used to optionally exclude the comment in the rule.\n\n- `position` (_default: 50_): **relative** position to insert rule at. Position may be any integer between 0 < n < 100 (exclusive), and more than one rule may specify the same position.\n\n- `command`: What action to take on a particular packet\n\n - `:allow` (_default action_): the rule should allow matching packets\n - `:deny`: the rule should deny matching packets\n - `:reject`: the rule should reject matching packets\n - `:masqerade`: Masquerade the matching packets\n - `:redirect`: Redirect the matching packets\n - `:log`: Configure logging\n\n- `stateful`: a symbol or array of symbols, such as ``[:related, :established]` that will be passed to the state module in iptables or firewalld.\n\n- `protocol`: `:tcp` (_default_), `:udp`, `:icmp`, `:none` or protocol number. Using protocol numbers is not supported using the ufw provider (default for debian/ubuntu systems).\n\n- `direction`: For ufw, direction of the rule. valid values are: `:in` (_default_), `:out`, `:pre`, `:post`.\n\n- `source` (_Default is `0.0.0.0/0` or `Anywhere`_): source ip address or subnet to filter.\n\n- `source_port` (_Default is nil_): source port for filtering packets.\n\n- `destination`: ip address or subnet to filter on packet destination, must be a valid IP\n\n- `port` or `dest_port`: target port number (ie. 22 to allow inbound SSH), or an array of incoming port numbers (ie. [80,443] to allow inbound HTTP & HTTPS).\n\n NOTE: `protocol` attribute is required with multiple ports, or a range of incoming port numbers (ie. 60000..61000 to allow inbound mobile-shell. NOTE: `protocol`, or an attribute is required with a range of ports.\n\n- `interface`: (source) interface to apply rule (ie. `eth0`).\n\n- `dest_interface`: interface where packets may be destined to go\n\n- `redirect_port`: redirected port for rules with command `:redirect`\n\n- `logging`: may be added to enable logging for a particular rule. valid values are: `:connections`, `:packets`. In the ufw provider, `:connections` logs new connections while `:packets` logs all packets.\n\n#### Examples\n\n```ruby\n# open standard ssh port\nfirewall_rule 'ssh' do\n port 22\n command :allow\nend\n\n# open standard http port to tcp traffic only; insert as first rule\nfirewall_rule 'http' do\n port 80\n protocol :tcp\n position 1\n command :allow\nend\n\n# restrict port 13579 to 10.0.111.0/24 on eth0\nfirewall_rule 'myapplication' do\n port 13579\n source '10.0.111.0/24'\n direction :in\n interface 'eth0'\n command :allow\nend\n\n# specify a protocol number (supported on centos/redhat)\nfirewall_rule 'vrrp' do\n protocol 112\n command :allow\nend\n\n# use the iptables provider to specify protocol number on debian/ubuntu\nfirewall_rule 'vrrp' do\n provider Chef::Provider::FirewallRuleIptables\n protocol 112\n command :allow\nend\n\n# can use :raw command with UFW provider for VRRP\nfirewall_rule \"VRRP\" do\n command :allow\n raw \"allow to 224.0.0.18\"\nend\n\n# open UDP ports 60000..61000 for mobile shell (mosh.mit.edu), note\n# that the protocol attribute is required when using port_range\nfirewall_rule 'mosh' do\n protocol :udp\n port 60000..61000\n command :allow\nend\n\n# open multiple ports for http/https, note that the protocol\n# attribute is required when using ports\nfirewall_rule 'http/https' do\n protocol :tcp\n port [80, 443]\n command :allow\nend\n\nfirewall 'default' do\n enabled false\n action :nothing\nend\n```\n\n#### Providers\n\n- See `libraries/z_provider_mapping.rb` for a full list of providers for each platform and version.\n\nDifferent providers will determine the current state of the rules differently -- parsing the output of a command, maintaining the state in a file, or some other way. If the firewall is adjusted from outside of chef (non-idempotent), it's possible that chef may be caught unaware of the current state of the firewall. The best workaround is to add a `:flush` action to the firewall resource as early as possible in the chef run, if you plan to modify the firewall state outside of chef.\n\n# Troubleshooting\n\nTo figure out what the position values are for current rules, print the hash that contains the weights:\n```\nrequire pp\ndefault_firewall = resources(:firewall, 'default')\npp default_firewall.rules\n```\n\n# Development\nThis section details \"quick development\" steps. For a detailed explanation, see [[Contributing.md]].\n\n1. Clone this repository from GitHub:\n\n $ git clone git@github.com:chef-cookbooks/firewall.git\n\n2. Create a git branch\n\n $ git checkout -b my_bug_fix\n\n3. Install dependencies:\n\n $ bundle install\n\n4. Make your changes/patches/fixes, committing appropiately\n5. **Write tests**\n6. Run the tests:\n - `bundle exec foodcritic -f any .`\n - `bundle exec rspec`\n - `bundle exec rubocop`\n - `bundle exec kitchen test`\n\n In detail:\n - Foodcritic will catch any Chef-specific style errors\n - RSpec will run the unit tests\n - Rubocop will check for Ruby-specific style errors\n - Test Kitchen will run and converge the recipes\n\n\n# License & Authors\n\n- Author:: Seth Chisamore ()\n- Author:: Ronald Doorn ()\n- Author:: Martin Smith ()\n- Author:: Sander van Harmelen ()\n\n```text\nCopyright:: 2011-2015, Chef Software, Inc\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n\n[0]: https://mosh.mit.edu/\n","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"centos":">= 0.0.0","debian":">= 0.0.0","ubuntu":">= 0.0.0","windows":">= 0.0.0"},"dependencies":{"chef-sugar":">= 0.0.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/chef-cookbooks/firewall","issues_url":"https://github.com/chef-cookbooks/firewall/issues","chef_version":[[">= 12.5"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/firewall/recipes/default.rb b/cookbooks/firewall/recipes/default.rb new file mode 100644 index 0000000..e301313 --- /dev/null +++ b/cookbooks/firewall/recipes/default.rb @@ -0,0 +1,80 @@ +# +# Cookbook:: firewall +# Recipe:: default +# +# Copyright:: 2011-2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +chef_sugar_cookbook_version = Gem::Version.new(run_context.cookbook_collection['chef-sugar'].metadata.version) + +include_recipe 'chef-sugar' if chef_sugar_cookbook_version < Gem::Version.new('4.0.0') + +firewall 'default' do + ipv6_enabled node['firewall']['ipv6_enabled'] + action :install +end + +# create a variable to use as a condition on some rules that follow +iptables_firewall = rhel? || node['firewall']['ubuntu_iptables'] + +firewall_rule 'allow loopback' do + interface 'lo' + protocol :none + command :allow + only_if { linux? && node['firewall']['allow_loopback'] } +end + +firewall_rule 'allow icmp' do + protocol :icmp + command :allow + # debian ufw doesn't allow 'icmp' protocol, but does open + # icmp by default, so we skip it in default recipe + only_if { (!debian? || iptables_firewall) && node['firewall']['allow_icmp'] } +end + +firewall_rule 'allow world to ssh' do + port 22 + source '0.0.0.0/0' + only_if { linux? && node['firewall']['allow_ssh'] } +end + +firewall_rule 'allow world to winrm' do + port 5989 + source '0.0.0.0/0' + only_if { windows? && node['firewall']['allow_winrm'] } +end + +firewall_rule 'allow world to mosh' do + protocol :udp + port 60000..61000 + source '0.0.0.0/0' + only_if { linux? && node['firewall']['allow_mosh'] } +end + +# allow established connections, ufw defaults to this but iptables does not +firewall_rule 'established' do + stateful [:related, :established] + protocol :none # explicitly don't specify protocol + command :allow + only_if { node['firewall']['allow_established'] && iptables_firewall } +end + +# ipv6 needs ICMP to reliably work, so ensure it's enabled if ipv6 +# allow established connections, ufw defaults to this but iptables does not +firewall_rule 'ipv6_icmp' do + protocol :'ipv6-icmp' + command :allow + only_if { node['firewall']['ipv6_enabled'] && node['firewall']['allow_established'] && iptables_firewall } +end diff --git a/cookbooks/firewall/recipes/disable_firewall.rb b/cookbooks/firewall/recipes/disable_firewall.rb new file mode 100644 index 0000000..330953d --- /dev/null +++ b/cookbooks/firewall/recipes/disable_firewall.rb @@ -0,0 +1,23 @@ +# +# Cookbook:: firewall +# Recipe:: disable_firewall +# +# Copyright:: 2011-2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Disable platform default firewall +firewall 'default' do + action :disable +end diff --git a/cookbooks/firewall/templates/default/ufw/default.erb b/cookbooks/firewall/templates/default/ufw/default.erb new file mode 100644 index 0000000..5e6e9c2 --- /dev/null +++ b/cookbooks/firewall/templates/default/ufw/default.erb @@ -0,0 +1,13 @@ +# /etc/default/ufw +# This file is managed by Chef. Do not edit. + +IPV6=<%= node['firewall']['ufw']['defaults']['ipv6'] %> +MANAGE_BUILTINS=<%= node['firewall']['ufw']['defaults']['manage_builtins'] %> + +<% node['firewall']['ufw']['defaults']['policy'].each do |policy, value| -%> +<%= "DEFAULT_#{policy.upcase}_POLICY=\"#{value}\"" %> +<% end -%> + +IPT_SYSCTL="<%= node['firewall']['ufw']['defaults']['ipt_sysctl'] %>" + +IPT_MODULES="<%= node['firewall']['ufw']['defaults']['ipt_modules'] %>" diff --git a/cookbooks/git/.foodcritic b/cookbooks/git/.foodcritic new file mode 100644 index 0000000..b9f8767 --- /dev/null +++ b/cookbooks/git/.foodcritic @@ -0,0 +1 @@ +~FC016 diff --git a/cookbooks/git/CHANGELOG.md b/cookbooks/git/CHANGELOG.md new file mode 100644 index 0000000..d2f2797 --- /dev/null +++ b/cookbooks/git/CHANGELOG.md @@ -0,0 +1,257 @@ +# git Cookbook CHANGELOG + +This file is used to list changes made in each version of the git cookbook. + +## 6.0.0 (2017-02-14) + +- Fail on deprecations is now enabled so we're fully Chef 13 compatible +- Define the chefspec matchers properly +- Remove the legacy platform mappings that fail on Chef 13 +- Improve the test cookbook / integration tests +- Convert config LWRP to a custom resource and make it fully idempotent +- Require Chef 12.5 or later + +## 5.0.2 (2017-01-18) + +- Remove arch for the metadata +- Avoid deprecation warning during testing +- respond_to?(:chef_version) for < 12.6 compat + +## 5.0.1 (2016-09-15) + +- Clarify we require Chef 12.1 or later + +## 5.0.0 (2016-09-02) + +- Require Chef 12 or later +- Don't depend on the windows cookbook since windows_package is built into Chef 12 +- Updates for testing + +## v4.6.0 (2016-07-05) + +- Added support for compiling git on suse +- Added the ability to pass a new group property to the config provider +- Documented the git_config provider +- Added the tar package on RHEL/Fedora for source installs as some minimal installs lack this package +- Added suse, opensuse, and opensuseleap as supported platforms in the metadata +- Switched to inspec for testing +- Switched to cookstyle for Ruby linting +- Added Travis integration testing of Debian 7/8 + +## v4.5.0 (2016-04-28) + +- Update git versions to 2.8.1 + +## v4.4.1 (2016-03-31) + +- PR #95 support 32 bit and 64 bit installs on windows @smurawski + +## v4.4.0 (2016-03-23) + +- PR #93 bump to latest git @ksubrama + +## v4.3.7 (2016-02-03) + +- PR #90 port node[git][server][export_all] to true/false @scalp42 +- PR #89 make attributes more wrapper friendly @scalp42 +- Update testing deps + rubocop fixes +- README fix @zverulacis + +## v4.3.6 (2016-01-25) + +- Windows fixes + +## v4.3.5 (2015-12-15) + +- Fixed installation on Windows nodes +- Removed the last of the Chef 10 compatibility code +- Added up to date contributing and testing docs +- Updated test deps in the Gemfile +- Removed test kitchen digital ocean config +- Test with kitchen-docker in Travis CI +- Removed uncessary windows cookbook entry from the Berksfile +- Added the chef standard rubocop.yml file and resolved all warnings +- Added chefignore file +- Removed bin dir +- Added maintainers.md and maintainers.toml files +- Added travis and supermarket version badges to the readme + +## v4.3.4 (2015-09-06) + +- Fixing package_id on OSX +- Adding 2.5.1 data for Windows + +## v4.3.3 (2015-07-27) + +- # 76: Use checksum keyname instead of value in source recipe + +## v4.3.2 (2015-07-27) + +- Fixing up Windows provider (issue #73) +- Supporting changes to source_prefix in source provider (#62) + +## v4.3.1 (2015-07-23) + +- Fixing up osx_dmg_source_url + +## v4.3.0 (2015-07-20) + +- Removing references to node attributes from provider code +- Name-spacing of client resource property names +- Addition of windows recipe +- Creation of package recipe + +## v4.2.4 (2015-07-19) + +- Fixing source provider selection bug from 4.2.3 + +## v4.2.3 (2015-07-18) + +- mac_os_x provider mapping +- various rubocops + +## v4.2.2 (2015-04-23) + +- Fix up action in Chef::Resource::GitService +- Adding matchers + +## v4.2.1 (2015-04-17) + +- Fixing Chef 11 support. +- Adding provider mapping file + +## v4.2.0 (2015-04-15) + +- Converting recipes to resources. +- Keeping recipe interface for backwards compat + +## v4.1.0 (2014-12-23) + +- Fixing windows package checksums +- Various test coverage additions + +## v4.0.2 (2014-04-23) + +- [COOK-4482] - Add FreeBSD support for installing git client + +## v4.0.0 (2014-03-18) + +- [COOK-4397] Only use_inline_resources on Chef 11 + +## v3.1.0 (2014-03-12) + +- [COOK-4392] - Cleanup git_config LWRP + +## v3.0.0 (2014-02-28) + +[COOK-4387] Add git_config type [COOK-4388] Fix up rubocops [COOK-4390] Add integration tests for default and server suites + +## v2.10.0 (2014-02-25) + +- [COOK-4146] - wrong dependency in git::source for rhel 6 +- [COOK-3947] - Git cookbook adds itself to the path every run + +## v2.9.0 + +Updating to depend on cookbook yum ~> 3 Fixing style to pass rubocop Updating test scaffolding + +## v2.8.4 + +fixing metadata version error. locking to 3.0 + +## v2.8.1 + +Locking yum dependency to '< 3' + +## v2.8.0 + +### Bug + +- [COOK-3433] - git::server does not correctly set git-daemon's base-path on Debian + +## v2.7.0 + +### Bug + +- **[COOK-3624](https://tickets.chef.io/browse/COOK-3624)** - Don't restart `xinetd` on each Chef client run +- **[COOK-3482](https://tickets.chef.io/browse/COOK-3482)** - Force git to add itself to the current process' PATH + +### New Feature + +- **[COOK-3223](https://tickets.chef.io/browse/COOK-3223)** - Support Omnios and SmartOS package installs + +## v2.6.0 + +### Improvement + +- **[COOK-3193](https://tickets.chef.io/browse/COOK-3193)** - Add proper debian packages + +## v2.5.2 + +### Bug + +- [COOK-2813]: Fix bad string interpolation in source recipe + +## v2.5.0 + +- Relax runit version constraint (now depend on 1.0+). + +## v2.4.0 + +- [COOK-2734] - update git versions + +## v2.3.0 + +- [COOK-2385] - update git::server for `runit_service` resource support + +## v2.2.0 + +- [COOK-2303] - git::server support for RHEL `platform_family` + +## v2.1.4 + +- [COOK-2110] - initial test-kitchen support (only available in GitHub repository) +- [COOK-2253] - pin runit dependency + +## v2.1.2 + +- [COOK-2043] - install git on ubuntu 12.04 not git-core + +## v2.1.0 + +The repository didn't have pushed commits, and so the following changes from earlier-than-latest versions wouldn't be available on the community site. We're releasing 2.1.0 to correct this. + +- [COOK-1943] - Update to git 1.8.0 +- [COOK-2020] - Add setup option attributes to Git Windows package install + +## v2.0.0 + +This version uses `platform_family` attribute, making the cookbook incompatible with older versions of Chef/Ohai, hence the major version bump. + +- [COOK-1668] - git cookbook fails to run due to bad `platform_family` call +- [COOK-1759] - git::source needs additional package for rhel `platform_family` + +## v1.1.2 + +- [COOK-2020] - Add setup option attributes to Git Windows package install + +## v1.1.0 + +- [COOK-1943] - Update to git 1.8.0 + +## v1.0.2 + +- [COOK-1537] - add recipe for source installation + +## v1.0.0 + +- [COOK-1152] - Add support for Mac OS X +- [COOK-1112] - Add support for Windows + +## v0.10.0 + +- [COOK-853] - Git client installation on CentOS + +## v0.9.0 + +- Current public release diff --git a/cookbooks/git/CONTRIBUTING.md b/cookbooks/git/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/git/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/cookbooks/git/MAINTAINERS.md b/cookbooks/git/MAINTAINERS.md new file mode 100644 index 0000000..645ed14 --- /dev/null +++ b/cookbooks/git/MAINTAINERS.md @@ -0,0 +1,15 @@ + + +# Maintainers + +This file lists how this cookbook project is maintained. When making changes to the system, this file tells you who needs to review your patch - you need a review from an existing maintainer for the cookbook to provide a :+1: on your pull request. Additionally, you need to not receive a veto from a Lieutenant or the Project Lead. + +Check out [How Cookbooks are Maintained](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD) for details on the process and how to become a maintainer or the project lead. + +# Project Maintainer +* [Tim Smith](https://github.com/tas50) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) diff --git a/cookbooks/git/README.md b/cookbooks/git/README.md new file mode 100644 index 0000000..2196803 --- /dev/null +++ b/cookbooks/git/README.md @@ -0,0 +1,161 @@ +# Git Cookbook + +[![Build Status](https://travis-ci.org/chef-cookbooks/git.svg?branch=master)](https://travis-ci.org/chef-cookbooks/git) [![Cookbook Version](https://img.shields.io/cookbook/v/git.svg)](https://supermarket.chef.io/cookbooks/git) + +Installs git_client from package or source. Optionally sets up a git service under xinetd. + +## Scope + +This cookbook is concerned with the Git SCM utility. It does not address ecosystem tooling or related projects. + +## Requirements + +### Platforms + +The following platforms have been tested with Test Kitchen: + +``` +|---------------+-------| +| centos-6 | X | +|---------------+-------| +| centos-7 | X | +|---------------+-------| +| fedora | X | +|---------------+-------| +| debian-7 | X | +|---------------+-------| +| debian-8 | X | +|---------------+-------| +| ubuntu-14.04 | X | +|---------------+-------| +| ubuntu-16.04 | X | +|---------------+-------| +| openSUSE 13.2 | X | +|---------------+-------| +| openSUSE Leap | X | +|---------------+-------| +``` + +### Chef + +- Chef 12.5+ + +### Cookbooks + +- depends 'build-essential' - For compiling from source +- depends 'dmg' - For macOS Support +- depends 'yum-epel' - For older RHEL platform_family support + +## Usage + +Add `git::default`, `git::source` or `git::windows` to your run_list OR add `depends 'git', '~> 4.3'` to your cookbook's metadata.rb. include_recipe one of the recipes from your cookbook OR use the git_client resource directly, the same way you'd use core Chef resources (file, template, directory, package, etc). + +## Resources Overview + +- `git_client`: Manages a Git client installation on a machine. Acts as a singleton when using the (default) package provider. Source provider available as well. +- `git_service`: Sets up a Git service via xinetd. WARNING: This is insecure and will probably be removed in the future +- `git_config`: Sets up Git configuration on a node. + +### git_client + +The `git_client` resource manages the installation of a Git client on a machine. + +#### Example + +```ruby +git_client 'default' do + action :install +end +``` + +### git_config + +The `git_config` resource manages the configuration of Git client on a machine. + +#### Example + +```ruby +git_config 'url.https://github.com/.insteadOf' do + value 'git://github.com/' + scope 'system' + options '--add' +end +``` + +#### Properties + +Currently, there are distinct sets of resource properties, used by the providers for source, package, macos, and windows. + +# used by linux package providers + +- `package_name` - Package name to install on Linux machines. Defaults to a calculated value based on platform. +- `package_version` - Defaults to nil. +- `package_action` - Defaults to `:install` + +# used by source providers + +- `source_prefix` - Defaults to '/usr/local' +- `source_url` - Defaults to a calculated URL based on source_version +- `source_version` - Defaults to 2.7.4 +- `source_use_pcre` - configure option for build. Defaults to false +- `source_checksum` - Defaults to a known value for the 2.7.4 source tarball + +# used by OSX package providers + +- `osx_dmg_app_name` - Defaults to 'git-2.7.1-intel-universal-mavericks' +- `osx_dmg_package_id` - Defaults to 'GitOSX.Installer.git271.git.pkg' +- `osx_dmg_volumes_dir` - Defaults to 'Git 2.7.1 Mavericks Intel Universal' +- `osx_dmg_url` - Defaults to Sourceforge +- `osx_dmg_checksum` - Defaults to the value for 2.7.1 + +# used by the Windows package providers + +- `windows_display_name` - Windows display name +- `windows_package_url` - Defaults to the Internet +- `windows_package_checksum` - Defaults to the value for 2.7.4 + +## Recipes + +This cookbook ships with ready to use, attribute driven recipes that utilize the `git_client` and `git_service` resources. As of cookbook 4.x, they utilize the same attributes layout scheme from the 3.x. Due to some overlap, it is currently impossible to simultaneously install the Git client as a package and from source by using the "manipulate a the node attributes and run a recipe" technique. If you need both, you'll need to utilize the git_client resource in a recipe. + +## Attributes + +### Windows + +- `node['git']['version']` - git version to install +- `node['git']['url']` - URL to git package +- `node['git']['checksum']` - package SHA256 checksum +- `node['git']['display_name']` - `windows_package` resource Display Name (makes the package install idempotent) + +### Mac OS X + +- `node['git']['osx_dmg']['url']` - URL to git package +- `node['git']['osx_dmg']['checksum']` - package SHA256 checksum + +### Linux + +- `node['git']['prefix']` - git install directory +- `node['git']['version']` - git version to install +- `node['git']['url']` - URL to git tarball +- `node['git']['checksum']` - tarball SHA256 checksum +- `node['git']['use_pcre']` - if true, builds git with PCRE enabled + +## License & Authors + +- Author:: Joshua Timberman ([joshua@chef.io](mailto:joshua@chef.io)) +- Author:: Sean OMeara ([sean@sean.io](mailto:sean@sean.io)) +- Copyright:: 2009-2017, Chef Software, Inc. + +``` +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/cookbooks/git/attributes/default.rb b/cookbooks/git/attributes/default.rb new file mode 100644 index 0000000..a8b339e --- /dev/null +++ b/cookbooks/git/attributes/default.rb @@ -0,0 +1,47 @@ +# +# Author:: Jamie Winsor () +# Cookbook:: git +# Attributes:: default +# +# Copyright:: 2008-2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the 'License'); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an 'AS IS' BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +case node['platform_family'] +when 'windows' + default['git']['version'] = '2.8.1' + if node['kernel']['machine'] == 'x86_64' + default['git']['architecture'] = '64' + default['git']['checksum'] = '5e5283990cc91d1e9bd0858f8411e7d0afb70ce26e23680252fb4869288c7cfb' + else + default['git']['architecture'] = '32' + default['git']['checksum'] = '17418c2e507243b9c98db161e9e5e8041d958b93ce6078530569b8edaec6b8a4' + end + default['git']['url'] = 'https://github.com/git-for-windows/git/releases/download/v%{version}.windows.1/Git-%{version}-%{architecture}-bit.exe' + default['git']['display_name'] = "Git version #{node['git']['version']}" +when 'mac_os_x' + default['git']['osx_dmg']['app_name'] = 'git-2.8.1-intel-universal-mavericks' + default['git']['osx_dmg']['volumes_dir'] = 'Git 2.8.1 Mavericks Intel Universal' + default['git']['osx_dmg']['package_id'] = 'GitOSX.Installer.git281Universal.git.pkg' + default['git']['osx_dmg']['url'] = 'http://sourceforge.net/projects/git-osx-installer/files/git-2.8.1-intel-universal-mavericks.dmg/download' + default['git']['osx_dmg']['checksum'] = 'c2912895a1e2018d9be4c646765d511f7c82e0114275505dbd13d1ac70c62023' +else + default['git']['prefix'] = '/usr/local' + default['git']['version'] = '2.8.1' + default['git']['url'] = 'https://nodeload.github.com/git/git/tar.gz/v%{version}' + default['git']['checksum'] = 'e08503ecaf5d3ac10c40f22871c996a392256c8d038d16f52ebf974cba29ae42' + default['git']['use_pcre'] = false +end + +default['git']['server']['base_path'] = '/srv/git' +default['git']['server']['export_all'] = true diff --git a/cookbooks/git/libraries/helpers.rb b/cookbooks/git/libraries/helpers.rb new file mode 100644 index 0000000..bedde84 --- /dev/null +++ b/cookbooks/git/libraries/helpers.rb @@ -0,0 +1,48 @@ +module GitCookbook + module Helpers + # linux packages default to distro offering + def parsed_package_name + return new_resource.package_name if new_resource.package_name + return 'git-core' if node['platform'] == 'ubuntu' && node['platform_version'].to_f < 10.10 + return 'developer/versioning/git' if node['platform'] == 'omnios' + return 'scmgit' if node['platform'] == 'smartos' + 'git' + end + + def parsed_package_version + return new_resource.package_version if new_resource.package_version + end + + # source + def parsed_source_url + return new_resource.source_url if new_resource.source_url + "https://nodeload.github.com/git/git/tar.gz/v#{new_resource.source_version}" + end + + def parsed_source_checksum + return new_resource.source_checksum if new_resource.source_checksum + '8d53703d75890c03e26a915c7af3b7b98d8cfb94382f685a9bcbee1eeaec47b4' # 2.7.4 tarball + end + + # windows + def parsed_windows_display_name + return new_resource.windows_display_name if new_resource.windows_display_name + "Git version #{parsed_windows_package_version}" + end + + def parsed_windows_package_version + return new_resource.windows_package_version if new_resource.windows_package_version + '2.7.4' + end + + def parsed_windows_package_url + return new_resource.windows_package_url if new_resource.windows_package_url + "https://github.com/git-for-windows/git/releases/download/v%#{parsed_windows_package_version}.windows.1/Git-%#{parsed_windows_package_version}-32-bit.exe" + end + + def parsed_windows_package_checksum + return new_resource.windows_package_checksum if new_resource.windows_package_checksum + '49601d5102df249d6f866ecfa1eea68eb5672acc1dbb7e4051099e792f6da5fc' + end + end +end diff --git a/cookbooks/git/libraries/matchers.rb b/cookbooks/git/libraries/matchers.rb new file mode 100644 index 0000000..25ed8df --- /dev/null +++ b/cookbooks/git/libraries/matchers.rb @@ -0,0 +1,16 @@ +if defined?(ChefSpec) + ChefSpec.define_matcher(:git_client) + ChefSpec.define_matcher(:git_service) + + def set_git_config(resource_name) # rubocop:disable Style/AccessorMethodName + ChefSpec::Matchers::ResourceMatcher.new(:git_config, :set, resource_name) + end + + def install_git_client(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:git_client, :install, resource_name) + end + + def install_git_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:git_service, :install, resource_name) + end +end diff --git a/cookbooks/git/libraries/provider_git_client.rb b/cookbooks/git/libraries/provider_git_client.rb new file mode 100644 index 0000000..41d7cfd --- /dev/null +++ b/cookbooks/git/libraries/provider_git_client.rb @@ -0,0 +1,13 @@ +class Chef + class Provider + class GitClient < Chef::Provider::LWRPBase + use_inline_resources + + def whyrun_supported? + true + end + + include GitCookbook::Helpers + end + end +end diff --git a/cookbooks/git/libraries/provider_git_client_osx.rb b/cookbooks/git/libraries/provider_git_client_osx.rb new file mode 100644 index 0000000..db604c9 --- /dev/null +++ b/cookbooks/git/libraries/provider_git_client_osx.rb @@ -0,0 +1,26 @@ +class Chef + class Provider + class GitClient + class Osx < Chef::Provider::GitClient + include Chef::DSL::IncludeRecipe + + provides :git_client, os: 'mac_os_x' + + action :install do + dmg_package 'GitOSX-Installer' do + app new_resource.osx_dmg_app_name + package_id new_resource.osx_dmg_package_id + volumes_dir new_resource.osx_dmg_volumes_dir + source new_resource.osx_dmg_url + checksum new_resource.osx_dmg_checksum + type 'pkg' + action :install + end + end + + action :delete do + end + end + end + end +end diff --git a/cookbooks/git/libraries/provider_git_client_package.rb b/cookbooks/git/libraries/provider_git_client_package.rb new file mode 100644 index 0000000..8c750e3 --- /dev/null +++ b/cookbooks/git/libraries/provider_git_client_package.rb @@ -0,0 +1,27 @@ +class Chef + class Provider + class GitClient + class Package < Chef::Provider::GitClient + include Chef::DSL::IncludeRecipe + + provides :git_client, os: 'linux' + + action :install do + # FIXME: rhel 5 + include_recipe 'yum-epel' if node['platform_family'] == 'rhel' && node['platform_version'].to_i == 5 + + # Software installation + package "#{new_resource.name} :create #{parsed_package_name}" do + package_name parsed_package_name + version parsed_package_version + action new_resource.package_action + action :install + end + end + + action :delete do + end + end + end + end +end diff --git a/cookbooks/git/libraries/provider_git_client_source.rb b/cookbooks/git/libraries/provider_git_client_source.rb new file mode 100644 index 0000000..6ab8bc7 --- /dev/null +++ b/cookbooks/git/libraries/provider_git_client_source.rb @@ -0,0 +1,66 @@ +class Chef + class Provider + class GitClient + class Source < Chef::Provider::GitClient + include Chef::DSL::IncludeRecipe + + action :install do + return "#{node['platform']} is not supported by the #{cookbook_name}::#{recipe_name} recipe" unless platform_family?('rhel', 'suse', 'fedora', 'debian') + + include_recipe 'build-essential' + include_recipe 'yum-epel' if node['platform_family'] == 'rhel' && node['platform_version'].to_i == 5 + + # move this to attributes. + case node['platform_family'] + when 'fedora' + pkgs = %w(tar openssl-devel libcurl-devel expat-devel perl-ExtUtils-MakeMaker) + when 'rhel' + case node['platform_version'].to_i + when 5 + pkgs = %w(tar expat-devel gettext-devel curl-devel openssl-devel zlib-devel) + pkgs += %w( pcre-devel ) if new_resource.source_use_pcre + when 6, 7 + pkgs = %w(tar expat-devel gettext-devel libcurl-devel openssl-devel perl-ExtUtils-MakeMaker zlib-devel) + pkgs += %w( pcre-devel ) if new_resource.source_use_pcre + else + pkgs = %w(expat-devel gettext-devel curl-devel openssl-devel perl-ExtUtils-MakeMaker zlib-devel) if node['platform'] == 'amazon' + pkgs += %w( pcre-devel ) if new_resource.source_use_pcre + end + when 'debian' + pkgs = %w(libcurl4-gnutls-dev libexpat1-dev gettext libz-dev libssl-dev) + pkgs += %w( libpcre3-dev ) if new_resource.source_use_pcre + when 'suse' + pkgs = %w(tar libcurl-devel libexpat-devel gettext-tools zlib-devel libopenssl-devel) + pkgs += %w( libpcre2-devel ) if new_resource.source_use_pcre + end + + package pkgs + + # reduce line-noise-eyness + remote_file "#{Chef::Config['file_cache_path']}/git-#{new_resource.source_version}.tar.gz" do + source parsed_source_url # helpers.rb + checksum parsed_source_checksum # helpers.rb + mode '0644' + not_if "test -f #{Chef::Config['file_cache_path']}/git-#{new_resource.source_version}.tar.gz" + end + + # reduce line-noise-eyness + execute "Extracting and Building Git #{new_resource.source_version} from Source" do + cwd Chef::Config['file_cache_path'] + additional_make_params = '' + additional_make_params += 'USE_LIBPCRE=1' if new_resource.source_use_pcre + command <<-COMMAND + (mkdir git-#{new_resource.source_version} && tar -zxf git-#{new_resource.source_version}.tar.gz -C git-#{new_resource.source_version} --strip-components 1) + (cd git-#{new_resource.source_version} && make prefix=#{new_resource.source_prefix} #{additional_make_params} install) + COMMAND + not_if "git --version | grep #{new_resource.source_version}" + not_if "#{new_resource.source_prefix}/bin/git --version | grep #{new_resource.source_version}" + end + end + + action :delete do + end + end + end + end +end diff --git a/cookbooks/git/libraries/provider_git_client_windows.rb b/cookbooks/git/libraries/provider_git_client_windows.rb new file mode 100644 index 0000000..305cdd2 --- /dev/null +++ b/cookbooks/git/libraries/provider_git_client_windows.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true +class Chef + class Provider + class GitClient + class Windows < Chef::Provider::GitClient + include Chef::DSL::IncludeRecipe + + provides :git_client, os: 'windows' + + action :install do + windows_package parsed_windows_display_name do + action :install + source parsed_windows_package_url + checksum parsed_windows_package_checksum + installer_type :inno + end + + # Git is installed to Program Files (x86) on 64-bit machines and + # 'Program Files' on 32-bit machines + PROGRAM_FILES = if node['git']['architecture'] == '32' + ENV['ProgramFiles(x86)'] || ENV['ProgramFiles'] + else + ENV['ProgramW6432'] || ENV['ProgramFiles'] + end + GIT_PATH = "#{PROGRAM_FILES}\\Git\\Cmd".freeze + + # COOK-3482 - windows_path resource doesn't change the current process + # environment variables. Therefore, git won't actually be on the PATH + # until the next chef-client run + ruby_block 'Add Git Path' do + block do + ENV['PATH'] += ";#{GIT_PATH}" + end + not_if { ENV['PATH'] =~ /GIT_PATH/ } + action :nothing + end + + windows_path GIT_PATH do + notifies :create, 'ruby_block[Add Git Path]', :immediately + action :add + end + end + + action :delete do + end + end + end + end +end diff --git a/cookbooks/git/libraries/provider_git_service.rb b/cookbooks/git/libraries/provider_git_service.rb new file mode 100644 index 0000000..7f74e90 --- /dev/null +++ b/cookbooks/git/libraries/provider_git_service.rb @@ -0,0 +1,57 @@ +class Chef + class Provider + class GitClient < Chef::Provider::LWRPBase + use_inline_resources + + def whyrun_supported? + true + end + + include Chef::DSL::IncludeRecipe + include GitCookbook::Helpers + + provides :git_service, os: 'linux' + + action :create do + return "#{node['platform']} is not supported by the #{cookbook_name}::#{recipe_name} recipe" if node['platform'] == 'windows' + + include_recipe 'git' + + directory new_resource.service_base_path do + owner 'root' + group 'root' + mode '0755' + end + + case node['platform_family'] + when 'debian' + package 'xinetd' + when 'rhel' + package 'git-daemon' + else + log 'Platform requires setting up a git daemon service script.' + log "Hint: /usr/bin/git daemon --export-all --user=nobody --group=daemon --base-path=#{new_resource.service_base_path}" + return + end + + template '/etc/xinetd.d/git' do + backup false + source 'git-xinetd.d.erb' + owner 'root' + group 'root' + mode '0644' + variables( + git_daemon_binary: value_for_platform_family( + 'debian' => '/usr/lib/git-core/git-daemon', + 'rhel' => '/usr/libexec/git-core/git-daemon' + ) + ) + end + + service 'xinetd' do + action [:enable, :restart] + end + end + end + end +end diff --git a/cookbooks/git/libraries/provider_git_service_xinetd.rb b/cookbooks/git/libraries/provider_git_service_xinetd.rb new file mode 100644 index 0000000..74b524e --- /dev/null +++ b/cookbooks/git/libraries/provider_git_service_xinetd.rb @@ -0,0 +1,55 @@ +class Chef + class Provider + class GitClient < Chef::Provider::LWRPBase + use_inline_resources + + def whyrun_supported? + true + end + + include Chef::DSL::IncludeRecipe + include GitCookbook::Helpers + + action :create do + return "#{node['platform']} is not supported by the #{cookbook_name}::#{recipe_name} recipe" if node['platform'] == 'windows' + + include_recipe 'git' + + directory new_resource.service_base_path do + owner 'root' + group 'root' + mode '0755' + end + + case node['platform_family'] + when 'debian' + package 'xinetd' + when 'rhel' + package 'git-daemon' + else + log 'Platform requires setting up a git daemon service script.' + log "Hint: /usr/bin/git daemon --export-all --user=nobody --group=daemon --base-path=#{new_resource.service_base_path}" + return + end + + template '/etc/xinetd.d/git' do + backup false + source 'git-xinetd.d.erb' + owner 'root' + group 'root' + mode '0644' + variables( + git_daemon_binary: value_for_platform_family( + 'debian' => '/usr/lib/git-core/git-daemon', + 'rhel' => '/usr/libexec/git-core/git-daemon' + ) + ) + end + + service 'xinetd' do + action [:enable, :restart] + end + end + end + end +end diff --git a/cookbooks/git/libraries/resource_git_client.rb b/cookbooks/git/libraries/resource_git_client.rb new file mode 100644 index 0000000..c426ebe --- /dev/null +++ b/cookbooks/git/libraries/resource_git_client.rb @@ -0,0 +1,38 @@ +require 'chef/resource/lwrp_base' + +class Chef + class Resource + class GitClient < Chef::Resource::LWRPBase + self.resource_name = :git_client + actions :install, :remove + default_action :install + + provides :git_client + + # used by source providers + attribute :source_checksum, kind_of: String, default: nil + attribute :source_prefix, kind_of: String, default: '/usr/local' + attribute :source_url, kind_of: String, default: nil + attribute :source_use_pcre, kind_of: [TrueClass, FalseClass], default: false + attribute :source_version, kind_of: String, default: nil + + # used by linux package providers + attribute :package_name, kind_of: String, default: nil + attribute :package_version, kind_of: String, default: nil + attribute :package_action, kind_of: Symbol, default: :install + + # used by OSX package providers + attribute :osx_dmg_app_name, kind_of: String, default: 'git-2.7.1-intel-universal-mavericks' + attribute :osx_dmg_package_id, kind_of: String, default: 'GitOSX.Installer.git271.git.pkg' + attribute :osx_dmg_volumes_dir, kind_of: String, default: 'Git 2.7.1 Mavericks Intel Universal' + attribute :osx_dmg_url, kind_of: String, default: 'http://sourceforge.net/projects/git-osx-installer/files/git-2.7.1-intel-universal-mavericks.dmg/download' + attribute :osx_dmg_checksum, kind_of: String, default: '260b32e8877eb72d07807b26163aeec42e2d98c350f32051ab1ff0cc33626440' # 2.7.1 + + # used by Windows providers + attribute :windows_display_name, kind_of: String, default: nil + attribute :windows_package_url, kind_of: String, default: nil + attribute :windows_package_checksum, kind_of: String, default: nil + attribute :windows_package_version, kind_of: String, default: nil + end + end +end diff --git a/cookbooks/git/libraries/resource_git_service.rb b/cookbooks/git/libraries/resource_git_service.rb new file mode 100644 index 0000000..a1f2343 --- /dev/null +++ b/cookbooks/git/libraries/resource_git_service.rb @@ -0,0 +1,16 @@ +require 'chef/resource/lwrp_base' + +class Chef + class Resource + class GitService < Chef::Resource::LWRPBase + self.resource_name = :git_service + actions :create + default_action :create + + provides :git_service + + # used by the service xinetd provider + attribute :service_base_path, kind_of: String, default: '/srv/git' + end + end +end diff --git a/cookbooks/git/metadata.json b/cookbooks/git/metadata.json new file mode 100644 index 0000000..28f80e7 --- /dev/null +++ b/cookbooks/git/metadata.json @@ -0,0 +1 @@ +{"name":"git","version":"6.0.0","description":"Installs git and/or sets up a Git server daemon","long_description":"# Git Cookbook\n\n[![Build Status](https://travis-ci.org/chef-cookbooks/git.svg?branch=master)](https://travis-ci.org/chef-cookbooks/git) [![Cookbook Version](https://img.shields.io/cookbook/v/git.svg)](https://supermarket.chef.io/cookbooks/git)\n\nInstalls git_client from package or source. Optionally sets up a git service under xinetd.\n\n## Scope\n\nThis cookbook is concerned with the Git SCM utility. It does not address ecosystem tooling or related projects.\n\n## Requirements\n\n### Platforms\n\nThe following platforms have been tested with Test Kitchen:\n\n```\n|---------------+-------|\n| centos-6 | X |\n|---------------+-------|\n| centos-7 | X |\n|---------------+-------|\n| fedora | X |\n|---------------+-------|\n| debian-7 | X |\n|---------------+-------|\n| debian-8 | X |\n|---------------+-------|\n| ubuntu-14.04 | X |\n|---------------+-------|\n| ubuntu-16.04 | X |\n|---------------+-------|\n| openSUSE 13.2 | X |\n|---------------+-------|\n| openSUSE Leap | X |\n|---------------+-------|\n```\n\n### Chef\n\n- Chef 12.5+\n\n### Cookbooks\n\n- depends 'build-essential' - For compiling from source\n- depends 'dmg' - For macOS Support\n- depends 'yum-epel' - For older RHEL platform_family support\n\n## Usage\n\nAdd `git::default`, `git::source` or `git::windows` to your run_list OR add `depends 'git', '~> 4.3'` to your cookbook's metadata.rb. include_recipe one of the recipes from your cookbook OR use the git_client resource directly, the same way you'd use core Chef resources (file, template, directory, package, etc).\n\n## Resources Overview\n\n- `git_client`: Manages a Git client installation on a machine. Acts as a singleton when using the (default) package provider. Source provider available as well.\n- `git_service`: Sets up a Git service via xinetd. WARNING: This is insecure and will probably be removed in the future\n- `git_config`: Sets up Git configuration on a node.\n\n### git_client\n\nThe `git_client` resource manages the installation of a Git client on a machine.\n\n#### Example\n\n```ruby\ngit_client 'default' do\n action :install\nend\n```\n\n### git_config\n\nThe `git_config` resource manages the configuration of Git client on a machine.\n\n#### Example\n\n```ruby\ngit_config 'url.https://github.com/.insteadOf' do\n value 'git://github.com/'\n scope 'system'\n options '--add'\nend\n```\n\n#### Properties\n\nCurrently, there are distinct sets of resource properties, used by the providers for source, package, macos, and windows.\n\n# used by linux package providers\n\n- `package_name` - Package name to install on Linux machines. Defaults to a calculated value based on platform.\n- `package_version` - Defaults to nil.\n- `package_action` - Defaults to `:install`\n\n# used by source providers\n\n- `source_prefix` - Defaults to '/usr/local'\n- `source_url` - Defaults to a calculated URL based on source_version\n- `source_version` - Defaults to 2.7.4\n- `source_use_pcre` - configure option for build. Defaults to false\n- `source_checksum` - Defaults to a known value for the 2.7.4 source tarball\n\n# used by OSX package providers\n\n- `osx_dmg_app_name` - Defaults to 'git-2.7.1-intel-universal-mavericks'\n- `osx_dmg_package_id` - Defaults to 'GitOSX.Installer.git271.git.pkg'\n- `osx_dmg_volumes_dir` - Defaults to 'Git 2.7.1 Mavericks Intel Universal'\n- `osx_dmg_url` - Defaults to Sourceforge\n- `osx_dmg_checksum` - Defaults to the value for 2.7.1\n\n# used by the Windows package providers\n\n- `windows_display_name` - Windows display name\n- `windows_package_url` - Defaults to the Internet\n- `windows_package_checksum` - Defaults to the value for 2.7.4\n\n## Recipes\n\nThis cookbook ships with ready to use, attribute driven recipes that utilize the `git_client` and `git_service` resources. As of cookbook 4.x, they utilize the same attributes layout scheme from the 3.x. Due to some overlap, it is currently impossible to simultaneously install the Git client as a package and from source by using the \"manipulate a the node attributes and run a recipe\" technique. If you need both, you'll need to utilize the git_client resource in a recipe.\n\n## Attributes\n\n### Windows\n\n- `node['git']['version']` - git version to install\n- `node['git']['url']` - URL to git package\n- `node['git']['checksum']` - package SHA256 checksum\n- `node['git']['display_name']` - `windows_package` resource Display Name (makes the package install idempotent)\n\n### Mac OS X\n\n- `node['git']['osx_dmg']['url']` - URL to git package\n- `node['git']['osx_dmg']['checksum']` - package SHA256 checksum\n\n### Linux\n\n- `node['git']['prefix']` - git install directory\n- `node['git']['version']` - git version to install\n- `node['git']['url']` - URL to git tarball\n- `node['git']['checksum']` - tarball SHA256 checksum\n- `node['git']['use_pcre']` - if true, builds git with PCRE enabled\n\n## License & Authors\n\n- Author:: Joshua Timberman ([joshua@chef.io](mailto:joshua@chef.io))\n- Author:: Sean OMeara ([sean@sean.io](mailto:sean@sean.io))\n- Copyright:: 2009-2017, Chef Software, Inc.\n\n```\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache 2.0","platforms":{"amazon":">= 0.0.0","centos":">= 0.0.0","debian":">= 0.0.0","fedora":">= 0.0.0","freebsd":">= 0.0.0","mac_os_x":">= 10.6.0","omnios":">= 0.0.0","oracle":">= 0.0.0","redhat":">= 0.0.0","smartos":">= 0.0.0","scientific":">= 0.0.0","suse":">= 0.0.0","opensuse":">= 0.0.0","opensuseleap":">= 0.0.0","ubuntu":">= 0.0.0","windows":">= 0.0.0"},"dependencies":{"build-essential":">= 0.0.0","dmg":">= 0.0.0","yum-epel":">= 0.0.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{"git":"Installs git","git::server":"Sets up a runit_service for git daemon","git::source":"Installs git from source"}} \ No newline at end of file diff --git a/cookbooks/git/recipes/default.rb b/cookbooks/git/recipes/default.rb new file mode 100644 index 0000000..bc7feed --- /dev/null +++ b/cookbooks/git/recipes/default.rb @@ -0,0 +1,19 @@ +# +# Cookbook:: git +# Recipe:: default +# +# Copyright:: 2008-2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include_recipe 'git::package' diff --git a/cookbooks/git/recipes/package.rb b/cookbooks/git/recipes/package.rb new file mode 100644 index 0000000..e8812f6 --- /dev/null +++ b/cookbooks/git/recipes/package.rb @@ -0,0 +1,37 @@ +# +# Cookbook:: git +# Recipe:: package +# +# Copyright:: 2008-2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +case node['platform'] +when 'mac_os_x' + # FIXME: The resource has three distinct groups of properties used in + # different providers... should we make multiple resource types instead? + git_client 'default' do + osx_dmg_app_name node['git']['osx_dmg']['app_name'] + osx_dmg_package_id node['git']['osx_dmg']['package_id'] + osx_dmg_volumes_dir node['git']['osx_dmg']['volumes_dir'] + osx_dmg_url node['git']['osx_dmg']['url'] + osx_dmg_checksum node['git']['osx_dmg']['checksum'] + action :install + end +when 'windows' + include_recipe 'git::windows' +else + git_client 'default' do + action :install + end +end diff --git a/cookbooks/git/recipes/server.rb b/cookbooks/git/recipes/server.rb new file mode 100644 index 0000000..1567cbb --- /dev/null +++ b/cookbooks/git/recipes/server.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: git +# Recipe:: server +# +# Copyright:: 2009-2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +git_service 'default' do + service_base_path node['git']['server']['base_path'] + action :create +end diff --git a/cookbooks/git/recipes/source.rb b/cookbooks/git/recipes/source.rb new file mode 100644 index 0000000..73429d5 --- /dev/null +++ b/cookbooks/git/recipes/source.rb @@ -0,0 +1,28 @@ +# +# Cookbook:: git +# Recipe:: source +# +# Copyright:: 2012-2016, Brian Flad, Fletcher Nichol +# +# 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. + +# drive version from node attributes +git_client 'default' do + provider Chef::Provider::GitClient::Source + source_checksum node['git']['checksum'] + source_prefix node['git']['prefix'] + source_url format(node['git']['url'], version: node['git']['version']) + source_use_pcre node['git']['use_pcre'] + source_version node['git']['version'] + action :install +end diff --git a/cookbooks/git/recipes/windows.rb b/cookbooks/git/recipes/windows.rb new file mode 100644 index 0000000..7fd5882 --- /dev/null +++ b/cookbooks/git/recipes/windows.rb @@ -0,0 +1,24 @@ +# +# Cookbook:: git +# Recipe:: windows +# +# Copyright:: 2008-2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +git_client 'default' do + windows_display_name node['git']['display_name'] + windows_package_url format(node['git']['url'], version: node['git']['version'], architecture: node['git']['architecture']) + windows_package_checksum node['git']['checksum'] + action :install +end diff --git a/cookbooks/git/resources/config.rb b/cookbooks/git/resources/config.rb new file mode 100644 index 0000000..2f3d88c --- /dev/null +++ b/cookbooks/git/resources/config.rb @@ -0,0 +1,49 @@ +property :key, String, name_attribute: true +property :value, String +property :scope, equal_to: %w(local global system), default: 'global', desired_state: false +property :path, String, desired_state: false +property :user, String, desired_state: false +property :group, String, desired_state: false +property :options, String, desired_state: false + +attr_accessor :exists + +require 'mixlib/shellout' + +def initialize(*args) + super + + @run_context.include_recipe 'git' +end + +load_current_value do + cmd_env = user ? { 'USER' => user, 'HOME' => ::Dir.home(user) } : nil + config_vals = Mixlib::ShellOut.new("git config --get --#{scope} #{key}", user: user, group: group, cwd: path, env: cmd_env) + config_vals.run_command + if config_vals.stdout.empty? + value nil + else + value config_vals.stdout.chomp + end +end + +action :set do + converge_if_changed do + execute "#{config_cmd} #{new_resource.key} \"#{new_resource.value}\" #{new_resource.options}".rstrip do + cwd new_resource.path + user new_resource.user + group new_resource.group + environment cmd_env + end + end +end + +action_class.class_eval do + def config_cmd + "git config --#{new_resource.scope}" + end + + def cmd_env + new_resource.user ? { 'USER' => new_resource.user, 'HOME' => ::Dir.home(new_resource.user) } : nil + end +end diff --git a/cookbooks/git/templates/default/git-xinetd.d.erb b/cookbooks/git/templates/default/git-xinetd.d.erb new file mode 100644 index 0000000..3c6bb3b --- /dev/null +++ b/cookbooks/git/templates/default/git-xinetd.d.erb @@ -0,0 +1,10 @@ +service git +{ + disable = no + socket_type = stream + wait = no + user = nobody + server = <%= @git_daemon_binary %> + server_args = --base-path=<%= node["git"]["server"]["base_path"] %> <%= node['git']['server']['export_all'] ? '--export-all' : nil %> --syslog --inetd --verbose + log_on_failure += USERID +} diff --git a/cookbooks/git/templates/default/sv-git-daemon-log-run.erb b/cookbooks/git/templates/default/sv-git-daemon-log-run.erb new file mode 100644 index 0000000..a79a518 --- /dev/null +++ b/cookbooks/git/templates/default/sv-git-daemon-log-run.erb @@ -0,0 +1,2 @@ +#!/bin/sh +exec svlogd -tt ./main diff --git a/cookbooks/git/templates/default/sv-git-daemon-run.erb b/cookbooks/git/templates/default/sv-git-daemon-run.erb new file mode 100644 index 0000000..f340a23 --- /dev/null +++ b/cookbooks/git/templates/default/sv-git-daemon-run.erb @@ -0,0 +1,3 @@ +#!/bin/sh +exec 2>&1 +exec /usr/bin/git daemon <%= node['git']['server']['export_all'] ? '--export-all' : nil %> --user=nobody --group=daemon --syslog --base-path=<%= node["git"]["server"]["base_path"] %> <%= node["git"]["server"]["base_path"] %> diff --git a/cookbooks/homebrew/CHANGELOG.md b/cookbooks/homebrew/CHANGELOG.md new file mode 100644 index 0000000..b63b898 --- /dev/null +++ b/cookbooks/homebrew/CHANGELOG.md @@ -0,0 +1,200 @@ +# homebrew Cookbook CHANGELOG + +This file is used to list changes made in each version of the homebrew cookbook. + +## 3.0.0 (2016-12-19) + +- The homebrew package provider has been removed from this cookbook. It ships with Chef 12.0+. This cookbook now requires a minimum of Chef 12.1 or later. +- This cookbook no longer depends on build-essential as it wasn't using it directly +- Properly define the chefspec matchers +- Add chef_version metadata and remove OS X server which isn't an actual platform from ohai +- Don't grab homebrew_go script if homebrew is already installed. +- Add ability to disable sending analytics data via a new attribute +- Move testing to a test cookbook to make it easier to expand in the future. Also convert integration tests to InSpec from ServerSpec + +## 2.1.2 (2016-09-07) + +- Allow passing custom options to brew packages + +## 2.1.1 (2016-09-06) + +- Run chefspecs as OS X +- Update cask recipe to not create /opt/homebrew-cask and /opt/homebrew-cask/Caskroom +- Update tests + +## v2.1.0 (2016-03-29) + +- Make homebrew install script url configurable +- Make package_info more efficient + +## v2.0.5 (2016-01-25) + +- Updated execute resources to pass in the HOME/USER environmental variables so homebrew commands are properly executed +- Removed redundant code from recipes and providers +- Removed brew-cask installation and the upgade execute that are no longer necessary +- Added directory creation of /Library/Caches/Homebrew/Casks in case it's not present +- Updated creation of /opt/homebrew-cask to be recursive in case /opt hasn't been created yet + +## v2.0.4 (2016-01-20) + +- Use the officially supported method of querying homebrew data vs. unsupported internal APIs +- Fixed environmental variables in the homebrew command execution + +## v2.0.3 (2015-12-09) + +- Fixed poor name matching in determining if a cask had been installed already, which prevented some casks from installing + +## v2.0.2 (2015-12-04) + +- Prevents casks from installing on every chef run + +## v2.0.1 (2015-12-03) + +- Fixed already-installed casks breaking builds + +## v2.0.0 (2015-12-01) + +- Removed all Chef 10 compatibility code +- 77 Update the tap provider to properly notify on changes +- 73 Allow specifying versions (or HEAD) of formulas (see readme for usage) +- Updated contributing, testing, and maintainers docs +- Updated contents of chefignore and .gitignore files +- Updated development dependencies in the Gemfile +- Added Travis CI and supermarket version badges to the readme +- Added Chef standard rubocop file and resolved all warnings +- Added super metadata for Supermarket +- Added testing in Travis CI +- 75 Fix Chefspecs to properly run on Linux hosts (like Travis) +- Add Rakefile for simplified testing +- Resolved all foodcritic warnings + +## v1.13.0 (2015-06-23) + +- 72 Massage Chef12HomebrewUser.find_homebrew_uid into username +- 69 Add options to cask + +## v1.12.0 (2015-01-29) + +- 67 Add attribute and recipe for installing homebrew taps + +## v1.11.0 (2015-01-12) + +- 59 Update Homebrew Cask if auto-update attribute is true +- 52 Manage Homebrew Cask's install directories +- 56 Fix check for existing casks +- 61 Fix owner class for Chef 12 +- Depend on build-essential cookbook 2.1.2+ to support OS X 10.10 +- 64, #66 add and fix ChefSpec tests for default recipe + +## v1.10.0 (2014-12-09) + +- 55 This cookbook no longer sets its `homebrew_package` as the +- `package` provider for OS X when running under Chef 12 +- List CHEF as the maintainer instead of Chef. + +## v1.9.2 (2014-10-09) + +Bug Fixes: + +- 57 Update url per homebrew error: Upstream, the homebrew project +- has changed the URL for the installation script. All users of this +- cookbook are advised to update to this version. + +## v1.9.0 (2014-07-29) + +Improvements: + +- 35 Modernize the cask provider (use why run mode, inline resources) +- 43 Use `brew cask list` to determine if casks are installed +- 45 Add `default_action` and print warning messages on earlier +- versions of Chef (10.10) + +New Features: + +- 44 Add `:install` and `:uninstall` actions and alias previous `:cask`, +- `:uncask` actions to them + +Bug Fixes: + +- 27 Fix name for taps adding the `/homebrew` prefix +- 28 Set `RUBYOPT` to `nil` so Chef can execute in a bundle (bundler +- sets `RUBYOPT` and this can cause issues when running the +- underlying `brew` commands) +- 40 Fix regex for cask to match current homebrew conventions +- 42 Fix attribute for list of formulas to match the README and +- maintain backward compat for 6 day old version + +## v1.8.0 (2014-07-23) + +- Add recipes to install an array of formulas/casks + +## v1.7.2 (2014-06-26) + +- Implement attribute to control auto-update + +## v1.7.0 (2014-06-26) + +# 38 - Add homebrew::cask recipe + +## v1.6.6 (2014-05-29) + +- [COOK-3283] Use homebrew_owner for cask and tap +- [COOK-4670] homebrew_tap provider is not idempotent +- [COOK-4671] Syntax Error in README + +## v1.6.4 (2014-05-08) + +- Fixing cask provider correctly this time. "brew cask list" + +## v1.6.2 (2014-05-08) + +- Fixing typo in cask provider: 's/brew brew/brew/' + +## v1.6.0 (2014-04-23) + +- [COOK-3960] Added LWRP for brew cask +- [COOK-4508] Add ChefSpec matchers for homebrew_tap +- [COOK-4566] Guard against "HEAD only" formulae + +## v1.5.4 + +- [COOK-4023] Fix installer script's URL. +- Fixing up style for rubocop + +## v1.5.2 + +- [COOK-3825] setting $HOME on homebrew_package + +## v1.5.0 + +### Bug + +- **[COOK-3589](https://tickets.chef.io/browse/COOK-3589)** - Add homebrew as the default package manager on OS X Server + +## v1.4.0 + +### Bug + +- **[COOK-3283](https://tickets.chef.io/browse/COOK-3283)** - Support running homebrew cookbook as root user, with sudo, or a non-privileged user + +## v1.3.2 + +- [COOK-1793] - use homebrew "go" script to install homebrew +- [COOK-1821] - Discovered version using Homebrew Formula factory fails check that verifies that version is a String +- [COOK-1843] - Homebrew README.md contains non-ASCII characters, triggering same issue as COOK-522 + +## v1.3.0 + +- [COOK-1425] - use new json output format for formula +- [COOK-1578] - Use shell_out! instead of popen4 + +## v1.2.0 + +Chef Software has taken maintenance of this cookbook as the original author has other commitments. This is the initial release with Chef Software as maintainer. + +Changes in this release: + +- [pull/2] - support for option passing to brew +- [pull/3] - add brew upgrade and control return value from command +- [pull/9] - added LWRP for "brew tap" +- README is now markdown, not rdoc. diff --git a/cookbooks/homebrew/CONTRIBUTING.md b/cookbooks/homebrew/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/homebrew/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/cookbooks/homebrew/MAINTAINERS.md b/cookbooks/homebrew/MAINTAINERS.md new file mode 100644 index 0000000..645ed14 --- /dev/null +++ b/cookbooks/homebrew/MAINTAINERS.md @@ -0,0 +1,15 @@ + + +# Maintainers + +This file lists how this cookbook project is maintained. When making changes to the system, this file tells you who needs to review your patch - you need a review from an existing maintainer for the cookbook to provide a :+1: on your pull request. Additionally, you need to not receive a veto from a Lieutenant or the Project Lead. + +Check out [How Cookbooks are Maintained](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD) for details on the process and how to become a maintainer or the project lead. + +# Project Maintainer +* [Tim Smith](https://github.com/tas50) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) diff --git a/cookbooks/homebrew/README.md b/cookbooks/homebrew/README.md new file mode 100644 index 0000000..b87382a --- /dev/null +++ b/cookbooks/homebrew/README.md @@ -0,0 +1,147 @@ +# Homebrew Cookbook + +[![Build Status](https://travis-ci.org/chef-cookbooks/homebrew.svg?branch=master)](http://travis-ci.org/chef-cookbooks/homebrew) [![Cookbook Version](https://img.shields.io/cookbook/v/homebrew.svg)](https://supermarket.chef.io/cookbooks/homebrew) + +This cookbook installs [Homebrew](http://brew.sh/) and provides resources for working with taps and casks + +## Requirements + +### Platforms + +- macOS + +### Chef + +- Chef 12.1+ + +### Cookbooks + +- none + +## Attributes + +- `node['homebrew']['owner']` - The user that will own the Homebrew installation and packages. Setting this will override the default behavior which is to use the non-privileged user that has invoked the Chef run (or the `SUDO_USER` if invoked with sudo). The default is `nil`. +- `node['homebrew']['auto-update']` - Whether the default recipe should automatically update Homebrew each run or not. The default is `true` to maintain compatibility. Set to false or nil to disable. Note that disabling this feature may cause formula to not work. +- `node['homebrew']['formulas']` - An Array of formula that should be installed using Homebrew by default, used only in the `homebrew::install_formulas` recipe. + + - To install the most recent version, include just the recipe name: `- simple_formula` + - To install a specific version, specify both its name and version: + + ``` + - name: special-version-formula + version: 1.2.3 + ``` + + - To install the HEAD of a formula, specify both its name and `head: true`: + + ``` + - name: head-tracking-formula + head: true + ``` + + - To provide other options, specify both its name and options + + ``` + - name: formula-with-options + options: --with-option-1 --with-other-option + ``` + +- `node['homebrew']['casks']` - An Array of casks that should be installed using brew cask by default, used only in the `homebrew::install_casks` recipe. + +- `node['homebrew']['taps']` - An Array of taps that should be installed using brew tap by default, used only in the `homebrew::install_taps` recipe. + +## Resources (provider) + +### homebrew_tap + +LWRP for `brew tap`, a Homebrew command used to add additional formula repositories. From the `brew` man page: + +```text +tap [tap] + Tap a new formula repository from GitHub, or list existing taps. + + tap is of the form user/repo, e.g. brew tap homebrew/dupes. +``` + +Default action is `:tap` which enables the repository. Use `:untap` to disable a tapped repository. + +#### Examples + +```ruby +homebrew_tap 'homebrew/dupes' + +homebrew_tap 'homebrew/dupes' do + action :untap +end +``` + +### homebrew_cask + +LWRP for `brew cask`, a Homebrew-style CLI workflow for the administration of Mac applications distributed as binaries. It's implemented as a homebrew "external command" called cask. + +[homebrew-cask on GitHub](https://github.com/caskroom/homebrew-cask) + +#### Prerequisites + +You must have the homebrew-cask repository tapped. + +```ruby +homebrew_tap 'caskroom/cask' +``` + +And then install the homebrew cask package before using this LWRP. + +```ruby +package "brew-cask" do + action :install + end +``` + +You can include the `homebrew::cask` recipe to do this. + +### Examples + +```ruby +homebrew_cask "google-chrome" + +homebrew_cask "google-chrome" do + action :uncask +end +``` + +Default action is `:cask` which installs the Application binary . Use `:uncask` to uninstall a an Application. + +[View the list of available Casks](https://github.com/caskroom/homebrew-cask/tree/master/Casks) + +# Usage + +We strongly recommend that you put "recipe[homebrew]" in your node's run list, to ensure that it is available on the system and that Homebrew itself gets installed. Putting an explicit dependency in the metadata will cause the cookbook to be downloaded and the library loaded, thus resulting in changing the package provider on Mac OS X, so if you have systems you want to use the default (Mac Ports), they would be changed to Homebrew. + +The default recipe also ensures that Homebrew is installed and up to date if the auto update attribute (above) is true (default). + +## License and Authors + +This cookbook is maintained by CHEF. The original author, maintainer and copyright holder is Graeme Mathieson. The cookbook remains licensed under the Apache License version 2. + +[Original blog post by Graeme](https://woss.name/articles/converging-your-home-directory-with-chef/) + +Author:: Graeme Mathieson ([mathie@woss.name](mailto:mathie@woss.name)) + +Author:: Joshua Timberman ([joshua@chef.io](mailto:joshua@chef.io)) + +```text +Copyright:: 2011, Graeme Mathieson +Copyright:: 2012-2016, Chef Software, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/cookbooks/homebrew/attributes/default.rb b/cookbooks/homebrew/attributes/default.rb new file mode 100644 index 0000000..67245a6 --- /dev/null +++ b/cookbooks/homebrew/attributes/default.rb @@ -0,0 +1,29 @@ +# +# Author:: Joshua Timberman () +# Author:: Graeme Mathieson () +# Cookbook:: homebrew +# Attributes:: default +# +# Copyright:: 2011-2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# only used if auto detection fails +default['homebrew']['owner'] = nil # only used if auto detection fails +default['homebrew']['auto-update'] = true +default['homebrew']['casks'] = [] +default['homebrew']['formulas'] = node['homebrew']['formula'] || [] +default['homebrew']['taps'] = [] +default['homebrew']['installer']['url'] = 'https://raw.githubusercontent.com/Homebrew/install/master/install' +default['homebrew']['installer']['checksum'] = nil +default['homebrew']['enable-analytics'] = true diff --git a/cookbooks/homebrew/libraries/homebrew_mixin.rb b/cookbooks/homebrew/libraries/homebrew_mixin.rb new file mode 100644 index 0000000..e292214 --- /dev/null +++ b/cookbooks/homebrew/libraries/homebrew_mixin.rb @@ -0,0 +1,63 @@ +# +# Author:: Joshua Timberman () +# Author:: Graeme Mathieson () +# Cookbook:: homebrew +# Libraries:: homebrew_mixin +# +# Copyright:: 2011-2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +class Chef12HomebrewUser + include Chef::Mixin::HomebrewUser +end + +module Homebrew + # Homebrew + module Mixin + def homebrew_owner + require 'etc' + @homebrew_owner ||= ::Etc.getpwuid(Chef12HomebrewUser.new.find_homebrew_uid).name + rescue Chef::Exceptions::CannotDetermineHomebrewOwner + @homebrew_owner ||= calculate_owner + end + + private + + def calculate_owner + owner = homebrew_owner_attr || sudo_user || current_user + if owner == 'root' + raise Chef::Exceptions::User, + "Homebrew owner is 'root' which is not supported. " \ + "To set an explicit owner, please set node['homebrew']['owner']." + end + owner + end + + def homebrew_owner_attr + node['homebrew']['owner'] + end + + def sudo_user + ENV['SUDO_USER'] + end + + def current_user + ENV['USER'] + end + end +end + +Chef::Resource.send(:include, Homebrew::Mixin) +Chef::Recipe.send(:include, Homebrew::Mixin) diff --git a/cookbooks/homebrew/libraries/matchers.rb b/cookbooks/homebrew/libraries/matchers.rb new file mode 100644 index 0000000..67d1d88 --- /dev/null +++ b/cookbooks/homebrew/libraries/matchers.rb @@ -0,0 +1,28 @@ +if defined?(ChefSpec) + ChefSpec.define_matcher :homebrew_package + + def tap_homebrew_tap(tap) + ChefSpec::Matchers::ResourceMatcher.new(:homebrew_tap, :tap, tap) + end + + def untap_homebrew_tap(tap) + ChefSpec::Matchers::ResourceMatcher.new(:homebrew_tap, :untap, tap) + end + + def cask_homebrew_cask(cask) + ChefSpec::Matchers::ResourceMatcher.new(:homebrew_cask, :cask, cask) + end + + def uncask_homebrew_cask(cask) + ChefSpec::Matchers::ResourceMatcher.new(:homebrew_cask, :uncask, cask) + end + + def install_homebrew_cask(cask) + ChefSpec::Matchers::ResourceMatcher.new(:homebrew_cask, :install, cask) + end + + def uninstall_homebrew_cask(cask) + ChefSpec::Matchers::ResourceMatcher.new(:homebrew_cask, :uninstall, cask) + end + +end diff --git a/cookbooks/homebrew/metadata.json b/cookbooks/homebrew/metadata.json new file mode 100644 index 0000000..e69fd81 --- /dev/null +++ b/cookbooks/homebrew/metadata.json @@ -0,0 +1 @@ +{"name":"homebrew","version":"3.0.0","description":"Install Homebrew and includes resources for working with taps and casks","long_description":"# Homebrew Cookbook\n\n[![Build Status](https://travis-ci.org/chef-cookbooks/homebrew.svg?branch=master)](http://travis-ci.org/chef-cookbooks/homebrew) [![Cookbook Version](https://img.shields.io/cookbook/v/homebrew.svg)](https://supermarket.chef.io/cookbooks/homebrew)\n\nThis cookbook installs [Homebrew](http://brew.sh/) and provides resources for working with taps and casks\n\n## Requirements\n\n### Platforms\n\n- macOS\n\n### Chef\n\n- Chef 12.1+\n\n### Cookbooks\n\n- none\n\n## Attributes\n\n- `node['homebrew']['owner']` - The user that will own the Homebrew installation and packages. Setting this will override the default behavior which is to use the non-privileged user that has invoked the Chef run (or the `SUDO_USER` if invoked with sudo). The default is `nil`.\n- `node['homebrew']['auto-update']` - Whether the default recipe should automatically update Homebrew each run or not. The default is `true` to maintain compatibility. Set to false or nil to disable. Note that disabling this feature may cause formula to not work.\n- `node['homebrew']['formulas']` - An Array of formula that should be installed using Homebrew by default, used only in the `homebrew::install_formulas` recipe.\n\n - To install the most recent version, include just the recipe name: `- simple_formula`\n - To install a specific version, specify both its name and version:\n\n ```\n - name: special-version-formula\n version: 1.2.3\n ```\n\n - To install the HEAD of a formula, specify both its name and `head: true`:\n\n ```\n - name: head-tracking-formula\n head: true\n ```\n\n - To provide other options, specify both its name and options\n\n ```\n - name: formula-with-options\n options: --with-option-1 --with-other-option\n ```\n\n- `node['homebrew']['casks']` - An Array of casks that should be installed using brew cask by default, used only in the `homebrew::install_casks` recipe.\n\n- `node['homebrew']['taps']` - An Array of taps that should be installed using brew tap by default, used only in the `homebrew::install_taps` recipe.\n\n## Resources (provider)\n\n### homebrew_tap\n\nLWRP for `brew tap`, a Homebrew command used to add additional formula repositories. From the `brew` man page:\n\n```text\ntap [tap]\n Tap a new formula repository from GitHub, or list existing taps.\n\n tap is of the form user/repo, e.g. brew tap homebrew/dupes.\n```\n\nDefault action is `:tap` which enables the repository. Use `:untap` to disable a tapped repository.\n\n#### Examples\n\n```ruby\nhomebrew_tap 'homebrew/dupes'\n\nhomebrew_tap 'homebrew/dupes' do\n action :untap\nend\n```\n\n### homebrew_cask\n\nLWRP for `brew cask`, a Homebrew-style CLI workflow for the administration of Mac applications distributed as binaries. It's implemented as a homebrew \"external command\" called cask.\n\n[homebrew-cask on GitHub](https://github.com/caskroom/homebrew-cask)\n\n#### Prerequisites\n\nYou must have the homebrew-cask repository tapped.\n\n```ruby\nhomebrew_tap 'caskroom/cask'\n```\n\nAnd then install the homebrew cask package before using this LWRP.\n\n```ruby\npackage \"brew-cask\" do\n action :install\n end\n```\n\nYou can include the `homebrew::cask` recipe to do this.\n\n### Examples\n\n```ruby\nhomebrew_cask \"google-chrome\"\n\nhomebrew_cask \"google-chrome\" do\n action :uncask\nend\n```\n\nDefault action is `:cask` which installs the Application binary . Use `:uncask` to uninstall a an Application.\n\n[View the list of available Casks](https://github.com/caskroom/homebrew-cask/tree/master/Casks)\n\n# Usage\n\nWe strongly recommend that you put \"recipe[homebrew]\" in your node's run list, to ensure that it is available on the system and that Homebrew itself gets installed. Putting an explicit dependency in the metadata will cause the cookbook to be downloaded and the library loaded, thus resulting in changing the package provider on Mac OS X, so if you have systems you want to use the default (Mac Ports), they would be changed to Homebrew.\n\nThe default recipe also ensures that Homebrew is installed and up to date if the auto update attribute (above) is true (default).\n\n## License and Authors\n\nThis cookbook is maintained by CHEF. The original author, maintainer and copyright holder is Graeme Mathieson. The cookbook remains licensed under the Apache License version 2.\n\n[Original blog post by Graeme](https://woss.name/articles/converging-your-home-directory-with-chef/)\n\nAuthor:: Graeme Mathieson ([mathie@woss.name](mailto:mathie@woss.name))\n\nAuthor:: Joshua Timberman ([joshua@chef.io](mailto:joshua@chef.io))\n\n```text\nCopyright:: 2011, Graeme Mathieson\nCopyright:: 2012-2016, Chef Software, Inc. \n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache 2.0","platforms":{"mac_os_x":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{"homebrew":"Install Homebrew"}} \ No newline at end of file diff --git a/cookbooks/homebrew/providers/cask.rb b/cookbooks/homebrew/providers/cask.rb new file mode 100644 index 0000000..dc7126a --- /dev/null +++ b/cookbooks/homebrew/providers/cask.rb @@ -0,0 +1,47 @@ +# +# Cookbook:: homebrew +# Providers:: cask +# +# Copyright:: 2011-2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include ::Homebrew::Mixin + +use_inline_resources + +def whyrun_supported? + true +end + +action :install do + execute "installing cask #{new_resource.name}" do + command "/usr/local/bin/brew cask install #{new_resource.name} #{new_resource.options}" + user homebrew_owner + environment lazy { { 'HOME' => ::Dir.home(homebrew_owner), 'USER' => homebrew_owner } } + not_if { new_resource.casked? } + end +end + +action :uninstall do + execute "uninstalling cask #{new_resource.name}" do + command "/usr/local/bin/brew cask uninstall #{new_resource.name}" + user homebrew_owner + environment lazy { { 'HOME' => ::Dir.home(homebrew_owner), 'USER' => homebrew_owner } } + only_if { new_resource.casked? } + end +end + +alias_method :action_cask, :action_install +alias_method :action_uncask, :action_uninstall diff --git a/cookbooks/homebrew/providers/tap.rb b/cookbooks/homebrew/providers/tap.rb new file mode 100644 index 0000000..fd04df8 --- /dev/null +++ b/cookbooks/homebrew/providers/tap.rb @@ -0,0 +1,58 @@ +# +# Author:: Joshua Timberman () +# Author:: Graeme Mathieson () +# Cookbook:: homebrew +# Providers:: tap +# +# Copyright:: 2011-2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include ::Homebrew::Mixin + +use_inline_resources + +def load_current_resource + @tap = Chef::Resource::HomebrewTap.new(new_resource.name) + tap_dir = @tap.name.gsub('/', '/homebrew-') + + Chef::Log.debug("Checking whether we've already tapped #{new_resource.name}") + if ::File.directory?("/usr/local/Library/Taps/#{tap_dir}") + @tap.tapped true + else + @tap.tapped false + end +end + +action :tap do + unless @tap.tapped + execute "tapping #{new_resource.name}" do + command "/usr/local/bin/brew tap #{new_resource.name}" + environment lazy { { 'HOME' => ::Dir.home(homebrew_owner), 'USER' => homebrew_owner } } + not_if "/usr/local/bin/brew tap | grep #{new_resource.name}" + user homebrew_owner + end + end +end + +action :untap do + if @tap.tapped + execute "untapping #{new_resource.name}" do + command "/usr/local/bin/brew untap #{new_resource.name}" + environment lazy { { 'HOME' => ::Dir.home(homebrew_owner), 'USER' => homebrew_owner } } + only_if "/usr/local/bin/brew tap | grep #{new_resource.name}" + user homebrew_owner + end + end +end diff --git a/cookbooks/homebrew/recipes/cask.rb b/cookbooks/homebrew/recipes/cask.rb new file mode 100644 index 0000000..38148e6 --- /dev/null +++ b/cookbooks/homebrew/recipes/cask.rb @@ -0,0 +1,26 @@ +# +# Cookbook:: homebrew +# Recipes:: cask +# +# Copyright:: 2014-2016, Chef Software, Inc +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +homebrew_tap 'caskroom/cask' + +directory '/Library/Caches/Homebrew/Casks' do + owner homebrew_owner + mode '775' + only_if { ::Dir.exist?('/Library/Caches/Homebrew') } +end diff --git a/cookbooks/homebrew/recipes/default.rb b/cookbooks/homebrew/recipes/default.rb new file mode 100644 index 0000000..feab10e --- /dev/null +++ b/cookbooks/homebrew/recipes/default.rb @@ -0,0 +1,57 @@ +# +# Author:: Joshua Timberman () +# Author:: Graeme Mathieson () +# Cookbook:: homebrew +# Recipe:: default +# +# Copyright:: 2011-2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +homebrew_go = "#{Chef::Config[:file_cache_path]}/homebrew_go" + +Chef::Log.debug("Homebrew owner is '#{homebrew_owner}'") + +remote_file homebrew_go do + source node['homebrew']['installer']['url'] + checksum node['homebrew']['installer']['checksum'] unless node['homebrew']['installer']['checksum'].nil? + mode '755' + not_if { ::File.exist? '/usr/local/bin/brew' } +end + +execute 'install homebrew' do + command homebrew_go + environment lazy { { 'HOME' => ::Dir.home(homebrew_owner), 'USER' => homebrew_owner } } + user homebrew_owner + not_if { ::File.exist? '/usr/local/bin/brew' } +end + +execute 'set analytics' do + environment lazy { { 'HOME' => ::Dir.home(homebrew_owner), 'USER' => homebrew_owner } } + user homebrew_owner + command "/usr/local/bin/brew analytics #{node['homebrew']['enable-analytics'] ? 'on' : 'off'}" + only_if { shell_out('/usr/local/bin/brew analytics state', user: homebrew_owner).stdout.include?('enabled') != node['homebrew']['enable-analytics'] } +end + +if node['homebrew']['auto-update'] + package 'git' do + not_if 'which git' + end + + execute 'update homebrew from github' do + environment lazy { { 'HOME' => ::Dir.home(homebrew_owner), 'USER' => homebrew_owner } } + user homebrew_owner + command '/usr/local/bin/brew update || true' + end +end diff --git a/cookbooks/homebrew/recipes/install_casks.rb b/cookbooks/homebrew/recipes/install_casks.rb new file mode 100644 index 0000000..3635e17 --- /dev/null +++ b/cookbooks/homebrew/recipes/install_casks.rb @@ -0,0 +1,24 @@ +# +# Cookbook:: homebrew +# Recipe:: install_casks +# +# Copyright:: 2014-2016, Chef Software, Inc +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'homebrew::cask' + +node['homebrew']['casks'].each do |cask| + homebrew_cask cask +end diff --git a/cookbooks/homebrew/recipes/install_formulas.rb b/cookbooks/homebrew/recipes/install_formulas.rb new file mode 100644 index 0000000..ca13679 --- /dev/null +++ b/cookbooks/homebrew/recipes/install_formulas.rb @@ -0,0 +1,33 @@ +# +# Cookbook:: homebrew +# Recipes:: install_casks +# +# Copyright:: 2014-2016, Chef Software, Inc +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'homebrew' + +node['homebrew']['formulas'].each do |formula| + if formula.class == Chef::Node::ImmutableMash + formula_options = formula.fetch(:options, '') + formula_options += ' --HEAD' if formula.fetch(:head, false) + package formula.fetch(:name) do + options formula_options.strip + version formula['version'] if formula.fetch(:version, false) + end + else + package formula + end +end diff --git a/cookbooks/homebrew/recipes/install_taps.rb b/cookbooks/homebrew/recipes/install_taps.rb new file mode 100644 index 0000000..950165c --- /dev/null +++ b/cookbooks/homebrew/recipes/install_taps.rb @@ -0,0 +1,24 @@ +# +# Cookbook:: homebrew +# Recipes:: install_taps +# +# Copyright:: 2015-2016, Chef Software, Inc +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'homebrew' + +node['homebrew']['taps'].each do |tap| + homebrew_tap tap +end diff --git a/cookbooks/homebrew/resources/cask.rb b/cookbooks/homebrew/resources/cask.rb new file mode 100644 index 0000000..797a0d9 --- /dev/null +++ b/cookbooks/homebrew/resources/cask.rb @@ -0,0 +1,14 @@ +actions :cask, :uncask, :install, :uninstall +default_action :install + +attribute :name, + name_attribute: true, + kind_of: String, + regex: /^[\w-]+$/ + +attribute :options, + kind_of: String + +def casked? + shell_out('/usr/local/bin/brew cask list 2>/dev/null').stdout.split.include?(name) +end diff --git a/cookbooks/homebrew/resources/tap.rb b/cookbooks/homebrew/resources/tap.rb new file mode 100644 index 0000000..f7a8c99 --- /dev/null +++ b/cookbooks/homebrew/resources/tap.rb @@ -0,0 +1,31 @@ +# +# Author:: Joshua Timberman () +# Author:: Graeme Mathieson () +# Cookbook:: homebrew +# Resources:: tap +# +# Copyright:: 2011-2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +actions :tap, :untap +default_action :tap + +attribute :name, + name_attribute: true, + kind_of: String, + regex: %r{^[\w-]+(?:\/[\w-]+)+$} + +attribute :tapped, + kind_of: [TrueClass, FalseClass] diff --git a/cookbooks/hostname/.kitchen.yml b/cookbooks/hostname/.kitchen.yml new file mode 100644 index 0000000..a1bca39 --- /dev/null +++ b/cookbooks/hostname/.kitchen.yml @@ -0,0 +1,34 @@ +--- +driver_plugin: vagrant +driver_config: + require_chef_omnibus: true + +platforms: + - name: ubuntu-12.04 + - name: ubuntu-14.04 + - name: ubuntu-16.04 + - name: debian-7.11 + - name: debian-8.5 + - name: centos-6.8 + - name: centos-7.2 + - name: freebsd-9.3 + - name: freebsd-10.3 + - name: fedora-21 + - name: fedora-22 + - name: fedora-23 + - name: fedora-24 + +suites: + - name: default + run_list: + - recipe[hostname::default] + attributes: + set_fqdn: test.example.com + - name: wildcard + run_list: + - recipe[hostname::default] + provisioner: + solo_rb: + node_name: test + attributes: + set_fqdn: '*.example.com' diff --git a/cookbooks/hostname/.rubocop.yml b/cookbooks/hostname/.rubocop.yml new file mode 100644 index 0000000..68797c4 --- /dev/null +++ b/cookbooks/hostname/.rubocop.yml @@ -0,0 +1,23 @@ +AllCops: + DisplayCopNames: true + Exclude: + - tmp/** + +Lint/AmbiguousBlockAssociation: + Enabled: false + +Metrics/BlockLength: + Enabled: false + +Metrics/LineLength: + Enabled: false + +Style/Documentation: + Exclude: + - Thorfile + +Style/PercentLiteralDelimiters: + Enabled: false + +Style/SingleSpaceBeforeFirstArg: + Enabled: false diff --git a/cookbooks/hostname/Gemfile b/cookbooks/hostname/Gemfile new file mode 100644 index 0000000..5a955a6 --- /dev/null +++ b/cookbooks/hostname/Gemfile @@ -0,0 +1,13 @@ +source 'https://rubygems.org' + +gem 'berkshelf' +gem 'chef', '~> 12.13' +gem 'chefspec' +gem 'foodcritic' +gem 'rake' +gem 'rubocop' + +group :integration do + gem 'kitchen-vagrant' + gem 'test-kitchen' +end diff --git a/cookbooks/hostname/LICENSE b/cookbooks/hostname/LICENSE new file mode 100644 index 0000000..5fd6878 --- /dev/null +++ b/cookbooks/hostname/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2011-2017 Maciej Pasternacki + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/cookbooks/hostname/README.md b/cookbooks/hostname/README.md new file mode 100644 index 0000000..988b256 --- /dev/null +++ b/cookbooks/hostname/README.md @@ -0,0 +1,52 @@ +# hostname cookbook + +[![Build Status](https://travis-ci.org/3ofcoins/chef-cookbook-hostname.svg?branch=master)](https://travis-ci.org/3ofcoins/chef-cookbook-hostname) +[![Chef cookbook](https://img.shields.io/cookbook/v/hostname.svg)](https://supermarket.chef.io/cookbooks/hostname) +## Description + +Sets hostname and FQDN of the node. The latest code is hosted at +https://github.com/3ofcoins/chef-cookbook-hostname + +### Important + +Setting hostname on FQDN is not (and won't be) supported. Unfortunately, using dots in the hostname can cause +[inconsistent results for any system that consumes DNS](http://serverfault.com/questions/229331/can-i-have-dots-in-a-hostname) +and [is not allowed by RFC952](http://tools.ietf.org/html/rfc952). If a user +needs additional info in their shell prompt, they can change PS1 in etc/profile +to include the FQDN together with any information they find useful (such as +the customer, the environment, etc). + +## Attributes + +- `node['set_fqdn']` - FQDN to set. + +The asterisk character will be replaced with `node.name`. This way, +you can add this to base role: + +```ruby +default_attributes :set_fqdn => '*.project-domain.com' +``` + +and have node set its FQDN and hostname based on its chef node name +(which is provided on `chef-client` first run's command line). + +- `node['hostname_cookbook']['hostsfile_ip']` -- IP used in + `/etc/hosts` to correctly set FQDN (default: `127.0.1.1`) +- `node['hostname_cookbook']['hostsfile_aliases']` -- list of aliases used in + `/etc/hosts` for the ip set above (default: [`hostname`]) +- `node['hostname_cookbook']['hostsfile_include_hostname_in_aliases']` -- whether to include the hostname + at the end of the aliases list above (default: true) + +- `node['hostname_cookbook']['append_hostsfile_ip']` -- Set to `false` to + prevent an entry for the node's hostname from being appended in `/etc/hosts` (default: `true`) + +## Recipes + +* `hostname::default` -- will set node's FQDN to value of `set_fqdn` attribute, +and hostname to its host part (up to first dot). +* `hostname::vmware` -- sets hostname automatically using vmtoolsd. +You do not need to set `node["set_fqdn"]`. + +## Author + +Author: Maciej Pasternacki maciej@3ofcoins.net diff --git a/cookbooks/hostname/Rakefile b/cookbooks/hostname/Rakefile new file mode 100644 index 0000000..638e011 --- /dev/null +++ b/cookbooks/hostname/Rakefile @@ -0,0 +1,15 @@ +require 'foodcritic' +require 'rspec/core/rake_task' +require 'rubocop/rake_task' + +RuboCop::RakeTask.new(:rubocop) + +FoodCritic::Rake::LintTask.new do |t| + t.options = { + fail_tags: ['any'] + } +end + +RSpec::Core::RakeTask.new(:spec) + +task default: %w[foodcritic rubocop spec] diff --git a/cookbooks/hostname/TESTING.md b/cookbooks/hostname/TESTING.md new file mode 100644 index 0000000..76fdc00 --- /dev/null +++ b/cookbooks/hostname/TESTING.md @@ -0,0 +1,45 @@ +Testing +======= + +Preparation +----- + + $ bundle install + +And then, to install all cookbooks: + + $ bundle exec berks install + +Local +----- + + $ bundle exec rake + +The above runs: + + - rubocop lint + - Foodcritic lint + - Chefspec tests + +Chefspec tests (the interesting part) are in `spec/`. + +Integration +----------- + + $ bundle exec kitchen test + + See `.kitchen.yml` and `test/` directory for details. + + It is important to check if the applied hostname and fqdn values remain the same + also after machine reboot. As it is impossible to reboot using kitchen, it has to + be done manually: + + - run `kitchen converge` and `kitchen verify` to ensure your run is error-free, + - log in to the machine. If you're on a Debian-based system, you need to ensure + that the `/tmp` folder won't be deleted with rebooting, since that's where busser + resides. If `/tmp` is deleted, `kitchen verify` will fail after reboot even if a + manual check confirms that hostname, fqdn and dnsdomainname are correct. You can + preserve the `/tmp` folder by typing the following in your terminal: + `sudo find /etc/default/rcS -type f -exec sed -i 's/TMPTIME=0/TMPTIME=-1/g' {} \;` + - run `sudo reboot`, + - wait for the machine to reboot and run `kitchen verify` again. diff --git a/cookbooks/hostname/Thorfile b/cookbooks/hostname/Thorfile new file mode 100644 index 0000000..97baa90 --- /dev/null +++ b/cookbooks/hostname/Thorfile @@ -0,0 +1,41 @@ +# -*- ruby -*- + +require 'rubygems' +require 'bundler/setup' + +require 'shellwords' + +class Cookbook < Thor + COOKBOOK_NAME = 'hostname'.freeze + COOKBOOK_CATEGORY = 'utilities'.freeze + + include Thor::Actions + + desc :edit, 'Edit cookbook in browser' + def edit + open "http://community.opscode.com/cookbooks/#{COOKBOOK_NAME}/edit" + end + + desc :browse, "Go to cookbook's page on Opscode's community website" + def browse + open "http://community.opscode.com/cookbooks/#{COOKBOOK_NAME}/" + end + + desc :upload, "Upload cookbook to Opscode's community website" + def upload + run "knife cookbook site share #{COOKBOOK_NAME} #{Shellwords.escape(COOKBOOK_CATEGORY)} -o #{Shellwords.escape(File.dirname(File.dirname(__FILE__)))}" + end + + private + + def open(what) + run "#{open_cmd} #{Shellwords.escape(what)}" + end + + def open_cmd + @open_cmd ||= %w[open xdg-open].find do |command| + system "which #{command} >/dev/null 2>&1" + $CHILD_STATUS.success? + end + end +end diff --git a/cookbooks/hostname/attributes/default.rb b/cookbooks/hostname/attributes/default.rb new file mode 100644 index 0000000..0aac597 --- /dev/null +++ b/cookbooks/hostname/attributes/default.rb @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- + +default['hostname_cookbook']['hostsfile_ip'] = '127.0.1.1' +default['hostname_cookbook']['hostsfile_ip_interface'] = 'lo0' if node['platform'] == 'freebsd' +default['hostname_cookbook']['hostsfile_aliases'] = [] +default['hostname_cookbook']['hostsfile_include_hostname_in_aliases'] = true +default['hostname_cookbook']['append_hostsfile_ip'] = true diff --git a/cookbooks/hostname/chefignore b/cookbooks/hostname/chefignore new file mode 100644 index 0000000..a6de142 --- /dev/null +++ b/cookbooks/hostname/chefignore @@ -0,0 +1,96 @@ +# Put files/directories that should be ignored in this file when uploading +# or sharing to the community site. +# Lines that start with '# ' are comments. + +# OS generated files # +###################### +.DS_Store +Icon? +nohup.out +ehthumbs.db +Thumbs.db + +# SASS # +######## +.sass-cache + +# EDITORS # +########### +\#* +.#* +*~ +*.sw[a-z] +*.bak +REVISION +TAGS* +tmtags +*_flymake.* +*_flymake +*.tmproj +.project +.settings +mkmf.log + +## COMPILED ## +############## +a.out +*.o +*.pyc +*.so +*.com +*.class +*.dll +*.exe +*/rdoc/ + +# Testing # +########### +.watchr +.rspec +spec/* +spec/fixtures/* +test/* +features/* +Guardfile +Procfile + +# SCM # +####### +.git +*/.git +.gitignore +.gitmodules +.gitconfig +.gitattributes +.svn +*/.bzr/* +*/.hg/* +*/.svn/* + +# Berkshelf # +############# +Berksfile +Berksfile.lock +cookbooks/* +tmp + +# Cookbooks # +############# +CONTRIBUTING +CHANGELOG* + +# Strainer # +############ +Colanderfile +Strainerfile +.colander +.strainer + +# Vagrant # +########### +.vagrant +Vagrantfile + +# Travis # +########## +.travis.yml diff --git a/cookbooks/hostname/metadata.json b/cookbooks/hostname/metadata.json new file mode 100644 index 0000000..82b2a09 --- /dev/null +++ b/cookbooks/hostname/metadata.json @@ -0,0 +1,44 @@ +{ + "name": "hostname", + "description": "Configures hostname and FQDN", + "long_description": "# hostname cookbook\n\n[![Build Status](https://travis-ci.org/3ofcoins/chef-cookbook-hostname.svg?branch=master)](https://travis-ci.org/3ofcoins/chef-cookbook-hostname)\n[![Chef cookbook](https://img.shields.io/cookbook/v/hostname.svg)](https://supermarket.chef.io/cookbooks/hostname)\n## Description\n\nSets hostname and FQDN of the node. The latest code is hosted at\nhttps://github.com/3ofcoins/chef-cookbook-hostname\n\n### Important\n\nSetting hostname on FQDN is not (and won't be) supported. Unfortunately, using dots in the hostname can cause\n[inconsistent results for any system that consumes DNS](http://serverfault.com/questions/229331/can-i-have-dots-in-a-hostname)\nand [is not allowed by RFC952](http://tools.ietf.org/html/rfc952). If a user\nneeds additional info in their shell prompt, they can change PS1 in etc/profile\nto include the FQDN together with any information they find useful (such as\nthe customer, the environment, etc).\n\n## Attributes\n\n- `node['set_fqdn']` - FQDN to set.\n\nThe asterisk character will be replaced with `node.name`. This way,\nyou can add this to base role:\n\n```ruby\ndefault_attributes :set_fqdn => '*.project-domain.com'\n```\n\nand have node set its FQDN and hostname based on its chef node name\n(which is provided on `chef-client` first run's command line).\n\n- `node['hostname_cookbook']['hostsfile_ip']` -- IP used in\n `/etc/hosts` to correctly set FQDN (default: `127.0.1.1`)\n- `node['hostname_cookbook']['hostsfile_aliases']` -- list of aliases used in\n `/etc/hosts` for the ip set above (default: [`hostname`])\n- `node['hostname_cookbook']['hostsfile_include_hostname_in_aliases']` -- whether to include the hostname\n at the end of the aliases list above (default: true)\n\n- `node['hostname_cookbook']['append_hostsfile_ip']` -- Set to `false` to\n prevent an entry for the node's hostname from being appended in `/etc/hosts` (default: `true`)\n\n## Recipes\n\n* `hostname::default` -- will set node's FQDN to value of `set_fqdn` attribute,\nand hostname to its host part (up to first dot).\n* `hostname::vmware` -- sets hostname automatically using vmtoolsd.\nYou do not need to set `node[\"set_fqdn\"]`.\n\n## Author\n\nAuthor: Maciej Pasternacki maciej@3ofcoins.net\n", + "maintainer": "Maciej Pasternacki", + "maintainer_email": "maciej@3ofcoins.net", + "license": "MIT", + "platforms": { + "debian": ">= 0.0.0", + "ubuntu": ">= 0.0.0", + "freebsd": ">= 0.0.0" + }, + "dependencies": { + "hostsfile": ">= 0.0.0" + }, + "recommendations": { + + }, + "suggestions": { + + }, + "conflicting": { + + }, + "providing": { + + }, + "replacing": { + + }, + "attributes": { + + }, + "groupings": { + + }, + "recipes": { + + }, + "version": "0.4.2", + "source_url": "https://github.com/3ofcoins/chef-cookbook-hostname", + "issues_url": "https://github.com/3ofcoins/chef-cookbook-hostname/issues", + "privacy": false +} diff --git a/cookbooks/hostname/metadata.rb b/cookbooks/hostname/metadata.rb new file mode 100644 index 0000000..8355ea1 --- /dev/null +++ b/cookbooks/hostname/metadata.rb @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- + +name 'hostname' +maintainer 'Maciej Pasternacki' +maintainer_email 'maciej@3ofcoins.net' +license 'MIT' +description 'Configures hostname and FQDN' +long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) +version '0.4.2' + +supports 'debian' +supports 'ubuntu' +supports 'freebsd' + +depends 'hostsfile' + +source_url 'https://github.com/3ofcoins/chef-cookbook-hostname' if respond_to?(:source_url) +issues_url 'https://github.com/3ofcoins/chef-cookbook-hostname/issues' if respond_to?(:issues_url) + +chef_version '>= 12.1' if respond_to?(:chef_version) diff --git a/cookbooks/hostname/recipes/default.rb b/cookbooks/hostname/recipes/default.rb new file mode 100644 index 0000000..b9c1cf1 --- /dev/null +++ b/cookbooks/hostname/recipes/default.rb @@ -0,0 +1,139 @@ +# -*- coding: utf-8 -*- +# +# Cookbook Name:: hostname +# Recipe:: default +# +# Copyright 2011, Maciej Pasternacki +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +fqdn = node['set_fqdn'] +if fqdn + fqdn = fqdn.sub('*', node.name) + fqdn =~ /^([^.]+)/ + hostname = Regexp.last_match[1] + + aliases = node['hostname_cookbook']['hostsfile_aliases'] + aliases += [hostname] if node['hostname_cookbook']['hostsfile_include_hostname_in_aliases'] + + case node['platform_family'] + when 'freebsd' + directory '/etc/rc.conf.d' do + mode '0755' + end + + rc_conf_lines = ["hostname=#{fqdn}\n"] + if node['hostname_cookbook']['hostsfile_ip_interface'] + rc_conf_lines << + "ifconfig_#{node['hostname_cookbook']['hostsfile_ip_interface']}_alias=\"inet #{node['hostname_cookbook']['hostsfile_ip']}/32\"\n" + service 'netif' + end + + file '/etc/rc.conf.d/hostname' do + content rc_conf_lines.join + mode '0644' + notifies :reload, 'service[netif]', :immediately \ + if node['hostname_cookbook']['hostsfile_ip_interface'] + end + + execute "hostname #{fqdn}" do + only_if { node['fqdn'] != fqdn } + notifies :reload, 'ohai[reload_hostname]', :immediately + end + + when 'rhel' + service 'network' do + action :nothing + end + hostfile = '/etc/sysconfig/network' + file hostfile do + action :create + content lazy { + ::IO.read(hostfile).gsub(/^HOSTNAME=.*$/, "HOSTNAME=#{fqdn}") + } + not_if { ::IO.read(hostfile) =~ /^HOSTNAME=#{fqdn}$/ } + notifies :reload, 'ohai[reload_hostname]', :immediately + notifies :restart, 'service[network]', :delayed + end + # this is to persist the correct hostname after machine reboot + sysctl = '/etc/sysctl.conf' + file sysctl do + action :create + regex = /^kernel\.hostname=.*/ + newline = "kernel.hostname=#{hostname}" + content lazy { + original = ::IO.read(sysctl) + original.match(regex) ? original.gsub(regex, newline) : original + newline + } + not_if { ::IO.read(sysctl).scan(regex).last == newline } + notifies :reload, 'ohai[reload_hostname]', :immediately + notifies :restart, 'service[network]', :delayed + end + execute "hostname #{hostname}" do + only_if { node['hostname'] != hostname } + notifies :reload, 'ohai[reload_hostname]', :immediately + end + # update /etc/hostname in RHEL7+ + file '/etc/hostname' do + content "#{hostname}\n" + mode '0644' + only_if { ::File.exist?('/etc/hostname') } + notifies :reload, 'ohai[reload_hostname]', :immediately + end + + else + file '/etc/hostname' do + content "#{hostname}\n" + mode '0644' + notifies :reload, 'ohai[reload_hostname]', :immediately + end + + execute "hostname #{hostname}" do + only_if { node['hostname'] != hostname } + notifies :reload, 'ohai[reload_hostname]', :immediately + end + end + + hostsfile_entry 'localhost' do + ip_address '127.0.0.1' + hostname 'localhost' + action :append + end + + hostsfile_entry 'set hostname' do + ip_address node['hostname_cookbook']['hostsfile_ip'] + hostname fqdn + aliases aliases + unique true + action :create + notifies :reload, 'ohai[reload_hostname]', :immediately + only_if { node['hostname_cookbook']['append_hostsfile_ip'] } + end + + ohai 'reload_hostname' do + plugin 'hostname' + action :nothing + end +else + log 'Please set the set_fqdn attribute to desired hostname' do + level :warn + end +end diff --git a/cookbooks/hostname/recipes/vmware.rb b/cookbooks/hostname/recipes/vmware.rb new file mode 100644 index 0000000..ac10f42 --- /dev/null +++ b/cookbooks/hostname/recipes/vmware.rb @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# +# Cookbook Name:: hostname +# Recipe:: vmware +# +# Copyright 2011, Maciej Pasternacki +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +if node['virtualization']['system'] != 'vmware' + Chef::Log.warn('node["virtualization"]["system"] is not "vmware".') +end + +unless FileTest.executable?('/usr/sbin/vmtoolsd') + Chef::Application.fatal!('/usr/sbin/vmtoolsd is not found or not executable.') +end + +node.default['set_fqdn'] = Mixlib::ShellOut.new("/usr/sbin/vmtoolsd --cmd 'info-get guestinfo.hostname'").stdout.chomp +include_recipe 'hostname::default' diff --git a/cookbooks/hostsfile/CHANGELOG.md b/cookbooks/hostsfile/CHANGELOG.md new file mode 100644 index 0000000..79838bb --- /dev/null +++ b/cookbooks/hostsfile/CHANGELOG.md @@ -0,0 +1,73 @@ +hostsfile Cookbook CHANGELOG +======================= +This file is used to list changes made in each version of the hostsfile cookbook. + + +v2.4.5 (2014-06-24) +------------------- +- Fix notifications and why-run mode + + +v2.4.4 (2014-02-25) +------------------- +- Bump Berkshelf version +- Remove scope pieces from IPv6 addresses + + +v2.4.3 (2014-02-01) +------------------- + +- Package custom ChefSpec matchers +- Update testing harness +- Avoid using `Chef::Application.fatal!` +- Use Chef::Resource::File for atomic updates + + +v2.4.2 +------ +- Fix Travis CI integration +- Remove newline characters +- Allow specifying a custom hostsfile path + + +v2.4.1 +------ +- Force a new upload to the community site + + +v2.4.0 +------ +- Convert everything to Ruby 1.9 syntax because I'm tired of people removing trailing commas despite the **massive** warning in the README: ([#29](https://github.com/customink-webops/hostsfile/issues/29), [#30](https://github.com/customink-webops/hostsfile/issues/30), [#32](https://github.com/customink-webops/hostsfile/issues/32), [#33](https://github.com/customink-webops/hostsfile/issues/33), [#34](https://github.com/customink-webops/hostsfile/issues/34), [#35](https://github.com/customink-webops/hostsfile/issues/35), [#36](https://github.com/customink-webops/hostsfile/issues/36), [#38](https://github.com/customink-webops/hostsfile/issues/38), [#39](https://github.com/customink-webops/hostsfile/issues/39)) +- Update to the latest and greatest testing gems and practices +- Remove strainer in favor of a purer solution +- Update `.gitignore` to ignore additional files +- Add more platforms to the `.kitchen.yml` +- Use `converge_by` and support whyruny mode + +v2.0.0 +------ +- Completely manage the hostsfile, ensuring no duplicate entries + +v1.0.2 +------ +- Support Windows (thanks @igantt-daptiv) +- Specs + Travis support +- Throw fatal error if hostsfile does not exist (@jkerzner) +- Write priorities in hostsfile so they are read on subsequent Chef runs + +v0.2.0 +------ +- Updated README to require Ruby 1.9 +- Allow hypens in hostnames +- Ensure newline at end of file +- Allow priority ordering in hostsfile + +v0.1.1 +------ +- Fixed issue #1 +- Better unique object filtering +- Better handing of aliases + +v0.1.0 +------ +- Initial release diff --git a/cookbooks/hostsfile/README.md b/cookbooks/hostsfile/README.md new file mode 100644 index 0000000..f4574ce --- /dev/null +++ b/cookbooks/hostsfile/README.md @@ -0,0 +1,234 @@ +hostsfile LWRP +============== +[![Build Status](https://travis-ci.org/customink-webops/hostsfile.png?branch=master)](https://travis-ci.org/customink-webops/hostsfile) + +`hostsfile` provides an LWRP for managing your `/etc/hosts` (or Windows equivalent) file using Chef. + + +Requirements +------------ +- Chef 11 or higher +- **Ruby 1.9.3 or higher** + +**Please stop opening Pull Requests to restore Ruby 1.8 support!** Any of the `1.x.y` series of this cookbook will work with Chef 10 and Ruby 1.8. You can use Opscode's [Omnibus installer](http://www.opscode.com/blog/2012/06/29/omnibus-chef-packaging/) to install Ruby 1.9+ and Seth Chisamore's [Vagrant Omnibus plugin](https://github.com/schisamo/vagrant-omnibus) to get Ruby 1.9+ on your Vagrant box. + + +Attributes +---------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeDescriptionExampleDefault
ip_address(name attribute) the IP address for the entry1.2.3.4
hostname(required) the hostname associated with the entryexample.com
uniqueremove any existing entries that have the same hostnametruefalse
aliasesarray of aliases for the entry['www.example.com'][]
commenta comment to append to the end of the entry'interal DNS server'nil
prioritythe relative position of this entry20(varies, see **Priorities** section)
+ + +Actions +------- +**Please note**: In `v0.1.2`, specifying a hostname or alias that existed in another automatically removed that hostname from the other entry before. In `v2.1.0`, the `unique` option was added to give the user case-by-case control of this behavior. For example, given an `/etc/hosts` file that contains: + + 1.2.3.4 example.com www.example.com + +when the Chef recipe below is converged: + +```ruby +hostsfile_entry '2.3.4.5' do + hostname 'www.example.com' + unique true +end +``` + +then the `/etc/hosts` file will look like this: + + 1.2.3.4 example.com + 2.3.4.5 www.example.com + +Not specifying the `unique` parameter will result in duplicate hostsfile entries. + +#### `create` +Creates a new hosts file entry. If an entry already exists, it will be overwritten by this one. + +```ruby +hostsfile_entry '1.2.3.4' do + hostname 'example.com' + action :create +end +``` + +This will create an entry like this: + + 1.2.3.4 example.com + +#### `create_if_missing` +Create a new hosts file entry, only if one does not already exist for the given IP address. If one exists, this does nothing. + +```ruby +hostsfile_entry '1.2.3.4' do + hostname 'example.com' + action :create_if_missing +end +``` + +#### `append` +Append a hostname or alias to an existing record. If the given IP address doesn't already exist in the hostsfile, this method behaves the same as create. Otherwise, it will append the additional hostname and aliases to the existing entry. + + 1.2.3.4 example.com www.example.com # Created by Chef + +```ruby +hostsfile_entry '1.2.3.4' do + hostname 'www2.example.com' + aliases ['foo.com', 'foobar.com'] + comment 'Append by Recipe X' + action :append +end +``` + +would yield: + + 1.2.3.4 example.com www.example.com www2.example.com foo.com foobar.com # Created by Chef, Appended by Recipe X + + +#### `update` +Updates the given hosts file entry. Does nothing if the entry does not exist. + +```ruby +hostsfile_entry '1.2.3.4' do + hostname 'example.com' + comment 'Update by Chef' + action :update +end +``` + +This will create an entry like this: + + 1.2.3.4 example # Updated by Chef + +#### `remove` +Removes an entry from the hosts file. Does nothing if the entry does not +exist. + +```ruby +hostsfile_entry '1.2.3.4' do + action :remove +end +``` + +This will remove the entry for `1.2.3.4`. + + +Usage +----- +If you're using [Berkshelf](http://berkshelf.com/), just add `hostsfile` to your `Berksfile`: + +```ruby +cookbook 'hostsfile' +``` + +Otherwise, install the cookbook from the community site: + + knife cookbook site install hostsfile + +Have any other cookbooks *depend* on hostsfile by editing editing the `metadata.rb` for your cookbook. + +```ruby +# metadata.rb +depends 'hostsfile' +``` + +Note that you can specify a custom path to your hosts file in the `['hostsfile']['path']` node attribute. Otherwise, it defaults to sensible paths depending on your OS. + +### Testing +If you are using [ChefSpec](https://github.com/sethvargo/chefspec) to unit test a cookbook that implements the `hostsfile_entry` LWRP, this cookbook packages customer matchers that you can use in your unit tests: + +- `append_hostsfile_entry` +- `create_hostsfile_entry` +- `create_hostsfile_entry_if_missing` +- `remove_hostsfile_entry` +- `update_hostsfile_entry` + +For example: + +```ruby +it 'creates a hostsfile entry for the DNS server' do + expect(chef_run).to create_hostsfile_entry('1.2.3.4') + .with_hostname('dns.example.com') +end +``` + +Priority +-------- +Priority is a relatively new addition to the cookbook. It gives you the ability to (somewhat) specify the relative order of entries. By default, the priority is calculated for you as follows: + +1. Local, loopback +2. IPV4 +3. IPV6 + +However, you can override it using the `priority` option. + + +Contributing +------------ +1. Fork the project +2. Create a feature branch corresponding to you change +3. Commit and test thoroughly +4. Create a Pull Request on github + + +License & Authors +----------------- +- Author:: Seth Vargo (sethvargo@gmail.com) + +```text +Copyright 2012-2013, Seth Vargo +Copyright 2012, CustomInk, LLC + +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/cookbooks/hostsfile/attributes/default.rb b/cookbooks/hostsfile/attributes/default.rb new file mode 100644 index 0000000..d9175e6 --- /dev/null +++ b/cookbooks/hostsfile/attributes/default.rb @@ -0,0 +1,22 @@ +# +# Author:: Seth Vargo +# Cookbook:: hostsfile +# Attribute:: default +# +# Copyright 2012-2013, Seth Vargo +# Copyright 2012, CustomInk, LCC +# +# 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. +# + +default['hostsfile']['path'] = nil diff --git a/cookbooks/hostsfile/libraries/entry.rb b/cookbooks/hostsfile/libraries/entry.rb new file mode 100644 index 0000000..53b79db --- /dev/null +++ b/cookbooks/hostsfile/libraries/entry.rb @@ -0,0 +1,183 @@ +# +# Author:: Seth Vargo +# Cookbook:: hostsfile +# Library:: entry +# +# Copyright 2012-2013, Seth Vargo +# Copyright 2012, CustomInk, LCC +# +# 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. +# + +require 'ipaddr' + +# An object representation of a single line in a hostsfile. +# +# @author Seth Vargo +class Entry + class << self + # Creates a new Hostsfile::Entry object by parsing a text line. The + # `line` attribute will be in the following format: + # + # 1.2.3.4 hostname [alias[, alias[, alias]]] [# comment [@priority]] + # + # @param [String] line + # the line to parse + # @return [Entry] + # a new entry object + def parse(line) + entry, comment = extract_comment(line) + comment, priority = extract_priority(comment) + entries = extract_entries(entry) + + # Return nil if the line is empty + return nil if entries.nil? || entries.empty? + + # If /etc/hosts has a broken content we throw a descriptive exception + if entries[0].nil? + raise ArgumentError, "/etc/hosts has a line without IP address: #{line}" + end + if entries[1].nil? + raise ArgumentError, "/etc/hosts has a line without hostname: #{line}" + end + + return self.new( + ip_address: entries[0], + hostname: entries[1], + aliases: entries[2..-1], + comment: comment, + priority: priority, + ) + end + + private + + def extract_comment(line) + return nil if presence(line).nil? + line.split('#', 2).collect { |part| presence(part) } + end + + def extract_priority(comment) + return nil if comment.nil? + + if comment.include?('@') + comment.split('@', 2).collect { |part| presence(part) } + else + [comment, nil] + end + end + + def extract_entries(entry) + return nil if entry.nil? + entry.split(/\s+/).collect { |entry| presence(entry) }.compact + end + + def presence(string) + return nil if string.nil? + return nil if string.strip.empty? + string.strip + end + end + + # @return [String] + attr_accessor :ip_address, :hostname, :aliases, :comment, :priority + + # Creates a new entry from the given options. + # + # @param [Hash] options + # a list of options to create the entry with + # @option options [String] :ip_address + # the IP Address for this entry + # @option options [String] :hostname + # the hostname for this entry + # @option options [String, Array] :aliases + # a alias or array of aliases for this entry + # @option options[String] :comment + # an optional comment for this entry + # @option options [Fixnum] :priority + # the relative priority of this entry (compared to others) + # + # @raise [ArgumentError] + # if neither :ip_address nor :hostname are supplied + def initialize(options = {}) + if options[:ip_address].nil? || options[:hostname].nil? + raise ArgumentError, ':ip_address and :hostname are both required options' + end + + @ip_address = IPAddr.new(remove_ip_scope(options[:ip_address])) + @hostname = options[:hostname] + @aliases = [options[:aliases]].flatten.compact + @comment = options[:comment] + @priority = options[:priority] || calculated_priority + end + + # Set a the new priority for an entry. + # + # @param [Fixnum] new_priority + # the new priority to set + def priority=(new_priority) + @calculated_priority = false + @priority = new_priority + end + + # The line representation of this entry. + # + # @return [String] + # the string representation of this entry + def to_line + hosts = [hostname, aliases].flatten.join(' ') + + comments = "# #{comment.to_s}".strip + comments << " @#{priority}" unless priority.nil? || @calculated_priority + comments = comments.strip + comments = nil if comments == '#' + + [ip_address, hosts, comments].compact.join("\t").strip + end + + # Returns true if priority is calculated + # + # @return [Boolean] + # true if priority is calculated and false otherwise + def calculated_priority? + @calculated_priority + end + + private + + # Calculates the relative priority of this entry. + # + # @return [Fixnum] + # the relative priority of this item + def calculated_priority + @calculated_priority = true + + return 81 if ip_address == IPAddr.new('127.0.0.1') + return 80 if IPAddr.new('127.0.0.0/8').include?(ip_address) # local + return 60 if ip_address.ipv4? # ipv4 + return 20 if ip_address.ipv6? # ipv6 + return 00 + end + + # Removes the scopes pieces of the address, because reasons. + # + # @see https://bugs.ruby-lang.org/issues/8464 + # @see https://github.com/customink-webops/hostsfile/issues/51 + # + # @return [String, nil] + # + def remove_ip_scope(address) + return nil if address.nil? + address.to_s.sub(/%.*/, '') + end +end diff --git a/cookbooks/hostsfile/libraries/manipulator.rb b/cookbooks/hostsfile/libraries/manipulator.rb new file mode 100644 index 0000000..6afc047 --- /dev/null +++ b/cookbooks/hostsfile/libraries/manipulator.rb @@ -0,0 +1,293 @@ +# +# Author:: Seth Vargo +# Cookbook:: hostsfile +# Library:: manipulator +# +# Copyright 2012-2013, Seth Vargo +# Copyright 2012, CustomInk, LCC +# +# 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. +# + +require 'chef/application' +require 'digest/sha2' + +class Manipulator + attr_reader :node + attr_reader :entries + + # Create a new Manipulator object (aka an /etc/hosts manipulator). If a + # hostsfile is not found, an exception is raised. + # + # @param [Chef::node] node + # the current Chef node + # @return [Manipulator] + # a class designed to manipulate the node's /etc/hosts file + def initialize(node) + @node = node + + # Fail if no hostsfile is found + unless ::File.exists?(hostsfile_path) + raise RuntimeError, "No hostsfile exists at `#{hostsfile_path}'!" + end + + @entries = [] + collect_and_flatten(::File.readlines(hostsfile_path)) + end + + # Return a list of all IP Addresses for this hostsfile. + # + # @return [Array] + # the list of IP Addresses + def ip_addresses + @entries.collect do |entry| + entry.ip_address + end.compact || [] + end + + # Add a new record to the hostsfile. + # + # @param [Hash] options + # a list of options to create the entry with + # @option options [String] :ip_address + # the IP Address for this entry + # @option options [String] :hostname + # the hostname for this entry + # @option options [String, Array] :aliases + # a alias or array of aliases for this entry + # @option options[String] :comment + # an optional comment for this entry + # @option options [Fixnum] :priority + # the relative priority of this entry (compared to others) + def add(options = {}) + entry = Entry.new( + ip_address: options[:ip_address], + hostname: options[:hostname], + aliases: options[:aliases], + comment: options[:comment], + priority: options[:priority], + ) + + @entries << entry + remove_existing_hostnames(entry) if options[:unique] + end + + # Update an existing entry. This method will do nothing if the entry + # does not exist. + # + # @param (see #add) + def update(options = {}) + if entry = find_entry_by_ip_address(options[:ip_address]) + entry.hostname = options[:hostname] + entry.aliases = options[:aliases] + entry.comment = options[:comment] + entry.priority = options[:priority] + + remove_existing_hostnames(entry) if options[:unique] + end + end + + # Append content to an existing entry. This method will add a new entry + # if one does not already exist. + # + # @param (see #add) + def append(options = {}) + if entry = find_entry_by_ip_address(options[:ip_address]) + hosts = normalize(entry.hostname, entry.aliases, options[:hostname], options[:aliases]) + entry.hostname = hosts.shift + entry.aliases = hosts + + unless entry.comment && options[:comment] && entry.comment.include?(options[:comment]) + entry.comment = normalize(entry.comment, options[:comment]).join(', ') + end + + remove_existing_hostnames(entry) if options[:unique] + else + add(options) + end + end + + # Remove an entry by it's IP Address + # + # @param [String] ip_address + # the IP Address of the entry to remove + def remove(ip_address) + if entry = find_entry_by_ip_address(ip_address) + @entries.delete(entry) + end + end + + # Save the new hostsfile to the target machine. This method will only write the + # hostsfile if the current version has changed. In other words, it is convergent. + def save + file = Chef::Resource::File.new(hostsfile_path, node.run_context) + file.content(new_content) + file.run_action(:create) + end + + # Determine if the content of the hostfile has changed by comparing sha + # values of existing file and new content + # + # @return [Boolean] + def content_changed? + new_sha = Digest::SHA512.hexdigest(new_content) + new_sha != current_sha + end + + # Find an entry by the given IP Address. + # + # @param [String] ip_address + # the IP Address of the entry to find + # @return [Entry, nil] + # the corresponding entry object, or nil if it does not exist + def find_entry_by_ip_address(ip_address) + @entries.find do |entry| + !entry.ip_address.nil? && entry.ip_address == ip_address + end + end + + # Determine if the current hostsfile contains the given resource. This + # is really just a proxy to {find_resource_by_ip_address} / + # + # @param [Chef::Resource] resource + # + # @return [Boolean] + def contains?(resource) + !!find_entry_by_ip_address(resource.ip_address) + end + + private + + # The path to the current hostsfile. + # + # @return [String] + # the full path to the hostsfile, depending on the operating system + # can also be overriden in the node attributes + def hostsfile_path + return @hostsfile_path if @hostsfile_path + @hostsfile_path = node['hostsfile']['path'] || case node['platform_family'] + when 'windows' + "#{node['kernel']['os_info']['system_directory']}\\drivers\\etc\\hosts" + else + '/etc/hosts' + end + end + + # The header of the new hostsfile + # + # @return [Array] + # an array of header comments + def hostsfile_header + lines = [] + lines << '#' + lines << '# This file is managed by Chef, using the hostsfile cookbook.' + lines << '# Editing this file by hand is highly discouraged!' + lines << '#' + lines << '# Comments containing an @ sign should not be modified or else' + lines << '# hostsfile will be unable to guarantee relative priority in' + lines << '# future Chef runs!' + lines << '#' + lines << '' + end + + # The content that will be written to the hostfile + # + # @return [String] + # the full contents of the hostfile to be written + def new_content + entries = hostsfile_header + entries += unique_entries.map(&:to_line) + entries << '' + entries.join("\n") + end + + # The current sha of the system hostsfile. + # + # @return [String] + # the sha of the current hostsfile + def current_sha + @current_sha ||= Digest::SHA512.hexdigest(File.read(hostsfile_path)) + end + + # Normalize the given list of elements into a single array with no nil + # values and no duplicate values. + # + # @param [Object] things + # + # @return [Array] + # a normalized array of things + def normalize(*things) + things.flatten.compact.uniq + end + + # This is a crazy way of ensuring unique objects in an array using a Hash. + # + # @return [Array] + # the sorted list of entires that are unique + def unique_entries + entries = Hash[*@entries.map { |entry| [entry.ip_address, entry] }.flatten].values + entries.sort_by { |e| [-e.priority.to_i, e.hostname.to_s] } + end + + # Takes /etc/hosts file contents and builds a flattened entries + # array so that each IP address has only one line and multiple hostnames + # are flattened into a list of aliases. + # + # @param [Array] contents + # Array of lines from /etc/hosts file + def collect_and_flatten(contents) + contents.each do |line| + entry = Entry.parse(line) + next if entry.nil? + + append( + ip_address: entry.ip_address, + hostname: entry.hostname, + aliases: entry.aliases, + comment: entry.comment, + priority: !entry.calculated_priority? && entry.priority, + ) + end + end + + # Removes duplicate hostnames in other files ensuring they are unique + # + # @param [Entry] entry + # the entry to keep the hostname and aliases from + # + # @return [nil] + def remove_existing_hostnames(entry) + @entries.delete(entry) + changed_hostnames = [entry.hostname, entry.aliases].flatten.uniq + + @entries = @entries.collect do |entry| + entry.hostname = nil if changed_hostnames.include?(entry.hostname) + entry.aliases = entry.aliases - changed_hostnames + + if entry.hostname.nil? + if entry.aliases.empty? + nil + else + entry.hostname = entry.aliases.shift + entry + end + else + entry + end + end.compact + + @entries << entry + + nil + end +end diff --git a/cookbooks/hostsfile/libraries/matchers.rb b/cookbooks/hostsfile/libraries/matchers.rb new file mode 100644 index 0000000..788e427 --- /dev/null +++ b/cookbooks/hostsfile/libraries/matchers.rb @@ -0,0 +1,21 @@ +if defined?(ChefSpec) + def append_hostsfile_entry(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:hostsfile_entry, :append, resource_name) + end + + def create_hostsfile_entry(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:hostsfile_entry, :create, resource_name) + end + + def create_hostsfile_entry_if_missing(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:hostsfile_entry, :create_if_missing, resource_name) + end + + def remove_hostsfile_entry(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:hostsfile_entry, :remove, resource_name) + end + + def update_hostsfile_entry(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:hostsfile_entry, :update, resource_name) + end +end diff --git a/cookbooks/hostsfile/metadata.json b/cookbooks/hostsfile/metadata.json new file mode 100644 index 0000000..c2296cf --- /dev/null +++ b/cookbooks/hostsfile/metadata.json @@ -0,0 +1,29 @@ +{ + "name": "hostsfile", + "version": "2.4.5", + "description": "Provides an LWRP for managing the /etc/hosts file", + "long_description": "hostsfile LWRP\n==============\n[![Build Status](https://travis-ci.org/customink-webops/hostsfile.png?branch=master)](https://travis-ci.org/customink-webops/hostsfile)\n\n`hostsfile` provides an LWRP for managing your `/etc/hosts` (or Windows equivalent) file using Chef.\n\n\nRequirements\n------------\n- Chef 11 or higher\n- **Ruby 1.9.3 or higher**\n\n**Please stop opening Pull Requests to restore Ruby 1.8 support!** Any of the `1.x.y` series of this cookbook will work with Chef 10 and Ruby 1.8. You can use Opscode's [Omnibus installer](http://www.opscode.com/blog/2012/06/29/omnibus-chef-packaging/) to install Ruby 1.9+ and Seth Chisamore's [Vagrant Omnibus plugin](https://github.com/schisamo/vagrant-omnibus) to get Ruby 1.9+ on your Vagrant box.\n\n\nAttributes\n----------\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
AttributeDescriptionExampleDefault
ip_address(name attribute) the IP address for the entry1.2.3.4
hostname(required) the hostname associated with the entryexample.com
uniqueremove any existing entries that have the same hostnametruefalse
aliasesarray of aliases for the entry['www.example.com'][]
commenta comment to append to the end of the entry'interal DNS server'nil
prioritythe relative position of this entry20(varies, see **Priorities** section)
\n\n\nActions\n-------\n**Please note**: In `v0.1.2`, specifying a hostname or alias that existed in another automatically removed that hostname from the other entry before. In `v2.1.0`, the `unique` option was added to give the user case-by-case control of this behavior. For example, given an `/etc/hosts` file that contains:\n\n 1.2.3.4 example.com www.example.com\n\nwhen the Chef recipe below is converged:\n\n```ruby\nhostsfile_entry '2.3.4.5' do\n hostname 'www.example.com'\n unique true\nend\n```\n\nthen the `/etc/hosts` file will look like this:\n\n 1.2.3.4 example.com\n 2.3.4.5 www.example.com\n\nNot specifying the `unique` parameter will result in duplicate hostsfile entries.\n\n#### `create`\nCreates a new hosts file entry. If an entry already exists, it will be overwritten by this one.\n\n```ruby\nhostsfile_entry '1.2.3.4' do\n hostname 'example.com'\n action :create\nend\n```\n\nThis will create an entry like this:\n\n 1.2.3.4 example.com\n\n#### `create_if_missing`\nCreate a new hosts file entry, only if one does not already exist for the given IP address. If one exists, this does nothing.\n\n```ruby\nhostsfile_entry '1.2.3.4' do\n hostname 'example.com'\n action :create_if_missing\nend\n```\n\n#### `append`\nAppend a hostname or alias to an existing record. If the given IP address doesn't already exist in the hostsfile, this method behaves the same as create. Otherwise, it will append the additional hostname and aliases to the existing entry.\n\n 1.2.3.4 example.com www.example.com # Created by Chef\n\n```ruby\nhostsfile_entry '1.2.3.4' do\n hostname 'www2.example.com'\n aliases ['foo.com', 'foobar.com']\n comment 'Append by Recipe X'\n action :append\nend\n```\n\nwould yield:\n\n 1.2.3.4 example.com www.example.com www2.example.com foo.com foobar.com # Created by Chef, Appended by Recipe X\n\n\n#### `update`\nUpdates the given hosts file entry. Does nothing if the entry does not exist.\n\n```ruby\nhostsfile_entry '1.2.3.4' do\n hostname 'example.com'\n comment 'Update by Chef'\n action :update\nend\n```\n\nThis will create an entry like this:\n\n 1.2.3.4 example # Updated by Chef\n\n#### `remove`\nRemoves an entry from the hosts file. Does nothing if the entry does not\nexist.\n\n```ruby\nhostsfile_entry '1.2.3.4' do\n action :remove\nend\n```\n\nThis will remove the entry for `1.2.3.4`.\n\n\nUsage\n-----\nIf you're using [Berkshelf](http://berkshelf.com/), just add `hostsfile` to your `Berksfile`:\n\n```ruby\ncookbook 'hostsfile'\n```\n\nOtherwise, install the cookbook from the community site:\n\n knife cookbook site install hostsfile\n\nHave any other cookbooks *depend* on hostsfile by editing editing the `metadata.rb` for your cookbook.\n\n```ruby\n# metadata.rb\ndepends 'hostsfile'\n```\n\nNote that you can specify a custom path to your hosts file in the `['hostsfile']['path']` node attribute. Otherwise, it defaults to sensible paths depending on your OS.\n\n### Testing\nIf you are using [ChefSpec](https://github.com/sethvargo/chefspec) to unit test a cookbook that implements the `hostsfile_entry` LWRP, this cookbook packages customer matchers that you can use in your unit tests:\n\n- `append_hostsfile_entry`\n- `create_hostsfile_entry`\n- `create_hostsfile_entry_if_missing`\n- `remove_hostsfile_entry`\n- `update_hostsfile_entry`\n\nFor example:\n\n```ruby\nit 'creates a hostsfile entry for the DNS server' do\n expect(chef_run).to create_hostsfile_entry('1.2.3.4')\n .with_hostname('dns.example.com')\nend\n```\n\nPriority\n--------\nPriority is a relatively new addition to the cookbook. It gives you the ability to (somewhat) specify the relative order of entries. By default, the priority is calculated for you as follows:\n\n1. Local, loopback\n2. IPV4\n3. IPV6\n\nHowever, you can override it using the `priority` option.\n\n\nContributing\n------------\n1. Fork the project\n2. Create a feature branch corresponding to you change\n3. Commit and test thoroughly\n4. Create a Pull Request on github\n\n\nLicense & Authors\n-----------------\n- Author:: Seth Vargo (sethvargo@gmail.com)\n\n```text\nCopyright 2012-2013, Seth Vargo\nCopyright 2012, CustomInk, LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n", + "maintainer": "Seth Vargo", + "maintainer_email": "sethvargo@gmail.com", + "license": "Apache 2.0", + "platforms": { + }, + "dependencies": { + }, + "recommendations": { + }, + "suggestions": { + }, + "conflicting": { + }, + "providing": { + }, + "replacing": { + }, + "attributes": { + }, + "groupings": { + }, + "recipes": { + } +} \ No newline at end of file diff --git a/cookbooks/hostsfile/metadata.rb b/cookbooks/hostsfile/metadata.rb new file mode 100644 index 0000000..5474e5d --- /dev/null +++ b/cookbooks/hostsfile/metadata.rb @@ -0,0 +1,7 @@ +name 'hostsfile' +maintainer 'Seth Vargo' +maintainer_email 'sethvargo@gmail.com' +license 'Apache 2.0' +description 'Provides an LWRP for managing the /etc/hosts file' +long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) +version '2.4.5' diff --git a/cookbooks/hostsfile/providers/entry.rb b/cookbooks/hostsfile/providers/entry.rb new file mode 100644 index 0000000..dde469a --- /dev/null +++ b/cookbooks/hostsfile/providers/entry.rb @@ -0,0 +1,138 @@ +# +# Author:: Seth Vargo +# Cookbook:: hostsfile +# Provider:: entry +# +# Copyright 2012-2013, Seth Vargo +# Copyright 2012, CustomInk, LCC +# +# 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. +# + +# Support whyrun +def whyrun_supported? + true +end + +# Creates a new hosts file entry. If an entry already exists, it will be +# overwritten by this one. +action :create do + if hostsfile.contains?(new_resource) + Chef::Log.debug "#{new_resource} already exists - overwriting." + end + + hostsfile.add( + ip_address: new_resource.ip_address, + hostname: new_resource.hostname, + aliases: new_resource.aliases, + comment: new_resource.comment, + priority: new_resource.priority, + unique: new_resource.unique, + ) + + if hostsfile.content_changed? + converge_by("Create #{new_resource}") { hostsfile.save } + else + Chef::Log.info "#{new_resource} content already matches - nothing to do." + end +end + +# Create a new hosts file entry, only if one does not already exist for +# the given IP address. If one exists, this does nothing. +action :create_if_missing do + if hostsfile.contains?(new_resource) + Chef::Log.info "#{new_resource} already exists - skipping create_if_missing." + else + converge_by("Create #{new_resource} if missing") do + hostsfile.add( + ip_address: new_resource.ip_address, + hostname: new_resource.hostname, + aliases: new_resource.aliases, + comment: new_resource.comment, + priority: new_resource.priority, + unique: new_resource.unique, + ) + hostsfile.save + end + end +end + +# Appends the given data to an existing entry. If an entry does not exist, +# one will be created +action :append do + unless hostsfile.contains?(new_resource) + Chef::Log.info "#{new_resource} does not exist - creating instead." + end + + hostsfile.append( + ip_address: new_resource.ip_address, + hostname: new_resource.hostname, + aliases: new_resource.aliases, + comment: new_resource.comment, + priority: new_resource.priority, + unique: new_resource.unique, + ) + + if hostsfile.content_changed? + converge_by("Append #{new_resource}") { hostsfile.save } + else + Chef::Log.info "#{new_resource} content already matches - nothing to do." + end +end + +# Updates the given hosts file entry. Does nothing if the entry does not +# exist. +action :update do + if hostsfile.contains?(new_resource) + + hostsfile.update( + ip_address: new_resource.ip_address, + hostname: new_resource.hostname, + aliases: new_resource.aliases, + comment: new_resource.comment, + priority: new_resource.priority, + unique: new_resource.unique, + ) + + if hostsfile.content_changed? + converge_by("Update #{new_resource}") { hostsfile.save } + else + Chef::Log.info "#{new_resource} content already matches - nothing to do." + end + else + Chef::Log.info "#{new_resource} does not exist - skipping update." + end +end + +# Removes an entry from the hosts file. Does nothing if the entry does +# not exist. +action :remove do + if hostsfile.contains?(new_resource) + converge_by("Remove #{new_resource}") do + hostsfile.remove(new_resource.ip_address) + hostsfile.save + end + else + Chef::Log.info "#{new_resource} does not exist - skipping remove." + end +end + +private + +# The hostsfile object +# +# @return [Manipulator] +# the manipulator for this hostsfile +def hostsfile + @hostsfile ||= Manipulator.new(node) +end diff --git a/cookbooks/hostsfile/resources/entry.rb b/cookbooks/hostsfile/resources/entry.rb new file mode 100644 index 0000000..781e665 --- /dev/null +++ b/cookbooks/hostsfile/resources/entry.rb @@ -0,0 +1,36 @@ +# +# Author:: Seth Vargo +# Cookbook:: hostsfile +# Resource:: entry +# +# Copyright 2012-2013, Seth Vargo +# Copyright 2012, CustomInk, LCC +# +# 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. +# + +# List of all actions supported by the provider +actions :create, :create_if_missing, :append, :update, :remove + +# Make create the default action +default_action :create + +# Required attributes +attribute :ip_address, kind_of: String, name_attribute: true +attribute :hostname, kind_of: String + +# Optional attributes +attribute :aliases, kind_of: Array +attribute :comment, kind_of: String +attribute :priority, kind_of: Fixnum +attribute :unique, kind_of: [TrueClass, FalseClass] diff --git a/cookbooks/ipfs/.delivery/project.toml b/cookbooks/ipfs/.delivery/project.toml new file mode 100644 index 0000000..6d5e361 --- /dev/null +++ b/cookbooks/ipfs/.delivery/project.toml @@ -0,0 +1 @@ +remote_file = "https://raw.githubusercontent.com/chef-cookbooks/community_cookbook_tools/master/delivery/project.toml" diff --git a/cookbooks/ipfs/.gitignore b/cookbooks/ipfs/.gitignore new file mode 100644 index 0000000..c15fe86 --- /dev/null +++ b/cookbooks/ipfs/.gitignore @@ -0,0 +1 @@ +/.kitchen/ diff --git a/cookbooks/ipfs/.kitchen.dokken.yml b/cookbooks/ipfs/.kitchen.dokken.yml new file mode 100644 index 0000000..856fa9a --- /dev/null +++ b/cookbooks/ipfs/.kitchen.dokken.yml @@ -0,0 +1,40 @@ +--- +driver: + name: dokken + privileged: true # because Docker and SystemD/Upstart + chef_version: <%= ENV['CHEF_VERSION'] || 'current' %> + +transport: + name: dokken + +provisioner: + name: dokken + deprecations_as_errors: true + +verifier: + name: inspec + +platforms: + - name: ubuntu-16.04 + driver: + image: dokken/ubuntu-16.04 + pid_one_command: /bin/systemd + - name: ubuntu-18.04 + driver: + image: dokken/ubuntu-18.04 + pid_one_command: /bin/systemd + - name: debian-9 + driver: + image: dokken/debian-9 + pid_one_command: /bin/systemd + +suites: + - name: default + run_list: + - recipe[ipfs::default] + attributes: + - name: cluster + run_list: + - recipe[ipfs::cluster] + - recipe[ipfs::cluster_service] + attributes: diff --git a/cookbooks/ipfs/.kitchen.yml b/cookbooks/ipfs/.kitchen.yml new file mode 100644 index 0000000..5c9425c --- /dev/null +++ b/cookbooks/ipfs/.kitchen.yml @@ -0,0 +1,22 @@ +--- +driver: + name: vagrant + +provisioner: + name: chef_zero + +platforms: + - name: ubuntu-16.04 + - name: ubuntu-18.04 + - name: debian-9 + +suites: + - name: default + run_list: + - recipe[ipfs::default] + attributes: + - name: cluster + run_list: + - recipe[ipfs::cluster] + - recipe[ipfs::cluster_service] + attributes: diff --git a/cookbooks/ipfs/.travis.yml b/cookbooks/ipfs/.travis.yml new file mode 100644 index 0000000..c581c93 --- /dev/null +++ b/cookbooks/ipfs/.travis.yml @@ -0,0 +1,39 @@ +sudo: required +dist: trusty + +addons: + apt: + sources: + - chef-current-trusty + packages: + - chefdk + +# Don't `bundle install` which takes about 1.5 mins +install: echo "skip bundle install" + +branches: + only: + - master + +services: docker + +env: + matrix: + - INSTANCE=default-debian-9 + - INSTANCE=default-ubuntu-1604 + - INSTANCE=default-ubuntu-1804 + +before_script: + - sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER ) + - eval "$(chef shell-init bash)" + - CHEF_LICENSE=accept-no-persist chef --version + - cookstyle --version + - foodcritic --version + +script: CHEF_LICENSE=accept-no-persist KITCHEN_LOCAL_YAML=.kitchen.dokken.yml CHEF_VERSION=13.10.4 kitchen verify ${INSTANCE} + +matrix: + include: + - script: + - CHEF_LICENSE=accept-no-persist chef exec delivery local all + env: UNIT_AND_LINT=1 diff --git a/cookbooks/ipfs/Berksfile b/cookbooks/ipfs/Berksfile new file mode 100644 index 0000000..44bc4fc --- /dev/null +++ b/cookbooks/ipfs/Berksfile @@ -0,0 +1,3 @@ +source 'https://api.berkshelf.com' + +metadata diff --git a/cookbooks/ipfs/Berksfile.lock b/cookbooks/ipfs/Berksfile.lock new file mode 100644 index 0000000..1167417 --- /dev/null +++ b/cookbooks/ipfs/Berksfile.lock @@ -0,0 +1,19 @@ +DEPENDENCIES + ipfs + path: . + metadata: true + +GRAPH + ark (4.0.0) + build-essential (>= 0.0.0) + seven_zip (>= 0.0.0) + build-essential (8.1.1) + mingw (>= 1.1) + seven_zip (>= 0.0.0) + ipfs (0.4.0) + ark (>= 0.0.0) + mingw (2.1.0) + seven_zip (>= 0.0.0) + seven_zip (3.0.0) + windows (>= 0.0.0) + windows (5.0.0) diff --git a/cookbooks/ipfs/CHANGELOG.md b/cookbooks/ipfs/CHANGELOG.md new file mode 100644 index 0000000..1523cdc --- /dev/null +++ b/cookbooks/ipfs/CHANGELOG.md @@ -0,0 +1,4 @@ +# ipfs CHANGELOG + +## 0.1.0 +- [gregkare] - Initial release of ipfs diff --git a/cookbooks/ipfs/LICENSE b/cookbooks/ipfs/LICENSE new file mode 100644 index 0000000..deca87d --- /dev/null +++ b/cookbooks/ipfs/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2018 Kosmos Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/cookbooks/ipfs/README.md b/cookbooks/ipfs/README.md new file mode 100644 index 0000000..6d740d4 --- /dev/null +++ b/cookbooks/ipfs/README.md @@ -0,0 +1,91 @@ +# IPFS Cookbook + +This cookbook installs go-ipfs and starts it as a daemon + +## Requirements + +### Platforms + +This cookbook is tested on Ubuntu 18.06, 16.04 and Debian 9 using Test Kitchen. +It currently only supports 64bit platforms + +### Chef + +- Chef 12.5 or later (the cookbook provides a + [Custom Resource](https://docs.chef.io/custom_resources.html) to configure + go-ipfs) + +### Cookbook dependencies + +- `ark` to download and uncompress the go-ipfs package + +## Usage + +### ipfs::default + +Just include `ipfs` in your node's `run_list`: + +```json +{ + "name":"my_node", + "run_list": [ + "recipe[ipfs]" + ] +} +``` + +## Attributes + +- `node['ipfs']['version']` - the go-ipfs version to download from the official +site (64bit) +- `node['ipfs']['checksum']` - the SHA256 checksum for the package +- `node['ipfs']['config']` - a hash of config options + +## Resources + +`ipfs_config` sets the config. Supports hashes, arrays, booleans and strings. +Does not change anything if the config already has that value, and restarts +the server automatically + +```ruby +ipfs_config "Gateway.Writable" do + value "true" + end +``` + +## Running the specs and integrations tests + +Install the latest [Chef DK](https://downloads.chef.io/chefdk). + +``` +chef exec delivery local all # Run the linting check, syntax check and unit tests +kitchen verify # Run the integration tests for Ubuntu 16.04, 18.06 and Debian 9 +``` + +## License and Authors + +Authors: Kosmos Developers mail@kosmos.org +Copyright: 2018-2019, [Kosmos Developers](https://kredits.kosmos.org/) + +``` +Unless otherwise noted, all files are released under the MIT license, possible +exceptions will contain licensing information in them. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` diff --git a/cookbooks/ipfs/Rakefile b/cookbooks/ipfs/Rakefile new file mode 100644 index 0000000..981af6b --- /dev/null +++ b/cookbooks/ipfs/Rakefile @@ -0,0 +1,65 @@ +#!/usr/bin/env rake + +# Style tests. cookstyle (rubocop) and Foodcritic +namespace :style do + begin + require 'cookstyle' + require 'rubocop/rake_task' + + desc 'Run Ruby style checks' + RuboCop::RakeTask.new(:ruby) + rescue LoadError => e + puts ">>> Gem load error: #{e}, omitting #{task.name}" unless ENV['CI'] + end + + begin + require 'foodcritic' + + desc 'Run Chef style checks' + FoodCritic::Rake::LintTask.new(:chef) do |t| + t.options = { + fail_tags: ['any'], + progress: true, + } + end + rescue LoadError + puts ">>> Gem load error: #{e}, omitting #{task.name}" unless ENV['CI'] + end +end + +desc 'Run all style checks' +task style: ['style:chef', 'style:ruby'] + +# ChefSpec +begin + desc 'Run ChefSpec examples' + require 'rspec/core/rake_task' + RSpec::Core::RakeTask.new(:spec) +rescue LoadError => e + puts ">>> Gem load error: #{e}, omitting #{task.name}" unless ENV['CI'] +end + +# Integration tests. Kitchen.ci +namespace :integration do + begin + require 'kitchen/rake_tasks' + + desc 'Run kitchen integration tests' + Kitchen::RakeTasks.new + rescue StandardError => e + puts ">>> Gem load error: #{e}, omitting #{task.name}" unless ENV['CI'] + end +end + +namespace :supermarket do + begin + desc 'Publish cookbook to Supermarket with Stove' + require 'stove/rake_task' + Stove::RakeTask.new + rescue LoadError => e + puts ">>> Gem load error: #{e}, omitting #{task.name}" unless ENV['CI'] + end +end + +# Default +task default: %w(style spec) diff --git a/cookbooks/ipfs/attributes/default.rb b/cookbooks/ipfs/attributes/default.rb new file mode 100644 index 0000000..ec65268 --- /dev/null +++ b/cookbooks/ipfs/attributes/default.rb @@ -0,0 +1,31 @@ +node.default['ipfs']['version'] = '0.4.22' +node.default['ipfs']['checksum'] = '43431bbef105b1c8d0679350d6f496b934d005df28c13280a67f0c88054976aa' + +node.default['ipfs']['ulimit'] = 64000 +node.default['ipfs']['memory_max'] = '512M' +node.default['ipfs']['config'] = { + # Do not contact local network addresses. This will stop platforms like Hetzner + # to block your server (https://github.com/ipfs/go-ipfs/issues/1226) + 'Swarm.AddrFilters' => ['/ip4/10.0.0.0/ipcidr/8', + '/ip4/100.64.0.0/ipcidr/10', + '/ip4/169.254.0.0/ipcidr/16', + '/ip4/172.16.0.0/ipcidr/12', + '/ip4/192.0.0.0/ipcidr/24', + '/ip4/192.0.0.0/ipcidr/29', + '/ip4/192.0.0.8/ipcidr/32', + '/ip4/192.0.0.170/ipcidr/32', + '/ip4/192.0.0.171/ipcidr/32', + '/ip4/192.0.2.0/ipcidr/24', + '/ip4/192.168.0.0/ipcidr/16', + '/ip4/198.18.0.0/ipcidr/15', + '/ip4/198.51.100.0/ipcidr/24', + '/ip4/203.0.113.0/ipcidr/24', + '/ip4/240.0.0.0/ipcidr/4'], + # Set up the Gateway to be writable + 'Gateway.Writable' => true, + + # Set up CORS headers + 'API.HTTPHeaders.Access-Control-Allow-Credentials' => ['true'], + 'API.HTTPHeaders.Access-Control-Allow-Methods' => %w(PUT GET POST), + 'API.HTTPHeaders.Access-Control-Allow-Origin' => ['*'], +} diff --git a/cookbooks/ipfs/chefignore b/cookbooks/ipfs/chefignore new file mode 100644 index 0000000..7be3c6d --- /dev/null +++ b/cookbooks/ipfs/chefignore @@ -0,0 +1 @@ +.kitchen diff --git a/cookbooks/ipfs/metadata.json b/cookbooks/ipfs/metadata.json new file mode 100644 index 0000000..7f1ec90 --- /dev/null +++ b/cookbooks/ipfs/metadata.json @@ -0,0 +1,35 @@ +{ + "name": "ipfs", + "description": "Installs/Configures ipfs", + "long_description": "# IPFS Cookbook\n\nThis cookbook installs go-ipfs and starts it as a daemon\n\n## Requirements\n\n### Platforms\n\nThis cookbook is tested on Ubuntu 18.06, 16.04 and Debian 9 using Test Kitchen.\nIt currently only supports 64bit platforms\n\n### Chef\n\n- Chef 12.5 or later (the cookbook provides a\n [Custom Resource](https://docs.chef.io/custom_resources.html) to configure\n go-ipfs)\n\n### Cookbook dependencies\n\n- `ark` to download and uncompress the go-ipfs package\n\n## Usage\n\n### ipfs::default\n\nJust include `ipfs` in your node's `run_list`:\n\n```json\n{\n \"name\":\"my_node\",\n \"run_list\": [\n \"recipe[ipfs]\"\n ]\n}\n```\n\n## Attributes\n\n- `node['ipfs']['version']` - the go-ipfs version to download from the official\nsite (64bit)\n- `node['ipfs']['checksum']` - the SHA256 checksum for the package\n- `node['ipfs']['config']` - a hash of config options\n\n## Resources\n\n`ipfs_config` sets the config. Supports hashes, arrays, booleans and strings.\nDoes not change anything if the config already has that value, and restarts\nthe server automatically\n\n```ruby\nipfs_config \"Gateway.Writable\" do\n value \"true\"\n end\n```\n\n## Running the specs and integrations tests\n\nInstall the latest [Chef DK](https://downloads.chef.io/chefdk).\n\n```\nchef exec delivery local all # Run the linting check, syntax check and unit tests\nkitchen verify # Run the integration tests for Ubuntu 16.04, 18.06 and Debian 9\n```\n\n## License and Authors\n\nAuthors: Kosmos Developers mail@kosmos.org \nCopyright: 2018-2019, [Kosmos Developers](https://kredits.kosmos.org/)\n\n```\nUnless otherwise noted, all files are released under the MIT license, possible\nexceptions will contain licensing information in them.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n```\n", + "maintainer": "Kosmos Developers", + "maintainer_email": "mail@kosmos.org", + "license": "MIT", + "platforms": { + "[\"ubuntu\", \"debian\"]": ">= 0.0.0" + }, + "dependencies": { + "ark": ">= 0.0.0" + }, + "providing": { + + }, + "recipes": { + + }, + "version": "0.4.1", + "source_url": "https://github.com/67P/ipfs-cookbook", + "issues_url": "https://github.com/67P/ipfs-cookbook/issues", + "privacy": false, + "chef_versions": [ + [ + ">= 12.14" + ] + ], + "ohai_versions": [ + + ], + "gems": [ + + ] +} diff --git a/cookbooks/ipfs/metadata.rb b/cookbooks/ipfs/metadata.rb new file mode 100644 index 0000000..42758b4 --- /dev/null +++ b/cookbooks/ipfs/metadata.rb @@ -0,0 +1,15 @@ +name 'ipfs' +maintainer 'Kosmos Developers' +maintainer_email 'mail@kosmos.org' +license 'MIT' +description 'Installs/Configures ipfs' +long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) +version '0.4.1' + +supports %w(ubuntu debian) + +depends 'ark' + +source_url 'https://github.com/67P/ipfs-cookbook' +issues_url 'https://github.com/67P/ipfs-cookbook/issues' +chef_version '>= 12.14' if respond_to?(:chef_version) diff --git a/cookbooks/ipfs/recipes/_user.rb b/cookbooks/ipfs/recipes/_user.rb new file mode 100644 index 0000000..6278513 --- /dev/null +++ b/cookbooks/ipfs/recipes/_user.rb @@ -0,0 +1,38 @@ +# +# Cookbook Name:: ipfs +# Recipe:: _user +# +# The MIT License (MIT) +# +# Copyright:: 2018, Kosmos Developers +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +group 'ipfs' do + gid 4737 +end + +user 'ipfs' do + comment 'ipfs' + uid 4737 + gid 4737 + home '/home/ipfs' + shell '/bin/bash' + manage_home true +end diff --git a/cookbooks/ipfs/recipes/default.rb b/cookbooks/ipfs/recipes/default.rb new file mode 100644 index 0000000..73799a6 --- /dev/null +++ b/cookbooks/ipfs/recipes/default.rb @@ -0,0 +1,86 @@ +# +# Cookbook Name:: ipfs +# Recipe:: default +# +# The MIT License (MIT) +# +# Copyright:: 2018, Kosmos Developers +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +include_recipe 'ipfs::_user' + +version = node['ipfs']['version'] + +ark 'ipfs' do + url "https://dist.ipfs.io/go-ipfs/v#{version}/go-ipfs_v#{version}_linux-amd64.tar.gz" + checksum node['ipfs']['checksum'] + has_binaries ['ipfs'] +end + +execute 'ipfs init --empty-repo' do + environment 'IPFS_PATH' => '/home/ipfs/.ipfs' + user 'ipfs' + not_if { File.directory? '/home/ipfs/.ipfs' } +end + +if platform?('ubuntu') && node['platform_version'].to_f < 15.04 || + platform?('debian') && node['platform_version'].to_f < 8 + template 'ipfs.initd.service.erb' do + path '/etc/init.d/ipfs' + source 'ipfs.initd.service.erb' + owner 'root' + group 'root' + mode '0750' + notifies :restart, 'service[ipfs]', :delayed + end + + service 'ipfs' do + provider Chef::Provider::Service::Init::Debian + action [:enable] + supports start: true, stop: true, restart: true, reload: false, status: true + end + +else + execute 'systemctl daemon-reload' do + command 'systemctl daemon-reload' + action :nothing + end + + template 'ipfs.systemd.service.erb' do + path '/lib/systemd/system/ipfs.service' + source 'ipfs.systemd.service.erb' + owner 'root' + group 'root' + mode '0644' + notifies :run, 'execute[systemctl daemon-reload]', :delayed + notifies :restart, 'service[ipfs]', :delayed + end + + service 'ipfs' do + provider Chef::Provider::Service::Systemd + action [:enable] + end +end + +node['ipfs']['config'].each do |k, v| + ipfs_config k do + value v + end +end diff --git a/cookbooks/ipfs/resources/config.rb b/cookbooks/ipfs/resources/config.rb new file mode 100644 index 0000000..3051a47 --- /dev/null +++ b/cookbooks/ipfs/resources/config.rb @@ -0,0 +1,26 @@ +require 'json' +require 'mixlib/shellout' + +property :key, String, name_property: true +property :value, [String, Hash, Array, TrueClass, FalseClass, Integer], required: true + +action :create do + include_recipe 'ipfs' + + execute "ipfs config --json #{new_resource.key} '#{JSON.generate(new_resource.value)}'" do + environment 'IPFS_PATH' => '/home/ipfs/.ipfs' + user 'ipfs' + not_if do + cmd = Mixlib::ShellOut.new('ipfs', 'config', new_resource.key, + user: 'ipfs', + env: { 'IPFS_PATH' => '/home/ipfs/.ipfs' }) + cmd.run_command + begin + JSON.parse(cmd.stdout) == JSON.parse(JSON.generate(new_resource.value)) + rescue JSON::ParserError + cmd.stdout.include?(new_resource.value.to_s) + end + end + notifies :restart, 'service[ipfs]', :delayed + end +end diff --git a/cookbooks/ipfs/spec/spec_helper.rb b/cookbooks/ipfs/spec/spec_helper.rb new file mode 100644 index 0000000..052d78a --- /dev/null +++ b/cookbooks/ipfs/spec/spec_helper.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true +require 'chefspec' +require 'chefspec/berkshelf' diff --git a/cookbooks/ipfs/spec/unit/recipes/default_spec.rb b/cookbooks/ipfs/spec/unit/recipes/default_spec.rb new file mode 100644 index 0000000..9a43132 --- /dev/null +++ b/cookbooks/ipfs/spec/unit/recipes/default_spec.rb @@ -0,0 +1,55 @@ +# +# Cookbook:: ipfs +# Spec:: default +# +# The MIT License (MIT) +# +# Copyright:: 2018, Kosmos Developers +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +require 'spec_helper' + +describe 'ipfs::default' do + context 'When all attributes are default, on Ubuntu 16.04' do + let(:chef_run) do + # for a complete list of available platforms and versions see: + # https://github.com/customink/fauxhai/blob/master/PLATFORMS.md + runner = ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '16.04') + runner.converge(described_recipe) + end + + it 'converges successfully' do + expect { chef_run }.to_not raise_error + end + end + + context 'When all attributes are default, on Ubuntu 18.04' do + let(:chef_run) do + # for a complete list of available platforms and versions see: + # https://github.com/customink/fauxhai/blob/master/PLATFORMS.md + runner = ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '18.04') + runner.converge(described_recipe) + end + + it 'converges successfully' do + expect { chef_run }.to_not raise_error + end + end +end diff --git a/cookbooks/ipfs/templates/default/ipfs.initd.service.erb b/cookbooks/ipfs/templates/default/ipfs.initd.service.erb new file mode 100644 index 0000000..7315dd7 --- /dev/null +++ b/cookbooks/ipfs/templates/default/ipfs.initd.service.erb @@ -0,0 +1,102 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: ipfs daemon +# Required-Start: $local_fs $remote_fs $network $syslog $named +# Required-Stop: $local_fs $remote_fs $network $syslog $named +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Starts the ipfs daemon +# Description: Starts the ipfs daemon using the start-stop-daemon +### END INIT INFO + +# Author: Dylan Powers = 3.2-14) to ensure that this file is present +# and status_of_proc is working. +. /lib/lsb/init-functions + +# +# Function that starts the daemon/service +# +do_start() { + # Return + # 0 if daemon has been started + # 1 if daemon was already running + # 2 if daemon could not be started + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test >/dev/null \ + || return 1 + start-stop-daemon --start --quiet --pidfile $PIDFILE --make-pidfile \ + --background --chuid $IPFS_USER --no-close \ + --exec /usr/bin/env IPFS_PATH="$IPFS_PATH" $DAEMON 2>>$IPFS_PATH/daemon.log 1>/dev/null \ + -- $DAEMON_ARGS \ + || return 2 +} + +# +# Function that stops the daemon/service +# +do_stop() { + # Return + # 0 if daemon has been stopped + # 1 if daemon was already stopped + # 2 if daemon could not be stopped + # other if a failure occurred + start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME + RETVAL="$?" + [ "$RETVAL" = 2 ] && return 2 + + # Delete the pid + rm -f $PIDFILE + return "$RETVAL" +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? + ;; + restart) + do_stop + do_start + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|status|restart}" >&2 + exit 3 + ;; +esac diff --git a/cookbooks/ipfs/templates/default/ipfs.systemd.service.erb b/cookbooks/ipfs/templates/default/ipfs.systemd.service.erb new file mode 100644 index 0000000..f8155fb --- /dev/null +++ b/cookbooks/ipfs/templates/default/ipfs.systemd.service.erb @@ -0,0 +1,15 @@ +[Unit] +Description=Start ipfs + +[Service] +ExecStart=/usr/local/bin/ipfs daemon --migrate --routing=dhtclient +User=ipfs +Group=ipfs +Restart=always +# Raise the ulimit (max number of open files) +LimitNOFILE=<%= node['ipfs']['ulimit'] %> +# Limit the memory usage +MemoryMax=<%= node['ipfs']['memory_max'] %> + +[Install] +WantedBy=multi-user.target diff --git a/cookbooks/ipfs/test/integration/data_bags/.kitchen/logs/kitchen.log b/cookbooks/ipfs/test/integration/data_bags/.kitchen/logs/kitchen.log new file mode 100644 index 0000000..3f6cf59 --- /dev/null +++ b/cookbooks/ipfs/test/integration/data_bags/.kitchen/logs/kitchen.log @@ -0,0 +1,30 @@ +I, [2018-08-10T16:28:48.996619 #26331] INFO -- Kitchen: -----> Starting Kitchen (v1.15.0) +E, [2018-08-10T16:28:48.997042 #26331] ERROR -- Kitchen: ------Exception------- +E, [2018-08-10T16:28:48.997089 #26331] ERROR -- Kitchen: Class: Kitchen::UserError +E, [2018-08-10T16:28:48.997122 #26331] ERROR -- Kitchen: Message: Kitchen YAML file /Users/kare/code/kosmos/cookbooks/ipfs/test/integration/data_bags/.kitchen.yml does not exist. +E, [2018-08-10T16:28:48.997151 #26331] ERROR -- Kitchen: ---------------------- +E, [2018-08-10T16:28:48.997178 #26331] ERROR -- Kitchen: ------Backtrace------- +E, [2018-08-10T16:28:48.997205 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/test-kitchen-1.15.0/lib/kitchen/loader/yaml.rb:71:in `read' +E, [2018-08-10T16:28:48.997239 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/test-kitchen-1.15.0/lib/kitchen/config.rb:152:in `data' +E, [2018-08-10T16:28:48.997266 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/test-kitchen-1.15.0/lib/kitchen/config.rb:131:in `suites' +E, [2018-08-10T16:28:48.997294 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/test-kitchen-1.15.0/lib/kitchen/config.rb:182:in `filter_instances' +E, [2018-08-10T16:28:48.997321 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/test-kitchen-1.15.0/lib/kitchen/config.rb:141:in `build_instances' +E, [2018-08-10T16:28:48.997347 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/test-kitchen-1.15.0/lib/kitchen/config.rb:117:in `instances' +E, [2018-08-10T16:28:48.997374 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/test-kitchen-1.15.0/lib/kitchen/command.rb:112:in `filtered_instances' +E, [2018-08-10T16:28:48.997402 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/test-kitchen-1.15.0/lib/kitchen/command.rb:142:in `parse_subcommand' +E, [2018-08-10T16:28:48.997431 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/test-kitchen-1.15.0/lib/kitchen/command/action.rb:35:in `block in call' +E, [2018-08-10T16:28:48.997459 #26331] ERROR -- Kitchen: /Users/kare/.rubies/ruby-2.4.2/lib/ruby/2.4.0/benchmark.rb:293:in `measure' +E, [2018-08-10T16:28:48.997515 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/test-kitchen-1.15.0/lib/kitchen/command/action.rb:34:in `call' +E, [2018-08-10T16:28:48.997566 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/test-kitchen-1.15.0/lib/kitchen/cli.rb:53:in `perform' +E, [2018-08-10T16:28:48.997600 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/test-kitchen-1.15.0/lib/kitchen/cli.rb:187:in `block (2 levels) in ' +E, [2018-08-10T16:28:48.997631 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/thor-0.20.0/lib/thor/command.rb:27:in `run' +E, [2018-08-10T16:28:48.997666 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/thor-0.20.0/lib/thor/invocation.rb:126:in `invoke_command' +E, [2018-08-10T16:28:48.997696 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/test-kitchen-1.15.0/lib/kitchen/cli.rb:334:in `invoke_task' +E, [2018-08-10T16:28:48.997726 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/thor-0.20.0/lib/thor.rb:387:in `dispatch' +E, [2018-08-10T16:28:48.997766 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/thor-0.20.0/lib/thor/base.rb:466:in `start' +E, [2018-08-10T16:28:48.997796 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/test-kitchen-1.15.0/bin/kitchen:13:in `block in ' +E, [2018-08-10T16:28:48.997826 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/test-kitchen-1.15.0/lib/kitchen/errors.rb:171:in `with_friendly_errors' +E, [2018-08-10T16:28:48.997855 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/gems/test-kitchen-1.15.0/bin/kitchen:13:in `' +E, [2018-08-10T16:28:48.997882 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/bin/kitchen:23:in `load' +E, [2018-08-10T16:28:48.997918 #26331] ERROR -- Kitchen: /Users/kare/.gem/ruby/2.4.2/bin/kitchen:23:in `
' +E, [2018-08-10T16:28:48.997949 #26331] ERROR -- Kitchen: ----End Backtrace----- diff --git a/cookbooks/ipfs/test/integration/default/serverspec/ipfs_spec.rb b/cookbooks/ipfs/test/integration/default/serverspec/ipfs_spec.rb new file mode 100644 index 0000000..48cb2b4 --- /dev/null +++ b/cookbooks/ipfs/test/integration/default/serverspec/ipfs_spec.rb @@ -0,0 +1,58 @@ +require 'serverspec' +require 'json' + +# Required by serverspec +set :backend, :exec + +describe 'IPFS' do + # It is in the PATH + describe command('which ipfs') do + its(:exit_status) { should eq 0 } + end + + it 'is listening on port 4001' do + expect(port(4001)).to be_listening + end + + it 'is listening on port 8080 (gateway)' do + expect(port(8080)).to be_listening + end + + it 'has a running service of ipfs' do + expect(service('ipfs')).to be_running + expect(service('ipfs')).to be_enabled + end + + addr_filters = <<-EOF +[ + "/ip4/10.0.0.0/ipcidr/8", + "/ip4/100.64.0.0/ipcidr/10", + "/ip4/169.254.0.0/ipcidr/16", + "/ip4/172.16.0.0/ipcidr/12", + "/ip4/192.0.0.0/ipcidr/24", + "/ip4/192.0.0.0/ipcidr/29", + "/ip4/192.0.0.8/ipcidr/32", + "/ip4/192.0.0.170/ipcidr/32", + "/ip4/192.0.0.171/ipcidr/32", + "/ip4/192.0.2.0/ipcidr/24", + "/ip4/192.168.0.0/ipcidr/16", + "/ip4/198.18.0.0/ipcidr/15", + "/ip4/198.51.100.0/ipcidr/24", + "/ip4/203.0.113.0/ipcidr/24", + "/ip4/240.0.0.0/ipcidr/4" +] + EOF + + { + 'Swarm.AddrFilters' => addr_filters.rstrip, + 'Swarm.DisableBandwidthMetrics' => true, + 'Swarm.DisableRelay' => true, + 'Swarm.ConnMgr.HighWater' => 10, + 'Swarm.ConnMgr.LowWater' => 1, + }.each do |k, v| + describe command("IPFS_PATH=/home/ipfs/.ipfs ipfs config '#{k}'") do + let(:sudo_options) { '-u ipfs -i' } + its(:stdout) { should eq "#{v}\n" } + end + end +end diff --git a/cookbooks/java/CHANGELOG.md b/cookbooks/java/CHANGELOG.md new file mode 100644 index 0000000..1aae605 --- /dev/null +++ b/cookbooks/java/CHANGELOG.md @@ -0,0 +1,590 @@ +# Java Cookbook CHANGELOG + +This file is used to list changes made in each version of the Java cookbook. + +## Unreleased + +## 4.3.0 (2019-08-04) + +- Upgrade Amazon Corretto to the latest versions: 8.222.10.1 and 11.0.4.11.1 +- Upgrade circleci orb to version 2 and add yamllint and markdown lint + +## 4.2.0 - (2019-07-15) + +- Fix for issue 538 +- Added "download_path" node attribute defaulting to file_cache_path +- Replaced all hardcoded instances of file_cache_path with the node attribute + +## 4.1.0 - (2019-05-08) + +- Added new install flavor "corretto" for Amazon's Corretto distribution of OpenJDK + +## 4.0.0 - (2019-04-19) + +- Added new install flavor "adoptopenjdk" for AdoptOpenJDK's distribution of Java +- The certificate resource now uses the Java version to determine the default cacerts location +- Updated AdoptOpenJDK links for Java 8 +- Updated AdoptOpenJDK links for Java 11 to 11.0.1 +- BREAKING CHANGE: Remove support for Java 6 & 7 +- Remove platform suport for untested platforms (smartOS, XenServer, zlinux, arch) +- Remove testing of Ubuntu 14.04, support at this point is no longer guaranteed and patches or other changes may not be accepted going further as Ubuntu 14.04 will be shortly EOL +- Fixed oracle download link for JDK 8 (update to 8u202 from 8u201) +- fixed specs for windows + +## 3.2.0 - (2019-01-24) + +- Add support OpenJDK 11 +- Fixed oracle download link again + +## 3.1.2 - (2018-12-11) + +- Set java home on macosx using /usr/libexec/java_home +- Find command should have ./ for path to search, works for nix and mac +- Make `java_certificate` work with SNI endpoints + +## 3.1.1 - (2018-11-09) + +- Fix jce installation linux +- Allow overwrite `returns` property of windows_packages + +## 3.1.0 - (2018-10-18) + +- Add support for JDK 11 + +## 3.0.0 - (2018-10-18) + +- Fix broken JCE with JRE installations +- make cert alias matching case insensitive as `keytool` always returns results downcases +- BREAKING CHANGE: fixed greedy matching by adding a word boundry when checking cert alias this prevents matching `foo_123` as `foo` +- verify artifact after downloading from oracle +- fixed `recipes/openjdk` when `node['java']['jdk_version']` by casting it to a string +- Updated Oracle Java links to 8u191 + +## 2.2.1 - (2018-09-29) + +- Allows for additional Oracle (post 9) jdk download file naming, including '10.0.2'. '18.9', '11' + +## 2.2.0 - (2018-07-19) + +- Updated Oracle Java links to 8u181 +- Fixed incorrect kitchen setup runlists that preventing local testing +- Resolve undefined certout errors + +## 2.1.0 - (2018-05-25) + +- Added Java 10 JCE attributes to default attrs +- Update oracle recipeM to not perform a switch on java major version and instead use the version provided in attributes. This allows end users to include new Java versions without the cookbook requiring an update each time a major version gets released +- Updated the oracle_install resource to pick up semantic versioning that Oracle has started using for Java 10+ +- Updated the default attributes file to include x86_64 endpoint and checksum for Oracle Java 10\. The i586 version is not (yet) available. +- Fix JCE installation on Windows +- Avoid EmptyWindowsCommand error on Windows + +## v2.0.1 - (2018-05-02) + +- Fix java_certificate and java_oracle_install to work on FIPS enabled systems + +## v2.0.0 - (2018-05-02) + +- Converted alternatives, ark, and certificate LWRP/HWRPs to custom resources with improved logging and convergence notification. +- Renamed the java_ark resource to java_oracle_install, which better represents what it does. The existing name will continue to function +- Removed the need for the apt cookbook and instead require Chef 12.9+ +- Fixed Amazon Linux support on Chef 13+. +- Fixed the alternatives commands on Fedora systems. +- Added initial openSUSE leap support. +- Updated code to use multi-package installs to speed up runs +- Made the 'cert_alias' property in the certificate resource the name_property to allow users to avoid resource cloning and to be able to use friendly resource names +- Moved the warning code for downloading directly from Oracle into the resource to prevent another resource showing as converged +- Updated the metadata to resolve failures to parse chef_version on older chef-client releases. +- Added installation of tar directly to the ark resource when uncompression .tar.gz files. This prevents installation in the recipe that occurred even if tar wasn't needed. +- Deprecated the java::purge recipe which purged old Sun Java packages which were distributed in distro repos before the Oracle acquisition of Sun. Migration away from these packages occurred many years ago and this recipe will be removed in the next major release of this cookbook. +- Updated the metadata license string to an SPDX compliant string to resolve Foodcritic warnings. +- Removed Chef 10 compatibility code in the Windows recipe that resulted in Foodcritic warnings. +- Removed logic to support paths on Debian < 7 and Ubuntu < 12.04 as these are both EOL. +- Removed duplicate logging in the resources. +- Converted integration tests from bats to InSpec. +- Moved template files out of the default directory as +- Corrected deprecation warnings in the ChefSpecs. +- Moved all Kitchen testing logic to the test_java cookbook and eliminated the need for the apt & free_bsd bash cookbooks in testing +- Don't try to create Chef's cache directory in the certificate resource. +- Disabled certificate integration tests since we're not currently running the certificate resource in Test Kitchen. +- Removed testing of Oracle JDK 6/7 since Oracle no longer allows directly downloading these releases. +- Added kitchen-dokken based testing + +## v1.50.0 - (05/24/2017) + +- Oracle downloads changed again. Only Oracle 8 is able to be downloaded automatically. Please host your own copy internally to avoid issues such as this. +- Add Log warning if download url contains oracle.com + +## v1.49.0 - (04/21/2017) + +- potential 'curl' resource cloning #415 +- Oracle 8u131 +- Add ChefSpec matchers for java_certificate resource +- Remove unnecessary apt update + +## v1.48.0 - (03/31/2017) + +- Update Oracle Java links from 101 to 121 +- Remove convergence report +- Remove Fedora 24 testing +- Fix test cookbook license +- Update platforms in the specs +- Remove testing on EOL platforms + +## v1.47.0 - (01/30/2017) + +- Fix typo in method name (#397) +- Remove useless ruby_block[set-env-java-home] +- Update README: using java::notify +- Add forgotten "do" to README + +## v1.46.0 - (01/09/2017) + +- fix jce installation on windows #386 + +## v1.45.0 - (12/27/2016) + +- Update to resolve latest rubocop rules + +## v1.44.0 - (12/27/2016) + +- Unpublished due to newer rubocop rules in travis +- Added zlinux defaults + +## v1.43.0 - (12/6/2016) + +- Switch recursive chown from executing on the jdk parent directory to executing on the jdk directory itself. +- Added proxy support to curl +- add java_certificate LWRP from java-libraries cookbook - java-libraries now depricated. +- (Windows) support removal of obsolete JREs via optional attribute +- (Windows) Can download from s3 only using an IAM profile +- (Windows) aws session token for windows java download + +## v1.42.0 - (8/8/2016) + +- Use openjdk ppa for all ubuntu versions to allow for older/newer jdks to be installed. Fixes #368 +- update oracle java 8u101 - Use sha256 hash (seems to help with downloading each converge) +- Mac default converge fails since notify is not included by homebrew +- Remove chef 14(!) depreciation warning in tests +- Resolve chef-12 related warning + +## v1.41.0 - (7/15/2016) + +- Feature: Add new resource for cookbooks to subscribe to, see README +- Use a remote_file resource for JCE download instead of curl in an execute block. +- Since v1.40.4 Travis deploys cookbook to supermarket - expect more frequent, smaller releases. + +## v1.40.4 - (7/12/2016) + +- Automated deploy, no cookbook changes. + +## v1.40.3 - (7/12/2016) + +- Attempt to have travis publish this. +- Mac depends on homebrew. +- Fixed typo in platform family spelling for OS X +- fix openjdk version logic for freebsd +- Enable Ark provider to handle URI with get parameters + +## v1.40.1 - (7/8/2016) + +- Fixed: JAVA_HOME not set on systems with restrictive umask #359 + +## v1.40 - (6/29/2016) + +- Travis build green +- Add Windows JCE support +- Changes to prevent re-execution of resource creating file '/etc/profile.d/jdk.sh' +- Fix JDK checksum +- Update ibm_jdk.installer.properties.erb for IBM JDK 1.8 +- Install OpenJDK from distribution if Ubuntu version >= 15.10 +- Fixes #342 - Tar is included in macosx and homebrews package is gnutar which causes this to fail +- Add 12.04 to jdk8 test suite +- Add source and issues urls to supermarket +- Distinguishing the Java version for installing on the Mac OS X +- Doc and cruft cleanup + +## v1.39 - (1/14/2016) + +- Travis debugging only, no code changes. + +## v1.38 - (1/13/2016) + +- (Win) Fix for Java install failing on Windows (introduced in #315) +- Travis fixes/badge + +## v1.37 - (11/9/2015) + +- (Win) Attirbute for specifying the install directory for the public jre #315 + +## v1.36 - (9/3/2015) + +- Oracle JDK 1.8.0_65 +- Add Ubuntu ppa (allows OpenJDK 8) +- Added ChefSpec matchers #284 +- Fix compile error using Chef::Application.fatal #279 +- #222 Provide possibility to set ark download timeout +- Openjdk6 does not exist in deb 8.2 +- Change to create java home dir even if top level doesn't exist(Eg mkdir_p instead of mkdir) +- Fix berks url and remove apt +- Documentation and dependency updates + +## v1.35 - (8/4/2015) + +- Use bento boxes and remove EOL distros from testing suite. +- Update to latest JDKs. Note Oracle JDK7 is now EOL. +- Alternatives improvements +- Fixes #155 to allow install of OpenJDK 1.8 +- Fixes #257 Changed switches for the jdk 8 exe installer on windows +- Make sure tar package installed for java_ark +- Add support for Mac OS X "mac_os_x" via homebrew. +- Update metadata.rb to contain source and issue information for supermarket and chef-repo convenience + +### Known Issues + +- Kitchen CI test with 12.04 fails due to hostname unable to be set. + +## v1.31 - (2/3/2015) + +- Update to latest JDKs for 7 and 8\. JDK7 will be EOL April 2015 +- Fix up Travis support. +- Add ability to install JCE policy files for oracle JDK #228 +- Change connect timeout to 30 seconds + +## v1.29.0 - (11/14/2014) + +- **[#216](https://github.com/agileorbit-cookbooks/java/pull/216)** - Ensure dirs, links, and jinfo files are owned correctly +- **[#217](https://github.com/agileorbit-cookbooks/java/pull/217)** - Update to Oracle JDK 8u25 +- **[#214](https://github.com/agileorbit-cookbooks/java/pull/214)** - Update to Oracle JDK 7u71-b14 +- Adding a connect_timeout option for downloading java. +- Switched to chef-zero provisioner in test suites. +- Adding ISSUES.md for guidance on creating new issues for the Java cookbook. +- Fix IBM unit tests. + +## v1.28.0 - (9/6/2014) + +- Allow setting of group to extracted java files. +- Add -no-same-owner parameter to tar extract to avoid issues when the chef cache dir is on an NFS mounted drive. +- In the ark provider, it doesn't compare the MD5 sum with the right value which causes Java cookbook always download tarball from oracle server + +## v1.27.0 - (8/22/2014) + +- Update Oracle JDK8 to version 8u20 + +## v1.26.0 - (8/16/2014) + +- **[#201](https://github.com/agileorbit-cookbooks/java/pull/201)** - Allow pinning of package versions for openjdk +- **[#198](https://github.com/agileorbit-cookbooks/java/pull/198)** - Update Oracle JDK7 to version 7u67 +- **[#189](https://github.com/agileorbit-cookbooks/java/pull/184)** - Support specific version and name for Oracle RPM + +## v1.25.0 - (8/1/2014) + +- **[#189](https://github.com/agileorbit-cookbooks/java/pull/189)** - Resource ark -> attribute bin_cmds default value +- **[#168](https://github.com/agileorbit-cookbooks/java/pull/168)** - Add option to put JAVA_HOME in /etc/environment +- **[#172](https://github.com/agileorbit-cookbooks/java/pull/172)** - Allow ark to pull from http and files ending in .gz. +- Recommendations for inclusion in community cookbooks +- Production Deployment with Oracle Java +- Update testing instructions for chefdk +- Various Readme formatting. +- Use Supermarket endpoint in berksfile +- rspec cleanup +- Adding ubuntu-14.04 to test suite + +## v1.24.0 - (7/25/2014) + +New Cookbook maintainer! **[Agile Orbit](http://agileorbit.com)** + +- **[#192](https://github.com/agileorbit-cookbooks/java/pull/192)** - Bump JDK7 URLs to 7u65 +- **[#191](https://github.com/agileorbit-cookbooks/java/pull/192)** - Upgrade Oracle's Java 8 to u11 +- **[#188](https://github.com/agileorbit-cookbooks/java/pull/188)** - Allow for alternatives priority to be set from attribute. +- **[#176](https://github.com/agileorbit-cookbooks/java/pull/176)** - Change ownership of extracted files +- **[#169](https://github.com/agileorbit-cookbooks/java/pull/169)** - Add retries and retry_delay parameters to java_ark LWRP +- **[#167](https://github.com/agileorbit-cookbooks/java/pull/167)** - default: don't fail when using java 8 on windows +- **[#165](https://github.com/agileorbit-cookbooks/java/pull/165)** - Support for Server JRE +- **[#158](https://github.com/agileorbit-cookbooks/java/pull/158)** - Updated README for accepting oracle terms +- **[#157](https://github.com/agileorbit-cookbooks/java/pull/157)** -Remove VirtualBox specific box_urls +- List AgileOrbit as the maintainer (AgileOrbit took over from Socrata in July 2014) + +## v1.23.0 - (7/25/2014) + +- Tagged but never published to community cookbooks. All changes rolled into 1.24.0 + +## v1.22.0 + +- **[#148](https://github.com/socrata-cookbooks/java/pull/148)** - Add support for Oracle JDK 1.8.0 +- **[#150](https://github.com/socrata-cookbooks/java/pull/150)** - Make use of Chef's cache directory instead of /tmp +- **[#151](https://github.com/socrata-cookbooks/java/pull/151)** - Update Test Kitchen suites +- **[#154](https://github.com/socrata-cookbooks/java/pull/154)** - Add safety check for JDK 8 on non-Oracle + +## v1.21.2 + +- **[#146](https://github.com/socrata-cookbooks/java/pull/146)** - Update Oracle accept-license-terms cookie format + +## v1.21.0 + +- **[#143](https://github.com/socrata-cookbooks/java/pull/143)** - Symlink /usr/lib/jvm/default-java for both OpenJDK and Oracle +- **[#144](https://github.com/socrata-cookbooks/java/pull/144)** - Remove /var/lib/alternatives/#{cmd} before calling alternatives (Hopefully fixes sporadic issues when setting alternatives) +- **[Make default_java_symlink conditional on set_default attribute](https://github.com/socrata-cookbooks/java/commit/e300e235a463382a5022e1dddaac674930b4d138)** + +## v1.20.0 + +- **[#137](https://github.com/socrata-cookbooks/java/pull/137)** - Create /usr/lib/jvm/default-java on Debian +- **[#138](https://github.com/socrata-cookbooks/java/pull/138)** - allow wrapping cookbook without providing templates +- **[#140](https://github.com/socrata-cookbooks/java/pull/140)** - Adds set_default attribute to toggle setting JDK as default +- **[#141](https://github.com/socrata-cookbooks/java/pull/141)** - set java_home correctly for oracle_rpm + +## v1.19.2 + +- **[#129](https://github.com/socrata-cookbooks/java/pull/129)** - Upgrade to ChefSpec 3 +- Rewrite unit tests for better coverage and to work with ChefSpec 3 (various commits) +- List Socrata as the maintainer (Socrata took over from Opscode in December 2013) +- **[#133](https://github.com/socrata-cookbooks/java/pull/133)** - Allow jdk_version to be a string or number +- **[#131](https://github.com/socrata-cookbooks/java/pull/131)** - Fix JDK install on Windows +- **[Fix openjdk_packages on Arch Linux](https://github.com/socrata-cookbooks/java/commit/677bee7b9bf08988596d40ac65e75984a86bda99)** + +## v1.19.0 + +Refactor the cookbook to better support wrapper cookbooks and other cookbook authoring patterns. + +- **[#123](https://github.com/socrata-cookbooks/java/pull/123)** - Update documentation & add warning for issue 122 +- **[#124](https://github.com/socrata-cookbooks/java/pull/124)** - Refactor default recipe to better enable wrapper cookbooks +- **[#125](https://github.com/socrata-cookbooks/java/pull/125)** - Removes the attribute to purge deprecated packages +- **[#127](https://github.com/socrata-cookbooks/java/pull/127)** - Add safety check if attributes are unset +- **[Adds tests for directly using openjdk and oracle recipes](https://github.com/socrata-cookbooks/java/commit/794df596959d65a1a6d5f6c52688bffd8de6bff4)** +- **[Adds recipes to README](https://github.com/socrata-cookbooks/java/commit/76d52114bb9df084174d43fed143123b1cdbae16)** +- **[The Opscode CCLA is no longer required](https://github.com/socrata-cookbooks/java/commit/ce4ac25caa8383f185c25c4e32cafef8c0453376)** +- **[Adds tests for openjdk-7 and oracle-7](https://github.com/socrata-cookbooks/java/commit/9c38af241f68b3198cde4ad6fe2b4cb752062009)** +- **[#119](https://github.com/socrata-cookbooks/java/pull/119)** - Use java_home instead of java_location for update-alternatives +- **[Fix java_home for rhel and fedora](https://github.com/socrata-cookbooks/java/commit/71dadbd1bfe2eab50ff21cdab4ded97877911cc4)** + +## v1.18.0 + +- **[#118](https://github.com/socrata-cookbooks/java/pull/118)** - Upgrade to 7u51 +- **[#117](https://github.com/socrata-cookbooks/java/pull/117)** - Suggest windows and aws + +## v1.17.6 + +- Revert **[COOK-4165](https://tickets.opscode.com/browse/COOK-4165)** - The headers option was only added to remote_file in Chef 11.6.0, meaning this change breaks older clients. + +## v1.17.4 + +### Bug + +- **[#111](https://github.com/socrata-cookbooks/java/pull/111)** - Fix alternatives for centos + +### Improvement + +- **[COOK-4165](https://tickets.opscode.com/browse/COOK-4165)** - Replace curl with remote_file with cookie header +- **[#110](https://github.com/socrata-cookbooks/java/pull/110)** - Update openjdk to use the alternatives resource + +## v1.17.2 + +### Bug + +- **[COOK-4136](https://tickets.opscode.com/browse/COOK-4136)** - Add md5 parameter to java_ark resource + +## v1.17.0 + +- **[COOK-4114](https://tickets.opscode.com/browse/COOK-4114)** - Test Kitchen no longer works after merging Pull Request #95 for openjdk tests on Debian/Ubuntu +- **[COOK-4124](https://tickets.opscode.com/browse/COOK-4124)** - update-alternatives fails to run +- **[#81](https://github.com/socrata/java/pull/81)** - Ensure local directory hierarchy +- **[#97](https://github.com/socrata/java/pull/97)** - Expose LWRP state attributes +- **[#99](https://github.com/socrata/java/pull/99)** - support for MD5 checksum +- **[#106](https://github.com/socrata/java/pull/106)** - Fixed windows case to prevent bad java_home variable setting +- **[Update checksums to the officially-published ones from Oracle](https://github.com/socrata/java/commit/b9e1df24caeb6e22346d2d415b3b4384f15d4ffd)** +- **[Further test kitchen fixes to use the default recipe](https://github.com/socrata/java/commit/01c0b432705d9cfa6d2dfeaa380983e3f604069f)** + +## v1.16.4 + +### Bug + +- **[#103](https://github.com/socrata/java/pull/103)** - set alternatives when using ibm_tar recipe +- **[#104](https://github.com/socrata/java/pull/104)** - Specify windows attributes in attribute files + +## v1.16.2 + +### Improvement + +- **[COOK-3488](https://tickets.opscode.com/browse/COOK-3488)** - set alternatives for ibm jdk +- **[COOK-3764](https://tickets.opscode.com/browse/COOK-3764)** - IBM Java installer needs 'rpm' package on Ubuntu + +### Bug + +- **[COOK-3857](https://tickets.opscode.com/browse/COOK-3857)** - do not unescape the java windows url before parsing it +- **[#95](https://github.com/socrata/java/pull/95)** - fixes update-alternatives for openjdk installs +- **[#100](https://github.com/socrata/java/pull/100)** - Use escaped quotes for Windows INSTALLDIR + +## v1.16.0 + +### Improvement + +- **[COOK-3823](https://tickets.opscode.com/browse/COOK-3823)** - Upgrade to JDK 7u45-b18 + +## v1.15.4 + +[COOK-4210] - remove unneeded run_command to prevent zombie processes + +## v1.15.2 + +[CHEF-4210] remove unneeded run_command to prevent zombie processes + +## v1.15.0 + +### Bug + +- Fixing version number. Accidently released at 0.15.x instead of 1.15.x + +## v0.15.2 + +### FIX + +- [COOK-3908] - Fixing JAVA_HOME on Ubuntu 10.04 + +## v1.14.0 + +### Bug + +- **[COOK-3704](https://tickets.opscode.com/browse/COOK-3704)** - Fix alternatives when the package is already installed +- **[COOK-3668](https://tickets.opscode.com/browse/COOK-3668)** - Fix a condition that would result in an error executing action `run` on resource 'bash[update-java-alternatives]' +- **[COOK-3569](https://tickets.opscode.com/browse/COOK-3569)** - Fix bad checksum length +- **[COOK-3541](https://tickets.opscode.com/browse/COOK-3541)** - Fix an issue where Java cookbook installs both JDK 6 and JDK 7 when JDK 7 is specified +- **[COOK-3518](https://tickets.opscode.com/browse/COOK-3518)** - Allow Windoes recipe to download from signed S3 url +- **[COOK-2996](https://tickets.opscode.com/browse/COOK-2996)** - Fix a failure on Centos 6.4 and Oracle JDK 7 + +### Improvement + +- **[COOK-2793](https://tickets.opscode.com/browse/COOK-2793)** - Improve Windows support + +## v1.13.0 + +### Bug + +- **[COOK-3295](https://tickets.opscode.com/browse/COOK-3295)** - Add default `platform_family` option in Java helper +- **[COOK-3277](https://tickets.opscode.com/browse/COOK-3277)** - Fix support for Fedora + +### Improvement + +- **[COOK-3278](https://tickets.opscode.com/browse/COOK-3278)** - Upgrade to Oracle Java 7u25 +- **[COOK-3029](https://tickets.opscode.com/browse/COOK-3029)** - Add Oracle RPM support +- **[COOK-2931](https://tickets.opscode.com/browse/COOK-2931)** - Add support for the platform `xenserver` +- **[COOK-2154](https://tickets.opscode.com/browse/COOK-2154)** - Add SmartOS support + +## v1.12.0 + +### Improvement + +- [COOK-2154]: Add SmartOS support to java::openjdk recipe +- [COOK-3278]: upgrade to Oracle Java 7u25 +- [COOK-2931]: Adding support for the platform 'xenserver' (for installations of java in DOM0) +- [COOK-3277]: java cookbook fails on Fedora + +## v1.11.6 + +- [COOK-2847]: Java cookbook does not have opensuse support +- [COOK-3142]: Syntax Errors spec/default_spec.rb:4-8 + +## v1.11.4 + +- [COOK-2989]: `bash[update-java-alternatives]` resource uses wrong attribute + +## v1.11.2 + +- Use SHA256 checksums for Oracle downloads, not SHA1. + +## v1.11.0 + +This version brings a wealth of tests and (backwards-compatible) refactoring, plus some new features (updated Java, IBM recipe). + +- [COOK-2897]: Add ibm recipe to java cookbook +- [COOK-2903]: move java_home resources to their own recipe +- [COOK-2904]: refactor ruby_block "update-java-alternatives" +- [COOK-2905]: use platform_family in java cookbook +- [COOK-2920]: add chefspec to java cookbook +- [COOK-2902]: Refactor java cookbook +- [COOK-2900]: update JDK to JDK 7u21, 6u45 + +## v1.10.2 + +- [COOK-2415] - Fixed deprecation warnings in ark provider and openjdk recipe by using Chef::Mixin::ShellOut instead of Chef::ShellOut + +## v1.10.0 + +- [COOK-2400] - Allow java ark :url to be https +- [COOK-2436] - Upgrade needed for oracle jdk in java cookbook + +## v1.9.6 + +- [COOK-2412] - add support for Oracle Linux + +## v1.9.4 + +- [COOK-2083] - Run set-env-java-home in Java cookbook only if necessary +- [COOK-2332] - ark provider does not allow for *.tgz tarballs to be used +- [COOK-2345] - Java cookbook fails on CentOS6 (update-java-alternatives) + +## v1.9.2 + +- [COOK-2306] - FoodCritic fixes for java cookbook + +## v1.9.0 + +- [COOK-2236] - Update the Oracle Java version in the Java cookbook to release 1.7u11 + +## v1.8.2 + +- [COOK-2205] - Fix for missing /usr/lib/jvm/default-java on Debian + +## v1.8.0 + +- [COOK-2095] - Add windows support + +## v1.7.0 + +- [COOK-2001] - improvements for Oracle update-alternatives + - When installing an Oracle JDK it is now registered with a higher priority than OpenJDK. (Related to COOK-1131.) + - When running both the oracle and oracle_i386 recipes, alternatives are now created for both JDKs. + - Alternatives are now created for all binaries listed in version specific attributes. (Related to COOK-1563 and COOK-1635.) + - When installing Oracke JDKs on Ubuntu, create .jinfo files for use with update-java-alternatives. Commands to set/install alternatives now only run if needed. + +## v1.6.4 + +- [COOK-1930] - fixed typo in attribute for java 5 on i586 + +## v1.6.2 + +- whyrun support in `java_ark` LWRP +- CHEF-1804 compatibility +- [COOK-1786] - install Java 6u37 and Java 7u9 +- [COOK-1819] - incorrect warning text about `node['java']['oracle']['accept_oracle_download_terms']` + +## v1.6.0 + +- [COOK-1218] - Install Oracle JDK from Oracle download directly +- [COOK-1631] - set JAVA_HOME in openjdk recipe +- [COOK-1655] - Install correct architecture on Amazon Linux + +## v1.5.4 + +- [COOK-885] - update alternatives called on wrong file +- [COOK-1607] - use shellout instead of execute resource to update alternatives + +## v1.5.2 + +- [COOK-1200] - remove sun-java6-jre on Ubuntu before installing Oracle's Java +- [COOK-1260] - fails on Ubuntu 12.04 64bit with openjdk7 +- [COOK-1265] - Oracle Java should symlink the jar command + +## v1.5.0 + +- [COOK-1146] - Oracle now prevents download of JDK via non-browser +- [COOK-1114] - fix File.exists? + +## v1.4.2 + +- [COOK-1051] - fix attributes typo and platform case switch consistency + +## v1.4.0 + +- [COOK-858] - numerous updates: handle jdk6 and 7, switch from sun to oracle, make openjdk default, add `java_ark` LWRP. +- [COOK-942] - FreeBSD support +- [COOK-520] - ArchLinux support diff --git a/cookbooks/java/CONTRIBUTING.md b/cookbooks/java/CONTRIBUTING.md new file mode 100644 index 0000000..7e07372 --- /dev/null +++ b/cookbooks/java/CONTRIBUTING.md @@ -0,0 +1,21 @@ +# Contributing + +## Branches + +### `master` branch + +The master branch is the current committed changes. These changes may not yet be released although we try to release often. + +## Tags + +All releases are tagged in git. To see the releases available to you see the changelog or the tags directly. + +## Pull requests + +- + +## Issues + +Need to report an issue? Use the github issues: + +- diff --git a/cookbooks/java/README.md b/cookbooks/java/README.md new file mode 100644 index 0000000..4bddb12 --- /dev/null +++ b/cookbooks/java/README.md @@ -0,0 +1,466 @@ +# java cookbook + +[![Cookbook Version](https://img.shields.io/cookbook/v/java.svg)](https://supermarket.chef.io/cookbooks/java) +[![Build Status](https://img.shields.io/circleci/project/github/sous-chefs/java/master.svg)](https://circleci.com/gh/sous-chefs/java) +[![OpenCollective](https://opencollective.com/sous-chefs/backers/badge.svg)](#backers) +[![OpenCollective](https://opencollective.com/sous-chefs/sponsors/badge.svg)](#sponsors) +[![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)](https://opensource.org/licenses/Apache-2.0) + +This cookbook installs a Java JDK/JRE. It defaults to installing OpenJDK, but it can also install Oracle, IBM JDKs or AdoptOpenJDK. + +## Maintainers + +This cookbook is maintained by the Sous Chefs. The Sous Chefs are a community of Chef cookbook maintainers working together to maintain important cookbooks. If you’d like to know more please visit [sous-chefs.org](https://sous-chefs.org/) or come chat with us on the Chef Community Slack in [#sous-chefs](https://chefcommunity.slack.com/messages/C2V7B88SF). + +## Production Deployment with Oracle Java + +Oracle has been known to change the behavior of its download site frequently. It is recommended you store the archives on an artifact server or s3 bucket. You can then override the attributes in a cookbook, role, or environment: + +```ruby +default['java']['jdk_version'] = '8' +default['java']['install_flavor'] = 'oracle' +default['java']['jdk']['7']['x86_64']['url'] = 'http://artifactory.example.com/artifacts/jdk-7u65-linux-x64.tar.gz' +default['java']['jdk']['7']['x86_64']['checksum'] = 'The SHA-256 checksum of the JDK archive' +default['java']['oracle']['accept_oracle_download_terms'] = true +``` + +## Usage + +Include the `java` recipe wherever you would like Java installed, such as a run list (`recipe[java]`) or a cookbook (`include_recipe 'java'`). By default, OpenJDK 6 is installed. The `install_flavor` attribute is used to determine which JDK to install (AdoptOpenJDK, OpenJDK, Oracle, IBM, or Windows), and `jdk_version` specifies which version to install (currently 6 and 7 are supported for all JDK types, 8 and 10 for Oracle and AdoptOpenJDK ). + +### Examples + +To install Oracle Java 7 (note that when installing Oracle JDK, `accept_oracle_download_terms` attribute must be set -- see below role for an example): + +```ruby +name "java" +description "Install Oracle Java" +default_attributes( + "java" => { + "install_flavor" => "oracle", + "jdk_version" => "7", + "oracle" => { + "accept_oracle_download_terms" => true + } + } +) +run_list( + "recipe[java]" +) +``` + +Example role to install IBM flavored Java: + +```ruby +name "java" +description "Install IBM Java on Ubuntu" +default_attributes( + "java" => { + "install_flavor" => "ibm", + "ibm" => { + "accept_ibm_download_terms" => true, + "url" => "http://fileserver.example.com/ibm-java-x86_64-sdk-7.0-4.1.bin", + "checksum" => "The SHA256 checksum of the bin" + } + } +) +run_list( + "recipe[java]" +) +``` + +## Requirements + +Chef 13.4+ + +### Platforms + +- Debian, Ubuntu +- CentOS, RedHat, Fedora, Scientific, Amazon +- ArchLinux +- FreeBSD +- Windows +- macOS + +### Cookbooks + +- homebrew + +## Attributes + +See `attributes/default.rb` for default values. + +- `node['java']['download_path']` - Location to download and extract the tarball +- `node['java']['install_flavor']` - Flavor of JVM you would like installed (`oracle`, `oracle_rpm`, `openjdk`, `adoptopenjdk`, `ibm`, `windows`), default `openjdk` on Linux/Unix platforms, `windows` on Windows platforms. +- `node['java']['install_type']` - Type of Java installation, defauls to jdk, needed for JCE to find the install path of jar's for JDK/JRE installation. +- `node['java']['jdk_version']` - JDK version to install, defaults to `'6'`. +- `node['java']['java_home']` - Default location of the "`$JAVA_HOME`". To configure this attribute for `ibm`, `ibm_tar`, and `oracle_rpm` install flavors, you must use an attribute precedence of `force_default` or higher in your attribute file. +- `node['java']['set_etc_environment']` - Optionally sets JAVA_HOME in `/etc/environment` for Default `false`. +- `node['java']['openjdk_packages']` - Array of OpenJDK package names to install in the `java::openjdk` recipe. This is set based on the platform. +- `node['java']['jdk']` - Version and architecture specific attributes for setting the URL on Oracle's site for the JDK, and the checksum of the .tar.gz. +- `node['java']['oracle']['accept_oracle_download_terms']` - Indicates that you accept Oracle's EULA +- `node['java']['windows']['url']` - The internal location of your java install for windows +- `node['java']['windows']['package_name']` - The package name used by windows_package to check in the registry to determine if the install has already been run +- `node['java']['windows']['checksum']` - The checksum for the package to download on Windows machines (default is nil, which does not perform checksum validation) +- `node['java']['windows']['remove_obsolete']` - Indicates whether to remove previous versions of the JRE (default is `false`) +- `node['java']['windows']['aws_access_key_id']` - AWS Acess Key ID to use with AWS API calls +- `node['java']['windows']['aws_secret_access_key']` - AWS Secret Access Key to use with AWS API calls +- `node['java']['windows']['aws_session_token']` - AWS Session Token to use with AWS API calls +- `node['java']['windows']['returns']` - The allowed return codes for the package to + be installed on Windows machines (default is 0, you can define an array of valid values.) +- `node['java']['ibm']['url']` - The URL which to download the IBM JDK/SDK. See the `ibm` recipe section below. +- `node['java']['ibm']['accept_ibm_download_terms']` - Indicates that you accept IBM's EULA (for `java::ibm`) +- `node['java']['oracle_rpm']['type']` - Type of java RPM (`jre` or `jdk`), default `jdk` +- `node['java']['oracle_rpm']['package_version']` - optional, can be set to pin a version different from the up-to-date one available in the YUM repo, it might be needed to also override the node['java']['java_home'] attribute to a value consistent with the defined version +- `node['java']['oracle_rpm']['package_name']` - optional, can be set to define a package name different from the RPM published by Oracle. +- `node['java']['accept_license_agreement']` - Indicates that you accept the EULA for openjdk package installation. +- `node['java']['set_default']` - Indicates whether or not you want the JDK installed to be default on the system. Defaults to true. +- `node['java']['oracle']['jce']['enabled']` - Indicates if the JCE Unlimited Strength Jurisdiction Policy Files should be installed for oracle JDKs +- `node['java']['oracle']['jce']['home']` - Where the JCE policy files should be installed to +- `node['java']['oracle']['jce'][java_version]['checksum']` - Checksum of the JCE policy zip. Can be sha256 or md5 +- `node['java']['oracle']['jce'][java_version]['url']` - URL which to download the JCE policy zip +- `node['java']['adoptopenjdk']['variant']` - Install the Eclipse Openj9 (default), Eclipse OpenJ9 Large Heap or Hotspot version of AdoptOpenJDK + +## Recipes + +### default + +Include the default recipe in a run list or recipe to get `java`. By default the `openjdk` flavor of Java is installed, but this can be changed by using the `install_flavor` attribute. By default on Windows platform systems, the `install_flavor` is `windows` and on Mac OS X platform systems, the `install_flavor` is `homebrew`. + +OpenJDK is the default because of licensing changes made upstream by Oracle. See notes on the `oracle` recipe below. + +NOTE: In most cases, including just the default recipe will be sufficient. It's possible to include the install_type recipes directly, as long as the necessary attributes (such as java_home) are set. + +### set_attributes_from_version + +Sets default attributes based on the JDK version. This is included by `default.rb`. This logic must be in a recipe instead of attributes/default.rb. See [#95](https://github.com/agileorbit-cookbooks/java/pull/95) for details. + +### default_java_symlink + +Updates /usr/lib/jvm/default-java to point to JAVA_HOME. + +### openjdk + +This recipe installs the `openjdk` flavor of Java. It also uses the `alternatives` system on RHEL/Debian families to set the default Java. + +On platforms such as SmartOS that require the acceptance of a license agreement during package installation, set `node['java']['accept_license_agreement']` to true in order to indicate that you accept the license. + +### oracle + +This recipe installs the `oracle` flavor of Java. This recipe does not use distribution packages as Oracle changed the licensing terms with JDK 1.6u27 and prohibited the practice for both RHEL and Debian family platforms. + +You can not directly download the JDK from Oracle's website without using a special cookie. This cookbook uses that cookie to download the oracle recipe on your behalf, however the `java::oracle` recipe forces you to set either override the `node['java']['oracle']['accept_oracle_download_terms']` to true or set up a private repository accessible by HTTP. + +override the `accept_oracle_download_terms` in, e.g., `roles/base.rb` + +```ruby + default_attributes( + :java => { + :oracle => { + "accept_oracle_download_terms" => true + } + } + ) +``` + +For both RHEL and Debian families, this recipe pulls the binary distribution from the Oracle website, and installs it in the default `JAVA_HOME` for each distribution. For Debian, this is `/usr/lib/jvm/default-java`. For RHEL, this is `/usr/lib/jvm/java`. + +After putting the binaries in place, the `java::oracle` recipe updates `/usr/bin/java` to point to the installed JDK using the `update-alternatives` script. This is all handled in the `java_oracle_install` resource. + +### oracle_i386 + +This recipe installs the 32-bit Java virtual machine without setting it as the default. This can be useful if you have applications on the same machine that require different versions of the JVM. + +This recipe operates in a similar manner to `java::oracle`. + +### oracle_rpm + +This recipe installs the Oracle JRE or JDK provided by a custom YUM repositories. It also uses the `alternatives` system on RHEL families to set the default Java. + +While public YUM repos for Oracle Java 7 and prior are available, you need to download the RPMs manually for Java 8 and make your own internal repository. This must be done to use this recipe to install Oracle Java 8 via RPM. You will also likely need to set `node['java']['oracle_rpm']['package_name']` to `jdk1.8.0_40`, replacing `40` with the most current version in your local repo. + +### adoptopenjdk + +This recipe installs the `AdoptOpenJDK` flavor of Java from [https://adoptopenjdk.net/](https://adoptopenjdk.net/). It also uses the `alternatives` system on the RHEL/Debian families to set the default Java. + +### Amazon Corretto + +This recipe installs the `Amazon Corretto` flavor of OpenJDK from [https://aws.amazon.com/corretto/](https://aws.amazon.com/corretto/). It also uses the `alternatives` system on RHEL/Debian families to set the default Java. + +### windows + +Because as of 26 March 2012 you can no longer directly download the JDK msi from Oracle's website without using a special cookie. This recipe requires you to set `node['java']['oracle']['accept_oracle_download_terms']` to true or host it internally on your own http repo or s3 bucket. + +**IMPORTANT NOTE** + +If you use the `windows` recipe, you'll need to make sure you've uploaded the `aws` and `windows` cookbooks. As of version 1.18.0, this cookbook references them with `suggests` instead of `depends`, as they are only used by the `windows` recipe. + +### ibm + +The `java::ibm` recipe is used to install the IBM version of Java. Note that IBM requires you to create an account _and_ log in to download the binary installer for your platform. You must accept the license agreement with IBM to use their version of Java. In this cookbook, you indicate this by setting `node['java']['ibm']['accept_ibm_download_terms']` to `true`. You must also host the binary on your own HTTP server to have an automated installation. The `node['java']['ibm']['url']` attribute must be set to a valid https/http URL; the URL is checked for validity in the recipe. + +At this time the `java::ibm` recipe does not support multiple SDK installations. + +### notify + +The `java::notify` recipe contains a log resource whose `:write` action is called when a JDK version changes. This gives cookbook authors a way to subscribe to JDK changes and take actions (say restart a java service): + +```ruby +service 'somejavaservice' do + action :restart + subscribes :restart, 'log[jdk-version-changed]', :delayed +end +``` + +## Resources + +### java_oracle_install + +This cookbook contains the `java_oracle_install` resource which handles installation of Oracle's distribution of Java.. + +By default, the extracted directory is extracted to `app_root/extracted_dir_name` and symlinked to `app_root/default` + +#### Actions + +- `:install`: extracts the tarball and makes necessary symlinks +- `:remove`: removes the tarball and run update-alternatives for all symlinked `bin_cmds` + +#### Attribute Parameters + +- `url`: path to tarball, .tar.gz, .bin (oracle-specific), and .zip currently supported +- `checksum`: SHA256 checksum, not used for security but avoid redownloading the archive on each chef-client run +- `app_home`: the default for installations of this type of application, for example, `/usr/lib/tomcat/default`. If your application is not set to the default, it will be placed at the same level in the directory hierarchy but the directory name will be `app_root/extracted_directory_name + "_alt"` +- `app_home_mode`: file mode for app_home, is an integer +- `bin_cmds`: array of binary commands that should be symlinked to `/usr/bin`, examples are mvn, java, javac, etc. These cmds must be in the `bin` subdirectory of the extracted folder. Will be ignored if this `java_oracle_install` is not the default +- `owner`: owner of extracted directory, set to "root" by default +- `group`: group of extracted directory, set to `:owner` by default +- `default`: whether this the default installation of this package, boolean true or false +- `reset_alternatives`: whether alternatives is reset boolean true or false +- `use_alt_suffix`: whether `_alt` suffix is used for not default javas boolean true or false +- `proxy`: optional address and port of proxy server, for example, `proxy.example.com:1234` + +#### Examples + +```ruby +# install jdk6 from Oracle +java_oracle_install "jdk" do + url 'http://download.oracle.com/otn/java/jdk/6u29-b11/jdk-6u29-linux-x64.bin' + checksum 'a8603fa62045ce2164b26f7c04859cd548ffe0e33bfc979d9fa73df42e3b3365' + app_home '/usr/local/java/default' + bin_cmds ["java", "javac"] + action :install +end +``` + +### adoptopenjdk_install + +This cookbook contains the `adoptopenjdk_install` resource which handles the installation of AdopOpenJDK's distribution of Java. + +By default, the extracted directory is extracted to `app_root/extracted_dir_name` and symlinked to `app_root/default` + +#### Actions + +- `:install`: extracts the tarball and makes necessary symlinks +- `:remove`: removes the tarball and run update-alternatives for all symlinked `bin_cmds` + +#### Attribute Parameters + +- `url`: path to tarball, .tar.gz is currently supported +- `checksum`: SHA256 checksum, not used for security but avoid redownloading the archive on each chef-client run +- `app_home`: the default for installations of this type of application, for example, `/usr/lib/tomcat/default`. +- `app_home_mode`: file mode for app_home, is an integer +- `bin_cmds`: array of binary commands that should be symlinked to `/usr/bin`, examples are mvn, java, javac, etc. These cmds must be in the `bin` subdirectory of the extracted folder. Will be ignored if this `java_oracle_install` is not the default +- `owner`: owner of extracted directory, set to "root" by default +- `group`: group of extracted directory, set to `:owner` by default +- `default`: whether this the default installation of this package, boolean true or false +- `reset_alternatives`: whether alternatives is reset boolean true or false +- `variant`: One of `hotspot`, `openj9`, or `openj9-large-heap` + +#### Examples + +```ruby +# install Java 10 from AdoptOpenJDK +adoptopenjdk_install "jdk" do + url 'https://github.com/AdoptOpenJDK/openjdk10-openj9-releases/releases/download/jdk-10.0.2%2B13_openj9-0.9.0/OpenJDK10-OPENJ9_x64_Linux_jdk-10.0.2.13_openj9-0.9.0.tar.gz' + checksum '1ef0dab3853b2f3666091854ef8149fcb85970254558d5d62cfa9446831779d1' + app_home '/usr/local/java/default' + bin_cmds ["java", "javac"] + action :install +end +``` + +### java_alternatives + +The `java_alternatives` resource uses `update-alternatives` command to set and unset command alternatives for various Java tools such as java, javac, etc. + +#### Actions + +- `:set`: set alternatives for Java tools +- `:unset`: unset alternatives for Java tools + +#### Attribute Parameters + +- `java_location`: Java installation location. +- `bin_cmds`: array of Java tool names to set or unset alternatives on. +- `default`: whether to set the Java tools as system default. Boolean, defaults to `true`. +- `priority`: priority of the alternatives. Integer, defaults to `1061`. + +#### Examples + +```ruby +# set alternatives for java and javac commands +java_alternatives "set java alternatives" do + java_location '/usr/local/java' + bin_cmds ["java", "javac"] + action :set +end +``` + +### java_certificate + +This cookbook contains the `java_certificate` resource which simplifies adding certificates to a java keystore. It can also populate the keystore with a certificate retrieved from a given SSL end-point. It defaults to the default keystore `/jre/lib/security/cacerts` for Java 8 or below and `/lib/security/cacerts` for Java 9+ with the default password if a specific keystore is not provided. + +### Actions + +- `:install`: installs a certificate. +- `:remove`: removes a certificate. + +### Attribute Parameters + +- `cert_alias`: The alias of the certificate in the keystore. This defaults to the name of the resource. + +Optional parameters: + +- `java_home`: the java home directory. Defaults to `node['java']['java_home']`. + +- `keystore_path`: the keystore path. Defaults to `node['java']['java_home']/jre/lib/security/cacerts` for Java 8 or below and `node['java']['java_home']/lib/security/cacerts` for Java 9+. + +- `keystore_passwd`: the keystore password. Defaults to 'changeit' as specified by the Java Documentation. + +Only one of the following + +- `cert_data`: the certificate data to install +- `cert_file`: path to a certificate file to install +- `ssl_endpoint`: an SSL end-point from which to download the certificate + +### Examples + +```ruby +java_certificate "Install LDAP server certificate to Java CA keystore for Jenkins" do + cert_alias node['jenkins']['ldap']['url'][/\/\/(.*)/, 1] + ssl_endpoint node['jenkins']['ldap']['url'] + action :install + notifies :restart, "runit_service[jenkins]", :delayed +end +``` + +### java_jce + +This cookbook contains the `java_jce` resource, which installs the Java Cryptography Extension (JCE) policy files for a given Java installation. It defaults to installing the JCE files into the Java location defined by cookbook attributes, but it can be customized to install to arbitrary Java locations. Please note that if `node['java']['oracle']['jce']['enabled']` is set to true, this custom resource will be run automatically. + +### Actions + +- `:install`: Installs the JCE policy files. + +### Attribute Parameters + +No attributes are required by this resource. + +Optional parameters: + +- `jdk_version`: The Java version to install into. Defaults to `node['java']['jdk_version']`. +- `jce_url`: The URL for the JCE distribution. Defaults to `node['java']['oracle']['jce'][jdk_version]['url']`. +- `jce_checksum`: The checksum of the JCE distribution. Defaults to `node['java']['oracle']['jce'][jdk_version]['checksum']`. +- `jce_cookie`: Indicates that you accept Oracle's EULA. Defaults to the value of `node['java']['oracle']['accept_oracle_download_terms']`. +- `jce_home`: The location where JCE files will be decompressed for installation. Defaults to `node['java']['oracle']['jce']['home']`. +- `java_home`: The location of the Java installation.. Defaults to `node['java']['java_home']`. +- `principal`: For Windows installations only, this determines the owner of the JCE files. Defaults to `node['java']['windows']['owner']`. + +### Examples + +``` ruby +# Install the JCE for the default Java installation: +java_jce "Install the JCE files" do +end + +# Install the JCE for a Java installation in /opt/tools/jdk8: +java_jce "Install the JCE files" do + java_home "/opt/tools/jdk8" +end + +# Install the JCE for a Java 8 installation in /opt/tools/java using a custom download location: +java_jce "Install the JCE files" do + java_home "/opt/tools/java" + jdk_version "8" + jce_url "https://artifacts/path/to/jce/policy.zip" + jce_checksum "deadbeefcafe..." +end +``` + +## Recommendations for inclusion in community cookbooks + +This cookbook is a dependency for many other cookbooks in the Java/Chef sphere. Here are some guidelines for including it into other cookbooks: + +### Allow people to not use this cookbook + +Many users manage Java on their own or have systems that already have java installed. Give these users an option to skip this cookbook, for example: + +```ruby +include_recipe 'java' if node['maven']['install_java'] +``` + +This would allow a users of the maven cookbook to choose if they want the maven cookbook to install java for them or leave that up to the consumer. + +Another good example is from the [Jenkins Cookbook Java recipe](https://github.com/opscode-cookbooks/jenkins/commit/ca2a69d982011dc1bec6a6d0ee4da5c1a1599864). + +### Pinning to major version of cookbook and Java + +This cookbook follows semver. It is recommended to pin at the major version of this cookbook when including it in other cookbooks, eg: `depends 'java', '~> 1.0'` + +It is acceptable to set the `node['java']['jdk_version']` to a specific version if required for your software to run, eg software xyz requires Java 8 to run. Refrain from pinning to specific patches of the JDK to allow users to consume security updates. + +## Development + +This cookbook uses [test-kitchen](https://github.com/test-kitchen/test-kitchen) for integration tests and [ChefSpec/RSpec](https://github.com/sethvargo/chefspec) for unit tests. See [TESTING.md](https://github.com/agileorbit-cookbooks/java/blob/master/TESTING.md) for testing instructions. + +At this time due to licensing concerns, the IBM recipe is not set up in test kitchen. If you would like to test this locally, copy .kitchen.yml to .kitchen.local.yml and add the following suite: + +```yml +suites: +- name: ibm + run_list: ["recipe[java]"] + attributes: + java: + install_flavor: "ibm" + ibm: + accept_ibm_download_terms: true + url: "http://jenkins/ibm-java-x86_64-sdk-7.0-4.1.bin" + checksum: the-sha256-checksum +``` + +Log into the IBM DeveloperWorks site to download a copy of the IBM Java SDK you wish to use/test, host it on an internal HTTP server, and calculate the SHA256 checksum to use in the suite. + +## Contributors + +This project exists thanks to all the people who [contribute.](https://opencollective.com/sous-chefs/contributors.svg?width=890&button=false) + +### Backers + +Thank you to all our backers! + +![https://opencollective.com/sous-chefs#backers](https://opencollective.com/sous-chefs/backers.svg?width=600&avatarHeight=40) + +### Sponsors + +Support this project by becoming a sponsor. Your logo will show up here with a link to your website. + +![https://opencollective.com/sous-chefs/sponsor/0/website](https://opencollective.com/sous-chefs/sponsor/0/avatar.svg?avatarHeight=100) +![https://opencollective.com/sous-chefs/sponsor/1/website](https://opencollective.com/sous-chefs/sponsor/1/avatar.svg?avatarHeight=100) +![https://opencollective.com/sous-chefs/sponsor/2/website](https://opencollective.com/sous-chefs/sponsor/2/avatar.svg?avatarHeight=100) +![https://opencollective.com/sous-chefs/sponsor/3/website](https://opencollective.com/sous-chefs/sponsor/3/avatar.svg?avatarHeight=100) +![https://opencollective.com/sous-chefs/sponsor/4/website](https://opencollective.com/sous-chefs/sponsor/4/avatar.svg?avatarHeight=100) +![https://opencollective.com/sous-chefs/sponsor/5/website](https://opencollective.com/sous-chefs/sponsor/5/avatar.svg?avatarHeight=100) +![https://opencollective.com/sous-chefs/sponsor/6/website](https://opencollective.com/sous-chefs/sponsor/6/avatar.svg?avatarHeight=100) +![https://opencollective.com/sous-chefs/sponsor/7/website](https://opencollective.com/sous-chefs/sponsor/7/avatar.svg?avatarHeight=100) +![https://opencollective.com/sous-chefs/sponsor/8/website](https://opencollective.com/sous-chefs/sponsor/8/avatar.svg?avatarHeight=100) +![https://opencollective.com/sous-chefs/sponsor/9/website](https://opencollective.com/sous-chefs/sponsor/9/avatar.svg?avatarHeight=100) diff --git a/cookbooks/java/attributes/default.rb b/cookbooks/java/attributes/default.rb new file mode 100644 index 0000000..a1c7540 --- /dev/null +++ b/cookbooks/java/attributes/default.rb @@ -0,0 +1,185 @@ +# +# Author:: Seth Chisamore () +# Cookbook:: java +# Attributes:: default +# +# Copyright:: 2010-2015, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# default jdk attributes +default['java']['download_path'] = Chef::Config[:file_cache_path] +default['java']['jdk_version'] = '8' +default['java']['arch'] = node['kernel']['machine'] =~ /x86_64/ ? 'x86_64' : 'i586' +default['java']['openjdk_packages'] = [] +default['java']['openjdk_version'] = nil +default['java']['accept_license_agreement'] = false +default['java']['set_default'] = true +default['java']['alternatives_priority'] = 1062 +default['java']['set_etc_environment'] = false +default['java']['use_alt_suffix'] = true +default['java']['reset_alternatives'] = true + +# the following retry parameters apply when downloading oracle java +default['java']['ark_retries'] = 0 +default['java']['ark_retry_delay'] = 2 +default['java']['ark_timeout'] = 600 +default['java']['ark_download_timeout'] = 600 + +case node['platform_family'] +when 'windows' + default['java']['install_flavor'] = 'windows' + default['java']['windows']['url'] = nil + default['java']['windows']['checksum'] = nil + default['java']['windows']['package_name'] = 'Java(TM) SE Development Kit 7 (64-bit)' + default['java']['windows']['public_jre_home'] = nil + default['java']['windows']['owner'] = 'administrator' + default['java']['windows']['remove_obsolete'] = false + default['java']['windows']['returns'] = 0 +when 'mac_os_x' + default['java']['install_flavor'] = 'homebrew' +else + default['java']['install_flavor'] = 'openjdk' +end + +# type of Java installation, can be jdk or jre +default['java']['install_type'] = 'jdk' + +# S390(X) - IBM zSeries Architecture - only IBM jre / jdk can be used. Download from https://developer.ibm.com/javasdk/downloads/ +if node['kernel']['machine'].start_with?('s390') + default['java']['install_flavor'] = 'ibm' +end + +default['java']['ibm']['url'] = nil +default['java']['ibm']['checksum'] = nil +default['java']['ibm']['accept_ibm_download_terms'] = false + +default['java']['ibm']['6']['bin_cmds'] = %w(appletviewer apt ControlPanel extcheck HtmlConverter idlj jar jarsigner + java javac javadoc javah javap javaws jconsole jcontrol jdb jdmpview + jrunscript keytool native2ascii policytool rmic rmid rmiregistry + schemagen serialver tnameserv wsgen wsimport xjc) + +default['java']['ibm']['7']['bin_cmds'] = node['java']['ibm']['6']['bin_cmds'] + %w(pack200 unpack200) +default['java']['ibm']['8']['bin_cmds'] = node['java']['ibm']['7']['bin_cmds'] + +# type of java RPM : jdk or jre +default['java']['oracle_rpm']['type'] = 'jdk' + +# optional, can be overriden to pin to a version different +# from the up-to-date. +default['java']['oracle_rpm']['package_version'] = nil + +# optional, some distros re-package the official Oracle's RPM +# with a different name +default['java']['oracle_rpm']['package_name'] = nil + +# if you change this to true, you can download directly from Oracle +default['java']['oracle']['accept_oracle_download_terms'] = false + +# direct download paths for oracle, you have been warned! + +# jdk8 attributes + +default['java']['jdk']['8']['bin_cmds'] = %w(appletviewer apt ControlPanel extcheck idlj jar jarsigner java javac + javadoc javafxpackager javah javap javaws jcmd jconsole jcontrol jdb + jdeps jhat jinfo jjs jmap jmc jps jrunscript jsadebugd jstack + jstat jstatd jvisualvm keytool native2ascii orbd pack200 policytool + rmic rmid rmiregistry schemagen serialver servertool tnameserv + unpack200 wsgen wsimport xjc) + +# Official checksums for the latest release can be found at https://www.oracle.com/webfolder/s/digest/8u172checksum.html + +# x86_64 +default['java']['jdk']['8']['x86_64']['url'] = 'https://download.oracle.com/otn-pub/java/jdk/8u202-b08/1961070e4c9b4e26a04e7f5a083f551e/jdk-8u202-linux-x64.tar.gz' +default['java']['jdk']['8']['x86_64']['checksum'] = '9a5c32411a6a06e22b69c495b7975034409fa1652d03aeb8eb5b6f59fd4594e0' + +# i586 +default['java']['jdk']['8']['i586']['url'] = 'http://download.oracle.com/otn-pub/java/jdk/8u191-b12/2787e4a523244c269598db4e85c51e0c/jdk-8u191-linux-i586.tar.gz' +default['java']['jdk']['8']['i586']['checksum'] = '640333e749f24428b78c2b10422f7174f8fbd0b8acde27526c195024fad8b6b6' + +# x86_64 +default['java']['jdk']['10']['x86_64']['url'] = 'http://download.oracle.com/otn-pub/java/jdk/10.0.1+10/fb4372174a714e6b8c52526dc134031e/jdk-10.0.1_linux-x64_bin.tar.gz' +default['java']['jdk']['10']['x86_64']['checksum'] = 'ae8ed645e6af38432a56a847597ac61d4283b7536688dbab44ab536199d1e5a4' + +# i586 +default['java']['jdk']['10']['i586']['url'] = 'NOT YET AVAILABLE' +default['java']['jdk']['10']['i586']['checksum'] = 'NOT YET AVAILABLE' + +default['java']['jdk']['10']['bin_cmds'] = %w(appletviewer jar javac javapackager jconsole jdeprscan jimage jlink jmod + jshell jstatd orbd rmid serialver unpack200 xjc idlj jarsigner javadoc javaws + jcontrol jdeps jinfo jmap jps jstack jweblauncher pack200 rmiregistry servertool wsgen + jaotc java javap jcmd jdb jhsdb jjs jmc jrunscript jstat keytool rmic schemagen tnameserv + wsimport) + +# x86_64 +default['java']['jdk']['11']['x86_64']['url'] = 'http://download.oracle.com/otn-pub/java/jdk/11.0.1+13/90cf5d8f270a4347a95050320eef3fb7/jdk-11.0.1_linux-x64_bin.tar.gz' +default['java']['jdk']['11']['x86_64']['checksum'] = 'e7fd856bacad04b6dbf3606094b6a81fa9930d6dbb044bbd787be7ea93abc885' + +default['java']['jdk']['11']['bin_cmds'] = %w(jaotc jar jarsigner java javac javadoc javap jcmd jconsole jdb jdeprscan + jdeps jhsdb jimage jinfo jjs jlink jmap jmod jps jrunscript jshell jstack + jstat jstatd keytool pack200 rmic rmid rmiregistry serialver unpack200 + ) + +default['java']['oracle']['jce']['enabled'] = false +default['java']['oracle']['jce']['10']['url'] = 'https://edelivery.oracle.com/otn-pub/java/jce/8/jce_policy-8.zip' +default['java']['oracle']['jce']['10']['checksum'] = 'f3020a3922efd6626c2fff45695d527f34a8020e938a49292561f18ad1320b59' +default['java']['oracle']['jce']['8']['url'] = 'https://edelivery.oracle.com/otn-pub/java/jce/8/jce_policy-8.zip' +default['java']['oracle']['jce']['8']['checksum'] = 'f3020a3922efd6626c2fff45695d527f34a8020e938a49292561f18ad1320b59' +default['java']['oracle']['jce']['7']['url'] = 'http://ORACLE_HAS_REMOVED_THESE_FILES.SELF_HOST_THEM_INSTEAD' +default['java']['oracle']['jce']['7']['checksum'] = 'CALCULATE_THIS_FROM_YOUR_FILE' +default['java']['oracle']['jce']['6']['url'] = 'http://ORACLE_HAS_REMOVED_THESE_FILES.SELF_HOST_THEM_INSTEAD' +default['java']['oracle']['jce']['6']['checksum'] = 'CALCULATE_THIS_FROM_YOUR_FILE' +default['java']['oracle']['jce']['home'] = '/opt/java_jce' + +# AdoptOpenJDK +default['java']['adoptopenjdk']['variant'] = 'openj9' +# AdoptOpenJDK 8 +default['java']['adoptopenjdk']['8']['x86_64']['hotspot']['url'] = 'https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u181-b13/OpenJDK8U-jdk_x64_linux_hotspot_8u181b13.tar.gz' +default['java']['adoptopenjdk']['8']['x86_64']['hotspot']['checksum'] = '7cac51df1a976a376e9acd6d053c96ce0fe54db24e5d7079c303d09c416270a2' +default['java']['adoptopenjdk']['8']['x86_64']['openj9']['url'] = 'https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u192-b12/OpenJDK8U-jdk_x64_linux_openj9_8u192b12.tar.gz' +default['java']['adoptopenjdk']['8']['x86_64']['openj9']['checksum'] = '23f7f99c051b45366f0d91a94f8d5465f01bfccdc78f6d62222b1f338e6663eb' +default['java']['adoptopenjdk']['8']['bin_cmds']['default'] = %w(appletviewer extcheck idlj jar jarsigner java javac javadoc javah javap jconsole jdb jdeps jdmpview jextract jjs jrunscript jsadebugd keytool native2ascii orbd pack200 policytool rmic rmid rmiregistry schemagen serialver servertool tnameserv traceformat unpack200 wsgen wsimport xjc) +# AdoptOpenJDK 10 +default['java']['adoptopenjdk']['10']['x86_64']['hotspot']['url'] = 'https://github.com/AdoptOpenJDK/openjdk10-releases/releases/download/jdk-10.0.2%2B13/OpenJDK10_x64_Linux_jdk-10.0.2.13.tar.gz' +default['java']['adoptopenjdk']['10']['x86_64']['hotspot']['checksum'] = 'f8caa2e8c28370e3b8e455686e1ddeb74656f068848f8c355d9d8d1c225528f4' +default['java']['adoptopenjdk']['10']['x86_64']['openj9']['url'] = 'https://github.com/AdoptOpenJDK/openjdk10-openj9-releases/releases/download/jdk-10.0.2%2B13_openj9-0.9.0/OpenJDK10-OPENJ9_x64_Linux_jdk-10.0.2.13_openj9-0.9.0.tar.gz' +default['java']['adoptopenjdk']['10']['x86_64']['openj9']['checksum'] = '1ef0dab3853b2f3666091854ef8149fcb85970254558d5d62cfa9446831779d1' +default['java']['adoptopenjdk']['10']['bin_cmds']['default'] = %w(appletviewer idlj jar jarsigner java javac javadoc javap jconsole jdb jdeprscan jdeps jdmpview jextract jimage jinfo jjs jlink jmap jmod jps jrunscript jshell jstack jstat keytool orbd pack200 rmic rmid rmiregistry schemagen serialver servertool tnameserv traceformat unpack200 wsgen wsimport xjc) +default['java']['adoptopenjdk']['10']['bin_cmds']['hotspot'] = %w(appletviewer idlj jaotc jar jarsigner java javac javadoc javap jcmd jconsole jdb jdeprscan jdeps jhsdb jimage jinfo jjs jlink jmap jmod jps jrunscript jshell jstack jstat jstatd keytool orbd pack200 rmic rmid rmiregistry schemagen serialver servertool tnameserv unpack200 wsgen wsimport xjc) +# AdoptOpenJDK 11 +default['java']['adoptopenjdk']['11']['x86_64']['hotspot']['url'] = 'https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11%2B28/OpenJDK11-jdk_x64_linux_hotspot_11_28.tar.gz' +default['java']['adoptopenjdk']['11']['x86_64']['hotspot']['checksum'] = 'e1e18fc9ce2917473da3e0acb5a771bc651f600c0195a3cb40ef6f22f21660af' +default['java']['adoptopenjdk']['11']['x86_64']['openj9']['url'] = 'https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.1%2B13/OpenJDK11-jdk_x64_linux_openj9_11.0.1_13.tar.gz' +default['java']['adoptopenjdk']['11']['x86_64']['openj9']['checksum'] = '765947ab9457a29d2aa9d11460a4849611343c1e0ea3b33b9c08409cd4672251' +default['java']['adoptopenjdk']['11']['x86_64']['openj9-large-heap']['url'] = 'https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.1%2B13/OpenJDK11-jdk_x64_linux_openj9_linuxXL_11.0.1_13.tar.gz' +default['java']['adoptopenjdk']['11']['x86_64']['openj9-large-heap']['checksum'] = '0b6050cc670eefd9465370ab19ae70401476430fca329e65f0dd636ca9cce9bd' +default['java']['adoptopenjdk']['11']['bin_cmds']['default'] = %w(jar jarsigner java javac javadoc javap jconsole jdb jdeprscan jdeps jdmpview jextract jimage jjs jlink jrunscript jshell keytool pack200 rmic rmid rmiregistry serialver traceformat unpack200) +default['java']['adoptopenjdk']['11']['bin_cmds']['hotspot'] = %w(jaotc jar jarsigner java javac javadoc javap jcmd jconsole jdb jdeprscan jdeps jhsdb jimage jinfo jjs jlink jmap jmod jps jrunscript jshell jstack jstat jstatd keytool pack200 rmic rmid rmiregistry serialver unpack200) +# Placeholders for AdoptOpenJDK 12 when it gets released +default['java']['adoptopenjdk']['12']['x86_64']['hotspot']['url'] = nil +default['java']['adoptopenjdk']['12']['x86_64']['hotspot']['checksum'] = nil +default['java']['adoptopenjdk']['12']['x86_64']['openj9']['url'] = nil +default['java']['adoptopenjdk']['12']['x86_64']['openj9']['checksum'] = nil +default['java']['adoptopenjdk']['12']['x86_64']['openj9-large-heap']['url'] = nil +default['java']['adoptopenjdk']['12']['x86_64']['openj9-large-heap']['checksum'] = nil +# TODO: Update list when released +default['java']['adoptopenjdk']['12']['bin_cmds']['default'] = %w(jar jarsigner java javac javadoc javap jcmd jconsole jdb jdeprscan jdeps jhsdb jimage jinfo jjs jlink jmap jmod jps jrunscript jshell jstack jstat jstatd keytool pack200 rmic rmid rmiregistry serialver unpack200) + +# Amazon Corretto +default['java']['corretto']['8']['x86_64']['url'] = 'https://d3pxv6yz143wms.cloudfront.net/8.222.10.1/amazon-corretto-8.222.10.1-linux-x64.tar.gz' +default['java']['corretto']['8']['x86_64']['checksum'] = '6599a081ce56dda81ee7ac23802d6e67' +default['java']['corretto']['8']['bin_cmds'] = %w(appletviewer clhsdb extcheck hsdb idlj jar jarsigner java java-rmi.cgi javac javadoc javafxpackager javah javap javapackager jcmd jconsole jdb jdeps jhat jinfo jjs jmap jps jrunscript jsadebugd jstack jstat jstatd keytool native2ascii orbd pack200 policytool rmic rmid rmiregistry schemagen serialver servertool tnameserv unpack200 wsgen wsimport xjc) + +default['java']['corretto']['11']['x86_64']['url'] = 'https://d3pxv6yz143wms.cloudfront.net/11.0.4.11.1/amazon-corretto-11.0.4.11.1-linux-x64.tar.gz' +default['java']['corretto']['11']['x86_64']['checksum'] = '4bbcd5e6d721fef56e46b3bfa8631c1c' +default['java']['corretto']['11']['bin_cmds'] = %w(jaotc jar jarsigner java javac javadoc javap jcmd jconsole jdb jdeprscan jdeps jhsdb jimage jinfo jjs jlink jmap jmod jps jrunscript jshell jstack jstat jstatd keytool pack200 rmic rmid rmiregistry serialver unpack200) diff --git a/cookbooks/java/libraries/helpers.rb b/cookbooks/java/libraries/helpers.rb new file mode 100644 index 0000000..cd6b00d --- /dev/null +++ b/cookbooks/java/libraries/helpers.rb @@ -0,0 +1,88 @@ +# +# Author:: Joshua Timberman +# Copyright:: Copyright (c) 2013-2015, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'chef/version_constraint' +require 'uri' +require 'pathname' + +module ChefCookbook + class OpenJDK + attr_accessor :java_home, :jdk_version + + def initialize(node) + @node = node.to_hash + @java_home = @node['java']['java_home'] || '/usr/lib/jvm/default-java' + @jdk_version = @node['java']['jdk_version'].to_s || '6' + end + + def java_location + File.join(java_home_parent(@java_home), openjdk_path, 'bin/java') + end + + def java_home_parent(java_home) + Pathname.new(java_home).parent.to_s + end + + def openjdk_path + case @node['platform_family'] + when 'debian' + format('java-%s-openjdk%s/jre', @jdk_version, arch_dir) + when 'rhel', 'fedora', 'amazon' + path = @node['java']['jdk_version'].to_i < 11 ? 'jre-1.%s.0-openjdk%s' : 'java-%s' + format(path, @jdk_version, arch_dir) + else + 'jre' + end + end + + def arch_dir + @node['kernel']['machine'] == 'x86_64' ? sixty_four : thirty_two + end + + def sixty_four + case @node['platform_family'] + when 'debian' + '-amd64' + when 'rhel', 'fedora', 'amazon' + '.x86_64' + else + '-x86_64' + end + end + + def thirty_two + case @node['platform_family'] + when 'debian' + '-i386' + else + '' + end + end + end +end + +class Chef + class Recipe + def valid_ibm_jdk_uri?(url) + url =~ ::URI::ABS_URI && %w(file http https).include?(::URI.parse(url).scheme) + end + + def platform_requires_license_acceptance? + %w(smartos).include?(node['platform']) + end + end +end diff --git a/cookbooks/java/metadata.json b/cookbooks/java/metadata.json new file mode 100644 index 0000000..4f18608 --- /dev/null +++ b/cookbooks/java/metadata.json @@ -0,0 +1 @@ +{"name":"java","version":"4.3.0","description":"Recipes and resources for installing Java and managing certificates","long_description":"# java cookbook\n\n[![Cookbook Version](https://img.shields.io/cookbook/v/java.svg)](https://supermarket.chef.io/cookbooks/java)\n[![Build Status](https://img.shields.io/circleci/project/github/sous-chefs/java/master.svg)](https://circleci.com/gh/sous-chefs/java)\n[![OpenCollective](https://opencollective.com/sous-chefs/backers/badge.svg)](#backers)\n[![OpenCollective](https://opencollective.com/sous-chefs/sponsors/badge.svg)](#sponsors)\n[![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)](https://opensource.org/licenses/Apache-2.0)\n\nThis cookbook installs a Java JDK/JRE. It defaults to installing OpenJDK, but it can also install Oracle, IBM JDKs or AdoptOpenJDK.\n\n## Maintainers\n\nThis cookbook is maintained by the Sous Chefs. The Sous Chefs are a community of Chef cookbook maintainers working together to maintain important cookbooks. If you’d like to know more please visit [sous-chefs.org](https://sous-chefs.org/) or come chat with us on the Chef Community Slack in [#sous-chefs](https://chefcommunity.slack.com/messages/C2V7B88SF).\n\n## Production Deployment with Oracle Java\n\nOracle has been known to change the behavior of its download site frequently. It is recommended you store the archives on an artifact server or s3 bucket. You can then override the attributes in a cookbook, role, or environment:\n\n```ruby\ndefault['java']['jdk_version'] = '8'\ndefault['java']['install_flavor'] = 'oracle'\ndefault['java']['jdk']['7']['x86_64']['url'] = 'http://artifactory.example.com/artifacts/jdk-7u65-linux-x64.tar.gz'\ndefault['java']['jdk']['7']['x86_64']['checksum'] = 'The SHA-256 checksum of the JDK archive'\ndefault['java']['oracle']['accept_oracle_download_terms'] = true\n```\n\n## Usage\n\nInclude the `java` recipe wherever you would like Java installed, such as a run list (`recipe[java]`) or a cookbook (`include_recipe 'java'`). By default, OpenJDK 6 is installed. The `install_flavor` attribute is used to determine which JDK to install (AdoptOpenJDK, OpenJDK, Oracle, IBM, or Windows), and `jdk_version` specifies which version to install (currently 6 and 7 are supported for all JDK types, 8 and 10 for Oracle and AdoptOpenJDK ).\n\n### Examples\n\nTo install Oracle Java 7 (note that when installing Oracle JDK, `accept_oracle_download_terms` attribute must be set -- see below role for an example):\n\n```ruby\nname \"java\"\ndescription \"Install Oracle Java\"\ndefault_attributes(\n \"java\" => {\n \"install_flavor\" => \"oracle\",\n \"jdk_version\" => \"7\",\n \"oracle\" => {\n \"accept_oracle_download_terms\" => true\n }\n }\n)\nrun_list(\n \"recipe[java]\"\n)\n```\n\nExample role to install IBM flavored Java:\n\n```ruby\nname \"java\"\ndescription \"Install IBM Java on Ubuntu\"\ndefault_attributes(\n \"java\" => {\n \"install_flavor\" => \"ibm\",\n \"ibm\" => {\n \"accept_ibm_download_terms\" => true,\n \"url\" => \"http://fileserver.example.com/ibm-java-x86_64-sdk-7.0-4.1.bin\",\n \"checksum\" => \"The SHA256 checksum of the bin\"\n }\n }\n)\nrun_list(\n \"recipe[java]\"\n)\n```\n\n## Requirements\n\nChef 13.4+\n\n### Platforms\n\n- Debian, Ubuntu\n- CentOS, RedHat, Fedora, Scientific, Amazon\n- ArchLinux\n- FreeBSD\n- Windows\n- macOS\n\n### Cookbooks\n\n- homebrew\n\n## Attributes\n\nSee `attributes/default.rb` for default values.\n\n- `node['java']['download_path']` - Location to download and extract the tarball\n- `node['java']['install_flavor']` - Flavor of JVM you would like installed (`oracle`, `oracle_rpm`, `openjdk`, `adoptopenjdk`, `ibm`, `windows`), default `openjdk` on Linux/Unix platforms, `windows` on Windows platforms.\n- `node['java']['install_type']` - Type of Java installation, defauls to jdk, needed for JCE to find the install path of jar's for JDK/JRE installation.\n- `node['java']['jdk_version']` - JDK version to install, defaults to `'6'`.\n- `node['java']['java_home']` - Default location of the \"`$JAVA_HOME`\". To configure this attribute for `ibm`, `ibm_tar`, and `oracle_rpm` install flavors, you must use an attribute precedence of `force_default` or higher in your attribute file.\n- `node['java']['set_etc_environment']` - Optionally sets JAVA_HOME in `/etc/environment` for Default `false`.\n- `node['java']['openjdk_packages']` - Array of OpenJDK package names to install in the `java::openjdk` recipe. This is set based on the platform.\n- `node['java']['jdk']` - Version and architecture specific attributes for setting the URL on Oracle's site for the JDK, and the checksum of the .tar.gz.\n- `node['java']['oracle']['accept_oracle_download_terms']` - Indicates that you accept Oracle's EULA\n- `node['java']['windows']['url']` - The internal location of your java install for windows\n- `node['java']['windows']['package_name']` - The package name used by windows_package to check in the registry to determine if the install has already been run\n- `node['java']['windows']['checksum']` - The checksum for the package to download on Windows machines (default is nil, which does not perform checksum validation)\n- `node['java']['windows']['remove_obsolete']` - Indicates whether to remove previous versions of the JRE (default is `false`)\n- `node['java']['windows']['aws_access_key_id']` - AWS Acess Key ID to use with AWS API calls\n- `node['java']['windows']['aws_secret_access_key']` - AWS Secret Access Key to use with AWS API calls\n- `node['java']['windows']['aws_session_token']` - AWS Session Token to use with AWS API calls\n- `node['java']['windows']['returns']` - The allowed return codes for the package to\n be installed on Windows machines (default is 0, you can define an array of valid values.)\n- `node['java']['ibm']['url']` - The URL which to download the IBM JDK/SDK. See the `ibm` recipe section below.\n- `node['java']['ibm']['accept_ibm_download_terms']` - Indicates that you accept IBM's EULA (for `java::ibm`)\n- `node['java']['oracle_rpm']['type']` - Type of java RPM (`jre` or `jdk`), default `jdk`\n- `node['java']['oracle_rpm']['package_version']` - optional, can be set to pin a version different from the up-to-date one available in the YUM repo, it might be needed to also override the node['java']['java_home'] attribute to a value consistent with the defined version\n- `node['java']['oracle_rpm']['package_name']` - optional, can be set to define a package name different from the RPM published by Oracle.\n- `node['java']['accept_license_agreement']` - Indicates that you accept the EULA for openjdk package installation.\n- `node['java']['set_default']` - Indicates whether or not you want the JDK installed to be default on the system. Defaults to true.\n- `node['java']['oracle']['jce']['enabled']` - Indicates if the JCE Unlimited Strength Jurisdiction Policy Files should be installed for oracle JDKs\n- `node['java']['oracle']['jce']['home']` - Where the JCE policy files should be installed to\n- `node['java']['oracle']['jce'][java_version]['checksum']` - Checksum of the JCE policy zip. Can be sha256 or md5\n- `node['java']['oracle']['jce'][java_version]['url']` - URL which to download the JCE policy zip\n- `node['java']['adoptopenjdk']['variant']` - Install the Eclipse Openj9 (default), Eclipse OpenJ9 Large Heap or Hotspot version of AdoptOpenJDK\n\n## Recipes\n\n### default\n\nInclude the default recipe in a run list or recipe to get `java`. By default the `openjdk` flavor of Java is installed, but this can be changed by using the `install_flavor` attribute. By default on Windows platform systems, the `install_flavor` is `windows` and on Mac OS X platform systems, the `install_flavor` is `homebrew`.\n\nOpenJDK is the default because of licensing changes made upstream by Oracle. See notes on the `oracle` recipe below.\n\nNOTE: In most cases, including just the default recipe will be sufficient. It's possible to include the install_type recipes directly, as long as the necessary attributes (such as java_home) are set.\n\n### set_attributes_from_version\n\nSets default attributes based on the JDK version. This is included by `default.rb`. This logic must be in a recipe instead of attributes/default.rb. See [#95](https://github.com/agileorbit-cookbooks/java/pull/95) for details.\n\n### default_java_symlink\n\nUpdates /usr/lib/jvm/default-java to point to JAVA_HOME.\n\n### openjdk\n\nThis recipe installs the `openjdk` flavor of Java. It also uses the `alternatives` system on RHEL/Debian families to set the default Java.\n\nOn platforms such as SmartOS that require the acceptance of a license agreement during package installation, set `node['java']['accept_license_agreement']` to true in order to indicate that you accept the license.\n\n### oracle\n\nThis recipe installs the `oracle` flavor of Java. This recipe does not use distribution packages as Oracle changed the licensing terms with JDK 1.6u27 and prohibited the practice for both RHEL and Debian family platforms.\n\nYou can not directly download the JDK from Oracle's website without using a special cookie. This cookbook uses that cookie to download the oracle recipe on your behalf, however the `java::oracle` recipe forces you to set either override the `node['java']['oracle']['accept_oracle_download_terms']` to true or set up a private repository accessible by HTTP.\n\noverride the `accept_oracle_download_terms` in, e.g., `roles/base.rb`\n\n```ruby\n default_attributes(\n :java => {\n :oracle => {\n \"accept_oracle_download_terms\" => true\n }\n }\n )\n```\n\nFor both RHEL and Debian families, this recipe pulls the binary distribution from the Oracle website, and installs it in the default `JAVA_HOME` for each distribution. For Debian, this is `/usr/lib/jvm/default-java`. For RHEL, this is `/usr/lib/jvm/java`.\n\nAfter putting the binaries in place, the `java::oracle` recipe updates `/usr/bin/java` to point to the installed JDK using the `update-alternatives` script. This is all handled in the `java_oracle_install` resource.\n\n### oracle_i386\n\nThis recipe installs the 32-bit Java virtual machine without setting it as the default. This can be useful if you have applications on the same machine that require different versions of the JVM.\n\nThis recipe operates in a similar manner to `java::oracle`.\n\n### oracle_rpm\n\nThis recipe installs the Oracle JRE or JDK provided by a custom YUM repositories. It also uses the `alternatives` system on RHEL families to set the default Java.\n\nWhile public YUM repos for Oracle Java 7 and prior are available, you need to download the RPMs manually for Java 8 and make your own internal repository. This must be done to use this recipe to install Oracle Java 8 via RPM. You will also likely need to set `node['java']['oracle_rpm']['package_name']` to `jdk1.8.0_40`, replacing `40` with the most current version in your local repo.\n\n### adoptopenjdk\n\nThis recipe installs the `AdoptOpenJDK` flavor of Java from [https://adoptopenjdk.net/](https://adoptopenjdk.net/). It also uses the `alternatives` system on the RHEL/Debian families to set the default Java.\n\n### Amazon Corretto\n\nThis recipe installs the `Amazon Corretto` flavor of OpenJDK from [https://aws.amazon.com/corretto/](https://aws.amazon.com/corretto/). It also uses the `alternatives` system on RHEL/Debian families to set the default Java.\n\n### windows\n\nBecause as of 26 March 2012 you can no longer directly download the JDK msi from Oracle's website without using a special cookie. This recipe requires you to set `node['java']['oracle']['accept_oracle_download_terms']` to true or host it internally on your own http repo or s3 bucket.\n\n**IMPORTANT NOTE**\n\nIf you use the `windows` recipe, you'll need to make sure you've uploaded the `aws` and `windows` cookbooks. As of version 1.18.0, this cookbook references them with `suggests` instead of `depends`, as they are only used by the `windows` recipe.\n\n### ibm\n\nThe `java::ibm` recipe is used to install the IBM version of Java. Note that IBM requires you to create an account _and_ log in to download the binary installer for your platform. You must accept the license agreement with IBM to use their version of Java. In this cookbook, you indicate this by setting `node['java']['ibm']['accept_ibm_download_terms']` to `true`. You must also host the binary on your own HTTP server to have an automated installation. The `node['java']['ibm']['url']` attribute must be set to a valid https/http URL; the URL is checked for validity in the recipe.\n\nAt this time the `java::ibm` recipe does not support multiple SDK installations.\n\n### notify\n\nThe `java::notify` recipe contains a log resource whose `:write` action is called when a JDK version changes. This gives cookbook authors a way to subscribe to JDK changes and take actions (say restart a java service):\n\n```ruby\nservice 'somejavaservice' do\n action :restart\n subscribes :restart, 'log[jdk-version-changed]', :delayed\nend\n```\n\n## Resources\n\n### java_oracle_install\n\nThis cookbook contains the `java_oracle_install` resource which handles installation of Oracle's distribution of Java..\n\nBy default, the extracted directory is extracted to `app_root/extracted_dir_name` and symlinked to `app_root/default`\n\n#### Actions\n\n- `:install`: extracts the tarball and makes necessary symlinks\n- `:remove`: removes the tarball and run update-alternatives for all symlinked `bin_cmds`\n\n#### Attribute Parameters\n\n- `url`: path to tarball, .tar.gz, .bin (oracle-specific), and .zip currently supported\n- `checksum`: SHA256 checksum, not used for security but avoid redownloading the archive on each chef-client run\n- `app_home`: the default for installations of this type of application, for example, `/usr/lib/tomcat/default`. If your application is not set to the default, it will be placed at the same level in the directory hierarchy but the directory name will be `app_root/extracted_directory_name + \"_alt\"`\n- `app_home_mode`: file mode for app_home, is an integer\n- `bin_cmds`: array of binary commands that should be symlinked to `/usr/bin`, examples are mvn, java, javac, etc. These cmds must be in the `bin` subdirectory of the extracted folder. Will be ignored if this `java_oracle_install` is not the default\n- `owner`: owner of extracted directory, set to \"root\" by default\n- `group`: group of extracted directory, set to `:owner` by default\n- `default`: whether this the default installation of this package, boolean true or false\n- `reset_alternatives`: whether alternatives is reset boolean true or false\n- `use_alt_suffix`: whether `_alt` suffix is used for not default javas boolean true or false\n- `proxy`: optional address and port of proxy server, for example, `proxy.example.com:1234`\n\n#### Examples\n\n```ruby\n# install jdk6 from Oracle\njava_oracle_install \"jdk\" do\n url 'http://download.oracle.com/otn/java/jdk/6u29-b11/jdk-6u29-linux-x64.bin'\n checksum 'a8603fa62045ce2164b26f7c04859cd548ffe0e33bfc979d9fa73df42e3b3365'\n app_home '/usr/local/java/default'\n bin_cmds [\"java\", \"javac\"]\n action :install\nend\n```\n\n### adoptopenjdk_install\n\nThis cookbook contains the `adoptopenjdk_install` resource which handles the installation of AdopOpenJDK's distribution of Java.\n\nBy default, the extracted directory is extracted to `app_root/extracted_dir_name` and symlinked to `app_root/default`\n\n#### Actions\n\n- `:install`: extracts the tarball and makes necessary symlinks\n- `:remove`: removes the tarball and run update-alternatives for all symlinked `bin_cmds`\n\n#### Attribute Parameters\n\n- `url`: path to tarball, .tar.gz is currently supported\n- `checksum`: SHA256 checksum, not used for security but avoid redownloading the archive on each chef-client run\n- `app_home`: the default for installations of this type of application, for example, `/usr/lib/tomcat/default`.\n- `app_home_mode`: file mode for app_home, is an integer\n- `bin_cmds`: array of binary commands that should be symlinked to `/usr/bin`, examples are mvn, java, javac, etc. These cmds must be in the `bin` subdirectory of the extracted folder. Will be ignored if this `java_oracle_install` is not the default\n- `owner`: owner of extracted directory, set to \"root\" by default\n- `group`: group of extracted directory, set to `:owner` by default\n- `default`: whether this the default installation of this package, boolean true or false\n- `reset_alternatives`: whether alternatives is reset boolean true or false\n- `variant`: One of `hotspot`, `openj9`, or `openj9-large-heap`\n\n#### Examples\n\n```ruby\n# install Java 10 from AdoptOpenJDK\nadoptopenjdk_install \"jdk\" do\n url 'https://github.com/AdoptOpenJDK/openjdk10-openj9-releases/releases/download/jdk-10.0.2%2B13_openj9-0.9.0/OpenJDK10-OPENJ9_x64_Linux_jdk-10.0.2.13_openj9-0.9.0.tar.gz'\n checksum '1ef0dab3853b2f3666091854ef8149fcb85970254558d5d62cfa9446831779d1'\n app_home '/usr/local/java/default'\n bin_cmds [\"java\", \"javac\"]\n action :install\nend\n```\n\n### java_alternatives\n\nThe `java_alternatives` resource uses `update-alternatives` command to set and unset command alternatives for various Java tools such as java, javac, etc.\n\n#### Actions\n\n- `:set`: set alternatives for Java tools\n- `:unset`: unset alternatives for Java tools\n\n#### Attribute Parameters\n\n- `java_location`: Java installation location.\n- `bin_cmds`: array of Java tool names to set or unset alternatives on.\n- `default`: whether to set the Java tools as system default. Boolean, defaults to `true`.\n- `priority`: priority of the alternatives. Integer, defaults to `1061`.\n\n#### Examples\n\n```ruby\n# set alternatives for java and javac commands\njava_alternatives \"set java alternatives\" do\n java_location '/usr/local/java'\n bin_cmds [\"java\", \"javac\"]\n action :set\nend\n```\n\n### java_certificate\n\nThis cookbook contains the `java_certificate` resource which simplifies adding certificates to a java keystore. It can also populate the keystore with a certificate retrieved from a given SSL end-point. It defaults to the default keystore `/jre/lib/security/cacerts` for Java 8 or below and `/lib/security/cacerts` for Java 9+ with the default password if a specific keystore is not provided.\n\n### Actions\n\n- `:install`: installs a certificate.\n- `:remove`: removes a certificate.\n\n### Attribute Parameters\n\n- `cert_alias`: The alias of the certificate in the keystore. This defaults to the name of the resource.\n\nOptional parameters:\n\n- `java_home`: the java home directory. Defaults to `node['java']['java_home']`.\n\n- `keystore_path`: the keystore path. Defaults to `node['java']['java_home']/jre/lib/security/cacerts` for Java 8 or below and `node['java']['java_home']/lib/security/cacerts` for Java 9+.\n\n- `keystore_passwd`: the keystore password. Defaults to 'changeit' as specified by the Java Documentation.\n\nOnly one of the following\n\n- `cert_data`: the certificate data to install\n- `cert_file`: path to a certificate file to install\n- `ssl_endpoint`: an SSL end-point from which to download the certificate\n\n### Examples\n\n```ruby\njava_certificate \"Install LDAP server certificate to Java CA keystore for Jenkins\" do\n cert_alias node['jenkins']['ldap']['url'][/\\/\\/(.*)/, 1]\n ssl_endpoint node['jenkins']['ldap']['url']\n action :install\n notifies :restart, \"runit_service[jenkins]\", :delayed\nend\n```\n\n### java_jce\n\nThis cookbook contains the `java_jce` resource, which installs the Java Cryptography Extension (JCE) policy files for a given Java installation. It defaults to installing the JCE files into the Java location defined by cookbook attributes, but it can be customized to install to arbitrary Java locations. Please note that if `node['java']['oracle']['jce']['enabled']` is set to true, this custom resource will be run automatically.\n\n### Actions\n\n- `:install`: Installs the JCE policy files.\n\n### Attribute Parameters\n\nNo attributes are required by this resource.\n\nOptional parameters:\n\n- `jdk_version`: The Java version to install into. Defaults to `node['java']['jdk_version']`.\n- `jce_url`: The URL for the JCE distribution. Defaults to `node['java']['oracle']['jce'][jdk_version]['url']`.\n- `jce_checksum`: The checksum of the JCE distribution. Defaults to `node['java']['oracle']['jce'][jdk_version]['checksum']`.\n- `jce_cookie`: Indicates that you accept Oracle's EULA. Defaults to the value of `node['java']['oracle']['accept_oracle_download_terms']`.\n- `jce_home`: The location where JCE files will be decompressed for installation. Defaults to `node['java']['oracle']['jce']['home']`.\n- `java_home`: The location of the Java installation.. Defaults to `node['java']['java_home']`.\n- `principal`: For Windows installations only, this determines the owner of the JCE files. Defaults to `node['java']['windows']['owner']`.\n\n### Examples\n\n``` ruby\n# Install the JCE for the default Java installation:\njava_jce \"Install the JCE files\" do\nend\n\n# Install the JCE for a Java installation in /opt/tools/jdk8:\njava_jce \"Install the JCE files\" do\n java_home \"/opt/tools/jdk8\"\nend\n\n# Install the JCE for a Java 8 installation in /opt/tools/java using a custom download location:\njava_jce \"Install the JCE files\" do\n java_home \"/opt/tools/java\"\n jdk_version \"8\"\n jce_url \"https://artifacts/path/to/jce/policy.zip\"\n jce_checksum \"deadbeefcafe...\"\nend\n```\n\n## Recommendations for inclusion in community cookbooks\n\nThis cookbook is a dependency for many other cookbooks in the Java/Chef sphere. Here are some guidelines for including it into other cookbooks:\n\n### Allow people to not use this cookbook\n\nMany users manage Java on their own or have systems that already have java installed. Give these users an option to skip this cookbook, for example:\n\n```ruby\ninclude_recipe 'java' if node['maven']['install_java']\n```\n\nThis would allow a users of the maven cookbook to choose if they want the maven cookbook to install java for them or leave that up to the consumer.\n\nAnother good example is from the [Jenkins Cookbook Java recipe](https://github.com/opscode-cookbooks/jenkins/commit/ca2a69d982011dc1bec6a6d0ee4da5c1a1599864).\n\n### Pinning to major version of cookbook and Java\n\nThis cookbook follows semver. It is recommended to pin at the major version of this cookbook when including it in other cookbooks, eg: `depends 'java', '~> 1.0'`\n\nIt is acceptable to set the `node['java']['jdk_version']` to a specific version if required for your software to run, eg software xyz requires Java 8 to run. Refrain from pinning to specific patches of the JDK to allow users to consume security updates.\n\n## Development\n\nThis cookbook uses [test-kitchen](https://github.com/test-kitchen/test-kitchen) for integration tests and [ChefSpec/RSpec](https://github.com/sethvargo/chefspec) for unit tests. See [TESTING.md](https://github.com/agileorbit-cookbooks/java/blob/master/TESTING.md) for testing instructions.\n\nAt this time due to licensing concerns, the IBM recipe is not set up in test kitchen. If you would like to test this locally, copy .kitchen.yml to .kitchen.local.yml and add the following suite:\n\n```yml\nsuites:\n- name: ibm\n run_list: [\"recipe[java]\"]\n attributes:\n java:\n install_flavor: \"ibm\"\n ibm:\n accept_ibm_download_terms: true\n url: \"http://jenkins/ibm-java-x86_64-sdk-7.0-4.1.bin\"\n checksum: the-sha256-checksum\n```\n\nLog into the IBM DeveloperWorks site to download a copy of the IBM Java SDK you wish to use/test, host it on an internal HTTP server, and calculate the SHA256 checksum to use in the suite.\n\n## Contributors\n\nThis project exists thanks to all the people who [contribute.](https://opencollective.com/sous-chefs/contributors.svg?width=890&button=false)\n\n### Backers\n\nThank you to all our backers!\n\n![https://opencollective.com/sous-chefs#backers](https://opencollective.com/sous-chefs/backers.svg?width=600&avatarHeight=40)\n\n### Sponsors\n\nSupport this project by becoming a sponsor. Your logo will show up here with a link to your website.\n\n![https://opencollective.com/sous-chefs/sponsor/0/website](https://opencollective.com/sous-chefs/sponsor/0/avatar.svg?avatarHeight=100)\n![https://opencollective.com/sous-chefs/sponsor/1/website](https://opencollective.com/sous-chefs/sponsor/1/avatar.svg?avatarHeight=100)\n![https://opencollective.com/sous-chefs/sponsor/2/website](https://opencollective.com/sous-chefs/sponsor/2/avatar.svg?avatarHeight=100)\n![https://opencollective.com/sous-chefs/sponsor/3/website](https://opencollective.com/sous-chefs/sponsor/3/avatar.svg?avatarHeight=100)\n![https://opencollective.com/sous-chefs/sponsor/4/website](https://opencollective.com/sous-chefs/sponsor/4/avatar.svg?avatarHeight=100)\n![https://opencollective.com/sous-chefs/sponsor/5/website](https://opencollective.com/sous-chefs/sponsor/5/avatar.svg?avatarHeight=100)\n![https://opencollective.com/sous-chefs/sponsor/6/website](https://opencollective.com/sous-chefs/sponsor/6/avatar.svg?avatarHeight=100)\n![https://opencollective.com/sous-chefs/sponsor/7/website](https://opencollective.com/sous-chefs/sponsor/7/avatar.svg?avatarHeight=100)\n![https://opencollective.com/sous-chefs/sponsor/8/website](https://opencollective.com/sous-chefs/sponsor/8/avatar.svg?avatarHeight=100)\n![https://opencollective.com/sous-chefs/sponsor/9/website](https://opencollective.com/sous-chefs/sponsor/9/avatar.svg?avatarHeight=100)\n","maintainer":"Sous Chefs","maintainer_email":"help@sous-chefs.org","license":"Apache-2.0","platforms":{"debian":">= 0.0.0","ubuntu":">= 0.0.0","centos":">= 0.0.0","redhat":">= 0.0.0","scientific":">= 0.0.0","fedora":">= 0.0.0","amazon":">= 0.0.0","oracle":">= 0.0.0","freebsd":">= 0.0.0","windows":">= 0.0.0","suse":">= 0.0.0","opensuseleap":">= 0.0.0","mac_os_x":">= 0.0.0"},"dependencies":{"homebrew":">= 0.0.0","windows":">= 0.0.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/sous-chefs/java","issues_url":"https://github.com/sous-chefs/java/issues","chef_version":[[">= 13.4"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/java/metadata.rb b/cookbooks/java/metadata.rb new file mode 100644 index 0000000..867cbcf --- /dev/null +++ b/cookbooks/java/metadata.rb @@ -0,0 +1,28 @@ +name 'java' +maintainer 'Sous Chefs' +maintainer_email 'help@sous-chefs.org' +license 'Apache-2.0' +description 'Recipes and resources for installing Java and managing certificates' +long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) +version '4.3.0' + +supports 'debian' +supports 'ubuntu' +supports 'centos' +supports 'redhat' +supports 'scientific' +supports 'fedora' +supports 'amazon' +supports 'oracle' +supports 'freebsd' +supports 'windows' +supports 'suse' +supports 'opensuseleap' +supports 'mac_os_x' + +depends 'homebrew' +depends 'windows' + +source_url 'https://github.com/sous-chefs/java' +issues_url 'https://github.com/sous-chefs/java/issues' +chef_version '>= 13.4' diff --git a/cookbooks/java/recipes/adoptopenjdk.rb b/cookbooks/java/recipes/adoptopenjdk.rb new file mode 100644 index 0000000..b83d6dd --- /dev/null +++ b/cookbooks/java/recipes/adoptopenjdk.rb @@ -0,0 +1,46 @@ +# Cookbook:: java +# Recipe:: adoptopenjdk + +include_recipe 'java::notify' + +unless node.recipe?('java::default') + Chef::Log.warn('Using java::default instead is recommended.') + + # Even if this recipe is included by itself, a safety check is nice... + if node['java']['java_home'].nil? || node['java']['java_home'].empty? + include_recipe 'java::set_attributes_from_version' + end +end + +include_recipe 'java::set_java_home' + +java_home = node['java']['java_home'] +arch = node['java']['arch'] +version = node['java']['jdk_version'].to_s +variant = node['java']['adoptopenjdk']['variant'] +tarball_url = node['java']['adoptopenjdk'][version][arch][variant]['url'] +tarball_checksum = node['java']['adoptopenjdk'][version][arch][variant]['checksum'] +bin_cmds = if node['java']['adoptopenjdk'][version]['bin_cmds'].key?(variant) + node['java']['adoptopenjdk'][version]['bin_cmds'][variant] + else + node['java']['adoptopenjdk'][version]['bin_cmds']['default'] + end + +adoptopenjdk_install 'adoptopenjdk' do + url tarball_url + default node['java']['set_default'] + checksum tarball_checksum + app_home java_home + bin_cmds bin_cmds + alternatives_priority node['java']['alternatives_priority'] + retries node['java']['ark_retries'] + retry_delay node['java']['ark_retry_delay'] + reset_alternatives node['java']['reset_alternatives'] + variant variant + action :install + notifies :write, 'log[jdk-version-changed]', :immediately +end + +if node['java']['set_default'] && platform_family?('debian') + include_recipe 'java::default_java_symlink' +end diff --git a/cookbooks/java/recipes/corretto.rb b/cookbooks/java/recipes/corretto.rb new file mode 100644 index 0000000..8c98691 --- /dev/null +++ b/cookbooks/java/recipes/corretto.rb @@ -0,0 +1,46 @@ +# Cookbook:: java +# Recipe:: corretto +# This recipe installs and configures Amazon's Corretto package +# https://aws.amazon.com/corretto/ + +include_recipe 'java::notify' + +unless node.recipe?('java::default') + Chef::Log.warn('Using java::default instead is recommended.') + + # Even if this recipe is included by itself, a safety check is nice... + if node['java']['java_home'].nil? || node['java']['java_home'].empty? + include_recipe 'java::set_attributes_from_version' + end +end + +java_home = node['java']['java_home'] +arch = node['java']['arch'] +version = node['java']['jdk_version'].to_s +tarball_url = node['java']['corretto'][version][arch]['url'] +tarball_checksum = node['java']['corretto'][version][arch]['checksum'] +bin_cmds = node['java']['corretto'][version]['bin_cmds'] + +include_recipe 'java::set_java_home' + +java_oracle_install 'jdk' do + url tarball_url + default node['java']['set_default'] + md5 tarball_checksum + app_home java_home + bin_cmds bin_cmds + alternatives_priority node['java']['alternatives_priority'] + retries node['java']['ark_retries'] + retry_delay node['java']['ark_retry_delay'] + connect_timeout node['java']['ark_timeout'] + use_alt_suffix node['java']['use_alt_suffix'] + reset_alternatives node['java']['reset_alternatives'] + download_timeout node['java']['ark_download_timeout'] + proxy node['java']['ark_proxy'] + action :install + notifies :write, 'log[jdk-version-changed]', :immediately +end + +if node['java']['set_default'] && platform_family?('debian') + include_recipe 'java::default_java_symlink' +end diff --git a/cookbooks/java/recipes/default.rb b/cookbooks/java/recipes/default.rb new file mode 100644 index 0000000..e907e08 --- /dev/null +++ b/cookbooks/java/recipes/default.rb @@ -0,0 +1,22 @@ +# +# Author:: Seth Chisamore () +# Cookbook:: java +# Recipe:: default +# +# Copyright:: 2008-2015, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'java::set_attributes_from_version' +include_recipe "java::#{node['java']['install_flavor']}" diff --git a/cookbooks/java/recipes/default_java_symlink.rb b/cookbooks/java/recipes/default_java_symlink.rb new file mode 100644 index 0000000..f935e80 --- /dev/null +++ b/cookbooks/java/recipes/default_java_symlink.rb @@ -0,0 +1,19 @@ +# Cookbook:: java +# Recipe:: default_java_symlink +# +# 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. + +link '/usr/lib/jvm/default-java' do + to node['java']['java_home'] + not_if { node['java']['java_home'] == '/usr/lib/jvm/default-java' } +end diff --git a/cookbooks/java/recipes/homebrew.rb b/cookbooks/java/recipes/homebrew.rb new file mode 100644 index 0000000..6b761df --- /dev/null +++ b/cookbooks/java/recipes/homebrew.rb @@ -0,0 +1,8 @@ +include_recipe 'homebrew' +include_recipe 'homebrew::cask' +include_recipe 'java::notify' + +homebrew_tap 'caskroom/versions' +homebrew_cask "java#{node['java']['jdk_version']}" do + notifies :write, 'log[jdk-version-changed]', :immediately +end diff --git a/cookbooks/java/recipes/ibm.rb b/cookbooks/java/recipes/ibm.rb new file mode 100644 index 0000000..cb3de21 --- /dev/null +++ b/cookbooks/java/recipes/ibm.rb @@ -0,0 +1,83 @@ +# Author:: Joshua Timberman () +# Cookbook:: java +# Recipe:: ibm +# +# Copyright:: 2013-2015, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require 'uri' + +include_recipe 'java::notify' + +# If you need to override this in an attribute file you must use +# force_default or higher precedence. +node.default['java']['java_home'] = '/opt/ibm/java' + +source_url = node['java']['ibm']['url'] +jdk_uri = ::URI.parse(source_url) +jdk_filename = ::File.basename(jdk_uri.path) + +unless valid_ibm_jdk_uri?(source_url) + raise "You must set the attribute `node['java']['ibm']['url']` to a valid HTTP URI" +end + +# "installable package" installer needs rpm on Ubuntu +package 'rpm' do + action :install + only_if { platform_family?('debian') && jdk_filename !~ /archive/ } +end + +template "#{node['java']['download_path']}/installer.properties" do + source 'ibm_jdk.installer.properties.erb' + only_if { node['java']['ibm']['accept_ibm_download_terms'] } +end + +remote_file "#{node['java']['download_path']}/#{jdk_filename}" do + source source_url + mode '0755' + if node['java']['ibm']['checksum'] + checksum node['java']['ibm']['checksum'] + action :create + else + action :create_if_missing + end + notifies :run, 'execute[install-ibm-java]', :immediately +end + +java_alternatives 'set-java-alternatives' do + java_location node['java']['java_home'] + default node['java']['set_default'] + case node['java']['jdk_version'].to_s + when '6' + bin_cmds node['java']['ibm']['6']['bin_cmds'] + when '7' + bin_cmds node['java']['ibm']['7']['bin_cmds'] + when '8' + bin_cmds node['java']['ibm']['8']['bin_cmds'] + end + action :nothing +end + +execute 'install-ibm-java' do + cwd node['java']['download_path'] + environment('_JAVA_OPTIONS' => '-Dlax.debug.level=3 -Dlax.debug.all=true', + 'LAX_DEBUG' => '1') + command "./#{jdk_filename} -f ./installer.properties -i silent" + creates "#{node['java']['java_home']}/jre/bin/java" + + notifies :set, 'java_alternatives[set-java-alternatives]', :immediately + notifies :write, 'log[jdk-version-changed]', :immediately +end + +include_recipe 'java::set_java_home' diff --git a/cookbooks/java/recipes/ibm_tar.rb b/cookbooks/java/recipes/ibm_tar.rb new file mode 100644 index 0000000..fe1bf19 --- /dev/null +++ b/cookbooks/java/recipes/ibm_tar.rb @@ -0,0 +1,79 @@ +# Cookbook:: java +# Recipe:: ibm_tar +# +# Copyright:: 2013-2015, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require 'uri' + +include_recipe 'java::notify' + +# If you need to override this in an attribute file you must use +# force_default or higher precedence. +node.default['java']['java_home'] = '/opt/ibm/java' + +source_url = node['java']['ibm']['url'] +jdk_uri = ::URI.parse(source_url) +jdk_filename = ::File.basename(jdk_uri.path) + +unless valid_ibm_jdk_uri?(source_url) + raise "You must set the attribute `node['java']['ibm']['url']` to a valid URI" +end + +unless jdk_filename =~ /\.(tar.gz|tgz)$/ + raise "The attribute `node['java']['ibm']['url']` must specify a .tar.gz file" +end + +remote_file "#{node['java']['download_path']}/#{jdk_filename}" do + source source_url + mode '0755' + if node['java']['ibm']['checksum'] + checksum node['java']['ibm']['checksum'] + action :create + else + action :create_if_missing + end + notifies :create, 'directory[create-java-home]', :immediately + notifies :run, 'execute[untar-ibm-java]', :immediately +end + +directory 'create-java-home' do + path node['java']['java_home'] + mode '0755' + recursive true +end + +java_alternatives 'set-java-alternatives' do + java_location node['java']['java_home'] + default node['java']['set_default'] + case node['java']['jdk_version'].to_s + when '6' + bin_cmds node['java']['ibm']['6']['bin_cmds'] + when '7' + bin_cmds node['java']['ibm']['7']['bin_cmds'] + when '8' + bin_cmds node['java']['ibm']['8']['bin_cmds'] + end + action :nothing +end + +execute 'untar-ibm-java' do + cwd node['java']['download_path'] + command "tar xzf ./#{jdk_filename} -C #{node['java']['java_home']} --strip 1" + notifies :set, 'java_alternatives[set-java-alternatives]', :immediately + notifies :write, 'log[jdk-version-changed]', :immediately + creates "#{node['java']['java_home']}/jre/bin/java" +end + +include_recipe 'java::set_java_home' diff --git a/cookbooks/java/recipes/notify.rb b/cookbooks/java/recipes/notify.rb new file mode 100644 index 0000000..4ca23c2 --- /dev/null +++ b/cookbooks/java/recipes/notify.rb @@ -0,0 +1,33 @@ +# +# Author:: Eric Helgeson () +# Cookbook:: java +# Recipe:: notify +# +# Copyright:: 2008-2015, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This resource is avalible for other recipes to subscribe to so they can be +# notified of a JDK change. For example you want to restart a service to take +# advantage of the new JDK +# eg: +# service 'somejavaservice' +# action :restart +# subscribes :write, 'log[jdk-version-changed]', :delayed +# end +log 'jdk-version-changed' do + message 'A new version of java was installed' + level :info + action :nothing +end diff --git a/cookbooks/java/recipes/openjdk.rb b/cookbooks/java/recipes/openjdk.rb new file mode 100644 index 0000000..517c802 --- /dev/null +++ b/cookbooks/java/recipes/openjdk.rb @@ -0,0 +1,72 @@ +# Author:: Bryan W. Berry () +# Author:: Seth Chisamore () +# Author:: Joshua Timberman () +# +# Cookbook:: java +# Recipe:: openjdk +# +# Copyright:: 2010-2015, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include_recipe 'java::notify' + +unless node.recipe?('java::default') + Chef::Log.warn('Using java::default instead is recommended.') + + # Even if this recipe is included by itself, a safety check is nice... + [node['java']['openjdk_packages'], node['java']['java_home']].each do |v| + include_recipe 'java::set_attributes_from_version' if v.nil? || v.empty? + end +end + +jdk = ChefCookbook::OpenJDK.new(node) + +if platform_requires_license_acceptance? + file '/opt/local/.dlj_license_accepted' do + owner 'root' + group 'root' + mode '0400' + action :create + only_if { node['java']['accept_license_agreement'] } + end +end + +if node['platform'] == 'ubuntu' + apt_repository 'openjdk-r-ppa' do + uri 'ppa:openjdk-r' + distribution node['lsb']['codename'] + end +end + +package node['java']['openjdk_packages'] do + version node['java']['openjdk_version'] if node['java']['openjdk_version'] + notifies :write, 'log[jdk-version-changed]', :immediately +end + +java_alternatives 'set-java-alternatives' do + java_location jdk.java_home + default node['java']['set_default'] + priority 1100 + bin_cmds node['java']['jdk'][node['java']['jdk_version'].to_s]['bin_cmds'] + action :set + only_if { platform_family?('debian', 'rhel', 'fedora', 'amazon') } +end + +if node['java']['set_default'] && platform_family?('debian') + include_recipe 'java::default_java_symlink' +end + +# We must include this recipe AFTER updating the alternatives or else JAVA_HOME +# will not point to the correct java. +include_recipe 'java::set_java_home' diff --git a/cookbooks/java/recipes/oracle.rb b/cookbooks/java/recipes/oracle.rb new file mode 100644 index 0000000..e43e94b --- /dev/null +++ b/cookbooks/java/recipes/oracle.rb @@ -0,0 +1,62 @@ +# +# Author:: Bryan W. Berry () +# Cookbook:: java +# Recipe:: oracle +# +# Copyright:: 2011, Bryan w. Berry +# +# 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. + +include_recipe 'java::notify' + +unless node.recipe?('java::default') + Chef::Log.warn('Using java::default instead is recommended.') + + # Even if this recipe is included by itself, a safety check is nice... + if node['java']['java_home'].nil? || node['java']['java_home'].empty? + include_recipe 'java::set_attributes_from_version' + end +end + +java_home = node['java']['java_home'] +arch = node['java']['arch'] +version = node['java']['jdk_version'].to_s +tarball_url = node['java']['jdk'][version][arch]['url'] +tarball_checksum = node['java']['jdk'][version][arch]['checksum'] +bin_cmds = node['java']['jdk'][version]['bin_cmds'] + +include_recipe 'java::set_java_home' + +java_oracle_install 'jdk' do + url tarball_url + default node['java']['set_default'] + checksum tarball_checksum + app_home java_home + bin_cmds bin_cmds + alternatives_priority node['java']['alternatives_priority'] + retries node['java']['ark_retries'] + retry_delay node['java']['ark_retry_delay'] + connect_timeout node['java']['ark_timeout'] + use_alt_suffix node['java']['use_alt_suffix'] + reset_alternatives node['java']['reset_alternatives'] + download_timeout node['java']['ark_download_timeout'] + proxy node['java']['ark_proxy'] + action :install + notifies :write, 'log[jdk-version-changed]', :immediately +end + +if node['java']['set_default'] && platform_family?('debian') + include_recipe 'java::default_java_symlink' +end + +include_recipe 'java::oracle_jce' if node['java']['oracle']['jce']['enabled'] diff --git a/cookbooks/java/recipes/oracle_i386.rb b/cookbooks/java/recipes/oracle_i386.rb new file mode 100644 index 0000000..32dad22 --- /dev/null +++ b/cookbooks/java/recipes/oracle_i386.rb @@ -0,0 +1,74 @@ +# +# Author:: Bryan W. Berry () +# Cookbook:: java +# Recipe:: oracle_i386 +# +# Copyright:: 2010-2015, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include_recipe 'java::notify' + +unless node.recipe?('java::default') + Chef::Log.warn('Using java::default instead is recommended.') + + # Even if this recipe is included by itself, a safety check is nice... + if node['java']['java_home'].nil? || node['java']['java_home'].empty? + include_recipe 'java::set_attributes_from_version' + end +end + +java_home = node['java']['java_home'] + +case node['java']['jdk_version'].to_s +when '6' + tarball_url = node['java']['jdk']['6']['i586']['url'] + tarball_checksum = node['java']['jdk']['6']['i586']['checksum'] + bin_cmds = node['java']['jdk']['6']['bin_cmds'] +when '7' + tarball_url = node['java']['jdk']['7']['i586']['url'] + tarball_checksum = node['java']['jdk']['7']['i586']['checksum'] + bin_cmds = node['java']['jdk']['7']['bin_cmds'] +when '8' + tarball_url = node['java']['jdk']['8']['i586']['url'] + tarball_checksum = node['java']['jdk']['8']['i586']['checksum'] + bin_cmds = node['java']['jdk']['8']['bin_cmds'] +end + +include_recipe 'java::set_java_home' + +yum_package 'glibc' do + arch 'i686' + only_if { platform_family?('rhel', 'fedora', 'amazon') } +end + +java_oracle_install 'jdk-alt' do + url tarball_url + default node['java']['set_default'] + checksum tarball_checksum + app_home java_home + bin_cmds bin_cmds + retries node['java']['ark_retries'] + retry_delay node['java']['ark_retries'] + use_alt_suffix node['java']['use_alt_suffix'] + reset_alternatives node['java']['reset_alternatives'] + action :install + default false + notifies :write, 'log[jdk-version-changed]', :immediately +end + +if node['java']['set_default'] && platform_family?('debian') + include_recipe 'java::default_java_symlink' +end + +include_recipe 'java::oracle_jce' if node['java']['oracle']['jce']['enabled'] diff --git a/cookbooks/java/recipes/oracle_jce.rb b/cookbooks/java/recipes/oracle_jce.rb new file mode 100644 index 0000000..eb5d367 --- /dev/null +++ b/cookbooks/java/recipes/oracle_jce.rb @@ -0,0 +1,21 @@ +# +# Author:: Kyle McGovern () +# Cookbook:: java +# Recipe:: oracle_jce +# +# Copyright:: 2014, Kyle McGovern +# +# 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. + +jdk_version = node['java']['jdk_version'].to_s +java_jce "Install JCE for JDK #{jdk_version}" diff --git a/cookbooks/java/recipes/oracle_rpm.rb b/cookbooks/java/recipes/oracle_rpm.rb new file mode 100644 index 0000000..5920a31 --- /dev/null +++ b/cookbooks/java/recipes/oracle_rpm.rb @@ -0,0 +1,61 @@ +# Author:: Christophe Arguel () +# +# Cookbook:: java +# Recipe:: oracle_rpm +# +# Copyright:: 2013, Christophe Arguel +# +# 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. + +# If you need to override this in an attribute file you must use +# force_default or higher precedence. +node.default['java']['java_home'] = '/usr/java/latest' + +include_recipe 'java::set_java_home' +include_recipe 'java::notify' + +slave_cmds = case node['java']['oracle_rpm']['type'] + when 'jdk' + %w(appletviewer apt ControlPanel extcheck idlj jar jarsigner javac javadoc javafxpackager javah javap java-rmi.cgi javaws jcmd jconsole jcontrol jdb jhat jinfo jmap jps jrunscript jsadebugd jstack jstat jstatd jvisualvm keytool native2ascii orbd pack200 policytool rmic rmid rmiregistry schemagen serialver servertool tnameserv unpack200 wsgen wsimport xjc) + + when 'jre' + %w(ControlPanel java_vm javaws jcontrol keytool orbd pack200 policytool rmid rmiregistry servertool tnameserv unpack200) + + else + Chef::Application.fatal!("Unsupported oracle RPM type (#{node['java']['oracle_rpm']['type']})") + end + +bash 'update-java-alternatives' do + java_home = node['java']['java_home'] + java_location = File.join(java_home, 'bin', 'java') + slave_lines = slave_cmds.inject('') do |slaves, cmd| + slaves << "--slave /usr/bin/#{cmd} #{cmd} #{File.join(java_home, 'bin', cmd)} \\\n" + end + + code <<-EOH.gsub(/^\s+/, '') + update-alternatives --install /usr/bin/java java #{java_location} #{node['java']['alternatives_priority']} \ + #{slave_lines} && \ + update-alternatives --set java #{java_location} + EOH + action :nothing +end + +package_name = node['java']['oracle_rpm']['package_name'] || node['java']['oracle_rpm']['type'] +package package_name do + action :install + version node['java']['oracle_rpm']['package_version'] if node['java']['oracle_rpm']['package_version'] + notifies :run, 'bash[update-java-alternatives]', :immediately if platform_family?('rhel', 'fedora', 'amazon') && node['java']['set_default'] + notifies :write, 'log[jdk-version-changed]', :immediately +end + +include_recipe 'java::oracle_jce' if node['java']['oracle']['jce']['enabled'] diff --git a/cookbooks/java/recipes/set_attributes_from_version.rb b/cookbooks/java/recipes/set_attributes_from_version.rb new file mode 100644 index 0000000..f7c9a82 --- /dev/null +++ b/cookbooks/java/recipes/set_attributes_from_version.rb @@ -0,0 +1,76 @@ +# Cookbook:: java +# Recipe:: set_attributes_from_version +# +# 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. + +# Calculate variables that depend on jdk_version +# If you need to override this in an attribute file you must use +# force_default or higher precedence. + +case node['platform_family'] +when 'rhel', 'fedora', 'amazon' + node.default['java']['java_home'] = case node['java']['install_flavor'] + when 'adoptopenjdk' + "/usr/lib/jvm/java-#{node['java']['jdk_version'].to_i}-#{node['java']['install_flavor']}-#{node['java']['adoptopenjdk']['variant']}" + when 'oracle' + '/usr/lib/jvm/java' + when 'oracle_rpm' + '/usr/java/latest' + else + node['java']['jdk_version'].to_i < 11 ? "/usr/lib/jvm/java-1.#{node['java']['jdk_version']}.0" : "/usr/lib/jvm/java-#{node['java']['jdk_version']}" + end + node.default['java']['openjdk_packages'] = node['java']['jdk_version'].to_i < 11 ? ["java-1.#{node['java']['jdk_version']}.0-openjdk", "java-1.#{node['java']['jdk_version']}.0-openjdk-devel"] : ["java-#{node['java']['jdk_version']}-openjdk", "java-#{node['java']['jdk_version']}-openjdk-devel"] +when 'suse' + node.default['java']['java_home'] = case node['java']['install_flavor'] + when 'adoptopenjdk' + "/usr/lib/jvm/java-#{node['java']['jdk_version'].to_i}-#{node['java']['install_flavor']}-#{node['java']['adoptopenjdk']['variant']}" + when 'oracle' + '/usr/lib/jvm/java' + when 'oracle_rpm' + '/usr/java/latest' + else + "/usr/lib#{node['kernel']['machine'] == 'x86_64' ? '64' : nil}/jvm/java-1.#{node['java']['jdk_version']}.0" + end + node.default['java']['openjdk_packages'] = ["java-1_#{node['java']['jdk_version']}_0-openjdk", "java-1_#{node['java']['jdk_version']}_0-openjdk-devel"] +when 'freebsd' + node.default['java']['java_home'] = "/usr/local/openjdk#{node['java']['jdk_version']}" + jdk_version = node['java']['jdk_version'] + openjdk_package = jdk_version == '7' ? 'openjdk' : "openjdk#{node['java']['jdk_version']}" + node.default['java']['openjdk_packages'] = [openjdk_package] +when 'arch' + node.default['java']['java_home'] = "/usr/lib/jvm/java-#{node['java']['jdk_version']}-openjdk" + node.default['java']['openjdk_packages'] = ["openjdk#{node['java']['jdk_version']}"] +when 'debian' + node.default['java']['java_home'] = case node['java']['install_flavor'] + when 'adoptopenjdk' + "/usr/lib/jvm/java-#{node['java']['jdk_version'].to_i}-#{node['java']['install_flavor']}-#{node['java']['adoptopenjdk']['variant']}" + else + "/usr/lib/jvm/java-#{node['java']['jdk_version']}-#{node['java']['install_flavor']}-#{node['kernel']['machine'] == 'x86_64' ? 'amd64' : 'i386'}" + end + node.default['java']['openjdk_packages'] = ["openjdk-#{node['java']['jdk_version']}-jdk", "openjdk-#{node['java']['jdk_version']}-jre-headless"] +when 'smartos' + node.default['java']['java_home'] = '/opt/local/java/sun6' + node.default['java']['openjdk_packages'] = ["sun-jdk#{node['java']['jdk_version']}", "sun-jre#{node['java']['jdk_version']}"] +when 'windows' + node.default['java']['java_home'] = nil +when 'mac_os_x' + java_home = if node['java']['jdk_version'].to_i >= 10 + "$(/usr/libexec/java_home -v #{node['java']['jdk_version']})" + else + "$(/usr/libexec/java_home -v 1.#{node['java']['jdk_version']})" + end + node.default['java']['java_home'] = java_home +else + node.default['java']['java_home'] = '/usr/lib/jvm/default-java' + node.default['java']['openjdk_packages'] = ["openjdk-#{node['java']['jdk_version']}-jdk"] +end diff --git a/cookbooks/java/recipes/set_java_home.rb b/cookbooks/java/recipes/set_java_home.rb new file mode 100644 index 0000000..33a3212 --- /dev/null +++ b/cookbooks/java/recipes/set_java_home.rb @@ -0,0 +1,37 @@ +# Author:: Joshua Timberman () +# Cookbook:: java +# Recipe:: set_java_home +# +# Copyright:: 2013-2015, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +directory '/etc/profile.d' do + mode '0755' +end + +template '/etc/profile.d/jdk.sh' do + source 'jdk.sh.erb' + mode '0755' +end + +if node['java']['set_etc_environment'] + ruby_block 'Set JAVA_HOME in /etc/environment' do + block do + file = Chef::Util::FileEdit.new('/etc/environment') + file.insert_line_if_no_match(/^JAVA_HOME=/, "JAVA_HOME=#{node['java']['java_home']}") + file.search_file_replace_line(/^JAVA_HOME=/, "JAVA_HOME=#{node['java']['java_home']}") + file.write_file + end + end +end diff --git a/cookbooks/java/recipes/windows.rb b/cookbooks/java/recipes/windows.rb new file mode 100644 index 0000000..f472967 --- /dev/null +++ b/cookbooks/java/recipes/windows.rb @@ -0,0 +1,109 @@ +# +# Author:: Kendrick Martin () +# Cookbook:: java +# Recipe:: windows +# +# Copyright:: 2008-2012 Webtrends, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'uri' + +include_recipe 'java::notify' + +Chef::Log.fatal('No download url set for java installer.') unless node['java'] && node['java']['windows'] && node['java']['windows']['url'] + +pkg_checksum = node['java']['windows']['checksum'] +aws_access_key_id = node['java']['windows']['aws_access_key_id'] +aws_secret_access_key = node['java']['windows']['aws_secret_access_key'] +aws_session_token = node['java']['windows']['aws_session_token'] + +s3_bucket = node['java']['windows']['bucket'] +s3_remote_path = node['java']['windows']['remote_path'] + +uri = ::URI.parse(node['java']['windows']['url']) +cache_file_path = File.join(node['java']['download_path'], File.basename(::URI.unescape(uri.path))) + +if s3_bucket && s3_remote_path + aws_s3_file cache_file_path do + aws_access_key_id aws_access_key_id + aws_secret_access_key aws_secret_access_key + aws_session_token aws_session_token + checksum pkg_checksum if pkg_checksum + bucket s3_bucket + remote_path s3_remote_path + backup false + action :create + end +else + ruby_block 'Enable Accessing cookies' do + block do + cookie_jar = Chef::HTTP::CookieJar + + cookie_jar.instance["#{uri.host}:#{uri.port}"] = 'oraclelicense=accept-securebackup-cookie' + end + + only_if { node['java']['oracle']['accept_oracle_download_terms'] } + end + + remote_file cache_file_path do + checksum pkg_checksum if pkg_checksum + source node['java']['windows']['url'] + backup false + action :create + end +end + +if node['java'].attribute?('java_home') && !node['java']['java_home'].nil? + java_home_win = win_friendly_path(node['java']['java_home']) + additional_options = if node['java']['jdk_version'].to_s == '8' + # Seems that the jdk 8 EXE installer does not need anymore the /v /qn flags + "INSTALLDIR=\"#{java_home_win}\"" + else + # The jdk 7 EXE installer expects escaped quotes, so we need to double escape + # them here. The final string looks like : + # /v"/qn INSTALLDIR=\"C:\Program Files\Java\"" + "/v\"/qn INSTALLDIR=\\\"#{java_home_win}\\\"\"" + end + + env 'JAVA_HOME' do + value java_home_win + end + + # update path + windows_path "#{java_home_win}\\bin" do + action :add + end +end + +if node['java']['windows'].attribute?('public_jre_home') && node['java']['windows']['public_jre_home'] + java_publicjre_home_win = win_friendly_path(node['java']['windows']['public_jre_home']) + additional_options = "#{additional_options} /INSTALLDIRPUBJRE=\"#{java_publicjre_home_win}\"" +end + +if node['java']['windows'].attribute?('remove_obsolete') && node['java']['windows']['remove_obsolete'] + additional_options = "#{additional_options} REMOVEOUTOFDATEJRES=1" +end + +windows_package node['java']['windows']['package_name'] do + source cache_file_path + checksum node['java']['windows']['checksum'] + action :install + returns node['java']['windows']['returns'] + installer_type :custom + options "/s #{additional_options}" + notifies :write, 'log[jdk-version-changed]', :immediately +end + +include_recipe 'java::oracle_jce' if node['java']['oracle']['jce']['enabled'] diff --git a/cookbooks/java/resources/adoptopenjdk_install.rb b/cookbooks/java/resources/adoptopenjdk_install.rb new file mode 100644 index 0000000..402ff8c --- /dev/null +++ b/cookbooks/java/resources/adoptopenjdk_install.rb @@ -0,0 +1,202 @@ +# +# Cookbook:: java +# Resource:: adoptopenjdk_install +# +# Based on oracle_install.rb by Bryan W. Berry () +# + +resource_name :adoptopenjdk_install + +default_action :install + +property :url, String +property :checksum, String, regex: /^[0-9a-f]{32}$|^[a-zA-Z0-9]{40,64}$/ +property :md5, String, regex: /^[0-9a-f]{32}$|^[a-zA-Z0-9]{40,64}$/ +property :app_home, String +property :app_home_mode, Integer, default: 0755 +property :bin_cmds, Array, default: [] +property :owner, String, default: 'root' +property :group, String, default: lazy { node['root_group'] } +property :default, [true, false], default: true +property :alternatives_priority, Integer, default: 1 +property :reset_alternatives, [true, false], default: true +property :variant, ['hotspot', 'openj9', 'openj9-large-heap'], default: 'openj9' + +action :install do + raise 'No URL provided to download AdoptOpenJDK\'s tar file!' if new_resource.url.nil? || new_resource.url.empty? + app_dir_name, tarball_name, app_root, app_dir = + parse_dir_names(new_resource.url, + new_resource.app_home, + new_resource.variant) + app_group = new_resource.group + app_home = new_resource.app_home + Chef::Log.debug("processing #{new_resource.variant} variant") + + directory app_root do + owner new_resource.owner + group app_group + mode new_resource.app_home_mode + recursive true + action :nothing + end.run_action(:create) + + unless ::File.exist?(app_dir) + download_path = "#{node['java']['download_path']}/#{tarball_name}" + if adoptopendjk_downloaded?(download_path, new_resource) + Chef::Log.debug('AdoptOpenJDK tarball already downloaded, not downloading again') + else + Chef::Log.debug("downloading tarball from #{URI.parse(new_resource.url).host}") + remote_file "#{node['java']['download_path']}/#{tarball_name}" do + source new_resource.url + checksum new_resource.checksum + retries new_resource.retries + retry_delay new_resource.retry_delay + mode 0o644 + action :nothing + end.run_action(:create_if_missing) + end + + converge_by("extract compressed data into Chef file cache path and move extracted data to #{app_dir}") do + package 'tar' do + not_if { platform_family?('mac_os_x', 'windows') } + action :nothing + end.run_action(:install) + + cmd = shell_out(%(tar xvzf "#{node['java']['download_path']}/#{tarball_name}" -C "#{node['java']['download_path']}" --no-same-owner) + ) + unless cmd.exitstatus == 0 + Chef::Application.fatal!("Failed to extract file #{tarball_name}!") + end + + cmd = shell_out( + %(mv "#{node['java']['download_path']}/#{app_dir_name}" "#{app_dir}" ) + ) + unless cmd.exitstatus == 0 + Chef::Application.fatal!(%( Command \' mv "#{node['java']['download_path']}/#{app_dir_name}" "#{app_dir}" \' failed )) + end + + # change ownership of extracted files + FileUtils.chown_R new_resource.owner, app_group, app_dir + end + end + + # set up .jinfo file for update-java-alternatives + java_name, jinfo_file = alternatives_config_file(app_root, app_home) + if platform_family?('debian') && !::File.exist?(jinfo_file) + converge_by("Add #{jinfo_file} for debian") do + template jinfo_file do + cookbook 'java' + source 'adoptopenjdk.jinfo.erb' + owner new_resource.owner + group app_group + variables( + priority: new_resource.alternatives_priority, + bin_cmds: new_resource.bin_cmds, + name: java_name, + app_dir: app_home + ) + action :nothing + end.run_action(:create) + end + end + + # link app_home to app_dir + Chef::Log.debug "app_home is #{app_home} and app_dir is #{app_dir}" + current_link = ::File.symlink?(app_home) ? ::File.readlink(app_home) : nil + if current_link != app_dir + converge_by("symlink #{app_dir} to #{app_home}") do + FileUtils.rm_f app_home + FileUtils.ln_sf app_dir, app_home + FileUtils.chown new_resource.owner, app_group, app_home + end + end + + # update-alternatives + java_alternatives 'set-java-alternatives' do + java_location app_home + bin_cmds new_resource.bin_cmds + priority new_resource.alternatives_priority + default new_resource.default + reset_alternatives new_resource.reset_alternatives + action :set + end +end + +action :remove do + raise 'No URL provided for AdoptOpenJDK\'s tar file!' if new_resource.url.nil? || new_resource.url.empty? + _app_dir_name, _tarball_name, _app_root, app_dir = + parse_dir_names(new_resource.url, + new_resource.app_home, + new_resource.variant) + app_home = new_resource.app_home + Chef::Log.debug("processing #{new_resource.variant} variant") + + if ::File.exist?(app_dir) + java_alternatives 'unset-java-alternatives' do + java_location app_home + bin_cmds new_resource.bin_cmds + action :unset + end + + directory "AdoptOpenJDK removal of #{app_home}" do + path app_home + recursive true + action :delete + end + directory "AdoptOpenJDK removal of #{app_dir}" do + path app_dir + recursive true + action :delete + end + end +end + +action_class do + require 'uri' + + def parse_app_dir_name(url) + uri = URI.parse(url) + file_name = uri.path.split('/').last + if file_name =~ /jdk\d+u\d+-b\d+/ # OpenJDK8 + dir_name_results = file_name.scan(/_(jdk\d+u\d+-b\d+)(?:_openj[-.\d]+)?\.tar\.gz$/) + app_dir_name = dir_name_results[0][0] unless dir_name_results.empty? + elsif file_name =~ /_\d+u\d+b\d+\.tar\.gz$/ # OpenJDK8U + dir_name_results = file_name.scan(/_(\d+u\d+)(b\d+)\.tar\.gz$/) + app_dir_name = "jdk#{dir_name_results[0][0]}-#{dir_name_results[0][1]}" unless dir_name_results.empty? + else + dir_name_results = file_name.scan(/[-_]([.\d]+)[._]([\d]+)(?:_openj[-.\d]+)?\.tar\.gz$/) + app_dir_name = "jdk-#{dir_name_results[0][0]}+#{dir_name_results[0][1]}" unless dir_name_results.empty? + end + Chef::Application.fatal!("Failed to parse #{file_name} for application directory name!") if dir_name_results.empty? + + [app_dir_name, file_name] + end + + def parse_dir_names(url, app_home, variant) + app_dir_name, tarball_name = parse_app_dir_name(url) + app_root = app_home.split('/')[0..-2].join('/') + app_dir = "#{app_root}/#{app_dir_name}-#{variant}" + [app_dir_name, tarball_name, app_root, app_dir] + end + + def alternatives_config_file(app_root, app_home) + java_name = app_home.split('/')[-1] + config_file = "#{app_root}/.#{java_name}.jinfo" + [java_name, config_file] + end + + def adoptopendjk_downloaded?(download_path, new_resource) + if ::File.exist? download_path + require 'openssl' + if new_resource.checksum =~ /^[0-9a-f]{32}$/ + downloaded_md5 = OpenSSL::Digest::MD5.file(download_path).hexdigest + downloaded_md5 == new_resource.checksum + else + downloaded_sha = OpenSSL::Digest::SHA256.file(download_path).hexdigest + downloaded_sha == new_resource.checksum + end + else + false + end + end +end diff --git a/cookbooks/java/resources/alternatives.rb b/cookbooks/java/resources/alternatives.rb new file mode 100644 index 0000000..2b130b4 --- /dev/null +++ b/cookbooks/java/resources/alternatives.rb @@ -0,0 +1,89 @@ +# +# Cookbook:: java +# Provider:: alternatives +# +# 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. + +property :java_location, String +property :bin_cmds, Array +property :default, [true, false], default: true +property :priority, Integer, default: 1061 +property :reset_alternatives, [true, false], default: true + +action :set do + if new_resource.bin_cmds + new_resource.bin_cmds.each do |cmd| + bin_path = "/usr/bin/#{cmd}" + alt_path = "#{new_resource.java_location}/bin/#{cmd}" + priority = new_resource.priority + + unless ::File.exist?(alt_path) + Chef::Log.debug "Skipping setting alternative for #{cmd}. Command #{alt_path} does not exist." + next + end + + alternative_exists_same_priority = shell_out("#{alternatives_cmd} --display #{cmd} | grep #{alt_path} | grep 'priority #{priority}$'").exitstatus == 0 + alternative_exists = shell_out("#{alternatives_cmd} --display #{cmd} | grep #{alt_path}").exitstatus == 0 + # remove alternative if priority is changed and install it with new priority + if alternative_exists && !alternative_exists_same_priority + converge_by("Removing alternative for #{cmd} with old priority") do + Chef::Log.debug "Removing alternative for #{cmd} with old priority" + remove_cmd = shell_out("#{alternatives_cmd} --remove #{cmd} #{alt_path}") + alternative_exists = false + unless remove_cmd.exitstatus == 0 + Chef::Application.fatal!(%( remove alternative failed )) + end + end + end + # install the alternative if needed + unless alternative_exists + converge_by("Add alternative for #{cmd}") do + Chef::Log.debug "Adding alternative for #{cmd}" + if new_resource.reset_alternatives + shell_out("rm /var/lib/alternatives/#{cmd}") + end + install_cmd = shell_out("#{alternatives_cmd} --install #{bin_path} #{cmd} #{alt_path} #{priority}") + unless install_cmd.exitstatus == 0 + Chef::Application.fatal!(%( install alternative failed )) + end + end + end + + # set the alternative if default + next unless new_resource.default + alternative_is_set = shell_out("#{alternatives_cmd} --display #{cmd} | grep \"link currently points to #{alt_path}\"").exitstatus == 0 + next if alternative_is_set + converge_by("Set alternative for #{cmd}") do + Chef::Log.debug "Setting alternative for #{cmd}" + set_cmd = shell_out("#{alternatives_cmd} --set #{cmd} #{alt_path}") + unless set_cmd.exitstatus == 0 + Chef::Application.fatal!(%( set alternative failed )) + end + end + end + end +end + +action :unset do + new_resource.bin_cmds.each do |cmd| + converge_by("Remove alternative for #{cmd}") do + shell_out("#{alternatives_cmd} --remove #{cmd} #{new_resource.java_location}/bin/#{cmd}") + end + end +end + +action_class do + def alternatives_cmd + platform_family?('rhel', 'fedora', 'amazon') ? 'alternatives' : 'update-alternatives' + end +end diff --git a/cookbooks/java/resources/certificate.rb b/cookbooks/java/resources/certificate.rb new file mode 100644 index 0000000..e6c5ab7 --- /dev/null +++ b/cookbooks/java/resources/certificate.rb @@ -0,0 +1,144 @@ +# +# Author:: Mevan Samaratunga () +# Author:: Michael Goetz () +# Cookbook:: java +# Resource:: certificate +# +# Copyright:: 2013, Mevan Samaratunga +# +# 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. + +property :java_home, String, default: lazy { node['java']['java_home'] } +property :keystore_path, String, default: lazy { node['java']['jdk_version'].to_i < 11 ? "#{node['java']['java_home']}/jre/lib/security/cacerts" : "#{node['java']['java_home']}/lib/security/cacerts" } +property :keystore_passwd, String, default: 'changeit' +property :cert_alias, String, name_property: true +property :cert_data, String +property :cert_file, String +property :ssl_endpoint, String + +action :install do + require 'openssl' + + java_home = new_resource.java_home + keytool = "#{java_home}/bin/keytool" + truststore = if new_resource.keystore_path.empty? + truststore_default_location + else + new_resource.keystore_path + end + truststore_passwd = new_resource.keystore_passwd + certalias = new_resource.cert_alias + certdata = new_resource.cert_data || fetch_certdata + + hash = OpenSSL::Digest::SHA512.hexdigest(certdata) + certfile = "#{node['java']['download_path']}/#{certalias}.cert.#{hash}" + cmd = Mixlib::ShellOut.new("#{keytool} -list -keystore #{truststore} -storepass #{truststore_passwd} -rfc -alias \"#{certalias}\"") + cmd.run_command + keystore_cert = cmd.stdout.match(/^[-]+BEGIN.*END(\s|\w)+[-]+$/m).to_s + + keystore_cert_digest = keystore_cert.empty? ? nil : OpenSSL::Digest::SHA512.hexdigest(OpenSSL::X509::Certificate.new(keystore_cert).to_der) + certfile_digest = OpenSSL::Digest::SHA512.hexdigest(OpenSSL::X509::Certificate.new(certdata).to_der) + if keystore_cert_digest == certfile_digest + Chef::Log.debug("Certificate \"#{certalias}\" in keystore \"#{truststore}\" is up-to-date.") + else + cmd = Mixlib::ShellOut.new("#{keytool} -list -keystore #{truststore} -storepass #{truststore_passwd} -v") + cmd.run_command + Chef::Log.debug(cmd.format_for_exception) + Chef::Application.fatal!("Error querying keystore for existing certificate: #{cmd.exitstatus}", cmd.exitstatus) unless cmd.exitstatus == 0 + + has_key = !cmd.stdout[/Alias name: \b#{certalias}/i].nil? + + if has_key + converge_by("delete existing certificate #{certalias} from #{truststore}") do + cmd = Mixlib::ShellOut.new("#{keytool} -delete -alias \"#{certalias}\" -keystore #{truststore} -storepass #{truststore_passwd}") + cmd.run_command + Chef::Log.debug(cmd.format_for_exception) + unless cmd.exitstatus == 0 + Chef::Application.fatal!("Error deleting existing certificate \"#{certalias}\" in " \ + "keystore so it can be updated: #{cmd.exitstatus}", cmd.exitstatus) + end + end + end + + ::File.open(certfile, 'w', 0o644) { |f| f.write(certdata) } + + converge_by("add certificate #{certalias} to keystore #{truststore}") do + cmd = Mixlib::ShellOut.new("#{keytool} -import -trustcacerts -alias \"#{certalias}\" -file #{certfile} -keystore #{truststore} -storepass #{truststore_passwd} -noprompt") + cmd.run_command + Chef::Log.debug(cmd.format_for_exception) + + unless cmd.exitstatus == 0 + FileUtils.rm_f(certfile) + Chef::Application.fatal!("Error importing certificate into keystore: #{cmd.exitstatus}", cmd.exitstatus) + end + end + end +end + +action :remove do + certalias = new_resource.name + truststore = if new_resource.keystore_path.nil? + truststore_default_location + else + new_resource.keystore_path + end + truststore_passwd = new_resource.keystore_passwd + keytool = "#{node['java']['java_home']}/bin/keytool" + + cmd = Mixlib::ShellOut.new("#{keytool} -list -keystore #{truststore} -storepass #{truststore_passwd} -v | grep \"#{certalias}\"") + cmd.run_command + has_key = !cmd.stdout[/Alias name: #{certalias}/].nil? + Chef::Application.fatal!("Error querying keystore for existing certificate: #{cmd.exitstatus}", cmd.exitstatus) unless cmd.exitstatus == 0 + + if has_key + converge_by("remove certificate #{certalias} from #{truststore}") do + cmd = Mixlib::ShellOut.new("#{keytool} -delete -alias \"#{certalias}\" -keystore #{truststore} -storepass #{truststore_passwd}") + cmd.run_command + unless cmd.exitstatus == 0 + Chef::Application.fatal!("Error deleting existing certificate \"#{certalias}\" in " \ + "keystore so it can be updated: #{cmd.exitstatus}", cmd.exitstatus) + end + end + end + + FileUtils.rm_f("#{node['java']['download_path']}/#{certalias}.cert.*") +end + +action_class do + def fetch_certdata + return IO.read(new_resource.cert_file) unless new_resource.cert_file.nil? + + certendpoint = new_resource.ssl_endpoint + unless certendpoint.nil? + cmd = Mixlib::ShellOut.new("echo QUIT | openssl s_client -showcerts -servername #{certendpoint.split(':').first} -connect #{certendpoint} 2> /dev/null | openssl x509") + cmd.run_command + Chef::Log.debug(cmd.format_for_exception) + + Chef::Application.fatal!("Error returned when attempting to retrieve certificate from remote endpoint #{certendpoint}: #{cmd.exitstatus}", cmd.exitstatus) unless cmd.exitstatus == 0 + + certout = cmd.stdout + return certout unless certout.empty? + Chef::Application.fatal!("Unable to parse certificate from openssl query of #{certendpoint}.", 999) + end + + Chef::Application.fatal!('At least one of cert_data, cert_file or ssl_endpoint attributes must be provided.', 999) + end + + def truststore_default_location + if node['java']['jdk_version'].to_i > 8 + "#{node['java']['java_home']}/lib/security/cacerts" + else + "#{node['java']['java_home']}/jre/lib/security/cacerts" + end + end +end diff --git a/cookbooks/java/resources/jce.rb b/cookbooks/java/resources/jce.rb new file mode 100644 index 0000000..2feef7e --- /dev/null +++ b/cookbooks/java/resources/jce.rb @@ -0,0 +1,106 @@ +# +# Cookbook:: java +# Provider:: jce +# +# 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. + +property :jdk_version, String, default: lazy { node['java']['jdk_version'].to_s } +property :jce_url, String, default: lazy { node['java']['oracle']['jce'][jdk_version]['url'] } +property :jce_checksum, String, default: lazy { node['java']['oracle']['jce'][jdk_version]['checksum'] } +property :java_home, String, default: lazy { node['java']['java_home'] } +property :jce_home, String, default: lazy { node['java']['oracle']['jce']['home'] } +property :jce_cookie, String, default: lazy { node['java']['oracle']['accept_oracle_download_terms'] ? 'oraclelicense=accept-securebackup-cookie' : '' } +property :principal, String, default: lazy { platform_family?('windows') ? node['java']['windows']['owner'] : 'administrator' } + +action :install do + jdk_version = new_resource.jdk_version + jce_url = new_resource.jce_url + jce_checksum = new_resource.jce_checksum + java_home = new_resource.java_home + jce_home = new_resource.jce_home + jce_cookie = new_resource.jce_cookie + principal = new_resource.principal + + directory ::File.join(jce_home, jdk_version) do + mode '0755' + recursive true + end + + r = remote_file "#{node['java']['download_path']}/jce.zip" do + source jce_url + checksum jce_checksum + headers( + 'Cookie' => jce_cookie + ) + not_if { ::File.exist?(::File.join(jce_home, jdk_version, 'US_export_policy.jar')) } + end + + # JRE installation does not have a jre folder + jre_path = node['java']['install_type'] == 'jdk' ? 'jre' : '' + + if node['os'] == 'windows' + + staging_path = ::File.join(jce_home, jdk_version) + staging_local_policy = ::File.join(staging_path, "UnlimitedJCEPolicyJDK#{jdk_version}", 'local_policy.jar') + staging_export_policy = ::File.join(staging_path, "UnlimitedJCEPolicyJDK#{jdk_version}", 'US_export_policy.jar') + jre_final_path = ::File.join(java_home, jre_path, 'lib', 'security') + final_local_policy = ::File.join(jre_final_path, 'local_policy.jar') + final_export_policy = ::File.join(jre_final_path, 'US_export_policy.jar') + + windows_zipfile staging_path do + source r.path + checksum jce_checksum + action :unzip + not_if { ::File.exist? staging_local_policy } + end + + remote_file final_local_policy do + rights :full_control, principal + source "file://#{staging_local_policy}" + end + + remote_file final_export_policy do + rights :full_control, principal + source "file://#{staging_export_policy}" + end + + else + package 'unzip' + package 'curl' + + execute 'extract jce' do + command <<-EOF + rm -rf java_jce + mkdir java_jce + cd java_jce + unzip -o ../jce.zip + find ./ -name '*.jar' | xargs -I JCE_JAR mv JCE_JAR #{jce_home}/#{jdk_version}/ + chmod -R 0644 #{jce_home}/#{jdk_version}/*.jar + EOF + cwd node['java']['download_path'] + creates ::File.join(jce_home, jdk_version, 'US_export_policy.jar') + end + + %w(local_policy.jar US_export_policy.jar).each do |jar| + jar_path = ::File.join(java_home, jre_path, 'lib', 'security', jar) + # remove the jars already in the directory + file jar_path do + action :delete + not_if { ::File.symlink? jar_path } + end + link jar_path do + to ::File.join(jce_home, jdk_version, jar) + end + end + end +end diff --git a/cookbooks/java/resources/oracle_install.rb b/cookbooks/java/resources/oracle_install.rb new file mode 100644 index 0000000..eb46db4 --- /dev/null +++ b/cookbooks/java/resources/oracle_install.rb @@ -0,0 +1,285 @@ +# +# Author:: Bryan W. Berry () +# Cookbook:: java +# Resource:: oracle_install +# +# Copyright:: 2011, Bryan w. Berry +# Copyright:: 2017-2018, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# backwards compatibility with the old name +provides :java_oracle_install +provides :java_ark + +property :url, String +property :mirrorlist, Array, default: [] +property :checksum, String, regex: /^[0-9a-f]{32}$|^[a-zA-Z0-9]{40,64}$/ +property :md5, String, regex: /^[0-9a-f]{32}$|^[a-zA-Z0-9]{40,64}$/ +property :app_home, String +property :app_home_mode, Integer, default: 0755 +property :bin_cmds, Array, default: [] +property :owner, String, default: 'root' +property :group, String, default: lazy { node['root_group'] } +property :default, [true, false], default: true +property :alternatives_priority, Integer, default: 1 +property :connect_timeout, Integer, default: 30 # => 30 seconds +property :reset_alternatives, [true, false], default: true +property :use_alt_suffix, [true, false], default: true +property :download_timeout, Integer, default: 600 # => 600 seconds +property :proxy, String +property :accept_oracle_download_terms, [true, false], default: lazy { node['java']['oracle']['accept_oracle_download_terms'] } + +action :install do + app_dir_name, tarball_name = parse_app_dir_name(new_resource.url) + app_root = new_resource.app_home.split('/')[0..-2].join('/') + app_dir = app_root + '/' + app_dir_name + app_group = new_resource.group + + if !new_resource.default && new_resource.use_alt_suffix + Chef::Log.debug('processing alternate jdk') + app_dir += '_alt' + app_home = new_resource.app_home + '_alt' + else + app_home = new_resource.app_home + end + + directory app_root do + owner new_resource.owner + group app_group + mode new_resource.app_home_mode + recursive true + action :nothing + end.run_action(:create) + + unless ::File.exist?(app_dir) + if new_resource.url =~ /oracle\.com.*$/ + download_path = "#{node['java']['download_path']}/#{tarball_name}" + if oracle_downloaded?(download_path, new_resource) + Chef::Log.debug('oracle tarball already downloaded, not downloading again') + else + Chef::Log.warn('Downloading directly from Oracle is unreliable as artifacts have been removed in the past. Change download url.') + download_direct_from_oracle tarball_name, new_resource + end + else + Chef::Log.debug('downloading tarball from an unofficial repository') + remote_file "#{node['java']['download_path']}/#{tarball_name}" do + source new_resource.url + checksum new_resource.checksum + retries new_resource.retries + retry_delay new_resource.retry_delay + mode '0755' + action :nothing + end.run_action(:create_if_missing) + end + + converge_by("extract compressed data into Chef file cache path and move extracted data to #{app_dir}") do + case tarball_name + when /^.*\.bin/ + cmd = shell_out( + %(cd "#{node['java']['download_path']}"; + bash ./#{tarball_name} -noregister + ) + ) + unless cmd.exitstatus == 0 + Chef::Application.fatal!("Failed to extract file #{tarball_name}!") + end + when /^.*\.zip/ + cmd = shell_out( + %(unzip "#{node['java']['download_path']}/#{tarball_name}" -d "#{node['java']['download_path']}" ) + ) + unless cmd.exitstatus == 0 + Chef::Application.fatal!("Failed to extract file #{tarball_name}!") + end + when /^.*\.(tar.gz|tgz)/ + package 'tar' do + not_if { platform_family?('mac_os_x', 'windows') } + action :nothing + end.run_action(:install) + + cmd = shell_out( + %(tar xvzf "#{node['java']['download_path']}/#{tarball_name}" -C "#{node['java']['download_path']}" --no-same-owner) + ) + unless cmd.exitstatus == 0 + Chef::Application.fatal!("Failed to extract file #{tarball_name}!") + end + end + + cmd = shell_out( + %(mv "#{node['java']['download_path']}/#{app_dir_name}" "#{app_dir}" ) + ) + unless cmd.exitstatus == 0 + Chef::Application.fatal!(%( Command \' mv "#{node['java']['download_path']}/#{app_dir_name}" "#{app_dir}" \' failed )) + end + + # change ownership of extracted files + FileUtils.chown_R new_resource.owner, app_group, app_dir + end + end + + # set up .jinfo file for update-java-alternatives + java_name = app_home.split('/')[-1] + jinfo_file = "#{app_root}/.#{java_name}.jinfo" + if platform_family?('debian') && !::File.exist?(jinfo_file) + converge_by("Add #{jinfo_file} for debian") do + template jinfo_file do + cookbook 'java' + source 'oracle.jinfo.erb' + owner new_resource.owner + group app_group + variables( + priority: new_resource.alternatives_priority, + bin_cmds: new_resource.bin_cmds, + name: java_name, + app_dir: app_home + ) + action :nothing + end.run_action(:create) + end + end + + # link app_home to app_dir + Chef::Log.debug "app_home is #{app_home} and app_dir is #{app_dir}" + current_link = ::File.symlink?(app_home) ? ::File.readlink(app_home) : nil + if current_link != app_dir + converge_by("symlink #{app_dir} to #{app_home}") do + FileUtils.rm_f app_home + FileUtils.ln_sf app_dir, app_home + FileUtils.chown new_resource.owner, app_group, app_home + end + end + + # update-alternatives + java_alternatives 'set-java-alternatives' do + java_location app_home + bin_cmds new_resource.bin_cmds + priority new_resource.alternatives_priority + default new_resource.default + reset_alternatives new_resource.reset_alternatives + action :set + end +end + +action :remove do + app_dir_name, _tarball_name = parse_app_dir_name(new_resource.url) + app_root = new_resource.app_home.split('/')[0..-2].join('/') + app_dir = app_root + '/' + app_dir_name + + if new_resource.default + app_home = new_resource.app_home + else + Chef::Log.debug('processing alternate jdk') + app_dir += '_alt' + app_home = new_resource.app_home + '_alt' + end + + if ::File.exist?(app_dir) + java_alternatives 'unset-java-alternatives' do + java_location app_home + bin_cmds new_resource.bin_cmds + action :unset + end + + converge_by("remove #{new_resource.name} at #{app_dir}") do + Chef::Log.info "Removing #{new_resource.name} at #{app_dir}" + FileUtils.rm_rf app_dir + end + end +end + +action_class do + require 'uri' + + def parse_app_dir_name(url) + uri = URI.parse(url) + file_name = uri.path.split('/').last + # funky logic to parse oracle's non-standard naming convention + # for jdk1.6 -> 1.9, 10.0.0->10.0.2, 11 + if file_name =~ /^(jre|jdk|server-jre).*$/ + major_num = file_name.scan(/\d{1,}/)[0] + package_name = file_name =~ /^server-jre.*$/ ? 'jdk' : file_name.scan(/[a-z]+/)[0] + if major_num.to_i >= 10 + # Versions 10 and above incorporate semantic versioning and/or single version numbers + version_result = file_name.scan(/.*-([\d\.]+)_.*/)[0][0] + app_dir_name = "#{package_name}-#{version_result}" + else + update_token = file_name.scan(/u(\d+)/)[0] + update_num = update_token ? update_token[0] : '0' + # pad a single digit number with a zero + update_num = '0' + update_num if update_num.length < 2 + app_dir_name = if update_num == '00' + "#{package_name}1.#{major_num}.0" + else + "#{package_name}1.#{major_num}.0_#{update_num}" + end + end + else + app_dir_name = file_name.split(/(.tgz|.tar.gz|.zip)/)[0] + app_dir_name = app_dir_name.split('-bin')[0] + end + [app_dir_name, file_name] + end + + def oracle_downloaded?(download_path, new_resource) + if ::File.exist? download_path + require 'openssl' + if new_resource.checksum =~ /^[0-9a-f]{32}$/ + downloaded_md5 = OpenSSL::Digest::MD5.file(download_path).hexdigest + downloaded_md5 == new_resource.checksum + else + downloaded_sha = OpenSSL::Digest::SHA256.file(download_path).hexdigest + downloaded_sha == new_resource.checksum + end + else + false + end + end + + def download_direct_from_oracle(tarball_name, new_resource) + download_path = "#{node['java']['download_path']}/#{tarball_name}" + cookie = 'oraclelicense=accept-securebackup-cookie' + proxy = "-x #{new_resource.proxy}" unless new_resource.proxy.nil? + if new_resource.accept_oracle_download_terms + # install the curl package + package 'curl' do + action :nothing + end.run_action(:install) + + converge_by('download oracle tarball straight from the server') do + Chef::Log.debug 'downloading oracle tarball straight from the source' + shell_out!( + %W( + curl + --fail + --create-dirs + -L + --retry #{new_resource.retries} + --retry-delay #{new_resource.retry_delay} --cookie "#{cookie}" + #{new_resource.url} + -o #{download_path} + --connect-timeout #{new_resource.connect_timeout} + #{proxy} + ).join(' '), + timeout: new_resource.download_timeout + ) + end + # Can't verify anything with HTTP return codes from Oracle. For example, they return 200 for auth failure. + # Do a generic verification of the download + unless oracle_downloaded?(download_path, new_resource) + Chef::Application.fatal!("Checksum verification failure. Possible wrong checksum or download from Oracle failed.\nVerify artifact checksum and/or verify #{download_path} is an archive and not an HTML response from Oracle") + end + else + Chef::Application.fatal!("You must set the resource property 'accept_oracle_download_terms' or set the node attribute node['java']['oracle']['accept_oracle_download_terms'] to true if you want to download directly from the oracle site!") + end + end +end diff --git a/cookbooks/java/templates/adoptopenjdk.jinfo.erb b/cookbooks/java/templates/adoptopenjdk.jinfo.erb new file mode 100644 index 0000000..0d10b51 --- /dev/null +++ b/cookbooks/java/templates/adoptopenjdk.jinfo.erb @@ -0,0 +1,6 @@ +name=<%= @name %> +priority=<%= @priority %> +section=main + +<% @bin_cmds.each do |cmd| -%>jdk <%= cmd %> <%= @app_dir %>/bin/<%= cmd %> +<% end -%> diff --git a/cookbooks/java/templates/ibm_jdk.installer.properties.erb b/cookbooks/java/templates/ibm_jdk.installer.properties.erb new file mode 100644 index 0000000..cfb9279 --- /dev/null +++ b/cookbooks/java/templates/ibm_jdk.installer.properties.erb @@ -0,0 +1,4 @@ +LICENSE_ACCEPTED=<%= node['java']['accept_license_agreement'] %> +INSTALLER_UI=silent +USER_INSTALL_DIR=<%= node['java']['java_home'] %> +-fileOverwrite_<%= node['java']['java_home'] %>_uninstall/uninstall.lax=Yes diff --git a/cookbooks/java/templates/jdk.sh.erb b/cookbooks/java/templates/jdk.sh.erb new file mode 100644 index 0000000..39486d3 --- /dev/null +++ b/cookbooks/java/templates/jdk.sh.erb @@ -0,0 +1 @@ +export JAVA_HOME=<%= node['java']['java_home']%> diff --git a/cookbooks/java/templates/oracle.jinfo.erb b/cookbooks/java/templates/oracle.jinfo.erb new file mode 100644 index 0000000..0d10b51 --- /dev/null +++ b/cookbooks/java/templates/oracle.jinfo.erb @@ -0,0 +1,6 @@ +name=<%= @name %> +priority=<%= @priority %> +section=main + +<% @bin_cmds.each do |cmd| -%>jdk <%= cmd %> <%= @app_dir %>/bin/<%= cmd %> +<% end -%> diff --git a/cookbooks/logrotate/LICENSE b/cookbooks/logrotate/LICENSE new file mode 100644 index 0000000..911c489 --- /dev/null +++ b/cookbooks/logrotate/LICENSE @@ -0,0 +1,203 @@ + 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 2009-2013, Chef Software, Inc. +Copyright 2015-2016, Steven Danna +Copyright 2016, Bloomberg Finance L.P. + +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/cookbooks/logrotate/Makefile b/cookbooks/logrotate/Makefile new file mode 100644 index 0000000..0feec86 --- /dev/null +++ b/cookbooks/logrotate/Makefile @@ -0,0 +1,11 @@ +all: delivery + +travis: debug_version_info all + +debug_version_info: + /opt/chefdk/embedded/bin/chef --version + /opt/chefdk/embedded/bin/cookstyle --version + /opt/chefdk/embedded/bin/foodcritic --version + +delivery: + /opt/chefdk/bin/chef exec delivery local all diff --git a/cookbooks/logrotate/README.md b/cookbooks/logrotate/README.md new file mode 100644 index 0000000..a0ab6ff --- /dev/null +++ b/cookbooks/logrotate/README.md @@ -0,0 +1,232 @@ +# logrotate Cookbook +[![Build Status](https://secure.travis-ci.org/stevendanna/logrotate.png?branch=master)](http://travis-ci.org/stevendanna/logrotate) + +Manages the logrotate package and provides a definition to manage +application specific logrotate configuration. + + +## Requirements + +### Platforms + +Should work on any platform that includes a 'logrotate' package and +writes logrotate configuration to /etc/logrotate.d. Tested on Ubuntu +and Centos. + + +### Chef + +- Chef 12.5+ + +### Cookbooks + +- none + +## Recipes + +### global + +Generates and controls a global `/etc/logrotate.conf` file that will +include additional files generated by the `logrotate_app` definition +(see below). The contents of the configuration file is controlled +through node attributes under `node['logrotate']['global']`. The +default attributes are based on the configuration from the Ubuntu +logrotate package. + +To define a valueless directive (e.g. `compress`, `copy`) simply add +an attribute named for the directive with a truthy value: + +```ruby +node['logrotate']['global']['compress'] = 'any value here' +``` + +Note that defining a valueless directive with a falsey value will not +make it false, but will remove it: + +```ruby +# Removes a defaulted 'compress' directive; does not add a 'nocompress' directive. +node.override['logrotate']['global']['compress'] = false +``` + +To fully override a booleanish directive like `compress`, you should +probably remove the positive form and add the negative form: + +```ruby +node.override['logrotate']['global']['compress'] = false +node.override['logrotate']['global']['nocompress'] = true +``` + +The same is true of frequency directives; to be certain the frequency +directive you want is included in the global configuration, you should +override the ones you don't want as false: + +```ruby +%w[ daily weekly yearly ].each do |freq| + node.override['logrotate']['global'][freq] = false +end +node.override['logrotate']['global']['monthly'] = true +``` + +To define a parameter with a value (e.g. `create`, `mail`) add an +attribute with the desired value: + +```ruby +node['logrotate']['global']['create'] = '0644 root adm' +``` + +To define a path stanza in the global configuration (generally +unneeded because of the `logrotate_app` definition) just add an +attribute with the path as the name and a hash containing directives +and parameters as described above: + +```ruby +node['logrotate']['global']['/var/log/wtmp'] = { + 'missingok' => true, + 'monthly' => true, + 'create' => '0660 root utmp', + 'rotate' => 1 +} +``` + +`firstaction`, `prerotate`, `postrotate`, and `lastaction` scripts can +be defined either as arrays of the lines to put in the script or +multiline strings: + +```ruby +node['logrotate']['global']['/var/log/foo/*.log'] = { + 'missingok' => true, + 'monthly' => true, + 'create' => '0660 root adm', + 'rotate' => 1, + 'prerotate' => ['service foo start_rotate', 'logger started foo service log rotation'], + 'postrotate' => <<-EOF + service foo end_rotate + logger completed foo service log rotation + EOF +} +``` + + +Resources +----------- +### logrotate_app + +This resource can be used to drop off customized logrotate config +files on a per application basis. + +The resource takes the following properties: + +- `path`: specifies a single path (string) or multiple paths (array) + that should have logrotation stanzas created in the config file. No + default, this must be specified. + +- `cookbook`: The cookbook that continues the template for + logrotate_app config definitions. By default this is `logrotate`. + Users can provide their own template by setting this attribute to + point at a different cookbook. + +- `template_name`: sets the template source, default is + "logrotate.erb". + +- `template_mode`: the mode to create the logrotate template with + (default: "0644") + +- `template_owner`: the owner of the logrotate template (default: + "root") + +- `template_group`: the group of the logrotate template (default: + "root") + +- `frequency`: sets the frequency for rotation. Default value is + 'weekly'. Valid values are: hourly, daily, weekly, monthly, yearly, + see the logrotate man page for more information. Note that usually + logrotate is configured to be run by cron daily. You have to change + this configuration and run logrotate hourly to be able to really + rotate logs hourly. Hourly rotation requires logrotate v3.8.5 or + higher. + +- `options`: Any logrotate configuration option that doesn't specify a + value. See the logrotate(8) manual page of v3.9.2 or earlier for + details. + +In addition to these properties, any logrotate option that takes a +parameter can be used as a logrotate_app property. For example, to set +the `rotate` option you can use a resource declaration such as: + +```ruby +logrotate_app 'tomcat-myapp' do + path '/var/log/tomcat/myapp.log' + frequency 'daily' + rotate 30 + create '644 root adm' +end +``` + +See the logrotate(8) manual page of v3.9.2 or earlier for the list of +available options. + + +## Usage + +The default recipe will ensure logrotate is always up to date. + +To create application specific logrotate configs, use the +`logrotate_app` definition. For example, to rotate logs for a tomcat +application named myapp that writes its log file to +`/var/log/tomcat/myapp.log`: + +```ruby +logrotate_app 'tomcat-myapp' do + path '/var/log/tomcat/myapp.log' + frequency 'daily' + rotate 30 + create '644 root adm' +end +``` + +To rotate multiple logfile paths, specify the path as an array: + +```ruby +logrotate_app 'tomcat-myapp' do + path ['/var/log/tomcat/myapp.log', '/opt/local/tomcat/catalina.out'] + frequency 'daily' + create '644 root adm' + rotate 7 +end +``` + +To specify which logrotate options, specify the options as an array: + +```ruby +logrotate_app 'tomcat-myapp' do + path '/var/log/tomcat/myapp.log' + options ['missingok', 'delaycompress', 'notifempty'] + frequency 'daily' + rotate 30 + create '644 root adm' +end +``` + +## License & Authors + +- Author:: Steven Danna () +- Author:: Scott M. Likens () +- Author:: Joshua Timberman () + +```text +Copyright 2009, Scott M. Likens +Copyright 2011-2012, Chef Software, Inc. +Copyright 2016, Steven Danna + +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/cookbooks/logrotate/attributes/default.rb b/cookbooks/logrotate/attributes/default.rb new file mode 100644 index 0000000..0be2049 --- /dev/null +++ b/cookbooks/logrotate/attributes/default.rb @@ -0,0 +1,55 @@ +# +# Cookbook:: logrotate +# Attribute:: default +# +# Copyright:: 2013-2017, Chef Software, Inc +# Copyright:: 2015-2017, Steven Danna +# Copyright:: 2016-2017, Bloomberg Finance L.P. +# +# 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. +# + +default['logrotate']['package'] = { + 'name' => 'logrotate', + 'source' => nil, + 'version' => nil, + 'provider' => nil, + 'action' => :upgrade, +} + +default['logrotate']['directory'] = '/etc/logrotate.d' +default['logrotate']['cron']['install'] = platform?('solaris2') || platform?('aix') +default['logrotate']['cron']['name'] = 'logrotate' +default['logrotate']['cron']['command'] = '/usr/sbin/logrotate /etc/logrotate.conf' +default['logrotate']['cron']['minute'] = 35 +default['logrotate']['cron']['hour'] = 2 + +default['logrotate']['global'] = { + 'weekly' => true, + 'rotate' => 4, + 'create' => '', + + '/var/log/wtmp' => { + 'missingok' => true, + 'monthly' => true, + 'create' => '0664 root utmp', + 'rotate' => 1, + }, + + '/var/log/btmp' => { + 'missingok' => true, + 'monthly' => true, + 'create' => '0660 root utmp', + 'rotate' => 1, + }, +} diff --git a/cookbooks/logrotate/chefignore b/cookbooks/logrotate/chefignore new file mode 100644 index 0000000..a976917 --- /dev/null +++ b/cookbooks/logrotate/chefignore @@ -0,0 +1,102 @@ +# Put files/directories that should be ignored in this file when uploading +# to a chef-server or supermarket. +# Lines that start with '# ' are comments. + +# OS generated files # +###################### +.DS_Store +Icon? +nohup.out +ehthumbs.db +Thumbs.db + +# SASS # +######## +.sass-cache + +# EDITORS # +########### +\#* +.#* +*~ +*.sw[a-z] +*.bak +REVISION +TAGS* +tmtags +*_flymake.* +*_flymake +*.tmproj +.project +.settings +mkmf.log + +## COMPILED ## +############## +a.out +*.o +*.pyc +*.so +*.com +*.class +*.dll +*.exe +*/rdoc/ + +# Testing # +########### +.watchr +.rspec +spec/* +spec/fixtures/* +test/* +features/* +examples/* +Guardfile +Procfile +.kitchen* +.rubocop.yml +spec/* +Rakefile +.travis.yml +.foodcritic +.codeclimate.yml + +# SCM # +####### +.git +*/.git +.gitignore +.gitmodules +.gitconfig +.gitattributes +.svn +*/.bzr/* +*/.hg/* +*/.svn/* + +# Berkshelf # +############# +Berksfile +Berksfile.lock +cookbooks/* +tmp + +# Cookbooks # +############# +CONTRIBUTING* +CHANGELOG* +TESTING* +MAINTAINERS.toml + +# Strainer # +############ +Colanderfile +Strainerfile +.colander +.strainer + +# Vagrant # +########### +.vagrant +Vagrantfile diff --git a/cookbooks/logrotate/libraries/logrotate_config.rb b/cookbooks/logrotate/libraries/logrotate_config.rb new file mode 100644 index 0000000..5f20d3d --- /dev/null +++ b/cookbooks/logrotate/libraries/logrotate_config.rb @@ -0,0 +1,85 @@ +# +# Cookbook:: logrotate +# Library:: CookbookLogrotate +# +# Copyright:: 2013-2017, Chef +# +# 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. +# + +# Helper module for Logrotate configuration module CookbookLogrotate +module CookbookLogrotate + DIRECTIVES = %w(compress copy copytruncate daily dateext + dateyesterday delaycompress hourly ifempty mailfirst maillast + missingok monthly nocompress nocopy nocopytruncate nocreate nocreateolddir + nodelaycompress nodateext nomail nomissingok noolddir + nosharedscripts noshred notifempty renamecopy sharedscripts shred weekly + yearly).freeze unless const_defined?(:DIRECTIVES) + + VALUES = %w(compresscmd uncompresscmd compressext compressoptions + create createolddir dateformat include mail extension maxage minsize maxsize + rotate size shredcycles start tabooext su olddir).freeze unless const_defined?(:VALUES) + + SCRIPTS = %w(firstaction prerotate postrotate lastaction preremove).freeze unless const_defined?(:SCRIPTS) + + DIRECTIVES_AND_VALUES_AND_SCRIPTS = DIRECTIVES + VALUES + SCRIPTS unless const_defined?(:DIRECTIVES_AND_VALUES_AND_SCRIPTS) + + # Helper class for creating configurations + class LogrotateConfiguration + attr_reader :directives, :values, :scripts, :paths + + class << self + def from_hash(hash) + new(hash) + end + + def directives_from(hash) + hash.select { |k, v| DIRECTIVES.include?(k) && v }.keys + end + + def values_from(hash) + hash.select { |k| VALUES.include?(k) } + end + + def paths_from(hash) + hash.select { |k| !DIRECTIVES_AND_VALUES_AND_SCRIPTS.include?(k) }.each_with_object({}) do |(path, config), accum_paths| + accum_paths[path] = { + 'directives' => directives_from(config), + 'values' => values_from(config), + 'scripts' => scripts_from(config), + } + end + end + + def scripts_from(hash) + defined_scripts = hash.select { |k| SCRIPTS.include?(k) } + defined_scripts.each_with_object({}) do |(script, lines), accum_scripts| + accum_scripts[script] = if lines.respond_to?(:join) + lines.join("\n") + else + lines + end + end + end + end + + private + + def initialize(hash) + @directives = LogrotateConfiguration.directives_from(hash) + @values = LogrotateConfiguration.values_from(hash) + @scripts = LogrotateConfiguration.scripts_from(hash) + @paths = LogrotateConfiguration.paths_from(hash) + end + end +end diff --git a/cookbooks/logrotate/libraries/matchers.rb b/cookbooks/logrotate/libraries/matchers.rb new file mode 100644 index 0000000..82d5e18 --- /dev/null +++ b/cookbooks/logrotate/libraries/matchers.rb @@ -0,0 +1,11 @@ +if defined?(ChefSpec) + ChefSpec.define_matcher :logrotate_app + + def enable_logrotate_app(resource) + ChefSpec::Matchers::ResourceMatcher.new(:logrotate_app, :enable, resource) + end + + def disable_logrotate_app(resource) + ChefSpec::Matchers::ResourceMatcher.new(:logrotate_app, :disable, resource) + end +end diff --git a/cookbooks/logrotate/metadata.json b/cookbooks/logrotate/metadata.json new file mode 100644 index 0000000..ebda691 --- /dev/null +++ b/cookbooks/logrotate/metadata.json @@ -0,0 +1,60 @@ +{ + "name": "logrotate", + "description": "Installs logrotate package and provides a definition for logrotate configs", + "long_description": "Installs the logrotate package, manages /etc/logrotate.conf, and provides a logrotate_app definition.", + "maintainer": "Steven Danna", + "maintainer_email": "steve@chef.io", + "license": "Apache 2.0", + "platforms": { + "amazon": ">= 0.0.0", + "centos": ">= 0.0.0", + "debian": ">= 0.0.0", + "fedora": ">= 0.0.0", + "redhat": ">= 0.0.0", + "scientific": ">= 0.0.0", + "solaris2": ">= 0.0.0", + "ubuntu": ">= 0.0.0" + }, + "dependencies": { + + }, + "recommendations": { + + }, + "suggestions": { + + }, + "conflicting": { + + }, + "providing": { + "logrotate_app": ">= 0.0.0" + }, + "replacing": { + + }, + "attributes": { + + }, + "groupings": { + + }, + "recipes": { + "logrotate": "Installs logrotate package" + }, + "version": "2.2.0", + "source_url": "https://github.com/stevendanna/logrotate", + "issues_url": "https://github.com/stevendanna/logrotate/issues", + "privacy": false, + "chef_versions": [ + [ + ">= 12.5" + ] + ], + "ohai_versions": [ + + ], + "gems": [ + + ] +} diff --git a/cookbooks/logrotate/metadata.rb b/cookbooks/logrotate/metadata.rb new file mode 100644 index 0000000..e0899fc --- /dev/null +++ b/cookbooks/logrotate/metadata.rb @@ -0,0 +1,18 @@ +name 'logrotate' +maintainer 'Steven Danna' +maintainer_email 'steve@chef.io' +license 'Apache 2.0' +description 'Installs logrotate package and provides a definition for logrotate configs' +long_description 'Installs the logrotate package, manages /etc/logrotate.conf, and provides a logrotate_app definition.' +version '2.2.0' + +recipe 'logrotate', 'Installs logrotate package' +provides 'logrotate_app' + +%w(amazon centos debian fedora redhat scientific solaris2 ubuntu).each do |platform| + supports platform +end + +source_url 'https://github.com/stevendanna/logrotate' +issues_url 'https://github.com/stevendanna/logrotate/issues' +chef_version '>= 12.5' if respond_to?(:chef_version) diff --git a/cookbooks/logrotate/recipes/default.rb b/cookbooks/logrotate/recipes/default.rb new file mode 100644 index 0000000..482e616 --- /dev/null +++ b/cookbooks/logrotate/recipes/default.rb @@ -0,0 +1,42 @@ +# +# Cookbook:: logrotate +# Recipe:: default +# +# Copyright:: 2009-2017, Chef Software, Inc. +# Copyright:: 2015-2017, Steven Danna +# Copyright:: 2016-2017, Bloomberg Finance L.P. +# +# 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. +# +return if platform?('windows') + +package node['logrotate']['package']['name'] do + provider node['logrotate']['package']['provider'] if node['logrotate']['package']['provider'] + source node['logrotate']['package']['source'] if node['logrotate']['package']['source'] + version node['logrotate']['package']['version'] if node['logrotate']['package']['version'] + action node['logrotate']['package']['action'] +end + +directory node['logrotate']['directory'] do + owner 'root' + group node['root_group'] + mode '0755' +end + +if node['logrotate']['cron']['install'] # ~FC023 + cron node['logrotate']['cron']['name'] do + minute node['logrotate']['cron']['minute'] + hour node['logrotate']['cron']['hour'] + command node['logrotate']['cron']['command'] + end +end diff --git a/cookbooks/logrotate/recipes/global.rb b/cookbooks/logrotate/recipes/global.rb new file mode 100644 index 0000000..3dbf0a3 --- /dev/null +++ b/cookbooks/logrotate/recipes/global.rb @@ -0,0 +1,30 @@ +# +# Cookbook:: logrotate +# Recipe:: default +# +# Copyright:: 2009-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'logrotate::default' + +parsed_configuration = CookbookLogrotate::LogrotateConfiguration.from_hash(node['logrotate']['global'].to_hash) + +template '/etc/logrotate.conf' do + source 'logrotate-global.erb' + mode '0644' + variables( + configuration: parsed_configuration + ) +end diff --git a/cookbooks/logrotate/resources/app.rb b/cookbooks/logrotate/resources/app.rb new file mode 100644 index 0000000..0958e69 --- /dev/null +++ b/cookbooks/logrotate/resources/app.rb @@ -0,0 +1,116 @@ +# +# Copyright:: 2016-2017, Steven Danna +# +# 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. +# + +resource_name :logrotate_app + +property :path, [String, Array], required: true +property :frequency, String, default: 'weekly' +property :cookbook, default: 'logrotate' +property :template_name, default: 'logrotate.erb' +property :template_mode, default: '0644' +property :template_owner, default: 'root' +property :template_group, default: 'root' +property :base_dir, String, default: '/etc/logrotate.d' + +property :options, [Array, String], default: %w(missingok compress delaycompress copytruncate notifempty) + +default_action :enable + +CookbookLogrotate::SCRIPTS.each do |script_name| + property script_name.to_sym, coerce: proc { |val| Array(val).join("\n") } +end + +CookbookLogrotate::VALUES.each do |configurable_name| + property configurable_name.to_sym +end + +# Deprecated options +property :sharedscripts, [TrueClass, FalseClass], default: false +property :enable, [TrueClass, FalseClass], default: true + +action :enable do + unless new_resource.enable + Chef::Log.deprecation 'Use `action :disable` rather than `enable false` in the logrotate_app resource' + action_disable + return true + end + + logrotate_config = { + # The path should be a space separated list of quoted filesystem paths + path: Array(new_resource.path).map { |path| path.to_s.inspect }.join(' '), + frequency: new_resource.frequency, + directives: handle_options(new_resource), + scripts: handle_scripts(new_resource), + configurables: handle_configurables(new_resource), + } + + directory new_resource.base_dir do + owner 'root' + group node['root_group'] + mode '0755' + action :create + end + + template "#{new_resource.base_dir}/#{new_resource.name}" do + source new_resource.template_name + cookbook new_resource.cookbook + mode new_resource.template_mode + owner new_resource.template_owner + group new_resource.template_group + backup false + variables logrotate_config + end +end + +action :disable do + file "#{new_resource.base_dir}/#{new_resource.name}" do + action :delete + end +end + +def handle_configurables(new_resource) + configurables = {} + CookbookLogrotate::VALUES.each do |opt_name| + if value = new_resource.send(opt_name.to_sym) # rubocop: disable Lint/AssignmentInCondition + configurables[opt_name] = value + end + end + configurables +end + +def handle_scripts(new_resource) + scripts = {} + CookbookLogrotate::SCRIPTS.each do |script_name| + if script_body = new_resource.send(script_name.to_sym) # rubocop: disable Lint/AssignmentInCondition + scripts[script_name] = script_body + end + end + scripts +end + +def handle_options(new_resource) + opts = if new_resource.options.is_a?(Array) + new_resource.options.dup + else + new_resource.options.split + end + + if new_resource.sharedscripts + Chef::Log.deprecation('The sharedscripts resource property is deprecated. Use the options property instead to set this value') + opts << 'sharedscripts' + end + opts +end diff --git a/cookbooks/logrotate/templates/default/logrotate-global.erb b/cookbooks/logrotate/templates/default/logrotate-global.erb new file mode 100644 index 0000000..f59eda0 --- /dev/null +++ b/cookbooks/logrotate/templates/default/logrotate-global.erb @@ -0,0 +1,35 @@ +# This file was generated by Chef for <%= node['fqdn'] %>. +# Do not modify this file by hand! + +<% @configuration.directives.each do |d| -%> +<%= d %> +<% end -%> + +<% @configuration.values.each do |k, v| -%> +<%= k %> <%= v %> +<% end -%> + +<% @configuration.scripts.each do | scripttype, body | -%> +<%= scripttype %> +<%= body %> +endscript +<% end -%> + +include /etc/logrotate.d + +<% @configuration.paths.each do |path, path_config| -%> +<%= path %> { + <% path_config['directives'].each do |d|-%> + <%= d %> + <% end -%> + <% path_config['values'].each do | k, v | -%> + <%= k %> <%= v %> + <% end -%> + <% path_config['scripts'].each do | scripttype, body | -%> + <%= scripttype %> + <%= body %> + endscript + <% end -%> +} + +<% end -%> diff --git a/cookbooks/logrotate/templates/default/logrotate.erb b/cookbooks/logrotate/templates/default/logrotate.erb new file mode 100644 index 0000000..3e838cd --- /dev/null +++ b/cookbooks/logrotate/templates/default/logrotate.erb @@ -0,0 +1,19 @@ +# This file was generated by Chef for <%= node['fqdn'] %>. +# Do not modify this file by hand! + +<%= @path %> { +<%- if @frequency %> + <%= @frequency %> +<%- end %> +<%- @configurables.each do |name, value| %> + <%= "#{name} #{value}" %> +<%- end %> +<% @directives.each do |o| -%> + <%= o %> +<% end -%> +<%- @scripts.each do |script_name, script| %> + <%= script_name %> + <%= script %> + endscript +<%- end %> +} diff --git a/cookbooks/mariadb/CHANGELOG.md b/cookbooks/mariadb/CHANGELOG.md new file mode 100644 index 0000000..d19b938 --- /dev/null +++ b/cookbooks/mariadb/CHANGELOG.md @@ -0,0 +1,132 @@ +mariadb CHANGELOG +================= + +This file is used to list changes made in each version of the mariadb cookbook. + +0.3.1 +----- +- [BUG #76] - Service is restarted every run if not localhost +- [BUG #73] - Fix directory permissions regression +- [BUG #69] - Update repository.rb to be able to manage Scientific Linux +- [BUG #57] - Add user and password to correct debian-grants +- [ENH #71] - Add xtrabackup-v2 support for SST Method +- [ENH #62] - Allow Galera cluster nodes to be configured when using Chef Solo +- [ENH #64] - Add a vagrant config to test a galera cluster +- [BUG #66] - mariadb_configuration template uses current cookbook as template source +- [BUG #68] - Correct service name inconsistency on CentOS 7 + +0.3.0 +------ +- [ENH] - Add support for using operating system shipped mariadb packages + +0.2.12 +------ +- [BUG #39] - Push gpg key adds through http/80 - Helps with firewalled installs +- [ENH #46] - Add cookbook attribute on configuration lwrp +- [ENH #47] - Allow to pass true for unary options +- [BUG #48] - Load the needed plugins at startup + +0.2.11 +------ +- [ENH #38] - Add CentOS support +- [ENH #40] - Add sensitive flag to resource that deal with passwords +- [BUG #43] - Fix convert TypeError in the replication provider + +0.2.10 +------ +- [BUG] - Audit Plugin test and installation - Correct bad notifies, and stdout test + +0.2.9 +----- +- [BUG #36] - Audit plugin installation can crash mariadb server + +0.2.8 +----- +- [BUG #30] - When using galera, nodes were not sorted, applying configuration change too often +- [BUG #31] - ChefSpec coverage was not 100% +- [BUG #28] - Remove the only_if to mysql service +- [BUG #29] - Add a switch to not launch audit plugin install, when already installed +- [ENH] - Add a switch to separate server install and audit install when needed +- [ENH] - Add a rule to authorize line length to be 120 characters long + +0.2.7 +----- +- [BUG #24] - Fix convert TypeError in the replication provider +- [BUG #25] - Data are now moved when default datadir is changed +- [ENH #21] - Add audit_plugin management + +0.2.6 +----- +- [BUG #18] - Fix provider mariadb_replication compilation error +- [DOCS] - Complete Changelog, and correct README + +0.2.5 +----- +- [ENH #16] - Add a LWRP to manage replication slave +- [ENH #17] - Be able to not install development files within client recipe +- [ENH #11] - Fix the galera root password preseed +- [BUG #12] - Fix the debian-sys-maint user creation/password change +- [BUG #6] - Can change the apt repository base_url when the default one fail +- [TEST] - Add new tests for the new features (galera,development files install,replication LWRP) +- [DOCS] - Complete Changelog, and add new features explanations into README + +0.2.4 +----- +- [BUG #10] - Correct a FC004 broken rule +- [BUG #9] - Correct foodcritic tests (add --epic-fail any to be sure it fails when a broken rule is detected) + +0.2.3 +----- +- [BUG #4] - Add a real management of mysql root password +- [ENH #5] - Now restart mysql service when port is changed +- [ENH #7] - Remove or add root remote access via attribute +- [DOCS] - Complete documentations +- [TEST] - Add a lot of chefspec and kitchen/serverspec tests + +0.2.2 +----- +- [sinfomicien] - Correct repository install under debian family +- [sinfomicien] - Correct client install to add dev files +- [sinfomicien] - Correct and add multiples tests + +0.2.1 +----- +- [sinfomicien] - Use stove to package (remove PaxHeaders.*) + +0.2.0 +----- +- [sinfomicien] - Add rpm/yum management +- [sinfomicien] - Refactor the whole recipes list and management to ease it +- [sinfomicien] - Correct the Documentation +- [sinfomicien] - Rename the provider (from extraconf to configuration), and add matchers to it +- [sinfomicien] - Add a recipe to manage client only installation +- [sinfomicien] - Refactor all tests to manage new platform (centos/redhat/fedora) + +0.1.8 +----- +- [sinfomicien] - Add ignore-failure to debian grants correct, as it can break on initial setup + +0.1.7 +----- +- [sinfomicien] - Correct a typo (unnecessary call to run_command) + +0.1.6 +----- +- [sinfomicien] - improve Galera configuration management +- [sinfomicien] - Add new rspec tests +- [sinfomicien] - Create Kitchen test suite + +0.1.5 +----- +- [sinfomicien] - improve attributes management + +0.1.4 +----- +- [sinfomicien] - adapt galera55 recipe to use a generic galera recipe +- [sinfomicien] - use a generic galera recipe to create the galera10 recipe +- [sinfomicien] - Improve documentation + + +0.1.0 +----- +- [sinfomicien] - Initial release of mariadb diff --git a/cookbooks/mariadb/README.md b/cookbooks/mariadb/README.md new file mode 100644 index 0000000..01fdaea --- /dev/null +++ b/cookbooks/mariadb/README.md @@ -0,0 +1,207 @@ +MariaDB Cookbook +================ + +[![Build Status](https://travis-ci.org/sinfomicien/mariadb.png)](https://travis-ci.org/sinfomicien/mariadb) + +Description +----------- + +This cookbook contains all the stuffs to install and configure a mariadb server on a dpkg/apt compliant system (typically debian), or a rpm/yum compliant system (typically centos) + + +Requirements +------------ + +#### repository +- `mariadb` - This cookbook need that you have a valid apt repository installed with the mariadb official packages + +#### packages +- `percona-xtrabackup` - if you want to use the xtrabckup SST Auth for galera cluster. +- `socat` - if you want to use the xtrabckup SST Auth for galera cluster. +- `rsync` - if you want to use the rsync SST Auth for galera cluster. +- `debconf-utils` - if you use debian platform family. + +#### operating system +- `debian` - this cookbook is fully tested on debian +- `ubuntu` - not fully tested on ubuntu, but should work +- `centos` - not fully tested on centos, but should work + +Attributes +---------- + +#### mariadb::default + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyTypeDescriptionDefault
['mariadb']['install']['version']StringVersion to install (currently 10.0 et 5.5)10.0
['mariadb']['use_default_repository']BooleanWether to install MariaDB default repository or not. If you don't have a local repo containing packages, put it to truefalse
['mariadb']['server_root_password']Stringlocal root password
['mariadb']['forbid_remote_root']BooleanWether to activate root remote accesstrue
['mariadb']['allow_root_pass_change']BooleanWether to allow the recipe to change root password after the first installfalse
['mariadb']['client']['development_files']BooleanWether to install development files in client recipetrue
['mariadb']['apt_repository']['base_url']StringThe http base url to use when installing from default repository'ftp.igh.cnrs.fr/pub/mariadb/repo'
['mariadb']['install']['prefer_os_package']BooleanIndicator for preferring use packages shipped by running osfalse
+ +Usage +----- + +To install a default server for mariadb choose the version you want (MariaDB 5.5 or 10, galera or not), then call the recipe accordingly. + +List of availables recipes: + +- mariadb::default (just call server recipe with default options) +- mariadb::server +- mariadb::galera +- mariadb::client + +Please be ware that by default, the root password is empty! If you want have changed it use the `node['mariadb']['server_root_password']` attribute to put a correct value. And by default the remote root access is not activated. Use `node['mariadb']['forbid_remote_root']` attribute to change it. + +Sometimes, the default apt repository used for apt does not work (see issue #6). In this case, you need to choose another mirror which worki (pick it from mariadb website), and put the http base url in the attribute `node['mariadb']['apt_repository']['base_url']`. + +#### mariadb::galera + +When installing the mariadb::galera on debian recipe, You have to take care of one specific attribute: +`node['mariadb']['debian']['password']` which default to 'please-change-me' +As wee need to have the same password for this user on the whole cluster nodes... We will change the default install one by the content of this attribute. + +#### mariadb::client + +By default this recipe install the client, and all needed packages to develop client application. If you do not want to install development files when installing client package, +set the attribute `node['mariadb']['client']['development_files']` to false. + +Providers +---------- + +This recipe define 2 providers: +- `Chef::Provider::Mariadb::Configuration` shortcut resource `mariadb_configuration` +- `Chef::Provider::Mariadb::Replication` shortcut resource `mariadb_replication` + +#### mariadb_configuration + +Mainly use for internal purpose. You can use it to create a new configuration file into configuration dir. You have to define 2 variables `section` and `option`. +Where `section` is the configuration section, and `option` is a hash of key/value. The name of the resource is used as base for the filename. + +Example: +```ruby +mariadb_configuration 'fake' do + section 'mysqld' + option {foo: 'bar'} +end +``` +will become the file fake.cnf in the include dir (depend on your platform), which contain: +``` +[mysqld] +foo=bar +``` + +If the value start with a '#', then it's considered as a comment, and the value is printed as is (without the key) + +Example: +```ruby +mariadb_configuration 'fake' do + section 'mysqld' + option {comment1: '# Here i am', foo: bar} +end +``` +will become the file fake.cnf in the include dir (depend on your platform), which contain: +``` +[mysqld] +# Here i am +foo=bar +``` + +#### mariadb_replication + +This LWRP is used to manage replication setup on a host. To use this LWRP, the node need to have the mysql binary installed (via the mariadb::client or mariadb::server or mariadb::galera recipe). +It have 4 actions: +- add - to add a new replication setup (become a slave) +- stop - to stop the slave replication +- start - to start the slave replication +- remove - to remove the slave replication configuration + +The resource name need to be 'default' if your don't want to use a named connection (multi source replication in MariaDB 10). + +So by default the provider try to use the local instance of mysql, with the current user and no password. If you want to change, you have to define `host`, `port`, `user` or `password` + +```ruby +mariadb_replication 'default' do + user 'root' + password 'fakepass' + host 'fakehost' + action :stop +end +``` +will stop the replication on the host `fakehost` using the user `root` and password `fakepass` to connect to. + +When you add a replication configuration, you have to define at least 4 values `master_host`, `master_user`, `master_password` and `master_use_gtid`. And if you don't want the GTID support, you have to define also `master_log_file` and `master_log_pos` + +Example: +```ruby +mariadb_replication 'usefull_conn_name' do + master_host 'server1' + master_user 'slave_user' + master_password 'slave_password' + master_use_gtid 'current_pos' + action :add +end +``` + +Contributing +------------ + +1. Fork the repository on Github +2. Create a named feature branch (like `add_component_x`) +3. Write your change +4. Write tests for your change (if applicable) +5. Run the tests, ensuring they all pass +6. Submit a Pull Request using Github + +License and Authors +------------------- +Authors: +Nicolas Blanc diff --git a/cookbooks/mariadb/attributes/default.rb b/cookbooks/mariadb/attributes/default.rb new file mode 100644 index 0000000..7523035 --- /dev/null +++ b/cookbooks/mariadb/attributes/default.rb @@ -0,0 +1,164 @@ +# platform dependent attributes +case node['platform'] +when 'redhat', 'centos', 'fedora', 'scientific', 'amazon' + default['mariadb']['configuration']['path'] = '/etc' + default['mariadb']['configuration']['includedir'] = '/etc/my.cnf.d' + default['mariadb']['mysqld']['socket'] = '/var/lib/mysql/mysql.sock' + default['mariadb']['client']['socket'] = '/var/lib/mysql/mysql.sock' + default['mariadb']['mysqld_safe']['socket'] = '/var/lib/mysql/mysql.sock' +else + default['mariadb']['configuration']['path'] = '/etc/mysql' + default['mariadb']['configuration']['includedir'] = '/etc/mysql/conf.d' + default['mariadb']['mysqld']['socket'] = '/var/run/mysqld/mysqld.sock' + default['mariadb']['mysqld']['pid_file'] = '/var/run/mysqld/mysqld.pid' + default['mariadb']['client']['socket'] = '/var/run/mysqld/mysqld.sock' + default['mariadb']['mysqld_safe']['socket'] = '/var/run/mysqld/mysqld.sock' +end + +# +# mysqld default configuration +# +default['mariadb']['forbid_remote_root'] = true +default['mariadb']['server_root_password'] = '' +default['mariadb']['allow_root_pass_change'] = false +if node['platform'] == 'centos' + default['mariadb']['mysqld']['service_name'] = 'mariadb' +else + default['mariadb']['mysqld']['service_name'] = 'mysql' +end +default['mariadb']['mysqld']['user'] = 'mysql' +default['mariadb']['mysqld']['port'] = '3306' +default['mariadb']['mysqld']['basedir'] = '/usr' +default['mariadb']['mysqld']['default_datadir'] = '/var/lib/mysql' +# if different from previous value, datadir will be moved after install +default['mariadb']['mysqld']['datadir'] = '/var/lib/mysql' +default['mariadb']['mysqld']['tmpdir'] = '/var/tmp' +default['mariadb']['mysqld']['lc_messages_dir'] = '/usr/share/mysql' +default['mariadb']['mysqld']['lc_messages'] = 'en_US' +default['mariadb']['mysqld']['skip_external_locking'] = 'true' +default['mariadb']['mysqld']['bind_address'] = '127.0.0.1' +default['mariadb']['mysqld']['max_connections'] = '100' +default['mariadb']['mysqld']['connect_timeout'] = '5' +default['mariadb']['mysqld']['wait_timeout'] = '600' +default['mariadb']['mysqld']['max_allowed_packet'] = '16M' +default['mariadb']['mysqld']['thread_cache_size'] = '128' +default['mariadb']['mysqld']['sort_buffer_size'] = '4M' +default['mariadb']['mysqld']['bulk_insert_buffer_size'] = '16M' +default['mariadb']['mysqld']['tmp_table_size'] = '32M' +default['mariadb']['mysqld']['max_heap_table_size'] = '32M' +default['mariadb']['mysqld']['myisam_recover'] = 'BACKUP' +default['mariadb']['mysqld']['key_buffer_size'] = '128M' +# if not defined default is 2000 +default['mariadb']['mysqld']['open_files_limit'] = '' +default['mariadb']['mysqld']['table_open_cache'] = '400' +default['mariadb']['mysqld']['myisam_sort_buffer_size'] = '512M' +default['mariadb']['mysqld']['concurrent_insert'] = '2' +default['mariadb']['mysqld']['read_buffer_size'] = '2M' +default['mariadb']['mysqld']['read_rnd_buffer_size'] = '1M' +default['mariadb']['mysqld']['query_cache_limit'] = '128K' +default['mariadb']['mysqld']['query_cache_size'] = '64M' +# if not defined default is ON +default['mariadb']['mysqld']['query_cache_type'] = '' +default['mariadb']['mysqld']['default_storage_engine'] = 'InnoDB' +default['mariadb']['mysqld']['options'] = {} + +# +# InnoDB default configuration +# +# if not defined default is 50M +default['mariadb']['innodb']['log_file_size'] = '' +default['mariadb']['innodb']['bps_percentage_memory'] = false +default['mariadb']['innodb']['buffer_pool_size'] = '256M' +default['mariadb']['innodb']['log_buffer_size'] = '8M' +default['mariadb']['innodb']['file_per_table'] = '1' +default['mariadb']['innodb']['open_files'] = '400' +default['mariadb']['innodb']['io_capacity'] = '400' +default['mariadb']['innodb']['flush_method'] = 'O_DIRECT' +default['mariadb']['innodb']['options'] = {} + +# +# Galera default configuration +# +default['mariadb']['galera']['cluster_name'] = 'galera_cluster' +default['mariadb']['galera']['cluster_search_query'] = '' +default['mariadb']['galera']['wsrep_sst_method'] = 'rsync' +default['mariadb']['galera']['wsrep_provider'] = \ + '/usr/lib/galera/libgalera_smm.so' +default['mariadb']['galera']['options'] = {} + +# Node format: [{ :name => "mariadb_1", fqdn: "33.33.33.11"}] +default['mariadb']['galera']['cluster_nodes'] = [] + +# +# Replication default configuration +# +default['mariadb']['replication']['server_id'] = '' +default['mariadb']['replication']['log_bin'] = \ + '/var/log/mysql/mariadb-bin' +default['mariadb']['replication']['log_bin_index'] = \ + '/var/log/mysql/mariadb-bin.index' +default['mariadb']['replication']['expire_logs_days'] = '10' +default['mariadb']['replication']['max_binlog_size'] = '100M' +default['mariadb']['replication']['options'] = {} + +# +# mysqldump default configuration +# +default['mariadb']['mysqldump']['quick'] = 'true' +default['mariadb']['mysqldump']['quote_names'] = 'true' +default['mariadb']['mysqldump']['max_allowed_packet'] = '16M' + +# +# isamchk default configuration +default['mariadb']['isamchk']['key_buffer'] = '16M' + +# +# mysqld_safe default configuration +# +default['mariadb']['mysqld_safe']['options'] = {} + +# +# client default configuration +# +default['mariadb']['client']['port'] = 3306 +default['mariadb']['client']['options'] = {} +default['mariadb']['client']['development_files'] = true + +# +# debian specific configuration +# +default['mariadb']['debian']['user'] = 'debian-sys-maint' +default['mariadb']['debian']['password'] = 'please-change-me' +default['mariadb']['debian']['host'] = 'localhost' + +# +# mariadb default install configuration +# +# install valid value is 'package', +# hope to have 'from_source' in the near future +default['mariadb']['install']['type'] = 'package' +default['mariadb']['install']['version'] = '10.0' +default['mariadb']['install']['prefer_os_package'] = false + +# +# package(apt or yum) default configuration +# +default['mariadb']['use_default_repository'] = false +default['mariadb']['apt_repository']['base_url'] = \ + 'ftp.igh.cnrs.fr/pub/mariadb/repo' + +# +# MariaDB Plugins enabling +# +default['mariadb']['plugins_options']['auto_install'] = true +# Enabling Plugin Installation +default['mariadb']['plugins']['audit'] = false +# Load Plugins in .cnf (plugin-loadi variable) +default['mariadb']['plugins_loading']['audit'] = 'server_audit=server_audit.so' + +# Default Configuration +default['mariadb']['audit_plugin']['server_audit_events'] = '' +default['mariadb']['audit_plugin']['server_audit_output_type'] = 'file' +# Syslog (require server_audit_output_type = syslog) +default['mariadb']['audit_plugin']['server_audit_syslog_facility'] = 'LOG_USER' +default['mariadb']['audit_plugin']['server_audit_syslog_priority'] = 'LOG_INFO' diff --git a/cookbooks/mariadb/libraries/mariadb_helper.rb b/cookbooks/mariadb/libraries/mariadb_helper.rb new file mode 100644 index 0000000..8e8e706 --- /dev/null +++ b/cookbooks/mariadb/libraries/mariadb_helper.rb @@ -0,0 +1,78 @@ +# MariaDB is a module containing mariadb cookbook helper +module MariaDB + # Helper module for mariadb cookbook + module Helper + require 'socket' + require 'timeout' + + def do_port_connect(ip, port) + s = TCPSocket.new(ip, port) + s.close + true + rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH + false + end + + def port_open?(ip, port) + begin + Timeout.timeout(5) do + return do_port_connect(ip, port) + end + rescue Timeout::Error + false + end + false + end + + # Trying to determine if we need to restart the mysql service + def mariadb_service_restart_required?(ip, port, _socket) + restart = false + restart = true unless port_open?(ip, port) + restart + end + + # Helper to determine if running operating system shipped a package for + # mariadb server & client. No galera shipped in any os yet. + # @param [String] os_platform Indicate operating system type, e.g. centos + # @param [String] os_version Indicate operating system version, e.g. 7.0 + def os_package_provided?(os_platform, os_version) + package_provided = false + case os_platform + when 'centos', 'redhat' + package_provided = true if os_version.to_i == 7 + when 'fedora' + package_provided = true if os_version.to_i >= 19 + end + package_provided + end + + # Helper to determine mariadb server service name shipped by native package + # If no native package available on this platform, return nil + # @param [String] os_platform Indicate operating system type, e.g. centos + # @param [String] os_version Indicate operating system version, e.g. 7.0 + def os_service_name(os_platform, os_version) + return nil unless os_package_provided?(os_platform, os_version) + service_name = 'mariadb' + if os_platform == 'fedora' && os_version.to_i >= 19 + service_name = 'mysqld' + end + service_name + end + + # Helper to determine whether to use os native package + # @param [Boolean] prefer_os Indicate whether to prefer os native package + # @param [String] os_platform Indicate operating system type, e.g. centos + # @param [String] os_version Indicate operating system version, e.g. 7.0 + def use_os_native_package?(prefer_os, os_platform, os_version) + return false unless prefer_os + if os_package_provided?(os_platform, os_version) + true + else + Chef::Log.warn 'prefer_os_package detected, but no native mariadb'\ + " package available on #{os_platform}-#{os_version}."\ + ' Fall back to use community package.' + false + end + end + end +end diff --git a/cookbooks/mariadb/libraries/matchers.rb b/cookbooks/mariadb/libraries/matchers.rb new file mode 100644 index 0000000..91f1cc1 --- /dev/null +++ b/cookbooks/mariadb/libraries/matchers.rb @@ -0,0 +1,21 @@ +if defined?(ChefSpec) + def add_mariadb_configuration(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:mariadb_configuration, :add, resource_name) + end + + def remove_mariadb_configuration(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:mariadb_configuration, :remove, resource_name) + end + + def add_mariadb_replication(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:mariadb_replication, :add, resource_name) + end + + def remove_mariadb_replication(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:mariadb_replication, :remove, resource_name) + end +end diff --git a/cookbooks/mariadb/metadata.json b/cookbooks/mariadb/metadata.json new file mode 100644 index 0000000..049ad57 --- /dev/null +++ b/cookbooks/mariadb/metadata.json @@ -0,0 +1 @@ +{"name":"mariadb","version":"0.3.1","description":"Installs/Configures MariaDB","long_description":"MariaDB Cookbook\n================\n\n[![Build Status](https://travis-ci.org/sinfomicien/mariadb.png)](https://travis-ci.org/sinfomicien/mariadb)\n\nDescription\n-----------\n\nThis cookbook contains all the stuffs to install and configure a mariadb server on a dpkg/apt compliant system (typically debian), or a rpm/yum compliant system (typically centos)\n\n\nRequirements\n------------\n\n#### repository\n- `mariadb` - This cookbook need that you have a valid apt repository installed with the mariadb official packages\n\n#### packages\n- `percona-xtrabackup` - if you want to use the xtrabckup SST Auth for galera cluster.\n- `socat` - if you want to use the xtrabckup SST Auth for galera cluster.\n- `rsync` - if you want to use the rsync SST Auth for galera cluster.\n- `debconf-utils` - if you use debian platform family.\n\n#### operating system\n- `debian` - this cookbook is fully tested on debian\n- `ubuntu` - not fully tested on ubuntu, but should work\n- `centos` - not fully tested on centos, but should work\n\nAttributes\n----------\n\n#### mariadb::default\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
KeyTypeDescriptionDefault
['mariadb']['install']['version']StringVersion to install (currently 10.0 et 5.5)10.0
['mariadb']['use_default_repository']BooleanWether to install MariaDB default repository or not. If you don't have a local repo containing packages, put it to truefalse
['mariadb']['server_root_password']Stringlocal root password
['mariadb']['forbid_remote_root']BooleanWether to activate root remote accesstrue
['mariadb']['allow_root_pass_change']BooleanWether to allow the recipe to change root password after the first installfalse
['mariadb']['client']['development_files']BooleanWether to install development files in client recipetrue
['mariadb']['apt_repository']['base_url']StringThe http base url to use when installing from default repository'ftp.igh.cnrs.fr/pub/mariadb/repo'
['mariadb']['install']['prefer_os_package']BooleanIndicator for preferring use packages shipped by running osfalse
\n\nUsage\n-----\n\nTo install a default server for mariadb choose the version you want (MariaDB 5.5 or 10, galera or not), then call the recipe accordingly.\n\nList of availables recipes:\n\n- mariadb::default (just call server recipe with default options)\n- mariadb::server\n- mariadb::galera\n- mariadb::client\n\nPlease be ware that by default, the root password is empty! If you want have changed it use the `node['mariadb']['server_root_password']` attribute to put a correct value. And by default the remote root access is not activated. Use `node['mariadb']['forbid_remote_root']` attribute to change it.\n\nSometimes, the default apt repository used for apt does not work (see issue #6). In this case, you need to choose another mirror which worki (pick it from mariadb website), and put the http base url in the attribute `node['mariadb']['apt_repository']['base_url']`.\n\n#### mariadb::galera\n\nWhen installing the mariadb::galera on debian recipe, You have to take care of one specific attribute:\n`node['mariadb']['debian']['password']` which default to 'please-change-me'\nAs wee need to have the same password for this user on the whole cluster nodes... We will change the default install one by the content of this attribute.\n\n#### mariadb::client\n\nBy default this recipe install the client, and all needed packages to develop client application. If you do not want to install development files when installing client package,\nset the attribute `node['mariadb']['client']['development_files']` to false. \n\nProviders\n----------\n\nThis recipe define 2 providers:\n- `Chef::Provider::Mariadb::Configuration` shortcut resource `mariadb_configuration`\n- `Chef::Provider::Mariadb::Replication` shortcut resource `mariadb_replication`\n\n#### mariadb_configuration\n\nMainly use for internal purpose. You can use it to create a new configuration file into configuration dir. You have to define 2 variables `section` and `option`.\nWhere `section` is the configuration section, and `option` is a hash of key/value. The name of the resource is used as base for the filename.\n\nExample:\n```ruby\nmariadb_configuration 'fake' do\n section 'mysqld'\n option {foo: 'bar'}\nend\n```\nwill become the file fake.cnf in the include dir (depend on your platform), which contain:\n```\n[mysqld]\nfoo=bar\n```\n\nIf the value start with a '#', then it's considered as a comment, and the value is printed as is (without the key)\n\nExample:\n```ruby\nmariadb_configuration 'fake' do\n section 'mysqld'\n option {comment1: '# Here i am', foo: bar}\nend\n```\nwill become the file fake.cnf in the include dir (depend on your platform), which contain:\n```\n[mysqld]\n# Here i am\nfoo=bar\n```\n\n#### mariadb_replication\n\nThis LWRP is used to manage replication setup on a host. To use this LWRP, the node need to have the mysql binary installed (via the mariadb::client or mariadb::server or mariadb::galera recipe).\nIt have 4 actions:\n- add - to add a new replication setup (become a slave)\n- stop - to stop the slave replication\n- start - to start the slave replication\n- remove - to remove the slave replication configuration\n\nThe resource name need to be 'default' if your don't want to use a named connection (multi source replication in MariaDB 10).\n\nSo by default the provider try to use the local instance of mysql, with the current user and no password. If you want to change, you have to define `host`, `port`, `user` or `password`\n\n```ruby\nmariadb_replication 'default' do\n user 'root'\n password 'fakepass'\n host 'fakehost'\n action :stop\nend\n```\nwill stop the replication on the host `fakehost` using the user `root` and password `fakepass` to connect to.\n\nWhen you add a replication configuration, you have to define at least 4 values `master_host`, `master_user`, `master_password` and `master_use_gtid`. And if you don't want the GTID support, you have to define also `master_log_file` and `master_log_pos`\n\nExample:\n```ruby\nmariadb_replication 'usefull_conn_name' do\n master_host 'server1'\n master_user 'slave_user'\n master_password 'slave_password'\n master_use_gtid 'current_pos'\n action :add\nend\n```\n\nContributing\n------------\n\n1. Fork the repository on Github\n2. Create a named feature branch (like `add_component_x`)\n3. Write your change\n4. Write tests for your change (if applicable)\n5. Run the tests, ensuring they all pass\n6. Submit a Pull Request using Github\n\nLicense and Authors\n-------------------\nAuthors:\nNicolas Blanc \n","maintainer":"Nicolas Blanc","maintainer_email":"sinfomicien@gmail.com","license":"Apache 2.0","platforms":{"ubuntu":">= 0.0.0","debian":">= 7.0","centos":">= 6.4","redhat":">= 7.0"},"dependencies":{"apt":">= 0.0.0","yum":">= 0.0.0","yum-epel":">= 0.0.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file diff --git a/cookbooks/mariadb/providers/configuration.rb b/cookbooks/mariadb/providers/configuration.rb new file mode 100644 index 0000000..46adea3 --- /dev/null +++ b/cookbooks/mariadb/providers/configuration.rb @@ -0,0 +1,38 @@ +# +# Cookbook Name:: mariadb +# Provider:: configuration +# + +use_inline_resources if defined?(use_inline_resources) + +def whyrun_supported? + true +end + +action :add do + variables_hash = { + section: new_resource.section, + options: new_resource.option + } + template node['mariadb']['configuration']['includedir'] + \ + '/' + new_resource.name + '.cnf' do + source 'conf.d.generic.erb' + owner 'root' + group 'mysql' + mode '0640' + cookbook 'mariadb' + variables variables_hash + end +end + +action :remove do + if ::File.exist?(node['mariadb']['configuration']['includedir'] + \ + '/' + new_resource.name + '.cnf') + Chef::Log.info "Removing #{new_resource.name} repository from " + \ + node['mariadb']['configuration']['includedir'] + file node['mariadb']['configuration']['includedir'] + \ + '/' + new_resource.name + '.cnf' do + action :delete + end + end +end diff --git a/cookbooks/mariadb/providers/replication.rb b/cookbooks/mariadb/providers/replication.rb new file mode 100644 index 0000000..6470023 --- /dev/null +++ b/cookbooks/mariadb/providers/replication.rb @@ -0,0 +1,105 @@ +# +# Cookbook Name:: mariadb +# Provider:: replication +# + +use_inline_resources if defined?(use_inline_resources) + +def whyrun_supported? + true +end + +def get_mysql_command(host, port, user, password) + mysql_command = '/usr/bin/mysql' + mysql_command += ' -h ' + host unless host.nil? + mysql_command += ' -P ' + port unless port.nil? + mysql_command += ' -u ' + user unless user.nil? + mysql_command += ' -p' + password unless password.nil? + mysql_command +end + +action :add do + if new_resource.master_host.nil? || new_resource.master_user.nil? || + new_resource.master_password.nil? + fail '[ERROR] When adding a slave, you have to define master_host' \ + ' master_user and master_password !' + end + sql_string = 'CHANGE MASTER ' + sql_string += '\'' + new_resource.name + \ + '\' ' if new_resource.name != 'default' + sql_string += 'TO ' + sql_string += 'MASTER_HOST=\'' + new_resource.master_host + '\', ' + sql_string += 'MASTER_PORT=' + new_resource.master_port.to_s + \ + ', ' unless new_resource.master_port.nil? + sql_string += 'MASTER_USER=\'' + new_resource.master_user + '\', ' + sql_string += 'MASTER_PASSWORD=\'' + new_resource.master_password + '\'' + if new_resource.master_use_gtid == 'no' + # Use non GTID replication setup + if new_resource.master_log_file.nil? || new_resource.master_log_pos.nil? + fail '[ERROR] When adding a slave without GTID, you have to' \ + 'define master_log_file and master_log_pos !' + end + unless new_resource.master_log_file.nil? + sql_string += ', MASTER_LOG_FILE=\'' + \ + new_resource.master_log_file + '\'' + sql_string += ', MASTER_LOG_POS=' + new_resource.master_log_pos.to_s + end + else + # Use GTID replication + sql_string += ', MASTER_USE_GTID=' + new_resource.master_use_gtid + ';' + end + execute 'add_replication_from_master_' + new_resource.name do + # Add sensitive true when foodcritic #233 fixed + command '/bin/echo "' + sql_string + '" | ' + get_mysql_command( + new_resource.host, + new_resource.port, + new_resource.user, + new_resource.password + ) + action :run + end +end + +action :remove do + execute 'remove_replication_from_master_' + new_resource.name do + # Add sensitive true when foodcritic #233 fixed + command '/bin/echo "STOP SLAVE \'' + new_resource.name + '\'; ' \ + 'RESET SLAVE \'' + new_resource.name + '\' ALL' \ + ';" | ' + get_mysql_command( + new_resource.host, + new_resource.port, + new_resource.user, + new_resource.password + ) + end +end + +action :start do + command_master_connection = ' \'' + new_resource.name + \ + '\'' unless new_resource.name == 'default' + execute 'start_replication_from_master_' + new_resource.name do + # Add sensitive true when foodcritic #233 fixed + command '/bin/echo "START SLAVE' + command_master_connection + ';' \ + '" | ' + get_mysql_command( + new_resource.host, + new_resource.port, + new_resource.user, + new_resource.password + ) + end +end + +action :stop do + command_master_connection = ' \'' + new_resource.name + \ + '\'' unless new_resource.name == 'default' + execute 'start_replication_from_master_' + new_resource.name do + # Add sensitive true when foodcritic #233 fixed + command '/bin/echo "STOP SLAVE' + command_master_connection + ';' \ + '" | ' + get_mysql_command( + new_resource.host, + new_resource.port, + new_resource.user, + new_resource.password + ) + end +end diff --git a/cookbooks/mariadb/recipes/_audit_plugin.rb b/cookbooks/mariadb/recipes/_audit_plugin.rb new file mode 100644 index 0000000..9b8d030 --- /dev/null +++ b/cookbooks/mariadb/recipes/_audit_plugin.rb @@ -0,0 +1,53 @@ +# Prepare Configuration File +audit_plugin_options = {} + +audit_plugin_options['comment1'] = '#' +audit_plugin_options['comment2'] = '# * MariaDB Audit Plugin' +audit_plugin_options['comment3'] = '#' + +audit_plugin_options['server_audit_events'] = \ + node['mariadb']['audit_plugin']['server_audit_events'] +audit_plugin_options['server_audit_output_type'] = \ + node['mariadb']['audit_plugin']['server_audit_output_type'] +audit_plugin_options['server_audit_syslog_facility'] = \ + node['mariadb']['audit_plugin']['server_audit_syslog_facility'] +audit_plugin_options['server_audit_syslog_priority'] = \ + node['mariadb']['audit_plugin']['server_audit_syslog_priority'] + +audit_plugin_options['enable'] = '#server_audit_logging = ON' + +# Install the MariaDB Audit Plugin +execute 'install_mariadb_audit_plugin' do + command '/usr/bin/mysql -e "INSTALL PLUGIN server_audit '\ + 'SONAME \'server_audit\';"' + notifies :run, 'execute[configure_mariadb_audit_plugin]', :immediately + not_if do + cmd = Mixlib::ShellOut.new('/usr/bin/mysql -u root -B -N -e "SELECT 1 '\ + 'FROM information_schema.plugins '\ + 'WHERE PLUGIN_NAME = \'SERVER_AUDIT\''\ + 'AND PLUGIN_STATUS = \'ACTIVE\';"') + cmd.run_command + cmd.stdout.to_i == 1 + end +end + +# Configure (Dynamic) +execute 'configure_mariadb_audit_plugin' do + command 'echo "SET GLOBAL server_audit_events=\'' + \ + node['mariadb']['audit_plugin']['server_audit_events'] + '\';' \ + 'SET GLOBAL server_audit_output_type=\'' + \ + node['mariadb']['audit_plugin']['server_audit_output_type'] + '\';' \ + 'SET GLOBAL server_audit_syslog_facility=\'' + \ + node['mariadb']['audit_plugin']['server_audit_syslog_facility'] + '\';' \ + 'SET GLOBAL server_audit_syslog_priority=\'' + \ + node['mariadb']['audit_plugin']['server_audit_syslog_priority'] + '\';"' \ + '| /usr/bin/mysql' + action :nothing +end + +# Create Configuration File +mariadb_configuration 'audit_plugin' do + section 'mysqld' + option audit_plugin_options + action :add +end diff --git a/cookbooks/mariadb/recipes/_debian_galera.rb b/cookbooks/mariadb/recipes/_debian_galera.rb new file mode 100644 index 0000000..63531ea --- /dev/null +++ b/cookbooks/mariadb/recipes/_debian_galera.rb @@ -0,0 +1,55 @@ +# +# Cookbook Name:: mariadb +# Recipe:: _debian_galera +# +# Copyright 2014, blablacar.com +# +# 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. +# + +# To be sure that debconf is installed +package 'debconf-utils' do + action :install +end + +# Preseed Debian Package +# (but test for resource, as it can be declared by apt recipe) +begin + resources(directory: '/var/cache/local/preseeding') +rescue Chef::Exceptions::ResourceNotFound + directory '/var/cache/local/preseeding' do + owner 'root' + group 'root' + mode '0755' + recursive true + end +end + +template '/var/cache/local/preseeding/mariadb-galera-server.seed' do + source 'mariadb-server.seed.erb' + owner 'root' + group 'root' + mode '0600' + variables(package_name: 'mariadb-galera-server') + notifies :run, 'execute[preseed mariadb-galera-server]', :immediately +end + +execute 'preseed mariadb-galera-server' do + command '/usr/bin/debconf-set-selections ' \ + '/var/cache/local/preseeding/mariadb-galera-server.seed' + action :nothing +end + +package "mariadb-galera-server-#{node['mariadb']['install']['version']}" do + action :install +end diff --git a/cookbooks/mariadb/recipes/_debian_server.rb b/cookbooks/mariadb/recipes/_debian_server.rb new file mode 100644 index 0000000..4c17531 --- /dev/null +++ b/cookbooks/mariadb/recipes/_debian_server.rb @@ -0,0 +1,55 @@ +# +# Cookbook Name:: mariadb +# Recipe:: _debian_server +# +# Copyright 2014, blablacar.com +# +# 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. +# + +# To be sure that debconf is installed +package 'debconf-utils' do + action :install +end + +# Preseed Debian Package +# (but test for resource, as it can be declared by apt recipe) +begin + resources(directory: '/var/cache/local/preseeding') +rescue Chef::Exceptions::ResourceNotFound + directory '/var/cache/local/preseeding' do + owner 'root' + group 'root' + mode '0755' + recursive true + end +end + +template '/var/cache/local/preseeding/mariadb-server.seed' do + source 'mariadb-server.seed.erb' + owner 'root' + group 'root' + mode '0600' + variables(package_name: 'mariadb-server') + notifies :run, 'execute[preseed mariadb-server]', :immediately +end + +execute 'preseed mariadb-server' do + command '/usr/bin/debconf-set-selections ' \ + '/var/cache/local/preseeding/mariadb-server.seed' + action :nothing +end + +package "mariadb-server-#{node['mariadb']['install']['version']}" do + action :install +end diff --git a/cookbooks/mariadb/recipes/_redhat_galera.rb b/cookbooks/mariadb/recipes/_redhat_galera.rb new file mode 100644 index 0000000..8d725db --- /dev/null +++ b/cookbooks/mariadb/recipes/_redhat_galera.rb @@ -0,0 +1,49 @@ +# +# Cookbook Name:: mariadb +# Recipe:: _redhat_galera +# +# Copyright 2014, blablacar.com +# +# 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. +# + +# To force removing of mariadb-libs on CentOS >= 7 +package 'MariaDB-shared' do + action :install +end + +package 'MariaDB-Galera-server' do + action :install + notifies :create, 'directory[/var/log/mysql]', :immediately + notifies :start, 'service[mysql]', :immediately + notifies :run, 'execute[change first install root password]', :immediately +end + +directory '/var/log/mysql' do + action :nothing + user 'mysql' + group 'mysql' + mode '0755' +end + +service 'mysql' do + action :nothing +end + +execute 'change first install root password' do + # Add sensitive true when foodcritic #233 fixed + command '/usr/bin/mysqladmin -u root password \'' + \ + node['mariadb']['server_root_password'] + '\'' + action :nothing + not_if { node['mariadb']['server_root_password'].empty? } +end diff --git a/cookbooks/mariadb/recipes/_redhat_server.rb b/cookbooks/mariadb/recipes/_redhat_server.rb new file mode 100644 index 0000000..4c0805a --- /dev/null +++ b/cookbooks/mariadb/recipes/_redhat_server.rb @@ -0,0 +1,48 @@ +# +# Cookbook Name:: mariadb +# Recipe:: _redhat_server +# +# Copyright 2014, blablacar.com +# +# 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. +# + +# To force removing of mariadb-libs on CentOS >= 7 +package 'MariaDB-shared' do + action :install +end + +package 'MariaDB-server' do + action :install + notifies :create, 'directory[/var/log/mysql]', :immediately + notifies :start, 'service[mysql]', :immediately + notifies :run, 'execute[change first install root password]', :immediately +end + +directory '/var/log/mysql' do + action :nothing + user 'mysql' + group 'mysql' + mode '0755' +end + +execute 'change first install root password' do + # Add sensitive true when foodcritic #233 fixed + command '/usr/bin/mysqladmin -u root password \'' + \ + node['mariadb']['server_root_password'] + '\'' + action :nothing + not_if { node['mariadb']['server_root_password'].empty? } +end + +# Default policy for RH and fedora is to name it mysql +node.set['mariadb']['mysqld']['service_name'] = 'mysql' diff --git a/cookbooks/mariadb/recipes/_redhat_server_native.rb b/cookbooks/mariadb/recipes/_redhat_server_native.rb new file mode 100644 index 0000000..527a371 --- /dev/null +++ b/cookbooks/mariadb/recipes/_redhat_server_native.rb @@ -0,0 +1,45 @@ +# +# Cookbook Name:: mariadb +# Recipe:: _redhat_server_native +# +# 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. +# +# This recipe is for install and configure os shipped mariadb package + +Chef::Recipe.send(:include, MariaDB::Helper) + +service_name = os_service_name(node['platform'], node['platform_version']) +node.set['mariadb']['mysqld']['service_name'] = service_name\ + unless service_name.nil? + +package 'mariadb-server' do + action :install + notifies :enable, 'service[mysql]' +end + +directory '/var/log/mysql' do + action :create + user 'mysql' + group 'mysql' + mode '0755' + notifies :start, 'service[mysql]', :immediately + notifies :run, 'execute[change first install root password]', :immediately +end + +execute 'change first install root password' do + # Add sensitive true when foodcritic #233 fixed + command '/usr/bin/mysqladmin -u root password \'' + \ + node['mariadb']['server_root_password'] + '\'' + action :nothing + not_if { node['mariadb']['server_root_password'].empty? } +end diff --git a/cookbooks/mariadb/recipes/client.rb b/cookbooks/mariadb/recipes/client.rb new file mode 100644 index 0000000..a1296d2 --- /dev/null +++ b/cookbooks/mariadb/recipes/client.rb @@ -0,0 +1,89 @@ +# +# Cookbook Name:: mariadb +# Recipe:: client +# +# Copyright 2014, blablacar.com +# +# 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. +# + +Chef::Recipe.send(:include, MariaDB::Helper) +case node['mariadb']['install']['type'] +when 'package' + use_os_package = use_os_native_package?( + node['mariadb']['install']['prefer_os_package'], + node['platform'], + node['platform_version']) + + include_recipe "#{cookbook_name}::repository" unless use_os_package + + case node['platform_family'] + when 'rhel' + # On CentOS at least, there's a conflict between MariaDB and mysql-libs + package 'mysql-libs' do + action :remove + not_if { use_os_package } + end + + # rubocop:disable BlockNesting + if use_os_package + if node['mariadb']['client']['development_files'] + node.default['mariadb']['client']['packages'] = \ + %w(mariadb mariadb-devel) + else + node.default['mariadb']['client']['packages'] = \ + %w(mariadb) + end + else + if node['mariadb']['client']['development_files'] + node.default['mariadb']['client']['packages'] = \ + %w(MariaDB-client MariaDB-devel) + else + node.default['mariadb']['client']['packages'] = \ + %w(MariaDB-client) + end + end + # rubocop:enable BlockNesting + when 'fedora' + if node['mariadb']['client']['development_files'] + node.default['mariadb']['client']['packages'] = \ + %w(mariadb mariadb-devel) + else + node.default['mariadb']['client']['packages'] = \ + %w(mariadb) + end + when 'suse' + if node['mariadb']['client']['development_files'] + node.default['mariadb']['client']['packages'] = \ + %w(mariadb-community-server-client libmariadbclient-devel) + else + node.default['mariadb']['client']['packages'] = \ + %w(mariadb-community-server-client) + end + when 'debian' + if node['mariadb']['client']['development_files'] + node.default['mariadb']['client']['packages'] = \ + %W(mariadb-client-#{node['mariadb']['install']['version']} + libmariadbclient-dev) + else + node.default['mariadb']['client']['packages'] = \ + %W(mariadb-client-#{node['mariadb']['install']['version']}) + end + end + + node['mariadb']['client']['packages'].each do |name| + package name + end +when 'from_source' + # To be filled as soon as possible +end diff --git a/cookbooks/mariadb/recipes/config.rb b/cookbooks/mariadb/recipes/config.rb new file mode 100644 index 0000000..33ce0e1 --- /dev/null +++ b/cookbooks/mariadb/recipes/config.rb @@ -0,0 +1,95 @@ +# +# Cookbook Name:: mariadb +# Recipe:: config +# +# Copyright 2014, blablacar.com +# +# 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. +# + +template node['mariadb']['configuration']['path'] + '/my.cnf' do + source 'my.cnf.erb' + owner 'root' + group 'root' + mode '0644' +end + +innodb_options = {} + +innodb_options['comment1'] = '#' +innodb_options['comment2'] = '# * InnoDB' +innodb_options['comment3'] = '#' +innodb_options['comment4'] = '# InnoDB is enabled by default with a 10MB ' \ + 'datafile in /var/lib/mysql/.' +innodb_options['comment5'] = '# Read the manual for more InnoDB ' \ + 'related options. There are many!' + +innodb_options['innodb_log_file_size_comment1'] = '# you can\'t just ' \ + 'change log file size, ' \ + 'requires special procedure' +if node['mariadb']['innodb']['log_file_size'].empty? + innodb_options['innodb_log_file_size'] = '#innodb_log_file_size = 50M' +else + innodb_options['innodb_log_file_size'] = \ + node['mariadb']['innodb']['log_file_size'] +end +if node['mariadb']['innodb']['bps_percentage_memory'] + innodb_options['innodb_buffer_pool_size'] = ( + ( + node['mariadb']['innodb']['buffer_pool_size'].to_f * + (node['memory']['total'][0..-3].to_i / 1024) + ).round).to_s + 'M' +else + innodb_options['innodb_buffer_pool_size'] = \ + node['mariadb']['innodb']['buffer_pool_size'] +end +innodb_options['innodb_log_buffer_size'] = \ + node['mariadb']['innodb']['log_buffer_size'] +innodb_options['innodb_file_per_table'] = \ + node['mariadb']['innodb']['file_per_table'] +innodb_options['innodb_open_files'] = node['mariadb']['innodb']['open_files'] +innodb_options['innodb_io_capacity'] = \ + node['mariadb']['innodb']['io_capacity'] +innodb_options['innodb_flush_method'] = \ + node['mariadb']['innodb']['flush_method'] +node['mariadb']['innodb']['options'].each do |key, value| + innodb_options[key] = value +end + +mariadb_configuration 'innodb' do + section 'mysqld' + option innodb_options + action :add +end + +replication_opts = {} + +replication_opts['log_bin'] = node['mariadb']['replication']['log_bin'] +replication_opts['log_bin_index'] = \ + node['mariadb']['replication']['log_bin_index'] +replication_opts['expire_logs_days'] = \ + node['mariadb']['replication']['expire_logs_days'] +replication_opts['max_binlog_size'] = \ + node['mariadb']['replication']['max_binlog_size'] +unless node['mariadb']['replication']['server_id'].empty? + replication_opts['server-id'] = node['mariadb']['replication']['server_id'] +end +node['mariadb']['replication']['options'].each do |key, value| + replication_opts[key] = value +end + +mariadb_configuration 'replication' do + section 'mysqld' + option replication_opts + action :add +end diff --git a/cookbooks/mariadb/recipes/default.rb b/cookbooks/mariadb/recipes/default.rb new file mode 100644 index 0000000..7edcd87 --- /dev/null +++ b/cookbooks/mariadb/recipes/default.rb @@ -0,0 +1,20 @@ +# +# Cookbook Name:: mariadb +# Recipe:: default +# +# Copyright 2014, blablacar.com +# +# 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. +# + +include_recipe "#{cookbook_name}::server" diff --git a/cookbooks/mariadb/recipes/galera.rb b/cookbooks/mariadb/recipes/galera.rb new file mode 100644 index 0000000..df98265 --- /dev/null +++ b/cookbooks/mariadb/recipes/galera.rb @@ -0,0 +1,179 @@ +# +# Cookbook Name:: mariadb +# Recipe:: galera +# +# Copyright 2014, blablacar.com +# +# 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. +# + +case node['mariadb']['install']['type'] +when 'package' + # include MariaDB repositories + include_recipe "#{cookbook_name}::repository" + + case node['platform'] + when 'debian', 'ubuntu' + include_recipe "#{cookbook_name}::_debian_galera" + when 'redhat', 'centos', 'fedora', 'scientific', 'amazon' + include_recipe "#{cookbook_name}::_redhat_galera" + end +when 'from_source' + # To be filled as soon as possible +end + +if node['mariadb']['galera']['wsrep_sst_method'] == 'rsync' + package 'rsync' do + action :install + end +else + if node['mariadb']['galera']['wsrep_sst_method'] =~ /^xtrabackup(-v2)?/ + package 'percona-xtrabackup' do + action :install + end + + package 'socat' do + action :install + end + end +end + +include_recipe "#{cookbook_name}::config" + +galera_cluster_nodes = [] +if !node['mariadb'].attribute?('rspec') && Chef::Config[:solo] + if node['mariadb']['galera']['cluster_nodes'].empty? + Chef::Log.warn('By default this recipe uses search (unsupported by Chef Solo).' \ + ' Nodes may manually be configured as attributes.') + else + galera_cluster_nodes = node['mariadb']['galera']['cluster_nodes'] + end +else + if node['mariadb']['galera']['cluster_search_query'].empty? + galera_cluster_nodes = search( + :node, \ + "mariadb_galera_cluster_name:#{node['mariadb']['galera']['cluster_name']}" + ) + else + galera_cluster_nodes = search 'node', node['mariadb']['galera']['cluster_search_query'] + log 'Chef search results' do + message "Searching for \"#{node['mariadb']['galera']['cluster_search_query']}\" \ + resulted in \"#{galera_cluster_nodes}\" ..." + end + end + # Sort Nodes by fqdn + galera_cluster_nodes.sort! { |x, y| x[:fqdn] <=> y[:fqdn] } +end + +first = true +gcomm = 'gcomm://' +galera_cluster_nodes.each do |lnode| + next unless lnode.name != node.name + gcomm += ',' unless first + gcomm += lnode['fqdn'] + first = false +end + +galera_options = {} + +galera_options['wsrep_cluster_address'] = gcomm +galera_options['wsrep_cluster_name'] = \ + node['mariadb']['galera']['cluster_name'] +galera_options['wsrep_sst_method'] = \ + node['mariadb']['galera']['wsrep_sst_method'] +if node['mariadb']['galera'].attribute?('wsrep_sst_auth') + galera_options['wsrep_sst_auth'] = \ + node['mariadb']['galera']['wsrep_sst_auth'] +end +galera_options['wsrep_provider'] = \ + node['mariadb']['galera']['wsrep_provider'] +galera_options['wsrep_slave_threads'] = node['cpu']['total'] * 4 +node['mariadb']['galera']['options'].each do |key, value| + galera_options[key] = value +end + +mariadb_configuration 'galera' do + section 'mysqld' + option galera_options + action :add +end + +# +# Under debian system we have to change the debian-sys-maint default password. +# This password is the same for the overall cluster. +# +if platform?('debian', 'ubuntu') + template '/etc/mysql/debian.cnf' do + sensitive true + source 'debian.cnf.erb' + owner 'root' + group 'root' + mode '0600' + end + + grants_command = 'mysql -r -B -N -u root ' + + if node['mariadb']['server_root_password'].is_a?(String) + grants_command += '--password=\'' + \ + node['mariadb']['server_root_password'] + '\' ' + end + + grants_command += '-e "GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ' \ + 'DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, ' \ + 'INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY ' \ + 'TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, ' \ + 'REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ' \ + 'ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON ' \ + ' *.* TO \'' + node['mariadb']['debian']['user'] + \ + '\'@\'' + node['mariadb']['debian']['host'] + '\' ' \ + 'IDENTIFIED BY \'' + \ + node['mariadb']['debian']['password'] + '\' WITH GRANT ' \ + 'OPTION"' + + execute 'correct-debian-grants' do + # Add sensitive true when foodcritic #233 fixed + command grants_command + action :run + only_if do + cmd = Mixlib::ShellOut.new("/usr/bin/mysql --user=\"" + \ + node['mariadb']['debian']['user'] + \ + "\" --password=\"" + node['mariadb']['debian']['password'] + \ + "\" -r -B -N -e \"SELECT 1\"") + cmd.run_command + cmd.error? + end + ignore_failure true + end +end + +# +# NOTE: You cannot use the following code to restart Mariadb when in Galera mode. +# When your SST is longer than a chef run... +# ==> chef-client try to restart the service each time it run <== +# + +# restart the service if needed +# workaround idea from https://github.com/stissot +# +# Chef::Resource::Execute.send(:include, MariaDB::Helper) +# execute 'mariadb-service-restart-needed' do +# command 'true' +# only_if do +# mariadb_service_restart_required?( +# node['mariadb']['mysqld']['bind-address'], +# node['mariadb']['mysqld']['port'], +# node['mariadb']['mysqld']['socket'] +# ) +# end +# notifies :restart, 'service[mysql]', :immediately +# end diff --git a/cookbooks/mariadb/recipes/plugins.rb b/cookbooks/mariadb/recipes/plugins.rb new file mode 100644 index 0000000..5a722bc --- /dev/null +++ b/cookbooks/mariadb/recipes/plugins.rb @@ -0,0 +1,3 @@ +node['mariadb']['plugins'].each do |plugin, enable| + include_recipe "#{cookbook_name}::_" + plugin + '_plugin' if enable +end diff --git a/cookbooks/mariadb/recipes/repository.rb b/cookbooks/mariadb/recipes/repository.rb new file mode 100644 index 0000000..e8081eb --- /dev/null +++ b/cookbooks/mariadb/recipes/repository.rb @@ -0,0 +1,42 @@ +case node['platform'] +when 'debian', 'ubuntu' + install_method = 'apt' +when 'redhat', 'centos', 'fedora', 'scientific', 'amazon' + install_method = 'yum' +end + +if node['mariadb']['use_default_repository'] + case install_method + when 'apt' + include_recipe 'apt::default' + + apt_repository "mariadb-#{node['mariadb']['install']['version']}" do + uri 'http://' + node['mariadb']['apt_repository']['base_url'] + '/' + \ + node['mariadb']['install']['version'] + '/' + node['platform'] + distribution node['lsb']['codename'] + components ['main'] + keyserver 'hkp://keyserver.ubuntu.com:80' + key '0xcbcb082a1bb943db' + end + when 'yum' + include_recipe 'yum::default' + + if node['platform'] == 'redhat' || node['platform'] == 'scientific' + target_platform = "rhel#{node['platform_version'].to_i}" + else + target_platform = "#{node['platform']}#{node['platform_version'].to_i}" + end + yum_repository "mariadb-#{node['mariadb']['install']['version']}" do + description 'MariaDB Official Repository' + baseurl 'http://yum.mariadb.org/' + \ + node['mariadb']['install']['version'] + "/#{target_platform}-amd64" + gpgkey 'https://yum.mariadb.org/RPM-GPG-KEY-MariaDB' + action :create + end + + case node['platform'] + when 'redhat', 'centos', 'scientific' + include_recipe 'yum-epel::default' + end + end +end diff --git a/cookbooks/mariadb/recipes/server.rb b/cookbooks/mariadb/recipes/server.rb new file mode 100644 index 0000000..aa5db89 --- /dev/null +++ b/cookbooks/mariadb/recipes/server.rb @@ -0,0 +1,130 @@ +# +# Cookbook Name:: mariadb +# Recipe:: server +# +# Copyright 2014, blablacar.com +# +# 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. +# + +Chef::Recipe.send(:include, MariaDB::Helper) +case node['mariadb']['install']['type'] +when 'package' + if use_os_native_package?(node['mariadb']['install']['prefer_os_package'], + node['platform'], node['platform_version']) + # currently, no releases with apt (e.g. ubuntu) ship mariadb + # only provide one type of server here (with yum support) + include_recipe "#{cookbook_name}::_redhat_server_native" + else + include_recipe "#{cookbook_name}::repository" + + case node['platform'] + when 'debian', 'ubuntu' + include_recipe "#{cookbook_name}::_debian_server" + when 'redhat', 'centos', 'fedora', 'scientific', 'amazon' + include_recipe "#{cookbook_name}::_redhat_server" + end + end +when 'from_source' + # To be filled as soon as possible +end + +include_recipe "#{cookbook_name}::config" + +service 'mysql' do + service_name node['mariadb']['mysqld']['service_name'] + supports restart: true + action :nothing +end + +# move the datadir if needed +if node['mariadb']['mysqld']['datadir'] != + node['mariadb']['mysqld']['default_datadir'] + + bash 'move-datadir' do + user 'root' + code <<-EOH + /bin/cp -a #{node['mariadb']['mysqld']['default_datadir']}/* \ + #{node['mariadb']['mysqld']['datadir']} && + /bin/rm -r #{node['mariadb']['mysqld']['default_datadir']} && + /bin/ln -s #{node['mariadb']['mysqld']['datadir']} \ + #{node['mariadb']['mysqld']['default_datadir']} + EOH + action :nothing + end + + directory node['mariadb']['mysqld']['datadir'] do + owner 'mysql' + group 'mysql' + mode 00750 + action :create + notifies :stop, 'service[mysql]', :immediately + notifies :run, 'bash[move-datadir]', :immediately + notifies :start, 'service[mysql]', :immediately + only_if { !File.symlink?(node['mariadb']['mysqld']['default_datadir']) } + end +end + +# restart the service if needed +# workaround idea from https://github.com/stissot +Chef::Resource::Execute.send(:include, MariaDB::Helper) +execute 'mariadb-service-restart-needed' do + command 'true' + only_if do + mariadb_service_restart_required?( + node['mariadb']['mysqld']['bind_address'], + node['mariadb']['mysqld']['port'], + node['mariadb']['mysqld']['socket'] + ) + end + notifies :restart, 'service[mysql]', :immediately +end + +if node['mariadb']['allow_root_pass_change'] + # Used to change root password after first install + # Still experimental + if node['mariadb']['server_root_password'].empty? + md5 = Digest::MD5.hexdigest('empty') + else + md5 = Digest::MD5.hexdigest(node['mariadb']['server_root_password']) + end + + file '/etc/mysql_root_change' do + content md5 + action :create + notifies :run, 'execute[install-grants]', :immediately + end +end + +if node['mariadb']['allow_root_pass_change'] || + node['mariadb']['forbid_remote_root'] + execute 'install-grants' do + # Add sensitive true when foodcritic #233 fixed + command '/bin/bash /etc/mariadb_grants \'' + \ + node['mariadb']['server_root_password'] + '\'' + only_if { File.exist?('/etc/mariadb_grants') } + action :nothing + end + + template '/etc/mariadb_grants' do + sensitive true + source 'mariadb_grants.erb' + owner 'root' + group 'root' + mode '0600' + notifies :run, 'execute[install-grants]', :immediately + end +end + +# MariaDB Plugins +include_recipe "#{cookbook_name}::plugins" if node['mariadb']['plugins_options']['auto_install'] diff --git a/cookbooks/mariadb/resources/configuration.rb b/cookbooks/mariadb/resources/configuration.rb new file mode 100644 index 0000000..57e458a --- /dev/null +++ b/cookbooks/mariadb/resources/configuration.rb @@ -0,0 +1,13 @@ +# +# Cookbook Name:: mariadb +# Resource:: configuration +# + +actions :add, :remove +default_action :add + +# name of the extra conf file, used for .cnf filename +attribute :conf_name, kind_of: String, name_attribute: true +attribute :section, kind_of: String +attribute :option, kind_of: Hash, default: {} +attribute :cookbook, kind_of: String, default: nil diff --git a/cookbooks/mariadb/resources/replication.rb b/cookbooks/mariadb/resources/replication.rb new file mode 100644 index 0000000..afb0462 --- /dev/null +++ b/cookbooks/mariadb/resources/replication.rb @@ -0,0 +1,22 @@ +# +# Cookbook Name:: mariadb +# Resource:: replication +# + +actions :add, :remove, :start, :stop +default_action :add + +# name of the extra conf file, used for .cnf filename +attribute :connection_name, kind_of: String, name_attribute: true +attribute :host, kind_of: [String, NilClass], default: nil +attribute :port, kind_of: [String, NilClass], default: nil +attribute :user, kind_of: [String, NilClass], default: nil +attribute :password, kind_of: [String, NilClass], default: nil +attribute :master_host, kind_of: [String, NilClass], default: nil +attribute :master_user, kind_of: [String, NilClass], default: nil +attribute :master_password, kind_of: [String, NilClass], default: nil +attribute :master_connect_retry, kind_of: [String, NilClass], default: nil +attribute :master_port, kind_of: [Integer, NilClass], default: nil +attribute :master_log_pos, kind_of: [Integer, NilClass], default: nil +attribute :master_log_file, kind_of: [String, NilClass], default: nil +attribute :master_use_gtid, kind_of: String, default: 'no' diff --git a/cookbooks/mariadb/templates/default/conf.d.generic.erb b/cookbooks/mariadb/templates/default/conf.d.generic.erb new file mode 100644 index 0000000..56af4e1 --- /dev/null +++ b/cookbooks/mariadb/templates/default/conf.d.generic.erb @@ -0,0 +1,19 @@ +# DEPLOYED BY CHEF +[<%= @section -%>] +<% @options.each do | option_name, option_value |-%> + <% if option_value.to_s == 'true' -%> +<%= option_name %> + <% else -%> + <% if option_value.kind_of?(String) && option_value.start_with?('#') -%> +<%= option_value %> + <% else -%> + <% if option_value.kind_of?(Array) -%> + <% option_value.each do | option_value_array_value | -%> +<%= option_name -%> = <%= option_value_array_value %> + <% end -%> + <% else -%> +<%= option_name -%> = <%= option_value %> + <% end -%> + <% end -%> + <% end -%> +<% end -%> diff --git a/cookbooks/mariadb/templates/default/debian.cnf.erb b/cookbooks/mariadb/templates/default/debian.cnf.erb new file mode 100644 index 0000000..b7fb3f6 --- /dev/null +++ b/cookbooks/mariadb/templates/default/debian.cnf.erb @@ -0,0 +1,12 @@ +# Automatically generated for Debian scripts (Managed by CHEF). DO NOT TOUCH! +[client] +host = <%= node['mariadb']['debian']['host'] %> +user = <%= node['mariadb']['debian']['user'] %> +password = <%= node['mariadb']['debian']['password'] %> +socket = <%= node['mariadb']['client']['socket'] %> +[mysql_upgrade] +host = <%= node['mariadb']['debian']['host'] %> +user = <%= node['mariadb']['debian']['user'] %> +password = <%= node['mariadb']['debian']['password'] %> +socket = <%= node['mariadb']['mysqld_safe']['socket'] %> +basedir = <%= node['mariadb']['mysqld']['basedir'] %> diff --git a/cookbooks/mariadb/templates/default/mariadb-server.seed.erb b/cookbooks/mariadb/templates/default/mariadb-server.seed.erb new file mode 100644 index 0000000..eddb939 --- /dev/null +++ b/cookbooks/mariadb/templates/default/mariadb-server.seed.erb @@ -0,0 +1,13 @@ +<% +# Value obtained via the debconf-get-selections tool on debian wheezy +pack_w_version = @package_name + '-' + node['mariadb']['install']['version'] +-%> +<%= pack_w_version %> mysql-server/root_password_again select <%= node['mariadb']['server_root_password'] %> +<%= pack_w_version %> mysql-server/root_password select <%= node['mariadb']['server_root_password'] %> +<%= pack_w_version %> mysql-server/error_setting_password boolean false +<%= pack_w_version %> mysql-server-5.1/nis_warning note +<%= pack_w_version %> mysql-server-5.1/start_on_boot boolean true +<%= pack_w_version %> <%= pack_w_version %>/really_downgrade boolean false +<%= pack_w_version %> mysql-server-5.1/postrm_remove_databases boolean false +<%= pack_w_version %> mysql-server/password_mismatch boolean false +<%= pack_w_version %> mysql-server/no_upgrade_when_using_ndb boolean true diff --git a/cookbooks/mariadb/templates/default/mariadb_grants.erb b/cookbooks/mariadb/templates/default/mariadb_grants.erb new file mode 100644 index 0000000..6eda39d --- /dev/null +++ b/cookbooks/mariadb/templates/default/mariadb_grants.erb @@ -0,0 +1,25 @@ +#!/bin/bash +# Generated by CHEF +# Local modification will be overriden + +<% if node['mariadb']['allow_root_pass_change'] -%> +<% if node['mariadb']['server_root_password'].empty? -%> +/usr/bin/mysqladmin -u root password "$1" +<% else -%> +/usr/bin/mysqladmin -u root -p'<%= node['mariadb']['server_root_password'] %>' password "$1" +<% end -%> + +<% end -%> +password_flag="" +if [ "$1" ]; then + password_flag="-p$1" +fi + +<% if node['mariadb']['forbid_remote_root'] -%> +user_exist=`/usr/bin/mysql -u root ${password_flag} -D mysql -r -B -N -e "SELECT user from user where user = 'root' and host = '%'"` +if [ $user_exist == 'root' ]; then + /bin/echo "DROP USER 'root'@'%';" | /usr/bin/mysql -u root ${password_flag} +fi +<% else -%> +/bin/echo "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '<%= node['mariadb']['server_root_password'] %>' WITH GRANT OPTION;" | /usr/bin/mysql -u root ${password_flag} +<% end -%> diff --git a/cookbooks/mariadb/templates/default/my.cnf.erb b/cookbooks/mariadb/templates/default/my.cnf.erb new file mode 100644 index 0000000..4b78c25 --- /dev/null +++ b/cookbooks/mariadb/templates/default/my.cnf.erb @@ -0,0 +1,191 @@ +# DEPLOYED BY CHEF +# MariaDB database server configuration file. +# +# You can copy this file to one of: +# - "/etc/mysql/my.cnf" to set global options, +# - "~/.my.cnf" to set user-specific options. +# +# One can use all long options that the program supports. +# Run program with --help to get a list of available options and with +# --print-defaults to see which it would actually understand and use. +# +# For explanations see +# http://dev.mysql.com/doc/mysql/en/server-system-variables.html + +# This will be passed to all mysql clients +# It has been reported that passwords should be enclosed with ticks/quotes +# escpecially if they contain "#" chars... +# Remember to edit /etc/mysql/debian.cnf when changing the socket location. +[client] +port = <%= node['mariadb']['client']['port'] %> +socket = <%= node['mariadb']['client']['socket'] %> +<% if node['mariadb']['client'].attribute?('host') && !node['mariadb']['client']['host'].nil? %> +host = <%= node['mariadb']['client']['host'] %> +<% end %> + +# Here is entries for some specific programs +# The following values assume you have at least 32M ram + +# This was formally known as [safe_mysqld]. Both versions are currently parsed. +[mysqld_safe] +socket = <%= node['mariadb']['mysqld_safe']['socket'] %> +nice = 0 + +[mysqld] +# +# * Basic Settings +# +user = <%= node['mariadb']['mysqld']['user'] %> +<% if node['mariadb']['mysqld'].attribute?('pid_file') %> +pid-file = <%= node['mariadb']['mysqld']['pid_file'] %> +<% end %> +socket = <%= node['mariadb']['mysqld']['socket'] %> +port = <%= node['mariadb']['mysqld']['port'] %> +basedir = <%= node['mariadb']['mysqld']['basedir'] %> +datadir = <%= node['mariadb']['mysqld']['default_datadir'] %> +tmpdir = <%= node['mariadb']['mysqld']['tmpdir'] %> +lc_messages_dir = <%= node['mariadb']['mysqld']['lc_messages_dir'] %> +lc_messages = <%= node['mariadb']['mysqld']['lc_messages'] %> +<% if node['mariadb']['mysqld']['skip_external_locking'] == 'true' -%> +skip-external-locking +<% end -%> +# +# Instead of skip-networking the default is now to listen only on +# localhost which is more compatible and is not less secure. +<% unless node['mariadb']['mysqld']['bind_address'].nil? or node['mariadb']['mysqld']['bind_address'].empty? -%> +bind-address = <%= node['mariadb']['mysqld']['bind_address'] %> +<% end -%> +# +# * Fine Tuning +# +max_connections = <%= node['mariadb']['mysqld']['max_connections'] %> +connect_timeout = <%= node['mariadb']['mysqld']['connect_timeout'] %> +wait_timeout = <%= node['mariadb']['mysqld']['wait_timeout'] %> +max_allowed_packet = <%= node['mariadb']['mysqld']['max_allowed_packet'] %> +thread_cache_size = <%= node['mariadb']['mysqld']['thread_cache_size'] %> +sort_buffer_size = <%= node['mariadb']['mysqld']['sort_buffer_size'] %> +bulk_insert_buffer_size = <%= node['mariadb']['mysqld']['bulk_insert_buffer_size'] %> +tmp_table_size = <%= node['mariadb']['mysqld']['tmp_table_size'] %> +max_heap_table_size = <%= node['mariadb']['mysqld']['max_heap_table_size'] %> +# +# * MyISAM +# +# This replaces the startup script and checks MyISAM tables if needed +# the first time they are touched. On error, make copy and try a repair. +myisam_recover = <%= node['mariadb']['mysqld']['myisam_recover'] %> +key_buffer_size = <%= node['mariadb']['mysqld']['key_buffer_size'] %> +<% if node['mariadb']['mysqld']['open_files_limit'].empty? -%> +#open-files-limit = 2000 +<% else -%> +open-files-limit = <%= node['mariadb']['mysqld']['open_files_limit'] %> +<% end -%> +table_open_cache = <%= node['mariadb']['mysqld']['table_open_cache'] %> +myisam_sort_buffer_size = <%= node['mariadb']['mysqld']['myisam_sort_buffer_size'] %> +concurrent_insert = <%= node['mariadb']['mysqld']['concurrent_insert'] %> +read_buffer_size = <%= node['mariadb']['mysqld']['read_buffer_size'] %> +read_rnd_buffer_size = <%= node['mariadb']['mysqld']['read_rnd_buffer_size'] %> +# +# * Query Cache Configuration +# +# Cache only tiny result sets, so we can fit more in the query cache. +query_cache_limit = <%= node['mariadb']['mysqld']['query_cache_limit'] %> +query_cache_size = <%= node['mariadb']['mysqld']['query_cache_size'] %> +# for more write intensive setups, set to DEMAND or OFF +<% if node['mariadb']['mysqld']['query_cache_type'].empty? -%> +#query_cache_type = DEMAND +<% else -%> +query_cache_type = <%= node['mariadb']['mysqld']['query_cache_type'] %> +<% end -%> +# +# * Logging and Replication +# +# Both location gets rotated by the cronjob. +# Be aware that this log type is a performance killer. +# As of 5.1 you can enable the log at runtime! +#general_log_file = /var/log/mysql/mysql.log +#general_log = 1 +# +# Error logging goes to syslog due to /etc/mysql/conf.d/mysqld_safe_syslog.cnf. +# +# we do want to know about network errors and such +log_warnings = 2 +# +# Enable the slow query log to see queries with especially long duration +#slow_query_log[={0|1}] +slow_query_log_file = /var/log/mysql/mariadb-slow.log +long_query_time = 10 +#log_slow_rate_limit = 1000 +log_slow_verbosity = query_plan + +#log-queries-not-using-indexes +#log_slow_admin_statements +# +# The following can be used as easy to replay backup logs or for replication. +# note: if you are setting up a replication slave, see README.Debian about +# other settings you may need to change. +#report_host = master1 +#auto_increment_increment = 2 +#auto_increment_offset = 1 +# not fab for performance, but safer +#sync_binlog = 1 +# slaves +#relay_log = /var/log/mysql/relay-bin +#relay_log_index = /var/log/mysql/relay-bin.index +#relay_log_info_file = /var/log/mysql/relay-bin.info +#log_slave_updates +#read_only +# +# If applications support it, this stricter sql_mode prevents some +# mistakes like inserting invalid dates etc. +#sql_mode = NO_ENGINE_SUBSTITUTION,TRADITIONAL + +default_storage_engine = <%= node['mariadb']['mysqld']['default_storage_engine'] %> + +# +# * Security Features +# +# Read the manual, too, if you want chroot! +# chroot = /var/lib/mysql/ +# +# For generating SSL certificates I recommend the OpenSSL GUI "tinyca". +# +# ssl-ca=/etc/mysql/cacert.pem +# ssl-cert=/etc/mysql/server-cert.pem +# ssl-key=/etc/mysql/server-key.pem + +<% if node['mariadb']['mysqld'].key?('options') -%> +<% node['mariadb']['mysqld']['options'].each { |key, value| -%> +<%= key %> = <%= value %> +<% } -%> +<% end -%> + +# +# * Plugins Options +# +<% plugin_load = [] -%> +<% node['mariadb']['plugins_loading'].each { |plugin, loading| -%> + <% plugin_load.push(loading) if node['mariadb']['plugins'][plugin] %> +<% } -%> +plugin-load = <%= plugin_load.join(';') %> + +[mysqldump] +<% if node['mariadb']['mysqldump']['quick'].empty? -%> +quick +<% end -%> +<% if node['mariadb']['mysqldump']['quote_names'].empty? -%> +quote-names +<% end -%> +max_allowed_packet = <%= node['mariadb']['mysqldump']['max_allowed_packet'] %> + +[mysql] +#no-auto-rehash # faster start of mysql but no tab completition + +[isamchk] +key_buffer = <%= node['mariadb']['isamchk']['key_buffer'] %> + +# +# * IMPORTANT: Additional settings that can override those from this file! +# The files must end with '.cnf', otherwise they'll be ignored. +# +!includedir <%= node['mariadb']['configuration']['includedir'] %>/ + diff --git a/cookbooks/mediawiki/.kitchen.yml b/cookbooks/mediawiki/.kitchen.yml new file mode 100644 index 0000000..d3610e7 --- /dev/null +++ b/cookbooks/mediawiki/.kitchen.yml @@ -0,0 +1,22 @@ +--- +driver: + name: vagrant + +provisioner: + name: chef_solo + +platforms: + - name: centos-6.5 + driver: + box: centos-6.5 + box_url: https://vagrantcloud.com/baremettle/centos-6.5/version/1/provider/libvirt.box +# - name: debian-7.5 +# driver: +# box: debian-7.5 +# box_url: https://vagrantcloud.com/baremettle/debian-7.5/version/1/provider/libvirt.box + +suites: + - name: default + run_list: + - "recipe[mediawiki::default]" + attributes: diff --git a/cookbooks/mediawiki/Berksfile b/cookbooks/mediawiki/Berksfile new file mode 100644 index 0000000..04f25b7 --- /dev/null +++ b/cookbooks/mediawiki/Berksfile @@ -0,0 +1,4 @@ +source "https://supermarket.getchef.com" + +metadata + diff --git a/cookbooks/mediawiki/Gemfile b/cookbooks/mediawiki/Gemfile new file mode 100644 index 0000000..55f8096 --- /dev/null +++ b/cookbooks/mediawiki/Gemfile @@ -0,0 +1,18 @@ +source 'https://rubygems.org' + +gem 'berkshelf' + +# Uncomment these lines if you want to live on the Edge: +# +# group :development do +# gem "berkshelf", github: "berkshelf/berkshelf" +# gem "vagrant", github: "mitchellh/vagrant", tag: "v1.5.2" +# end +# +# group :plugins do +# gem "vagrant-berkshelf", github: "berkshelf/vagrant-berkshelf" +# gem "vagrant-omnibus", github: "schisamo/vagrant-omnibus" +# end + +gem 'test-kitchen' +gem 'kitchen-vagrant' diff --git a/cookbooks/mediawiki/LICENSE b/cookbooks/mediawiki/LICENSE new file mode 100644 index 0000000..8ce2314 --- /dev/null +++ b/cookbooks/mediawiki/LICENSE @@ -0,0 +1,3 @@ +Copyright (C) 2014 YOUR_NAME + +All rights reserved - Do Not Redistribute diff --git a/cookbooks/mediawiki/README.md b/cookbooks/mediawiki/README.md new file mode 100644 index 0000000..a0fe2a6 --- /dev/null +++ b/cookbooks/mediawiki/README.md @@ -0,0 +1,88 @@ +Mediawiki Cookbook +================== + +Installs/Configures mediawiki + +Requirements +------------ + +### Platform: + +* Centos +* Debian + +### Cookbooks: + +* apache2 +* php +* mysql +* database + +Attributes +---------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeDescriptionDefault
node['mediawiki']['version']
node['mediawiki']['database']['name']
node['mediawiki']['database']['user']
node['mediawiki']['database']['password']
node['mediawiki']['server_name']
node['mediawiki']['sciptpath']
node['mediawiki']['admin_user']
node['mediawiki']['admin_password']
+ +Recipes +------- + +### mediawiki::default + +Installs/Configures mediawiki + + +License and Author +------------------ + +Author:: pulsation + +Copyright:: 2014, pulsation + +License:: BSD + diff --git a/cookbooks/mediawiki/Thorfile b/cookbooks/mediawiki/Thorfile new file mode 100644 index 0000000..b23ee16 --- /dev/null +++ b/cookbooks/mediawiki/Thorfile @@ -0,0 +1,12 @@ +# encoding: utf-8 + +require 'bundler' +require 'bundler/setup' +require 'berkshelf/thor' + +begin + require 'kitchen/thor_tasks' + Kitchen::ThorTasks.new +rescue LoadError + puts ">>>>> Kitchen gem not loaded, omitting tasks" unless ENV['CI'] +end diff --git a/cookbooks/mediawiki/attributes/default.rb b/cookbooks/mediawiki/attributes/default.rb new file mode 100644 index 0000000..4743cc7 --- /dev/null +++ b/cookbooks/mediawiki/attributes/default.rb @@ -0,0 +1,26 @@ +default["mediawiki"]["version"] = "1.26.2" +default["mediawiki"]["docroot_dir"] = "/var/www" +default["mediawiki"]["webdir"] = "#{default["mediawiki"]["docroot_dir"]}/mediawiki-#{default["mediawiki"]["version"]}" +default["mediawiki"]["tarball"]["name"] = "mediawiki-" + default["mediawiki"]["version"] + ".tar.gz" +default["mediawiki"]["tarball"]["url"] = "https://releases.wikimedia.org/mediawiki/1.26/" + default["mediawiki"]["tarball"]["name"] +default["mediawiki"]["server_name"] = "wiki.localhost" +default["mediawiki"]["scriptpath"] = "" + +default["mediawiki"]["server"] = "http://" + default["mediawiki"]["server_name"] +default["mediawiki"]["site_name"] = "my Wiki" +default["mediawiki"]["language_code"] = "en" +default["mediawiki"]["admin_user"] = "administrator" +default["mediawiki"]["admin_password"] = "admin" + +default["mediawiki"]["php_options"] = { "php_admin_value[upload_max_filesize]" => "50M", "php_admin_value[post_max_size]" => "55M" } + +default['mediawiki']['db']['root_password'] = 'my_root_password' +default['mediawiki']['db']['instance_name'] = 'default' +default['mediawiki']['db']['name'] = "mediawikidb" +default['mediawiki']['db']['user'] = "mediawikiuser" +default['mediawiki']['db']['pass'] = nil +default['mediawiki']['db']['prefix'] = 'wp_' +default['mediawiki']['db']['host'] = 'localhost' +default['mediawiki']['db']['port'] = '3307' # Must be a string +default['mediawiki']['db']['charset'] = 'utf8' +default['mediawiki']['db']['collate'] = '' diff --git a/cookbooks/mediawiki/chefignore b/cookbooks/mediawiki/chefignore new file mode 100644 index 0000000..138a808 --- /dev/null +++ b/cookbooks/mediawiki/chefignore @@ -0,0 +1,94 @@ +# Put files/directories that should be ignored in this file when uploading +# or sharing to the community site. +# Lines that start with '# ' are comments. + +# OS generated files # +###################### +.DS_Store +Icon? +nohup.out +ehthumbs.db +Thumbs.db + +# SASS # +######## +.sass-cache + +# EDITORS # +########### +\#* +.#* +*~ +*.sw[a-z] +*.bak +REVISION +TAGS* +tmtags +*_flymake.* +*_flymake +*.tmproj +.project +.settings +mkmf.log + +## COMPILED ## +############## +a.out +*.o +*.pyc +*.so +*.com +*.class +*.dll +*.exe +*/rdoc/ + +# Testing # +########### +.watchr +.rspec +spec/* +spec/fixtures/* +test/* +features/* +Guardfile +Procfile + +# SCM # +####### +.git +*/.git +.gitignore +.gitmodules +.gitconfig +.gitattributes +.svn +*/.bzr/* +*/.hg/* +*/.svn/* + +# Berkshelf # +############# +cookbooks/* +tmp + +# Cookbooks # +############# +CONTRIBUTING +CHANGELOG* + +# Strainer # +############ +Colanderfile +Strainerfile +.colander +.strainer + +# Vagrant # +########### +.vagrant +Vagrantfile + +# Travis # +########## +.travis.yml diff --git a/cookbooks/mediawiki/metadata.json b/cookbooks/mediawiki/metadata.json new file mode 100644 index 0000000..6e73805 --- /dev/null +++ b/cookbooks/mediawiki/metadata.json @@ -0,0 +1,37 @@ +{ + "name": "mediawiki", + "description": "Installs/Configures mediawiki", + "long_description": "Installs/Configures mediawiki", + "maintainer": "pulsation", + "maintainer_email": "", + "license": "BSD", + "platforms": { + "centos": ">= 0.0.0", + "debian": ">= 0.0.0" + }, + "dependencies": { + "apache2": ">= 0.0.0", + "php": ">= 0.0.0", + "nginx": ">= 0.0.0", + "php-fpm": ">= 0.0.0" + }, + "providing": { + + }, + "recipes": { + "mediawiki::default": "Installs/Configures mediawiki" + }, + "version": "0.5.0", + "source_url": "", + "issues_url": "", + "privacy": false, + "chef_versions": [ + + ], + "ohai_versions": [ + + ], + "gems": [ + + ] +} diff --git a/cookbooks/mediawiki/metadata.rb b/cookbooks/mediawiki/metadata.rb new file mode 100644 index 0000000..4dbc567 --- /dev/null +++ b/cookbooks/mediawiki/metadata.rb @@ -0,0 +1,56 @@ +name 'mediawiki' +maintainer 'pulsation' +license 'BSD' +description 'Installs/Configures mediawiki' +long_description 'Installs/Configures mediawiki' +version '0.5.0' + +depends 'apache2' +depends 'php' +depends 'nginx' +depends 'php-fpm' + +attribute 'mediawiki/version', + :display_name => "Mediawiki version", + :type => "string", + :required => "recommended" + +attribute 'mediawiki/database/name', + :display_name => "Database name", + :type => "string", + :required => "optional" + +attribute 'mediawiki/database/user', + :display_name => "Database user", + :type => "string", + :required => "optional" + +attribute 'mediawiki/database/password', + :display_name => "Database password", + :type => "string", + :required => "optional" + +attribute 'mediawiki/server_name', + :display_name => "Server name", + :type => "string", + :required => "recommended" + +attribute 'mediawiki/sciptpath', + :display_name => "Script path", + :type => "string", + :required => "optional" + +attribute 'mediawiki/admin_user', + :display_name => "Admin user", + :type => "string", + :required => "recommended" + +attribute 'mediawiki/admin_password', + :display_name => "Admin password", + :type => "string", + :required => "recommended" + +recipe "mediawiki::default", "Installs/Configures mediawiki" + +supports "centos" +supports "debian" diff --git a/cookbooks/mediawiki/recipes/apache2.rb b/cookbooks/mediawiki/recipes/apache2.rb new file mode 100644 index 0000000..ac6ba1f --- /dev/null +++ b/cookbooks/mediawiki/recipes/apache2.rb @@ -0,0 +1,10 @@ +include_recipe "apache2" +include_recipe "apache2::mod_php5" +include_recipe "apache2::mod_rewrite" + +# Add virtualhost +web_app "mediawiki" do + server_name node["mediawiki"]["server_name"] + docroot node["mediawiki"]["webdir"] +end + diff --git a/cookbooks/mediawiki/recipes/database.rb b/cookbooks/mediawiki/recipes/database.rb new file mode 100644 index 0000000..8ac64d1 --- /dev/null +++ b/cookbooks/mediawiki/recipes/database.rb @@ -0,0 +1,31 @@ +::Chef::Recipe.send(:include, Opscode::OpenSSL::Password) + +package('libmysqlclient-dev') { action :nothing }.run_action(:install) + +build_essential 'mediawiki' do + compile_time true +end + +node.normal['mediawiki']['db']['pass'] = secure_password +node.save unless Chef::Config[:solo] + +db = node["mediawiki"]["db"] + +package %w(mysql-client mysql-server) + +service 'mysql' do + action [:enable, :start] +end + +# Create database +execute "create #{db["name"]} db" do + command "mysql -e \"CREATE DATABASE IF NOT EXISTS #{db["name"]};\"" + user "root" +end + +# Create user +execute "create #{db["user"]} user" do + command "mysql -e \"CREATE USER IF NOT EXISTS '#{db["user"]}'@'localhost' IDENTIFIED BY '#{db["pass"]}'; GRANT ALL PRIVILEGES ON #{db["name"]}.* to '#{db["user"]}'@'localhost'; FLUSH PRIVILEGES;\"" + sensitive true + user "root" +end diff --git a/cookbooks/mediawiki/recipes/default.rb b/cookbooks/mediawiki/recipes/default.rb new file mode 100644 index 0000000..1da9d91 --- /dev/null +++ b/cookbooks/mediawiki/recipes/default.rb @@ -0,0 +1,69 @@ +# +# Cookbook Name:: mediawiki +# Recipe:: default +# +# Copyright (C) 2014 YOUR_NAME +# +# All rights reserved - Do Not Redistribute +# + +include_recipe "apt" + +include_recipe "php::default" + +package %w(php-apcu php-mysql php-mbstring) + +include_recipe "mediawiki::database" + +# Download mediawiki tarball +remote_file "#{Chef::Config[:file_cache_path]}/#{node['mediawiki']['tarball']['name']}" do + source node['mediawiki']['tarball']['url'] + notifies :run, "bash[extract_mediawiki]", :immediately +end + +# Extract mediawiki tarball +bash "extract_mediawiki" do + user "root" + cwd node["mediawiki"]["docroot_dir"] + code "tar -zxf #{Chef::Config[:file_cache_path]}/#{node['mediawiki']['tarball']['name']}; chown -R #{node['nginx']['user']}:#{node['nginx']['group']} #{node['mediawiki']['docroot_dir']}" + action :nothing +end + +# Additional packages +case node["platform_family"] +when "rhel" + package "php-xml" + package "libicu-devel" +when "debian" + package "libicu-dev" +end + +if platform?('ubuntu') && node[:platform_version].to_f < 16.04 + # bundled with PHP since version 5.3 + php_pear "intl" do + action :install + end +end + +# Configure mediawiki database +bash "configure_mediawiki_database" do + user node["nginx"]["user"] + cwd node["mediawiki"]["webdir"] + code "php maintenance/install.php" + + " --pass '" + node["mediawiki"]["admin_password"] + + "' --dbname '" + node["mediawiki"]["db"]["name"] + + "' --dbuser '" + node["mediawiki"]["db"]["user"] + + "' --dbpass '" + node["mediawiki"]["db"]["pass"] + + "' --server '" + node["mediawiki"]["server"] + + "' --scriptpath '" + node["mediawiki"]["scriptpath"] + + "' --lang '" + node["mediawiki"]["language_code"] + + "' '" + node["mediawiki"]["site_name"] + "' '" + node["mediawiki"]["admin_user"] + "'" + not_if { File.exist? "#{node["mediawiki"]["webdir"]}/LocalSettings.php" } + action :run +end + +file "#{node["mediawiki"]["webdir"]}/LocalSettings.php" do + mode "0640" + owner node["nginx"]["user"] + group node["nginx"]["group"] +end diff --git a/cookbooks/mediawiki/recipes/nginx.rb b/cookbooks/mediawiki/recipes/nginx.rb new file mode 100644 index 0000000..30c1fb8 --- /dev/null +++ b/cookbooks/mediawiki/recipes/nginx.rb @@ -0,0 +1,32 @@ +# +# Cookbook Name:: mediawiki +# Recipe:: nginx +# + +node.default['php-fpm']['pools'] = [] +node.override['php-fpm']['package_name'] = "php-fpm" +node.override['php-fpm']['service_name'] = "php7.2-fpm" +node.override['php-fpm']['conf_dir'] = "/etc/php/7.2/fpm/conf.d" +node.override['php-fpm']['pool_conf_dir'] = "/etc/php/7.2/fpm/pool.d" +node.override['php-fpm']['conf_file'] = "/etc/php/7.2/fpm/php-fpm.conf" + +include_recipe "php-fpm" +include_recipe 'php-fpm::repository' unless node['php-fpm']['skip_repository_install'] +include_recipe "php-fpm::install" + +php_fpm_pool "www" do + enable false +end + +php_fpm_pool "mediawiki" do + listen "127.0.0.1:9002" + user node['nginx']['user'] + group node['nginx']['group'] + listen_owner node['nginx']['user'] + listen_group node['nginx']['group'] + php_options node['mediawiki']['php_options'] + start_servers 5 + enable true +end + +include_recipe "nginx" diff --git a/cookbooks/mediawiki/templates/default/web_app.conf.erb b/cookbooks/mediawiki/templates/default/web_app.conf.erb new file mode 100644 index 0000000..ef44d22 --- /dev/null +++ b/cookbooks/mediawiki/templates/default/web_app.conf.erb @@ -0,0 +1,49 @@ +> + ServerName <%= @params[:server_name] %> + <% if @params[:server_aliases] -%> + ServerAlias <%= @params[:server_aliases].join " " %> + <% end -%> + DocumentRoot <%= @params[:docroot] %> + + > + Options <%= [@params[:directory_options] || "FollowSymLinks" ].flatten.join " " %> + AllowOverride <%= [@params[:allow_override] || "None" ].flatten.join " " %> + Order allow,deny + Allow from all + + + + Options FollowSymLinks + AllowOverride None + + + + SetHandler server-status + + Order Deny,Allow + Deny from all + Allow from 127.0.0.1 + + + LogLevel info + ErrorLog <%= node['apache']['log_dir'] %>/<%= @params[:name] %>-error.log + CustomLog <%= node['apache']['log_dir'] %>/<%= @params[:name] %>-access.log combined + + <% if @params[:directory_index] -%> + DirectoryIndex <%= [@params[:directory_index]].flatten.join " " %> + <% end -%> + + RewriteEngine On + RewriteLog <%= node['apache']['log_dir'] %>/<%= @application_name %>-rewrite.log + RewriteLogLevel 0 + + # Canonical host, <%= @params[:server_name] %> + RewriteCond %{HTTP_HOST} !^<%= @params[:server_name] %> [NC] + RewriteCond %{HTTP_HOST} !^$ + RewriteRule ^/(.*)$ http://<%= @params[:server_name] %>/$1 [L,R=301] + + RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f + RewriteCond %{SCRIPT_FILENAME} !maintenance.html + RewriteRule ^.*$ /system/maintenance.html [L] + + diff --git a/cookbooks/mingw/CHANGELOG.md b/cookbooks/mingw/CHANGELOG.md new file mode 100644 index 0000000..a1671ec --- /dev/null +++ b/cookbooks/mingw/CHANGELOG.md @@ -0,0 +1,58 @@ +# mingw Cookbook CHANGELOG + +This file is used to list changes made in each version of the mingw cookbook. + +## 2.1.0 (2018-07-24) + +- refactor msys2 package source and checksum to attributes + +## 2.0.2 (2018-02-15) + +- Remove kind_of usage in the custom resources (FC117) + +## 2.0.1 (2017-04-26) + +- Test with Local Delivery instead of Rake +- Add chef_version to the metadata +- Use standardize Apache 2 license string + +## 2.0.0 (2017-02-27) + +- Require Chef 12.5 and remove compat_resource dependency + +## 1.2.5 (2017-01-18) + +- Require a working compat_resource + +## v1.2.4 (2016-07-26) + +- New msys2 shells do not inherit PATH from windows. Provide a way for + clients to do this. + +## v1.2.3 (2016-07-25) + +- If PKG_CONFIG_PATH is already defined, honor it in the msys2 shell. + +## v1.2.2 (2016-06-24) + +- Download msys2 from the primary download url (instead of a specific mirror). + +## v1.2.1 (2016-06-23) + +- Fix msys2 initial install/upgrade steps that dependended on file modification time. +- Make msys2_package :install idempotent - it should not reinstall packages. +- Do not allow bash.exe to be called if MSYSTEM is undefined. + +## v1.2.0 (2016-06-03) +- Updating to fix the issue where msys2 bash does not inherit the cwd correctly + +## v1.1.0 (2016-06-03) +- Add msys2 based compiler support using the new msys2_package resource + +## v1.0.0 (2016-05-11) + +- Remove unnecessary default_action from the resources +- Depend on compat_resource cookbook to add Chef 12.1 - 12.4 compatbility +- Add this changelog file +- Fix license metadata in metadata.rb +- Disable FC016 check diff --git a/cookbooks/mingw/CONTRIBUTING.md b/cookbooks/mingw/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/mingw/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/cookbooks/mingw/README.md b/cookbooks/mingw/README.md new file mode 100644 index 0000000..16da102 --- /dev/null +++ b/cookbooks/mingw/README.md @@ -0,0 +1,138 @@ +# mingw Cookbook + +[![Cookbook Version](http://img.shields.io/cookbook/v/mingw.svg)][cookbook] [![Build Status](http://img.shields.io/travis/chef-cookbooks/mingw.svg?branch=master)][travis] + +Installs a mingw/msys based compiler tools chain on windows. This is required for compiling C software from source. + +## Requirements + +### Platforms + +- Windows + +### Chef + +- Chef 12.5+ + +### Cookbooks + +- seven_zip + +## Usage + +Add this cookbook as a dependency to your cookbook in its `metadata.rb` and include the default recipe in one of your recipes. + +```ruby +# metadata.rb +depends 'mingw' +``` + +```ruby +# your recipe.rb +include_recipe 'mingw::default' +``` + +Use the `msys2_package` resource in any recipe to fetch msys2 based packages. Use the `mingw_get` resource in any recipe to fetch mingw packages. Use the `mingw_tdm_gcc` resource to fetch a version of the TDM GCC compiler. + +By default, you should prefer the msys2 packages as they are newer and better supported. C/C++ compilers on windows use various different exception formats and you need to pick the right one for your task. In the 32-bit world, you have SJLJ (set-jump/long-jump) based exception handling and DWARF-2 (shortened to DW2) based exception handling. SJLJ produces code that can happily throw exceptions across stack frames of code compiled by MSVC. DW2 involves more extensive metadata but produces code that cannot unwind MSVC generated stack-frames - hence you need to ensure that you don't have any code that throws across a "system call". Certain languages and runtimes have specific requirements as to the exception format supported. As an example, if you are building code for Rust, you will probably need a modern gcc from msys2 with DW2 support as that's what the panic/exception formatter in Rust depends on. In a 64-bit world, you may still use SJLJ but compilers all commonly support SEH (structured exception handling). + +Of course, to further complicate matters, different versions of different compilers support different exception handling. The default compilers that come with mingw_get are 32-bit only compilers and support DW2\. The TDM compilers come in 3 flavors: a 32-bit only version with SJLJ support, a 32-bit only version with DW2 support and a "multilib" compiler which supports only SJLJ in 32-bit mode but can produce 64-bit SEH code. The standard library support varies drastically between these various compiler flavors (even within the same version). In msys2, you can install a mingw-w64 based compilers for either 32-bit DW2 support or 64-bit SEH support. If all this hurts your brain, I can only apologize. + +## Resources + +### msys2_package + +- ':install' - Installs an msys2 package using pacman. +- ':remove' - Uninstalls any existing msys2 package. +- ':upgrade' - Upgrades the specified package using pacman. + +All options also automatically attempt to install a 64-bit based msys2 base file system at the root path specified. Note that you probably won't need a "32-bit" msys2 unless you are actually on a 32-bit only platform. You can still install both 32 and 64-bit compilers and libraries in a 64-bit msys2 base file system. + +#### Attributes + +- `node['msys2']['url']` - overrides the url from which to download the package. +- `node['msys2']['checksum']` - overrides the checksum used to verify the downloaded package. + +#### Parameters + +- `package` - An msys2 pacman package (or meta-package) to fetch and install. You may use a legal package wild-card pattern here if you are installing. This is the name attribute. +- `root` - The root directory where msys2 tools will be installed. This directory must not contain any spaces in order to pacify old posix tools and most Makefiles. + +#### Examples + +To get the core msys2 developer tools in `C:\msys2` + +```ruby +msys2_package 'base-devel' do + root 'C:\msys2' +end +``` + +### mingw_get + +#### Actions + +- `:install` - Installs a mingw package from sourceforge using mingw-get.exe. +- `:remove` - Uninstalls a mingw package. +- `:upgrade` - Upgrades a mingw package (even to a lower version). + +#### Parameters + +- `package` - A mingw-get package (or meta-package) to fetch and install. You may use a legal package wild-card pattern here if you are installing. This is the name attribute. +- `root` - The root directory where msys and mingw tools will be installed. This directory must not contain any spaces in order to pacify old posix tools and most Makefiles. + +#### Examples + +To get the core msys developer tools in `C:\mingw32` + +```ruby +mingw_get 'msys-base=2013072300-msys-bin.meta' do + root 'C:\mingw32' +end +``` + +### mingw_tdm_gcc + +#### Actions + +- `:install` - Installs the TDM compiler toolchain at the given path. This only gives you a compiler. If you need any support tooling such as make/grep/awk/bash etc., see `mingw_get`. + +#### Parameters + +- `flavor` - Either `:sjlj_32` or `:seh_sjlj_64`. TDM-64 is a 32/64-bit multi-lib "cross-compiler" toolchain that builds 64-bit by default. It uses structured exception handling (SEH) in 64-bit code and setjump-longjump exception handling (SJLJ) in 32-bit code. TDM-32 only builds 32-bit binaries and uses SJLJ. +- `root` - The root directory where compiler tools and runtime will be installed. This directory must not contain any spaces in order to pacify old posix tools and most Makefiles. +- `version` - The version of the compiler to fetch and install. This is the name attribute. Currently, '5.1.0' is supported. + +#### Examples + +To get the 32-bit TDM GCC compiler in `C:\mingw32` + +```ruby +mingw_tdm_gcc '5.1.0' do + flavor :sjlj_32 + root 'C:\mingw32' +end +``` + +## License & Authors + +**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io)) + +**Copyright:** 2009-2016, Chef Software, Inc. + +``` +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` + +[cookbook]: https://supermarket.chef.io/cookbooks/mingw +[travis]: http://travis-ci.org/chef-cookbooks/mingw diff --git a/cookbooks/mingw/attributes/default.rb b/cookbooks/mingw/attributes/default.rb new file mode 100644 index 0000000..9176ec3 --- /dev/null +++ b/cookbooks/mingw/attributes/default.rb @@ -0,0 +1,3 @@ +# override these attributes to pull the msys2 package from a custom url +default['msys2']['url'] = 'http://downloads.sourceforge.net/project/msys2/Base/x86_64/msys2-base-x86_64-20160205.tar.xz' +default['msys2']['checksum'] = '7e97e2af042e1b6f62cf0298fe84839014ef3d4a3e7825cffc6931c66cc0fc20' diff --git a/cookbooks/mingw/files/default/bash.bat b/cookbooks/mingw/files/default/bash.bat new file mode 100644 index 0000000..97a7f99 --- /dev/null +++ b/cookbooks/mingw/files/default/bash.bat @@ -0,0 +1,17 @@ +@echo off +set HOME=/home/%USERNAME% + +IF "%MSYSTEM%"=="" ( + echo MSYSTEM is NOT defined + exit +) + +rem Ask MSYS to initialize with a minimal path by default. +rem This will put only the windows system paths into the msys path. +set MSYS2_PATH_TYPE=minimal + +rem See /etc/profile - it should invoke post-install step 05-home-dir.post +rem which uses this environment variable to change directories. +set CHERE_INVOKING=1 + +%~dp0..\usr\bin\bash.exe -l %* diff --git a/cookbooks/mingw/files/default/custom-upgrade.sh b/cookbooks/mingw/files/default/custom-upgrade.sh new file mode 100644 index 0000000..db729eb --- /dev/null +++ b/cookbooks/mingw/files/default/custom-upgrade.sh @@ -0,0 +1,23 @@ +declare -r CRITICAL_PACKAGES="bash pacman msys2-runtime" +declare -r OPTIONAL_PACKAGES="msys2-runtime-devel" + +# set pacman command if not already defined +PACMAN=${PACMAN:-pacman} +# save full path to command as PATH may change when sourcing /etc/profile +PACMAN_PATH=$(type -P $PACMAN) + +run_pacman() { + local cmd + cmd=("$PACMAN_PATH" "$@") + "${cmd[@]}" +} + +if ! run_pacman -Sy; then + exit 1 +fi + +run_pacman -Qu ${CRITICAL_PACKAGES} + +if ! run_pacman -S --noconfirm --needed ${CRITICAL_PACKAGES} ${OPTIONAL_PACKAGES}; then + exit 1 +fi diff --git a/cookbooks/mingw/files/default/custom_prefix.sh b/cookbooks/mingw/files/default/custom_prefix.sh new file mode 100644 index 0000000..85a1e2e --- /dev/null +++ b/cookbooks/mingw/files/default/custom_prefix.sh @@ -0,0 +1,13 @@ +# Prepend values from the parent environment to msys2 environment variables. + +export PKG_CONFIG_PATH="${PREMSYS2_PKG_CONFIG_PATH:+${PREMSYS2_PKG_CONFIG_PATH}:}${PKG_CONFIG_PATH}" + +# Instead of placing our entire windows path into msys2, we can selectively +# prepend just the important parts that we need. This also ensures that +# we don't accidentally add other unnecessary chef or git msys2 library +# files in the path. +export PATH="${PREMSYS2_PATH:+${PREMSYS2_PATH}:}${PATH}" + +# TODO: If there are other variabled we want to control like MANPATH or ACLOCALPATH, +# add those here. + diff --git a/cookbooks/mingw/files/default/pthread.h b/cookbooks/mingw/files/default/pthread.h new file mode 100644 index 0000000..ac8fb37 --- /dev/null +++ b/cookbooks/mingw/files/default/pthread.h @@ -0,0 +1,719 @@ +/* + Copyright (c) 2011-2013 mingw-w64 project + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/* + * Parts of this library are derived by: + * + * Posix Threads library for Microsoft Windows + * + * Use at own risk, there is no implied warranty to this code. + * It uses undocumented features of Microsoft Windows that can change + * at any time in the future. + * + * (C) 2010 Lockless Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of Lockless Inc. nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef WIN_PTHREADS_H +#define WIN_PTHREADS_H + +#include +#include +#include + +#include +#include +#include + +#include + +#include "pthread_compat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define __WINPTHREADS_VERSION_MAJOR 0 +#define __WINPTHREADS_VERSION_MINOR 5 +#define __WINPTHREADS_VERSION_PATCHLEVEL 0 + +/* MSB 8-bit major version, 8-bit minor version, 16-bit patch level. */ +#define __WINPTHREADS_VERSION 0x00050000 + +#if defined DLL_EXPORT && !defined WINPTHREAD_STATIC +#ifdef IN_WINPTHREAD +#define WINPTHREAD_API __declspec(dllexport) +#else +#define WINPTHREAD_API __declspec(dllimport) +#endif +#else +#define WINPTHREAD_API +#endif + +/* #define WINPTHREAD_DBG 1 */ + +/* Compatibility stuff: */ +#define RWLS_PER_THREAD 8 + +/* Error-codes. */ +#ifndef ETIMEDOUT +#define ETIMEDOUT 138 +#endif +#ifndef ENOTSUP +#define ENOTSUP 129 +#endif +#ifndef EWOULDBLOCK +#define EWOULDBLOCK 140 +#endif + +/* pthread specific defines. */ + +#define PTHREAD_CANCEL_DISABLE 0 +#define PTHREAD_CANCEL_ENABLE 0x01 + +#define PTHREAD_CANCEL_DEFERRED 0 +#define PTHREAD_CANCEL_ASYNCHRONOUS 0x02 + +#define PTHREAD_CREATE_JOINABLE 0 +#define PTHREAD_CREATE_DETACHED 0x04 + +#define PTHREAD_EXPLICIT_SCHED 0 +#define PTHREAD_INHERIT_SCHED 0x08 + +#define PTHREAD_SCOPE_PROCESS 0 +#define PTHREAD_SCOPE_SYSTEM 0x10 + +#define PTHREAD_DEFAULT_ATTR (PTHREAD_CANCEL_ENABLE) + +#define PTHREAD_CANCELED ((void *) (intptr_t) 0xDEADBEEF) + +#define _PTHREAD_NULL_THREAD ((pthread_t) 0) + +#define PTHREAD_ONCE_INIT 0 + +#define PTHREAD_DESTRUCTOR_ITERATIONS 256 +#define PTHREAD_KEYS_MAX (1<<20) + +#define PTHREAD_MUTEX_NORMAL 0 +#define PTHREAD_MUTEX_ERRORCHECK 1 +#define PTHREAD_MUTEX_RECURSIVE 2 +#define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL + +#define PTHREAD_MUTEX_SHARED 1 +#define PTHREAD_MUTEX_PRIVATE 0 + +#define PTHREAD_PRIO_NONE 0 +#define PTHREAD_PRIO_INHERIT 8 +#define PTHREAD_PRIO_PROTECT 16 +#define PTHREAD_PRIO_MULT 32 +#define PTHREAD_PROCESS_SHARED 1 +#define PTHREAD_PROCESS_PRIVATE 0 + +#define PTHREAD_MUTEX_FAST_NP PTHREAD_MUTEX_NORMAL +#define PTHREAD_MUTEX_TIMED_NP PTHREAD_MUTEX_FAST_NP +#define PTHREAD_MUTEX_ADAPTIVE_NP PTHREAD_MUTEX_FAST_NP +#define PTHREAD_MUTEX_ERRORCHECK_NP PTHREAD_MUTEX_ERRORCHECK +#define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE + +void * WINPTHREAD_API pthread_timechange_handler_np(void * dummy); +/* int WINPTHREAD_API pthread_delay_np (const struct timespec *interval); */ +int WINPTHREAD_API pthread_num_processors_np(void); +int WINPTHREAD_API pthread_set_num_processors_np(int n); + +#define PTHREAD_BARRIER_SERIAL_THREAD 1 + +/* maximum number of times a read lock may be obtained */ +#define MAX_READ_LOCKS (INT_MAX - 1) + +/* No fork() in windows - so ignore this */ +#define pthread_atfork(F1,F2,F3) 0 + +/* unsupported stuff: */ +#define pthread_mutex_getprioceiling(M, P) ENOTSUP +#define pthread_mutex_setprioceiling(M, P) ENOTSUP +#define pthread_getcpuclockid(T, C) ENOTSUP +#define pthread_attr_getguardsize(A, S) ENOTSUP +#define pthread_attr_setgaurdsize(A, S) ENOTSUP + +typedef long pthread_once_t; +typedef unsigned pthread_mutexattr_t; +typedef unsigned pthread_key_t; +typedef void *pthread_barrierattr_t; +typedef int pthread_condattr_t; +typedef int pthread_rwlockattr_t; + +/* +struct _pthread_v; + +typedef struct pthread_t { + struct _pthread_v *p; + int x; +} pthread_t; +*/ + +typedef uintptr_t pthread_t; + +typedef struct _pthread_cleanup _pthread_cleanup; +struct _pthread_cleanup +{ + void (*func)(void *); + void *arg; + _pthread_cleanup *next; +}; + +#define pthread_cleanup_push(F, A)\ +{\ + const _pthread_cleanup _pthread_cup = {(F), (A), *pthread_getclean()};\ + __sync_synchronize();\ + *pthread_getclean() = (_pthread_cleanup *) &_pthread_cup;\ + __sync_synchronize() + +/* Note that if async cancelling is used, then there is a race here */ +#define pthread_cleanup_pop(E)\ + (*pthread_getclean() = _pthread_cup.next, (E?_pthread_cup.func((pthread_once_t *)_pthread_cup.arg):0));} + +/* ------------------------------------------------------------------- + * CHEF PATCHES + * + * PREVENT REDECLERATION OF timespec + * + * The original header here assumed that struct timespec was not + * available on windows under mingw. So it redeclared timespec itself. + * + * This currently generates and error. With recent binutils, timespec + * is declared in time.h but in a slightly different manner from the + * traditional posix definition (it involves unions) to account for + * MSVC related issues. + * + * They need to go through a lot of hoops to declare the exact size + * and layout of timespec because MSVC uses a slightly more loltastic + * definition of time_t than everyone else in the universe. + * Traditionally, time_t was an integral quantity that represents the + * number of seconds since the unix epoch and it's 32-bits wide. + * This leads to the Y2038 problem where the timestamp will overflow. + * MSVC "solves" this by changing the definition of time_t to 64-bit + * on 64-bit platforms which wreaks havoc on a large number of + * structs that need to deal with the new layout (including timespec). + * Thankfully, we are using a compiler that sticks to the older + * definition of time_t - so as long as we don't attempt to link it + * to any MSVC generated libraries, we should be ok. The winpthreads + * compatibility layer that ships with TDM GCC was patched and + * compiled under these assumptions. + * + * Since we are assuming that we aren't going to generally be mixing + * MSVC generated and mingw generated dlls and TDM GCC provides us with + * good old-fashioned system libraries and dlls, we can simply delete + * the declaration of timespec here and use parts/time.h from mingwrt + * instead. + */ + +#define __need_time_t +#define __need_struct_timespec +#define _FAKE_TIME_H_SOURCED 1 +#include + +/* END OF CHEF PATCHES + * ------------------------------------------------------------------- + */ + +#ifndef SCHED_OTHER +/* Some POSIX realtime extensions, mostly stubbed */ +#define SCHED_OTHER 0 +#define SCHED_FIFO 1 +#define SCHED_RR 2 +#define SCHED_MIN SCHED_OTHER +#define SCHED_MAX SCHED_RR + +struct sched_param { + int sched_priority; +}; + +int WINPTHREAD_API sched_yield(void); +int WINPTHREAD_API sched_get_priority_min(int pol); +int WINPTHREAD_API sched_get_priority_max(int pol); +int WINPTHREAD_API sched_getscheduler(pid_t pid); +int WINPTHREAD_API sched_setscheduler(pid_t pid, int pol, const struct sched_param *param); + +#endif + +typedef struct pthread_attr_t pthread_attr_t; +struct pthread_attr_t +{ + unsigned p_state; + void *stack; + size_t s_size; + struct sched_param param; +}; + +int WINPTHREAD_API pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param); +int WINPTHREAD_API pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param); +int WINPTHREAD_API pthread_getschedparam(pthread_t thread, int *pol, struct sched_param *param); +int WINPTHREAD_API pthread_setschedparam(pthread_t thread, int pol, const struct sched_param *param); +int WINPTHREAD_API pthread_attr_setschedpolicy (pthread_attr_t *attr, int pol); +int WINPTHREAD_API pthread_attr_getschedpolicy (pthread_attr_t *attr, int *pol); + +/* synchronization objects */ +typedef void *pthread_spinlock_t; +typedef void *pthread_mutex_t; +typedef void *pthread_cond_t; +typedef void *pthread_rwlock_t; +typedef void *pthread_barrier_t; + +#define PTHREAD_MUTEX_NORMAL 0 +#define PTHREAD_MUTEX_ERRORCHECK 1 +#define PTHREAD_MUTEX_RECURSIVE 2 + +#define GENERIC_INITIALIZER ((void *) (size_t) -1) +#define GENERIC_ERRORCHECK_INITIALIZER ((void *) (size_t) -2) +#define GENERIC_RECURSIVE_INITIALIZER ((void *) (size_t) -3) +#define GENERIC_NORMAL_INITIALIZER ((void *) (size_t) -1) +#define PTHREAD_MUTEX_INITIALIZER (pthread_mutex_t)GENERIC_INITIALIZER +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER (pthread_mutex_t)GENERIC_RECURSIVE_INITIALIZER +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER (pthread_mutex_t)GENERIC_ERRORCHECK_INITIALIZER +#define PTHREAD_NORMAL_MUTEX_INITIALIZER (pthread_mutex_t)GENERIC_NORMAL_INITIALIZER +#define PTHREAD_DEFAULT_MUTEX_INITIALIZER PTHREAD_NORMAL_MUTEX_INITIALIZER +#define PTHREAD_COND_INITIALIZER (pthread_cond_t)GENERIC_INITIALIZER +#define PTHREAD_RWLOCK_INITIALIZER (pthread_rwlock_t)GENERIC_INITIALIZER +#define PTHREAD_SPINLOCK_INITIALIZER (pthread_spinlock_t)GENERIC_INITIALIZER + +extern void WINPTHREAD_API (**_pthread_key_dest)(void *); +int WINPTHREAD_API pthread_key_create(pthread_key_t *key, void (* dest)(void *)); +int WINPTHREAD_API pthread_key_delete(pthread_key_t key); +void * WINPTHREAD_API pthread_getspecific(pthread_key_t key); +int WINPTHREAD_API pthread_setspecific(pthread_key_t key, const void *value); + +pthread_t WINPTHREAD_API pthread_self(void); +int WINPTHREAD_API pthread_once(pthread_once_t *o, void (*func)(void)); +void WINPTHREAD_API pthread_testcancel(void); +int WINPTHREAD_API pthread_equal(pthread_t t1, pthread_t t2); +void WINPTHREAD_API pthread_tls_init(void); +void WINPTHREAD_API _pthread_cleanup_dest(pthread_t t); +int WINPTHREAD_API pthread_get_concurrency(int *val); +int WINPTHREAD_API pthread_set_concurrency(int val); +void WINPTHREAD_API pthread_exit(void *res); +void WINPTHREAD_API _pthread_invoke_cancel(void); +int WINPTHREAD_API pthread_cancel(pthread_t t); +int WINPTHREAD_API pthread_kill(pthread_t t, int sig); +unsigned WINPTHREAD_API _pthread_get_state(const pthread_attr_t *attr, unsigned flag); +int WINPTHREAD_API _pthread_set_state(pthread_attr_t *attr, unsigned flag, unsigned val); +int WINPTHREAD_API pthread_setcancelstate(int state, int *oldstate); +int WINPTHREAD_API pthread_setcanceltype(int type, int *oldtype); +int WINPTHREAD_API pthread_create_wrapper(void *args); +int WINPTHREAD_API pthread_create(pthread_t *th, const pthread_attr_t *attr, void *(* func)(void *), void *arg); +int WINPTHREAD_API pthread_join(pthread_t t, void **res); +int WINPTHREAD_API pthread_detach(pthread_t t); + +int WINPTHREAD_API pthread_rwlock_init(pthread_rwlock_t *rwlock_, const pthread_rwlockattr_t *attr); +int WINPTHREAD_API pthread_rwlock_wrlock(pthread_rwlock_t *l); +int WINPTHREAD_API pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock, const struct timespec *ts); +int WINPTHREAD_API pthread_rwlock_rdlock(pthread_rwlock_t *l); +int WINPTHREAD_API pthread_rwlock_timedrdlock(pthread_rwlock_t *l, const struct timespec *ts); +int WINPTHREAD_API pthread_rwlock_unlock(pthread_rwlock_t *l); +int WINPTHREAD_API pthread_rwlock_tryrdlock(pthread_rwlock_t *l); +int WINPTHREAD_API pthread_rwlock_trywrlock(pthread_rwlock_t *l); +int WINPTHREAD_API pthread_rwlock_destroy (pthread_rwlock_t *l); + +int WINPTHREAD_API pthread_cond_init(pthread_cond_t *cv, const pthread_condattr_t *a); +int WINPTHREAD_API pthread_cond_destroy(pthread_cond_t *cv); +int WINPTHREAD_API pthread_cond_signal (pthread_cond_t *cv); +int WINPTHREAD_API pthread_cond_broadcast (pthread_cond_t *cv); +int WINPTHREAD_API pthread_cond_wait (pthread_cond_t *cv, pthread_mutex_t *external_mutex); +int WINPTHREAD_API pthread_cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *external_mutex, const struct timespec *t); +int WINPTHREAD_API pthread_cond_timedwait_relative_np(pthread_cond_t *cv, pthread_mutex_t *external_mutex, const struct timespec *t); + +int WINPTHREAD_API pthread_mutex_lock(pthread_mutex_t *m); +int WINPTHREAD_API pthread_mutex_timedlock(pthread_mutex_t *m, const struct timespec *ts); +int WINPTHREAD_API pthread_mutex_unlock(pthread_mutex_t *m); +int WINPTHREAD_API pthread_mutex_trylock(pthread_mutex_t *m); +int WINPTHREAD_API pthread_mutex_init(pthread_mutex_t *m, const pthread_mutexattr_t *a); +int WINPTHREAD_API pthread_mutex_destroy(pthread_mutex_t *m); + +int WINPTHREAD_API pthread_barrier_destroy(pthread_barrier_t *b); +int WINPTHREAD_API pthread_barrier_init(pthread_barrier_t *b, const void *attr, unsigned int count); +int WINPTHREAD_API pthread_barrier_wait(pthread_barrier_t *b); + +int WINPTHREAD_API pthread_spin_init(pthread_spinlock_t *l, int pshared); +int WINPTHREAD_API pthread_spin_destroy(pthread_spinlock_t *l); +/* No-fair spinlock due to lack of knowledge of thread number. */ +int WINPTHREAD_API pthread_spin_lock(pthread_spinlock_t *l); +int WINPTHREAD_API pthread_spin_trylock(pthread_spinlock_t *l); +int WINPTHREAD_API pthread_spin_unlock(pthread_spinlock_t *l); + +int WINPTHREAD_API pthread_attr_init(pthread_attr_t *attr); +int WINPTHREAD_API pthread_attr_destroy(pthread_attr_t *attr); +int WINPTHREAD_API pthread_attr_setdetachstate(pthread_attr_t *a, int flag); +int WINPTHREAD_API pthread_attr_getdetachstate(const pthread_attr_t *a, int *flag); +int WINPTHREAD_API pthread_attr_setinheritsched(pthread_attr_t *a, int flag); +int WINPTHREAD_API pthread_attr_getinheritsched(const pthread_attr_t *a, int *flag); +int WINPTHREAD_API pthread_attr_setscope(pthread_attr_t *a, int flag); +int WINPTHREAD_API pthread_attr_getscope(const pthread_attr_t *a, int *flag); +int WINPTHREAD_API pthread_attr_getstackaddr(pthread_attr_t *attr, void **stack); +int WINPTHREAD_API pthread_attr_setstackaddr(pthread_attr_t *attr, void *stack); +int WINPTHREAD_API pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *size); +int WINPTHREAD_API pthread_attr_setstacksize(pthread_attr_t *attr, size_t size); + +int WINPTHREAD_API pthread_mutexattr_init(pthread_mutexattr_t *a); +int WINPTHREAD_API pthread_mutexattr_destroy(pthread_mutexattr_t *a); +int WINPTHREAD_API pthread_mutexattr_gettype(const pthread_mutexattr_t *a, int *type); +int WINPTHREAD_API pthread_mutexattr_settype(pthread_mutexattr_t *a, int type); +int WINPTHREAD_API pthread_mutexattr_getpshared(const pthread_mutexattr_t *a, int *type); +int WINPTHREAD_API pthread_mutexattr_setpshared(pthread_mutexattr_t * a, int type); +int WINPTHREAD_API pthread_mutexattr_getprotocol(const pthread_mutexattr_t *a, int *type); +int WINPTHREAD_API pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int type); +int WINPTHREAD_API pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *a, int * prio); +int WINPTHREAD_API pthread_mutexattr_setprioceiling(pthread_mutexattr_t *a, int prio); +int WINPTHREAD_API pthread_getconcurrency(void); +int WINPTHREAD_API pthread_setconcurrency(int new_level); + +int WINPTHREAD_API pthread_condattr_destroy(pthread_condattr_t *a); +int WINPTHREAD_API pthread_condattr_init(pthread_condattr_t *a); +int WINPTHREAD_API pthread_condattr_getpshared(const pthread_condattr_t *a, int *s); +int WINPTHREAD_API pthread_condattr_setpshared(pthread_condattr_t *a, int s); + +#ifndef __clockid_t_defined +typedef int clockid_t; +#define __clockid_t_defined 1 +#endif /* __clockid_t_defined */ + +int WINPTHREAD_API pthread_condattr_getclock (const pthread_condattr_t *attr, + clockid_t *clock_id); +int WINPTHREAD_API pthread_condattr_setclock(pthread_condattr_t *attr, + clockid_t clock_id); +int WINPTHREAD_API __pthread_clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, struct timespec *rmtp); + +int WINPTHREAD_API pthread_barrierattr_init(void **attr); +int WINPTHREAD_API pthread_barrierattr_destroy(void **attr); +int WINPTHREAD_API pthread_barrierattr_setpshared(void **attr, int s); +int WINPTHREAD_API pthread_barrierattr_getpshared(void **attr, int *s); + +/* Private extensions for analysis and internal use. */ +struct _pthread_cleanup ** WINPTHREAD_API pthread_getclean (void); +void * WINPTHREAD_API pthread_gethandle (pthread_t t); +void * WINPTHREAD_API pthread_getevent (); + +unsigned long long WINPTHREAD_API _pthread_rel_time_in_ms(const struct timespec *ts); +unsigned long long WINPTHREAD_API _pthread_time_in_ms(void); +unsigned long long WINPTHREAD_API _pthread_time_in_ms_from_timespec(const struct timespec *ts); +int WINPTHREAD_API _pthread_tryjoin (pthread_t t, void **res); +int WINPTHREAD_API pthread_rwlockattr_destroy(pthread_rwlockattr_t *a); +int WINPTHREAD_API pthread_rwlockattr_getpshared(pthread_rwlockattr_t *a, int *s); +int WINPTHREAD_API pthread_rwlockattr_init(pthread_rwlockattr_t *a); +int WINPTHREAD_API pthread_rwlockattr_setpshared(pthread_rwlockattr_t *a, int s); + +#ifndef SIG_BLOCK +#define SIG_BLOCK 0 +#endif +#ifndef SIG_UNBLOCK +#define SIG_UNBLOCK 1 +#endif +#ifndef SIG_SETMASK +#define SIG_SETMASK 2 +#endif + +#include + +#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS PTHREAD_DESTRUCTOR_ITERATIONS + +#undef _POSIX_THREAD_KEYS_MAX +#define _POSIX_THREAD_KEYS_MAX PTHREAD_KEYS_MAX + +#undef PTHREAD_THREADS_MAX +#define PTHREAD_THREADS_MAX 2019 + +#undef _POSIX_SEM_NSEMS_MAX +#define _POSIX_SEM_NSEMS_MAX 256 + +#undef SEM_NSEMS_MAX +#define SEM_NSEMS_MAX 1024 + +/* Wrap cancellation points. */ +#ifdef __WINPTRHEAD_ENABLE_WRAP_API +#define accept(...) (pthread_testcancel(), accept(__VA_ARGS__)) +#define aio_suspend(...) (pthread_testcancel(), aio_suspend(__VA_ARGS__)) +#define clock_nanosleep(...) (pthread_testcancel(), clock_nanosleep(__VA_ARGS__)) +#define close(...) (pthread_testcancel(), close(__VA_ARGS__)) +#define connect(...) (pthread_testcancel(), connect(__VA_ARGS__)) +#define creat(...) (pthread_testcancel(), creat(__VA_ARGS__)) +#define fcntl(...) (pthread_testcancel(), fcntl(__VA_ARGS__)) +#define fdatasync(...) (pthread_testcancel(), fdatasync(__VA_ARGS__)) +#define fsync(...) (pthread_testcancel(), fsync(__VA_ARGS__)) +#define getmsg(...) (pthread_testcancel(), getmsg(__VA_ARGS__)) +#define getpmsg(...) (pthread_testcancel(), getpmsg(__VA_ARGS__)) +#define lockf(...) (pthread_testcancel(), lockf(__VA_ARGS__)) +#define mg_receive(...) (pthread_testcancel(), mg_receive(__VA_ARGS__)) +#define mg_send(...) (pthread_testcancel(), mg_send(__VA_ARGS__)) +#define mg_timedreceive(...) (pthread_testcancel(), mg_timedreceive(__VA_ARGS__)) +#define mg_timessend(...) (pthread_testcancel(), mg_timedsend(__VA_ARGS__)) +#define msgrcv(...) (pthread_testcancel(), msgrecv(__VA_ARGS__)) +#define msgsnd(...) (pthread_testcancel(), msgsnd(__VA_ARGS__)) +#define msync(...) (pthread_testcancel(), msync(__VA_ARGS__)) +#define nanosleep(...) (pthread_testcancel(), nanosleep(__VA_ARGS__)) +#define open(...) (pthread_testcancel(), open(__VA_ARGS__)) +#define pause(...) (pthread_testcancel(), pause(__VA_ARGS__)) +#define poll(...) (pthread_testcancel(), poll(__VA_ARGS__)) +#define pread(...) (pthread_testcancel(), pread(__VA_ARGS__)) +#define pselect(...) (pthread_testcancel(), pselect(__VA_ARGS__)) +#define putmsg(...) (pthread_testcancel(), putmsg(__VA_ARGS__)) +#define putpmsg(...) (pthread_testcancel(), putpmsg(__VA_ARGS__)) +#define pwrite(...) (pthread_testcancel(), pwrite(__VA_ARGS__)) +#define read(...) (pthread_testcancel(), read(__VA_ARGS__)) +#define readv(...) (pthread_testcancel(), readv(__VA_ARGS__)) +#define recv(...) (pthread_testcancel(), recv(__VA_ARGS__)) +#define recvfrom(...) (pthread_testcancel(), recvfrom(__VA_ARGS__)) +#define recvmsg(...) (pthread_testcancel(), recvmsg(__VA_ARGS__)) +#define select(...) (pthread_testcancel(), select(__VA_ARGS__)) +#define sem_timedwait(...) (pthread_testcancel(), sem_timedwait(__VA_ARGS__)) +#define sem_wait(...) (pthread_testcancel(), sem_wait(__VA_ARGS__)) +#define send(...) (pthread_testcancel(), send(__VA_ARGS__)) +#define sendmsg(...) (pthread_testcancel(), sendmsg(__VA_ARGS__)) +#define sendto(...) (pthread_testcancel(), sendto(__VA_ARGS__)) +#define sigpause(...) (pthread_testcancel(), sigpause(__VA_ARGS__)) +#define sigsuspend(...) (pthread_testcancel(), sigsuspend(__VA_ARGS__)) +#define sigwait(...) (pthread_testcancel(), sigwait(__VA_ARGS__)) +#define sigwaitinfo(...) (pthread_testcancel(), sigwaitinfo(__VA_ARGS__)) +#define sleep(...) (pthread_testcancel(), sleep(__VA_ARGS__)) +//#define Sleep(...) (pthread_testcancel(), Sleep(__VA_ARGS__)) +#define system(...) (pthread_testcancel(), system(__VA_ARGS__)) +#define access(...) (pthread_testcancel(), access(__VA_ARGS__)) +#define asctime(...) (pthread_testcancel(), asctime(__VA_ARGS__)) +#define catclose(...) (pthread_testcancel(), catclose(__VA_ARGS__)) +#define catgets(...) (pthread_testcancel(), catgets(__VA_ARGS__)) +#define catopen(...) (pthread_testcancel(), catopen(__VA_ARGS__)) +#define closedir(...) (pthread_testcancel(), closedir(__VA_ARGS__)) +#define closelog(...) (pthread_testcancel(), closelog(__VA_ARGS__)) +#define ctermid(...) (pthread_testcancel(), ctermid(__VA_ARGS__)) +#define ctime(...) (pthread_testcancel(), ctime(__VA_ARGS__)) +#define dbm_close(...) (pthread_testcancel(), dbm_close(__VA_ARGS__)) +#define dbm_delete(...) (pthread_testcancel(), dbm_delete(__VA_ARGS__)) +#define dbm_fetch(...) (pthread_testcancel(), dbm_fetch(__VA_ARGS__)) +#define dbm_nextkey(...) (pthread_testcancel(), dbm_nextkey(__VA_ARGS__)) +#define dbm_open(...) (pthread_testcancel(), dbm_open(__VA_ARGS__)) +#define dbm_store(...) (pthread_testcancel(), dbm_store(__VA_ARGS__)) +#define dlclose(...) (pthread_testcancel(), dlclose(__VA_ARGS__)) +#define dlopen(...) (pthread_testcancel(), dlopen(__VA_ARGS__)) +#define endgrent(...) (pthread_testcancel(), endgrent(__VA_ARGS__)) +#define endhostent(...) (pthread_testcancel(), endhostent(__VA_ARGS__)) +#define endnetent(...) (pthread_testcancel(), endnetent(__VA_ARGS__)) +#define endprotoent(...) (pthread_testcancel(), endprotoend(__VA_ARGS__)) +#define endpwent(...) (pthread_testcancel(), endpwent(__VA_ARGS__)) +#define endservent(...) (pthread_testcancel(), endservent(__VA_ARGS__)) +#define endutxent(...) (pthread_testcancel(), endutxent(__VA_ARGS__)) +#define fclose(...) (pthread_testcancel(), fclose(__VA_ARGS__)) +#define fflush(...) (pthread_testcancel(), fflush(__VA_ARGS__)) +#define fgetc(...) (pthread_testcancel(), fgetc(__VA_ARGS__)) +#define fgetpos(...) (pthread_testcancel(), fgetpos(__VA_ARGS__)) +#define fgets(...) (pthread_testcancel(), fgets(__VA_ARGS__)) +#define fgetwc(...) (pthread_testcancel(), fgetwc(__VA_ARGS__)) +#define fgetws(...) (pthread_testcancel(), fgetws(__VA_ARGS__)) +#define fmtmsg(...) (pthread_testcancel(), fmtmsg(__VA_ARGS__)) +#define fopen(...) (pthread_testcancel(), fopen(__VA_ARGS__)) +#define fpathconf(...) (pthread_testcancel(), fpathconf(__VA_ARGS__)) +#define fprintf(...) (pthread_testcancel(), fprintf(__VA_ARGS__)) +#define fputc(...) (pthread_testcancel(), fputc(__VA_ARGS__)) +#define fputs(...) (pthread_testcancel(), fputs(__VA_ARGS__)) +#define fputwc(...) (pthread_testcancel(), fputwc(__VA_ARGS__)) +#define fputws(...) (pthread_testcancel(), fputws(__VA_ARGS__)) +#define fread(...) (pthread_testcancel(), fread(__VA_ARGS__)) +#define freopen(...) (pthread_testcancel(), freopen(__VA_ARGS__)) +#define fscanf(...) (pthread_testcancel(), fscanf(__VA_ARGS__)) +#define fseek(...) (pthread_testcancel(), fseek(__VA_ARGS__)) +#define fseeko(...) (pthread_testcancel(), fseeko(__VA_ARGS__)) +#define fsetpos(...) (pthread_testcancel(), fsetpos(__VA_ARGS__)) +#define fstat(...) (pthread_testcancel(), fstat(__VA_ARGS__)) +#define ftell(...) (pthread_testcancel(), ftell(__VA_ARGS__)) +#define ftello(...) (pthread_testcancel(), ftello(__VA_ARGS__)) +#define ftw(...) (pthread_testcancel(), ftw(__VA_ARGS__)) +#define fwprintf(...) (pthread_testcancel(), fwprintf(__VA_ARGS__)) +#define fwrite(...) (pthread_testcancel(), fwrite(__VA_ARGS__)) +#define fwscanf(...) (pthread_testcancel(), fwscanf(__VA_ARGS__)) +#define getaddrinfo(...) (pthread_testcancel(), getaddrinfo(__VA_ARGS__)) +#define getc(...) (pthread_testcancel(), getc(__VA_ARGS__)) +#define getc_unlocked(...) (pthread_testcancel(), getc_unlocked(__VA_ARGS__)) +#define getchar(...) (pthread_testcancel(), getchar(__VA_ARGS__)) +#define getchar_unlocked(...) (pthread_testcancel(), getchar_unlocked(__VA_ARGS__)) +#define getcwd(...) (pthread_testcancel(), getcwd(__VA_ARGS__)) +#define getdate(...) (pthread_testcancel(), getdate(__VA_ARGS__)) +#define getgrent(...) (pthread_testcancel(), getgrent(__VA_ARGS__)) +#define getgrgid(...) (pthread_testcancel(), getgrgid(__VA_ARGS__)) +#define getgrgid_r(...) (pthread_testcancel(), getgrgid_r(__VA_ARGS__)) +#define gergrnam(...) (pthread_testcancel(), getgrnam(__VA_ARGS__)) +#define getgrnam_r(...) (pthread_testcancel(), getgrnam_r(__VA_ARGS__)) +#define gethostbyaddr(...) (pthread_testcancel(), gethostbyaddr(__VA_ARGS__)) +#define gethostbyname(...) (pthread_testcancel(), gethostbyname(__VA_ARGS__)) +#define gethostent(...) (pthread_testcancel(), gethostent(__VA_ARGS__)) +#define gethostid(...) (pthread_testcancel(), gethostid(__VA_ARGS__)) +#define gethostname(...) (pthread_testcancel(), gethostname(__VA_ARGS__)) +#define getlogin(...) (pthread_testcancel(), getlogin(__VA_ARGS__)) +#define getlogin_r(...) (pthread_testcancel(), getlogin_r(__VA_ARGS__)) +#define getnameinfo(...) (pthread_testcancel(), getnameinfo(__VA_ARGS__)) +#define getnetbyaddr(...) (pthread_testcancel(), getnetbyaddr(__VA_ARGS__)) +#define getnetbyname(...) (pthread_testcancel(), getnetbyname(__VA_ARGS__)) +#define getnetent(...) (pthread_testcancel(), getnetent(__VA_ARGS__)) +#define getopt(...) (pthread_testcancel(), getopt(__VA_ARGS__)) +#define getprotobyname(...) (pthread_testcancel(), getprotobyname(__VA_ARGS__)) +#define getprotobynumber(...) (pthread_testcancel(), getprotobynumber(__VA_ARGS__)) +#define getprotoent(...) (pthread_testcancel(), getprotoent(__VA_ARGS__)) +#define getpwent(...) (pthread_testcancel(), getpwent(__VA_ARGS__)) +#define getpwnam(...) (pthread_testcancel(), getpwnam(__VA_ARGS__)) +#define getpwnam_r(...) (pthread_testcancel(), getpwnam_r(__VA_ARGS__)) +#define getpwuid(...) (pthread_testcancel(), getpwuid(__VA_ARGS__)) +#define getpwuid_r(...) (pthread_testcancel(), getpwuid_r(__VA_ARGS__)) +#define gets(...) (pthread_testcancel(), gets(__VA_ARGS__)) +#define getservbyname(...) (pthread_testcancel(), getservbyname(__VA_ARGS__)) +#define getservbyport(...) (pthread_testcancel(), getservbyport(__VA_ARGS__)) +#define getservent(...) (pthread_testcancel(), getservent(__VA_ARGS__)) +#define getutxent(...) (pthread_testcancel(), getutxent(__VA_ARGS__)) +#define getutxid(...) (pthread_testcancel(), getutxid(__VA_ARGS__)) +#define getutxline(...) (pthread_testcancel(), getutxline(__VA_ARGS__)) +#undef getwc +#define getwc(...) (pthread_testcancel(), getwc(__VA_ARGS__)) +#undef getwchar +#define getwchar(...) (pthread_testcancel(), getwchar(__VA_ARGS__)) +#define getwd(...) (pthread_testcancel(), getwd(__VA_ARGS__)) +#define glob(...) (pthread_testcancel(), glob(__VA_ARGS__)) +#define iconv_close(...) (pthread_testcancel(), iconv_close(__VA_ARGS__)) +#define iconv_open(...) (pthread_testcancel(), iconv_open(__VA_ARGS__)) +#define ioctl(...) (pthread_testcancel(), ioctl(__VA_ARGS__)) +#define link(...) (pthread_testcancel(), link(__VA_ARGS__)) +#define localtime(...) (pthread_testcancel(), localtime(__VA_ARGS__)) +#define lseek(...) (pthread_testcancel(), lseek(__VA_ARGS__)) +#define lstat(...) (pthread_testcancel(), lstat(__VA_ARGS__)) +#define mkstemp(...) (pthread_testcancel(), mkstemp(__VA_ARGS__)) +#define nftw(...) (pthread_testcancel(), nftw(__VA_ARGS__)) +#define opendir(...) (pthread_testcancel(), opendir(__VA_ARGS__)) +#define openlog(...) (pthread_testcancel(), openlog(__VA_ARGS__)) +#define pathconf(...) (pthread_testcancel(), pathconf(__VA_ARGS__)) +#define pclose(...) (pthread_testcancel(), pclose(__VA_ARGS__)) +#define perror(...) (pthread_testcancel(), perror(__VA_ARGS__)) +#define popen(...) (pthread_testcancel(), popen(__VA_ARGS__)) +#define posix_fadvise(...) (pthread_testcancel(), posix_fadvise(__VA_ARGS__)) +#define posix_fallocate(...) (pthread_testcancel(), posix_fallocate(__VA_ARGS__)) +#define posix_madvise(...) (pthread_testcancel(), posix_madvise(__VA_ARGS__)) +#define posix_openpt(...) (pthread_testcancel(), posix_openpt(__VA_ARGS__)) +#define posix_spawn(...) (pthread_testcancel(), posix_spawn(__VA_ARGS__)) +#define posix_spawnp(...) (pthread_testcancel(), posix_spawnp(__VA_ARGS__)) +#define posix_trace_clear(...) (pthread_testcancel(), posix_trace_clear(__VA_ARGS__)) +#define posix_trace_close(...) (pthread_testcancel(), posix_trace_close(__VA_ARGS__)) +#define posix_trace_create(...) (pthread_testcancel(), posix_trace_create(__VA_ARGS__)) +#define posix_trace_create_withlog(...) (pthread_testcancel(), posix_trace_create_withlog(__VA_ARGS__)) +#define posix_trace_eventtypelist_getne(...) (pthread_testcancel(), posix_trace_eventtypelist_getne(__VA_ARGS__)) +#define posix_trace_eventtypelist_rewin(...) (pthread_testcancel(), posix_trace_eventtypelist_rewin(__VA_ARGS__)) +#define posix_trace_flush(...) (pthread_testcancel(), posix_trace_flush(__VA_ARGS__)) +#define posix_trace_get_attr(...) (pthread_testcancel(), posix_trace_get_attr(__VA_ARGS__)) +#define posix_trace_get_filter(...) (pthread_testcancel(), posix_trace_get_filter(__VA_ARGS__)) +#define posix_trace_get_status(...) (pthread_testcancel(), posix_trace_get_status(__VA_ARGS__)) +#define posix_trace_getnext_event(...) (pthread_testcancel(), posix_trace_getnext_event(__VA_ARGS__)) +#define posix_trace_open(...) (pthread_testcancel(), posix_trace_open(__VA_ARGS__)) +#define posix_trace_rewind(...) (pthread_testcancel(), posix_trace_rewind(__VA_ARGS__)) +#define posix_trace_setfilter(...) (pthread_testcancel(), posix_trace_setfilter(__VA_ARGS__)) +#define posix_trace_shutdown(...) (pthread_testcancel(), posix_trace_shutdown(__VA_ARGS__)) +#define posix_trace_timedgetnext_event(...) (pthread_testcancel(), posix_trace_timedgetnext_event(__VA_ARGS__)) +#define posix_typed_mem_open(...) (pthread_testcancel(), posix_typed_mem_open(__VA_ARGS__)) +#define printf(...) (pthread_testcancel(), printf(__VA_ARGS__)) +#define putc(...) (pthread_testcancel(), putc(__VA_ARGS__)) +#define putc_unlocked(...) (pthread_testcancel(), putc_unlocked(__VA_ARGS__)) +#define putchar(...) (pthread_testcancel(), putchar(__VA_ARGS__)) +#define putchar_unlocked(...) (pthread_testcancel(), putchar_unlocked(__VA_ARGS__)) +#define puts(...) (pthread_testcancel(), puts(__VA_ARGS__)) +#define pututxline(...) (pthread_testcancel(), pututxline(__VA_ARGS__)) +#undef putwc +#define putwc(...) (pthread_testcancel(), putwc(__VA_ARGS__)) +#undef putwchar +#define putwchar(...) (pthread_testcancel(), putwchar(__VA_ARGS__)) +#define readdir(...) (pthread_testcancel(), readdir(__VA_ARSG__)) +#define readdir_r(...) (pthread_testcancel(), readdir_r(__VA_ARGS__)) +#define remove(...) (pthread_testcancel(), remove(__VA_ARGS__)) +#define rename(...) (pthread_testcancel(), rename(__VA_ARGS__)) +#define rewind(...) (pthread_testcancel(), rewind(__VA_ARGS__)) +#define rewinddir(...) (pthread_testcancel(), rewinddir(__VA_ARGS__)) +#define scanf(...) (pthread_testcancel(), scanf(__VA_ARGS__)) +#define seekdir(...) (pthread_testcancel(), seekdir(__VA_ARGS__)) +#define semop(...) (pthread_testcancel(), semop(__VA_ARGS__)) +#define setgrent(...) (pthread_testcancel(), setgrent(__VA_ARGS__)) +#define sethostent(...) (pthread_testcancel(), sethostemt(__VA_ARGS__)) +#define setnetent(...) (pthread_testcancel(), setnetent(__VA_ARGS__)) +#define setprotoent(...) (pthread_testcancel(), setprotoent(__VA_ARGS__)) +#define setpwent(...) (pthread_testcancel(), setpwent(__VA_ARGS__)) +#define setservent(...) (pthread_testcancel(), setservent(__VA_ARGS__)) +#define setutxent(...) (pthread_testcancel(), setutxent(__VA_ARGS__)) +#define stat(...) (pthread_testcancel(), stat(__VA_ARGS__)) +#define strerror(...) (pthread_testcancel(), strerror(__VA_ARGS__)) +#define strerror_r(...) (pthread_testcancel(), strerror_r(__VA_ARGS__)) +#define strftime(...) (pthread_testcancel(), strftime(__VA_ARGS__)) +#define symlink(...) (pthread_testcancel(), symlink(__VA_ARGS__)) +#define sync(...) (pthread_testcancel(), sync(__VA_ARGS__)) +#define syslog(...) (pthread_testcancel(), syslog(__VA_ARGS__)) +#define tmpfile(...) (pthread_testcancel(), tmpfile(__VA_ARGS__)) +#define tmpnam(...) (pthread_testcancel(), tmpnam(__VA_ARGS__)) +#define ttyname(...) (pthread_testcancel(), ttyname(__VA_ARGS__)) +#define ttyname_r(...) (pthread_testcancel(), ttyname_r(__VA_ARGS__)) +#define tzset(...) (pthread_testcancel(), tzset(__VA_ARGS__)) +#define ungetc(...) (pthread_testcancel(), ungetc(__VA_ARGS__)) +#define ungetwc(...) (pthread_testcancel(), ungetwc(__VA_ARGS__)) +#define unlink(...) (pthread_testcancel(), unlink(__VA_ARGS__)) +#define vfprintf(...) (pthread_testcancel(), vfprintf(__VA_ARGS__)) +#define vfwprintf(...) (pthread_testcancel(), vfwprintf(__VA_ARGS__)) +#define vprintf(...) (pthread_testcancel(), vprintf(__VA_ARGS__)) +#define vwprintf(...) (pthread_testcancel(), vwprintf(__VA_ARGS__)) +#define wcsftime(...) (pthread_testcancel(), wcsftime(__VA_ARGS__)) +#define wordexp(...) (pthread_testcancel(), wordexp(__VA_ARGS__)) +#define wprintf(...) (pthread_testcancel(), wprintf(__VA_ARGS__)) +#define wscanf(...) (pthread_testcancel(), wscanf(__VA_ARGS__)) +#endif + +/* We deal here with a gcc issue for posix threading on Windows. + We would need to change here gcc's gthr-posix.h header, but this + got rejected. So we deal it within this header. */ +#ifdef _GTHREAD_USE_MUTEX_INIT_FUNC +#undef _GTHREAD_USE_MUTEX_INIT_FUNC +#endif +#define _GTHREAD_USE_MUTEX_INIT_FUNC 1 + +#ifdef __cplusplus +} +#endif + +#endif /* WIN_PTHREADS_H */ diff --git a/cookbooks/mingw/files/default/time.h b/cookbooks/mingw/files/default/time.h new file mode 100644 index 0000000..1800b43 --- /dev/null +++ b/cookbooks/mingw/files/default/time.h @@ -0,0 +1,297 @@ +/* + * time.h + * + * Type definitions and function declarations relating to date and time. + * + * $Id: time.h,v ffe8d63c87e3 2015/05/18 12:49:39 keithmarshall $ + * + * Written by Rob Savoye + * Copyright (C) 1997-2007, 2011, 2015, MinGW.org Project. + * + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice, this permission notice, and the following + * disclaimer shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ +#ifndef _TIME_H +#define _TIME_H + +/* All the headers include this file. */ +#include <_mingw.h> + +/* Number of clock ticks per second. A clock tick is the unit by which + * processor time is measured and is returned by 'clock'. + */ +#define CLOCKS_PER_SEC ((clock_t)(1000)) +#define CLK_TCK CLOCKS_PER_SEC + +#ifndef RC_INVOKED +/* + * Some elements declared in time.h may also be required by other + * header files, without necessarily including time.h itself; such + * elements are declared in the local parts/time.h system header file. + * Declarations for such elements must be selected prior to inclusion: + */ +#define __need_time_t +#define __need_struct_timespec +#include + +/* time.h is also required to duplicate the following type definitions, + * which are nominally defined in stddef.h + */ +#define __need_NULL +#define __need_wchar_t +#define __need_size_t +#include + +/* A type for measuring processor time in clock ticks; (no need to + * guard this, since it isn't defined elsewhere). + */ +typedef long clock_t; + +#ifndef _TM_DEFINED +/* + * A structure for storing all kinds of useful information about the + * current (or another) time. + */ +struct tm +{ + int tm_sec; /* Seconds: 0-59 (K&R says 0-61?) */ + int tm_min; /* Minutes: 0-59 */ + int tm_hour; /* Hours since midnight: 0-23 */ + int tm_mday; /* Day of the month: 1-31 */ + int tm_mon; /* Months *since* january: 0-11 */ + int tm_year; /* Years since 1900 */ + int tm_wday; /* Days since Sunday (0-6) */ + int tm_yday; /* Days since Jan. 1: 0-365 */ + int tm_isdst; /* +1 Daylight Savings Time, 0 No DST, + * -1 don't know */ +}; +#define _TM_DEFINED +#endif + +_BEGIN_C_DECLS + +_CRTIMP clock_t __cdecl __MINGW_NOTHROW clock (void); +#if __MSVCRT_VERSION__ < 0x0800 +_CRTIMP time_t __cdecl __MINGW_NOTHROW time (time_t*); +_CRTIMP double __cdecl __MINGW_NOTHROW difftime (time_t, time_t); +_CRTIMP time_t __cdecl __MINGW_NOTHROW mktime (struct tm*); +#endif + +/* + * These functions write to and return pointers to static buffers that may + * be overwritten by other function calls. Yikes! + * + * NOTE: localtime, and perhaps the others of the four functions grouped + * below may return NULL if their argument is not 'acceptable'. Also note + * that calling asctime with a NULL pointer will produce an Invalid Page + * Fault and crap out your program. Guess how I know. Hint: stat called on + * a directory gives 'invalid' times in st_atime etc... + */ +_CRTIMP char* __cdecl __MINGW_NOTHROW asctime (const struct tm*); +#if __MSVCRT_VERSION__ < 0x0800 +_CRTIMP char* __cdecl __MINGW_NOTHROW ctime (const time_t*); +_CRTIMP struct tm* __cdecl __MINGW_NOTHROW gmtime (const time_t*); +_CRTIMP struct tm* __cdecl __MINGW_NOTHROW localtime (const time_t*); +#endif + +_CRTIMP size_t __cdecl __MINGW_NOTHROW strftime (char*, size_t, const char*, const struct tm*); + +#ifndef __STRICT_ANSI__ + +extern _CRTIMP void __cdecl __MINGW_NOTHROW _tzset (void); + +#ifndef _NO_OLDNAMES +extern _CRTIMP void __cdecl __MINGW_NOTHROW tzset (void); +#endif + +_CRTIMP char* __cdecl __MINGW_NOTHROW _strdate(char*); +_CRTIMP char* __cdecl __MINGW_NOTHROW _strtime(char*); + +/* These require newer versions of msvcrt.dll (6.10 or higher). */ +#if __MSVCRT_VERSION__ >= 0x0601 +_CRTIMP __time64_t __cdecl __MINGW_NOTHROW _time64( __time64_t*); +_CRTIMP __time64_t __cdecl __MINGW_NOTHROW _mktime64 (struct tm*); +_CRTIMP char* __cdecl __MINGW_NOTHROW _ctime64 (const __time64_t*); +_CRTIMP struct tm* __cdecl __MINGW_NOTHROW _gmtime64 (const __time64_t*); +_CRTIMP struct tm* __cdecl __MINGW_NOTHROW _localtime64 (const __time64_t*); +#endif /* __MSVCRT_VERSION__ >= 0x0601 */ + +/* These require newer versions of msvcrt.dll (8.00 or higher). */ +#if __MSVCRT_VERSION__ >= 0x0800 +_CRTIMP __time32_t __cdecl __MINGW_NOTHROW _time32 (__time32_t*); +_CRTIMP double __cdecl __MINGW_NOTHROW _difftime32 (__time32_t, __time32_t); +_CRTIMP double __cdecl __MINGW_NOTHROW _difftime64 (__time64_t, __time64_t); +_CRTIMP __time32_t __cdecl __MINGW_NOTHROW _mktime32 (struct tm*); +_CRTIMP __time32_t __cdecl __MINGW_NOTHROW _mkgmtime32 (struct tm*); +_CRTIMP __time64_t __cdecl __MINGW_NOTHROW _mkgmtime64 (struct tm*); +_CRTIMP char* __cdecl __MINGW_NOTHROW _ctime32 (const __time32_t*); +_CRTIMP struct tm* __cdecl __MINGW_NOTHROW _gmtime32 (const __time32_t*); +_CRTIMP struct tm* __cdecl __MINGW_NOTHROW _localtime32 (const __time32_t*); +#ifndef _USE_32BIT_TIME_T +_CRTALIAS time_t __cdecl __MINGW_NOTHROW time (time_t* _v) { return(_time64 (_v)); } +_CRTALIAS double __cdecl __MINGW_NOTHROW difftime (time_t _v1, time_t _v2) { return(_difftime64 (_v1,_v2)); } +_CRTALIAS time_t __cdecl __MINGW_NOTHROW mktime (struct tm* _v) { return(_mktime64 (_v)); } +_CRTALIAS time_t __cdecl __MINGW_NOTHROW _mkgmtime (struct tm* _v) { return(_mkgmtime64 (_v)); } +_CRTALIAS char* __cdecl __MINGW_NOTHROW ctime (const time_t* _v) { return(_ctime64 (_v)); } +_CRTALIAS struct tm* __cdecl __MINGW_NOTHROW gmtime (const time_t* _v) { return(_gmtime64 (_v)); } +_CRTALIAS struct tm* __cdecl __MINGW_NOTHROW localtime (const time_t* _v) { return(_localtime64 (_v)); } +#else +_CRTALIAS time_t __cdecl __MINGW_NOTHROW time (time_t* _v) { return(_time32 (_v)); } +_CRTALIAS double __cdecl __MINGW_NOTHROW difftime (time_t _v1, time_t _v2) { return(_difftime32 (_v1,_v2)); } +_CRTALIAS time_t __cdecl __MINGW_NOTHROW mktime (struct tm* _v) { return(_mktime32 (_v)); } +_CRTALIAS time_t __cdecl __MINGW_NOTHROW _mkgmtime (struct tm* _v) { return(_mkgmtime32 (_v)); } +_CRTALIAS char* __cdecl __MINGW_NOTHROW ctime (const time_t* _v) { return(_ctime32 (_v)); } +_CRTALIAS struct tm* __cdecl __MINGW_NOTHROW gmtime (const time_t* _v) { return(_gmtime32 (_v)); } +_CRTALIAS struct tm* __cdecl __MINGW_NOTHROW localtime (const time_t* _v) { return(_localtime32 (_v)); } +#endif /* !_USE_32BIT_TIME_T */ +#endif /* __MSVCRT_VERSION__ >= 0x0800 */ + +/* _daylight: non zero if daylight savings time is used. + * _timezone: difference in seconds between GMT and local time. + * _tzname: standard/daylight savings time zone names (an array with two + * elements). + */ +#ifdef __MSVCRT__ + +/* These are for compatibility with pre-VC 5.0 suppied MSVCRT. */ +extern _CRTIMP int* __cdecl __MINGW_NOTHROW __p__daylight (void); +extern _CRTIMP long* __cdecl __MINGW_NOTHROW __p__timezone (void); +extern _CRTIMP char** __cdecl __MINGW_NOTHROW __p__tzname (void); + +__MINGW_IMPORT int _daylight; +__MINGW_IMPORT long _timezone; +__MINGW_IMPORT char *_tzname[2]; + +#else /* not __MSVCRT (ie. crtdll) */ + +#ifndef __DECLSPEC_SUPPORTED + +extern int* _imp___daylight_dll; +extern long* _imp___timezone_dll; +extern char** _imp___tzname; + +#define _daylight (*_imp___daylight_dll) +#define _timezone (*_imp___timezone_dll) +#define _tzname (*_imp___tzname) + +#else /* __DECLSPEC_SUPPORTED */ + +__MINGW_IMPORT int _daylight_dll; +__MINGW_IMPORT long _timezone_dll; +__MINGW_IMPORT char* _tzname[2]; + +#define _daylight _daylight_dll +#define _timezone _timezone_dll + +#endif /* __DECLSPEC_SUPPORTED */ +#endif /* ! __MSVCRT__ */ +#endif /* ! __STRICT_ANSI__ */ + +#ifndef _NO_OLDNAMES +#ifdef __MSVCRT__ + +/* These go in the oldnames import library for MSVCRT. + */ +__MINGW_IMPORT int daylight; +__MINGW_IMPORT long timezone; +__MINGW_IMPORT char *tzname[2]; + +#else /* ! __MSVCRT__ */ +/* + * CRTDLL is royally messed up when it comes to these macros. + * TODO: import and alias these via oldnames import library instead + * of macros. + */ +#define daylight _daylight +/* + * NOTE: timezone not defined as a macro because it would conflict with + * struct timezone in sys/time.h. Also, tzname used to a be macro, but + * now it's in moldname. + */ +__MINGW_IMPORT char *tzname[2]; + +#endif /* ! __MSVCRT__ */ +#endif /* ! _NO_OLDNAMES */ + +#ifndef _WTIME_DEFINED +/* wide function prototypes, also declared in wchar.h */ +#ifndef __STRICT_ANSI__ +#ifdef __MSVCRT__ +_CRTIMP wchar_t* __cdecl __MINGW_NOTHROW _wasctime(const struct tm*); +#if __MSVCRT_VERSION__ < 0x0800 +_CRTIMP wchar_t* __cdecl __MINGW_NOTHROW _wctime(const time_t*); +#endif +_CRTIMP wchar_t* __cdecl __MINGW_NOTHROW _wstrdate(wchar_t*); +_CRTIMP wchar_t* __cdecl __MINGW_NOTHROW _wstrtime(wchar_t*); +#if __MSVCRT_VERSION__ >= 0x0601 +_CRTIMP wchar_t* __cdecl __MINGW_NOTHROW _wctime64 (const __time64_t*); +#endif +#if __MSVCRT_VERSION__ >= 0x0800 +_CRTIMP wchar_t* __cdecl __MINGW_NOTHROW _wctime32 (const __time32_t*); +#ifndef _USE_32BIT_TIME_T +_CRTALIAS wchar_t* __cdecl __MINGW_NOTHROW _wctime (const time_t* _v) { return(_wctime64 (_v)); } +#else +_CRTALIAS wchar_t* __cdecl __MINGW_NOTHROW _wctime (const time_t* _v) { return(_wctime32 (_v)); } +#endif +#endif /* __MSVCRT_VERSION__ >= 0x0800 */ +#endif /* __MSVCRT__ */ +#endif /* __STRICT_ANSI__ */ +_CRTIMP size_t __cdecl __MINGW_NOTHROW wcsftime (wchar_t*, size_t, const wchar_t*, const struct tm*); +#define _WTIME_DEFINED +#endif /* _WTIME_DEFINED */ + +_END_C_DECLS + +/* ------------------------------------------------------------------- + * CHEF PATCHES + * + * PROVIDE clock_gettime ETC. IN time.h FOR POSIX COMPLIANCE. + * + * This code was copied from the 64-bit TDM gcc compiler headers. It + * is here to allow certain libraries (like libxslt) to compile + * because they assume that they are only going to be built on a POSIX + * system. The C99 standards do not require that these functions be + * available but most POSIX systems provide them unless strict x-play + * compatibility is requested. + * + * On windows, configure could possibly identify that these functions + * are unavailable but since it tests for function availability to + * attempting to link a binary with said functions, these tests + * succeed with our TDM mingw runtime (because we indeed support these + * posix compatibility methods). Hence we pretend like we are a POSIX + * compliant system and export these methods. + */ + +/* POSIX 2008 says clock_gettime and timespec are defined in time.h header, + but other systems - like Linux, Solaris, etc - tend to declare such + recent extensions only if the following guards are met. */ +#if !defined(IN_WINPTHREAD) && \ + ((!defined(_STRICT_STDC) && !defined(__XOPEN_OR_POSIX)) || \ + (_POSIX_C_SOURCE > 2) || defined(__EXTENSIONS__)) +#include +#endif + +/* END OF CHEF PATCHES + * ------------------------------------------------------------------- + */ + +#endif /* ! RC_INVOKED */ +#endif /* ! _TIME_H: $RCSfile: time.h,v $: end of file */ diff --git a/cookbooks/mingw/libraries/_helper.rb b/cookbooks/mingw/libraries/_helper.rb new file mode 100644 index 0000000..4a90fa4 --- /dev/null +++ b/cookbooks/mingw/libraries/_helper.rb @@ -0,0 +1,38 @@ +# +# Cookbook:: mingw +# Library:: _helper +# +# Copyright:: 2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +module Mingw + module Helper + def win_friendly_path(path) + path.gsub(::File::SEPARATOR, ::File::ALT_SEPARATOR || '\\') if path + end + + def archive_name(source) + url = ::URI.parse(source) + ::File.basename(::URI.unescape(url.path)) + end + + def tar_name(source) + aname = archive_name(source) + ::File.basename(aname, ::File.extname(aname)) + end + end +end + +Chef::Resource.send(:include, Mingw::Helper) diff --git a/cookbooks/mingw/metadata.json b/cookbooks/mingw/metadata.json new file mode 100644 index 0000000..b2cccf0 --- /dev/null +++ b/cookbooks/mingw/metadata.json @@ -0,0 +1 @@ +{"name":"mingw","version":"2.1.0","description":"Installs a mingw/msys based toolchain on windows","long_description":"# mingw Cookbook\n\n[![Cookbook Version](http://img.shields.io/cookbook/v/mingw.svg)][cookbook] [![Build Status](http://img.shields.io/travis/chef-cookbooks/mingw.svg?branch=master)][travis]\n\nInstalls a mingw/msys based compiler tools chain on windows. This is required for compiling C software from source.\n\n## Requirements\n\n### Platforms\n\n- Windows\n\n### Chef\n\n- Chef 12.5+\n\n### Cookbooks\n\n- seven_zip\n\n## Usage\n\nAdd this cookbook as a dependency to your cookbook in its `metadata.rb` and include the default recipe in one of your recipes.\n\n```ruby\n# metadata.rb\ndepends 'mingw'\n```\n\n```ruby\n# your recipe.rb\ninclude_recipe 'mingw::default'\n```\n\nUse the `msys2_package` resource in any recipe to fetch msys2 based packages. Use the `mingw_get` resource in any recipe to fetch mingw packages. Use the `mingw_tdm_gcc` resource to fetch a version of the TDM GCC compiler.\n\nBy default, you should prefer the msys2 packages as they are newer and better supported. C/C++ compilers on windows use various different exception formats and you need to pick the right one for your task. In the 32-bit world, you have SJLJ (set-jump/long-jump) based exception handling and DWARF-2 (shortened to DW2) based exception handling. SJLJ produces code that can happily throw exceptions across stack frames of code compiled by MSVC. DW2 involves more extensive metadata but produces code that cannot unwind MSVC generated stack-frames - hence you need to ensure that you don't have any code that throws across a \"system call\". Certain languages and runtimes have specific requirements as to the exception format supported. As an example, if you are building code for Rust, you will probably need a modern gcc from msys2 with DW2 support as that's what the panic/exception formatter in Rust depends on. In a 64-bit world, you may still use SJLJ but compilers all commonly support SEH (structured exception handling).\n\nOf course, to further complicate matters, different versions of different compilers support different exception handling. The default compilers that come with mingw_get are 32-bit only compilers and support DW2\\. The TDM compilers come in 3 flavors: a 32-bit only version with SJLJ support, a 32-bit only version with DW2 support and a \"multilib\" compiler which supports only SJLJ in 32-bit mode but can produce 64-bit SEH code. The standard library support varies drastically between these various compiler flavors (even within the same version). In msys2, you can install a mingw-w64 based compilers for either 32-bit DW2 support or 64-bit SEH support. If all this hurts your brain, I can only apologize.\n\n## Resources\n\n### msys2_package\n\n- ':install' - Installs an msys2 package using pacman.\n- ':remove' - Uninstalls any existing msys2 package.\n- ':upgrade' - Upgrades the specified package using pacman.\n\nAll options also automatically attempt to install a 64-bit based msys2 base file system at the root path specified. Note that you probably won't need a \"32-bit\" msys2 unless you are actually on a 32-bit only platform. You can still install both 32 and 64-bit compilers and libraries in a 64-bit msys2 base file system.\n\n#### Attributes\n\n- `node['msys2']['url']` - overrides the url from which to download the package.\n- `node['msys2']['checksum']` - overrides the checksum used to verify the downloaded package.\n\n#### Parameters\n\n- `package` - An msys2 pacman package (or meta-package) to fetch and install. You may use a legal package wild-card pattern here if you are installing. This is the name attribute.\n- `root` - The root directory where msys2 tools will be installed. This directory must not contain any spaces in order to pacify old posix tools and most Makefiles.\n\n#### Examples\n\nTo get the core msys2 developer tools in `C:\\msys2`\n\n```ruby\nmsys2_package 'base-devel' do\n root 'C:\\msys2'\nend\n```\n\n### mingw_get\n\n#### Actions\n\n- `:install` - Installs a mingw package from sourceforge using mingw-get.exe.\n- `:remove` - Uninstalls a mingw package.\n- `:upgrade` - Upgrades a mingw package (even to a lower version).\n\n#### Parameters\n\n- `package` - A mingw-get package (or meta-package) to fetch and install. You may use a legal package wild-card pattern here if you are installing. This is the name attribute.\n- `root` - The root directory where msys and mingw tools will be installed. This directory must not contain any spaces in order to pacify old posix tools and most Makefiles.\n\n#### Examples\n\nTo get the core msys developer tools in `C:\\mingw32`\n\n```ruby\nmingw_get 'msys-base=2013072300-msys-bin.meta' do\n root 'C:\\mingw32'\nend\n```\n\n### mingw_tdm_gcc\n\n#### Actions\n\n- `:install` - Installs the TDM compiler toolchain at the given path. This only gives you a compiler. If you need any support tooling such as make/grep/awk/bash etc., see `mingw_get`.\n\n#### Parameters\n\n- `flavor` - Either `:sjlj_32` or `:seh_sjlj_64`. TDM-64 is a 32/64-bit multi-lib \"cross-compiler\" toolchain that builds 64-bit by default. It uses structured exception handling (SEH) in 64-bit code and setjump-longjump exception handling (SJLJ) in 32-bit code. TDM-32 only builds 32-bit binaries and uses SJLJ.\n- `root` - The root directory where compiler tools and runtime will be installed. This directory must not contain any spaces in order to pacify old posix tools and most Makefiles.\n- `version` - The version of the compiler to fetch and install. This is the name attribute. Currently, '5.1.0' is supported.\n\n#### Examples\n\nTo get the 32-bit TDM GCC compiler in `C:\\mingw32`\n\n```ruby\nmingw_tdm_gcc '5.1.0' do\n flavor :sjlj_32\n root 'C:\\mingw32'\nend\n```\n\n## License & Authors\n\n**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io))\n\n**Copyright:** 2009-2016, Chef Software, Inc.\n\n```\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n\n[cookbook]: https://supermarket.chef.io/cookbooks/mingw\n[travis]: http://travis-ci.org/chef-cookbooks/mingw\n","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"windows":">= 0.0.0"},"dependencies":{"seven_zip":">= 0.0.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/chef-cookbooks/mingw","issues_url":"https://github.com/chef-cookbooks/mingw/issues","chef_version":[[">= 12.5"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/mingw/recipes/default.rb b/cookbooks/mingw/recipes/default.rb new file mode 100644 index 0000000..33426f0 --- /dev/null +++ b/cookbooks/mingw/recipes/default.rb @@ -0,0 +1,19 @@ +# +# Cookbook:: mingw +# Recipe:: default +# +# Copyright:: 2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include_recipe 'seven_zip::default' diff --git a/cookbooks/mingw/resources/get.rb b/cookbooks/mingw/resources/get.rb new file mode 100644 index 0000000..bd77efe --- /dev/null +++ b/cookbooks/mingw/resources/get.rb @@ -0,0 +1,56 @@ +# +# Cookbook:: mingw +# Resource:: get +# +# Copyright:: 2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Installs the core msys utilities needed for mingw/git/any other posix +# based toolchain at a desired location using mingw-get.exe. + +property :package, String, name_property: true +property :root, String, required: true + +resource_name :mingw_get + +action_class do + def mingw_do_action(action_cmd) + seven_zip_archive "fetching mingw-get to #{win_friendly_path(root)}" do + source 'http://iweb.dl.sourceforge.net/project/mingw/Installer/mingw-get/mingw-get-0.6.2-beta-20131004-1/mingw-get-0.6.2-mingw32-beta-20131004-1-bin.zip' + path root + checksum '2e0e9688d42adc68c5611759947e064156e169ff871816cae52d33ee0655826d' + not_if do + ::File.exist?(::File.join(root, 'bin/mingw-get.exe')) + end + end + + execute "performing #{action_cmd} for #{package}" do + command ".\\bin\\mingw-get.exe -v #{action_cmd} #{package}" + cwd root + end + end +end + +action :install do + mingw_do_action('install') +end + +action :upgrade do + mingw_do_action('upgrade') +end + +action :remove do + mingw_do_action('remove') +end diff --git a/cookbooks/mingw/resources/msys2_package.rb b/cookbooks/mingw/resources/msys2_package.rb new file mode 100644 index 0000000..ddad055 --- /dev/null +++ b/cookbooks/mingw/resources/msys2_package.rb @@ -0,0 +1,139 @@ +# +# Cookbook:: mingw +# Resource:: msys2_package +# +# Copyright:: 2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Installs msys2 base system and installs/upgrades packages within in. +# +# Where's the version flag? Where's idempotence you say? Well f*** you +# for trying to version your product. This is arch. They live on the edge. +# You never get anything but the latest version. And if that's broken... +# well that's your problem isn't it? And they don't believe in preserving +# older versions. Good luck! + +property :package, String, name_property: true +property :root, String, required: true + +resource_name :msys2_package + +action_class do + # + # Runs a command through a bash login shell made by our shim .bat file. + # The bash.bat file defaults %HOME% to #{root}/home/%USERNAME% and requests + # that the command be run in the current working directory. + # + def msys2_exec(comment, cmd) + f_root = win_friendly_path(root) + execute comment do + command ".\\bin\\bash.bat -c '#{cmd}'" + cwd f_root + live_stream true + environment('MSYSTEM' => 'MSYS') + end + end + + def msys2_init + cache_dir = ::File.join(root, '.cache') + f_cache_dir = win_friendly_path(cache_dir) + base_url = node['msys2']['url'] + base_checksum = node['msys2']['checksum'] + + unless ::File.exist?(::File.join(root, 'msys2.exe')) + seven_zip_archive "cache msys2 base to #{f_cache_dir}" do + source base_url + path f_cache_dir + checksum base_checksum + overwrite true + end + + seven_zip_archive "extract msys2 base archive to #{f_cache_dir}" do + source "#{f_cache_dir}\\#{tar_name(base_url)}" + path f_cache_dir + overwrite true + end + + ruby_block 'copy msys2 base files to root' do + block do + # Oh my god msys2 and pacman are picky as hell when it comes to + # updating core files. They use the mtime on certain files to + # determine if they need to updated or not and simply skip various + # steps otherwise. + ::FileUtils.cp_r(::Dir.glob("#{cache_dir}/msys64/*"), root, preserve: true) + end + end + end + + pacman_key_dir = ::File.join(root, 'etc/pacman.d/gnupg') + bin_dir = ::File.join(root, 'bin') + + directory win_friendly_path(bin_dir) + + cookbook_file win_friendly_path("#{bin_dir}/bash.bat") do + source 'bash.bat' + cookbook 'mingw' + end + + cookbook_file win_friendly_path(::File.join(root, 'custom-upgrade.sh')) do + source 'custom-upgrade.sh' + cookbook 'mingw' + end + + cookbook_file win_friendly_path(::File.join(root, 'etc/profile.d/custom_prefix.sh')) do + source 'custom_prefix.sh' + cookbook 'mingw' + end + + # $HOME is using files from /etc/skel. The home-directory creation step + # will automatically be performed if other users log in - so if you wish + # to globally modify user first time setup, edit /etc/skel or add + # "post-setup" steps to /etc/post-install/ + # The first-time init shell must be restarted and cannot be reused. + msys2_exec('msys2 first time init', 'exit') unless ::File.exist?(pacman_key_dir) + + # Update pacman and msys base packages. + if ::File.exist?(::File.join(root, 'usr/bin/update-core')) || !::File.exist?(::File.join(root, 'custom-upgrade.sh')) + msys2_exec('upgrade msys2 core', '/custom-upgrade.sh') + msys2_exec('upgrade msys2 core: part 2', 'pacman -Suu --noconfirm') + # Now we can actually upgrade everything ever. + msys2_exec('upgrade entire msys2 system: 1', 'pacman -Syuu --noconfirm') + # Might need to do it once more to pick up a few stragglers. + msys2_exec('upgrade entire msys2 system: 2', 'pacman -Syuu --noconfirm') + end + end + + def msys2_do_action(comment, action_cmd) + msys2_init + msys2_exec(comment, action_cmd) + end +end + +action :install do + msys2_do_action("installing #{package}", "pacman -S --needed --noconfirm #{package}") +end + +# Package name is ignored. This is arch. Why would you ever upgrade a single +# package and its deps? That'll just break everything else that ever depended +# on a different version of that dep. Because arch is wonderful like that. +# So you only get the choice to move everything to latest or not... it's the +# most agile development possible! +action :upgrade do + msys2_do_action("upgrading #{package}", "pacman -Syu --noconfirm #{package}") +end + +action :remove do + msys2_do_action("removing #{package}", "pacman -R --noconfirm #{package}") +end diff --git a/cookbooks/mingw/resources/tdm_gcc.rb b/cookbooks/mingw/resources/tdm_gcc.rb new file mode 100644 index 0000000..085eee3 --- /dev/null +++ b/cookbooks/mingw/resources/tdm_gcc.rb @@ -0,0 +1,114 @@ +# +# Cookbook:: mingw +# Resource:: tdm_gcc +# +# Copyright:: 2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Installs a gcc based C/C++ compiler and runtime from TDM GCC. + +property :flavor, Symbol, is: [:sjlj_32, :seh_sjlj_64], default: :seh_sjlj_64 +property :root, String, required: true +property :version, String, is: ['5.1.0'], name_property: true + +resource_name :mingw_tdm_gcc + +tdm_gcc_64 = { + 'http://iweb.dl.sourceforge.net/project/tdm-gcc/TDM-GCC%205%20series/5.1.0-tdm64-1/gcc-5.1.0-tdm64-1-core.tar.lzma' => + '29393aac890847089ad1e93f81a28f6744b1609c00b25afca818f3903e42e4bd', + 'http://iweb.dl.sourceforge.net/project/tdm-gcc/MinGW-w64%20runtime/GCC%205%20series/mingw64runtime-v4-git20150618-gcc5-tdm64-1.tar.lzma' => + '29186e0bb36824b10026d78bdcf238d631d8fc1d90718d2ebbd9ec239b6f94dd', + 'http://iweb.dl.sourceforge.net/project/tdm-gcc/GNU%20binutils/binutils-2.25-tdm64-1.tar.lzma' => + '4722bb7b4d46cef714234109e25e5d1cfd29f4e53365b6d615c8a00735f60e40', + 'http://iweb.dl.sourceforge.net/project/tdm-gcc/TDM-GCC%205%20series/5.1.0-tdm64-1/gcc-5.1.0-tdm64-1-c%2B%2B.tar.lzma' => + '17fd497318d1ac187a113e8665330d746ad9607a0406ab2374db0d8e6f4094d1', +} + +tdm_gcc_32 = { + 'http://iweb.dl.sourceforge.net/project/tdm-gcc/TDM-GCC%205%20series/5.1.0-tdm-1%20SJLJ/gcc-5.1.0-tdm-1-core.tar.lzma' => + '9199e6ecbce956ff4704b52098beb38e313176ace610285fb93758a08752870e', + 'http://iweb.dl.sourceforge.net/project/tdm-gcc/TDM-GCC%205%20series/5.1.0-tdm-1%20SJLJ/gcc-5.1.0-tdm-1-c%2B%2B.tar.lzma' => + '19fe46819ce43531d066b438479300027bbf06da57e8a10be5100466f80c28fc', +} + +action :install do + cache_dir = ::File.join(root, '.cache') + f_root = win_friendly_path(root) + + if flavor == :sjlj_32 + [ + 'binutils-bin=2.25.1', + 'libintl-dll=0.18.3.2', + 'mingwrt-dll=3.21.1', + 'mingwrt-dev=3.21.1', + 'w32api-dev=3.17', + ].each do |package_fragment| + mingw_get "install #{package_fragment} at #{f_root}" do + package "mingw32-#{package_fragment}-*" + root new_resource.root + end + end + end + + to_fetch = + case flavor + when :sjlj_32 + tdm_gcc_32 + when :seh_sjlj_64 + tdm_gcc_64 + else + raise "Unknown flavor: #{flavor}" + end + + to_fetch.each do |url, hash| + seven_zip_archive "cache #{archive_name(url)} to #{win_friendly_path(cache_dir)}" do + source url + path cache_dir + checksum hash + overwrite true + end + + seven_zip_archive "extract #{tar_name(url)} to #{f_root}" do + source ::File.join(cache_dir, tar_name(url)) + path root + overwrite true + end + end + + # Patch time.h headers for compatibility with winpthreads. + # These patches were made for binutils 2.25.1 for 32-bit TDM GCC only. + if flavor == :sjlj_32 + include_dir = win_friendly_path(::File.join(root, 'include')) + cookbook_file "#{include_dir}\\pthread.h" do + cookbook 'mingw' + source 'pthread.h' + end + + cookbook_file "#{include_dir}\\time.h" do + cookbook 'mingw' + source 'time.h' + end + end +end + +def archive_name(source) + url = ::URI.parse(source) + ::File.basename(::URI.unescape(url.path)) +end + +def tar_name(source) + aname = archive_name(source) + ::File.basename(aname, ::File.extname(aname)) +end diff --git a/cookbooks/mysql/.foodcritic b/cookbooks/mysql/.foodcritic new file mode 100644 index 0000000..913f038 --- /dev/null +++ b/cookbooks/mysql/.foodcritic @@ -0,0 +1 @@ +~FC005 diff --git a/cookbooks/mysql/CHANGELOG.md b/cookbooks/mysql/CHANGELOG.md new file mode 100644 index 0000000..92291b9 --- /dev/null +++ b/cookbooks/mysql/CHANGELOG.md @@ -0,0 +1,692 @@ +# mysql Cookbook CHANGELOG + +This file is used to list changes made in each version of the mysql cookbook. + +## 8.5.1 (2017-08-23) + +- Fix the remainder of the namespace collision deprecation warnings +- Remove the class_eval in the action class as this causes issues with some releases of Chef 12 + +## 8.5.0 (2017-08-23) + +- Require Chef 12.7+ since 12.5/12.6 has custom resource action_class issues +- Resolve several Chef 14 deprecation warnings + +## 8.4.0 (2017-05-30) + +- Fix client/server install on Amazon Linux and add testing +- Remove support for Ubuntu Precise since it's EOL +- Add Amazon Linux testing + +## 8.3.1 (2017-04-04) + +- Fix an ignoring of 'cookbook' attribute by 'mysql_config' resource +- Remove unused helper method +- Call out the supported platform versions in the metadata +- Switch to Delivery Local and rename the docked config +- Remove mention of the EOL opensuse 13.x in the readme + +## 8.3.0 (2017-03-20) +- Refactor mysql_service_manager_upstart.rb to eliminate use of cloned resource + +## 8.2.0 (2016-12-03) + +- Include client development packages on RHEL/SUSE platforms + +## 8.1.1 (2016-10-31) +- Fixing CVE-2016-6662 - Reverting execure bit on mysql config + +## 8.1.0 (2016-10-29) + +- Drop hardcoded, specific package version logic that broke many users + +## 8.0.4 (2016-09-26) +- Bump debian version +- Updated packages for 12.04 and 14.04 too +- Add chef_version metadata +- Update platforms in the kitchen file +- Add selinux to the Berksfile for testing +- Make sure yum repos are setup in local Test Kitchen + +## 8.0.3 (2016-09-14) +- [GH-390] Fix #390 incorrect escaping of initial_root_password +- Updated package versions for Ubuntu 16.04 +- Testing updates + +# v8.0.2 (2016-08-25) +- Various bug fixed and updates to package version strings + +# v8.0.1 (2016-07-20) +- Fixed a regression in the mysql_client resource where the action was changed from create to install in the 8.0 release +- Added oracle, opensuse, and opensuseleap as supported platforms in the metadata + +# v8.0.0 (2016-07-11) + +- Converting from LWRP to custom resources +- Removing yum-mysql and other dependencies. +- ^ BREAKING CHANGE: RHELish users are now responsible + for including a recipe from the "yum-mysql" or equivalent + cookbook before utilizing the mysql_* resources. +- More thoughtful ChefSpec +- Renaming "replication" test suite to "smoke" +- Moving to Inspec + +## v7.2.0 (2016-06-30) + +- Support openeSUSE leap +- Support Fedora 24 + +## v7.1.2 (2016-06-30) + +- Avoid deprecation warnings on the upcoming Chef 12.12 release + +## v7.1.1 (2016-06-03) + +- Fix apparmor blocking writes to non-default tmp_dirs +- Updated apparmor config to allow read & write to sock.lock file +- Use cookstyle instead of Rubocop directly + +## v7.1.0 (2016-05-11) + +- Added support for Ubuntu 16.04 + +## v7.0.0 (2016-04-19) + +- Removed support for legacy distros: Ubuntu 10.04/13.04/14.10/15.04, Fedora 20/21, OmniOS r151006, opensuse 11.3/12.0 +- Added support for Fedora 23, suse 13.X, and Ubuntu 16.04 +- Updated the systemd support to create unit files in /etc/systemd and not /usr/lib/systemd +- Adding umask to bash resource that sets root password PR #386 @gziskind +- Cleaned up the Test Kitchen config to test the right platform version + mysql pairings +- Added Travis CI Test Kitchen testing on Fedora 22/23 and removed Fedora 21 +- Updated the platforms used in the specs + +## v6.1.3 (2016-03-14) + +- Added support for Ubuntu 15.10 +- Added support for Amazon Linux 2016-03 +- Updated Kitchen testing configs + +## v6.1.2 (2015-10-05) + +- Added support for Amazon Linux 2015.09 + +## v6.1.1 (2015-09-24) + +- Completing ChefSpec matchers + +## v6.1.0 (2015-07-17) + +- Adding tunables for tmp_dir, error_log, and pid_file +- Adding mysqld_options hash interface for main my.cnf template + +## v6.0.31 (2015-07-13) + +- Reverting create_stop_system_service checks + +## v6.0.30 (2015-07-13) + +- Ubuntu 15.04 support +- Check for scripts and unit files during create_stop_system_service + +## v6.0.29 (2015-07-12) + +- Patch to allow blank root password +- Adding package information for Suse 12.0 + +## v6.0.28 (2015-07-10) + +- Fixes for 12.4.x + +## v6.0.27 (2015-07-09) + +- Allowing integer value for port number + +## v6.0.26 (2015-07-07) + +- Reverting breaking changes introduced in 6.0.25 + +## v6.0.25 (2015-07-06) + +- Fixes for 12.4.1 + +## v6.0.24 (2015-06-27) + +- 341 - Changing default GRANT for root from '%' to 'localhost' and '127.0.0.1' + +## v6.0.23 (2015-06-21) + +- 354 Better handling of long MySQL startup times + +## v6.0.22 (2015-05-07) + +- Debian 8 (Jessie) support + +## v6.0.21 (2015-04-08) + +- Fix to Upstart prestart script when using custom socket +- Adding --explicit_defaults_for_timestamp mysql_install_db_cmd for +- 5.6 and above + +## v6.0.20 (2015-03-27) + +- 318 - Fixing Upstart pre-start script to handle custom socket paths + +## v6.0.19 (2015-03-25) + +- Adding support for Amazon Linux 2015.03 + +## v6.0.18 (2015-03-24) + +- Adding support for 5.6 and 5.7 packages from dotdeb repos on Debian 7 + +## v6.0.17 (2015-03-13) + +- Updated for MySQL 5.7.6. +- Handing removal of mysql_install_db and mysqld_safe + +## v6.0.16 (2015-03-10) + +- Moved --defaults-file as first option to mysql_install_db_script + +## v6.0.15 (2015-02-26) + +- Updating docker detection fix to pass specs + +## v6.0.14 (2015-02-26) + +- Fixed debian system service :disable action. Now survives reboot +- Fixing centos-7 instance :enable action. Now survives +- Not applying Apparmor policy if running in a Docker container + +## v6.0.13 (2015-02-15) + +- Adding support for special characters in initial_root_password +- Fixing failure status bug in sysvinit script + +## v6.0.12 (2015-02-30) + +- No changes. Released a 6.0.11 that was identical to 6.0.10. +- Git before coffee. + +## v6.0.11 (2015-02-30) + +- Adding support for configurable socket files + +## v6.0.10 (2015-01-19) + +- Fix #282 - Fixing up data_dir template variable + +## v6.0.9 (2015-01-19) + +- Fix #282 - undefined method `parsed_data_dir' bug + +## v6.0.8 (2015-01-19) + +- Refactoring helper methods out of resource classes + +## v6.0.7 (2015-01-14) + +- Fixing timing issue with Upstart provider :restart and :reload +- actions where service returns before being available + +## v6.0.6 (2014-12-26) + +- Fixing subtle bug where MysqlCookbook::Helper methods were polluting Chef::Resource + +## v6.0.5 (2014-12-25) + +- Using 'include_recipe' instead of 'recipe_eval' in LWRP +- Fixing type checking on package_name attribute in mysql_client resource. + +## v6.0.4 (2014-12-21) + +- Suggest available versions if current is not available for current platform. + +## v6.0.3 (2014-12-17) + +- Adding bind_address parameter to mysql_service resource + +## v6.0.2 (2014-12-17) + +- Fixing sysvinit provider to survive reboots + +## v6.0.1 (2014-12-16) + +- Fixing Upstart template to survive reboots + +## v6.0.0 (2014-12-15) + +- Major version update +- Cookbook now provides LWRPs instead of recipes +- Platform providers re-factored into init system providers +- Separated :create and :start actions for use in recipes that build containers +- mysql_service now supports multiple instances on the same machine +- mysql_service no longer attempts to manage user records +- Removal of debian-sys-maint +- Unified Sysvinit script that works on all platforms +- mysql_config resource introduced +- mysql_client fixed up +- Refactored acceptance tests +- Temporarily dropped FreeBSD support + +## v5.6.1 (2014-10-29) + +- Use Gem::Version instead of Chef::Version + +## v5.6.0 (2014-10-29) + +- Changing default charset to utf8 +- Quoting passwords in debian.cnf.erb +- Amazon 2014.09 support +- Ubuntu 14.10 support +- Only hide passwords from STDOUT via "sensitive true" in chef-client higher than 11.14 +- Updating test harness + +## v5.5.4 (2014-10-07) + +- Adding sensitive flag to execute resources to protect passwords from logs + +## v5.5.3 (2014-09-24) + +- Reverting back to Upstart on Ubuntu 14.04 + +## v5.5.2 (2014-09-8) + +- Reverting commit that broke Debian pass_string + +## v5.5.1 (2014-09-2) + +- Switching Ubuntu service provider to use SysVinit instead of Upstart + +## v5.5.0 (2014-08-27) + +- Adding package version and action parameters to mysql_service resource +- Fixing Debian pass_string + +## v5.4.4 (2014-08-27) + +- Changing module namespace to MysqlCookbook + +## v5.4.3 (2014-08-25) + +- More refactoring. Moving helper function bits into resource parsed_parameters + +## v5.4.2 (2014-08-25) + +- Moving provider local variables into definitions for RHEL provider + +## v5.4.1 (2014-08-25) + +- Refactoring resources into the LWRP style with parsed parameters +- Moving provider local variables into definitions + +## v5.4.0 (2014-08-25) + +- 212 - support for centos-7 (mysql55 and mysql56) +- Adding (untested) Debian-6 support +- Adding Suse support to metadata.rb +- Adding ability to change MySQL root password +- Added libmysqlclient-devel package to SuSE client provider +- Appeasing AppArmor +- Reducing duplication in client provider + +## v5.3.6 (2014-06-18) + +- Fixing pid path location. Updating tests to include real RHEL + +## v5.3.4 (2014-06-16) + +- Fixing specs for Amazon Linux server package names + +## v5.3.2 (2014-06-16) + +- Fixing Amazon Linux support + +## v5.3.0 (2014-06-11) + +- 189 - Fix server_repl_password description +- 191 - Adding support for server55 and server56 on el-6 +- 193 - Fix syntax in mysql_service example +- 199 - Adding Suse support + +## v5.2.12 (2014-05-19) + +PR #192 - recipes/server.rb should honor parameter node['mysql']['version'] + +## v5.2.10 (2014-05-15) + +- COOK-4394 - restore freebsd support + +## v5.2.8 (2014-05-15) + +- [COOK-4653] - Missing mySQL 5.6 support for Ubuntu 14.04 + +## v5.2.6 (2014-05-07) + +- [COOK-4625] - Fix password resource parameter consumption on Debian and Ubuntu +- Fix up typos and version numbers in PLATFORMS.md +- Fix up specs from COOK-4613 changes + +## v5.2.4 (2014-05-02) + +- [COOK-4613] - Fix permissions on mysql data_dir to allow global access to mysql.sock + +## v5.2.2 (2014-04-24) + +- [COOK-4564] - Using positive tests for datadir move + +## v5.2.0 (2014-04-22) + +- [COOK-4551] - power grants.sql from resource parameters + +## v5.1.12 (2014-04-21) + +- [COOK-4554] - Support for Debian Sid + +## v5.1.10 (2014-04-21) + +- [COOK-4565] Support for Ubuntu 14.04 +- [COOK-4565] Adding Specs and TK platform +- Removing non-LTS 13.10 specs and TK platform + +## v5.1.8 (2014-04-12) + +Adding Ubuntu 13.04 to Platforminfo + +## v5.1.6 (2014-04-11) + +- [COOK-4548] - Add template[/etc/mysql/debian.cnf] to Ubuntu provider + +## v5.1.4 (2014-04-11) + +- [COOK-4547] - Shellescape server_root_password + +## v5.1.2 (2014-04-09) + +- [COOK-4519] - Fix error in run_dir for Ubuntu +- [COOK-4531] - Fix pid and run_dir for Debian + +## v5.1.0 (2014-04-08) + +[COOK-4523] - Allow for both :restart and :reload + +## v5.0.6 (2014-04-07) + +- [COOK-4519] - Updating specs to reflect pid file change on Ubuntu + +## v5.0.4 (2014-04-07) + +- [COOK-4519] - Fix path to pid file on Ubuntu + +## v5.0.2 (2014-04-01) + +- Moving server_deprecated into recipes directory + +## v5.0.0 (2014-03-31) + +- Rewriting as a library cookbook +- Exposing mysql_service and mysql_client resources +- User now needs to supply configuration +- Moving attribute driven recipe to server-deprecated + +## v4.1.2 (2014-02-28) + +- [COOK-4349] - Fix invalid platform check +- [COOK-4184] - Better handling of Ubuntu upstart service +- [COOK-2100] - Changing innodb_log_file_size tunable results in inability to start MySQL + +## v4.1.1 (2014-02-25) + +- **[COOK-2966] - Address foodcritic failures' +- **[COOK-4182] - Template parse failure in /etc/init/mysql.conf (data_dir)' +- **[COOK-4198] - Added missing tunable' +- **[COOK-4206] - create root@127.0.0.1, as well as root@localhost' + +## v4.0.20 (2014-01-18) + +- [COOK-3931] - MySQL Server Recipe Regression for Non-LTS Ubuntu Versions +- [COOK-3945] - MySQL cookbook fails on Ubuntu 13.04/13.10 +- [COOK-3966] - mysql::server recipe can't find a template with debian 7.x +- [COOK-3985] - Missing /etc/mysql/debian.cnf template on mysql::_server_debian.rb recipe (mysql 4.0.4) +- [COOK-3974] - debian.cnf not updated +- [COOK-4001] - Pull request: Fixes for broken mysql::server on Debian +- [COOK-4071] - Mysql cookbook doesn't work on debian 7.2 + +## v4.0.14 + +Fixing style cops + +## v4.0.12 + +### Bug + +- **[COOK-4068](https://tickets.chef.io/browse/COOK-4068)** - rework MySQL Windows recipe + +### Improvement + +- **[COOK-3801](https://tickets.chef.io/browse/COOK-3801)** - Add innodb_adaptive_flushing_method and innodb_adaptive_checkpoint + +## v4.0.10 + +fixing metadata version error. locking to 3.0 + +## v4.0.8 + +Locking yum dependency to '< 3' + +## v4.0.6 + +# Bug + +- [COOK-3943] Notifying service restart on grants update + +## v4.0.4 + +[COOK-3952] - Adding 'recursive true' to directory resources + +## v4.0.2 + +### BUGS + +- Adding support for Amazon Linux in attributes/server_rhel.rb +- Fixing bug where unprivileged users cannot connect over a local socket. Adding integration test. +- Fixing bug in mysql_grants_cmd generation + +## v4.0.0 + +- [COOK-3928] Heavily refactoring for readability. Moving platform implementation into separate recipes +- Moving integration tests from minitest to serverspec, removing "improper" tests +- Moving many attributes into the ['mysql']['server']['whatever'] namespace +- [COOK-3481] - Merged Lucas Welsh's Windows bits and moved into own recipe +- [COOK-3697] - Adding security hardening attributes +- [COOK-3780] - Fixing data_dir on Debian and Ubuntu +- [COOK-3807] - Don't use execute[assign-root-password] on Debian and Ubuntu +- [COOK-3881] - Fixing /etc being owned by mysql user + +## v3.0.12 + +### Bug + +- **[COOK-3752](https://tickets.chef.io/browse/COOK-3752)** - mysql service fails to start in mysql::server recipe + +## v3.0.10 + +- Fix a failed release attempt for v3.0.8 + +## v3.0.8 + +### Bug + +- **[COOK-3749](https://tickets.chef.io/browse/COOK-3749)** - Fix a regression with Chef 11-specific features + +## v3.0.6 + +### Bug + +- **[COOK-3674](https://tickets.chef.io/browse/COOK-3674)** - Fix an issue where the MySQL server fails to set the root password correctly when `data_dir` is a non-default value +- **[COOK-3647](https://tickets.chef.io/browse/COOK-3647)** - Fix README typo (databas => database) +- **[COOK-3477](https://tickets.chef.io/browse/COOK-3477)** - Fix log-queries-not-using-indexes not working +- **[COOK-3436](https://tickets.chef.io/browse/COOK-3436)** - Pull percona repo in compilation phase +- **[COOK-3208](https://tickets.chef.io/browse/COOK-3208)** - Fix README typo (LitenPort => ListenPort) +- **[COOK-3149](https://tickets.chef.io/browse/COOK-3149)** - Create my.cnf before installing +- **[COOK-2681](https://tickets.chef.io/browse/COOK-2681)** - Fix log_slow_queries for 5.5+ +- **[COOK-2606](https://tickets.chef.io/browse/COOK-2606)** - Use proper bind address on cloud providers + +### Improvement + +- **[COOK-3498](https://tickets.chef.io/browse/COOK-3498)** - Add support for replicate_* variables in my.cnf + +## v3.0.4 + +### Bug + +- **[COOK-3310](https://tickets.chef.io/browse/COOK-3310)** - Fix missing `GRANT` option +- **[COOK-3233](https://tickets.chef.io/browse/COOK-3233)** - Fix escaping special characters +- **[COOK-3156](https://tickets.chef.io/browse/COOK-3156)** - Fix GRANTS file when `remote_root_acl` is specified +- **[COOK-3134](https://tickets.chef.io/browse/COOK-3134)** - Fix Chef 11 support +- **[COOK-2318](https://tickets.chef.io/browse/COOK-2318)** - Remove redundant `if` block around `node.mysql.tunable.log_bin` + +## v3.0.2 + +### Bug + +- [COOK-2158]: apt-get update is run twice at compile time +- [COOK-2832]: mysql grants.sql file has errors depending on attrs +- [COOK-2995]: server.rb is missing a platform_family comparison value + +### Sub-task + +- [COOK-2102]: `innodb_flush_log_at_trx_commit` value is incorrectly set based on CPU count + +## v3.0.0 + +**Note** This is a backwards incompatible version with previous versions of the cookbook. Tickets that introduce incompatibility are COOK-2615 and COOK-2617. + +- [COOK-2478] - Duplicate 'read_only' server attribute in base and tunable +- [COOK-2471] - Add tunable to set slave_compressed_protocol for reduced network traffic +- [COOK-1059] - Update attributes in mysql cookbook to support missing options for my.cnf usable by Percona +- [COOK-2590] - Typo in server recipe to do with conf_dir and confd_dir +- [COOK-2602] - Add `lower_case_table_names` tunable +- [COOK-2430] - Add a tunable to create a network ACL when allowing `remote_root_access` +- [COOK-2619] - mysql: isamchk deprecated +- [COOK-2515] - Better support for SUSE distribution for mysql cookbook +- [COOK-2557] - mysql::percona_repo attributes missing and key server typo +- [COOK-2614] - Duplicate `innodb_file_per_table` +- [COOK-2145] - MySQL cookbook should remove anonymous and password less accounts +- [COOK-2553] - Enable include directory in my.cnf template for any platform +- [COOK-2615] - Rename `key_buffer` to `key_buffer_size` +- [COOK-2626] - Percona repo URL is being constructed incorrectly +- [COOK-2616] - Unneeded attribute thread_cache +- [COOK-2618] - myisam-recover not using attribute value +- [COOK-2617] - open-files is a duplicate of open-files-limit + +## v2.1.2 + +- [COOK-2172] - Mysql cookbook duplicates `binlog_format` configuration + +## v2.1.0 + +- [COOK-1669] - Using platform("ubuntu") in default attributes always returns true +- [COOK-1694] - Added additional my.cnf fields and reorganized cookbook to avoid race conditions with mysql startup and sql script execution +- [COOK-1851] - Support server-id and binlog_format settings +- [COOK-1929] - Update msyql server attributes file because setting attributes without specifying a precedence is deprecated +- [COOK-1999] - Add read_only tunable useful for replication slave servers + +## v2.0.2 + +- [COOK-1967] - mysql: trailing comma in server.rb platform family + +## v2.0.0 + +**Important note for this release** + +Under Chef Solo, you must set the node attributes for the root, debian and repl passwords or the run will completely fail. See COOK-1737 for background on this. + +- [COOK-1390] - MySQL service cannot start after reboot +- [COOK-1610] - Set root password outside preseed (blocker for drop-in mysql replacements) +- [COOK-1624] - Mysql cookbook fails to even compile on windows +- [COOK-1669] - Using platform("ubuntu") in default attributes always returns true +- [COOK-1686] - Add mysql service start +- [COOK-1687] - duplicate `innodb_buffer_pool_size` attribute +- [COOK-1704] - mysql cookbook fails spec tests when minitest-handler cookbook enabled +- [COOK-1737] - Fail a chef-solo run when `server_root_password`, `server_debian_password`, and/or `server_repl_password` is not set +- [COOK-1769] - link to database recipe in mysql README goes to old chef/cookbooks repo instead of chef-cookbook organization +- [COOK-1963] - use `platform_family` + +## v1.3.0 + +**Important note for this release** + +This version no longer installs Ruby bindings in the client recipe by default. Use the ruby recipe if you'd like the RubyGem. If you'd like packages from your distribution, use them in your application's specific cookbook/recipe, or modify the client packages attribute. This resolves the following tickets: + +- COOK-932 +- COOK-1009 +- COOK-1384 + +Additionally, this cookbook now has tests (COOK-1439) for use under test-kitchen. + +The following issues are also addressed in this release. + +- [COOK-1443] - MySQL (>= 5.1.24) does not support `innodb_flush_method` = fdatasync +- [COOK-1175] - Add Mac OS X support +- [COOK-1289] - handle additional tunable attributes +- [COOK-1305] - add auto-increment-increment and auto-increment-offset attributes +- [COOK-1397] - make the port an attribute +- [COOK-1439] - Add MySQL cookbook tests for test-kitchen support +- [COOK-1236] - Move package names into attributes to allow percona to free-ride +- [COOK-934] - remove deprecated mysql/libraries/database.rb, use the database cookbook instead. +- [COOK-1475] - fix restart on config change + +## v1.2.6 + +- [COOK-1113] - Use an attribute to determine if upstart is used +- [COOK-1121] - Add support for Windows +- [COOK-1140] - Fix conf.d on Debian +- [COOK-1151] - Fix server_ec2 handling /var/lib/mysql bind mount +- [COOK-1321] - Document setting password attributes for solo + +## v1.2.4 + +- [COOK-992] - fix FATAL nameerror +- [COOK-827] - `mysql:server_ec2` recipe can't mount `data_dir` +- [COOK-945] - FreeBSD support + +## v1.2.2 + +- [COOK-826] mysql::server recipe doesn't quote password string +- [COOK-834] Add 'scientific' and 'amazon' platforms to mysql cookbook + +## v1.2.1 + +- [COOK-644] Mysql client cookbook 'package missing' error message is confusing +- [COOK-645] RHEL6/CentOS6 - mysql cookbook contains 'skip-federated' directive which is unsupported on MySQL 5.1 + +## v1.2.0 + +- [COOK-684] remove mysql_database LWRP + +## v1.0.8 + +- [COOK-633] ensure "cloud" attribute is available + +## v1.0.7 + +- [COOK-614] expose all mysql tunable settings in config +- [COOK-617] bind to private IP if available + +## v1.0.6 + +- [COOK-605] install mysql-client package on ubuntu/debian + +## v1.0.5 + +- [COOK-465] allow optional remote root connections to mysql +- [COOK-455] improve platform version handling +- externalize conf_dir attribute for easier cross platform support +- change datadir attribute to data_dir for consistency + +## v1.0.4 + +- fix regressions on debian platform +- [COOK-578] wrap root password in quotes +- [COOK-562] expose all tunables in my.cnf diff --git a/cookbooks/mysql/CONTRIBUTING.md b/cookbooks/mysql/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/mysql/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/cookbooks/mysql/README.md b/cookbooks/mysql/README.md new file mode 100644 index 0000000..63dba0f --- /dev/null +++ b/cookbooks/mysql/README.md @@ -0,0 +1,424 @@ +# MySQL Cookbook + +[![Build Status](https://travis-ci.org/chef-cookbooks/mysql.svg?branch=master)](https://travis-ci.org/chef-cookbooks/mysql) [![Cookbook Version](https://img.shields.io/cookbook/v/mysql.svg)](https://supermarket.chef.io/cookbooks/mysql) + +The MySQL Cookbook is a library cookbook that provides resource primitives (LWRPs) for use in recipes. It is designed to be a reference example for creating highly reusable cross-platform cookbooks. + +## Scope + +This cookbook is concerned with the "MySQL Community Server", particularly those shipped with F/OSS Unix and Linux distributions. It does not address forks or value-added repackaged MySQL distributions like MariaDB or Percona. + +## Requirements + +- Chef 12.7 or higher +- Network accessible package repositories +- 'recipe[selinux::disabled]' on RHEL platforms + +## Platform Support + +The following platforms have been tested with Test Kitchen: + +``` +|----------------+-----+-----+-----+-----| +| | 5.1 | 5.5 | 5.6 | 5.7 | +|----------------+-----+-----+-----+-----| +| debian-7 | | X | | | +|----------------+-----+-----+-----+-----| +| debian-8 | | X | | | +|----------------+-----+-----+-----+-----| +| ubuntu-14.04 | | X | X | | +|----------------+-----+-----+-----+-----| +| ubuntu-16.04 | | | | X | +|----------------+-----+-----+-----+-----| +| centos-6 | X | X | X | X | +|----------------+-----+-----+-----+-----| +| centos-7 | | X | X | X | +|----------------+-----+-----+-----+-----| +| fedora | | | X | X | +|----------------+-----+-----+-----+-----| +| openSUSE Leap | | | X | | +|----------------+-----+-----+-----+-----| +``` + +## Cookbook Dependencies + +There are no hard coupled dependencies. However, there is a loose dependency on `yum-mysql-community` for RHEL/CentOS platforms. As of the 8.0 version of this cookbook, configuration of the package repos is now the responsibility of the user. + +## Usage + +Place a dependency on the mysql cookbook in your cookbook's metadata.rb + +```ruby +depends 'mysql', '~> 8.0' +``` + +Then, in a recipe: + +```ruby +mysql_service 'foo' do + port '3306' + version '5.5' + initial_root_password 'change me' + action [:create, :start] +end +``` + +The service name on the OS is `mysql-foo`. You can manually start and stop it with `service mysql-foo start` and `service mysql-foo stop`. + +The configuration file is at `/etc/mysql-foo/my.cnf`. It contains the minimum options to get the service running. It looks like this. + +``` +# Chef generated my.cnf for instance mysql-foo + +[client] +default-character-set = utf8 +port = 3306 +socket = /var/run/mysql-foo/mysqld.sock + +[mysql] +default-character-set = utf8 + +[mysqld] +user = mysql +pid-file = /var/run/mysql-foo/mysqld.pid +socket = /var/run/mysql-foo/mysqld.sock +port = 3306 +datadir = /var/lib/mysql-foo +tmpdir = /tmp +log-error = /var/log/mysql-foo/error.log +!includedir /etc/mysql-foo/conf.d + +[mysqld_safe] +socket = /var/run/mysql-foo/mysqld.sock +``` + +You can put extra configuration into the conf.d directory by using the `mysql_config` resource, like this: + +```ruby +mysql_service 'foo' do + port '3306' + version '5.5' + initial_root_password 'change me' + action [:create, :start] +end + +mysql_config 'foo' do + source 'my_extra_settings.erb' + notifies :restart, 'mysql_service[foo]' + action :create +end +``` + +You are responsible for providing `my_extra_settings.erb` in your own cookbook's templates folder. + +## Connecting with the mysql CLI command + +Logging into the machine and typing `mysql` with no extra arguments will fail. You need to explicitly connect over the socket with `mysql -S /var/run/mysql-foo/mysqld.sock`, or over the network with `mysql -h 127.0.0.1` + +## Upgrading from older version of the mysql cookbook + +- It is strongly recommended that you rebuild the machine from scratch. This is easy if you have your `data_dir` on a dedicated mount point. If you _must_ upgrade in-place, follow the instructions below. +- The 6.x series supports multiple service instances on a single machine. It dynamically names the support directories and service names. `/etc/mysql becomes /etc/mysql-instance_name`. Other support directories in `/var` `/run` etc work the same way. Make sure to specify the `data_dir` property on the `mysql_service` resource to point to the old `/var/lib/mysql` directory. + +## Resources Overview + +### mysql_service + +The `mysql_service` resource manages the basic plumbing needed to get a MySQL server instance running with minimal configuration. + +The `:create` action handles package installation, support directories, socket files, and other operating system level concerns. The internal configuration file contains just enough to get the service up and running, then loads extra configuration from a conf.d directory. Further configurations are managed with the `mysql_config` resource. + +- If the `data_dir` is empty, a database will be initialized, and a +- root user will be set up with `initial_root_password`. If this +- directory already contains database files, no action will be taken. + +The `:start` action starts the service on the machine using the appropriate provider for the platform. The `:start` action should be omitted when used in recipes designed to build containers. + +#### Example + +```ruby +mysql_service 'default' do + version '5.7' + bind_address '0.0.0.0' + port '3306' + data_dir '/data' + initial_root_password 'Ch4ng3me' + action [:create, :start] +end +``` + +Please note that when using `notifies` or `subscribes`, the resource to reference is `mysql_service[name]`, not `service[mysql]`. + +#### Parameters + +- `charset` - specifies the default character set. Defaults to `utf8`. +- `data_dir` - determines where the actual data files are kept on the machine. This is useful when mounting external storage. When omitted, it will default to the platform's native location. +- `error_log` - Tunable location of the error_log +- `initial_root_password` - allows the user to specify the initial root password for mysql when initializing new databases. This can be set explicitly in a recipe, driven from a node attribute, or from data_bags. When omitted, it defaults to `ilikerandompasswords`. Please be sure to change it. +- `instance` - A string to identify the MySQL service. By convention, to allow for multiple instances of the `mysql_service`, directories and files on disk are named `mysql-`. Defaults to the resource name. +- `package_action` - Defaults to `:install`. +- `package_name` - Defaults to a value looked up in an internal map. +- `package_version` - Specific version of the package to install,passed onto the underlying package manager. Defaults to `nil`. +- `bind_address` - determines the listen IP address for the mysqld service. When omitted, it will be determined by MySQL. If the address is "regular" IPv4/IPv6address (e.g 127.0.0.1 or ::1), the server accepts TCP/IP connections only for that particular address. If the address is "0.0.0.0" (IPv4) or "::" (IPv6), the server accepts TCP/IP connections on all IPv4 or IPv6 interfaces. +- `mysqld_options` - A key value hash of options to be rendered into the main my.cnf. WARNING - It is highly recommended that you use the `mysql_config` resource instead of sending extra config into a `mysql_service` resource. This will allow you to set up notifications and subscriptions between the service and its configuration. That being said, this can be useful for adding extra options needed for database initialization at first run. +- `port` - determines the listen port for the mysqld service. When omitted, it will default to '3306'. +- `run_group` - The name of the system group the `mysql_service` should run as. Defaults to 'mysql'. +- `run_user` - The name of the system user the `mysql_service` should run as. Defaults to 'mysql'. +- `pid_file` - Tunable location of the pid file. +- `socket` - determines where to write the socket file for the `mysql_service` instance. Useful when configuring clients on the same machine to talk over socket and skip the networking stack. Defaults to a calculated value based on platform and instance name. +- `tmp_dir` - Tunable location of the tmp_dir +- `version` - allows the user to select from the versions available for the platform, where applicable. When omitted, it will install the default MySQL version for the target platform. Available version numbers are `5.0`, `5.1`, `5.5`, `5.6`, and `5.7`, depending on platform. + +#### Actions + +- `:create` - Configures everything but the underlying operating system service. +- `:delete` - Removes everything but the package and data_dir. +- `:start` - Starts the underlying operating system service +- `:stop`- Stops the underlying operating system service +- `:restart` - Restarts the underlying operating system service +- `:reload` - Reloads the underlying operating system service + +#### Providers + +Chef selects the appropriate provider based on platform and version, but you can specify one if your platform support it. + +```ruby +mysql_service[instance-1] do + port '1234' + data_dir '/mnt/lottadisk' + provider Chef::Provider::MysqlServiceSysvinit + action [:create, :start] +end +``` + +- `Chef::Provider::MysqlServiceBase` - Configures everything needed to run a MySQL service except the platform service facility. This provider should never be used directly. The `:start`, `:stop`, `:restart`, and `:reload` actions are stubs meant to be overridden by the providers below. +- `Chef::Provider::MysqlServiceSmf` - Starts a `mysql_service` using the Service Management Facility, used by Solaris and Illumos. Manages the FMRI and method script. +- `Chef::Provider::MysqlServiceSystemd` - Starts a `mysql_service` using SystemD. Manages the unit file and activation state +- `Chef::Provider::MysqlServiceSysvinit` - Starts a `mysql_service` using SysVinit. Manages the init script and status. +- `Chef::Provider::MysqlServiceUpstart` - Starts a `mysql_service` using Upstart. Manages job definitions and status. + +### mysql_config + +The `mysql_config` resource is a wrapper around the core Chef `template` resource. Instead of a `path` parameter, it uses the `instance` parameter to calculate the path on the filesystem where file is rendered. + +#### Example + +```ruby +mysql_config[default] do + source 'site.cnf.erb' + action :create +end +``` + +#### Parameters + +- `config_name` - The base name of the configuration file to be rendered into the conf.d directory on disk. Defaults to the resource name. +- `cookbook` - The name of the cookbook to look for the template source. Defaults to nil +- `group` - System group for file ownership. Defaults to 'mysql'. +- `instance` - Name of the `mysql_service` instance the config is meant for. Defaults to 'default'. +- `owner` - System user for file ownership. Defaults to 'mysql'. +- `source` - Template in cookbook to be rendered. +- `variables` - Variables to be passed to the underlying `template` resource. +- `version` - Version of the `mysql_service` instance the config is meant for. Used to calculate path. Only necessary when using packages with unique configuration paths, such as RHEL Software Collections or OmniOS. Defaults to 'nil' + +#### Actions + +- `:create` - Renders the template to disk at a path calculated using the instance parameter. +- `:delete` - Deletes the file from the conf.d directory calculated using the instance parameter. + +#### More Examples + +```ruby +mysql_service 'instance-1' do + action [:create, :start] +end + +mysql_service 'instance-2' do + action [:create, :start] +end + +mysql_config 'logging' do + instance 'instance-1' + source 'logging.cnf.erb' + action :create + notifies :restart, 'mysql_service[instance-1]' +end + +mysql_config 'security settings for instance-2' do + config_name 'security' + instance 'instance-2' + source 'security_stuff.cnf.erb' + variables(:foo => 'bar') + action :create + notifies :restart, 'mysql_service[instance-2]' +end +``` + +### mysql_client + +The `mysql_client` resource manages the MySQL client binaries and development libraries. + +It is an example of a "singleton" resource. Declaring two `mysql_client` resources on a machine usually won't yield two separate copies of the client binaries, except for platforms that support multiple versions (RHEL SCL, OmniOS). + +#### Example + +```ruby +mysql_client 'default' do + action :create +end +``` + +#### Properties + +- `package_name` - An array of packages to be installed. Defaults to a value looked up in an internal map. +- `package_version` - Specific versions of the package to install, passed onto the underlying package manager. Defaults to `nil`. +- `version` - Major MySQL version number of client packages. Only valid on for platforms that support multiple versions, such as RHEL via Software Collections and OmniOS. + +#### Actions + +- `:create` - Installs the client software +- `:delete` - Removes the client software + +## Advanced Usage Examples + +There are a number of configuration scenarios supported by the use of resource primitives in recipes. For example, you might want to run multiple MySQL services, as different users, and mount block devices that contain pre-existing databases. + +### Multiple Instances as Different Users + +```ruby +# instance-1 +user 'alice' do + action :create +end + +directory '/mnt/data/mysql/instance-1' do + owner 'alice' + action :create +end + +mount '/mnt/data/mysql/instance-1' do + device '/dev/sdb1' + fstype 'ext4' + action [:mount, :enable] +end + +mysql_service 'instance-1' do + port '3307' + run_user 'alice' + data_dir '/mnt/data/mysql/instance-1' + action [:create, :start] +end + +mysql_config 'site config for instance-1' do + instance 'instance-1' + source 'instance-1.cnf.erb' + notifies :restart, 'mysql_service[instance-1]' +end + +# instance-2 +user 'bob' do + action :create +end + +directory '/mnt/data/mysql/instance-2' do + owner 'bob' + action :create +end + +mount '/mnt/data/mysql/instance-2' do + device '/dev/sdc1' + fstype 'ext3' + action [:mount, :enable] +end + +mysql_service 'instance-2' do + port '3308' + run_user 'bob' + data_dir '/mnt/data/mysql/instance-2' + action [:create, :start] +end + +mysql_config 'site config for instance-2' do + instance 'instance-2' + source 'instance-2.cnf.erb' + notifies :restart, 'mysql_service[instance-2]' +end +``` + +### Replication Testing + +Use multiple `mysql_service` instances to test a replication setup. This particular example serves as a smoke test in Test Kitchen because it exercises different resources and requires service restarts. + + + +## Frequently Asked Questions + +### How do I run this behind my firewall? + +On Linux, the `mysql_service` resource uses the platform's underlying package manager to install software. For this to work behind firewalls, you'll need to either: + +- Configure the system yum/apt utilities to use a proxy server that +- can reach the Internet +- Host a package repository on a network that the machine can talk to + +On the RHEL platform_family, applying the `yum::default` recipe will allow you to drive the `yum_globalconfig` resource with attributes to change the global yum proxy settings. + +If hosting repository mirrors, applying one of the following recipes and adjust the settings with node attributes. + +- `recipe[yum-centos::default]` from the Supermarket + + + + + +- `recipe[yum-mysql-community::default]` from the Supermarket + + + + + +### The mysql command line doesn't work + +If you log into the machine and type `mysql`, you may see an error like this one: + +`Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock'` + +This is because MySQL is hardcoded to read the defined default my.cnf file, typically at /etc/my.cnf, and this LWRP deletes it to prevent overlap among multiple MySQL configurations. + +To connect to the socket from the command line, check the socket in the relevant my.cnf file and use something like this: + +`mysql -S /var/run/mysql-foo/mysqld.sock -Pwhatever` + +Or to connect over the network, use something like this: connect over the network.. + +`mysql -h 127.0.0.1 -Pwhatever` + +These network or socket ssettings can also be put in you $HOME/.my.cnf, if preferred. + +### What about MariaDB, Percona, etc. + +MySQL forks are purposefully out of scope for this cookbook. This is mostly to reduce the testing matrix to a manageable size. Cookbooks for these technologies can easily be created by copying and adapting this cookbook. However, there will be differences. + +Package repository locations, package version names, software major version numbers, supported platform matrices, and the availability of software such as XtraDB and Galera are the main reasons that creating multiple cookbooks to make sense. + +## Maintainers + +This cookbook is maintained by Chef's Community Cookbook Engineering team. Our goal is to improve cookbook quality and to aid the community in contributing to cookbooks. To learn more about our team, process, and design goals see our [team documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/COOKBOOK_TEAM.MD). To learn more about contributing to cookbooks like this see our [contributing documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD), or if you have general questions about this cookbook come chat with us in #cookbok-engineering on the [Chef Community Slack](http://community-slack.chef.io/) + +## License + +```text +Copyright:: 2009-2017 Chef Software, Inc + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/cookbooks/mysql/libraries/helpers.rb b/cookbooks/mysql/libraries/helpers.rb new file mode 100644 index 0000000..e60d21d --- /dev/null +++ b/cookbooks/mysql/libraries/helpers.rb @@ -0,0 +1,291 @@ +module MysqlCookbook + module HelpersBase + require 'shellwords' + + def el6? + return true if node['platform_family'] == 'rhel' && node['platform_version'].to_i == 6 + false + end + + def el7? + return true if node['platform_family'] == 'rhel' && node['platform_version'].to_i == 7 + false + end + + def wheezy? + return true if node['platform'] == 'debian' && node['platform_version'].to_i == 7 + false + end + + def jessie? + return true if node['platform'] == 'debian' && node['platform_version'].to_i == 8 + false + end + + def stretch? + return true if node['platform'] == 'debian' && node['platform_version'].to_i == 9 + false + end + + def trusty? + return true if node['platform'] == 'ubuntu' && node['platform_version'] == '14.04' + return true if node['platform'] == 'linuxmint' && node['platform_version'] =~ /^17\.[0-9]$/ + false + end + + def xenial? + return true if node['platform'] == 'ubuntu' && node['platform_version'] == '16.04' + false + end + + def defaults_file + "#{etc_dir}/my.cnf" + end + + def default_data_dir + return "/var/lib/#{mysql_name}" if node['os'] == 'linux' + return "/opt/local/lib/#{mysql_name}" if node['os'] == 'solaris2' + return "/var/db/#{mysql_name}" if node['os'] == 'freebsd' + end + + def default_error_log + "#{log_dir}/error.log" + end + + def default_pid_file + "#{run_dir}/mysqld.pid" + end + + def default_major_version + # rhelish + return '5.1' if el6? + return '5.6' if el7? + return '5.6' if node['platform'] == 'amazon' + + # debian + return '5.5' if wheezy? + return '5.5' if jessie? + + # ubuntu + return '5.5' if trusty? + return '5.7' if xenial? + + # misc + return '5.6' if node['platform'] == 'freebsd' + return '5.6' if node['platform'] == 'fedora' + return '5.6' if node['platform_family'] == 'suse' + end + + def major_from_full(v) + v.split('.').shift(2).join('.') + end + + def mysql_name + "mysql-#{instance}" + end + + def default_socket_file + "#{run_dir}/mysqld.sock" + end + + def default_client_package_name + return ['mysql', 'mysql-devel'] if major_version == '5.1' && el6? + return ['mysql55', 'mysql55-devel.x86_64'] if major_version == '5.5' && node['platform'] == 'amazon' + return ['mysql56', 'mysql56-devel.x86_64'] if major_version == '5.6' && node['platform'] == 'amazon' + return ['mysql-client-5.5', 'libmysqlclient-dev'] if major_version == '5.5' && node['platform_family'] == 'debian' + return ['mysql-client-5.6', 'libmysqlclient-dev'] if major_version == '5.6' && node['platform_family'] == 'debian' + return ['mysql-client-5.7', 'libmysqlclient-dev'] if major_version == '5.7' && node['platform_family'] == 'debian' + return 'mysql-community-server-client' if major_version == '5.6' && node['platform_family'] == 'suse' + ['mysql-community-client', 'mysql-community-devel'] + end + + def default_server_package_name + return 'mysql-server' if major_version == '5.1' && el6? + return 'mysql55-server' if major_version == '5.5' && node['platform'] == 'amazon' + return 'mysql56-server' if major_version == '5.6' && node['platform'] == 'amazon' + return 'mysql-server-5.5' if major_version == '5.5' && node['platform_family'] == 'debian' + return 'mysql-server-5.6' if major_version == '5.6' && node['platform_family'] == 'debian' + return 'mysql-server-5.7' if major_version == '5.7' && node['platform_family'] == 'debian' + return 'mysql-community-server' if major_version == '5.6' && node['platform_family'] == 'suse' + 'mysql-community-server' + end + + def socket_dir + File.dirname(socket) + end + + def run_dir + return "#{prefix_dir}/var/run/#{mysql_name}" if node['platform_family'] == 'rhel' + return "/run/#{mysql_name}" if node['platform_family'] == 'debian' + "/var/run/#{mysql_name}" + end + + def prefix_dir + return "/opt/mysql#{pkg_ver_string}" if node['platform_family'] == 'omnios' + return '/opt/local' if node['platform_family'] == 'smartos' + return "/opt/rh/#{scl_name}/root" if scl_package? + end + + def scl_name + return unless node['platform_family'] == 'rhel' + return 'mysql51' if version == '5.1' && node['platform_version'].to_i == 5 + return 'mysql55' if version == '5.5' && node['platform_version'].to_i == 5 + end + + def scl_package? + return unless node['platform_family'] == 'rhel' + return true if version == '5.1' && node['platform_version'].to_i == 5 + return true if version == '5.5' && node['platform_version'].to_i == 5 + false + end + + def etc_dir + return "/opt/mysql#{pkg_ver_string}/etc/#{mysql_name}" if node['platform_family'] == 'omnios' + return "#{prefix_dir}/etc/#{mysql_name}" if node['platform_family'] == 'smartos' + "#{prefix_dir}/etc/#{mysql_name}" + end + + def base_dir + prefix_dir || '/usr' + end + + def system_service_name + return 'mysql51-mysqld' if node['platform_family'] == 'rhel' && scl_name == 'mysql51' + return 'mysql55-mysqld' if node['platform_family'] == 'rhel' && scl_name == 'mysql55' + return 'mysqld' if node['platform_family'] == 'rhel' + return 'mysqld' if node['platform_family'] == 'fedora' + 'mysql' # not one of the above + end + + def v56plus + return false if version.split('.')[0].to_i < 5 + return false if version.split('.')[1].to_i < 6 + true + end + + def v57plus + return false if version.split('.')[0].to_i < 5 + return false if version.split('.')[1].to_i < 7 + true + end + + def default_include_dir + "#{etc_dir}/conf.d" + end + + def log_dir + return "/var/adm/log/#{mysql_name}" if node['platform_family'] == 'omnios' + "#{prefix_dir}/var/log/#{mysql_name}" + end + + def lc_messages_dir; end + + def init_records_script + # Note: shell-escaping passwords in a SQL file may cause corruption - eg + # mysql will read \& as &, but \% as \%. Just escape bare-minimum \ and ' + sql_escaped_password = root_password.gsub('\\') { '\\\\' }.gsub("'") { '\\\'' } + + <<-EOS + set -e + rm -rf /tmp/#{mysql_name} + mkdir /tmp/#{mysql_name} + + cat > /tmp/#{mysql_name}/my.sql <<-'EOSQL' +UPDATE mysql.user SET #{password_column_name}=PASSWORD('#{sql_escaped_password}')#{password_expired} WHERE user = 'root'; +DELETE FROM mysql.user WHERE USER LIKE ''; +DELETE FROM mysql.user WHERE user = 'root' and host NOT IN ('127.0.0.1', 'localhost'); +FLUSH PRIVILEGES; +DELETE FROM mysql.db WHERE db LIKE 'test%'; +DROP DATABASE IF EXISTS test ; +EOSQL + + #{db_init} + #{record_init} + + while [ ! -f #{pid_file} ] ; do sleep 1 ; done + kill `cat #{pid_file}` + while [ -f #{pid_file} ] ; do sleep 1 ; done + rm -rf /tmp/#{mysql_name} + EOS + end + + def password_column_name + return 'authentication_string' if v57plus + 'password' + end + + def root_password + if initial_root_password == '' + Chef::Log.info('Root password is empty') + return '' + end + initial_root_password + end + + def password_expired + return ", password_expired='N'" if v57plus + '' + end + + def db_init + return mysqld_initialize_cmd if v57plus + mysql_install_db_cmd + end + + def mysql_install_db_bin + return "#{base_dir}/scripts/mysql_install_db" if node['platform_family'] == 'omnios' + return "#{prefix_dir}/bin/mysql_install_db" if node['platform_family'] == 'smartos' + 'mysql_install_db' + end + + def mysql_install_db_cmd + cmd = mysql_install_db_bin + cmd << " --defaults-file=#{etc_dir}/my.cnf" + cmd << " --datadir=#{data_dir}" + cmd << ' --explicit_defaults_for_timestamp' if v56plus && !v57plus + return "scl enable #{scl_name} \"#{cmd}\"" if scl_package? + cmd + end + + def mysqladmin_bin + return "#{prefix_dir}/bin/mysqladmin" if node['platform_family'] == 'smartos' + return 'mysqladmin' if scl_package? + "#{prefix_dir}/usr/bin/mysqladmin" + end + + def mysqld_bin + return "#{prefix_dir}/libexec/mysqld" if node['platform_family'] == 'smartos' + return "#{base_dir}/bin/mysqld" if node['platform_family'] == 'omnios' + return '/usr/sbin/mysqld' if node['platform_family'] == 'fedora' && v56plus + return '/usr/libexec/mysqld' if node['platform_family'] == 'fedora' + return 'mysqld' if scl_package? + "#{prefix_dir}/usr/sbin/mysqld" + end + + def mysqld_initialize_cmd + cmd = mysqld_bin + cmd << " --defaults-file=#{etc_dir}/my.cnf" + cmd << ' --initialize' + cmd << ' --explicit_defaults_for_timestamp' if v56plus + return "scl enable #{scl_name} \"#{cmd}\"" if scl_package? + cmd + end + + def mysqld_safe_bin + return "#{prefix_dir}/bin/mysqld_safe" if node['platform_family'] == 'smartos' + return "#{base_dir}/bin/mysqld_safe" if node['platform_family'] == 'omnios' + return 'mysqld_safe' if scl_package? + "#{prefix_dir}/usr/bin/mysqld_safe" + end + + def record_init + cmd = v56plus ? mysqld_bin : mysqld_safe_bin + cmd << " --defaults-file=#{etc_dir}/my.cnf" + cmd << " --init-file=/tmp/#{mysql_name}/my.sql" + cmd << ' --explicit_defaults_for_timestamp' if v56plus + cmd << ' &' + return "scl enable #{scl_name} \"#{cmd}\"" if scl_package? + cmd + end + end +end diff --git a/cookbooks/mysql/libraries/matchers.rb b/cookbooks/mysql/libraries/matchers.rb new file mode 100644 index 0000000..adf5e73 --- /dev/null +++ b/cookbooks/mysql/libraries/matchers.rb @@ -0,0 +1,71 @@ +if defined?(ChefSpec) + ChefSpec.define_matcher :mysql_config + ChefSpec.define_matcher :mysql_service + ChefSpec.define_matcher :mysql_client + + # mysql_client_client_installation_package + def install_mysql_client_installation_package(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:mysql_client_installation_package, :create, resource_name) + end + + def remove_mysql_client_installation_package(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:mysql_client_installation_package, :remove, resource_name) + end + + # mysql_server_server_installation_package + def install_mysql_server_installation_package(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:mysql_server_installation_package, :install, resource_name) + end + + def remove_mysql_server_installation_package(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:mysql_server_installation_package, :remove, resource_name) + end + + ##### + # old + ##### + + # client + def create_mysql_client(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:mysql_client, :create, resource_name) + end + + def delete_mysql_client(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:mysql_client, :delete, resource_name) + end + + # mysql_config + def create_mysql_config(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:mysql_config, :create, resource_name) + end + + def delete_mysql_config(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:mysql_config, :delete, resource_name) + end + + # service + def create_mysql_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:mysql_service, :create, resource_name) + end + + def delete_mysql_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:mysql_service, :delete, resource_name) + end + + def start_mysql_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:mysql_service, :start, resource_name) + end + + def stop_mysql_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:mysql_service, :stop, resource_name) + end + + def restart_mysql_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:mysql_service, :restart, resource_name) + end + + def reload_mysql_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:mysql_service, :reload, resource_name) + end + +end diff --git a/cookbooks/mysql/libraries/mysql_base.rb b/cookbooks/mysql/libraries/mysql_base.rb new file mode 100644 index 0000000..2db0c16 --- /dev/null +++ b/cookbooks/mysql/libraries/mysql_base.rb @@ -0,0 +1,30 @@ +module MysqlCookbook + class MysqlBase < Chef::Resource + require_relative 'helpers' + + # All resources are composites + def whyrun_supported? + true + end + + ################ + # Type Constants + ################ + + Boolean = property_type( + is: [true, false], + default: false + ) unless defined?(Boolean) + + ################### + # Common Properties + ################### + property :run_group, String, default: 'mysql', desired_state: false + property :run_user, String, default: 'mysql', desired_state: false + property :version, String, default: lazy { default_major_version }, desired_state: false + property :include_dir, String, default: lazy { default_include_dir }, desired_state: false + property :major_version, String, default: lazy { major_from_full(version) }, desired_state: false + + action_class + end +end diff --git a/cookbooks/mysql/libraries/mysql_client_installation_package.rb b/cookbooks/mysql/libraries/mysql_client_installation_package.rb new file mode 100644 index 0000000..1dc87f5 --- /dev/null +++ b/cookbooks/mysql/libraries/mysql_client_installation_package.rb @@ -0,0 +1,31 @@ +module MysqlCookbook + class MysqlClientInstallationPackage < MysqlBase + # helper methods + require_relative 'helpers' + include MysqlCookbook::HelpersBase + + # Resource properties + resource_name :mysql_client_installation_package + provides :mysql_client_installation, os: 'linux' + provides :mysql_client, os: 'linux' + + property :package_name, [String, Array], default: lazy { default_client_package_name }, desired_state: false + property :package_options, [String, nil], desired_state: false + property :package_version, [String, nil], default: nil, desired_state: false + + # Actions + action :create do + package new_resource.package_name do + version new_resource.package_version if new_resource.package_version + options new_resource.package_options if new_resource.package_options + action :install + end + end + + action :delete do + package new_resource.package_name do + action :remove + end + end + end +end diff --git a/cookbooks/mysql/libraries/mysql_config.rb b/cookbooks/mysql/libraries/mysql_config.rb new file mode 100644 index 0000000..d4a52c9 --- /dev/null +++ b/cookbooks/mysql/libraries/mysql_config.rb @@ -0,0 +1,56 @@ +module MysqlCookbook + class MysqlConfig < MysqlBase + resource_name :mysql_config + + property :config_name, String, name_property: true, desired_state: false + property :cookbook, String, desired_state: false + property :group, String, default: 'mysql', desired_state: false + property :instance, String, default: 'default', desired_state: false + property :owner, String, default: 'mysql', desired_state: false + property :source, String, desired_state: false + property :variables, [Hash], desired_state: false + property :version, String, default: lazy { default_major_version }, desired_state: false + + require_relative 'helpers' + include MysqlCookbook::HelpersBase + + provides :mysql_config + + action :create do + # hax because group property + g = Chef::Resource::Group.new(new_resource.group, run_context) + g.system true if new_resource.name == 'mysql' + resource_collection.insert g + + user new_resource.owner do + gid new_resource.owner + system true if new_resource.name == 'mysql' + action :create + end + + directory new_resource.include_dir do + owner new_resource.owner + group new_resource.group + mode '0750' + recursive true + action :create + end + + template "#{new_resource.include_dir}/#{new_resource.config_name}.cnf" do + owner new_resource.owner + group new_resource.group + mode '0640' + variables(new_resource.variables) + source new_resource.source + cookbook new_resource.cookbook + action :create + end + end + + action :delete do + file "#{new_resource.include_dir}/#{new_resource.config_name}.cnf" do + action :delete + end + end + end +end diff --git a/cookbooks/mysql/libraries/mysql_server_installation_package.rb b/cookbooks/mysql/libraries/mysql_server_installation_package.rb new file mode 100644 index 0000000..bf46c8d --- /dev/null +++ b/cookbooks/mysql/libraries/mysql_server_installation_package.rb @@ -0,0 +1,42 @@ +module MysqlCookbook + class MysqlServerInstallationPackage < MysqlBase + # Resource properties + resource_name :mysql_server_installation_package + provides :mysql_server_installation, os: 'linux' + + property :package_name, String, default: lazy { default_server_package_name }, desired_state: false + property :package_options, [String, nil], desired_state: false + property :package_version, [String, nil], default: nil, desired_state: false + + # helper methods + require_relative 'helpers' + include MysqlCookbook::HelpersBase + + # Actions + action :install do + package new_resource.package_name do + version new_resource.package_version if new_resource.package_version + options new_resource.package_options if new_resource.package_options + notifies :install, 'package[perl-Sys-Hostname-Long]', :immediately if platform_family?('suse') + notifies :run, 'execute[Initial DB setup script]', :immediately if platform_family?('suse') + action :install + end + + package 'perl-Sys-Hostname-Long' do + action :nothing + end + + execute 'Initial DB setup script' do + environment 'INSTANCE' => new_resource.name + command '/usr/lib/mysql/mysql-systemd-helper install' + action :nothing + end + end + + action :delete do + package new_resource.package_name do + action :remove + end + end + end +end diff --git a/cookbooks/mysql/libraries/mysql_service.rb b/cookbooks/mysql/libraries/mysql_service.rb new file mode 100644 index 0000000..aa969bd --- /dev/null +++ b/cookbooks/mysql/libraries/mysql_service.rb @@ -0,0 +1,105 @@ +module MysqlCookbook + require_relative 'mysql_service_base' + class MysqlService < MysqlServiceBase + resource_name :mysql_service + + # installation type and service_manager + property :install_method, %w(package auto), default: 'auto', desired_state: false + property :service_manager, %w(sysvinit upstart systemd auto), default: 'auto', desired_state: false + + # mysql_server_installation + property :version, String, default: lazy { default_major_version }, desired_state: false + property :major_version, String, default: lazy { major_from_full(version) }, desired_state: false + property :package_name, String, default: lazy { default_package_name }, desired_state: false + property :package_options, [String, nil], desired_state: false + property :package_version, [String, nil], default: nil, desired_state: false + + ################ + # Helper Methods + ################ + + def copy_properties_to(to, *properties) + properties = self.class.properties.keys if properties.empty? + properties.each do |p| + # If the property is set on from, and exists on to, set the + # property on to + if to.class.properties.include?(p) && property_is_set?(p) + to.send(p, send(p)) + end + end + end + + action_class do + def installation(&block) + case new_resource.install_method + when 'auto' + install = mysql_server_installation(new_resource.name, &block) + when 'package' + install = mysql_server_installation_package(new_resource.name, &block) + when 'none' + Chef::Log.info('Skipping MySQL installation. Assuming it was handled previously.') + return + end + copy_properties_to(install) + install + end + + def svc_manager(&block) + case new_resource.service_manager + when 'auto' + svc = mysql_service_manager(new_resource.name, &block) + when 'sysvinit' + svc = mysql_service_manager_sysvinit(new_resource.name, &block) + when 'upstart' + svc = mysql_service_manager_upstart(new_resource.name, &block) + when 'systemd' + svc = mysql_service_manager_systemd(new_resource.name, &block) + end + copy_properties_to(svc) + svc + end + end + + ######### + # Actions + ######### + + action :create do + installation do + action :install + end + + svc_manager do + action :create + end + end + + action :start do + svc_manager do + action :start + end + end + + action :delete do + svc_manager do + action :delete + end + + installation do + action :delete + end + end + + action :restart do + svc_manager do + action :restart + end + end + + action :stop do + svc_manager do + action :stop + end + end + end +end diff --git a/cookbooks/mysql/libraries/mysql_service_base.rb b/cookbooks/mysql/libraries/mysql_service_base.rb new file mode 100644 index 0000000..a03b5aa --- /dev/null +++ b/cookbooks/mysql/libraries/mysql_service_base.rb @@ -0,0 +1,203 @@ +module MysqlCookbook + class MysqlServiceBase < MysqlBase + property :bind_address, String, desired_state: false + property :charset, String, default: 'utf8', desired_state: false + property :data_dir, String, default: lazy { default_data_dir }, desired_state: false + property :error_log, String, default: lazy { default_error_log }, desired_state: false + property :initial_root_password, String, default: 'ilikerandompasswords', desired_state: false + property :instance, String, name_property: true, desired_state: false + property :mysqld_options, Hash, default: {}, desired_state: false + property :pid_file, String, default: lazy { default_pid_file }, desired_state: false + property :port, [String, Integer], default: '3306', desired_state: false + property :socket, String, default: lazy { default_socket_file }, desired_state: false + property :tmp_dir, String, desired_state: false + + alias socket_file socket + + require_relative 'helpers' + include MysqlCookbook::HelpersBase + + # action class methods are available within the actions and work as if the coded + # was inline the action. No messing with classes or passing in the new_resource + action_class do + def create_system_user + group 'mysql' do + action :create + end + + user 'mysql' do + gid 'mysql' + action :create + end + end + + def create_config + # require 'pry' ; binding.pry + + # Yak shaving secion. Account for random errata. + # + # Turns out that mysqld is hard coded to try and read + # /etc/mysql/my.cnf, and its presence causes problems when + # setting up multiple services. + file "#{prefix_dir}/etc/mysql/my.cnf" do + action :delete + end + + file "#{prefix_dir}/etc/my.cnf" do + action :delete + end + + # mysql_install_db is broken on 5.6.13 + link "#{prefix_dir}/usr/share/my-default.cnf" do + to "#{etc_dir}/my.cnf" + not_if { ::File.exist? "#{prefix_dir}/usr/share/my-default.cnf" } # FIXME: Chef bug? + action :create + end + + # Support directories + directory etc_dir do + owner new_resource.run_user + group new_resource.run_group + mode '0750' + recursive true + action :create + end + + directory new_resource.include_dir do + owner new_resource.run_user + group new_resource.run_group + mode '0750' + recursive true + action :create + end + + directory run_dir do + owner new_resource.run_user + group new_resource.run_group + mode '0755' + recursive true + action :create + end + + directory log_dir do + owner new_resource.run_user + group new_resource.run_group + mode '0750' + recursive true + action :create + end + + directory new_resource.data_dir do + owner new_resource.run_user + group new_resource.run_group + mode '0750' + recursive true + action :create + end + + # Main configuration file + template "#{etc_dir}/my.cnf" do + source 'my.cnf.erb' + cookbook 'mysql' + owner new_resource.run_user + group new_resource.run_group + mode '0600' + variables(config: new_resource) + action :create + end + end + + def initialize_database + # initialize database and create initial records + bash "#{new_resource.name} initial records" do + code init_records_script + umask '022' + returns [0, 1, 2] # facepalm + not_if "/usr/bin/test -f #{new_resource.data_dir}/mysql/user.frm" + action :run + end + end + + def delete_support_directories + # Stop the service before removing support directories + delete_stop_service + + directory etc_dir do + recursive true + action :delete + end + + directory run_dir do + recursive true + action :delete + end + + directory log_dir do + recursive true + action :delete + end + end + + # + # Platform specific bits + # + def configure_apparmor + # Do not add these resource if inside a container + # Only valid on Ubuntu + return if ::File.exist?('/.dockerenv') || ::File.exist?('/.dockerinit') || node['platform'] != 'ubuntu' + + # Apparmor + package 'apparmor' do + action :install + end + + directory '/etc/apparmor.d/local/mysql' do + owner 'root' + group 'root' + mode '0755' + recursive true + action :create + end + + template '/etc/apparmor.d/local/usr.sbin.mysqld' do + cookbook 'mysql' + source 'apparmor/usr.sbin.mysqld-local.erb' + owner 'root' + group 'root' + mode '0644' + action :create + notifies :restart, "service[#{new_resource.instance} apparmor]", :immediately + end + + template '/etc/apparmor.d/usr.sbin.mysqld' do + cookbook 'mysql' + source 'apparmor/usr.sbin.mysqld.erb' + owner 'root' + group 'root' + mode '0644' + action :create + notifies :restart, "service[#{new_resource.instance} apparmor]", :immediately + end + + template "/etc/apparmor.d/local/mysql/#{new_resource.instance}" do + cookbook 'mysql' + source 'apparmor/usr.sbin.mysqld-instance.erb' + owner 'root' + group 'root' + mode '0644' + variables( + config: new_resource, + mysql_name: mysql_name + ) + action :create + notifies :restart, "service[#{new_resource.instance} apparmor]", :immediately + end + + service "#{new_resource.instance} apparmor" do + service_name 'apparmor' + action :nothing + end + end + end + end +end diff --git a/cookbooks/mysql/libraries/mysql_service_manager_systemd.rb b/cookbooks/mysql/libraries/mysql_service_manager_systemd.rb new file mode 100644 index 0000000..5c6880a --- /dev/null +++ b/cookbooks/mysql/libraries/mysql_service_manager_systemd.rb @@ -0,0 +1,142 @@ +module MysqlCookbook + class MysqlServiceManagerSystemd < MysqlServiceBase + resource_name :mysql_service_manager_systemd + + provides :mysql_service_manager, os: 'linux' do |_node| + Chef::Platform::ServiceHelpers.service_resource_providers.include?(:systemd) + end + + action :create do + # from base + create_system_user + stop_system_service + create_config + configure_apparmor + initialize_database + end + + action :start do + # Needed for Debian / Ubuntu + directory '/usr/libexec' do + owner 'root' + group 'root' + mode '0755' + action :create + end + + # this script is called by the main systemd unit file, and + # spins around until the service is actually up and running. + template "/usr/libexec/#{mysql_name}-wait-ready" do + path "/usr/libexec/#{mysql_name}-wait-ready" + source 'systemd/mysqld-wait-ready.erb' + owner 'root' + group 'root' + mode '0755' + variables(socket_file: socket_file) + cookbook 'mysql' + action :create + end + + # this is the main systemd unit file + template "/etc/systemd/system/#{mysql_name}.service" do + path "/etc/systemd/system/#{mysql_name}.service" + source 'systemd/mysqld.service.erb' + owner 'root' + group 'root' + mode '0644' + variables( + config: new_resource, + etc_dir: etc_dir, + base_dir: base_dir, + mysqld_bin: mysqld_bin + ) + cookbook 'mysql' + notifies :run, "execute[#{new_resource.instance} systemctl daemon-reload]", :immediately + action :create + end + + # avoid 'Unit file changed on disk' warning + execute "#{new_resource.instance} systemctl daemon-reload" do + command '/bin/systemctl daemon-reload' + action :nothing + end + + # tmpfiles.d config so the service survives reboot + template "/usr/lib/tmpfiles.d/#{mysql_name}.conf" do + path "/usr/lib/tmpfiles.d/#{mysql_name}.conf" + source 'tmpfiles.d.conf.erb' + owner 'root' + group 'root' + mode '0644' + variables( + run_dir: run_dir, + run_user: new_resource.run_user, + run_group: new_resource.run_group + ) + cookbook 'mysql' + action :create + end + + # service management resource + service mysql_name.to_s do + service_name mysql_name + provider Chef::Provider::Service::Systemd + supports restart: true, status: true + action [:enable, :start] + end + end + + action :stop do + # service management resource + service mysql_name.to_s do + service_name mysql_name + provider Chef::Provider::Service::Systemd + supports status: true + action [:disable, :stop] + only_if { ::File.exist?("/usr/lib/systemd/system/#{mysql_name}.service") } + end + end + + action :restart do + # service management resource + service mysql_name.to_s do + service_name mysql_name + provider Chef::Provider::Service::Systemd + supports restart: true + action :restart + end + end + + action :reload do + # service management resource + service mysql_name.to_s do + service_name mysql_name + provider Chef::Provider::Service::Systemd + action :reload + end + end + + action_class do + def stop_system_service + # service management resource + service 'mysql' do + service_name system_service_name + provider Chef::Provider::Service::Systemd + supports status: true + action [:stop, :disable] + end + end + + def delete_stop_service + # service management resource + service mysql_name.to_s do + service_name mysql_name + provider Chef::Provider::Service::Systemd + supports status: true + action [:disable, :stop] + only_if { ::File.exist?("/usr/lib/systemd/system/#{mysql_name}.service") } + end + end + end + end +end diff --git a/cookbooks/mysql/libraries/mysql_service_manager_sysvinit.rb b/cookbooks/mysql/libraries/mysql_service_manager_sysvinit.rb new file mode 100644 index 0000000..5608dec --- /dev/null +++ b/cookbooks/mysql/libraries/mysql_service_manager_sysvinit.rb @@ -0,0 +1,79 @@ +module MysqlCookbook + class MysqlServiceManagerSysvinit < MysqlServiceBase + resource_name :mysql_service_manager_sysvinit + + provides :mysql_service_manager, os: 'linux' + + action :create do + # from base + create_system_user + stop_system_service + create_config + initialize_database + configure_apparmor + end + + action :start do + template "/etc/init.d/#{mysql_name}" do + source 'sysvinit/mysqld.erb' + owner 'root' + group 'root' + mode '0755' + variables( + config: new_resource, + defaults_file: defaults_file, + error_log: new_resource.error_log, + mysql_name: mysql_name, + mysqladmin_bin: mysqladmin_bin, + mysqld_safe_bin: mysqld_safe_bin, + pid_file: new_resource.pid_file, + scl_name: scl_name + ) + cookbook 'mysql' + action :create + end + + service mysql_name do + supports restart: true, status: true + action [:enable, :start] + end + end + + action :stop do + service mysql_name do + supports restart: true, status: true + action [:stop] + end + end + + action :restart do + service mysql_name do + supports restart: true + action :restart + end + end + + action :reload do + service mysql_name do + action :reload + end + end + + action_class do + def stop_system_service + service system_service_name do + supports status: true + action [:stop, :disable] + end + end + + def delete_stop_service + service mysql_name do + supports status: true + action [:disable, :stop] + only_if { ::File.exist?("#{etc_dir}/init.d/#{mysql_name}") } + end + end + end + end +end diff --git a/cookbooks/mysql/libraries/mysql_service_manager_upstart.rb b/cookbooks/mysql/libraries/mysql_service_manager_upstart.rb new file mode 100644 index 0000000..f8f28c2 --- /dev/null +++ b/cookbooks/mysql/libraries/mysql_service_manager_upstart.rb @@ -0,0 +1,103 @@ +module MysqlCookbook + class MysqlServiceManagerUpstart < MysqlServiceBase + resource_name :mysql_service_manager_upstart + + provides :mysql_service_manager, platform_family: 'debian' do |_node| + Chef::Platform::ServiceHelpers.service_resource_providers.include?(:upstart) && + !Chef::Platform::ServiceHelpers.service_resource_providers.include?(:systemd) && + !Chef::Platform::ServiceHelpers.service_resource_providers.include?(:redhat) && + ::File.exist?('/sbin/status') # Fix for Docker, in 7 and 8 images /sbin/status doesn't exists and Upstart provider doesn't work + end + + action :create do + # from base + create_system_user + stop_system_service + create_config + configure_apparmor + initialize_database + end + + action :start do + template "/usr/sbin/#{mysql_name}-wait-ready" do + source 'upstart/mysqld-wait-ready.erb' + owner 'root' + group 'root' + mode '0755' + variables(socket_file: socket_file) + cookbook 'mysql' + action :create + end + + template "/etc/init/#{mysql_name}.conf" do + source 'upstart/mysqld.erb' + owner 'root' + group 'root' + mode '0644' + variables( + defaults_file: defaults_file, + mysql_name: mysql_name, + run_group: new_resource.run_group, + run_user: new_resource.run_user, + socket_dir: new_resource.socket_dir + ) + cookbook 'mysql' + action :create + end + + service mysql_name do + provider Chef::Provider::Service::Upstart + supports status: true + action [:start] + end + end + + action :stop do + service mysql_name do + provider Chef::Provider::Service::Upstart + supports restart: true, status: true + action [:stop] + end + end + + action :restart do + # With Upstart, restarting the service doesn't behave "as expected". + # We want the post-start stanzas, which wait until the + # service is available before returning + # + # http://upstart.ubuntu.com/cookbook/#restart + service mysql_name do + provider Chef::Provider::Service::Upstart + action [:stop, :start] + end + end + + action :reload do + # With Upstart, reload just sends a HUP signal to the process. + # As far as I can tell, this doesn't work the way it's + # supposed to, so we need to actually restart the service. + service mysql_name do + provider Chef::Provider::Service::Upstart + action [:stop, :start] + end + end + + action_class do + def stop_system_service + service system_service_name do + provider Chef::Provider::Service::Upstart + supports status: true + action [:stop, :disable] + end + end + + def delete_stop_service + service mysql_name do + provider Chef::Provider::Service::Upstart + action [:disable, :stop] + only_if { ::File.exist?("#{etc_dir}/init/#{mysql_name}") } + end + end + end + end +end diff --git a/cookbooks/mysql/metadata.json b/cookbooks/mysql/metadata.json new file mode 100644 index 0000000..f847f3b --- /dev/null +++ b/cookbooks/mysql/metadata.json @@ -0,0 +1 @@ +{"name":"mysql","version":"8.5.1","description":"Provides mysql_service, mysql_config, and mysql_client resources","long_description":"","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"redhat":">= 6.0","centos":">= 6.0","scientific":">= 6.0","oracle":">= 6.0","amazon":">= 0.0.0","fedora":">= 0.0.0","debian":">= 7.0","ubuntu":">= 12.04","opensuse":">= 13.0","opensuseleap":">= 0.0.0","suse":">= 12.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/chef-cookbooks/mysql","issues_url":"https://github.com/chef-cookbooks/mysql/issues","chef_version":[[">= 12.7"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/mysql/templates/default/apparmor/usr.sbin.mysqld-instance.erb b/cookbooks/mysql/templates/default/apparmor/usr.sbin.mysqld-instance.erb new file mode 100644 index 0000000..130beb7 --- /dev/null +++ b/cookbooks/mysql/templates/default/apparmor/usr.sbin.mysqld-instance.erb @@ -0,0 +1,14 @@ +/etc/<%= @mysql_name %>/*.pem r, +/etc/<%= @mysql_name %>/conf.d/ r, +/etc/<%= @mysql_name %>/conf.d/* r, +/etc/<%= @mysql_name %>/my.cnf r, +<%= @config.log_dir %>/ r, +<%= @config.log_dir %>/* rw, +<%= @config.data_dir %>/ r, +<%= @config.data_dir %>/** rwk, +<%= @config.run_dir %>/** rw, +<%= @config.pid_file %> rw, +<%= @config.socket_file %> rw, +/tmp/<%= @mysql_name %>/ r, +/tmp/<%= @mysql_name %>/my.sql r, +<%= @config.tmp_dir %>/* rw, diff --git a/cookbooks/mysql/templates/default/apparmor/usr.sbin.mysqld-local.erb b/cookbooks/mysql/templates/default/apparmor/usr.sbin.mysqld-local.erb new file mode 100644 index 0000000..b261920 --- /dev/null +++ b/cookbooks/mysql/templates/default/apparmor/usr.sbin.mysqld-local.erb @@ -0,0 +1 @@ +#include diff --git a/cookbooks/mysql/templates/default/apparmor/usr.sbin.mysqld.erb b/cookbooks/mysql/templates/default/apparmor/usr.sbin.mysqld.erb new file mode 100644 index 0000000..19ddbf5 --- /dev/null +++ b/cookbooks/mysql/templates/default/apparmor/usr.sbin.mysqld.erb @@ -0,0 +1,47 @@ +# vim:syntax=apparmor +# Last Modified: Tue Jun 19 17:37:30 2007 +#include + +/usr/sbin/mysqld { + #include + #include + #include + #include + #include + + capability dac_override, + capability sys_resource, + capability setgid, + capability setuid, + + network tcp, + + /etc/hosts.allow r, + /etc/hosts.deny r, + + /etc/mysql/*.pem r, + /etc/mysql/conf.d/ r, + /etc/mysql/conf.d/* r, + /etc/mysql/*.cnf r, + /usr/lib/mysql/plugin/ r, + /usr/lib/mysql/plugin/*.so* mr, + /usr/sbin/mysqld mr, + /usr/share/mysql/** r, + /var/log/mysql.log rw, + /var/log/mysql.err rw, + /var/lib/mysql/ r, + /var/lib/mysql/** rwk, + /var/log/mysql/ r, + /var/log/mysql/* rw, + /var/run/mysqld/mysqld.pid rw, + /var/run/mysqld/mysqld.sock w, + /var/run/mysqld/mysqld.sock.lock rw, + /run/mysqld/mysqld.pid rw, + /run/mysqld/mysqld.sock w, + /run/mysqld/mysqld.sock.lock rw, + + /sys/devices/system/cpu/ r, + + # Site-specific additions and overrides. See local/README for details. + #include +} diff --git a/cookbooks/mysql/templates/default/my.cnf.erb b/cookbooks/mysql/templates/default/my.cnf.erb new file mode 100644 index 0000000..ff10156 --- /dev/null +++ b/cookbooks/mysql/templates/default/my.cnf.erb @@ -0,0 +1,57 @@ +# Chef generated my.cnf for instance mysql-<%= @config.name %> + +[client] +<% if @config.charset %> +default-character-set = <%= @config.charset %> +<% end %> +<% if @config.port %> +port = <%= @config.port %> +<% end %> +<% if @config.socket_file %> +socket = <%= @config.socket_file %> +<% end %> + +[mysql] +<% if @config.charset %> +default-character-set = <%= @config.charset %> +<% end %> + +[mysqld] +<% if @config.run_user %> +user = <%= @config.run_user %> +<% end %> +<% if @config.pid_file %> +pid-file = <%= @config.pid_file %> +<% end %> +<% if @config.socket_file %> +socket = <%= @config.socket_file %> +<% end %> +<% if @config.bind_address %> +bind-address = <%= @config.bind_address %> +<% end %> +<% if @config.port %> +port = <%= @config.port %> +<% end %> +<% if @config.data_dir %> +datadir = <%= @config.data_dir %> +<% end %> +<% if @config.tmp_dir %> +tmpdir = <%= @config.tmp_dir %> +<% end %> +<% @config.mysqld_options.each do |option,value| %> +<%= option %> = <%= value %> +<% end %> +<% if @config.lc_messages_dir %> +lc-messages-dir = <%= @config.lc_messages_dir %> +<% end %> +<% if @config.error_log %> +log-error = <%= @config.error_log %> +<% end %> +<% if @config.include_dir %> +!includedir <%= @config.include_dir %> +<% end %> + +[mysqld_safe] +<% if @config.socket_file %> +socket = <%= @config.socket_file %> +<% end %> diff --git a/cookbooks/mysql/templates/default/smf/svc.method.mysqld.erb b/cookbooks/mysql/templates/default/smf/svc.method.mysqld.erb new file mode 100644 index 0000000..5cc178a --- /dev/null +++ b/cookbooks/mysql/templates/default/smf/svc.method.mysqld.erb @@ -0,0 +1,28 @@ +#!/sbin/sh +# +# Generated by Chef +# + +. /lib/svc/share/smf_include.sh + +ulimit -n 10240 + +case "$1" in +start) + <%= @mysqld_bin %> \ + --defaults-file=<%= @defaults_file %> \ + --basedir=<%= @base_dir %> \ + --datadir=<%= @data_dir %> \ + --pid-file=<%= @pid_file %> \ + --log-error=<%= @error_log %> & + ;; +stop) + [ -f <%= @pid_file %> ] && kill `/usr/bin/head -1 <%= @pid_file %>` + ;; +*) + echo "Usage: $0 {start|stop}" >&2 + exit 1 + ;; +esac + +exit $SMF_EXIT_OK diff --git a/cookbooks/mysql/templates/default/systemd/mysqld-wait-ready.erb b/cookbooks/mysql/templates/default/systemd/mysqld-wait-ready.erb new file mode 100644 index 0000000..a566bf3 --- /dev/null +++ b/cookbooks/mysql/templates/default/systemd/mysqld-wait-ready.erb @@ -0,0 +1,30 @@ +#!/bin/sh + +daemon_pid="$1" + +# Wait for the server to come up or for the mysqld process to disappear +ret=0 +while /bin/true; do + RESPONSE=`/usr/bin/mysqladmin --no-defaults --socket="<%= @socket_file %>" --user=UNKNOWN_MYSQL_USER ping 2>&1` + mret=$? + if [ $mret -eq 0 ]; then + break + fi + # exit codes 1, 11 (EXIT_CANNOT_CONNECT_TO_SERVICE) are expected, + # anything else suggests a configuration error + if [ $mret -ne 1 -a $mret -ne 11 ]; then + ret=1 + break + fi + # "Access denied" also means the server is alive + echo "$RESPONSE" | grep -q "Access denied for user" && break + + # Check process still exists + if ! /bin/kill -0 $daemon_pid 2>/dev/null; then + ret=1 + break + fi + sleep 1 +done + +exit $ret diff --git a/cookbooks/mysql/templates/default/systemd/mysqld.service.erb b/cookbooks/mysql/templates/default/systemd/mysqld.service.erb new file mode 100644 index 0000000..f1fb6c1 --- /dev/null +++ b/cookbooks/mysql/templates/default/systemd/mysqld.service.erb @@ -0,0 +1,16 @@ +[Unit] +Description=mysql_service[mysql-<%= @config.instance %>] +After=syslog.target +After=network.target + +[Service] +Type=simple +User=<%= @config.run_user %> +Group=<%= @config.run_group %> +ExecStart=<%= @mysqld_bin %> --defaults-file=<%= @etc_dir %>/my.cnf --basedir=<%= @base_dir %> +ExecStartPost=/usr/libexec/mysql-<%= @config.instance %>-wait-ready $MAINPID +TimeoutSec=300 +PrivateTmp=true + +[Install] +WantedBy=multi-user.target diff --git a/cookbooks/mysql/templates/default/sysvinit/mysqld.erb b/cookbooks/mysql/templates/default/sysvinit/mysqld.erb new file mode 100644 index 0000000..45b952d --- /dev/null +++ b/cookbooks/mysql/templates/default/sysvinit/mysqld.erb @@ -0,0 +1,279 @@ +#!/bin/bash +# +### BEGIN INIT INFO +# Provides: <%= @mysql_name %> +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Should-Start: $network $time +# Should-Stop: $network $time +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start and stop the mysql database server daemon +# Description: Controls the main MySQL database server daemon "mysqld" +# and its wrapper script "mysqld_safe". +### END INIT INFO + +# set -e +# set -u + +### Exit code reference +# http://fedoraproject.org/wiki/Packaging:SysVInitScript +# http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html + +# Source functions +<% if node['platform_family'] == 'rhel' %> +# Source RHEL function library. +. /etc/rc.d/init.d/functions +<% end %> + +#### +# Variables +#### + +STARTTIMEOUT=900 +STOPTIMEOUT=900 +PID_DELAY=60 + +#### +# Helper functions +### + +# Boolean function to see if MYSQL_PID exists and is a number +pid_exists() { + PID_EXISTS=1 + if [ -f <%= @pid_file %> ]; then + MYSQLD_PID=`cat <%= @pid_file %> 2>/dev/null` + if [ -n "$MYSQLD_PID" ] && [ -d "/proc/$MYSQLD_PID" ] ; then + PID_EXISTS=0 + fi + fi + return $PID_EXISTS +} + +# Use mysqladmin to ping the service as an invalid user over a socket +running() { + RUNNING=1 + RESPONSE=`<%= @mysqladmin_bin %> --defaults-file=<%= @defaults_file %> --user=UNKNOWN_MYSQL_USER ping 2>&1` + local mret=$? + if pid_exists \ + && [ $mret -eq 0 ] \ + || [ `echo $RESPONSE | grep -q "Access denied for user"` ]; then + RUNNING=0 + fi + return $RUNNING +} + +writable_error_log() { + WRITABLE_ERROR_LOG=1 + touch "<%= @error_log %>" 2>/dev/null + touchret=$? + if [ $touchret -eq 0 ]; then + chown <%= @config.run_user %>:<%= @config.run_group %> <%= @error_log %> + return 0 + else + return $WRITABLE_ERROR_LOG + fi +} + +print_start_success() { + <% if node['platform_family'] == 'rhel' %> + action $"Starting <%= @mysql_name %>: " /bin/true + <% else %> + echo "Staring MySQL instance <%= @mysql_name %>" + <% end %> + return 0; +} + +print_start_failure() { + <% if node['platform_family'] == 'rhel' %> + action $"Starting <%= @mysql_name %>: " /bin/false + <% else %> + echo "Could not start MySQL instance <%= @mysql_name %>" + <% end %> + return 0; +} + +print_reload_success() { + <% if node['platform_family'] == 'rhel' %> + action $"Reloading <%= @mysql_name %>" /bin/true + <% else %> + echo "Reload success for <%= @mysql_name %>" + <% end %> + return 0; +} + +print_reload_failure() { + <% if node['platform_family'] == 'rhel' %> + action $"Reloading <%= @mysql_name %>" /bin/false + <% else %> + echo "Reload failed for <%= @mysql_name %>" + <% end %> + return 0; +} + +print_stop_success() { + <% if node['platform_family'] == 'rhel' %> + action $"Stopping <%= @mysql_name %>: " /bin/true + <% else %> + echo "Stopping MySQL instance <%= @mysql_name %>" + <% end %> + return 0; +} + +print_stop_failure() { + <% if node['platform_family'] == 'rhel' %> + action $"Stopping <%= @mysql_name %>: " /bin/false + <% else %> + echo "Could not stop MySQL instance <%= @mysql_name %>" + <% end %> + return 0; +} + +start_command() { + # Attempt to start <%= @mysql_name %> + echo "Starting MySQL instance <%= @mysql_name %>" + + local scl_name="<%= @scl_name %>" + + if [ -z $scl_name ]; then + <%= @mysqld_safe_bin %> \ + --defaults-file=<%= @defaults_file %> \ + >/dev/null 2>&1 & + local pid=$! + else + scl enable $scl_name "<%= @mysqld_safe_bin %> \ + --defaults-file=<%= @defaults_file %> \ + >/dev/null 2>&1 &" + local pid=$! + fi + + return $pid +} + +#### +# Init script actions +### + +# Start <%= @mysql_name %> +start() { + # exit 0 if already running. + if running; then + print_start_success + return 0; + fi + + # exit 4 if we can't write to error_log + if ! writable_error_log; then + print_start_failure + return 4 + fi + + # run program + start_command; + start_pid=$? + + # Timeout loop + local TIMEOUT=$STARTTIMEOUT + while [ $TIMEOUT -gt 0 ]; do + if running; then + break + fi + + let CURRENT_DELAY=${STARTTIMEOUT}-${TIMEOUT} + if [ $CURRENT_DELAY -gt $PID_DELAY ] \ + && ! pid_exists; then + break + fi + + sleep 1 + let TIMEOUT=${TIMEOUT}-1 + done + + if running; then + # successbaby.gif + print_start_success + return 0 + elif ! pid_exists; then + # Handle startup failure + print_start_failure + return 3 + elif [ $TIMEOUT -eq 0 ]; then + # Handle timeout + print_start_failure + # clean up + kill $start_pid 2>/dev/null + return 1 + fi +} + +# Reload <%= @mysql_name %> +reload() { + <%= @mysqladmin_bin %> reload + local ret=$? + if [ $ret -eq 0 ]; then + print_reload_success; + else + print_reload_failure; + fi + return $ret +} + +# Status of <%= @mysql_name %> +status() { + if running; then + echo "<%= @mysql_name %> is running" + return 0 + else + echo "<%= @mysql_name %> is not running" + return 1 + fi +} + +# Stop <%= @mysql_name %> +stop() { + if running; then + echo "Stopping MySQL instance <%= @mysql_name %>" + if [ -f <%= @pid_file %> ]; then + /bin/kill `cat <%= @pid_file %> 2>/dev/null` + kstat=$? + fi + + # Timeout loop + local TIMEOUT=$STARTTIMEOUT + while [ $TIMEOUT -gt 0 ]; do + if [ -e <%= @pid_file %> ]; then + sleep 1 + fi + let TIMEOUT=${TIMEOUT}-1 + done + + return $kstat + else + echo "MySQL instance <%= @mysql_name %> Stopped." + return 0 + fi +} + +# main() +case "$1" in + start) + start + ;; + stop) + stop + ;; + status) + status + ;; + restart) + stop ; start + ;; + reload) + reload + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|reload}" + exit 2 +esac + +exit $? diff --git a/cookbooks/mysql/templates/default/tmpfiles.d.conf.erb b/cookbooks/mysql/templates/default/tmpfiles.d.conf.erb new file mode 100644 index 0000000..59d0426 --- /dev/null +++ b/cookbooks/mysql/templates/default/tmpfiles.d.conf.erb @@ -0,0 +1 @@ +d <%= @run_dir %> 0755 <%= @run_user %> <%= @run_group %> - diff --git a/cookbooks/mysql/templates/default/upstart/mysqld-wait-ready.erb b/cookbooks/mysql/templates/default/upstart/mysqld-wait-ready.erb new file mode 100644 index 0000000..f99308f --- /dev/null +++ b/cookbooks/mysql/templates/default/upstart/mysqld-wait-ready.erb @@ -0,0 +1,22 @@ +#!/bin/sh + +# Wait for the server to come up +ret=0 +while /bin/true; do + RESPONSE=`/usr/bin/mysqladmin --no-defaults --socket="<%= @socket_file %>" --user=UNKNOWN_MYSQL_USER ping 2>&1` + mret=$? + if [ $mret -eq 0 ]; then + break + fi + # exit codes 1, 11 (EXIT_CANNOT_CONNECT_TO_SERVICE) are expected, + # anything else suggests a configuration error + if [ $mret -ne 1 -a $mret -ne 11 ]; then + ret=1 + break + fi + # "Access denied" also means the server is alive + echo "$RESPONSE" | grep -q "Access denied for user" && break + sleep 1 +done + +exit $ret diff --git a/cookbooks/mysql/templates/default/upstart/mysqld.erb b/cookbooks/mysql/templates/default/upstart/mysqld.erb new file mode 100644 index 0000000..4ac214c --- /dev/null +++ b/cookbooks/mysql/templates/default/upstart/mysqld.erb @@ -0,0 +1,26 @@ +# <%= @mysql_name %> Service + +description "MySQL service <%= @mysql_name %>" +author "chef-client" + +start on runlevel [2345] +stop on starting rc RUNLEVEL=[016] + +respawn +respawn limit 2 5 + +env HOME=/etc/<%= @mysql_name %> +umask 007 + +kill timeout 300 + +pre-start script +[ -d /run/<%= @mysql_name %> ] || install -m 755 -o <%= @run_user %> -g <%= @run_group %> -d /run/<%= @mysql_name %> +[ -d <%= @socket_dir %> ] || install -m 755 -o <%= @run_user %> -g <%= @run_group %> -d <%= @socket_dir %> +end script + +exec /usr/sbin/mysqld --defaults-file=<%= @defaults_file %> + +post-start script +/usr/sbin/<%= @mysql_name %>-wait-ready +end script diff --git a/cookbooks/nginx/CHANGELOG.md b/cookbooks/nginx/CHANGELOG.md new file mode 100644 index 0000000..900fa7c --- /dev/null +++ b/cookbooks/nginx/CHANGELOG.md @@ -0,0 +1,725 @@ +# nginx Cookbook CHANGELOG + +This file is used to list changes made in each version of the nginx cookbook. + +## 9.0.0 (2018-11-13) + +- This cookbook now requires Chef 13.3 or later, but no longer requires the zypper cookbook. This cookbook was throwing deprecation warnings for users of current Chef 14 releases. + +## 8.1.6 (2018-10-05) + +- passenger: fixed install order +- passenger Ubuntu 18.04 support +- Evaluate ohai_plugin_enabled in the source recipe +- Abstract nginx users home path to attribute + +## 8.1.5 (2018-07-23) + +- Fixes cookbook fails when installing repo passenger because there is no service declaration inline +- Add proxy buffers options + +## 8.1.4 (2018-07-18) + +- Adds the ability to toggle Ohai Plugin +- Use build_essential resource instead of the cookbook so we can use the built in resource on Chef 14+ + +## 8.1.2 (2018-02-26) + +- Add map_hash_max_size as configuration option + +## 8.1.1 (2018-02-26) + +- Use Chef::VersionConstraint in auth request module so we properly compare versions + +## 8.1.0 (2018-02-19) + +- Added a new nginx_stream resource for enabling/disable nginx stream blocks +- Make sure we install zlib for source installs. This gives us compression support and fixes compilation on Debian 9 + +## 8.0.1 (2018-02-16) + +- Update the required Chef release to 12.14 since we're using yum/apt repository resources +- Add a new 'site_name' property to the nginx_site resource. This allows you to specify a site name if it differs from the resource name +- Removed the check for nginx < 1.2 in the realip module + +## 8.0.0 (2018-02-16) + +- Remove ChefSpec matchers since these are autogenerated now +- Remove compat_resource cookbook dependency and require Chef 12.7+ instead +- Expand testing and test on Amazon Linux + +## 7.0.2 (2017-11-22) + +- Fix a bug that led to nginx recompiling when it didn't need to + +## 7.0.1 (2017-11-14) + +- Move passenger test attributes into the cookbook +- Resolve FC108 warning + +## 7.0.0 (2017-09-18) + +### Breaking Changes + +- This release of the nginx cookbook merges all changes that occurred within the chef_nginx fork from 2.8 - 6.2\. This includes multiple breaking changes along with a large number of improvements and bug fixes. If you're upgrading from 2.7 to current make sure to read the whole changelog to make sure you're ready. + +### Other Changes + +- Added a new resource nginx_runit_cleanup has been introduced which stops the existing nginx runit service and removes the init files. This is now called automatically from the default recipe to cleanup an existing installation. This should make it possible for users to migrate from the 2.X release to the current w/o manual steps. +- Fixed compile failures on Fedora and any other distros released in the future which use GCC 7 +- Added the .m3u8 mimetype +- Moved all files out of the files/default directory since this isn't required with Chef 12 and later +- Added ulimit to the nginx sysconfig file for RHEL platforms + +## 6.2.0 (2017-09-12) + +- Install basic configuration before starting the nginx service +- Correct documentation for `rate_limiting_backoff` attribute +- Phusion Passenger distro has pid file location in /run/nginx.pid +- [GH-92] add a test suite for passenger install +- Swap the maintainer files for a readme section +- Update nginx version [1.12.1] and checksum attributes for source installs +- Update versions and checksums for lua-nginx-module and echo-nginx-module +- Simplify repo logic and use HTTPS repos + +## 6.1.1 (2017-06-08) + +- Use multipackage installs in the pagespeed recipe to speed things up +- Several fixes for Amazon Linux on Chef 13+ + +## 6.1.0 (2017-06-07) + +- Add attributes for setting the repository URLs +- Fix support for Amazon Linux repos on Chef 13+ + +## 6.0.3 (2017-06-05) + +- Correctly compare nginx versions with multiple digits so 1.10 is properly recognized as coming after 1.2. + +## 6.0.2 (2017-04-27) + +- Resolve name conflicts in the resource + +## 6.0.1 (2017-04-04) + +- double quotes are unnecessary in lua configure flags + +## 6.0.0 (2017-03-25) + +### Breaking change + +- Support for Runit as an init system has been removed. If you require runit you will need to pin to the 5.X cookbook release. We highly recommend using either systemd or upstart instead of Runit. + +### Other changes + +- Install nginx 1.10.3 for source based installs +- Remove freebsd cookbook from testing as it's not necessary anymore +- Bump OpenSSL to 1.0.2k + +## 5.1.3 (2017-03-24) + +- Update apache2 license string +- Add image/svg+xml to gzip_files defaults +- support `worker_shutdown_timeout` released in 1.11.11 + +## 5.1.2 (2017-03-14) + +- Setup LD options to include /usr/local/lib for libluajit in search path and bump the lua version + +## 5.1.1 (2017-03-02) + +- Add WantedBy to systemd service file so it starts at boot +- Avoid a warning in nginx_site by moving the template check outside the resource +- Allow nginx_site to specify template as an array of templates + +## 5.1.0 (2017-03-01) + +- Support the load_module directive +- Test with Local Delivery and not Rake +- Remove EOL platforms from the kitchen configs + +## 5.0.7 (2017-02-12) + +- Fix Opsworks compatibility +- Resolve a Chef 13 deprecation warning + +## 5.0.6 (2017-01-16) + +- Rebuild shared library cache after installing luajit + +## 5.0.5 (2017-01-09) + +- Fix typo in the pagespeed recipe + +## 5.0.4 (2017-01-04) + +- Avoid deprecation warnings by only defining nginx service once + +## 5.0.3 (2017-01-03) + +- Add ability to write passenger log to another location +- Properly disable the default site with nginx.org packages + +## 5.0.2 (2016-12-22) + +- Requite the latest compat_resource + +## 5.0.1 (2016-12-13) + +- Use multipackage in pagespeed module recipe to speed up installs +- Simplify the distro repo setup logic to ensure we're using the correct repos under all conditions. Previously the upstream repo was being missed on Suse systems +- Determine pidfile location correctly via a helper so we correctly set pidfiles when using Upstream packages on Ubuntu 14.04 / 16.04\. This involved removing the attribute for the pidfile location, which may cause issues if you relied on that attribute. +- Testing improvements to make sure all suites run and the suites are testing the correct conditions + +## 5.0.0 (2016-12-07) + +### Breaking changes + +- Default to the upstream nginx.org repo for package installs. The official nginx repo gives an improved experience over outdated distro releases. This can be disabled via attribute if you'd like to remain on the distro packages. + +### Other changes + +- Add a deprecation warning when using runit +- Rewrite the readme usage section +- Better document how to compile modules + +## 4.0.2 (2016-12-01) + +- Default to openssl 1.0.2j with source installs +- Add cookbook property to the nginx_site resource to allow using templates defined in other cookbooks +- Prevent default docroot index.html on bad url in status +- Readme improvements + +## 4.0.1 (2016-10-31) + +- Fix a version check in the realip recipe +- Align the config with the default config a bit +- Fix the ChefSpec matchers now that nginx_site is a custom resource + +## 4.0.0 (2016-10-31) + +### Breaking changes + +The nginx_site definition is now a custom_resource. This improves the overall experience and allows for notifications and reporting on resource updates. It does change the behavior in some circumstances however. Previously to disable a site you would set 'enable false' on your definition. This will still function, but will result in a deprecation warning. Instead you should use 'action :disable' since this is a real resource now. + +### Other changes + +- Avoid splitting on compile params in the ohai plugin, which resulted in some source installs attempting to install on every Chef run. +- Expanded testing and improved kitchen suite setup +- Improved documentation of attributes and cookbook usage + +## 3.2.0 (2016-10-28) + +- Reload nginx on site change + +## 3.1.2 (2016-10-24) + +- [GH-26] Remove guard on package[nginx] resource +- Fix pcre packages on RHEL that prevented pagespeed module compilation + +## 3.1.1 (2016-09-21) + +- Raise on error vs. Chef::Appliation.fatal +- Require compat_resource with notification fixes + +## 3.1.0 (2016-09-14) + +- Resolve FC023 warnings +- FreeBSD fixes +- Fail hard on unsupported platforms in the source recipe +- Install 'ca-certificates' packages with passenger +- Add `passenger_show_version_in_header` config +- Remove chef 11 compatibility +- Replace apt/yum deps with compat_resource +- Fix specs for freebsd source installs +- Remove apt recipe from the repo_passenger recipe +- Switch to += operator as << also incorrectly replaces text in root. + +## 3.0.0 (2016-08-18) + +### Breaking changes + +Ideally we'd offer perfect backwards compatibility forever, but in order to maintain the cookbook going forward we've evaluated the current scope of the cookbook and removed lesser used functionality that added code complexity. + +- The minimum chef-client version is now 12.1 or later, which will enables support for Ohai 7+ plugins, the ohai_plugin custom resource, and automatic init system discovery. +- Support for Gentoo has been removed. Gentoo lacks an official Chef package and there is no Bento image to use for Test Kitchen integration tests. +- Support for the bluepill init system has been removed. Usage of this init system has declined, and supporting it added a cookbook dependency as well as code complexity. +- Ubuntu source installs will no longer default to runit, and will instead use either Upstart or Systemd depending on the release of Ubuntu. You can still force the use of runit by setting default['nginx']['init_style'] to 'runit'. Runit was used historically before reliable init systems were shipped with Ubuntu. Both Upstart and Systemd have the concept of restarting on failure, which was the main reason for choosing Runit over sys-v init. + +### Other changes + +- Don't setup the YUM EPEL repo on Fedora as it's not needed +- Systemd based platforms will now use systemd by default for source installs +- Retry downloads of the nginx source file as the mirror sometimes fails to load +- Download the nginx source from the secure nginx.org site +- Updated the Ohai plugin to avoid deprecation notices and function better on non us-en locale systems +- Install source install pre-reqs using multi-package which speeds up Chef runs +- Add testing in Travis with Kitchen Dokken for full integration testing of each PR +- Add integration test on Chef 12.1 as well as the latest Chef to ensure compatibility with the oldest release we support +- Remove installation of apt-transport-https and instead increase the apt dependency to >= 2.9.1 which includes the installation of apt-transport-https +- Don't try to setup the nginx.org repo on Fedora as this will fail +- Better log when trying to setup repositories on unsupported platforms +- Fixed source_url and issue_url in the metadata to point to the correct URLs +- Removed Chef 10 compatibility code +- Chefspec platform updates and minor fixes +- Replace all usage of node.set with node.normal to avoid deprecation notices +- Remove the suse init script that isn't used anymore +- Speed up the specs with caching +- Move test attributes and runlists out the kitchen.yml files and into a test cookbook + +## 2.9.0 (2016-08-12) + +- Add support for Suse Nginx.org packages + +## v2.8.0 (2016-08-12) + +This is the first release of the nginx codebase under the chef_nginx namespace. We've chosen to bring this cookbook under the direction of the Community Cookbook Team, in order to ship a working 2.X release. The cookbook name has been changed, but all attributes are the same and compatibility has been maintained. After this 2.8.0 release we will release 3.0 as a Chef 12+ version of the cookbook and then work to add additional custom resources for managing nginx with wrapper cookbooks. Expect regular releases as we march towards a resource driven model. + +- Removed the restrictive version constraints for cookbook dependencies that prevented users from utilizing new functionality. Ohai has been pinned to < 4.0 to allow for Chef 11 compatibility, but other cookbooks have no upper limit +- Updated all modules in the source install to their latest releases +- Removed the GeoIP database checksums as these files are constantly updates and this causes Chef run failures +- Updated OpenSSL for source installs to 1.0.1t +- Updated the source install of Nginx to version 1.10.1 +- Updated the ohai recipe to install a Ohai 7+ compatible plugin on systems running Ohai 7+ +- Fixed installation of Passenger version 5.X+ +- Added a http_v2_module recipe +- Replaced node.set usage with node.normal to avoid deprecation warnings +- Removed the apt version pin in the Berkfile that wasn't necessary and constrained the apt version +- Removed the lua-devel package install from the lua recipe that failed chef runs and wasn't necessary +- Removed duplicate packages from the source module installs +- Added a dependency on the yum cookbook which was missing from the metadata +- Updated the mime.types file and added the charset_types configuration option to the nginx config +- Added source_url, issue_url, and chef_version metadata +- Fixed the pid file attribute logic for Ubuntu 16.04 +- Removed the Contributing doc that was for contributing to Opscode cookbooks +- Updated all test dependencies in the Gemfile +- Removed default user/group/mode declarations from resources for simplicity +- Updated documentation for dependencies in the README +- Added a chefignore file to limit the cookbook files that are uploaded to the chef server and speed up cookbook syncs to nodes +- Added additional platforms to the Test Kitchen config and removed the .kitchen.cloud.yml file +- Switched integration tests to Inspec and fixed several non-functional tests +- Switched from Rubocop to Cookstyle and resolved all warnings +- Added the standard Chef Rakefile for simplified testing +- Updated Chefspecs to avoid constant deprecation warnings and converge using chef-zero on a newer Debian 8 system +- Switch Travis CI testing to use ChefDK instead of RVM/Gem installs +- Removed testing dependencies from the Gemfile as testing should be performed via ChefDK. Release gems are still in the Gemfile as they are not shipped with ChefDK +- Added a maintainers.md doc and updated the contributing/testing docs to point to the Chef docs +- Removed Guard as guard-foodcritic doesn't support the latest release which makes guard incompatible with ChefDK + +## v2.7.6 (2015-03-17) + +- Bugfix sites do not need a .conf suffix anymore, [#338][@runningman84] + +## v2.7.5 (2015-03-17) + +**NOTE** As of this release, this cookbook in its current format is deprecated, and only critical bugs and fixes will be added. A complete rewrite is in progress, so we appreciate your patience while we sort things out. The amount of change included here + +- Fix nginx 1.4.4 archive checksum to prevent redownload, [#305][@irontoby] +- Allow setting an empty string to prevent additional repos, [#243][@miketheman] +- Use correct `mime.types` for javascript, [#259][@dwradcliffe] +- Fix `headers_more` module for source installs, [#279], [@josh-padnick] & [@miketheman] +- Remove `libtool` from `geoip` and update download paths & checksums, [@miketheman] +- Fix unquoted URL with params failing geoip module build (and tests!), [#294][@karsten-bruckmann] & [@miketheman] +- Fix typo in `source.rb`, [#205][@gregkare] +- Test updates: ChefSpec, test-kitchen. Lots of help by [@jujugrrr] +- Toolchain updates for testing +- Adds support for `tcp_nopush`, `tcp_nodelay` [@shtouff] + +After merging a ton of pull requests, here's a brief changelog. Click each to read more. + +- Merge pull request [#335] from [@stevenolen] +- Merge pull request [#332] from [@monsterstrike] +- Merge pull request [#331] from [@jalberto] +- Merge pull request [#327] from [@nkadel-skyhook] +- Merge pull request [#326] from [@bchrobot] +- Merge pull request [#325] from [@CanOfSpam3bug324] +- Merge pull request [#321] from [@jalberto] +- Merge pull request [#318] from [@evertrue] +- Merge pull request [#314] from [@bkw] +- Merge pull request [#312] from [@thomasmeeus] +- Merge pull request [#310] from [@morr] +- Merge pull request [#305] from [@irontoby] +- Merge pull request [#302] from [@auth0] +- Merge pull request [#298] from [@Mytho] +- Merge pull request [#269] from [@yveslaroche] +- Merge pull request [#259] from [@dwradcliffe] +- Merge pull request [#254] from [@evertrue] +- Merge pull request [#252] from [@gkra] +- Merge pull request [#249] from [@whatcould] +- Merge pull request [#240] from [@jcoleman] +- Merge pull request [#236] from [@adepue] +- Merge pull request [#230] from [@n1koo] +- Merge pull request [#225] from [@thommay] +- Merge pull request [#223] from [@firmhouse] +- Merge pull request [#220] from [@evertrue] +- Merge pull request [#219] from [@evertrue] +- Merge pull request [#204] from [@usertesting] +- Merge pull request [#200] from [@ffuenf] +- Merge pull request [#188] from [@larkin] +- Merge pull request [#184] from [@tvdinner] +- Merge pull request [#183] from [@jenssegers] +- Merge pull request [#174] from [@9minutesnooze] + + + +## v2.7.4 (2014-06-06) + +- [COOK-4703] Default openssl version to 1.0.1h to address CVE-2014-0224 + +## v2.7.2 (2014-05-27) + +- [COOK-4658] - Nginx::socketproxy if the context is blank or nonexistent, the location in the config file has a double slash at the beginning +- [COOK-4644] - add support to nginx::repo for Amazon Linux +- Allow .kitchen.cloud.yml to use an environment variable for the EC2 Availability Zone + +## v2.7.0 (2014-05-15) + +- [COOK-4643] - Update metadata lock on ohai +- [COOK-4588] - Give more love to FreeBSD +- [COOK-4601] - Add proxy type: Socket + +## v2.6.2 (2014-04-09) + +[COOK-4527] - set default openssl source version to 1.0.1g to address CVE-2014-0160 aka Heartbleed + +## v2.6.0 (2014-04-08) + +- Reverting COOK-4323 + +## v2.5.0 (2014-03-27) + +- [COOK-4323] - Need a resource to easily configure available sites (vhosts) + +## v2.4.4 (2014-03-13) + +- Updating for build-essential 2.0 + +## v2.4.2 (2014-02-28) + +Fixing bad commit from COOK-4330 + +## v2.4.1 (2014-02-27) + +- [COOK-4345] - nginx default recipe include install type recipe directly + +## v2.4.0 (2014-02-27) + +- [COOK-4380] - kitchen.yml platform listings for ubuntu-10.04 and ubuntu-12.04 are missing the dot +- [COOK-4330] - Bump nginx version for security issues (CVE-2013-0337, CVE-2013-4547) + +## v2.3.0 (2014-02-25) + +- **[COOK-4293](https://tickets.chef.io/browse/COOK-4293)** - Update testing Gems in nginx and fix a rubocop warnings +- **[COOK-4237] - Nginx version incorrectly parsed on Ubuntu 13 +- **[COOK-3866] - Nginx default site folder + +## v2.2.2 (2014-01-23) + +[COOK-3672] - Add gzip_static option + +## v2.2.0 + +No changes. Version bump for toolchain + +## v2.1.0 + +[COOK-3923] - Enable the list of packages installed by nginx::passenger to be configurable [COOK-3672] - Nginx should support the gzip_static option Updating for yum ~> 3.0 Fixing up style for rubocop Updating test-kitchen harness + +## v2.0.8 + +fixing metadata version error. locking to 3.0 + +## v2.0.6 + +Locking yum dependency to '< 3' + +## v2.0.4 + +### Bug + +- **[COOK-3808](https://tickets.chef.io/browse/COOK-3808)** - nginx::passenger run fails because of broken installation of package dependencies +- **[COOK-3779](https://tickets.chef.io/browse/COOK-3779)** - Build in master fails due to rubocop error + +## v2.0.2 + +### Bug + +- **[COOK-3808](https://tickets.chef.io/browse/COOK-3808)** - nginx::passenger run fails because of broken installation of package dependencies +- **[COOK-3779](https://tickets.chef.io/browse/COOK-3779)** - Build in master fails due to rubocop error + +## v2.0.0 + +### Improvement + +- **[COOK-3733](https://tickets.chef.io/browse/COOK-3733)** - Add RPM key names and GPG checking +- **[COOK-3687](https://tickets.chef.io/browse/COOK-3687)** - Add support for `http_perl` +- **[COOK-3603](https://tickets.chef.io/browse/COOK-3603)** - Add a recipe for using custom openssl +- **[COOK-3602](https://tickets.chef.io/browse/COOK-3602)** - Use an attribute for the status module port +- **[COOK-3549](https://tickets.chef.io/browse/COOK-3549)** - Refactor custom modules support +- **[COOK-3521](https://tickets.chef.io/browse/COOK-3521)** - Add support for `http_auth_request` +- **[COOK-3520](https://tickets.chef.io/browse/COOK-3520)** - Add support for `spdy` +- **[COOK-3185](https://tickets.chef.io/browse/COOK-3185)** - Add `gzip_*` attributes +- **[COOK-2712](https://tickets.chef.io/browse/COOK-2712)** - Update `upload_progress` version to 0.9.0 + +### Bug + +- **[COOK-3686](https://tickets.chef.io/browse/COOK-3686)** - Remove deprecated 'passenger_use_global_queue' directive +- **[COOK-3626](https://tickets.chef.io/browse/COOK-3626)** - Parameterize hardcoded path to helper scripts +- **[COOK-3571](https://tickets.chef.io/browse/COOK-3571)** - Reloda ohai plugin after installation +- **[COOK-3428](https://tickets.chef.io/browse/COOK-3428)** - Fix an issue where access logs are not disabled when the `disable_access_log` attribute is set to `true` +- **[COOK-3322](https://tickets.chef.io/browse/COOK-3322)** - Fix an issue where `nginx::ohai_plugin` fails when using source recipe +- **[COOK-3241](https://tickets.chef.io/browse/COOK-3241)** - Fix an issue where`nginx::ohai_plugin` fails unless using source recipe + +### New Feature + +- **[COOK-3605](https://tickets.chef.io/browse/COOK-3605)** - Add Lua module + +## v1.8.0 + +### Bug + +- **[COOK-3397](https://tickets.chef.io/browse/COOK-3397)** - Fix user from nginx package on Gentoo +- **[COOK-2968](https://tickets.chef.io/browse/COOK-2968)** - Fix foodcritic failure +- **[COOK-2723](https://tickets.chef.io/browse/COOK-2723)** - Remove duplicate passenger `max_pool_size` + +### Improvement + +- **[COOK-3186](https://tickets.chef.io/browse/COOK-3186)** - Add `client_body_buffer_size` and `server_tokens attributes` +- **[COOK-3080](https://tickets.chef.io/browse/COOK-3080)** - Add rate-limiting support +- **[COOK-2927](https://tickets.chef.io/browse/COOK-2927)** - Add support for `real_ip_recursive` directive +- **[COOK-2925](https://tickets.chef.io/browse/COOK-2925)** - Fix ChefSpec converge +- **[COOK-2724](https://tickets.chef.io/browse/COOK-2724)** - Automatically create directory for PID file +- **[COOK-2472](https://tickets.chef.io/browse/COOK-2472)** - Bump nginx version to 1.2.9 +- **[COOK-2312](https://tickets.chef.io/browse/COOK-2312)** - Add additional `mine_types` to the `gzip_types` value + +### New Feature + +- **[COOK-3183](https://tickets.chef.io/browse/COOK-3183)** - Allow inclusion in extra-cookbook modules + +## v1.7.0 + +### Improvement + +- [COOK-3030]: The repo_source attribute should allow you to not add any additional repositories to your node + +### Sub-task + +- [COOK-2738]: move nginx::passenger attributes to `nginx/attributes/passenger.rb` + +## v1.6.0 + +### Task + +- [COOK-2409]: update nginx::source recipe for new `runit_service` resource +- [COOK-2877]: update nginx cookbook test-kitchen support to 1.0 (alpha) + +### Improvement + +- [COOK-1976]: nginx source should be able to configure binary path +- [COOK-2622]: nginx: add upstart support +- [COOK-2725]: add "configtest" subcommand in initscript + +### Bug + +- [COOK-2398]: nginx_site definition cannot be used to manage the default site +- [COOK-2493]: Resources in nginx::source recipe always use 1.2.6 version, even overriding version attribute +- [COOK-2531]: Remove usage of non-existant attribute "description" for `apt_repository` +- [COOK-2665]: nginx::source install with custom sbin_path breaks ohai data + +## v1.4.0 + +- [COOK-2183] - Install nginx package from nginxyum repo +- [COOK-2311] - headers-more should be updated to the latest version +- [COOK-2455] - Support sendfile option (nginx.conf) + +## v1.3.0 + +- [COOK-1979] - Passenger module requires curl-dev(el) +- [COOK-2219] - Support `proxy_read_timeout` (in nginx.conf) +- [COOK-2220] - Support `client_max_body_size` (in nginx.conf) +- [COOK-2280] - Allow custom timing of nginx_site's reload notification +- [COOK-2304] - nginx cookbook should install 1.2.6 not 1.2.3 for source installs +- [COOK-2309] - checksums for geoip files need to be updated in nginx +- [COOK-2310] - Checksum in the `nginx::upload_progress` recipe is not correct +- [COOK-2314] - nginx::passenger: Install the latest version of passenger +- [COOK-2327] - nginx: passenger recipe should find ruby via Ohai +- [COOK-2328] - nginx: Update mime.types file to the latest +- [COOK-2329] - nginx: Update naxsi rules to the current + +## v1.2.0 + +- [COOK-1752] - Add headers more module to the nginx cookbook +- [COOK-2209] - nginx source recipe should create web user before creating directories +- [COOK-2221] - make nginx::source compatible with gentoo +- [COOK-2267] - add version for runit recommends + +## v1.1.4 + +- [COOK-2168] - specify package name as an attribute + +## v1.1.2 + +- [COOK-1766] - Nginx Source Recipe Rebuilding Source at Every Run +- [COOK-1910] - Add IPv6 module +- [COOK-1966] - nginx cookbook should let you set `gzip_vary` and `gzip_buffers` in nginx.conf +- [COOK-1969]- - nginx::passenger module not included due to use of symbolized `:nginx_configure_flags` +- [COOK-1971] - Template passenger.conf.erb configures key `passenger_max_pool_size` 2 times +- [COOK-1972] - nginx::source compile_nginx_source reports success in spite of failed compilation +- [COOK-1975] - nginx::passenger requires rake gem +- [COOK-1979] - Passenger module requires curl-dev(el) +- [COOK-2080] - Restart nginx on source compilation + +## v1.1.0 + +- [COOK-1263] - Nginx log (and possibly other) directory creations should be recursive +- [COOK-1515] - move creation of `node['nginx']['dir']` out of commons.rb +- [COOK-1523] - nginx `http_geoip_module` requires libtoolize +- [COOK-1524] - nginx checksums are md5 +- [COOK-1641] - add "use", "`multi_accept`" and "`worker_rlimit_nofile`" to nginx cookbook +- [COOK-1683] - Nginx fails Windows nodes just by being required in metadata +- [COOK-1735] - Support Amazon Linux in nginx::source recipe +- [COOK-1753] - Add ability for nginx::passenger recipe to configure more Passenger global settings +- [COOK-1754] - Allow group to be set in nginx.conf file +- [COOK-1770] - nginx cookbook fails on servers that don't have a "cpu" attribute +- [COOK-1781] - Use 'sv' to reload nginx when using runit +- [COOK-1789] - stop depending on bluepill, runit and yum. they are not required by nginx cookbook +- [COOK-1791] - add name attribute to metadata +- [COOK-1837] - nginx::passenger doesn't work on debian family +- [COOK-1956] - update naxsi version due to incompatibility with newer nginx + +## v1.0.2 + +- [COOK-1636] - relax the version constraint on ohai + +## v1.0.0 + +- [COOK-913] - defaults for gzip cause warning on service restart +- [COOK-1020] - duplicate MIME type +- [COOK-1269] - add passenger module support through new recipe +- [COOK-1306] - increment nginx version to 1.2 (now 1.2.3) +- [COOK-1316] - default site should not always be enabled +- [COOK-1417] - resolve errors preventing build from source +- [COOK-1483] - source prefix attribute has no effect +- [COOK-1484] - source relies on /etc/sysconfig +- [COOK-1511] - add support for naxsi module +- [COOK-1525] - nginx source is downloaded every time +- [COOK-1526] - nginx_site does not remove sites +- [COOK-1527] - add `http_echo_module` recipe + +## v0.101.6 + +Erroneous cookbook upload due to timeout. + +Version #'s are cheap. + +## v0.101.4 + +- [COOK-1280] - Improve RHEL family support and fix ohai_plugins recipe bug +- [COOK-1194] - allow installation method via attribute +- [COOK-458] - fix duplicate nginx processes + +## v0.101.2 + +- [COOK-1211] - include the default attributes explicitly so version is available. + +## v0.101.0 + +**Attribute Change**: `node['nginx']['url']` -> `node['nginx']['source']['url']`; see the README.md. + +- [COOK-1115] - daemonize when using init script +- [COOK-477] - module compilation support in nginx::source + +## v0.100.4 + +- [COOK-1126] - source version bump to 1.0.14 + +## v0.100.2 + +- [COOK-1053] - Add :url attribute to nginx cookbook + +## v0.100.0 + +- [COOK-818] - add "application/json" per RFC. +- [COOK-870] - bluepill init style support +- [COOK-957] - Compress application/javascript. +- [COOK-981] - Add reload support to NGINX service + +## v0.99.2 + +- [COOK-809] - attribute to disable access logging +- [COOK-772] - update nginx download source location + + + +[#174]: https://github.com/miketheman/nginx/issues/174 +[#183]: https://github.com/miketheman/nginx/issues/183 +[#184]: https://github.com/miketheman/nginx/issues/184 +[#188]: https://github.com/miketheman/nginx/issues/188 +[#200]: https://github.com/miketheman/nginx/issues/200 +[#204]: https://github.com/miketheman/nginx/issues/204 +[#205]: https://github.com/miketheman/nginx/issues/205 +[#219]: https://github.com/miketheman/nginx/issues/219 +[#220]: https://github.com/miketheman/nginx/issues/220 +[#223]: https://github.com/miketheman/nginx/issues/223 +[#225]: https://github.com/miketheman/nginx/issues/225 +[#230]: https://github.com/miketheman/nginx/issues/230 +[#236]: https://github.com/miketheman/nginx/issues/236 +[#240]: https://github.com/miketheman/nginx/issues/240 +[#243]: https://github.com/miketheman/nginx/issues/243 +[#249]: https://github.com/miketheman/nginx/issues/249 +[#252]: https://github.com/miketheman/nginx/issues/252 +[#254]: https://github.com/miketheman/nginx/issues/254 +[#259]: https://github.com/miketheman/nginx/issues/259 +[#269]: https://github.com/miketheman/nginx/issues/269 +[#279]: https://github.com/miketheman/nginx/issues/279 +[#294]: https://github.com/miketheman/nginx/issues/294 +[#298]: https://github.com/miketheman/nginx/issues/298 +[#302]: https://github.com/miketheman/nginx/issues/302 +[#305]: https://github.com/miketheman/nginx/issues/305 +[#310]: https://github.com/miketheman/nginx/issues/310 +[#312]: https://github.com/miketheman/nginx/issues/312 +[#314]: https://github.com/miketheman/nginx/issues/314 +[#318]: https://github.com/miketheman/nginx/issues/318 +[#321]: https://github.com/miketheman/nginx/issues/321 +[#325]: https://github.com/miketheman/nginx/issues/325 +[#326]: https://github.com/miketheman/nginx/issues/326 +[#327]: https://github.com/miketheman/nginx/issues/327 +[#331]: https://github.com/miketheman/nginx/issues/331 +[#332]: https://github.com/miketheman/nginx/issues/332 +[#335]: https://github.com/miketheman/nginx/issues/335 +[#338]: https://github.com/miketheman/nginx/issues/338 +[@9minutesnooze]: https://github.com/9minutesnooze +[@adepue]: https://github.com/adepue +[@auth0]: https://github.com/auth0 +[@bchrobot]: https://github.com/bchrobot +[@bkw]: https://github.com/bkw +[@canofspam3bug324]: https://github.com/CanOfSpam3bug324 +[@dwradcliffe]: https://github.com/dwradcliffe +[@evertrue]: https://github.com/evertrue +[@ffuenf]: https://github.com/ffuenf +[@firmhouse]: https://github.com/firmhouse +[@gkra]: https://github.com/gkra +[@gregkare]: https://github.com/gregkare +[@irontoby]: https://github.com/irontoby +[@jalberto]: https://github.com/jalberto +[@jcoleman]: https://github.com/jcoleman +[@jenssegers]: https://github.com/jenssegers +[@josh-padnick]: https://github.com/josh-padnick +[@jujugrrr]: https://github.com/jujugrrr +[@karsten-bruckmann]: https://github.com/karsten-bruckmann +[@larkin]: https://github.com/larkin +[@miketheman]: https://github.com/miketheman +[@monsterstrike]: https://github.com/monsterstrike +[@morr]: https://github.com/morr +[@mytho]: https://github.com/Mytho +[@n1koo]: https://github.com/n1koo +[@nkadel-skyhook]: https://github.com/nkadel-skyhook +[@runningman84]: https://github.com/runningman84 +[@shtouff]: https://github.com/shtouff +[@stevenolen]: https://github.com/stevenolen +[@thomasmeeus]: https://github.com/thomasmeeus +[@thommay]: https://github.com/thommay +[@tvdinner]: https://github.com/tvdinner +[@usertesting]: https://github.com/usertesting +[@whatcould]: https://github.com/whatcould +[@yveslaroche]: https://github.com/yveslaroche diff --git a/cookbooks/nginx/CONTRIBUTING.md b/cookbooks/nginx/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/nginx/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/cookbooks/nginx/README.md b/cookbooks/nginx/README.md new file mode 100644 index 0000000..2191025 --- /dev/null +++ b/cookbooks/nginx/README.md @@ -0,0 +1,387 @@ +# nginx Cookbook + +[![Cookbook](http://img.shields.io/cookbook/v/nginx.svg)](https://supermarket.chef.io/cookbooks/nginx) [![Build Status](https://travis-ci.org/chef-cookbooks/nginx.svg?branch=master)](https://travis-ci.org/chef-cookbooks/nginx) + +Installs nginx from package OR source code and sets up configuration handling similar to Debian's Apache2 scripts. + +## Requirements + +### Cookbooks + +The following cookbooks are direct dependencies because they're used for common "default" functionality. + +- `build-essential` for source installations +- `ohai` for setting up the ohai plugin +- `yum-epel` for setting up the EPEL repository on RHEL platforms +- `zypper` for setting up the nginx.org repository on Suse platforms + +### Platforms + +The following platforms are supported and tested with Test Kitchen: + +- Ubuntu 14.04+ +- CentOS 6+ +- Debian 7+ +- openSUSE +- FreeBSD + +Other Debian and RHEL family distributions are assumed to work. + +### Chef + +- Chef 13.3+ + +## Attributes + +Node attributes for this cookbook are logically separated into different files. Some attributes are set only via a specific recipe. + +### nginx::auth_request + +These attributes are used in the `nginx::auth_request` recipe. + +- `node['nginx']['auth_request']['url']` - The url to the auth_request module tar.gz file +- `node['nginx']['auth_request']['checksum']` - The checksum of the auth_request module tar.gz file + +### nginx::default + +Generally used attributes. Some have platform specific values. See `attributes/default.rb`. "The Config" refers to "nginx.conf" the main config file. + +- `node['nginx']['dir']` - Location for nginx configuration. +- `node['nginx']['conf_template']` - The `source` template to use when creating the `nginx.conf`. +- `node['nginx']['conf_cookbook']` - The cookbook where `node['nginx']['conf_template']` resides. +- `node['nginx']['log_dir']` - Location for nginx logs. +- `node['nginx']['log_dir_perm']` - Permissions for nginx logs folder. +- `node['nginx']['user']` - User that nginx will run as. +- `node['nginx']['user_home']` - User home path, used during user creation. +- `node['nginx']['group']` - Group for nginx. +- `node['nginx']['port']` - Port for nginx to listen on. +- `node['nginx']['binary']` - Path to the nginx binary. +- `node['nginx']['init_style']` - How to run nginx as a service when using `nginx::source`. Values can be "upstart", "systemd", or "init". This attribute is not used in the `package` recipe because the package manager's init script style for the platform is assumed. +- `node['nginx']['cleanup_runit']` - Cleanup existing runit based nginx service installation. Uses the `nginx_cleanup_runit` resource. Default: true +- `node['nginx']['upstart']['foreground']` - Set this to true if you want upstart to run nginx in the foreground, set to false if you want upstart to detach and track the process via pid. +- `node['nginx']['upstart']['runlevels']` - String of runlevels in the format '2345' which determines which runlevels nginx will start at when entering and stop at when leaving. +- `node['nginx']['upstart']['respawn_limit']` - Respawn limit in upstart stanza format, count followed by space followed by interval in seconds. +- `node['nginx']['keepalive']` - Whether to use `keepalive_timeout`, any value besides "on" will leave that option out of the config. +- `node['nginx']['keepalive_requests']` - used for config value of `keepalive_requests`. +- `node['nginx']['keepalive_timeout']` - used for config value of `keepalive_timeout`. +- `node['nginx']['worker_processes']` - used for config value of `worker_processes`. +- `node['nginx']['worker_connections']` - used for config value of `events { worker_connections }` +- `node['nginx']['worker_rlimit_nofile']` - used for config value of `worker_rlimit_nofile`. Can replace any "ulimit -n" command. The value depend on your usage (cache or not) but must always be superior than worker_connections. +- `node['nginx']['worker_shutdown_timeout']` - used for config value of `worker_shutdown_timeout`. +- `node['nginx']['worker_connections']` - used for config value of `events { worker_connections }` +- `node['nginx']['multi_accept']` - used for config value of `events { multi_accept }`. Try to accept() as many connections as possible. Disable by default. +- `node['nginx']['event']` - used for config value of `events { use }`. Set the event-model. By default nginx looks for the most suitable method for your OS. +- `node['nginx']['accept_mutex_delay']` - used for config value of `accept_mutex_delay` +- `node['nginx']['server_tokens']` - used for config value of `server_tokens`. +- `node['nginx']['server_names_hash_bucket_size']` - used for config value of `server_names_hash_bucket_size`. +- `node['nginx']['disable_access_log']` - set to true to disable the general access log, may be useful on high traffic sites. +- `node['nginx']['access_log_options']` - Set to a string of additional options to be appended to the access log directive +- `node['nginx']['error_log_options']` - Set to a string of additional options to be appended to the error log directive +- `node['nginx']['default_site_enabled']` - enable the default site +- `node['nginx']['sendfile']` - Whether to use `sendfile`. Defaults to "on". +- `node['nginx']['tcp_nopush']` - Whether to use `tcp_nopush`. Defaults to "on". +- `node['nginx']['tcp_nodelay']` - Whether to use `tcp_nodelay`. Defaults to "on". +- `node['nginx']['install_method']` - Whether nginx is installed from packages or from source. +- `node['nginx']['types_hash_max_size']` - Used for the `types_hash_max_size` configuration directive. +- `node['nginx']['types_hash_bucket_size']` - Used for the `types_hash_bucket_size` configuration directive. +- `node['nginx']['proxy_read_timeout']` - defines a timeout (between two successive read operations) for reading a response from the proxied server. +- `node['nginx']['client_body_buffer_size']` - used for config value of `client_body_buffer_size`. +- `node['nginx']['client_max_body_size']` - specifies the maximum accepted body size of a client request, as indicated by the request header Content-Length. +- `node['nginx']['repo_source']` - when installed from a package this attribute affects which yum repositories, if any, will be added before installing the nginx package. The default value of 'epel' will use the `yum-epel` cookbook, 'nginx' will use the `nginx::repo` recipe, 'passenger' will use the 'nginx::repo_passenger' recipe, and setting no value will not add any additional repositories. +- `node['nginx']['sts_max_age']` - Enable Strict Transport Security for all apps (See: ). This attribute adds the following header: Strict-Transport-Security max-age=SECONDS to all incoming requests and takes an integer (in seconds) as its argument. +- `node['nginx']['default']['modules']` - Array specifying which modules to enable via the conf-enabled config include function. Currently the only valid value is "socketproxy". +- `node['nginx']['load_modules']` - Array of paths to modules to dynamically load on nginx startup using the `load_module` directive. Default is `[]`. + +#### authorized_ips module + +- `node['nginx']['remote_ip_var']` - The remote ip variable name to use. +- `node['nginx']['authorized_ips']` - IPs authorized by the module + +#### gzip module + +- `node['nginx']['gzip']` - Whether to use gzip, can be "on" or "off" +- `node['nginx']['gzip_http_version']` - used for config value of `gzip_http_version`. +- `node['nginx']['gzip_comp_level']` - used for config value of `gzip_comp_level`. +- `node['nginx']['gzip_proxied']` - used for config value of `gzip_proxied`. +- `node['nginx']['gzip_vary']` - used for config value of `gzip_vary`. +- `node['nginx']['gzip_buffers']` - used for config value of `gzip_buffers`. +- `node['nginx']['gzip_types']` - used for config value of `gzip_types` - must be an Array. +- `node['nginx']['gzip_min_length']` - used for config value of `gzip_min_length`. +- `node['nginx']['gzip_disable']` - used for config value of `gzip_disable`. +- `node['nginx']['gzip_static']` - used for config value of `gzip_static` (`http_gzip_static_module` must be enabled) + +#### Other configurations + +- `node['nginx']['extra_configs']` - a Hash of key/values to nginx configuration. + +### nginx::devel + +These attributes are used in the `nginx::ngx_devel_module` recipe. + +- `node['nginx']['devel']['version']` - The version of the nginx devel module +- `node['nginx']['devel']['url']` - The URL of the nginx devel module tar.gz file +- `node['nginx']['devel']['checksum']` - The checksum of the nginx devel module tar.gz file + +### nginx::echo + +These attributes are used in the `nginx::http_echo_module` recipe. + +- `node['nginx']['echo']['version']` - The version of `http_echo` you want (default: 0.59) +- `node['nginx']['echo']['url']` - URL for the tarball. +- `node['nginx']['echo']['checksum']` - Checksum of the tarball. + +### nginx::geoip + +These attributes are used in the `nginx::http_geoip_module` recipe. Please note that the `country_dat_checksum` and `city_dat_checksum` are based on downloads from a datacenter in Fremont, CA, USA. You really should override these with checksums for the geo tarballs from your node location. + +**Note** The upstream, maxmind.com, may block access for repeated downloads of the data files. It is recommended that you download and host the data files, and change the URLs in the attributes. + +- `node['nginx']['geoip']['path']` - Location where to install the geoip libraries. +- `node['nginx']['geoip']['enable_city']` - Whether to enable City data +- `node['nginx']['geoip']['country_dat_url']` - Country data tarball URL +- `node['nginx']['geoip']['country_dat_checksum']` - Country data tarball checksum +- `node['nginx']['geoip']['city_dat_url']` - City data tarball URL +- `node['nginx']['geoip']['city_dat_checksum']` - City data tarball checksum +- `node['nginx']['geoip']['lib_version']` - Version of the GeoIP library to install +- `node['nginx']['geoip']['lib_url']` - (Versioned) Tarball URL of the GeoIP library +- `node['nginx']['geoip']['lib_checksum']` - Checksum of the GeoIP library tarball + +### nginx::http_realip_module + +From: + +- `node['nginx']['realip']['header']` - Header to use for the RealIp Module; only accepts "X-Forwarded-For" or "X-Real-IP" +- `node['nginx']['realip']['addresses']` - Addresses to use for the `http_realip` configuration. +- `node['nginx']['realip']['real_ip_recursive']` - If recursive search is enabled, the original client address that matches one of the trusted addresses is replaced by the last non-trusted address sent in the request header field. Can be on "on" or "off" (default). + +### nginx::ohai_plugin + +The `ohai_plugin` recipe includes an Ohai plugin. It will be automatically installed and activated, providing the following attributes via ohai, no matter how nginx is installed (source or package): + +- `node['nginx']['version']` - version of nginx +- `node['nginx']['configure_arguments']` - options passed to `./configure` when nginx was built +- `node['nginx']['prefix']` - installation prefix +- `node['nginx']['conf_path']` - configuration file path +- `node['nginx']['ohai_plugin_enabled']` - Toggles ohai_plugin recipe. Defaults to true. + +In the source recipe, it is used to determine whether control attributes for building nginx have changed. + +### nginx::openssl_source + +These attributes are used in the `nginx::openssl_source` recipe. + +- `node['nginx']['openssl_source']['version']` - The version of OpenSSL you want to download and use (default: 1.0.1t) +- `node['nginx']['openssl_source']['url']` - The url for the OpenSSL source + +### nginx::passenger + +These attributes are used in the `nginx::passenger` recipe. + +- `node['nginx']['passenger']['version']` - passenger gem version +- `node['nginx']['passenger']['root']` - passenger gem root path +- `node['nginx']['passenger']['install_rake']` - set to false if rake already present on system +- `node['nginx']['passenger']['max_pool_size']` - maximum passenger pool size (default=10) +- `node['nginx']['passenger']['ruby']` - Ruby path for Passenger to use (default=`$(which ruby)`) +- `node['nginx']['passenger']['spawn_method']` - passenger spawn method to use (default=`smart-lv2`) +- `node['nginx']['passenger']['buffer_response']` - turns on or off response buffering (default=`on`) +- `node['nginx']['passenger']['max_pool_size']` - passenger maximum pool size (default=`6`) +- `node['nginx']['passenger']['min_instances']` - minimum instances (default=`1`) +- `node['nginx']['passenger']['max_instances_per_app']` - maximum instances per app (default=`0`) +- `node['nginx']['passenger']['pool_idle_time']` - passenger pool idle time (default=`300`) +- `node['nginx']['passenger']['max_requests']` - maximum requests (default=`0`) +- `node['nginx']['passenger']['nodejs']` - Nodejs path for Passenger to use (default=nil) +- `node['nginx']['passenger']['show_version_in_header']` - Show passenger version in HTTP headers (default=`on`) + +Basic configuration to use the official Phusion Passenger repositories: + +- `node['nginx']['repo_source']` - 'passenger' +- `node['nginx']['package_name']` - 'nginx-extras' +- `node['nginx']['passenger']['install_method']` - 'package' + +### nginx::rate_limiting + +- `node['nginx']['enable_rate_limiting']` - set to true to enable rate limiting (`limit_req_zone` in nginx.conf) +- `node['nginx']['rate_limiting_zone_name']` - sets the zone in `limit_req_zone`. +- `node['nginx']['rate_limiting_backoff']` - **Incorrect name, retained for compatibility reasons** - sets the size of the shared memory zone (default=`10m`, 10 megabytes) +- `node['nginx']['rate_limit']` - set the rate limit amount for `limit_req_zone`. + +### nginx::repo + +- `node['nginx']['upstream_repository']` - the URL to use for the package repository resource; default is set based on platform type +- `node['nginx']['repo_signing_key']` - The URL from which package signing/gpg key is retrieved + +### nginx::socketproxy + +These attributes are used in the `nginx::socketproxy` recipe. + +- `node['nginx']['socketproxy']['root']` - The directory (on your server) where socketproxy apps are deployed. +- `node['nginx']['socketproxy']['default_app']` - Static assets directory for requests to "/" that don't meet any proxy_pass filter requirements. +- `node['nginx']['socketproxy']['apps']['app_name']['prepend_slash']` - Prepend a slash to requests to app "app_name" before sending them to the socketproxy socket. +- `node['nginx']['socketproxy']['apps']['app_name']['context_name']` - URI (e.g. "app_name" in order to achieve "") at which to host the application "app_name" +- `node['nginx']['socketproxy']['apps']['app_name']['subdir']` - Directory (under `node['nginx']['socketproxy']['root']`) in which to find the application. + +### nginx::source + +These attributes are used in the `nginx::source` recipe. Some of them are dynamically modified during the run. See `attributes/source.rb` for default values. + +- `node['nginx']['source']['url']` - (versioned) URL for the nginx source code. By default this will use the version specified as `node['nginx']['version']`. +- `node['nginx']['source']['prefix']` - (versioned) prefix for installing nginx from source +- `node['nginx']['source']['conf_path']` - location of the main config file, in `node['nginx']['dir']` by default. +- `node['nginx']['source']['modules']` - Array of modules that should be compiled into nginx by including their recipes in `nginx::source`. +- `node['nginx']['source']['default_configure_flags']` - The default flags passed to the configure script when building nginx. +- `node['nginx']['configure_flags']` - Preserved for compatibility and dynamically generated from the `node['nginx']['source']['default_configure_flags']` in the `nginx::source` recipe. +- `node['nginx']['source']['use_existing_user']` - set to `true` if you do not want `nginx::source` recipe to create system user with name `node['nginx']['user']` and `node['nginx']['user_home']`. + +### nginx::status + +These attributes are used in the `nginx::http_stub_status_module` recipe. + +- `node['nginx']['status']['port']` - The port on which nginx will serve the status info (default: 8090) + +### nginx::syslog + +These attributes are used in the `nginx::syslog_module` recipe. + +- `node['nginx']['syslog']['git_repo']` - The git repository url to use for the syslog patches. +- `node['nginx']['syslog']['git_revision']` - The revision on the git repository to checkout. + +### nginx::upload_progress + +These attributes are used in the `nginx::upload_progress_module` recipe. + +- `node['nginx']['upload_progress']['url']` - URL for the tarball. +- `node['nginx']['upload_progress']['checksum']` - Checksum of the tarball. +- `node['nginx']['upload_progress']['javascript_output']` - Output in javascript. Default is `true` for backwards compatibility. +- `node['nginx']['upload_progress']['zone_name']` - Zone name which will be used to store the per-connection tracking information. Default is `proxied`. +- `node['nginx']['upload_progress']['zone_size']` - Zone size in bytes. Default is `1m` (1 megabyte). + +## Resources + +### nginx_site + +Enable or disable a Server Block in `#{node['nginx']['dir']}/sites-available` by calling nxensite or nxdissite (introduced by this cookbook) to manage the symbolic link in `#{node['nginx']['dir']}/sites-enabled`. + +### Actions + +- `enable` - Enable the nginx site (default) +- `disable` - Disable the nginx site + +### Properties: + +- `site_name` - (optional) Name of the site to enable. By default it's assumed that the name of the nginx_site resource is the site name, but this allows overriding that. +- `template` - (optional) Path to the source for the `template` resource. +- `variables` - (optional) Variables to be used with the `template` resource + +### nginx_stream + +Enable or disable a Stream Block in `#{node['nginx']['dir']}/streams-available` by calling nxenstream or nxdisstream (introduced by this cookbook) to manage the symbolic link in `#{node['nginx']['dir']}/streams-enabled`. + +### Actions + +- `enable` - Enable the nginx stream (default) +- `disable` - Disable the nginx stream + +### Properties: + +- `stream_name` - (optional) Name of the stream to enable. +- `template` - (optional) Path to the source for the `template` resource. +- `variables` - (optional) Variables to be used with the `template` resource + +### nginx_cleanup_runit + +A simple resource to remove existing runit based nginx service installations. This is used in the default nginx recipe to stop runit based nginx services and cleanup runit service configs before setting up nginx under the system's own init system. + +### Actions + +- `cleanup` - Stop runit based nginx and remove runit configs (default) + +## Usage + +This cookbook provides three distinct installation methods, all of which are controlled via attributes and executed using the nginx::default recipe. + +### Package installation using the nginx.org repositories + +Nginx provides repositories for RHEL, Debian/Ubuntu, and Suse platforms with up to date packages available on older distributions. Due to the age of many nginx packages shipping with distros we believe this is the ideal installation method. With no attributes set the nginx.org repositories will be added to your system and nginx will be installed via package. This provides a solid out of the box install for most users. + +### Package installation using distro repositories + +If you prefer to use the packages included in your distro or to roll your own packages you'll want to set `node['nginx']['repo_source']` to `nil` or `distro` to skip the repository setup. The default recipe will still install nginx from packages, but you'll retain control over the package location. + +### Source installation to compile non-dynamic modules + +If you need control over how nginx is built, or you need non-dynamic modules to be included you'll need to compile nginx from source. We highly recommend against using this method as it requires the installation of a full compilation toolchain and development dependencies on your nodes. Creating your own packages with nginx compiled as necessary is a preferred option. If that's not possible you can set `node['nginx']['install_method']` to `source` and provide a version in `node['nginx']['version']`. + +#### Specifying Modules to compile + +The following recipes are used to build module support into nginx. To compile a module, add its recipe name to the array attribute `node['nginx']['source']['modules']`. + +- `ipv6.rb` - enables IPv6 support +- `headers_more_module` - +- `http_auth_request_module`` +- `http_echo_module.rb` - downloads the `http_echo_module` module and enables it as a module when compiling nginx. +- `http_geoip_module.rb` - installs the GeoIP libraries and data files and enables the module for compilation. +- `http_gzip_static_module.rb` - enables the module for compilation. Be sure to set `node['nginx']['gzip_static'] = 'yes'`. +- `http_mp4_module` - +- `http_perl_module.rb` - enables embedded Perl for compilation. +- `http_realip_module.rb` - enables the module for compilation and creates the configuration. +- `http_spdy_module` - +- `http_ssl_module.rb` - enables SSL for compilation. +- `http_stub_status_module.rb` - provides `nginx_status` configuration and enables the module for compilation. +- `http_v2_module` +- `ipv6` - +- `naxsi_module` - enables the naxsi module for the web application firewall for nginx. +- `ngx_devel_module` - +- `ngx_lua_module` - +- `openssl_source.rb` - downloads and uses custom OpenSSL source when compiling nginx +- `pagespeed_module`- +- `passenger` - builds the passenger gem and configuration for "`mod_passenger`". +- `set_misc` - +- `syslog_module` - enables syslog support for nginx. This only works with source builds. See - +- `upload_progress_module.rb` - builds the `upload_progress` module and enables it as a module when compiling nginx. + +## Resources + +### nginx_site + +Enable or disable a Server Block in `#{node['nginx']['dir']}/sites-available` by calling nxensite or nxdissite (introduced by this cookbook) to manage the symbolic link in `#{node['nginx']['dir']}/sites-enabled`. + +### Actions + +- `enable` - Enable the nginx site (default) +- `disable` - Disable the nginx site + +### Properties: + +- `name` - (optional) Name of the site to enable. By default it's assumed that the name of the nginx_site resource is the site name, but this allows overriding that. +- `template` - (optional) Path to the source for the `template` resource. +- `cookbook` - (optional) The cookbook that contains the template source. +- `variables` - (optional) Variables to be used with the `template` resource + +## Adding New Modules + +Previously we'd add each possible module to this cookbook itself. That's not necessary using wrapper cookbooks and we'd prefer to not add any addition module recipes at this time. Instead in your nginx wrapper cookbook setup any necessary packages and then include the follow code to add the module to the list of modules to compile: + +```ruby +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ['--with-SOMETHING', "--with-SOME_OPT='things'"] +``` + +## Maintainers + +This cookbook is maintained by Chef's Community Cookbook Engineering team. Our goal is to improve cookbook quality and to aid the community in contributing to cookbooks. To learn more about our team, process, and design goals see our [team documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/COOKBOOK_TEAM.MD). To learn more about contributing to cookbooks like this see our [contributing documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD), or if you have general questions about this cookbook come chat with us in #cookbok-engineering on the [Chef Community Slack](http://community-slack.chef.io/) + +## License + +``` +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + 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/cookbooks/nginx/attributes/auth_request.rb b/cookbooks/nginx/attributes/auth_request.rb new file mode 100644 index 0000000..8538a66 --- /dev/null +++ b/cookbooks/nginx/attributes/auth_request.rb @@ -0,0 +1,23 @@ +# +# Cookbook:: nginx +# Attributes:: auth_request +# +# Author:: David Radcliffe () +# +# Copyright:: 2013-2017, David Radcliffe +# +# 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. +# + +default['nginx']['auth_request']['url'] = 'http://mdounin.ru/hg/ngx_http_auth_request_module/archive/662785733552.tar.gz' +default['nginx']['auth_request']['checksum'] = '2057bdefd2137a5000d9dbdbfca049d1ba7832ad2b9f8855a88ea5dfa70bd8c1' diff --git a/cookbooks/nginx/attributes/default.rb b/cookbooks/nginx/attributes/default.rb new file mode 100644 index 0000000..d3e4cac --- /dev/null +++ b/cookbooks/nginx/attributes/default.rb @@ -0,0 +1,134 @@ +# +# Cookbook:: nginx +# Attributes:: default +# +# Author:: Adam Jacob () +# Author:: Joshua Timberman () +# +# Copyright:: 2009-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# In order to update the version, the checksum attribute must be changed too. +# This attribute is defined in the source.rb attribute file +default['nginx']['version'] = '1.12.1' +default['nginx']['package_name'] = 'nginx' +default['nginx']['port'] = '80' +default['nginx']['dir'] = '/etc/nginx' +default['nginx']['script_dir'] = '/usr/sbin' +default['nginx']['log_dir'] = '/var/log/nginx' +default['nginx']['log_dir_perm'] = '0750' +default['nginx']['binary'] = '/usr/sbin/nginx' +default['nginx']['default_root'] = '/var/www/nginx-default' +default['nginx']['ulimit'] = '1024' + +# cleanup runit install of previous cookbooks +default['nginx']['cleanup_runit'] = true + +# use the upstream nginx repo vs. distro packages +# this enables the use of modern nginx releases +# set this to nil to use the distro packages +# this is ignored if install_method is set to source +default['nginx']['repo_source'] = 'nginx' +default['nginx']['install_method'] = 'package' + +case node['platform_family'] +when 'rhel', 'fedora', 'amazon' + default['nginx']['user'] = 'nginx' +when 'freebsd' + default['nginx']['package_name'] = 'www/nginx' + default['nginx']['user'] = 'www' + default['nginx']['dir'] = '/usr/local/etc/nginx' + default['nginx']['script_dir'] = '/usr/local/sbin' + default['nginx']['binary'] = '/usr/local/sbin/nginx' + default['nginx']['default_root'] = '/usr/local/www/nginx-dist' +when 'suse' + default['nginx']['user'] = 'wwwrun' + default['nginx']['group'] = 'www' +else # debian probably + default['nginx']['user'] = 'www-data' +end + +default['nginx']['user_home'] = '/var/www' + +default['nginx']['upstart']['runlevels'] = '2345' +default['nginx']['upstart']['respawn_limit'] = nil +default['nginx']['upstart']['foreground'] = true + +default['nginx']['group'] = node['nginx']['group'] || node['nginx']['user'] + +default['nginx']['gzip'] = 'on' +default['nginx']['gzip_static'] = 'off' +default['nginx']['gzip_http_version'] = '1.0' +default['nginx']['gzip_comp_level'] = '2' +default['nginx']['gzip_proxied'] = 'any' +default['nginx']['gzip_vary'] = 'off' +default['nginx']['gzip_buffers'] = nil +default['nginx']['gzip_types'] = %w( + text/plain + text/css + application/x-javascript + text/xml + application/xml + application/rss+xml + application/atom+xml + image/svg+xml + text/javascript + application/javascript + application/json + text/mathml +) +default['nginx']['gzip_min_length'] = 1_000 +default['nginx']['gzip_disable'] = 'MSIE [1-6]\.' + +default['nginx']['keepalive'] = 'on' +default['nginx']['keepalive_requests'] = 100 +default['nginx']['keepalive_timeout'] = 65 +default['nginx']['worker_processes'] = node['cpu'] && node['cpu']['total'] ? node['cpu']['total'] : 1 +default['nginx']['worker_connections'] = 1_024 +default['nginx']['worker_rlimit_nofile'] = nil +default['nginx']['multi_accept'] = false +default['nginx']['event'] = nil +default['nginx']['accept_mutex_delay'] = nil +default['nginx']['server_tokens'] = nil +default['nginx']['server_names_hash_bucket_size'] = 64 +default['nginx']['variables_hash_max_size'] = 1024 +default['nginx']['variables_hash_bucket_size'] = 64 +default['nginx']['sendfile'] = 'on' +default['nginx']['underscores_in_headers'] = nil +default['nginx']['tcp_nodelay'] = 'on' +default['nginx']['tcp_nopush'] = 'on' + +default['nginx']['access_log_options'] = nil +default['nginx']['error_log_options'] = nil +default['nginx']['disable_access_log'] = false +default['nginx']['log_formats'] = {} +default['nginx']['default_site_enabled'] = true +default['nginx']['types_hash_max_size'] = 2_048 +default['nginx']['types_hash_bucket_size'] = 64 + +default['nginx']['proxy_read_timeout'] = nil +default['nginx']['client_body_buffer_size'] = nil +default['nginx']['client_max_body_size'] = nil +default['nginx']['large_client_header_buffers'] = nil +default['nginx']['map_hash_max_size'] = nil +default['nginx']['proxy_buffer_size'] = nil +default['nginx']['proxy_buffers'] = nil +default['nginx']['proxy_busy_buffers_size'] = nil +default['nginx']['default']['modules'] = [] + +default['nginx']['extra_configs'] = {} +default['nginx']['ohai_plugin_enabled'] = true + +default['nginx']['load_modules'] = [] diff --git a/cookbooks/nginx/attributes/devel.rb b/cookbooks/nginx/attributes/devel.rb new file mode 100644 index 0000000..3c1aa39 --- /dev/null +++ b/cookbooks/nginx/attributes/devel.rb @@ -0,0 +1,24 @@ +# +# Cookbook:: nginx +# Attributes:: devel +# +# Author:: Arthur Freyman () +# +# Copyright:: 2013-2017, Riot Games +# +# 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. +# + +default['nginx']['devel']['version'] = '0.3.0' +default['nginx']['devel']['url'] = "https://github.com/simpl/ngx_devel_kit/archive/v#{node['nginx']['devel']['version']}.tar.gz" +default['nginx']['devel']['checksum'] = '88e05a99a8a7419066f5ae75966fb1efc409bad4522d14986da074554ae61619' diff --git a/cookbooks/nginx/attributes/echo.rb b/cookbooks/nginx/attributes/echo.rb new file mode 100644 index 0000000..75a3524 --- /dev/null +++ b/cookbooks/nginx/attributes/echo.rb @@ -0,0 +1,24 @@ +# +# Cookbook:: nginx +# Attributes:: echo +# +# Author:: Danial Pearce () +# +# Copyright:: 2013-2017, Danial Pearce +# +# 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. +# + +default['nginx']['echo']['version'] = '0.61' +default['nginx']['echo']['url'] = "https://github.com/openresty/echo-nginx-module/archive/v#{node['nginx']['echo']['version']}.tar.gz" +default['nginx']['echo']['checksum'] = '2e6a03032555f5da1bdff2ae96c96486f447da3da37c117e0f964ae0753d22aa' diff --git a/cookbooks/nginx/attributes/geoip.rb b/cookbooks/nginx/attributes/geoip.rb new file mode 100644 index 0000000..2d1f6b1 --- /dev/null +++ b/cookbooks/nginx/attributes/geoip.rb @@ -0,0 +1,35 @@ +# +# Cookbook:: nginx +# Attributes:: geoip +# +# Author:: Jamie Winsor () +# +# Copyright:: 2012-2017, Riot Games +# +# 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. +# + +# NOTE: The GeoIP database checksums are nil by default as these files change +# continuously and are not versioned. +# If you self host these files you should create a checksum and set these attributes + +default['nginx']['geoip']['path'] = '/srv/geoip' +default['nginx']['geoip']['enable_city'] = true +default['nginx']['geoip']['country_dat_url'] = 'http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz' +default['nginx']['geoip']['country_dat_checksum'] = nil +default['nginx']['geoip']['city_dat_url'] = 'http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz' +default['nginx']['geoip']['city_dat_checksum'] = nil +default['nginx']['geoip']['lib_version'] = '1.6.9' +lib_version = node['nginx']['geoip']['lib_version'] # convenience variable for line length +default['nginx']['geoip']['lib_url'] = "https://github.com/maxmind/geoip-api-c/releases/download/v#{lib_version}/GeoIP-#{lib_version}.tar.gz" +default['nginx']['geoip']['lib_checksum'] = '4b446491843de67c1af9b887da17a3e5939e0aeed4826923a5f4bf09d845096f' diff --git a/cookbooks/nginx/attributes/headers_more.rb b/cookbooks/nginx/attributes/headers_more.rb new file mode 100644 index 0000000..1150a4b --- /dev/null +++ b/cookbooks/nginx/attributes/headers_more.rb @@ -0,0 +1,24 @@ +# +# Cookbook:: nginx +# Attributes:: headers_more +# +# Author:: Lucas Jandrew () +# +# Copyright:: 2012-2017, Riot Games +# +# 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. +# + +default['nginx']['headers_more']['version'] = '0.30' +default['nginx']['headers_more']['source_url'] = "https://github.com/openresty/headers-more-nginx-module/archive/v#{node['nginx']['headers_more']['version']}.tar.gz" +default['nginx']['headers_more']['source_checksum'] = '2aad309a9313c21c7c06ee4e71a39c99d4d829e31c8b3e7d76f8c964ea8047f5' diff --git a/cookbooks/nginx/attributes/lua.rb b/cookbooks/nginx/attributes/lua.rb new file mode 100644 index 0000000..c896d6d --- /dev/null +++ b/cookbooks/nginx/attributes/lua.rb @@ -0,0 +1,28 @@ +# +# Cookbook:: nginx +# Attributes:: lua +# +# Author:: Arthur Freyman () +# +# Copyright:: 2013-2017, Riot Games +# +# 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. +# + +default['nginx']['lua']['version'] = '0.10.10' +default['nginx']['lua']['url'] = "https://github.com/chaoslawful/lua-nginx-module/archive/v#{node['nginx']['lua']['version']}.tar.gz" +default['nginx']['lua']['checksum'] = 'b4acb84e2d631035a516d61830c910ef6e6485aba86096221ec745e0dbb3fbc9' + +default['nginx']['luajit']['version'] = '2.0.4' +default['nginx']['luajit']['url'] = "http://luajit.org/download/LuaJIT-#{node['nginx']['luajit']['version']}.tar.gz" +default['nginx']['luajit']['checksum'] = '620fa4eb12375021bef6e4f237cbd2dd5d49e56beb414bee052c746beef1807d' diff --git a/cookbooks/nginx/attributes/naxsi.rb b/cookbooks/nginx/attributes/naxsi.rb new file mode 100644 index 0000000..3615c2e --- /dev/null +++ b/cookbooks/nginx/attributes/naxsi.rb @@ -0,0 +1,24 @@ +# +# Cookbook:: nginx +# Attributes:: naxsi +# +# Author:: Artiom Lunev () +# +# Copyright:: 2012-2017, Artiom Lunev +# +# 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. +# + +default['nginx']['naxsi']['version'] = '0.54' +default['nginx']['naxsi']['url'] = "https://github.com/nbs-system/naxsi/archive/#{node['nginx']['naxsi']['version']}.tar.gz" +default['nginx']['naxsi']['checksum'] = '9cc2c09405bc71f78ef26a8b6d70afcea3fccbe8125df70cb0cfc480133daba5' diff --git a/cookbooks/nginx/attributes/openssl_source.rb b/cookbooks/nginx/attributes/openssl_source.rb new file mode 100644 index 0000000..2da8791 --- /dev/null +++ b/cookbooks/nginx/attributes/openssl_source.rb @@ -0,0 +1,23 @@ +# +# Cookbook:: nginx +# Attributes:: openssl_source +# +# Author:: David Radcliffe () +# +# Copyright:: 2013-2017, David Radcliffe +# +# 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. +# + +default['nginx']['openssl_source']['version'] = '1.0.2k' +default['nginx']['openssl_source']['url'] = "http://www.openssl.org/source/openssl-#{node['nginx']['openssl_source']['version']}.tar.gz" diff --git a/cookbooks/nginx/attributes/pagespeed.rb b/cookbooks/nginx/attributes/pagespeed.rb new file mode 100644 index 0000000..319d416 --- /dev/null +++ b/cookbooks/nginx/attributes/pagespeed.rb @@ -0,0 +1,9 @@ +# +# Cookbook:: nginx +# Recipe:: pagespeed_module +# +default['nginx']['pagespeed']['version'] = '1.11.33.2' +default['nginx']['pagespeed']['url'] = "https://github.com/pagespeed/ngx_pagespeed/archive/release-#{node['nginx']['pagespeed']['version']}-beta.tar.gz" +default['nginx']['psol']['url'] = "https://dl.google.com/dl/page-speed/psol/#{node['nginx']['pagespeed']['version']}.tar.gz" +default['nginx']['pagespeed']['packages']['rhel'] = %w(pcre-devel zlib-devel) +default['nginx']['pagespeed']['packages']['debian'] = %w(zlib1g-dev libpcre3 libpcre3-dev) diff --git a/cookbooks/nginx/attributes/passenger.rb b/cookbooks/nginx/attributes/passenger.rb new file mode 100644 index 0000000..4c34b6b --- /dev/null +++ b/cookbooks/nginx/attributes/passenger.rb @@ -0,0 +1,74 @@ +# +# Cookbook:: nginx +# Attribute:: passenger +# +# Author:: Alex Dergachev () +# +# Copyright:: 2013-2017, Chef Software, Inc. +# Copyright:: 2012-2017, Susan Potter +# +# 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. +# +ubuntu_18 = platform?('ubuntu') && node['platform_version'].to_i >= 18 + +# this is only used for source installs +# for package installs you will receive the latest version in the repository +node.default['nginx']['passenger']['version'] = '4.0.57' + +if node['nginx']['repo_source'] == 'passenger' + node.default['nginx']['passenger']['root'] = '/usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini' + node.default['nginx']['passenger']['ruby'] = '/usr/bin/ruby' +elsif node['languages'].attribute?('ruby') + node.default['nginx']['passenger']['root'] = "#{node['languages']['ruby']['gems_dir']}/gems/passenger-#{node['nginx']['passenger']['version']}" + node.default['nginx']['passenger']['ruby'] = node['languages']['ruby']['ruby_bin'] +else + Chef::Log.warn("node['languages']['ruby'] attribute not detected in #{cookbook_name}::#{recipe_name}") + Chef::Log.warn("Install a Ruby for automatic detection of node['nginx']['passenger'] attributes (root, ruby)") + Chef::Log.warn('Using default values that may or may not work for this system.') + node.default['nginx']['passenger']['root'] = "/usr/lib/ruby/gems/1.8/gems/passenger-#{node['nginx']['passenger']['version']}" + node.default['nginx']['passenger']['ruby'] = '/usr/bin/ruby' +end + +node.default['nginx']['passenger']['conf_file'] = if ubuntu_18 + "#{node['nginx']['dir']}/conf.d/mod-http-passenger.conf" + else + "#{node['nginx']['dir']}/conf.d/passenger.conf" + end + +node.default['nginx']['passenger']['packages']['rhel'] = if platform_family?('rhel') && node['platform_version'].to_i >= 6 + %w(ruby-devel libcurl-devel) + else + %w(ruby-devel curl-devel) + end +node.default['nginx']['passenger']['packages']['fedora'] = %w(ruby-devel libcurl-devel) +node.default['nginx']['passenger']['packages']['debian'] = if ubuntu_18 + %w(ruby-dev libcurl4-gnutls-dev libnginx-mod-http-passenger) + else + %w(ruby-dev libcurl4-gnutls-dev) + end + +node.default['nginx']['passenger']['install_rake'] = true +node.default['nginx']['passenger']['spawn_method'] = 'smart-lv2' +node.default['nginx']['passenger']['buffer_response'] = 'on' +node.default['nginx']['passenger']['max_pool_size'] = 6 +node.default['nginx']['passenger']['min_instances'] = 1 +node.default['nginx']['passenger']['max_instances_per_app'] = 0 +node.default['nginx']['passenger']['pool_idle_time'] = 300 +node.default['nginx']['passenger']['max_requests'] = 0 +node.default['nginx']['passenger']['gem_binary'] = nil +node.default['nginx']['passenger']['show_version_in_header'] = 'on' +# By default, the Passenger log file is the global Nginx error log file. Set this attribute to write passenger log to another location. +node.default['nginx']['passenger']['passenger_log_file'] = nil + +# NodeJs disable by default +node.default['nginx']['passenger']['nodejs'] = nil diff --git a/cookbooks/nginx/attributes/rate_limiting.rb b/cookbooks/nginx/attributes/rate_limiting.rb new file mode 100644 index 0000000..c29e8ba --- /dev/null +++ b/cookbooks/nginx/attributes/rate_limiting.rb @@ -0,0 +1,23 @@ +# +# Cookbook:: nginx +# Attribute:: rate_limiting +# +# Copyright:: 2013-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +default['nginx']['enable_rate_limiting'] = false +default['nginx']['rate_limiting_zone_name'] = 'default' +default['nginx']['rate_limiting_backoff'] = '10m' +default['nginx']['rate_limit'] = '1r/s' diff --git a/cookbooks/nginx/attributes/repo.rb b/cookbooks/nginx/attributes/repo.rb new file mode 100644 index 0000000..3f630cc --- /dev/null +++ b/cookbooks/nginx/attributes/repo.rb @@ -0,0 +1,40 @@ +# +# Cookbook:: nginx +# Recipe:: repo +# +# Author:: Nick Rycar +# +# Copyright:: 2008-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +default['nginx']['upstream_repository'] = + case node['platform_family'] + when 'rhel', 'fedora', 'amazon' + case node['platform'] + when 'centos' + # See http://wiki.nginx.org/Install + "https://nginx.org/packages/centos/#{node['platform_version'].to_i}/$basearch/" + when 'amazon' # Chef < 13 on Amazon + 'https://nginx.org/packages/rhel/6/$basearch/' + else + "https://nginx.org/packages/rhel/#{node['platform_version'].to_i}/$basearch/" + end + when 'debian' + "https://nginx.org/packages/#{node['platform']}" + when 'suse' + 'https://nginx.org/packages/sles/12' + end + +default['nginx']['repo_signing_key'] = 'https://nginx.org/keys/nginx_signing.key' diff --git a/cookbooks/nginx/attributes/set_misc.rb b/cookbooks/nginx/attributes/set_misc.rb new file mode 100644 index 0000000..2bf905c --- /dev/null +++ b/cookbooks/nginx/attributes/set_misc.rb @@ -0,0 +1,8 @@ +# +# Cookbook:: nginx +# Attributes:: set_misc +# + +default['nginx']['set_misc']['version'] = '0.30' +default['nginx']['set_misc']['url'] = "https://github.com/agentzh/set-misc-nginx-module/archive/v#{node['nginx']['set_misc']['version']}.tar.gz" +default['nginx']['set_misc']['checksum'] = '59920dd3f92c2be32627121605751b52eae32b5884be09f2e4c53fb2fae8aabc' diff --git a/cookbooks/nginx/attributes/socketproxy.rb b/cookbooks/nginx/attributes/socketproxy.rb new file mode 100644 index 0000000..d4a2e3c --- /dev/null +++ b/cookbooks/nginx/attributes/socketproxy.rb @@ -0,0 +1,18 @@ +# +# Cookbook:: nginx +# Attributes:: socketproxy.rb +# + +default['nginx']['socketproxy']['root'] = '/usr/share/nginx/apps' +default['nginx']['socketproxy']['app_owner'] = 'root' +default['nginx']['socketproxy']['logname'] = 'socketproxy' +default['nginx']['socketproxy']['log_level'] = 'error' +# default['nginx']['socketproxy']['default_app'] = 'default' +# default['nginx']['socketproxy']['apps'] = { +# 'default' => { +# 'prepend_slash' => false, +# 'context_name' => '', +# 'subdir' => 'current', +# 'socket_path' => 'shared/sockets/unicorn.sock' +# } +# } diff --git a/cookbooks/nginx/attributes/source.rb b/cookbooks/nginx/attributes/source.rb new file mode 100644 index 0000000..5c81dc1 --- /dev/null +++ b/cookbooks/nginx/attributes/source.rb @@ -0,0 +1,52 @@ +# +# Cookbook:: nginx +# Attributes:: source +# +# Author:: Jamie Winsor () +# +# Copyright:: 2012-2017, Riot Games +# +# 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. +# + +include_attribute 'nginx::default' + +default['nginx']['init_style'] = if node['platform'] == 'ubuntu' && node['platform_version'].to_f <= 14.04 + # init_package identifies 12.04/14.04 as init, but we should be using upstart here + 'upstart' + else + node['init_package'] + end + +default['nginx']['source']['version'] = node['nginx']['version'] +default['nginx']['source']['prefix'] = "/opt/nginx-#{node['nginx']['source']['version']}" +default['nginx']['source']['conf_path'] = "#{node['nginx']['dir']}/nginx.conf" +default['nginx']['source']['sbin_path'] = "#{node['nginx']['source']['prefix']}/sbin/nginx" + +# Wno-error can be removed when nginx compiles on GCC7: https://trac.nginx.org/nginx/ticket/1259 +default['nginx']['source']['default_configure_flags'] = %W( + --prefix=#{node['nginx']['source']['prefix']} + --conf-path=#{node['nginx']['dir']}/nginx.conf + --sbin-path=#{node['nginx']['source']['sbin_path']} + --with-cc-opt=-Wno-error +) + +default['nginx']['configure_flags'] = [] +default['nginx']['source']['version'] = node['nginx']['version'] +default['nginx']['source']['url'] = "http://nginx.org/download/nginx-#{node['nginx']['source']['version']}.tar.gz" +default['nginx']['source']['checksum'] = '8793bf426485a30f91021b6b945a9fd8a84d87d17b566562c3797aba8fac76fb' +default['nginx']['source']['modules'] = %w( + nginx::http_ssl_module + nginx::http_gzip_static_module +) +default['nginx']['source']['use_existing_user'] = false diff --git a/cookbooks/nginx/attributes/status.rb b/cookbooks/nginx/attributes/status.rb new file mode 100644 index 0000000..e2191aa --- /dev/null +++ b/cookbooks/nginx/attributes/status.rb @@ -0,0 +1,22 @@ +# +# Cookbook:: nginx +# Attributes:: status +# +# Author:: David Radcliffe () +# +# Copyright:: 2013-2017, David Radcliffe +# +# 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. +# + +default['nginx']['status']['port'] = '8090' diff --git a/cookbooks/nginx/attributes/syslog.rb b/cookbooks/nginx/attributes/syslog.rb new file mode 100644 index 0000000..073ded3 --- /dev/null +++ b/cookbooks/nginx/attributes/syslog.rb @@ -0,0 +1,23 @@ +# +# Cookbook:: nginx +# Attributes:: syslog +# +# Author:: Bob Ziuchkovski () +# +# Copyright:: 2014-2017, UserTesting +# +# 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. +# + +default['nginx']['syslog']['git_repo'] = 'https://github.com/yaoweibin/nginx_syslog_patch.git' +default['nginx']['syslog']['git_revision'] = 'master' diff --git a/cookbooks/nginx/attributes/upload_progress.rb b/cookbooks/nginx/attributes/upload_progress.rb new file mode 100644 index 0000000..9c1819a --- /dev/null +++ b/cookbooks/nginx/attributes/upload_progress.rb @@ -0,0 +1,26 @@ +# +# Cookbook:: nginx +# Attributes:: upload_progress +# +# Author:: Jamie Winsor () +# +# Copyright:: 2012-2017, Riot Games +# +# 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. +# + +default['nginx']['upload_progress']['url'] = 'https://github.com/masterzen/nginx-upload-progress-module/tarball/v0.9.0' +default['nginx']['upload_progress']['checksum'] = '3fb903dab595cf6656fa0fc5743a48daffbba2f6b5c554836be630800eaad4e2' +default['nginx']['upload_progress']['javascript_output'] = true +default['nginx']['upload_progress']['zone_name'] = 'proxied' +default['nginx']['upload_progress']['zone_size'] = '1m' diff --git a/cookbooks/nginx/files/mime.types b/cookbooks/nginx/files/mime.types new file mode 100644 index 0000000..fd3000f --- /dev/null +++ b/cookbooks/nginx/files/mime.types @@ -0,0 +1,135 @@ +types { + + # Data interchange + + application/atom+xml atom; + application/json json map topojson; + application/ld+json jsonld; + application/rss+xml rss; + application/vnd.geo+json geojson; + application/xml rdf xml; + + + # JavaScript + + # Normalize to standard type. + # https://tools.ietf.org/html/rfc4329#section-7.2 + application/javascript js; + + + # Manifest files + + application/manifest+json webmanifest; + application/x-web-app-manifest+json webapp; + text/cache-manifest appcache; + text/cache.manifest manifest; + + + # Media files + + audio/midi mid midi kar; + audio/mp4 aac f4a f4b m4a; + audio/mpeg mp3; + audio/ogg oga ogg opus; + audio/x-realaudio ra; + audio/x-wav wav; + image/bmp bmp; + image/gif gif; + image/jpeg jpeg jpg; + image/png png; + image/svg+xml svg svgz; + image/tiff tif tiff; + image/vnd.wap.wbmp wbmp; + image/webp webp; + image/x-jng jng; + video/3gpp 3gp 3gpp; + video/mp4 f4p f4v m4v mp4; + video/mpeg mpeg mpg; + video/ogg ogv; + video/quicktime mov; + video/webm webm; + video/x-flv flv; + video/x-mng mng; + video/x-ms-asf asf asx; + video/x-ms-wmv wmv; + video/x-msvideo avi; + + # Serving `.ico` image files with a different media type + # prevents Internet Explorer from displaying then as images: + # https://github.com/h5bp/html5-boilerplate/commit/37b5fec090d00f38de64b591bcddcb205aadf8ee + + image/x-icon cur ico; + + + # Microsoft Office + + application/msword doc; + application/vnd.ms-excel xls; + application/vnd.ms-powerpoint ppt; + application/vnd.openxmlformats-officedocument.wordprocessingml.document docx; + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx; + application/vnd.openxmlformats-officedocument.presentationml.presentation pptx; + + + # Web fonts + + application/font-woff woff; + application/font-woff2 woff2; + application/vnd.ms-fontobject eot; + + # Browsers usually ignore the font media types and simply sniff + # the bytes to figure out the font type. + # https://mimesniff.spec.whatwg.org/#matching-a-font-type-pattern + # + # However, Blink and WebKit based browsers will show a warning + # in the console if the following font types are served with any + # other media types. + + application/x-font-ttf ttc ttf; + font/opentype otf; + + # Other + + application/java-archive ear jar war; + application/mac-binhex40 hqx; + application/octet-stream bin deb dll dmg exe img iso msi msm msp safariextz; + application/pdf pdf; + application/postscript ai eps ps; + application/rtf rtf; + application/vnd.apple.mpegurl m3u8; + application/vnd.google-earth.kml+xml kml; + application/vnd.google-earth.kmz kmz; + application/vnd.wap.wmlc wmlc; + application/x-7z-compressed 7z; + application/x-bb-appworld bbaw; + application/x-bittorrent torrent; + application/x-chrome-extension crx; + application/x-cocoa cco; + application/x-java-archive-diff jardiff; + application/x-java-jnlp-file jnlp; + application/x-makeself run; + application/x-opera-extension oex; + application/x-perl pl pm; + application/x-pilot pdb prc; + application/x-rar-compressed rar; + application/x-redhat-package-manager rpm; + application/x-sea sea; + application/x-shockwave-flash swf; + application/x-stuffit sit; + application/x-tcl tcl tk; + application/x-x509-ca-cert crt der pem; + application/x-xpinstall xpi; + application/xhtml+xml xhtml; + application/xslt+xml xsl; + application/zip zip; + text/css css; + text/html htm html shtml; + text/mathml mml; + text/plain txt; + text/vcard vcard vcf; + text/vnd.rim.location.xloc xloc; + text/vnd.sun.j2me.app-descriptor jad; + text/vnd.wap.wml wml; + text/vtt vtt; + text/x-component htc; +} diff --git a/cookbooks/nginx/files/naxsi_core.rules b/cookbooks/nginx/files/naxsi_core.rules new file mode 100644 index 0000000..8a8800a --- /dev/null +++ b/cookbooks/nginx/files/naxsi_core.rules @@ -0,0 +1,82 @@ +################################## +## INTERNAL RULES IDS:1-10 ## +################################## +#weird_request : 1 +#big_body : 2 +#no_content_type : 3 + +#@MainRule "msg:weird/incorrect request" id:1; +#@MainRule "msg:big request, unparsed" id:2; +#@MainRule "msg:uncommon hex encoding (%00 etc.)" id:10; +#@MainRule "msg:uncommon/empty content-type in POST" id:11; +#@MainRule "msg:uncommon/malformed URL" id:12; + +#MainRule "str:123FREETEXT" "msg:exemple learning test pattern" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:BLOCK" id:0; + +################################## +## SQL Injections IDs:1000-1099 ## +################################## +MainRule "rx:select|union|update|delete|insert|table|from|ascii|hex|unhex|drop" "msg:sql keywords" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1000; +MainRule "str:\"" "msg:double quote" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8,$XSS:8" id:1001; +MainRule "str:0x" "msg:0x, possible hex encoding" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:2" id:1002; +## Hardcore rules +MainRule "str:/*" "msg:mysql comment (/*)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1003; +MainRule "str:*/" "msg:mysql comment (*/)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1004; +MainRule "str:|" "msg:mysql keyword (|)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1005; +MainRule "str:&&" "msg:mysql keyword (&&)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1006; +## end of hardcore rules +MainRule "str:--" "msg:mysql comment (--)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1007; +MainRule "str:;" "msg:; in stuff" "mz:BODY|URL|ARGS" "s:$SQL:4,$XSS:8" id:1008; +MainRule "str:=" "msg:equal in var, probable sql/xss" "mz:ARGS|BODY" "s:$SQL:2" id:1009; +MainRule "str:(" "msg:parenthesis, probable sql/xss" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1010; +MainRule "str:)" "msg:parenthesis, probable sql/xss" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1011; +MainRule "str:'" "msg:simple quote" "mz:ARGS|BODY|URL|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1013; +MainRule "str:," "msg:, in stuff" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1015; +MainRule "str:#" "msg:mysql comment (#)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1016; + +############################### +## OBVIOUS RFI IDs:1100-1199 ## +############################### +MainRule "str:http://" "msg:http:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1100; +MainRule "str:https://" "msg:https:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1101; +MainRule "str:ftp://" "msg:ftp:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1102; +MainRule "str:php://" "msg:php:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1103; +MainRule "str:sftp://" "msg:sftp:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1104; +MainRule "str:zlib://" "msg:zlib:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1105; +MainRule "str:data://" "msg:data:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1106; +MainRule "str:glob://" "msg:glob:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1107; +MainRule "str:phar://" "msg:phar:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1108; +MainRule "str:file://" "msg:file:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1109; + +####################################### +## Directory traversal IDs:1200-1299 ## +####################################### +MainRule "str:.." "msg:double dot" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1200; +MainRule "str:/etc/passwd" "msg:obvious probe" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1202; +MainRule "str:c:\\" "msg:obvious windows path" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1203; +MainRule "str:cmd.exe" "msg:obvious probe" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1204; +MainRule "str:\\" "msg:backslash" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1205; +#MainRule "str:/" "msg:slash in args" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:2" id:1206; + +######################################## +## Cross Site Scripting IDs:1300-1399 ## +######################################## +MainRule "str:<" "msg:html open tag" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1302; +MainRule "str:>" "msg:html close tag" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1303; +MainRule "str:[" "msg:[, possible js" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$XSS:4" id:1310; +MainRule "str:]" "msg:], possible js" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$XSS:4" id:1311; +MainRule "str:~" "msg:~ character" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$XSS:4" id:1312; +MainRule "str:`" "msg:grave accent !" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1314; +MainRule "rx:%[2|3]." "msg:double encoding !" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1315; + +#################################### +## Evading tricks IDs: 1400-1500 ## +#################################### +MainRule "str:&#" "msg: utf7/8 encoding" "mz:ARGS|BODY|URL|$HEADERS_VAR:Cookie" "s:$EVADE:4" id:1400; +MainRule "str:%U" "msg: M$ encoding" "mz:ARGS|BODY|URL|$HEADERS_VAR:Cookie" "s:$EVADE:4" id:1401; +MainRule negative "rx:multipart/form-data|application/x-www-form-urlencoded" "msg:Content is neither mulipart/x-www-form.." "mz:$HEADERS_VAR:Content-type" "s:$EVADE:4" id:1402; + +############################# +## File uploads: 1500-1600 ## +############################# +MainRule "rx:.ph|.asp|.ht" "msg:asp/php file upload!" "mz:FILE_EXT" "s:$UPLOAD:8" id:1500; diff --git a/cookbooks/nginx/libraries/helpers.rb b/cookbooks/nginx/libraries/helpers.rb new file mode 100644 index 0000000..8c4f3b1 --- /dev/null +++ b/cookbooks/nginx/libraries/helpers.rb @@ -0,0 +1,38 @@ +# +# Cookbook:: nginx +# Library:: helpers +# +# Author:: Tim Smith () +# +# Copyright:: 2016-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# simple helper module for the nginx cookbook +module NginxRecipeHelpers + # pidfile is hard to determine on Debian systems. + # Upstream packages and older distro releases use '/var/run/nginx.pid' + # systemd based distros and Ubuntu 14.04 use '/run/nginx.pid' for their + # packages + def pidfile_location + if (node['nginx']['repo_source'].nil? || %w(distro passenger).include?(node['nginx']['repo_source'])) && + (node['init_package'] == 'systemd' || node['platform_version'].to_f == 14.04) + '/run/nginx.pid' + else + '/var/run/nginx.pid' + end + end +end + +Chef::Resource.send(:include, NginxRecipeHelpers) diff --git a/cookbooks/nginx/libraries/nginx_version.rb b/cookbooks/nginx/libraries/nginx_version.rb new file mode 100644 index 0000000..957267a --- /dev/null +++ b/cookbooks/nginx/libraries/nginx_version.rb @@ -0,0 +1,37 @@ +class NginxVersion + include Comparable + + attr_reader :version + + def initialize(version) + @version = version + end + + def <=>(other) + lhsegments = segments + rhsegments = other.segments + + parts = [lhsegments.size, rhsegments.size].max + + (0..(parts - 1)).each do |index| + lhs = lhsegments[index] || 0 + rhs = rhsegments[index] || 0 + + next if lhs == rhs + + return lhs <=> rhs + end + + 0 + end + + def to_s + version + end + + protected + + def segments + version.split('.').map { |part| Integer(part) } + end +end diff --git a/cookbooks/nginx/metadata.json b/cookbooks/nginx/metadata.json new file mode 100644 index 0000000..ba305ab --- /dev/null +++ b/cookbooks/nginx/metadata.json @@ -0,0 +1 @@ +{"name":"nginx","version":"9.0.0","description":"Installs and configures nginx","long_description":"# nginx Cookbook\n\n[![Cookbook](http://img.shields.io/cookbook/v/nginx.svg)](https://supermarket.chef.io/cookbooks/nginx) [![Build Status](https://travis-ci.org/chef-cookbooks/nginx.svg?branch=master)](https://travis-ci.org/chef-cookbooks/nginx)\n\nInstalls nginx from package OR source code and sets up configuration handling similar to Debian's Apache2 scripts.\n\n## Requirements\n\n### Cookbooks\n\nThe following cookbooks are direct dependencies because they're used for common \"default\" functionality.\n\n- `build-essential` for source installations\n- `ohai` for setting up the ohai plugin\n- `yum-epel` for setting up the EPEL repository on RHEL platforms\n- `zypper` for setting up the nginx.org repository on Suse platforms\n\n### Platforms\n\nThe following platforms are supported and tested with Test Kitchen:\n\n- Ubuntu 14.04+\n- CentOS 6+\n- Debian 7+\n- openSUSE\n- FreeBSD\n\nOther Debian and RHEL family distributions are assumed to work.\n\n### Chef\n\n- Chef 13.3+\n\n## Attributes\n\nNode attributes for this cookbook are logically separated into different files. Some attributes are set only via a specific recipe.\n\n### nginx::auth_request\n\nThese attributes are used in the `nginx::auth_request` recipe.\n\n- `node['nginx']['auth_request']['url']` - The url to the auth_request module tar.gz file\n- `node['nginx']['auth_request']['checksum']` - The checksum of the auth_request module tar.gz file\n\n### nginx::default\n\nGenerally used attributes. Some have platform specific values. See `attributes/default.rb`. \"The Config\" refers to \"nginx.conf\" the main config file.\n\n- `node['nginx']['dir']` - Location for nginx configuration.\n- `node['nginx']['conf_template']` - The `source` template to use when creating the `nginx.conf`.\n- `node['nginx']['conf_cookbook']` - The cookbook where `node['nginx']['conf_template']` resides.\n- `node['nginx']['log_dir']` - Location for nginx logs.\n- `node['nginx']['log_dir_perm']` - Permissions for nginx logs folder.\n- `node['nginx']['user']` - User that nginx will run as.\n- `node['nginx']['user_home']` - User home path, used during user creation.\n- `node['nginx']['group']` - Group for nginx.\n- `node['nginx']['port']` - Port for nginx to listen on.\n- `node['nginx']['binary']` - Path to the nginx binary.\n- `node['nginx']['init_style']` - How to run nginx as a service when using `nginx::source`. Values can be \"upstart\", \"systemd\", or \"init\". This attribute is not used in the `package` recipe because the package manager's init script style for the platform is assumed.\n- `node['nginx']['cleanup_runit']` - Cleanup existing runit based nginx service installation. Uses the `nginx_cleanup_runit` resource. Default: true\n- `node['nginx']['upstart']['foreground']` - Set this to true if you want upstart to run nginx in the foreground, set to false if you want upstart to detach and track the process via pid.\n- `node['nginx']['upstart']['runlevels']` - String of runlevels in the format '2345' which determines which runlevels nginx will start at when entering and stop at when leaving.\n- `node['nginx']['upstart']['respawn_limit']` - Respawn limit in upstart stanza format, count followed by space followed by interval in seconds.\n- `node['nginx']['keepalive']` - Whether to use `keepalive_timeout`, any value besides \"on\" will leave that option out of the config.\n- `node['nginx']['keepalive_requests']` - used for config value of `keepalive_requests`.\n- `node['nginx']['keepalive_timeout']` - used for config value of `keepalive_timeout`.\n- `node['nginx']['worker_processes']` - used for config value of `worker_processes`.\n- `node['nginx']['worker_connections']` - used for config value of `events { worker_connections }`\n- `node['nginx']['worker_rlimit_nofile']` - used for config value of `worker_rlimit_nofile`. Can replace any \"ulimit -n\" command. The value depend on your usage (cache or not) but must always be superior than worker_connections.\n- `node['nginx']['worker_shutdown_timeout']` - used for config value of `worker_shutdown_timeout`.\n- `node['nginx']['worker_connections']` - used for config value of `events { worker_connections }`\n- `node['nginx']['multi_accept']` - used for config value of `events { multi_accept }`. Try to accept() as many connections as possible. Disable by default.\n- `node['nginx']['event']` - used for config value of `events { use }`. Set the event-model. By default nginx looks for the most suitable method for your OS.\n- `node['nginx']['accept_mutex_delay']` - used for config value of `accept_mutex_delay`\n- `node['nginx']['server_tokens']` - used for config value of `server_tokens`.\n- `node['nginx']['server_names_hash_bucket_size']` - used for config value of `server_names_hash_bucket_size`.\n- `node['nginx']['disable_access_log']` - set to true to disable the general access log, may be useful on high traffic sites.\n- `node['nginx']['access_log_options']` - Set to a string of additional options to be appended to the access log directive\n- `node['nginx']['error_log_options']` - Set to a string of additional options to be appended to the error log directive\n- `node['nginx']['default_site_enabled']` - enable the default site\n- `node['nginx']['sendfile']` - Whether to use `sendfile`. Defaults to \"on\".\n- `node['nginx']['tcp_nopush']` - Whether to use `tcp_nopush`. Defaults to \"on\".\n- `node['nginx']['tcp_nodelay']` - Whether to use `tcp_nodelay`. Defaults to \"on\".\n- `node['nginx']['install_method']` - Whether nginx is installed from packages or from source.\n- `node['nginx']['types_hash_max_size']` - Used for the `types_hash_max_size` configuration directive.\n- `node['nginx']['types_hash_bucket_size']` - Used for the `types_hash_bucket_size` configuration directive.\n- `node['nginx']['proxy_read_timeout']` - defines a timeout (between two successive read operations) for reading a response from the proxied server.\n- `node['nginx']['client_body_buffer_size']` - used for config value of `client_body_buffer_size`.\n- `node['nginx']['client_max_body_size']` - specifies the maximum accepted body size of a client request, as indicated by the request header Content-Length.\n- `node['nginx']['repo_source']` - when installed from a package this attribute affects which yum repositories, if any, will be added before installing the nginx package. The default value of 'epel' will use the `yum-epel` cookbook, 'nginx' will use the `nginx::repo` recipe, 'passenger' will use the 'nginx::repo_passenger' recipe, and setting no value will not add any additional repositories.\n- `node['nginx']['sts_max_age']` - Enable Strict Transport Security for all apps (See: ). This attribute adds the following header: Strict-Transport-Security max-age=SECONDS to all incoming requests and takes an integer (in seconds) as its argument.\n- `node['nginx']['default']['modules']` - Array specifying which modules to enable via the conf-enabled config include function. Currently the only valid value is \"socketproxy\".\n- `node['nginx']['load_modules']` - Array of paths to modules to dynamically load on nginx startup using the `load_module` directive. Default is `[]`.\n\n#### authorized_ips module\n\n- `node['nginx']['remote_ip_var']` - The remote ip variable name to use.\n- `node['nginx']['authorized_ips']` - IPs authorized by the module\n\n#### gzip module\n\n- `node['nginx']['gzip']` - Whether to use gzip, can be \"on\" or \"off\"\n- `node['nginx']['gzip_http_version']` - used for config value of `gzip_http_version`.\n- `node['nginx']['gzip_comp_level']` - used for config value of `gzip_comp_level`.\n- `node['nginx']['gzip_proxied']` - used for config value of `gzip_proxied`.\n- `node['nginx']['gzip_vary']` - used for config value of `gzip_vary`.\n- `node['nginx']['gzip_buffers']` - used for config value of `gzip_buffers`.\n- `node['nginx']['gzip_types']` - used for config value of `gzip_types` - must be an Array.\n- `node['nginx']['gzip_min_length']` - used for config value of `gzip_min_length`.\n- `node['nginx']['gzip_disable']` - used for config value of `gzip_disable`.\n- `node['nginx']['gzip_static']` - used for config value of `gzip_static` (`http_gzip_static_module` must be enabled)\n\n#### Other configurations\n\n- `node['nginx']['extra_configs']` - a Hash of key/values to nginx configuration.\n\n### nginx::devel\n\nThese attributes are used in the `nginx::ngx_devel_module` recipe.\n\n- `node['nginx']['devel']['version']` - The version of the nginx devel module\n- `node['nginx']['devel']['url']` - The URL of the nginx devel module tar.gz file\n- `node['nginx']['devel']['checksum']` - The checksum of the nginx devel module tar.gz file\n\n### nginx::echo\n\nThese attributes are used in the `nginx::http_echo_module` recipe.\n\n- `node['nginx']['echo']['version']` - The version of `http_echo` you want (default: 0.59)\n- `node['nginx']['echo']['url']` - URL for the tarball.\n- `node['nginx']['echo']['checksum']` - Checksum of the tarball.\n\n### nginx::geoip\n\nThese attributes are used in the `nginx::http_geoip_module` recipe. Please note that the `country_dat_checksum` and `city_dat_checksum` are based on downloads from a datacenter in Fremont, CA, USA. You really should override these with checksums for the geo tarballs from your node location.\n\n**Note** The upstream, maxmind.com, may block access for repeated downloads of the data files. It is recommended that you download and host the data files, and change the URLs in the attributes.\n\n- `node['nginx']['geoip']['path']` - Location where to install the geoip libraries.\n- `node['nginx']['geoip']['enable_city']` - Whether to enable City data\n- `node['nginx']['geoip']['country_dat_url']` - Country data tarball URL\n- `node['nginx']['geoip']['country_dat_checksum']` - Country data tarball checksum\n- `node['nginx']['geoip']['city_dat_url']` - City data tarball URL\n- `node['nginx']['geoip']['city_dat_checksum']` - City data tarball checksum\n- `node['nginx']['geoip']['lib_version']` - Version of the GeoIP library to install\n- `node['nginx']['geoip']['lib_url']` - (Versioned) Tarball URL of the GeoIP library\n- `node['nginx']['geoip']['lib_checksum']` - Checksum of the GeoIP library tarball\n\n### nginx::http_realip_module\n\nFrom: \n\n- `node['nginx']['realip']['header']` - Header to use for the RealIp Module; only accepts \"X-Forwarded-For\" or \"X-Real-IP\"\n- `node['nginx']['realip']['addresses']` - Addresses to use for the `http_realip` configuration.\n- `node['nginx']['realip']['real_ip_recursive']` - If recursive search is enabled, the original client address that matches one of the trusted addresses is replaced by the last non-trusted address sent in the request header field. Can be on \"on\" or \"off\" (default).\n\n### nginx::ohai_plugin\n\nThe `ohai_plugin` recipe includes an Ohai plugin. It will be automatically installed and activated, providing the following attributes via ohai, no matter how nginx is installed (source or package):\n\n- `node['nginx']['version']` - version of nginx\n- `node['nginx']['configure_arguments']` - options passed to `./configure` when nginx was built\n- `node['nginx']['prefix']` - installation prefix\n- `node['nginx']['conf_path']` - configuration file path\n- `node['nginx']['ohai_plugin_enabled']` - Toggles ohai_plugin recipe. Defaults to true.\n\nIn the source recipe, it is used to determine whether control attributes for building nginx have changed.\n\n### nginx::openssl_source\n\nThese attributes are used in the `nginx::openssl_source` recipe.\n\n- `node['nginx']['openssl_source']['version']` - The version of OpenSSL you want to download and use (default: 1.0.1t)\n- `node['nginx']['openssl_source']['url']` - The url for the OpenSSL source\n\n### nginx::passenger\n\nThese attributes are used in the `nginx::passenger` recipe.\n\n- `node['nginx']['passenger']['version']` - passenger gem version\n- `node['nginx']['passenger']['root']` - passenger gem root path\n- `node['nginx']['passenger']['install_rake']` - set to false if rake already present on system\n- `node['nginx']['passenger']['max_pool_size']` - maximum passenger pool size (default=10)\n- `node['nginx']['passenger']['ruby']` - Ruby path for Passenger to use (default=`$(which ruby)`)\n- `node['nginx']['passenger']['spawn_method']` - passenger spawn method to use (default=`smart-lv2`)\n- `node['nginx']['passenger']['buffer_response']` - turns on or off response buffering (default=`on`)\n- `node['nginx']['passenger']['max_pool_size']` - passenger maximum pool size (default=`6`)\n- `node['nginx']['passenger']['min_instances']` - minimum instances (default=`1`)\n- `node['nginx']['passenger']['max_instances_per_app']` - maximum instances per app (default=`0`)\n- `node['nginx']['passenger']['pool_idle_time']` - passenger pool idle time (default=`300`)\n- `node['nginx']['passenger']['max_requests']` - maximum requests (default=`0`)\n- `node['nginx']['passenger']['nodejs']` - Nodejs path for Passenger to use (default=nil)\n- `node['nginx']['passenger']['show_version_in_header']` - Show passenger version in HTTP headers (default=`on`)\n\nBasic configuration to use the official Phusion Passenger repositories:\n\n- `node['nginx']['repo_source']` - 'passenger'\n- `node['nginx']['package_name']` - 'nginx-extras'\n- `node['nginx']['passenger']['install_method']` - 'package'\n\n### nginx::rate_limiting\n\n- `node['nginx']['enable_rate_limiting']` - set to true to enable rate limiting (`limit_req_zone` in nginx.conf)\n- `node['nginx']['rate_limiting_zone_name']` - sets the zone in `limit_req_zone`.\n- `node['nginx']['rate_limiting_backoff']` - **Incorrect name, retained for compatibility reasons** - sets the size of the shared memory zone (default=`10m`, 10 megabytes)\n- `node['nginx']['rate_limit']` - set the rate limit amount for `limit_req_zone`.\n\n### nginx::repo\n\n- `node['nginx']['upstream_repository']` - the URL to use for the package repository resource; default is set based on platform type\n- `node['nginx']['repo_signing_key']` - The URL from which package signing/gpg key is retrieved\n\n### nginx::socketproxy\n\nThese attributes are used in the `nginx::socketproxy` recipe.\n\n- `node['nginx']['socketproxy']['root']` - The directory (on your server) where socketproxy apps are deployed.\n- `node['nginx']['socketproxy']['default_app']` - Static assets directory for requests to \"/\" that don't meet any proxy_pass filter requirements.\n- `node['nginx']['socketproxy']['apps']['app_name']['prepend_slash']` - Prepend a slash to requests to app \"app_name\" before sending them to the socketproxy socket.\n- `node['nginx']['socketproxy']['apps']['app_name']['context_name']` - URI (e.g. \"app_name\" in order to achieve \"\") at which to host the application \"app_name\"\n- `node['nginx']['socketproxy']['apps']['app_name']['subdir']` - Directory (under `node['nginx']['socketproxy']['root']`) in which to find the application.\n\n### nginx::source\n\nThese attributes are used in the `nginx::source` recipe. Some of them are dynamically modified during the run. See `attributes/source.rb` for default values.\n\n- `node['nginx']['source']['url']` - (versioned) URL for the nginx source code. By default this will use the version specified as `node['nginx']['version']`.\n- `node['nginx']['source']['prefix']` - (versioned) prefix for installing nginx from source\n- `node['nginx']['source']['conf_path']` - location of the main config file, in `node['nginx']['dir']` by default.\n- `node['nginx']['source']['modules']` - Array of modules that should be compiled into nginx by including their recipes in `nginx::source`.\n- `node['nginx']['source']['default_configure_flags']` - The default flags passed to the configure script when building nginx.\n- `node['nginx']['configure_flags']` - Preserved for compatibility and dynamically generated from the `node['nginx']['source']['default_configure_flags']` in the `nginx::source` recipe.\n- `node['nginx']['source']['use_existing_user']` - set to `true` if you do not want `nginx::source` recipe to create system user with name `node['nginx']['user']` and `node['nginx']['user_home']`.\n\n### nginx::status\n\nThese attributes are used in the `nginx::http_stub_status_module` recipe.\n\n- `node['nginx']['status']['port']` - The port on which nginx will serve the status info (default: 8090)\n\n### nginx::syslog\n\nThese attributes are used in the `nginx::syslog_module` recipe.\n\n- `node['nginx']['syslog']['git_repo']` - The git repository url to use for the syslog patches.\n- `node['nginx']['syslog']['git_revision']` - The revision on the git repository to checkout.\n\n### nginx::upload_progress\n\nThese attributes are used in the `nginx::upload_progress_module` recipe.\n\n- `node['nginx']['upload_progress']['url']` - URL for the tarball.\n- `node['nginx']['upload_progress']['checksum']` - Checksum of the tarball.\n- `node['nginx']['upload_progress']['javascript_output']` - Output in javascript. Default is `true` for backwards compatibility.\n- `node['nginx']['upload_progress']['zone_name']` - Zone name which will be used to store the per-connection tracking information. Default is `proxied`.\n- `node['nginx']['upload_progress']['zone_size']` - Zone size in bytes. Default is `1m` (1 megabyte).\n\n## Resources\n\n### nginx_site\n\nEnable or disable a Server Block in `#{node['nginx']['dir']}/sites-available` by calling nxensite or nxdissite (introduced by this cookbook) to manage the symbolic link in `#{node['nginx']['dir']}/sites-enabled`.\n\n### Actions\n\n- `enable` - Enable the nginx site (default)\n- `disable` - Disable the nginx site\n\n### Properties:\n\n- `site_name` - (optional) Name of the site to enable. By default it's assumed that the name of the nginx_site resource is the site name, but this allows overriding that.\n- `template` - (optional) Path to the source for the `template` resource.\n- `variables` - (optional) Variables to be used with the `template` resource\n\n### nginx_stream\n\nEnable or disable a Stream Block in `#{node['nginx']['dir']}/streams-available` by calling nxenstream or nxdisstream (introduced by this cookbook) to manage the symbolic link in `#{node['nginx']['dir']}/streams-enabled`.\n\n### Actions\n\n- `enable` - Enable the nginx stream (default)\n- `disable` - Disable the nginx stream\n\n### Properties:\n\n- `stream_name` - (optional) Name of the stream to enable.\n- `template` - (optional) Path to the source for the `template` resource.\n- `variables` - (optional) Variables to be used with the `template` resource\n\n### nginx_cleanup_runit\n\nA simple resource to remove existing runit based nginx service installations. This is used in the default nginx recipe to stop runit based nginx services and cleanup runit service configs before setting up nginx under the system's own init system.\n\n### Actions\n\n- `cleanup` - Stop runit based nginx and remove runit configs (default)\n\n## Usage\n\nThis cookbook provides three distinct installation methods, all of which are controlled via attributes and executed using the nginx::default recipe.\n\n### Package installation using the nginx.org repositories\n\nNginx provides repositories for RHEL, Debian/Ubuntu, and Suse platforms with up to date packages available on older distributions. Due to the age of many nginx packages shipping with distros we believe this is the ideal installation method. With no attributes set the nginx.org repositories will be added to your system and nginx will be installed via package. This provides a solid out of the box install for most users.\n\n### Package installation using distro repositories\n\nIf you prefer to use the packages included in your distro or to roll your own packages you'll want to set `node['nginx']['repo_source']` to `nil` or `distro` to skip the repository setup. The default recipe will still install nginx from packages, but you'll retain control over the package location.\n\n### Source installation to compile non-dynamic modules\n\nIf you need control over how nginx is built, or you need non-dynamic modules to be included you'll need to compile nginx from source. We highly recommend against using this method as it requires the installation of a full compilation toolchain and development dependencies on your nodes. Creating your own packages with nginx compiled as necessary is a preferred option. If that's not possible you can set `node['nginx']['install_method']` to `source` and provide a version in `node['nginx']['version']`.\n\n#### Specifying Modules to compile\n\nThe following recipes are used to build module support into nginx. To compile a module, add its recipe name to the array attribute `node['nginx']['source']['modules']`.\n\n- `ipv6.rb` - enables IPv6 support\n- `headers_more_module` -\n- `http_auth_request_module``\n- `http_echo_module.rb` - downloads the `http_echo_module` module and enables it as a module when compiling nginx.\n- `http_geoip_module.rb` - installs the GeoIP libraries and data files and enables the module for compilation.\n- `http_gzip_static_module.rb` - enables the module for compilation. Be sure to set `node['nginx']['gzip_static'] = 'yes'`.\n- `http_mp4_module` -\n- `http_perl_module.rb` - enables embedded Perl for compilation.\n- `http_realip_module.rb` - enables the module for compilation and creates the configuration.\n- `http_spdy_module` -\n- `http_ssl_module.rb` - enables SSL for compilation.\n- `http_stub_status_module.rb` - provides `nginx_status` configuration and enables the module for compilation.\n- `http_v2_module`\n- `ipv6` -\n- `naxsi_module` - enables the naxsi module for the web application firewall for nginx.\n- `ngx_devel_module` -\n- `ngx_lua_module` -\n- `openssl_source.rb` - downloads and uses custom OpenSSL source when compiling nginx\n- `pagespeed_module`-\n- `passenger` - builds the passenger gem and configuration for \"`mod_passenger`\".\n- `set_misc` -\n- `syslog_module` - enables syslog support for nginx. This only works with source builds. See -\n- `upload_progress_module.rb` - builds the `upload_progress` module and enables it as a module when compiling nginx.\n\n## Resources\n\n### nginx_site\n\nEnable or disable a Server Block in `#{node['nginx']['dir']}/sites-available` by calling nxensite or nxdissite (introduced by this cookbook) to manage the symbolic link in `#{node['nginx']['dir']}/sites-enabled`.\n\n### Actions\n\n- `enable` - Enable the nginx site (default)\n- `disable` - Disable the nginx site\n\n### Properties:\n\n- `name` - (optional) Name of the site to enable. By default it's assumed that the name of the nginx_site resource is the site name, but this allows overriding that.\n- `template` - (optional) Path to the source for the `template` resource.\n- `cookbook` - (optional) The cookbook that contains the template source.\n- `variables` - (optional) Variables to be used with the `template` resource\n\n## Adding New Modules\n\nPreviously we'd add each possible module to this cookbook itself. That's not necessary using wrapper cookbooks and we'd prefer to not add any addition module recipes at this time. Instead in your nginx wrapper cookbook setup any necessary packages and then include the follow code to add the module to the list of modules to compile:\n\n```ruby\nnode.run_state['nginx_configure_flags'] =\n node.run_state['nginx_configure_flags'] | ['--with-SOMETHING', \"--with-SOME_OPT='things'\"]\n```\n\n## Maintainers\n\nThis cookbook is maintained by Chef's Community Cookbook Engineering team. Our goal is to improve cookbook quality and to aid the community in contributing to cookbooks. To learn more about our team, process, and design goals see our [team documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/COOKBOOK_TEAM.MD). To learn more about contributing to cookbooks like this see our [contributing documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD), or if you have general questions about this cookbook come chat with us in #cookbok-engineering on the [Chef Community Slack](http://community-slack.chef.io/)\n\n## License\n\n```\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"amazon":">= 0.0.0","centos":">= 0.0.0","debian":">= 0.0.0","fedora":">= 0.0.0","oracle":">= 0.0.0","redhat":">= 0.0.0","scientific":">= 0.0.0","ubuntu":">= 0.0.0","suse":">= 0.0.0","opensuse":">= 0.0.0","opensuseleap":">= 0.0.0"},"dependencies":{"build-essential":">= 5.0","ohai":">= 4.1.0","yum-epel":">= 0.0.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{"nginx":"Installs nginx package and sets up configuration with Debian apache style with sites-enabled/sites-available","nginx::source":"Installs nginx from source and sets up configuration with Debian apache style with sites-enabled/sites-available"},"source_url":"https://github.com/chef-cookbooks/nginx","issues_url":"https://github.com/chef-cookbooks/nginx/issues","chef_version":[[">= 13.3"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/nginx/recipes/authorized_ips.rb b/cookbooks/nginx/recipes/authorized_ips.rb new file mode 100644 index 0000000..c11d6dd --- /dev/null +++ b/cookbooks/nginx/recipes/authorized_ips.rb @@ -0,0 +1,29 @@ +# +# Cookbook:: nginx +# Recipe:: authorized_ips +# +# Author:: Jamie Winsor () +# +# Copyright:: 2012-2017, Riot Games +# +# 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. +# + +node.default['nginx']['remote_ip_var'] = 'remote_addr' +node.default['nginx']['authorized_ips'] = ['127.0.0.1/32'] + +template 'authorized_ip' do + path "#{node['nginx']['dir']}/authorized_ip" + source 'modules/authorized_ip.erb' + notifies :reload, 'service[nginx]', :delayed +end diff --git a/cookbooks/nginx/recipes/commons.rb b/cookbooks/nginx/recipes/commons.rb new file mode 100644 index 0000000..cfcf9f5 --- /dev/null +++ b/cookbooks/nginx/recipes/commons.rb @@ -0,0 +1,24 @@ +# +# Cookbook:: nginx +# Recipe:: commons +# +# Author:: AJ Christensen +# +# Copyright:: 2008-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'nginx::commons_dir' +include_recipe 'nginx::commons_script' +include_recipe 'nginx::commons_conf' diff --git a/cookbooks/nginx/recipes/commons_conf.rb b/cookbooks/nginx/recipes/commons_conf.rb new file mode 100644 index 0000000..948e543 --- /dev/null +++ b/cookbooks/nginx/recipes/commons_conf.rb @@ -0,0 +1,37 @@ +# +# Cookbook:: nginx +# Recipe:: common/conf +# +# Author:: AJ Christensen +# +# Copyright:: 2008-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +template 'nginx.conf' do + path "#{node['nginx']['dir']}/nginx.conf" + source node['nginx']['conf_template'] + cookbook node['nginx']['conf_cookbook'] + notifies :reload, 'service[nginx]', :delayed + variables(lazy { { pid_file: pidfile_location } }) +end + +template "#{node['nginx']['dir']}/sites-available/default" do + source 'default-site.erb' + notifies :reload, 'service[nginx]', :delayed +end + +nginx_site 'default' do + action node['nginx']['default_site_enabled'] ? :enable : :disable +end diff --git a/cookbooks/nginx/recipes/commons_dir.rb b/cookbooks/nginx/recipes/commons_dir.rb new file mode 100644 index 0000000..0503ea5 --- /dev/null +++ b/cookbooks/nginx/recipes/commons_dir.rb @@ -0,0 +1,52 @@ +# +# Cookbook:: nginx +# Recipe:: common/dir +# +# Author:: AJ Christensen +# +# Copyright:: 2008-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +directory node['nginx']['dir'] do + mode '0755' + recursive true +end + +directory node['nginx']['log_dir'] do + mode node['nginx']['log_dir_perm'] + owner node['nginx']['user'] + action :create + recursive true +end + +directory 'pid file directory' do + path lazy { File.dirname(pidfile_location) } + mode '0755' + recursive true +end + +%w(sites-available sites-enabled conf.d streams-available streams-enabled).each do |leaf| + directory File.join(node['nginx']['dir'], leaf) do + mode '0755' + end +end + +if !node['nginx']['default_site_enabled'] && platform_family?('rhel', 'fedora', 'amazon') + %w(default.conf example_ssl.conf).each do |config| + file "/etc/nginx/conf.d/#{config}" do + action :delete + end + end +end diff --git a/cookbooks/nginx/recipes/commons_script.rb b/cookbooks/nginx/recipes/commons_script.rb new file mode 100644 index 0000000..8e4a0f6 --- /dev/null +++ b/cookbooks/nginx/recipes/commons_script.rb @@ -0,0 +1,27 @@ +# +# Cookbook:: nginx +# Recipe:: common/script +# +# Author:: AJ Christensen +# +# Copyright:: 2008-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +%w(nxensite nxdissite nxenstream nxdisstream).each do |nxscript| + template "#{node['nginx']['script_dir']}/#{nxscript}" do + source "#{nxscript}.erb" + mode '0755' + end +end diff --git a/cookbooks/nginx/recipes/default.rb b/cookbooks/nginx/recipes/default.rb new file mode 100644 index 0000000..106f449 --- /dev/null +++ b/cookbooks/nginx/recipes/default.rb @@ -0,0 +1,28 @@ +# +# Cookbook:: nginx +# Recipe:: default +# +# Author:: AJ Christensen +# +# Copyright:: 2008-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +nginx_cleanup_runit 'cleanup' if node['nginx']['cleanup_runit'] + +include_recipe "nginx::#{node['nginx']['install_method']}" + +node['nginx']['default']['modules'].each do |ngx_module| + include_recipe "nginx::#{ngx_module}" +end diff --git a/cookbooks/nginx/recipes/headers_more_module.rb b/cookbooks/nginx/recipes/headers_more_module.rb new file mode 100644 index 0000000..cde990f --- /dev/null +++ b/cookbooks/nginx/recipes/headers_more_module.rb @@ -0,0 +1,45 @@ +# +# Cookbook:: nginx +# Recipe:: headers_more_module +# +# Author:: Lucas Jandrew () +# +# Copyright:: 2012-2017, Riot Games +# +# 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. + +tar_location = "#{Chef::Config['file_cache_path']}/headers_more.tar.gz" +module_location = "#{Chef::Config['file_cache_path']}/headers_more/#{node['nginx']['headers_more']['source_checksum']}" + +remote_file tar_location do + source node['nginx']['headers_more']['source_url'] + checksum node['nginx']['headers_more']['source_checksum'] +end + +directory module_location do + mode '0755' + recursive true + action :create +end + +bash 'extract_headers_more' do + cwd ::File.dirname(tar_location) + user 'root' + code <<-EOH + tar -zxf #{tar_location} -C #{module_location} + EOH + not_if { ::File.exist?("#{module_location}/headers-more-nginx-module-#{node['nginx']['headers_more']['version']}/config") } +end + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ["--add-module=#{module_location}/headers-more-nginx-module-#{node['nginx']['headers_more']['version']}/"] diff --git a/cookbooks/nginx/recipes/http_auth_request_module.rb b/cookbooks/nginx/recipes/http_auth_request_module.rb new file mode 100644 index 0000000..5ed944f --- /dev/null +++ b/cookbooks/nginx/recipes/http_auth_request_module.rb @@ -0,0 +1,49 @@ +# +# Cookbook:: nginx +# Recipe:: http_auth_request_module +# +# Author:: David Radcliffe () +# +# Copyright:: 2013-2017, David Radcliffe +# +# 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. +# + +# Documentation: +# http://nginx.org/en/docs/http/ngx_http_auth_request_module.html +if Chef::VersionConstraint.new('>= 1.5.4').include?(node['nginx']['source']['version']) + node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ['--with-http_auth_request_module'] +else + arm_src_filename = ::File.basename(node['nginx']['auth_request']['url']) + arm_src_filepath = "#{Chef::Config['file_cache_path']}/#{arm_src_filename}" + arm_extract_path = "#{Chef::Config['file_cache_path']}/nginx_auth_request/#{node['nginx']['auth_request']['checksum']}" + + remote_file arm_src_filepath do + source node['nginx']['auth_request']['url'] + checksum node['nginx']['auth_request']['checksum'] + end + + bash 'extract_auth_request_module' do + cwd ::File.dirname(arm_src_filepath) + code <<-EOH + mkdir -p #{arm_extract_path} + tar xzf #{arm_src_filename} -C #{arm_extract_path} + mv #{arm_extract_path}/*/* #{arm_extract_path}/ + EOH + not_if { ::File.exist?(arm_extract_path) } + end + + node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ["--add-module=#{arm_extract_path}"] +end diff --git a/cookbooks/nginx/recipes/http_echo_module.rb b/cookbooks/nginx/recipes/http_echo_module.rb new file mode 100644 index 0000000..a660e5d --- /dev/null +++ b/cookbooks/nginx/recipes/http_echo_module.rb @@ -0,0 +1,43 @@ +# +# Cookbook:: nginx +# Recipe:: http_echo_module +# +# Author:: Danial Pearce () +# +# Copyright:: 2012-2017, CushyCMS +# +# 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. +# + +echo_src_filename = "echo-nginx-module-v#{node['nginx']['echo']['version']}.tar.gz" +echo_src_filepath = "#{Chef::Config['file_cache_path']}/#{echo_src_filename}" +echo_extract_path = "#{Chef::Config['file_cache_path']}/nginx_echo_module/#{node['nginx']['echo']['checksum']}" + +remote_file echo_src_filepath do + source node['nginx']['echo']['url'] + checksum node['nginx']['echo']['checksum'] +end + +bash 'extract_http_echo_module' do + cwd ::File.dirname(echo_src_filepath) + code <<-EOH + mkdir -p #{echo_extract_path} + tar xzf #{echo_src_filename} -C #{echo_extract_path} + mv #{echo_extract_path}/*/* #{echo_extract_path}/ + EOH + + not_if { ::File.exist?(echo_extract_path) } +end + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ["--add-module=#{echo_extract_path}"] diff --git a/cookbooks/nginx/recipes/http_geoip_module.rb b/cookbooks/nginx/recipes/http_geoip_module.rb new file mode 100644 index 0000000..cba28ab --- /dev/null +++ b/cookbooks/nginx/recipes/http_geoip_module.rb @@ -0,0 +1,99 @@ +# +# Cookbook:: nginx +# Recipe:: http_geoip_module +# +# Author:: Jamie Winsor () +# +# Copyright:: 2012-2017, Riot Games +# +# 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. +# + +country_dat = "#{node['nginx']['geoip']['path']}/GeoIP.dat" +country_src_filename = ::File.basename(node['nginx']['geoip']['country_dat_url']) +country_src_filepath = "#{Chef::Config['file_cache_path']}/#{country_src_filename}" +city_dat = nil +city_src_filename = ::File.basename(node['nginx']['geoip']['city_dat_url']) +city_src_filepath = "#{Chef::Config['file_cache_path']}/#{city_src_filename}" +geolib_filename = ::File.basename(node['nginx']['geoip']['lib_url']) +geolib_filepath = "#{Chef::Config['file_cache_path']}/#{geolib_filename}" + +remote_file geolib_filepath do + source node['nginx']['geoip']['lib_url'] + checksum node['nginx']['geoip']['lib_checksum'] +end + +bash 'extract_geolib' do + cwd ::File.dirname(geolib_filepath) + code <<-EOH + tar xzvf #{geolib_filepath} -C #{::File.dirname(geolib_filepath)} + cd GeoIP-#{node['nginx']['geoip']['lib_version']} + ./configure + make && make install + EOH + environment('echo' => 'echo') if node['platform_family'] == 'rhel' && node['platform_version'].to_f < 6 + creates "/usr/local/lib/libGeoIP.so.#{node['nginx']['geoip']['lib_version']}" + subscribes :run, "remote_file[#{geolib_filepath}]" +end + +directory node['nginx']['geoip']['path'] do + mode '0755' + recursive true +end + +remote_file country_src_filepath do + not_if do + File.exist?(country_src_filepath) && + File.mtime(country_src_filepath) > Time.now - 86_400 + end + source node['nginx']['geoip']['country_dat_url'] + checksum node['nginx']['geoip']['country_dat_checksum'] +end + +bash 'gunzip_geo_lite_country_dat' do + code <<-EOH + gunzip -c "#{country_src_filepath}" > #{country_dat} + EOH + creates country_dat +end + +if node['nginx']['geoip']['enable_city'] + city_dat = "#{node['nginx']['geoip']['path']}/GeoLiteCity.dat" + + remote_file city_src_filepath do + not_if do + File.exist?(city_src_filepath) && + File.mtime(city_src_filepath) > Time.now - 86_400 + end + source node['nginx']['geoip']['city_dat_url'] + checksum node['nginx']['geoip']['city_dat_checksum'] + end + + bash 'gunzip_geo_lite_city_dat' do + code <<-EOH + gunzip -c "#{city_src_filepath}" > #{city_dat} + EOH + creates city_dat + end +end + +template "#{node['nginx']['dir']}/conf.d/http_geoip.conf" do + source 'modules/http_geoip.conf.erb' + variables( + country_dat: country_dat, + city_dat: city_dat + ) +end + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ['--with-http_geoip_module', "--with-ld-opt='-Wl,-R,/usr/local/lib -L /usr/local/lib'"] diff --git a/cookbooks/nginx/recipes/http_gzip_static_module.rb b/cookbooks/nginx/recipes/http_gzip_static_module.rb new file mode 100644 index 0000000..d52fadd --- /dev/null +++ b/cookbooks/nginx/recipes/http_gzip_static_module.rb @@ -0,0 +1,27 @@ +# +# Cookbook:: nginx +# Recipe:: http_gzip_static_module +# +# Author:: Jamie Winsor () +# +# Copyright:: 2012-2017, Riot Games +# +# 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. +# + +template "#{node['nginx']['dir']}/conf.d/http_gzip_static.conf" do + source 'modules/http_gzip_static.conf.erb' +end + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ['--with-http_gzip_static_module'] diff --git a/cookbooks/nginx/recipes/http_mp4_module.rb b/cookbooks/nginx/recipes/http_mp4_module.rb new file mode 100644 index 0000000..555f597 --- /dev/null +++ b/cookbooks/nginx/recipes/http_mp4_module.rb @@ -0,0 +1,2 @@ +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ['--with-http_mp4_module'] diff --git a/cookbooks/nginx/recipes/http_perl_module.rb b/cookbooks/nginx/recipes/http_perl_module.rb new file mode 100644 index 0000000..8efe202 --- /dev/null +++ b/cookbooks/nginx/recipes/http_perl_module.rb @@ -0,0 +1,23 @@ +# +# Cookbook:: nginx +# Recipe:: http_perl_module +# +# Author:: Akzhan Abdulin () +# +# Copyright:: 2012-2017, REG.RU +# +# 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. +# + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ['--with-http_perl_module'] diff --git a/cookbooks/nginx/recipes/http_realip_module.rb b/cookbooks/nginx/recipes/http_realip_module.rb new file mode 100644 index 0000000..d07ff4e --- /dev/null +++ b/cookbooks/nginx/recipes/http_realip_module.rb @@ -0,0 +1,35 @@ +# +# Cookbook:: nginx +# Recipe:: http_realip_module +# +# Author:: Jamie Winsor () +# +# Copyright:: 2012-2017, Riot Games +# +# 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. +# + +# Documentation: http://wiki.nginx.org/HttpRealIpModule + +# Currently only accepts X-Forwarded-For or X-Real-IP +node.default['nginx']['realip']['header'] = 'X-Forwarded-For' +node.default['nginx']['realip']['addresses'] = ['127.0.0.1'] +node.default['nginx']['realip']['real_ip_recursive'] = 'off' + +template "#{node['nginx']['dir']}/conf.d/http_realip.conf" do + source 'modules/http_realip.conf.erb' + notifies :reload, 'service[nginx]', :delayed +end + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ['--with-http_realip_module'] diff --git a/cookbooks/nginx/recipes/http_spdy_module.rb b/cookbooks/nginx/recipes/http_spdy_module.rb new file mode 100644 index 0000000..e15518e --- /dev/null +++ b/cookbooks/nginx/recipes/http_spdy_module.rb @@ -0,0 +1,23 @@ +# +# Cookbook:: nginx +# Recipe:: http_spdy_module +# +# Author:: Christoph Buente () +# +# Copyright:: 2013-2017, MeinekleineFarm.org +# +# 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. +# + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ['--with-http_spdy_module'] diff --git a/cookbooks/nginx/recipes/http_ssl_module.rb b/cookbooks/nginx/recipes/http_ssl_module.rb new file mode 100644 index 0000000..4163a05 --- /dev/null +++ b/cookbooks/nginx/recipes/http_ssl_module.rb @@ -0,0 +1,23 @@ +# +# Cookbook:: nginx +# Recipe:: http_ssl_module +# +# Author:: Jamie Winsor () +# +# Copyright:: 2012-2017, Riot Games +# +# 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. +# + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ['--with-http_ssl_module'] diff --git a/cookbooks/nginx/recipes/http_stub_status_module.rb b/cookbooks/nginx/recipes/http_stub_status_module.rb new file mode 100644 index 0000000..7e89dd0 --- /dev/null +++ b/cookbooks/nginx/recipes/http_stub_status_module.rb @@ -0,0 +1,33 @@ +# +# Cookbook:: nginx +# Recipe:: http_stub_status_module +# +# Author:: Jamie Winsor () +# +# Copyright:: 2012-2017, Riot Games +# +# 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. +# + +include_recipe 'nginx::authorized_ips' + +template 'nginx_status' do + path "#{node['nginx']['dir']}/sites-available/nginx_status" + source 'modules/nginx_status.erb' + notifies :reload, 'service[nginx]', :delayed +end + +nginx_site 'nginx_status' + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ['--with-http_stub_status_module'] diff --git a/cookbooks/nginx/recipes/http_v2_module.rb b/cookbooks/nginx/recipes/http_v2_module.rb new file mode 100644 index 0000000..0a7148f --- /dev/null +++ b/cookbooks/nginx/recipes/http_v2_module.rb @@ -0,0 +1,21 @@ +# +# Cookbook:: nginx +# Recipe:: http_v2_module +# +# +# +# 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. +# + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ['--with-http_v2_module'] diff --git a/cookbooks/nginx/recipes/ipv6.rb b/cookbooks/nginx/recipes/ipv6.rb new file mode 100644 index 0000000..57dba63 --- /dev/null +++ b/cookbooks/nginx/recipes/ipv6.rb @@ -0,0 +1,23 @@ +# +# Cookbook:: nginx +# Recipe:: ipv6 +# +# Author:: Alan Harper (alan@sct.com.au) +# +# Copyright:: 2013-2017, Alan Harper +# +# 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. +# + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ['--with-ipv6'] diff --git a/cookbooks/nginx/recipes/lua.rb b/cookbooks/nginx/recipes/lua.rb new file mode 100644 index 0000000..7f3a1a3 --- /dev/null +++ b/cookbooks/nginx/recipes/lua.rb @@ -0,0 +1,46 @@ +# +# Cookbook:: nginx +# Recipe:: lua +# +# Copyright:: 2013-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +luajit_src_filename = ::File.basename(node['nginx']['luajit']['url']) +luajit_src_filepath = "#{Chef::Config['file_cache_path']}/#{luajit_src_filename}" +luajit_extract_path = "#{Chef::Config['file_cache_path']}/luajit-#{node['nginx']['luajit']['version']}" + +remote_file luajit_src_filepath do + source node['nginx']['luajit']['url'] + checksum node['nginx']['luajit']['checksum'] +end + +bash 'extract_luajit' do + cwd ::File.dirname(luajit_src_filepath) + code <<-EOH + mkdir -p #{luajit_extract_path} + tar xzf #{luajit_src_filename} -C #{luajit_extract_path} + cd luajit-#{node['nginx']['luajit']['version']}/LuaJIT-#{node['nginx']['luajit']['version']} + make && make install + EOH + not_if { ::File.exist?(luajit_extract_path) } +end + +node.run_state['nginx_source_env'].merge!( + 'LUAJIT_INC' => '/usr/local/include/luajit-2.0', + 'LUAJIT_LIB' => '/usr/local/lib' +) + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ['--with-ld-opt=-Wl,-rpath,/usr/local/lib'] diff --git a/cookbooks/nginx/recipes/naxsi_module.rb b/cookbooks/nginx/recipes/naxsi_module.rb new file mode 100644 index 0000000..2adbaf6 --- /dev/null +++ b/cookbooks/nginx/recipes/naxsi_module.rb @@ -0,0 +1,46 @@ +# +# Cookbook:: nginx +# Recipe:: naxsi_module +# +# Author:: Artiom Lunev () +# +# Copyright:: 2012-2017, Artiom Lunev +# +# 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. +# + +cookbook_file "#{node['nginx']['dir']}/naxsi_core.rules" do + source 'naxsi_core.rules' + notifies :reload, 'service[nginx]', :delayed +end + +naxsi_src_filename = ::File.basename(node['nginx']['naxsi']['url']) +naxsi_src_filepath = "#{Chef::Config['file_cache_path']}/#{naxsi_src_filename}" +naxsi_extract_path = "#{Chef::Config['file_cache_path']}/nginx-naxsi-#{node['nginx']['naxsi']['version']}" + +remote_file naxsi_src_filepath do + source node['nginx']['naxsi']['url'] + checksum node['nginx']['naxsi']['checksum'] +end + +bash 'extract_naxsi_module' do + cwd ::File.dirname(naxsi_src_filepath) + code <<-EOH + mkdir -p #{naxsi_extract_path} + tar xzf #{naxsi_src_filename} -C #{naxsi_extract_path} + EOH + not_if { ::File.exist?(naxsi_extract_path) } +end + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ["--add-module=#{naxsi_extract_path}/naxsi-#{node['nginx']['naxsi']['version']}/naxsi_src"] diff --git a/cookbooks/nginx/recipes/ngx_devel_module.rb b/cookbooks/nginx/recipes/ngx_devel_module.rb new file mode 100644 index 0000000..89c9d46 --- /dev/null +++ b/cookbooks/nginx/recipes/ngx_devel_module.rb @@ -0,0 +1,41 @@ +# +# Cookbook:: nginx +# Recipes:: devel +# +# Author:: Arthur Freyman () +# +# Copyright:: 2013-2017, Riot Games +# +# 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. +# + +devel_src_filename = ::File.basename(node['nginx']['devel']['url']) +devel_src_filepath = "#{Chef::Config['file_cache_path']}/#{devel_src_filename}" +devel_extract_path = "#{Chef::Config['file_cache_path']}/nginx-devel-#{node['nginx']['devel']['version']}" + +remote_file devel_src_filepath do + source node['nginx']['devel']['url'] + checksum node['nginx']['devel']['checksum'] +end + +bash 'extract_devel_module' do + cwd ::File.dirname(devel_src_filepath) + code <<-EOH + mkdir -p #{devel_extract_path} + tar xzf #{devel_src_filename} -C #{devel_extract_path} + EOH + not_if { ::File.exist?(devel_extract_path) } +end + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ["--add-module=#{devel_extract_path}/ngx_devel_kit-#{node['nginx']['devel']['version']}"] diff --git a/cookbooks/nginx/recipes/ngx_lua_module.rb b/cookbooks/nginx/recipes/ngx_lua_module.rb new file mode 100644 index 0000000..083d8e1 --- /dev/null +++ b/cookbooks/nginx/recipes/ngx_lua_module.rb @@ -0,0 +1,44 @@ +# +# Cookbook:: nginx +# Recipes:: nginx_lua_module +# +# Author:: Arthur Freyman () +# +# Copyright:: 2013-2017, Riot Games +# +# 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. +# + +lua_src_filename = ::File.basename(node['nginx']['lua']['url']) +lua_src_filepath = "#{Chef::Config['file_cache_path']}/#{lua_src_filename}" +lua_extract_path = "#{Chef::Config['file_cache_path']}/nginx-lua-#{node['nginx']['lua']['version']}" + +remote_file lua_src_filepath do + source node['nginx']['lua']['url'] + checksum node['nginx']['lua']['checksum'] +end + +bash 'extract_lua_module' do + cwd ::File.dirname(lua_src_filepath) + code <<-EOH + mkdir -p #{lua_extract_path} + tar xzf #{lua_src_filename} -C #{lua_extract_path} + EOH + not_if { ::File.exist?(lua_extract_path) } +end + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ["--add-module=#{lua_extract_path}/lua-nginx-module-#{node['nginx']['lua']['version']}"] + +include_recipe 'nginx::lua' +include_recipe 'nginx::ngx_devel_module' diff --git a/cookbooks/nginx/recipes/ohai_plugin.rb b/cookbooks/nginx/recipes/ohai_plugin.rb new file mode 100644 index 0000000..a554754 --- /dev/null +++ b/cookbooks/nginx/recipes/ohai_plugin.rb @@ -0,0 +1,33 @@ +# +# Cookbook:: nginx +# Recipe:: ohai_plugin +# +# Author:: Jamie Winsor () +# +# Copyright:: 2012-2017, Riot Games +# Copyright:: 2016-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# for notification post install / change +ohai 'reload_nginx' do + plugin 'nginx' + action :nothing +end + +ohai_plugin 'nginx' do + source_file 'plugins/ohai-nginx.rb.erb' + variables binary: node['nginx']['binary'] + resource :template +end diff --git a/cookbooks/nginx/recipes/openssl_source.rb b/cookbooks/nginx/recipes/openssl_source.rb new file mode 100644 index 0000000..01969bb --- /dev/null +++ b/cookbooks/nginx/recipes/openssl_source.rb @@ -0,0 +1,42 @@ +# +# Cookbook:: nginx +# Recipe:: openssl_source +# +# Author:: David Radcliffe () +# +# Copyright:: 2013-2017, David Radcliffe +# +# 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. +# + +src_filename = ::File.basename(node['nginx']['openssl_source']['url']) +src_filepath = "#{Chef::Config['file_cache_path']}/#{src_filename}" +extract_path = "#{Chef::Config['file_cache_path']}/openssl-#{node['nginx']['openssl_source']['version']}" + +remote_file src_filepath do + source node['nginx']['openssl_source']['url'] + not_if { ::File.exist?(src_filepath) } +end + +bash 'extract_openssl' do + cwd ::File.dirname(src_filepath) + code <<-EOH + mkdir -p #{extract_path} + tar xzf #{src_filename} -C #{extract_path} + mv #{extract_path}/*/* #{extract_path}/ + EOH + not_if { ::File.exist?(extract_path) } +end + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ["--with-openssl=#{extract_path}"] diff --git a/cookbooks/nginx/recipes/package.rb b/cookbooks/nginx/recipes/package.rb new file mode 100644 index 0000000..461aaa6 --- /dev/null +++ b/cookbooks/nginx/recipes/package.rb @@ -0,0 +1,57 @@ +# +# Cookbook:: nginx +# Recipe:: package +# Author:: AJ Christensen +# +# Copyright:: 2008-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'nginx::ohai_plugin' if node['nginx']['ohai_plugin_enabled'] + +case node['nginx']['repo_source'] +when 'epel' + if platform_family?('rhel') + include_recipe 'yum-epel' + else + Chef::Log.warn("node['nginx']['repo_source'] set to EPEL, but not running on a RHEL platform so skipping EPEL setup") + end +when 'nginx' + include_recipe 'nginx::repo' + package_install_opts = '--disablerepo=* --enablerepo=nginx' if platform_family?('rhel') +when 'passenger' + if platform_family?('debian') + include_recipe 'nginx::repo_passenger' + else + Chef::Log.warn("node['nginx']['repo_source'] set to passenger, but not running on a Debian based platform so skipping repo setup") + end +else + Chef::Log.warn('Unrecognized distro value set, or no value set. Using distro provided packages instead.') +end + +package node['nginx']['package_name'] do + options package_install_opts + notifies :reload, 'ohai[reload_nginx]', :immediately if node['nginx']['ohai_plugin_enabled'] +end + +include_recipe 'nginx::commons' + +if node['nginx']['repo_source'] == 'passenger' + include_recipe 'nginx::passenger' +end + +service 'nginx' do + supports status: true, restart: true, reload: true + action [:start, :enable] +end diff --git a/cookbooks/nginx/recipes/pagespeed_module.rb b/cookbooks/nginx/recipes/pagespeed_module.rb new file mode 100644 index 0000000..2793807 --- /dev/null +++ b/cookbooks/nginx/recipes/pagespeed_module.rb @@ -0,0 +1,52 @@ +# +# Cookbook:: nginx +# Recipe:: pagespeed_module +# + +src_filename = ::File.basename(node['nginx']['pagespeed']['url']) +src_filepath = "#{Chef::Config['file_cache_path']}/#{src_filename}" +extract_path = "#{Chef::Config['file_cache_path']}/nginx_pagespeed-#{node['nginx']['pagespeed']['version']}" + +remote_file src_filepath do + source node['nginx']['pagespeed']['url'] + not_if { ::File.exist?(src_filepath) } +end + +psol_src_filename = "psol-#{::File.basename(node['nginx']['psol']['url'])}" +psol_src_filepath = "#{Chef::Config['file_cache_path']}/#{psol_src_filename}" +psol_extract_path = "#{Chef::Config['file_cache_path']}/nginx_pagespeed-#{node['nginx']['pagespeed']['version']}/psol" + +remote_file psol_src_filepath do + source node['nginx']['psol']['url'] + not_if { ::File.exist?(psol_src_filepath) } +end + +package_array = value_for_platform_family( + %w(rhel amazon) => node['nginx']['pagespeed']['packages']['rhel'], + %w(debian) => node['nginx']['pagespeed']['packages']['debian'] +) + +package package_array unless package_array.empty? + +bash 'extract_pagespeed' do + cwd ::File.dirname(src_filepath) + code <<-EOH + mkdir -p #{extract_path} + tar xzf #{src_filename} -C #{extract_path} + mv #{extract_path}/*/* #{extract_path}/ + EOH + not_if { ::File.exist?(extract_path) } +end + +bash 'extract_psol' do + cwd ::File.dirname(psol_src_filepath) + code <<-EOH + mkdir -p #{psol_extract_path} + tar xzf #{psol_src_filename} -C #{psol_extract_path} + mv #{psol_extract_path}/*/* #{psol_extract_path}/ + EOH + not_if { ::File.exist?(psol_extract_path) } +end + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ["--add-module=#{extract_path}"] diff --git a/cookbooks/nginx/recipes/passenger.rb b/cookbooks/nginx/recipes/passenger.rb new file mode 100644 index 0000000..4709dd0 --- /dev/null +++ b/cookbooks/nginx/recipes/passenger.rb @@ -0,0 +1,57 @@ +# +# Cookbook:: nginx +# Recipe:: Passenger +# +# Copyright:: 2013-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +packages = value_for_platform_family( + %w(rhel amazon) => node['nginx']['passenger']['packages']['rhel'], + %w(fedora) => node['nginx']['passenger']['packages']['fedora'], + %w(debian) => node['nginx']['passenger']['packages']['debian'] +) + +package packages unless packages.empty? + +gem_package 'rake' if node['nginx']['passenger']['install_rake'] + +if node['nginx']['passenger']['install_method'] == 'package' + package node['nginx']['package_name'] + package 'passenger' +elsif node['nginx']['passenger']['install_method'] == 'source' + + gem_package 'passenger' do + action :install + version node['nginx']['passenger']['version'] + gem_binary node['nginx']['passenger']['gem_binary'] if node['nginx']['passenger']['gem_binary'] + end + + passenger_module = node['nginx']['passenger']['root'] + + passenger_module += if Chef::VersionConstraint.new('>= 5.0.19').include?(node['nginx']['passenger']['version']) + '/src/nginx_module' + else + '/ext/nginx' + end + + node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ["--add-module=#{passenger_module}"] + +end + +template node['nginx']['passenger']['conf_file'] do + source 'modules/passenger.conf.erb' + notifies :reload, 'service[nginx]', :delayed +end diff --git a/cookbooks/nginx/recipes/repo.rb b/cookbooks/nginx/recipes/repo.rb new file mode 100644 index 0000000..a396bfb --- /dev/null +++ b/cookbooks/nginx/recipes/repo.rb @@ -0,0 +1,53 @@ +# +# Cookbook:: nginx +# Recipe:: repo +# Author:: Nick Rycar +# +# Copyright:: 2008-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +case node['platform_family'] +when 'rhel', 'amazon' + + yum_repository 'nginx' do + description 'Nginx.org Repository' + baseurl node['nginx']['upstream_repository'] + gpgkey node['nginx']['repo_signing_key'] + action :create + end + +when 'suse' + + zypper_repo 'nginx' do + repo_name 'Nginx.org Repository' + uri node['nginx']['upstream_repository'] + key node['nginx']['repo_signing_key'] + end + +when 'debian' + + apt_repository 'nginx' do + uri node['nginx']['upstream_repository'] + distribution node['lsb']['codename'] + components %w(nginx) + deb_src true + key node['nginx']['repo_signing_key'] + end + +else + log "nginx.org does not maintain packages for platform #{node['platform']}. Cannot setup the upstream repo!" do + level :warn + end +end diff --git a/cookbooks/nginx/recipes/repo_passenger.rb b/cookbooks/nginx/recipes/repo_passenger.rb new file mode 100644 index 0000000..3886393 --- /dev/null +++ b/cookbooks/nginx/recipes/repo_passenger.rb @@ -0,0 +1,34 @@ +# Cookbook:: nginx +# Recipe:: repo_passenger +# Author:: Jose Alberto Suarez Lopez +# +# 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. +# + +if platform_family?('debian') + package 'ca-certificates' + + apt_repository 'phusionpassenger' do + uri 'https://oss-binaries.phusionpassenger.com/apt/passenger' + distribution node['lsb']['codename'] + components %w(main) + deb_src true + keyserver 'keyserver.ubuntu.com' + key '561F9B9CAC40B2F7' + end +else + log "There is not official phusion passenger repo platform #{node['platform']}. Skipping repo setup!" do + level :warn + end +end + diff --git a/cookbooks/nginx/recipes/set_misc.rb b/cookbooks/nginx/recipes/set_misc.rb new file mode 100644 index 0000000..f09097c --- /dev/null +++ b/cookbooks/nginx/recipes/set_misc.rb @@ -0,0 +1,27 @@ +# +# Cookbook:: nginx +# Recipes:: set_misc +# + +set_misc_src_filename = ::File.basename(node['nginx']['set_misc']['url']) +set_misc_src_filepath = "#{Chef::Config['file_cache_path']}/#{set_misc_src_filename}" +set_misc_extract_path = "#{Chef::Config['file_cache_path']}/nginx-set_misc-#{node['nginx']['set_misc']['version']}" + +remote_file set_misc_src_filepath do + source node['nginx']['set_misc']['url'] + checksum node['nginx']['set_misc']['checksum'] +end + +bash 'extract_set_misc_module' do + cwd ::File.dirname(set_misc_src_filepath) + code <<-EOH + mkdir -p #{set_misc_extract_path} + tar xzf #{set_misc_src_filename} -C #{set_misc_extract_path} + EOH + not_if { ::File.exist?(set_misc_extract_path) } +end + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ["--add-module=#{set_misc_extract_path}/set-misc-nginx-module-#{node['nginx']['set_misc']['version']}"] + +include_recipe 'nginx::ngx_devel_module' diff --git a/cookbooks/nginx/recipes/socketproxy.rb b/cookbooks/nginx/recipes/socketproxy.rb new file mode 100644 index 0000000..1415a18 --- /dev/null +++ b/cookbooks/nginx/recipes/socketproxy.rb @@ -0,0 +1,23 @@ +include_recipe 'nginx::commons_dir' + +directory node['nginx']['socketproxy']['root'] do + owner node['nginx']['socketproxy']['app_owner'] + group node['nginx']['socketproxy']['app_owner'] + mode '0755' + action :create +end + +context_names = node['nginx']['socketproxy']['apps'].map do |_app, app_conf| + app_conf['context_name'] +end + +raise 'More than one app has the same context_name configured.' if context_names.uniq.length != context_names.length + +template node['nginx']['dir'] + '/sites-available/socketproxy.conf' do + source 'modules/socketproxy.conf.erb' + notifies :reload, 'service[nginx]', :delayed +end + +link node['nginx']['dir'] + '/sites-enabled/socketproxy.conf' do + to node['nginx']['dir'] + '/sites-available/socketproxy.conf' +end diff --git a/cookbooks/nginx/recipes/source.rb b/cookbooks/nginx/recipes/source.rb new file mode 100644 index 0000000..2e17e27 --- /dev/null +++ b/cookbooks/nginx/recipes/source.rb @@ -0,0 +1,173 @@ +# +# Cookbook:: nginx +# Recipe:: source +# +# Author:: Adam Jacob () +# Author:: Joshua Timberman () +# Author:: Jamie Winsor () +# +# Copyright:: 2009-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +raise "#{node['platform']} is not a supported platform in the nginx::source recipe" unless platform_family?('rhel', 'amazon', 'fedora', 'debian', 'suse') + +node.normal['nginx']['binary'] = node['nginx']['source']['sbin_path'] +node.normal['nginx']['daemon_disable'] = true + +user node['nginx']['user'] do + system true + shell '/bin/false' + home node['nginx']['user_home'] + manage_home true + not_if { node['nginx']['source']['use_existing_user'] } +end + +include_recipe 'nginx::ohai_plugin' if node['nginx']['ohai_plugin_enabled'] +include_recipe 'nginx::commons_dir' +include_recipe 'nginx::commons_script' +build_essential 'install compilation tools' + +src_filepath = "#{Chef::Config['file_cache_path']}/nginx-#{node['nginx']['source']['version']}.tar.gz" + +# install prereqs +package value_for_platform_family( + %w(rhel fedora amazon) => %w(pcre-devel openssl-devel tar zlib-devel), + %w(suse) => %w(pcre-devel libopenssl-devel tar), + %w(debian) => %w(libpcre3 libpcre3-dev libssl-dev tar zlib1g-dev) +) + +remote_file 'nginx source' do + source node['nginx']['source']['url'] + checksum node['nginx']['source']['checksum'] + path src_filepath + backup false + retries 4 +end + +node.run_state['nginx_force_recompile'] = false +node.run_state['nginx_configure_flags'] = + node['nginx']['source']['default_configure_flags'] | node['nginx']['configure_flags'] +node.run_state['nginx_source_env'] = {} + +include_recipe 'nginx::commons_conf' + +cookbook_file "#{node['nginx']['dir']}/mime.types" do + source 'mime.types' + notifies :reload, 'service[nginx]', :delayed +end + +# Unpack downloaded source so we could apply nginx patches +# in custom modules - example http://yaoweibin.github.io/nginx_tcp_proxy_module/ +# patch -p1 < /path/to/nginx_tcp_proxy_module/tcp.patch +bash 'unarchive_source' do + cwd ::File.dirname(src_filepath) + code <<-EOH + tar zxf #{::File.basename(src_filepath)} -C #{::File.dirname(src_filepath)} --no-same-owner + EOH + not_if { ::File.directory?("#{Chef::Config['file_cache_path'] || '/tmp'}/nginx-#{node['nginx']['source']['version']}") } +end + +node['nginx']['source']['modules'].each do |ngx_module| + include_recipe ngx_module +end + +configure_flags = node.run_state['nginx_configure_flags'] +nginx_force_recompile = node.run_state['nginx_force_recompile'] + +bash 'compile_nginx_source' do + cwd ::File.dirname(src_filepath) + environment node.run_state['nginx_source_env'] + code <<-EOH + cd nginx-#{node['nginx']['source']['version']} && + ./configure #{node.run_state['nginx_configure_flags'].join(' ')} && + make && make install + EOH + + not_if do + nginx_force_recompile == false && + node.automatic_attrs['nginx'] && + node.automatic_attrs['nginx']['version'] == node['nginx']['source']['version'] && + node.automatic_attrs['nginx']['configure_arguments'].sort == configure_flags.sort + end + + notifies :restart, 'service[nginx]' + notifies :reload, 'ohai[reload_nginx]', :immediately if node['nginx']['ohai_plugin_enabled'] +end + +case node['nginx']['init_style'] +when 'upstart' + # we rely on this to set up nginx.conf with daemon disable instead of doing + # it in the upstart init script. + node.normal['nginx']['daemon_disable'] = node['nginx']['upstart']['foreground'] + + template '/etc/init/nginx.conf' do + source 'nginx-upstart.conf.erb' + variables(lazy { { pid_file: pidfile_location } }) + end + + service 'nginx' do + provider Chef::Provider::Service::Upstart + supports status: true, restart: true, reload: true + action [:start, :enable] + end +when 'systemd' + + systemd_prefix = platform_family?('suse') ? '/usr/lib' : '/lib' + + template "#{systemd_prefix}/systemd/system/nginx.service" do + source 'nginx.service.erb' + end + + service 'nginx' do + provider Chef::Provider::Service::Systemd + supports status: true, restart: true, reload: true + action [:start, :enable] + end +else + node.normal['nginx']['daemon_disable'] = false + + generate_init = true + + case node['platform'] + when 'debian', 'ubuntu' + generate_template = true + defaults_path = '/etc/default/nginx' + when 'freebsd' + generate_init = false + else + generate_template = true + defaults_path = '/etc/sysconfig/nginx' + end + + template '/etc/init.d/nginx' do + source 'nginx.init.erb' + mode '0755' + variables(lazy { { pid_file: pidfile_location } }) + end if generate_init + + if generate_template # ~FC023 + template defaults_path do + source 'nginx.sysconfig.erb' + end + end + + service 'nginx' do + supports status: true, restart: true, reload: true + action [:start, :enable] + end +end + +node.run_state.delete('nginx_configure_flags') +node.run_state.delete('nginx_force_recompile') diff --git a/cookbooks/nginx/recipes/syslog_module.rb b/cookbooks/nginx/recipes/syslog_module.rb new file mode 100644 index 0000000..e731910 --- /dev/null +++ b/cookbooks/nginx/recipes/syslog_module.rb @@ -0,0 +1,67 @@ +# +# Cookbook:: nginx +# Recipe:: syslog_module +# +# Author:: Bob Ziuchkovski () +# +# Copyright:: 2014-2017, UserTesting +# +# 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. +# + +nginx_src = "#{Chef::Config['file_cache_path']}/nginx-#{node['nginx']['source']['version']}" +nginx_syslog_src = "#{Chef::Config['file_cache_path']}/nginx_syslog_module" + +major, minor, patch = node['nginx']['source']['version'].split('.').map { |s| Integer(s) } +raise 'Unsupported nginx version' if major != 1 +case minor +when 2 + syslog_patch = case patch + when 0..6 + 'syslog_1.2.0.patch' + else + 'syslog_1.2.7.patch' + end +when 3 + syslog_patch = case patch + when 0..9 + 'syslog_1.2.0.patch' + when 10..13 + 'syslog_1.3.11.patch' + else + 'syslog_1.3.14.patch' + end +when 4 + syslog_patch = 'syslog_1.4.0.patch' +when 5..6 + syslog_patch = 'syslog_1.5.6.patch' +when 7 + syslog_patch = 'syslog_1.7.0.patch' +else + raise 'Unsupported nginx version' +end + +git nginx_syslog_src do + repository node['nginx']['syslog']['git_repo'] + revision node['nginx']['syslog']['git_revision'] + action :sync +end + +execute 'apply_nginx_syslog_patch' do + cwd nginx_src + command "patch -p1 < #{nginx_syslog_src}/#{syslog_patch}" + not_if "patch -p1 --dry-run --reverse --silent < #{nginx_syslog_src}/#{syslog_patch}", cwd: nginx_src +end + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ["--add-module=#{nginx_syslog_src}"] diff --git a/cookbooks/nginx/recipes/upload_progress_module.rb b/cookbooks/nginx/recipes/upload_progress_module.rb new file mode 100644 index 0000000..8a64f07 --- /dev/null +++ b/cookbooks/nginx/recipes/upload_progress_module.rb @@ -0,0 +1,47 @@ +# +# Cookbook:: nginx +# Recipe:: upload_progress_module +# +# Author:: Jamie Winsor () +# +# Copyright:: 2012-2017, Riot Games +# +# 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. +# + +upm_src_filename = ::File.basename(node['nginx']['upload_progress']['url']) +upm_src_filepath = "#{Chef::Config['file_cache_path']}/#{upm_src_filename}" +upm_extract_path = "#{Chef::Config['file_cache_path']}/nginx_upload_progress/#{node['nginx']['upload_progress']['checksum']}" + +remote_file upm_src_filepath do + source node['nginx']['upload_progress']['url'] + checksum node['nginx']['upload_progress']['checksum'] +end + +template "#{node['nginx']['dir']}/conf.d/upload_progress.conf" do + source 'modules/upload_progress.erb' + notifies :reload, 'service[nginx]', :delayed +end + +bash 'extract_upload_progress_module' do + cwd ::File.dirname(upm_src_filepath) + code <<-EOH + mkdir -p #{upm_extract_path} + tar xzf #{upm_src_filename} -C #{upm_extract_path} + mv #{upm_extract_path}/*/* #{upm_extract_path}/ + EOH + not_if { ::File.exist?(upm_extract_path) } +end + +node.run_state['nginx_configure_flags'] = + node.run_state['nginx_configure_flags'] | ["--add-module=#{upm_extract_path}"] diff --git a/cookbooks/nginx/resources/cleanup_runit.rb b/cookbooks/nginx/resources/cleanup_runit.rb new file mode 100644 index 0000000..cb75b63 --- /dev/null +++ b/cookbooks/nginx/resources/cleanup_runit.rb @@ -0,0 +1,36 @@ +# +# Copyright:: 20017-2018, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +action :cleanup do + # remove old init script link + file 'remove symlinked runit init script' do + path '/etc/init.d/nginx' + manage_symlink_source false # nuke the link not the runit binary + action :delete + only_if { ::File.exist?('/etc/init.d/nginx') && ::File.symlink?('/etc/init.d/nginx') && ::File.realpath('/etc/init.d/nginx') == '/usr/bin/sv' } + end + + execute 'kill old nginx process' do + command 'pkill nginx' + returns [0, 1] # ignores failures + not_if { !::File.exist?('/etc/sv/nginx/supervise/pid') || ::File.zero?('/etc/sv/nginx/supervise/pid') } + end + + # remove the old service configs + directory '/etc/sv/nginx' do + recursive true + action :delete + end +end diff --git a/cookbooks/nginx/resources/site.rb b/cookbooks/nginx/resources/site.rb new file mode 100644 index 0000000..65c8e0a --- /dev/null +++ b/cookbooks/nginx/resources/site.rb @@ -0,0 +1,79 @@ +# +# Cookbook:: nginx +# Resource:: site +# +# Author:: AJ Christensen +# Author:: Tim Smith +# +# Copyright:: 2008-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +property :site_name, String, name_property: true +property :variables, Hash, default: {} +property :cookbook, String +property :template, [String, Array] +property :enable, [String, true, false] + +action :enable do + # this is pretty evil, but gives us backwards compat with the old + # definition where there was an enable property vs a true action + if new_resource.enable + Chef::Log.warn('The "enable" property in nginx_site is deprecated. Use "action :enable" instead.') + elsif new_resource.enable == false || new_resource.enable == 'false' + Chef::Log.warn('The "enable" property in nginx_site is deprecated. Use "action :disable" instead.') + action_disable + return # don't perform the actual enable action afterwards + end + + if new_resource.template + # use declare_resource so we can have a property also named template + declare_resource(:template, "#{node['nginx']['dir']}/sites-available/#{new_resource.site_name}") do + source new_resource.template + cookbook new_resource.cookbook + variables(new_resource.variables) + notifies :reload, 'service[nginx]' + end + end + + execute "nxensite #{new_resource.site_name}" do + command "#{node['nginx']['script_dir']}/nxensite #{new_resource.site_name}" + notifies :reload, 'service[nginx]' + not_if do + ::File.symlink?("#{node['nginx']['dir']}/sites-enabled/#{new_resource.site_name}") || + ::File.symlink?("#{node['nginx']['dir']}/sites-enabled/000-#{new_resource.site_name}") + end + end +end + +action :disable do + execute "nxdissite #{new_resource.site_name}" do + command "#{node['nginx']['script_dir']}/nxdissite #{new_resource.site_name}" + notifies :reload, 'service[nginx]' + only_if do + ::File.symlink?("#{node['nginx']['dir']}/sites-enabled/#{new_resource.site_name}") || + ::File.symlink?("#{node['nginx']['dir']}/sites-enabled/000-#{new_resource.site_name}") + end + end + + # The nginx.org packages store the default site at /etc/nginx/conf.d/default.conf and our + # normal script doesn't disable these. + if new_resource.site_name == 'default' && ::File.exist?('/etc/nginx/conf.d/default.conf') # ~FC023 + execute 'Move nginx.org package default site config to sites-available' do + command "mv /etc/nginx/conf.d/default.conf #{node['nginx']['dir']}/sites-available/default" + user 'root' + notifies :reload, 'service[nginx]' + end + end +end diff --git a/cookbooks/nginx/resources/stream.rb b/cookbooks/nginx/resources/stream.rb new file mode 100644 index 0000000..06ab35c --- /dev/null +++ b/cookbooks/nginx/resources/stream.rb @@ -0,0 +1,65 @@ +# +# Cookbook:: nginx +# Resource:: stream +# +# Copyright:: 2017-2018, David Sieciński +# +# 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. +# + +property :stream_name, String, name_property: true +property :variables, Hash, default: {} +property :cookbook, String +property :template, [String, Array] + +action :enable do + if new_resource.template + # use declare_resource so we can have a property also named template + declare_resource(:template, "#{node['nginx']['dir']}/streams-available/#{new_resource.stream_name}") do + source new_resource.template + cookbook new_resource.cookbook + variables(new_resource.variables) + notifies :reload, 'service[nginx]' + end + end + + execute "nxenstream #{new_resource.stream_name}" do + command "#{node['nginx']['script_dir']}/nxenstream #{new_resource.stream_name}" + notifies :reload, 'service[nginx]' + not_if do + ::File.symlink?("#{node['nginx']['dir']}/streams-enabled/#{new_resource.stream_name}") || + ::File.symlink?("#{node['nginx']['dir']}/streams-enabled/000-#{new_resource.stream_name}") + end + end +end + +action :disable do + execute "nxdisstream #{new_resource.stream_name}" do + command "#{node['nginx']['script_dir']}/nxdisstream #{new_resource.stream_name}" + notifies :reload, 'service[nginx]' + only_if do + ::File.symlink?("#{node['nginx']['dir']}/streams-enabled/#{new_resource.stream_name}") || + ::File.symlink?("#{node['nginx']['dir']}/streams-enabled/000-#{new_resource.stream_name}") + end + end + + # The nginx.org packages store the default stream at /etc/nginx/conf.d/default.conf and our + # normal script doesn't disable these. + if new_resource.stream_name == 'default' && ::File.exist?('/etc/nginx/conf.d/default.conf') # ~FC023 + execute 'Move nginx.org package default stream config to streams-available' do + command "mv /etc/nginx/conf.d/default.conf #{node['nginx']['dir']}/streams-available/default" + user 'root' + notifies :reload, 'service[nginx]' + end + end +end diff --git a/cookbooks/nginx/templates/debian/nginx.init.erb b/cookbooks/nginx/templates/debian/nginx.init.erb new file mode 100755 index 0000000..f058d78 --- /dev/null +++ b/cookbooks/nginx/templates/debian/nginx.init.erb @@ -0,0 +1,97 @@ +#!/bin/sh + +### BEGIN INIT INFO +# Provides: nginx +# Required-Start: $local_fs $remote_fs $network $syslog +# Required-Stop: $local_fs $remote_fs $network $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: starts the nginx web server +# Description: starts nginx using start-stop-daemon +### END INIT INFO + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=<%= node['nginx']['binary'] %> +NAME=nginx +DESC=nginx +PID=<%= @pid_file %> + +# Include nginx defaults if available +if [ -f /etc/default/nginx ]; then + . /etc/default/nginx +fi + +test -x $DAEMON || exit 0 + +set -e + +. /lib/lsb/init-functions + +test_nginx_config() { + if $DAEMON -t $DAEMON_OPTS >/dev/null 2>&1; then + return 0 + else + $DAEMON -t $DAEMON_OPTS + return $? + fi +} + +case "$1" in + start) + echo -n "Starting $DESC: " + test_nginx_config + # Check if the ULIMIT is set in /etc/default/nginx + if [ -n "$ULIMIT" ]; then + # Set the ulimits + ulimit $ULIMIT + fi + start-stop-daemon --start --quiet --pidfile $PID \ + --exec $DAEMON -- $DAEMON_OPTS || true + echo "$NAME." + ;; + + stop) + echo -n "Stopping $DESC: " + start-stop-daemon --stop --quiet --pidfile $PID \ + --exec $DAEMON || true + echo "$NAME." + ;; + + restart|force-reload) + echo -n "Restarting $DESC: " + start-stop-daemon --stop --quiet --pidfile \ + $PID --exec $DAEMON || true + sleep 1 + test_nginx_config + start-stop-daemon --start --quiet --pidfile \ + $PID --exec $DAEMON -- $DAEMON_OPTS || true + echo "$NAME." + ;; + + reload) + echo -n "Reloading $DESC configuration: " + test_nginx_config + start-stop-daemon --stop --signal HUP --quiet --pidfile $PID \ + --exec $DAEMON || true + echo "$NAME." + ;; + + configtest|testconfig) + echo -n "Testing $DESC configuration: " + if test_nginx_config; then + echo "$NAME." + else + exit $? + fi + ;; + + status) + status_of_proc -p $PID "$DAEMON" nginx && exit 0 || exit $? + ;; + *) + echo "Usage: $NAME {start|stop|restart|reload|force-reload|status|configtest}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/cookbooks/nginx/templates/default/default-site.erb b/cookbooks/nginx/templates/default/default-site.erb new file mode 100644 index 0000000..e76812e --- /dev/null +++ b/cookbooks/nginx/templates/default/default-site.erb @@ -0,0 +1,11 @@ +server { + listen <%= node['nginx']['port'] -%>; + server_name <%= node['hostname'] %>; + + access_log <%= node['nginx']['log_dir'] %>/localhost.access.log; + + location / { + root <%= node['nginx']['default_root'] %>; + index index.html index.htm; + } +} diff --git a/cookbooks/nginx/templates/default/modules/authorized_ip.erb b/cookbooks/nginx/templates/default/modules/authorized_ip.erb new file mode 100644 index 0000000..159f27e --- /dev/null +++ b/cookbooks/nginx/templates/default/modules/authorized_ip.erb @@ -0,0 +1,6 @@ +geo $<%= node['nginx']['remote_ip_var'] %> $authorized_ip { + default no; + <% node['nginx']['authorized_ips'].each do |ip| %> + <%= "#{ip} yes;" %> + <% end %> +} diff --git a/cookbooks/nginx/templates/default/modules/http_geoip.conf.erb b/cookbooks/nginx/templates/default/modules/http_geoip.conf.erb new file mode 100644 index 0000000..f1ce82a --- /dev/null +++ b/cookbooks/nginx/templates/default/modules/http_geoip.conf.erb @@ -0,0 +1,4 @@ +geoip_country <%= @country_dat %>; +<% if @city_dat -%> +geoip_city <%= @city_dat %>; +<% end -%> diff --git a/cookbooks/nginx/templates/default/modules/http_gzip_static.conf.erb b/cookbooks/nginx/templates/default/modules/http_gzip_static.conf.erb new file mode 100644 index 0000000..360d46e --- /dev/null +++ b/cookbooks/nginx/templates/default/modules/http_gzip_static.conf.erb @@ -0,0 +1 @@ +gzip_static <%= node['nginx']['gzip_static'] %>; diff --git a/cookbooks/nginx/templates/default/modules/http_realip.conf.erb b/cookbooks/nginx/templates/default/modules/http_realip.conf.erb new file mode 100644 index 0000000..0979fd4 --- /dev/null +++ b/cookbooks/nginx/templates/default/modules/http_realip.conf.erb @@ -0,0 +1,5 @@ +<% node['nginx']['realip']['addresses'].each do |address| -%> +set_real_ip_from <%= address %>; +<% end -%> +real_ip_header <%= node['nginx']['realip']['header'] %>; +real_ip_recursive <%= node['nginx']['realip']['real_ip_recursive'] %>; diff --git a/cookbooks/nginx/templates/default/modules/nginx_status.erb b/cookbooks/nginx/templates/default/modules/nginx_status.erb new file mode 100644 index 0000000..eeb6ab5 --- /dev/null +++ b/cookbooks/nginx/templates/default/modules/nginx_status.erb @@ -0,0 +1,18 @@ +include authorized_ip; + +server { + listen <%= node['nginx']['status']['port'] %>; + server_name _; + + location /nginx_status { + if ($authorized_ip = no) { + return 404; + } + stub_status on; + access_log off; + } + + location / { + return 404; + } +} diff --git a/cookbooks/nginx/templates/default/modules/passenger.conf.erb b/cookbooks/nginx/templates/default/modules/passenger.conf.erb new file mode 100644 index 0000000..1de3720 --- /dev/null +++ b/cookbooks/nginx/templates/default/modules/passenger.conf.erb @@ -0,0 +1,17 @@ +passenger_root <%= node['nginx']['passenger']['root'] %>; +passenger_ruby <%= node['nginx']['passenger']['ruby'] %>; +passenger_max_pool_size <%= node['nginx']['passenger']['max_pool_size'] %>; +passenger_spawn_method <%= node['nginx']['passenger']['spawn_method'] %>; +passenger_buffer_response <%= node['nginx']['passenger']['buffer_response'] %>; +passenger_min_instances <%= node['nginx']['passenger']['min_instances'] %>; +passenger_max_instances_per_app <%= node['nginx']['passenger']['max_instances_per_app'] %>; +passenger_pool_idle_time <%= node['nginx']['passenger']['pool_idle_time'] %>; +passenger_max_requests <%= node['nginx']['passenger']['max_requests'] %>; +passenger_show_version_in_header <%= node['nginx']['passenger']['show_version_in_header'] %>; +<%- if node['nginx']['passenger']['passenger_log_file'] %> + passenger_log_file <%= node['nginx']['passenger']['passenger_log_file'] %>; +<% end %> + +<%- if node['nginx']['passenger']['nodejs'] %> + passenger_nodejs <%= node['nginx']['passenger']['nodejs'] %>; +<% end %> diff --git a/cookbooks/nginx/templates/default/modules/socketproxy.conf.erb b/cookbooks/nginx/templates/default/modules/socketproxy.conf.erb new file mode 100644 index 0000000..60cb2e3 --- /dev/null +++ b/cookbooks/nginx/templates/default/modules/socketproxy.conf.erb @@ -0,0 +1,89 @@ + server { + + set $app_home <%= node['nginx']['socketproxy']['root'] %>; + + <% if node['nginx']['sts_max_age'] -%> + add_header Strict-Transport-Security "max-age=<%= node['nginx']['sts_max_age'] %>"; + <% end -%> + + listen <%= node['nginx']['port'] %> default; + + access_log <%= node['nginx']['log_dir'] %>/<%= node['nginx']['socketproxy']['logname'] %>.access.log<% if node['nginx']['access_log_options'] %> <%= node['nginx']['access_log_options'] %><% end %>; + error_log <%= node['nginx']['log_dir'] %>/<%= node['nginx']['socketproxy']['logname'] %>.error.log <%= node['nginx']['socketproxy']['log_level'] %>; + + <% if node['nginx']['server_name'] -%> + server_name ~^<%= node['nginx']['server_name'] %>\..*$; + <% end -%> + + client_max_body_size 4G; + keepalive_timeout 5; + + root $app_home/<%= node['nginx']['socketproxy']['default_app'] %>/<%= node['nginx']['socketproxy']['apps'][node['nginx']['socketproxy']['default_app']]['subdir'] %>/public; + + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; + + if ($request_method !~ ^(GET|HEAD|PUT|POST|DELETE|OPTIONS|PATCH)$ ) { + return 405; + } + + <% node['nginx']['socketproxy']['apps'].each do |app, app_conf| + if app_conf['context_name'] + base_loc = "/#{app_conf['context_name'].gsub(/^\/+/,'').gsub(/\/+$/,'')}" + else + base_loc = "" + end + -%> + + location ~ "^<%= base_loc %>/assets/(.*/)*.*-[0-9a-f]{32}.*" { + gzip_static on; + expires max; + add_header Cache-Control public; + } + + location ^~ /<%= app_conf['context_name'] %> { + + alias $app_home/<%= app %>/<%= app_conf['subdir'] %>/public/; + + try_files $uri/index.html $uri.html $uri @app_<%= app %>; + error_page 404 /404.html; + error_page 422 /422.html; + error_page 500 502 503 504 /500.html; + error_page 403 /403.html; + + } + + location @app_<%= app %> { + + proxy_read_timeout 600; + <% + if app_conf['socket']['type'] + case app_conf['socket']['type'] + when 'unix' + -%> + proxy_pass http://unix:$app_home/<%= app %>/<%= app_conf['socket']['path'] %><% if app_conf['prepend_slash'] %>:/<% end %>; + <% + when 'tcp' + -%> + proxy_pass http://localhost:<%= app_conf['socket']['port'] -%>; + <% + end + else + -%> + proxy_pass http://unix:$app_home/<%= app %>/<%= app_conf['socket_path'] %><% if app_conf['prepend_slash'] %>:/<% end %>; + <% + end + -%> + + } + + <% end # node['nginx']['socketproxy']['apps'].each -%> + + error_page 500 502 504 /50x.html; + location = /50x.html { + root html; + } + +} diff --git a/cookbooks/nginx/templates/default/modules/upload_progress.erb b/cookbooks/nginx/templates/default/modules/upload_progress.erb new file mode 100644 index 0000000..39387d2 --- /dev/null +++ b/cookbooks/nginx/templates/default/modules/upload_progress.erb @@ -0,0 +1,4 @@ +upload_progress <%= node['nginx']['upload_progress']['zone_name'] -%> <%= node['nginx']['upload_progress']['zone_size'] -%>; +<% if node['nginx']['upload_progress']['javascript_output'] -%> +upload_progress_java_output; +<% end -%> diff --git a/cookbooks/nginx/templates/default/nginx-upstart.conf.erb b/cookbooks/nginx/templates/default/nginx-upstart.conf.erb new file mode 100644 index 0000000..9ebafda --- /dev/null +++ b/cookbooks/nginx/templates/default/nginx-upstart.conf.erb @@ -0,0 +1,39 @@ +# nginx + +description "nginx http daemon" + +start on (local-filesystems and net-device-up IFACE=lo and runlevel [<%= node['nginx']['upstart']['runlevels'] %>]) +stop on runlevel [!<%= node['nginx']['upstart']['runlevels'] %>] + +env DAEMON=<%= node['nginx']['binary'] %> +env PID=<%= @pid_file %> +env CONFIG=<%= node['nginx']['source']['conf_path'] %> + +respawn +<% if node['nginx']['upstart']['respawn_limit'] -%> +respawn limit <%= node['nginx']['upstart']['respawn_limit'] %> +<% end -%> + +pre-start script + ${DAEMON} -t + if [ $? -ne 0 ]; then + exit $? + fi +end script + +<% unless node['nginx']['upstart']['foreground'] -%> +expect fork +<% else -%> +console output +<% end -%> + +exec ${DAEMON} -c "${CONFIG}" + +<% if node.recipe?('nginx::passenger') && !node['nginx']['upstart']['foreground'] -%> +# classic example of why pidfiles should have gone away +# with the advent of fork(). we missed that bus a long +# time ago so hack around it. +post-stop script + start-stop-daemon --stop --pidfile ${PID} --name nginx --exec ${DAEMON} --signal QUIT +end script +<% end -%> diff --git a/cookbooks/nginx/templates/default/nginx.conf.erb b/cookbooks/nginx/templates/default/nginx.conf.erb new file mode 100644 index 0000000..02e5b53 --- /dev/null +++ b/cookbooks/nginx/templates/default/nginx.conf.erb @@ -0,0 +1,129 @@ +user <%= node['nginx']['user'] %><% if node['nginx']['user'] != node['nginx']['group'] %> <%= node['nginx']['group'] %><% end %>; +worker_processes <%= node['nginx']['worker_processes'] %>; +<% if node['nginx']['daemon_disable'] -%> +daemon off; +<% end -%> +<% if node['nginx']['worker_rlimit_nofile'] -%> +worker_rlimit_nofile <%= node['nginx']['worker_rlimit_nofile'] %>; +<% end -%> +<% if node['nginx']['worker_shutdown_timeout'] -%> +worker_shutdown_timeout <%= node['nginx']['worker_shutdown_timeout'] %>; +<% end -%> +<% node['nginx']['load_modules'].each do |module_to_load| %> +load_module <%= module_to_load %>; +<% end -%> +<% if node['platform'] == 'ubuntu' && node['platform_version'].to_i >= 18 %> +include /etc/nginx/modules-enabled/*.conf; +<% end -%> + +error_log <%= node['nginx']['log_dir'] %>/error.log<% if node['nginx']['error_log_options'] %> <%= node['nginx']['error_log_options'] %><% end %>; +pid <%= @pid_file %>; +events { + worker_connections <%= node['nginx']['worker_connections'] %>; +<% if node['nginx']['multi_accept'] -%> + multi_accept on; +<% end -%> +<% if node['nginx']['event'] -%> + use <%= node['nginx']['event'] %>; +<% end -%> +<% if node['nginx']['accept_mutex_delay'] -%> + accept_mutex_delay <%= node['nginx']['accept_mutex_delay'] %>ms; +<% end -%> +} + +http { + <% if node.recipe?('nginx::naxsi_module') %> + include <%= node['nginx']['dir'] %>/naxsi_core.rules; + <% end %> + + include <%= node['nginx']['dir'] %>/mime.types; + default_type application/octet-stream; + charset_types text/css text/plain text/vnd.wap.wml application/javascript application/json application/rss+xml application/xml; + + <% node['nginx']['log_formats'].each do |name, format| %> + log_format <%= name %> <%= format %>; + <% end -%> + + <% if node['nginx']['disable_access_log'] -%> + access_log off; + <% else -%> + access_log <%= node['nginx']['log_dir'] %>/access.log<% if node['nginx']['access_log_options'] %> <%= node['nginx']['access_log_options'] %><% end %>; + <% end %> + <% if node['nginx']['server_tokens'] -%> + server_tokens <%= node['nginx']['server_tokens'] %>; + <% end -%> + + sendfile <%= node['nginx']['sendfile'] %>; + tcp_nopush <%= node['nginx']['tcp_nopush'] %>; + tcp_nodelay <%= node['nginx']['tcp_nodelay'] %>; + + <% if node['nginx']['keepalive'] == 'on' %> + keepalive_requests <%= node['nginx']['keepalive_requests'] %>; + keepalive_timeout <%= node['nginx']['keepalive_timeout'] %>; + <% end %> + + <% unless node['nginx']['underscores_in_headers'].nil? %> + underscores_in_headers <%= node['nginx']['underscores_in_headers'] %>; + <% end %> + + gzip <%= node['nginx']['gzip'] %>; + <% if node['nginx']['gzip'] == 'on' %> + gzip_http_version <%= node['nginx']['gzip_http_version'] %>; + gzip_comp_level <%= node['nginx']['gzip_comp_level'] %>; + gzip_proxied <%= node['nginx']['gzip_proxied'] %>; + gzip_vary <%= node['nginx']['gzip_vary'] %>; + <% if node['nginx']['gzip_buffers'] -%> + gzip_buffers <%= node['nginx']['gzip_buffers'] %>; + <% end -%> + gzip_types <%= node['nginx']['gzip_types'].join(' ') %>; + gzip_min_length <%= node['nginx']['gzip_min_length'] %>; + gzip_disable "<%= node['nginx']['gzip_disable'] %>"; + <% end %> + + + variables_hash_max_size <%= node['nginx']['variables_hash_max_size'] %>; + variables_hash_bucket_size <%= node['nginx']['variables_hash_bucket_size'] %>; + server_names_hash_bucket_size <%= node['nginx']['server_names_hash_bucket_size'] %>; + types_hash_max_size <%= node['nginx']['types_hash_max_size'] %>; + types_hash_bucket_size <%= node['nginx']['types_hash_bucket_size'] %>; + <% if node['nginx']['proxy_read_timeout'] -%> + proxy_read_timeout <%= node['nginx']['proxy_read_timeout'] %>; + <% end -%> + <% if node['nginx']['client_body_buffer_size'] -%> + client_body_buffer_size <%= node['nginx']['client_body_buffer_size'] %>; + <% end -%> + <% if node['nginx']['client_max_body_size'] -%> + client_max_body_size <%= node['nginx']['client_max_body_size'] %>; + <% end -%> + <% if node['nginx']['large_client_header_buffers'] -%> + large_client_header_buffers <%= node['nginx']['large_client_header_buffers'] %>; + <% end -%> + <% if node['nginx']['map_hash_max_size'] -%> + map_hash_max_size <%= node['nginx']['map_hash_max_size'] %>; + <% end -%> + <% if node['nginx']['proxy_buffer_size'] -%> + proxy_buffer_size <%= node['nginx']['proxy_buffer_size'] %>; + <% end -%> + <% if node['nginx']['proxy_buffers'] -%> + proxy_buffers <%= node['nginx']['proxy_buffers'] %>; + <% end -%> + <% if node['nginx']['proxy_busy_buffers_size'] -%> + proxy_busy_buffers_size <%= node['nginx']['proxy_busy_buffers_size'] %>; + <% end -%> + + <% if node['nginx']['enable_rate_limiting'] -%> + limit_req_zone $binary_remote_addr zone=<%= node['nginx']['rate_limiting_zone_name'] %>:<%= node['nginx']['rate_limiting_backoff'] %> rate=<%= node['nginx']['rate_limit'] %>; + <% end -%> + + <% node['nginx']['extra_configs'].each do |key, value| -%> + <%= key %> <%= value %>; + <% end -%> + + include <%= node['nginx']['dir'] %>/conf.d/*.conf; + include <%= node['nginx']['dir'] %>/sites-enabled/*; +} +<% if node['nginx']['install_method'] == 'source' and node['nginx']['configure_flags'].include? '--with-stream' %> +stream{ + include <%= node['nginx']['dir'] %>/streams-enabled/*; +} +<% end %> diff --git a/cookbooks/nginx/templates/default/nginx.init.erb b/cookbooks/nginx/templates/default/nginx.init.erb new file mode 100644 index 0000000..db945ad --- /dev/null +++ b/cookbooks/nginx/templates/default/nginx.init.erb @@ -0,0 +1,111 @@ +#!/bin/sh +# +# nginx +# +# chkconfig: - 57 47 +# description: nginx +# processname: nginx +# config: /etc/sysconfig/nginx +# + +# Source function library. +. /etc/rc.d/init.d/functions + +# Source networking configuration. +. /etc/sysconfig/network + +# Check that networking is up. +[ "$NETWORKING" = "no" ] && exit +exec=<%= node['nginx']['binary'] %> +prog=$(basename $exec) + +# default options, overruled by items in sysconfig +NGINX_GLOBAL="" + +[ -e /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx + +lockfile=/var/lock/subsys/nginx + +start() { + [ -x $exec ] || exit 5 + echo -n $"Starting $prog: " + # if not running, start it up here, usually something like "daemon $exec" + options="" + if [ "${NGINX_GLOBAL}" != "" ]; then + options="-g ${NGINX_GLOBAL}" + fi + $exec $options + retval=$? + echo + [ $retval -eq 0 ] && touch $lockfile + return $retval +} + +stop() { + echo -n $"Stopping $prog: " + $exec -s stop + retval=$? + echo + [ $retval -eq 0 ] && rm -f $lockfile + return $retval +} + +restart() { + stop + start +} + +reload() { + echo -n $"Reloading $prog: " + $exec -s reload + retval=$? + echo + [ $retval -eq 0 ] && rm -f $lockfile + return $retval +} + +configtest() { + if [ "$#" -ne 0 ] ; then + case "$1" in + -q) + FLAG=$1 + ;; + *) + ;; + esac + shift + fi + ${exec} -t $FLAG + RETVAL=$? + return $RETVAL +} + +# See how we were called. +case "$1" in + start) + start + ;; + stop) + stop + ;; + status) + status nginx + ;; + restart) + restart + ;; + reload|force-reload) + reload + ;; + condrestart) + [ -f $lockfile ] && restart || : + ;; + configtest) + configtest + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|reload|force-reload|condrestart|configtest}" + exit 1 +esac + +exit $? diff --git a/cookbooks/nginx/templates/default/nginx.service.erb b/cookbooks/nginx/templates/default/nginx.service.erb new file mode 100644 index 0000000..c187ad6 --- /dev/null +++ b/cookbooks/nginx/templates/default/nginx.service.erb @@ -0,0 +1,13 @@ +[Unit] +Description=The nginx HTTP and reverse proxy server +After=network.target remote-fs.target nss-lookup.target + +[Service] +ExecStartPre=<%= node['nginx']['binary'] %> -t +ExecStart=<%= node['nginx']['binary'] %> +ExecReload=/bin/kill -s HUP $MAINPID +ExecStop=/bin/kill -s QUIT $MAINPID +PrivateTmp=true + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/cookbooks/nginx/templates/default/nginx.sysconfig.erb b/cookbooks/nginx/templates/default/nginx.sysconfig.erb new file mode 100644 index 0000000..6b8834f --- /dev/null +++ b/cookbooks/nginx/templates/default/nginx.sysconfig.erb @@ -0,0 +1,2 @@ +NGINX_GLOBAL=<%= node['nginx']['global'] %> +ULIMIT="-n <%= node['nginx']['ulimit'] %>" diff --git a/cookbooks/nginx/templates/default/nxdissite.erb b/cookbooks/nginx/templates/default/nxdissite.erb new file mode 100644 index 0000000..8ba676b --- /dev/null +++ b/cookbooks/nginx/templates/default/nxdissite.erb @@ -0,0 +1,29 @@ +#!/bin/sh -e + +SYSCONFDIR='<%= node['nginx']['dir'] %>' + +if [ -z $1 ]; then + echo "Which site would you like to disable?" + echo -n "Your choices are: " + ls $SYSCONFDIR/sites-enabled/* | \ + sed -e "s,$SYSCONFDIR/sites-enabled/,,g" | xargs echo + echo -n "Site name? " + read SITENAME +else + SITENAME=$1 +fi + +if [ $SITENAME = "default" ]; then + PRIORITY="000" +fi + +if ! [ -e $SYSCONFDIR/sites-enabled/$SITENAME -o \ + -e $SYSCONFDIR/sites-enabled/"$PRIORITY"-"$SITENAME" ]; then + echo "This site is already disabled, or does not exist!" + exit 1 +fi + +if ! rm $SYSCONFDIR/sites-enabled/$SITENAME 2>/dev/null; then + rm -f $SYSCONFDIR/sites-enabled/"$PRIORITY"-"$SITENAME" +fi +echo "Site $SITENAME disabled; reload nginx to disable." diff --git a/cookbooks/nginx/templates/default/nxdisstream.erb b/cookbooks/nginx/templates/default/nxdisstream.erb new file mode 100644 index 0000000..eb9f05f --- /dev/null +++ b/cookbooks/nginx/templates/default/nxdisstream.erb @@ -0,0 +1,29 @@ +#!/bin/sh -e + +SYSCONFDIR='<%= node['nginx']['dir'] %>' + +if [ -z $1 ]; then + echo "Which stream would you like to disable?" + echo -n "Your choices are: " + ls $SYSCONFDIR/streams-enabled/* | \ + sed -e "s,$SYSCONFDIR/streams-enabled/,,g" | xargs echo + echo -n "Stream name? " + read STREAMNAME +else + STREAMNAME=$1 +fi + +if [ $STREAMNAME = "default" ]; then + PRIORITY="000" +fi + +if ! [ -e $SYSCONFDIR/streams-enabled/$STREAMNAME -o \ + -e $SYSCONFDIR/streams-enabled/"$PRIORITY"-"$STREAMNAME" ]; then + echo "This Stream is already disabled, or does not exist!" + exit 1 +fi + +if ! rm $SYSCONFDIR/streams-enabled/$STREAMNAME 2>/dev/null; then + rm -f $SYSCONFDIR/streams-enabled/"$PRIORITY"-"$STREAMNAME" +fi +echo "Stream $STREAMNAME disabled; reload nginx to disable." diff --git a/cookbooks/nginx/templates/default/nxensite.erb b/cookbooks/nginx/templates/default/nxensite.erb new file mode 100644 index 0000000..31a3c84 --- /dev/null +++ b/cookbooks/nginx/templates/default/nxensite.erb @@ -0,0 +1,38 @@ +#!/bin/sh -e + +SYSCONFDIR='<%= node['nginx']['dir'] %>' + +if [ -z $1 ]; then + echo "Which site would you like to enable?" + echo -n "Your choices are: " + ls $SYSCONFDIR/sites-available/* | \ + sed -e "s,$SYSCONFDIR/sites-available/,,g" | xargs echo + echo -n "Site name? " + read SITENAME +else + SITENAME=$1 +fi + +if [ $SITENAME = "default" ]; then + PRIORITY="000" +fi + +if [ -e $SYSCONFDIR/sites-enabled/$SITENAME -o \ + -e $SYSCONFDIR/sites-enabled/"$PRIORITY"-"$SITENAME" ]; then + echo "This site is already enabled!" + exit 0 +fi + +if ! [ -e $SYSCONFDIR/sites-available/$SITENAME ]; then + echo "This site does not exist!" + exit 1 +fi + +if [ $SITENAME = "default" ]; then + ln -sf $SYSCONFDIR/sites-available/$SITENAME \ + $SYSCONFDIR/sites-enabled/"$PRIORITY"-"$SITENAME" +else + ln -sf $SYSCONFDIR/sites-available/$SITENAME $SYSCONFDIR/sites-enabled/$SITENAME +fi + +echo "Site $SITENAME installed; reload nginx to enable." diff --git a/cookbooks/nginx/templates/default/nxenstream.erb b/cookbooks/nginx/templates/default/nxenstream.erb new file mode 100644 index 0000000..03ee044 --- /dev/null +++ b/cookbooks/nginx/templates/default/nxenstream.erb @@ -0,0 +1,38 @@ +#!/bin/sh -e + +SYSCONFDIR='<%= node['nginx']['dir'] %>' + +if [ -z $1 ]; then + echo "Which stream would you like to enable?" + echo -n "Your choices are: " + ls $SYSCONFDIR/streams-available/* | \ + sed -e "s,$SYSCONFDIR/streams-available/,,g" | xargs echo + echo -n "Stream name? " + read STREAMNAME +else + STREAMNAME=$1 +fi + +if [ $STREAMNAME = "default" ]; then + PRIORITY="000" +fi + +if [ -e $SYSCONFDIR/streams-enabled/$STREAMNAME -o \ + -e $SYSCONFDIR/streams-enabled/"$PRIORITY"-"$STREAMNAME" ]; then + echo "This stream is already enabled!" + exit 0 +fi + +if ! [ -e $SYSCONFDIR/streams-available/$STREAMNAME ]; then + echo "This stream does not exist!" + exit 1 +fi + +if [ $STREAMNAME = "default" ]; then + ln -sf $SYSCONFDIR/streams-available/$STREAMNAME \ + $SYSCONFDIR/streams-enabled/"$PRIORITY"-"$STREAMNAME" +else + ln -sf $SYSCONFDIR/streams-available/$STREAMNAME $SYSCONFDIR/streams-enabled/$STREAMNAME +fi + +echo "Stream $STREAMNAME installed; reload nginx to enable." diff --git a/cookbooks/nginx/templates/default/plugins/ohai-nginx.rb.erb b/cookbooks/nginx/templates/default/plugins/ohai-nginx.rb.erb new file mode 100644 index 0000000..a66d65e --- /dev/null +++ b/cookbooks/nginx/templates/default/plugins/ohai-nginx.rb.erb @@ -0,0 +1,82 @@ +# +# Author:: Jamie Winsor () +# +# Copyright 2012, Riot Games +# +# 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. +# + +Ohai.plugin(:Nginx) do + provides "nginx" + provides "nginx/version" + provides "nginx/configure_arguments" + provides "nginx/prefix" + provides "nginx/conf_path" + + def parse_flags(flags) + prefix = nil + conf_path = nil + + flags.each do |flag| + case flag + when /^--prefix=(.+)$/ + prefix = Regexp.last_match(1) + when /^--conf-path=(.+)$/ + conf_path = Regexp.last_match(1) + end + end + + [prefix, conf_path] + end + + collect_data do + nginx Mash.new unless nginx + # if we fail we should still have these values to avoid nil class errors + # if people try to use them + nginx[:version] = nil unless nginx[:version] + nginx[:configure_arguments] = [] unless nginx[:configure_arguments] + nginx[:prefix] = nil unless nginx[:prefix] + nginx[:conf_path] = nil unless nginx[:conf_path] + + begin + so = shell_out("<%= @binary %> -V") + # Sample output: + # nginx version: nginx/1.10.1 + # built by clang 7.3.0 (clang-703.0.31) + # built with OpenSSL 1.0.2h 3 May 2016 + # TLS SNI support enabled + # configure arguments: --prefix=/usr/local/Cellar/nginx/1.10.1 --with-http_ssl_module --with-pcre --with-ipv6 --sbin-path=/usr/local/Cellar/nginx/1.10.1/bin/nginx --with-cc-opt='-I/usr/local/Cellar/pcre/8.38/include -I/usr/local/Cellar/openssl/1.0.2h_1/include' --with-ld-opt='-L/usr/local/Cellar/pcre/8.38/lib -L/usr/local/Cellar/openssl/1.0.2h_1/lib' --conf-path=/usr/local/etc/nginx/nginx.conf --pid-path=/usr/local/var/run/nginx.pid --lock-path=/usr/local/var/run/nginx.lock --http-client-body-temp-path=/usr/local/var/run/nginx/client_body_temp --http-proxy-temp-path=/usr/local/var/run/nginx/proxy_temp --http-fastcgi-temp-path=/usr/local/var/run/nginx/fastcgi_temp --http-uwsgi-temp-path=/usr/local/var/run/nginx/uwsgi_temp --http-scgi-temp-path=/usr/local/var/run/nginx/scgi_temp --http-log-path=/usr/local/var/log/nginx/access.log --error-log-path=/usr/local/var/log/nginx/error.log --with-http_gzip_static_module + + if so.exitstatus == 0 + so.stderr.split("\n").each do |line| + case line + when /^configure arguments:(.+)/ + # This could be better: I'm splitting on configure arguments which removes them and also + # adds a blank string at index 0 of the array. This is why we drop index 0 and map to + # add the '--' prefix back to the configure argument. + nginx[:configure_arguments] = Regexp.last_match(1).split(/\s--(?!param)/).drop(1).map { |ca| "--#{ca}" } + + prefix, conf_path = parse_flags(nginx[:configure_arguments]) + + nginx[:prefix] = prefix + nginx[:conf_path] = conf_path + when /^nginx version: nginx\/(\d+\.\d+\.\d+)/ + nginx[:version] = Regexp.last_match(1) + end + end + end + rescue + Ohai::Log.debug('Nginx plugin: Could not shell_out "<%= @binary %> -V"') + end + end +end diff --git a/cookbooks/nginx/templates/default/sv-nginx-log-run.erb b/cookbooks/nginx/templates/default/sv-nginx-log-run.erb new file mode 100644 index 0000000..a79a518 --- /dev/null +++ b/cookbooks/nginx/templates/default/sv-nginx-log-run.erb @@ -0,0 +1,2 @@ +#!/bin/sh +exec svlogd -tt ./main diff --git a/cookbooks/nginx/templates/default/sv-nginx-run.erb b/cookbooks/nginx/templates/default/sv-nginx-run.erb new file mode 100644 index 0000000..4367891 --- /dev/null +++ b/cookbooks/nginx/templates/default/sv-nginx-run.erb @@ -0,0 +1,4 @@ +#!/bin/sh +ulimit -n <%= node['nginx']['ulimit'] %> +exec 2>&1 +exec <%= node['nginx']['src_binary'] %> -c <%= node['nginx']['dir'] %>/nginx.conf diff --git a/cookbooks/nginx/templates/ubuntu/nginx.init.erb b/cookbooks/nginx/templates/ubuntu/nginx.init.erb new file mode 100755 index 0000000..f058d78 --- /dev/null +++ b/cookbooks/nginx/templates/ubuntu/nginx.init.erb @@ -0,0 +1,97 @@ +#!/bin/sh + +### BEGIN INIT INFO +# Provides: nginx +# Required-Start: $local_fs $remote_fs $network $syslog +# Required-Stop: $local_fs $remote_fs $network $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: starts the nginx web server +# Description: starts nginx using start-stop-daemon +### END INIT INFO + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=<%= node['nginx']['binary'] %> +NAME=nginx +DESC=nginx +PID=<%= @pid_file %> + +# Include nginx defaults if available +if [ -f /etc/default/nginx ]; then + . /etc/default/nginx +fi + +test -x $DAEMON || exit 0 + +set -e + +. /lib/lsb/init-functions + +test_nginx_config() { + if $DAEMON -t $DAEMON_OPTS >/dev/null 2>&1; then + return 0 + else + $DAEMON -t $DAEMON_OPTS + return $? + fi +} + +case "$1" in + start) + echo -n "Starting $DESC: " + test_nginx_config + # Check if the ULIMIT is set in /etc/default/nginx + if [ -n "$ULIMIT" ]; then + # Set the ulimits + ulimit $ULIMIT + fi + start-stop-daemon --start --quiet --pidfile $PID \ + --exec $DAEMON -- $DAEMON_OPTS || true + echo "$NAME." + ;; + + stop) + echo -n "Stopping $DESC: " + start-stop-daemon --stop --quiet --pidfile $PID \ + --exec $DAEMON || true + echo "$NAME." + ;; + + restart|force-reload) + echo -n "Restarting $DESC: " + start-stop-daemon --stop --quiet --pidfile \ + $PID --exec $DAEMON || true + sleep 1 + test_nginx_config + start-stop-daemon --start --quiet --pidfile \ + $PID --exec $DAEMON -- $DAEMON_OPTS || true + echo "$NAME." + ;; + + reload) + echo -n "Reloading $DESC configuration: " + test_nginx_config + start-stop-daemon --stop --signal HUP --quiet --pidfile $PID \ + --exec $DAEMON || true + echo "$NAME." + ;; + + configtest|testconfig) + echo -n "Testing $DESC configuration: " + if test_nginx_config; then + echo "$NAME." + else + exit $? + fi + ;; + + status) + status_of_proc -p $PID "$DAEMON" nginx && exit 0 || exit $? + ;; + *) + echo "Usage: $NAME {start|stop|restart|reload|force-reload|status|configtest}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/cookbooks/nodejs/CHANGELOG.md b/cookbooks/nodejs/CHANGELOG.md new file mode 100644 index 0000000..752de3f --- /dev/null +++ b/cookbooks/nodejs/CHANGELOG.md @@ -0,0 +1,161 @@ +# NodeJS Cookbook Changelog + +## 5.0.0 (2017-11-15) + +- nodejs_npm resource has been converted to a custom resource and renamed to npm_package. The existing resource name will continue to function, but over time code should be updated for the new name. This name change has been made so we can eventually merge this resource into the chef-client. +- compat_resource cookbook dependency has been removed and this cookbook instead requires Chef 12.14 or later +- Chef 13 compatibility has been resolved +- The npm_package resource now properly installs packages when the 'package' property is setA +- Speed up npm operations by only returning a list of the desired package instead of every npm package +- Speed up source installation by using multipackage install for the dependencies +- Remove the broken url_valid? helper which didn't work + +## 4.0.0 (2017-07-11) + +- Updated the cookbook to require Chef 12.1+ and the compat_resource cookbook +- Removed support for io.js which has merged back into the node.js project +- Removed the dependency on homebrew, yum-epel, and apt cookbooks +- Added node['nodejs']['manage_node'] attribute to use only cookbook's LWRP (required to manage node by nvm) +- Updated the default repository URLs to be the 6.X repos +- Added initial support for Suse and Amazon Linux +- Improved architecture detection to support aarch64 +- Improved readme with examples for fetching your own binaries +- Added installation of openssl and xz utilities that are needed for the binary install recipe +- Updated the cookbook license string to be an SPDX compliant string +- Set the minimum version of the ark cookbook to 2.0.2 in order to support Suse +- Updated the default version from 6.9.1 to 6.10.2 +- Switched to Delivery local mode for testing +- Added Integration testing in Travis CI with kitchen-dokken and ChefDK + +## 3.0.0 (2016-11-02) + +- Updated the default release to the nodejs 6.9.1\. This requires C++11 extensions to compile, which are only present in GCC 4.8+. Due to this RHEL 5/6 and Ubuntu 12.04 are not supported if using this version. +- Switched the download URLs to the .xz packages since the .tar.gz packages are no longer being created +- Improvements to the readme examples and requirements sections +- Removed installation of apt-transport-https and instead rely on an apt cookbook that will do the same +- Fixed the ChefSpec matchers +- Added Scientific, Oracle, and Amazon as supported distros in the metadata +- Added chef_version metadata +- Removed conflicts and suggests metadata which aren't implemented or recommended for use +- Removed Chef 10 compatibility code +- Switched Integration testing to Inspec from bats +- Added the Apache 2.0 license file to the repo +- Expanded Test Kitchen testing +- Switched from Rubocop to Cookstyle and resolved all warnings +- Switched Travis to testing using ChefDK + +## 2.4.4 + +- Use HTTPS prefix URLs for node download #98 +- Update NPM symlink when installing from source #105 +- Add support for NPM private modules #107 + +## v2.4.2 + +- Fix check version +- Support iojs package install + +## v2.4.0 + +- Move `npm_packages` to his own recipe +- Fix different race conditions when using direct recipe call +- Fix npm recipe + +## v2.3.2 + +- Fix package recipe + +## v2.3.0 + +- Support io.js. Use node['nodejs']['engine']. +- Add MacOS support via homebrew + +## v2.2.0 + +- Add node['nodejs']['keyserver'] +- Update arm checksum +- Fix `npm_packages` JSON + +## v2.1.0 + +- Use official nodesource repository +- Add node['nodejs']['npm_packages'] to install npm package with `default` recipe + +## v2.0.0 + +- Travis integration +- Gems updated +- Rewrite cookbook dependencies +- Added complete test-kitchen integration : Rake, rubocop, foodcritic, vagrant, bats testing ... +- Added NodeJS `install_method` option (sources, bins or packages) +- Added NPM `install_method` option (sources or packages) +- NPM version can now be chosen independently from nodejs' embedded version +- Added a `nodejs_npm` LWRP to manage, install and resolve NPM packages + +## v1.3.0 + +- update default versions to the latest: node - v0.10.15 and npm - v1.3.5 +- default to package installation of nodejs on smartos ([@wanelo-pair]) +- Add Raspberry pi support ([@robertkowalski]) + +## v1.2.0 + +- implement installation from package on RedHat - ([@vaskas]) + +## v1.1.3: + +- update default version of node to 0.10.13 - and npm - v1.3.4 ([@jodosha][]) + +## v1.1.2: + +- update default version of node to 0.10.2 - ([@bakins]) +- fully migrated to test-kitchen 1.alpha and vagrant 1.1.x/berkshelf 1.3.1 + +## v1.1.1: + +- update default versions to the latest: node - v0.10.0 and npm - v1.2.14 +- `make_thread` is now a real attribute - ([@ChrisLundquist]) + +## v1.1.0: + +- rewrite the package install; remove rpm support since there are no longer any packages available anywhere +- add support to install `legacy_packages` from ubuntu repo as well as the latest 0.10.x branch (this is default). + +## v1.0.4: + +- add support for binary installation method ([@JulesAU]) + +## v1.0.3: + +- unreleased + +## v1.0.2: + +- add smartos support for package install ([@sax]) +- support to compile with all processors available (default 2 if unknown) - ([@ChrisLundquist]) +- moved to `platform_family` syntax +- ensure npm recipe honours the 'source' or 'package' setting - ([@markbirbeck]) +- updated the default versions to the latest stable node/npm + +## v1.0.1: + +- fixed bug that prevented overwritting the node/npm versions (moved the `src_url`s as local variables instead of attributes) - ([@johannesbecker]) +- updated the default versions to the latest node/npm + +## v1.0.0: + +- added packages installation support ([@smith]) + +[@bakins]: https://github.com/bakins +[@chrislundquist]: https://github.com/ChrisLundquist +[@gmccue]: https://github.com/gmccue +[@johannesbecker]: https://github.com/johannesbecker +[@julesau]: https://github.com/JulesAU +[@markbirbeck]: https://github.com/markbirbeck +[@predominant]: https://github.com/predominant +[@robertkowalski]: https://github.com/robertkowalski +[@sax]: https://github.com/sax +[@sjlu]: https://github.com/sjlu +[@smith]: https://github.com/smith +[@vaskas]: https://github.com/vaskas +[@wanelo-pair]: https://github.com/wanelo-pair diff --git a/cookbooks/nodejs/README.md b/cookbooks/nodejs/README.md new file mode 100644 index 0000000..6aa7fc2 --- /dev/null +++ b/cookbooks/nodejs/README.md @@ -0,0 +1,199 @@ +# [nodejs-cookbook](https://github.com/redguide/nodejs) + +[![CK Version](http://img.shields.io/cookbook/v/nodejs.svg?branch=master)](https://supermarket.chef.io/cookbooks/nodejs) [![Build Status](https://img.shields.io/travis/redguide/nodejs.svg)](https://travis-ci.org/redguide/nodejs) [![Gitter chat](https://badges.gitter.im/redguide/nodejs.svg)](https://gitter.im/redguide/nodejs) + +Installs node.js/npm and includes a resource for managing npm packages + +## Requirements + +### Platforms + +- Debian/Ubuntu +- RHEL/CentOS/Scientific/Amazon/Oracle +- openSUSE + +Note: Source installs require GCC 4.8+, which is not included on older distro releases + +### Chef + +- Chef 12.14+ + +### Cookbooks + +- build-essential +- ark + +## Usage + +Include the nodejs recipe to install node on your system based on the default installation method: + +```chef +include_recipe "nodejs" +``` + +### Install methods + +#### Package + +Install node from packages: + +```chef +node['nodejs']['install_method'] = 'package' # Not necessary because it's the default +include_recipe "nodejs" +# Or +include_recipe "nodejs::nodejs_from_package" +``` + +By default this will setup deb/rpm repositories from nodesource.com, which include up to date NodeJS packages. If you prefer to use distro provided package you can disable this behavior by setting `node['nodejs']['install_repo']` to `false`. + +#### Binary + +Install node from official prebuilt binaries: + +```chef +node['nodejs']['install_method'] = 'binary' +include_recipe "nodejs" + +# Or +include_recipe "nodejs::nodejs_from_binary" + +# Or set a specific version of nodejs to be installed +node.default['nodejs']['install_method'] = 'binary' +node.default['nodejs']['version'] = '5.9.0' +node.default['nodejs']['binary']['checksum'] = '99c4136cf61761fac5ac57f80544140a3793b63e00a65d4a0e528c9db328bf40' + +# Or fetch the binary from your own location +node.default['nodejs']['install_method'] = 'binary' +node.default['nodejs']['binary']['url'] = 'https://s3.amazonaws.com/my-bucket/node-v7.8.0-linux-x64.tar.gz' +node.default['nodejs']['binary']['checksum'] = '0bd86f2a39221b532172c7d1acb57f0b0cba88c7b82ea74ba9d1208b9f6f9697' +``` + +#### Source + +Install node from sources: + +```chef +node['nodejs']['install_method'] = 'source' +include_recipe "nodejs" +# Or +include_recipe "nodejs::nodejs_from_source" +``` + +## NPM + +Npm is included in nodejs installs by default. By default, we are using it and call it `embedded`. Adding recipe `nodejs::npm` assure you to have npm installed and let you choose install method with `node['nodejs']['npm']['install_method']` + +```chef +include_recipe "nodejs::npm" +``` + +_Warning:_ This recipe will include the `nodejs` recipe, which by default includes `nodejs::nodejs_from_package` if you did not set `node['nodejs']['install_method']`. + +## Resources + +### npm_package + +note: This resource was previously named nodejs_npm. Calls to that resource name will still function, but cookbooks should be updated for the new npm_package resource name. + +`npm_package` let you install npm packages from various sources: + +- npm registry: + + - name: `property :package` + - version: `property :version` (optional) + +- url: `property :url` + + - for git use `git://{your_repo}` + +- from a json (package.json by default): `property :json` + + - use `true` for default + - use a `String` to specify json file + +Packages can be installed globally (by default) or in a directory (by using `attribute :path`) + +You can specify an `NPM_TOKEN` environment variable for accessing [NPM private modules](https://docs.npmjs.com/private-modules/intro) by using `attribute :npm_token` + +You can append more specific options to npm command with `attribute :options` array : + +- use an array of options (w/ dash), they will be added to npm call. +- ex: `['--production','--force']` or `['--force-latest']` + +This LWRP attempts to use vanilla npm as much as possible (no custom wrapper). + +### Packages + +```ruby +npm_package 'express' + +npm_package 'async' do + version '0.6.2' +end + +npm_package 'request' do + url 'github mikeal/request' +end + +npm_package 'grunt' do + path '/home/random/grunt' + json true + user 'random' +end + +npm_package 'my_private_module' do + path '/home/random/myproject' # The root path to your project, containing a package.json file + json true + npm_token '12345-abcde-e5d4c3b2a1' + user 'random' + options ['--production'] # Only install dependencies. Skip devDependencies +end +``` + +[Working Examples](test/cookbooks/nodejs_test/recipes/npm.rb) + +Or add packages via attributes (which accept the same attributes as the LWRP above): + +```json +"nodejs": { + "npm_packages": [ + { + "name": "express" + }, + { + "name": "async", + "version": "0.6.2" + }, + { + "name": "request", + "url": "github mikeal/request" + } + { + "name": "grunt", + "path": "/home/random/grunt", + "json": true, + "user": "random" + } + ] +} +``` + +## License & Authors + +**Author:** Marius Ducea (marius@promethost.com) **Author:** Nathan L Smith (nlloyds@gmail.com) **Author:** Guilhem Lettron (guilhem@lettron.fr) **Author:** Barthelemy Vessemont (bvessemont@gmail.com) + +**Copyright:** 2008-2017, Chef Software, Inc. + +``` +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/cookbooks/nodejs/attributes/default.rb b/cookbooks/nodejs/attributes/default.rb new file mode 100644 index 0000000..2ab61bf --- /dev/null +++ b/cookbooks/nodejs/attributes/default.rb @@ -0,0 +1,41 @@ +# +# Cookbook:: nodejs +# Attributes:: nodejs +# +# Copyright:: 2010-2017, Promet Solutions +# +# 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. +# + +case node['platform_family'] +when 'smartos', 'rhel', 'debian', 'fedora', 'mac_os_x', 'suse', 'amazon' + default['nodejs']['install_method'] = 'package' +else + default['nodejs']['install_method'] = 'source' +end + +default['nodejs']['version'] = '6.10.2' + +default['nodejs']['prefix_url']['node'] = 'https://nodejs.org/dist/' + +default['nodejs']['source']['url'] = nil # Auto generated +default['nodejs']['source']['checksum'] = '9b897dd6604d50ae5fff25fd14b1c4035462d0598735799e0cfb4f17cb6e0d19' + +default['nodejs']['binary']['url'] = nil # Auto generated +default['nodejs']['binary']['checksum']['linux_x64'] = '35accd2d9ccac747eff0f236e2843bc2198ba7765e2340441d6230861bae4e1b' +default['nodejs']['binary']['checksum']['linux_x86'] = '6721221fab4e3b3a1be6573900b9e368c7a74ac1c1c3ae982e49c5583e8962e3' +default['nodejs']['binary']['checksum']['linux_arm64'] = '97de0340b6dbf38e3d995df880a94c58d403c3054676d8fc9192b83a3735f0b8' + +default['nodejs']['make_threads'] = node['cpu'] ? node['cpu']['total'].to_i : 2 + +default['nodejs']['manage_node'] = true diff --git a/cookbooks/nodejs/attributes/npm.rb b/cookbooks/nodejs/attributes/npm.rb new file mode 100644 index 0000000..97ee5d3 --- /dev/null +++ b/cookbooks/nodejs/attributes/npm.rb @@ -0,0 +1,2 @@ +default['nodejs']['npm']['install_method'] = 'embedded' +default['nodejs']['npm']['version'] = 'latest' diff --git a/cookbooks/nodejs/attributes/packages.rb b/cookbooks/nodejs/attributes/packages.rb new file mode 100644 index 0000000..169e28a --- /dev/null +++ b/cookbooks/nodejs/attributes/packages.rb @@ -0,0 +1,11 @@ +include_attribute 'nodejs::default' +include_attribute 'nodejs::repo' + +default['nodejs']['packages'] = value_for_platform_family( + 'debian' => node['nodejs']['install_repo'] ? ['nodejs'] : ['nodejs', 'npm', 'nodejs-dev'], + %w(rhel fedora amazon) => node['nodejs']['install_repo'] ? ['nodejs', 'nodejs-devel'] : ['nodejs', 'npm', 'nodejs-dev'], + 'suse' => node['platform_version'].to_i < 42 ? ['nodejs', 'nodejs-devel'] : ['nodejs4', 'npm4', 'nodejs4-devel'], + 'mac_os_x' => ['node'], + 'freebsd' => %w(node npm), + 'default' => ['nodejs'] +) diff --git a/cookbooks/nodejs/attributes/repo.rb b/cookbooks/nodejs/attributes/repo.rb new file mode 100644 index 0000000..fa95c19 --- /dev/null +++ b/cookbooks/nodejs/attributes/repo.rb @@ -0,0 +1,12 @@ +case node['platform_family'] +when 'debian' + default['nodejs']['install_repo'] = true + default['nodejs']['repo'] = 'https://deb.nodesource.com/node_6.x' + default['nodejs']['keyserver'] = 'keyserver.ubuntu.com' + default['nodejs']['key'] = '1655a0ab68576280' +when 'rhel', 'amazon' + default['nodejs']['install_repo'] = true + release_ver = platform?('amazon') ? 6 : node['platform_version'].to_i + default['nodejs']['repo'] = "https://rpm.nodesource.com/pub_6.x/el/#{release_ver}/$basearch" + default['nodejs']['key'] = 'https://rpm.nodesource.com/pub/el/NODESOURCE-GPG-SIGNING-KEY-EL' +end diff --git a/cookbooks/nodejs/libraries/nodejs_helper.rb b/cookbooks/nodejs/libraries/nodejs_helper.rb new file mode 100644 index 0000000..d566065 --- /dev/null +++ b/cookbooks/nodejs/libraries/nodejs_helper.rb @@ -0,0 +1,40 @@ +module NodeJs + module Helper + def npm_dist + if node['nodejs']['npm']['url'] + { 'url' => node['nodejs']['npm']['url'] } + else + + require 'open-uri' + require 'json' + result = JSON.parse(URI.parse("https://registry.npmjs.org/npm/#{node['nodejs']['npm']['version']}").read, max_nesting: false) + ret = { 'url' => result['dist']['tarball'], 'version' => result['_npmVersion'], 'shasum' => result['dist']['shasum'] } + Chef::Log.debug("Npm dist #{ret}") + ret + end + end + + def npm_list(package, path = nil, environment = {}) + require 'json' + cmd = if path + Mixlib::ShellOut.new("npm list #{package} -json", cwd: path, environment: environment) + else + Mixlib::ShellOut.new("npm list #{package} -global -json", environment: environment) + end + + JSON.parse(cmd.run_command.stdout, max_nesting: false) + end + + def version_valid?(list, package, version) + (version ? list[package]['version'] == version : true) + end + + def npm_package_installed?(package, version = nil, path = nil, npm_token = nil) + environment = { 'NPM_TOKEN' => npm_token } if npm_token + + list = npm_list(package, path, environment)['dependencies'] + # Return true if package installed and installed to good version + !list.nil? && list.key?(package) && version_valid?(list, package, version) + end + end +end diff --git a/cookbooks/nodejs/metadata.json b/cookbooks/nodejs/metadata.json new file mode 100644 index 0000000..0c1afd9 --- /dev/null +++ b/cookbooks/nodejs/metadata.json @@ -0,0 +1 @@ +{"name":"nodejs","version":"5.0.0","description":"Installs/Configures node.js","long_description":"# [nodejs-cookbook](https://github.com/redguide/nodejs)\n\n[![CK Version](http://img.shields.io/cookbook/v/nodejs.svg?branch=master)](https://supermarket.chef.io/cookbooks/nodejs) [![Build Status](https://img.shields.io/travis/redguide/nodejs.svg)](https://travis-ci.org/redguide/nodejs) [![Gitter chat](https://badges.gitter.im/redguide/nodejs.svg)](https://gitter.im/redguide/nodejs)\n\nInstalls node.js/npm and includes a resource for managing npm packages\n\n## Requirements\n\n### Platforms\n\n- Debian/Ubuntu\n- RHEL/CentOS/Scientific/Amazon/Oracle\n- openSUSE\n\nNote: Source installs require GCC 4.8+, which is not included on older distro releases\n\n### Chef\n\n- Chef 12.14+\n\n### Cookbooks\n\n- build-essential\n- ark\n\n## Usage\n\nInclude the nodejs recipe to install node on your system based on the default installation method:\n\n```chef\ninclude_recipe \"nodejs\"\n```\n\n### Install methods\n\n#### Package\n\nInstall node from packages:\n\n```chef\nnode['nodejs']['install_method'] = 'package' # Not necessary because it's the default\ninclude_recipe \"nodejs\"\n# Or\ninclude_recipe \"nodejs::nodejs_from_package\"\n```\n\nBy default this will setup deb/rpm repositories from nodesource.com, which include up to date NodeJS packages. If you prefer to use distro provided package you can disable this behavior by setting `node['nodejs']['install_repo']` to `false`.\n\n#### Binary\n\nInstall node from official prebuilt binaries:\n\n```chef\nnode['nodejs']['install_method'] = 'binary'\ninclude_recipe \"nodejs\"\n\n# Or\ninclude_recipe \"nodejs::nodejs_from_binary\"\n\n# Or set a specific version of nodejs to be installed\nnode.default['nodejs']['install_method'] = 'binary'\nnode.default['nodejs']['version'] = '5.9.0'\nnode.default['nodejs']['binary']['checksum'] = '99c4136cf61761fac5ac57f80544140a3793b63e00a65d4a0e528c9db328bf40'\n\n# Or fetch the binary from your own location\nnode.default['nodejs']['install_method'] = 'binary'\nnode.default['nodejs']['binary']['url'] = 'https://s3.amazonaws.com/my-bucket/node-v7.8.0-linux-x64.tar.gz'\nnode.default['nodejs']['binary']['checksum'] = '0bd86f2a39221b532172c7d1acb57f0b0cba88c7b82ea74ba9d1208b9f6f9697'\n```\n\n#### Source\n\nInstall node from sources:\n\n```chef\nnode['nodejs']['install_method'] = 'source'\ninclude_recipe \"nodejs\"\n# Or\ninclude_recipe \"nodejs::nodejs_from_source\"\n```\n\n## NPM\n\nNpm is included in nodejs installs by default. By default, we are using it and call it `embedded`. Adding recipe `nodejs::npm` assure you to have npm installed and let you choose install method with `node['nodejs']['npm']['install_method']`\n\n```chef\ninclude_recipe \"nodejs::npm\"\n```\n\n_Warning:_ This recipe will include the `nodejs` recipe, which by default includes `nodejs::nodejs_from_package` if you did not set `node['nodejs']['install_method']`.\n\n## Resources\n\n### npm_package\n\nnote: This resource was previously named nodejs_npm. Calls to that resource name will still function, but cookbooks should be updated for the new npm_package resource name.\n\n`npm_package` let you install npm packages from various sources:\n\n- npm registry:\n\n - name: `property :package`\n - version: `property :version` (optional)\n\n- url: `property :url`\n\n - for git use `git://{your_repo}`\n\n- from a json (package.json by default): `property :json`\n\n - use `true` for default\n - use a `String` to specify json file\n\nPackages can be installed globally (by default) or in a directory (by using `attribute :path`)\n\nYou can specify an `NPM_TOKEN` environment variable for accessing [NPM private modules](https://docs.npmjs.com/private-modules/intro) by using `attribute :npm_token`\n\nYou can append more specific options to npm command with `attribute :options` array :\n\n- use an array of options (w/ dash), they will be added to npm call.\n- ex: `['--production','--force']` or `['--force-latest']`\n\nThis LWRP attempts to use vanilla npm as much as possible (no custom wrapper).\n\n### Packages\n\n```ruby\nnpm_package 'express'\n\nnpm_package 'async' do\n version '0.6.2'\nend\n\nnpm_package 'request' do\n url 'github mikeal/request'\nend\n\nnpm_package 'grunt' do\n path '/home/random/grunt'\n json true\n user 'random'\nend\n\nnpm_package 'my_private_module' do\n path '/home/random/myproject' # The root path to your project, containing a package.json file\n json true\n npm_token '12345-abcde-e5d4c3b2a1'\n user 'random'\n options ['--production'] # Only install dependencies. Skip devDependencies\nend\n```\n\n[Working Examples](test/cookbooks/nodejs_test/recipes/npm.rb)\n\nOr add packages via attributes (which accept the same attributes as the LWRP above):\n\n```json\n\"nodejs\": {\n \"npm_packages\": [\n {\n \"name\": \"express\"\n },\n {\n \"name\": \"async\",\n \"version\": \"0.6.2\"\n },\n {\n \"name\": \"request\",\n \"url\": \"github mikeal/request\"\n }\n {\n \"name\": \"grunt\",\n \"path\": \"/home/random/grunt\",\n \"json\": true,\n \"user\": \"random\"\n }\n ]\n}\n```\n\n## License & Authors\n\n**Author:** Marius Ducea (marius@promethost.com) **Author:** Nathan L Smith (nlloyds@gmail.com) **Author:** Guilhem Lettron (guilhem@lettron.fr) **Author:** Barthelemy Vessemont (bvessemont@gmail.com)\n\n**Copyright:** 2008-2017, Chef Software, Inc.\n\n```\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","maintainer":"redguide","maintainer_email":"guilhem@lettron.fr","license":"Apache-2.0","platforms":{"debian":">= 0.0.0","ubuntu":">= 0.0.0","centos":">= 0.0.0","redhat":">= 0.0.0","scientific":">= 0.0.0","oracle":">= 0.0.0","amazon":">= 0.0.0","smartos":">= 0.0.0","mac_os_x":">= 0.0.0","opensuseleap":">= 0.0.0","suse":">= 0.0.0"},"dependencies":{"build-essential":">= 0.0.0","ark":">= 2.0.2"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/redguide/nodejs","issues_url":"https://github.com/redguide/nodejs/issues","chef_version":[[">= 12.14"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/nodejs/recipes/default.rb b/cookbooks/nodejs/recipes/default.rb new file mode 100644 index 0000000..a4234be --- /dev/null +++ b/cookbooks/nodejs/recipes/default.rb @@ -0,0 +1,23 @@ +# +# Author:: Marius Ducea (marius@promethost.com) +# Cookbook:: nodejs +# Recipe:: default +# +# Copyright:: 2010-2017, Promet Solutions +# +# 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. +# + +include_recipe 'nodejs::install' if node['nodejs']['manage_node'] +include_recipe 'nodejs::npm' if node['nodejs']['manage_node'] +include_recipe 'nodejs::npm_packages' if node['nodejs']['manage_node'] diff --git a/cookbooks/nodejs/recipes/install.rb b/cookbooks/nodejs/recipes/install.rb new file mode 100644 index 0000000..bb4b529 --- /dev/null +++ b/cookbooks/nodejs/recipes/install.rb @@ -0,0 +1,21 @@ +# +# Author:: Marius Ducea (marius@promethost.com) +# Cookbook:: nodejs +# Recipe:: install +# +# Copyright:: 2010-2017, Promet Solutions +# +# 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. +# + +include_recipe "nodejs::nodejs_from_#{node['nodejs']['install_method']}" diff --git a/cookbooks/nodejs/recipes/iojs.rb b/cookbooks/nodejs/recipes/iojs.rb new file mode 100644 index 0000000..a1244b0 --- /dev/null +++ b/cookbooks/nodejs/recipes/iojs.rb @@ -0,0 +1 @@ +Chef::Log.fatal('The nodejs::iojs recipe has been deprecated. If you need iojs installation pin to cookbook version 3.0.1.') diff --git a/cookbooks/nodejs/recipes/nodejs.rb b/cookbooks/nodejs/recipes/nodejs.rb new file mode 100644 index 0000000..368b88d --- /dev/null +++ b/cookbooks/nodejs/recipes/nodejs.rb @@ -0,0 +1,21 @@ +# +# Author:: Marius Ducea (marius@promethost.com) +# Cookbook:: nodejs +# Recipe:: nodejs +# +# Copyright:: 2010-2017, Promet Solutions +# +# 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. +# + +Chef::Log.fatal('The nodejs::nodejs recipe is no longer used. Use nodejs::install to install nodejs instead.') diff --git a/cookbooks/nodejs/recipes/nodejs_from_binary.rb b/cookbooks/nodejs/recipes/nodejs_from_binary.rb new file mode 100644 index 0000000..640e12c --- /dev/null +++ b/cookbooks/nodejs/recipes/nodejs_from_binary.rb @@ -0,0 +1,65 @@ +# +# Author:: Julian Wilde (jules@jules.com.au) +# Cookbook:: nodejs +# Recipe:: install_from_binary +# +# 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. +# + +Chef::Recipe.send(:include, NodeJs::Helper) + +# Shamelessly borrowed from http://docs.chef.io/dsl_recipe_method_platform.html +# Surely there's a more canonical way to get arch? +arch = if node['kernel']['machine'] =~ /armv6l/ + # FIXME: This should really check the version of node we're looking for + # as it seems that they haven't build an `arm-pi` version in a while... + # if it's old, return this, otherwise just return `node['kernel']['machine']` + 'arm-pi' # assume a raspberry pi + elsif node['kernel']['machine'] =~ /aarch64/ + 'arm64' + elsif node['kernel']['machine'] =~ /x86_64/ + 'x64' + elsif node['kernel']['machine'] =~ /\d86/ + 'x86' + else + node['kernel']['machine'] + end + +# needed to uncompress the binary +package 'tar' if platform_family?('rhel', 'fedora', 'amazon', 'suse') + +# package_stub is for example: "node-v6.9.1-linux-x64.tar.gz" +version = "v#{node['nodejs']['version']}/" +prefix = node['nodejs']['prefix_url']['node'] + +filename = "node-v#{node['nodejs']['version']}-linux-#{arch}.tar.gz" +archive_name = 'nodejs-binary' +binaries = ['bin/node'] + +binaries.push('bin/npm') if node['nodejs']['npm']['install_method'] == 'embedded' + +if node['nodejs']['binary']['url'] + nodejs_bin_url = node['nodejs']['binary']['url'] + checksum = node['nodejs']['binary']['checksum'] +else + nodejs_bin_url = ::URI.join(prefix, version, filename).to_s + checksum = node['nodejs']['binary']['checksum']["linux_#{arch}"] +end + +ark archive_name do + url nodejs_bin_url + version node['nodejs']['version'] + checksum checksum + has_binaries binaries + action :install +end diff --git a/cookbooks/nodejs/recipes/nodejs_from_package.rb b/cookbooks/nodejs/recipes/nodejs_from_package.rb new file mode 100644 index 0000000..6bd995d --- /dev/null +++ b/cookbooks/nodejs/recipes/nodejs_from_package.rb @@ -0,0 +1,33 @@ +# +# Author:: Nathan L Smith (nlloyds@gmail.com) +# Author:: Marius Ducea (marius@promethost.com) +# Cookbook:: nodejs +# Recipe:: package +# +# Copyright:: 2012-2017, Cramer Development, Inc. +# Copyright:: 2013-2017, Opscale +# +# 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. +# + +include_recipe 'nodejs::repo' if node['nodejs']['install_repo'] + +unless node['nodejs']['packages'] + Chef::Log.error 'No package for nodejs' + Chef::Log.warn 'Please use the source or binary method to install node' + return +end + +node['nodejs']['packages'].each do |node_pkg| + package node_pkg +end diff --git a/cookbooks/nodejs/recipes/nodejs_from_source.rb b/cookbooks/nodejs/recipes/nodejs_from_source.rb new file mode 100644 index 0000000..ace91e1 --- /dev/null +++ b/cookbooks/nodejs/recipes/nodejs_from_source.rb @@ -0,0 +1,45 @@ +# +# Author:: Marius Ducea (marius@promethost.com) +# Cookbook:: nodejs +# Recipe:: source +# +# Copyright:: 2010-2017, Promet Solutions +# +# 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. +# + +Chef::Recipe.send(:include, NodeJs::Helper) + +include_recipe 'build-essential' + +case node['platform_family'] +when 'rhel', 'fedora', 'amazon' + package %w(openssl-devel tar) +when 'debian' + package 'libssl-dev' +end + +version = "v#{node['nodejs']['version']}/" +prefix = node['nodejs']['prefix_url']['node'] +filename = "node-v#{node['nodejs']['version']}.tar.gz" +archive_name = 'nodejs-source' + +nodejs_src_url = node['nodejs']['source']['url'] || ::URI.join(prefix, version, filename).to_s + +ark archive_name do + url nodejs_src_url + version node['nodejs']['version'] + checksum node['nodejs']['source']['checksum'] + make_opts ["-j #{node['nodejs']['make_threads']}"] + action :install_with_make +end diff --git a/cookbooks/nodejs/recipes/npm.rb b/cookbooks/nodejs/recipes/npm.rb new file mode 100644 index 0000000..9d049fc --- /dev/null +++ b/cookbooks/nodejs/recipes/npm.rb @@ -0,0 +1,28 @@ +# +# Author:: Marius Ducea (marius@promethost.com) +# Cookbook:: nodejs +# Recipe:: npm +# +# Copyright:: 2010-2017, Promet Solutions +# +# 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. +# + +case node['nodejs']['npm']['install_method'] +when 'embedded' + include_recipe 'nodejs::install' +when 'source' + include_recipe 'nodejs::npm_from_source' +else + Chef::Log.error('No install method found for npm') +end diff --git a/cookbooks/nodejs/recipes/npm_from_source.rb b/cookbooks/nodejs/recipes/npm_from_source.rb new file mode 100644 index 0000000..bfe6871 --- /dev/null +++ b/cookbooks/nodejs/recipes/npm_from_source.rb @@ -0,0 +1,32 @@ +# +# Author:: Marius Ducea (marius@promethost.com) +# Cookbook:: nodejs +# Recipe:: npm +# +# Copyright:: 2010-2017, Promet Solutions +# +# 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. +# + +Chef::Recipe.send(:include, NodeJs::Helper) + +include_recipe 'nodejs::nodejs_from_source' + +dist = npm_dist + +ark 'npm' do + url dist['url'] + checksum dist['checksum'] + version dist['version'] + action :install_with_make +end diff --git a/cookbooks/nodejs/recipes/npm_packages.rb b/cookbooks/nodejs/recipes/npm_packages.rb new file mode 100644 index 0000000..3331fb3 --- /dev/null +++ b/cookbooks/nodejs/recipes/npm_packages.rb @@ -0,0 +1,11 @@ +node['nodejs']['npm_packages'].each do |pkg| + pkg_action = pkg.key?('action') ? pkg['action'] : :install + f = npm_package "nodejs_npm-#{pkg['name']}-#{pkg_action}" do + action :nothing + package pkg['name'] + end + pkg.each do |key, value| + f.send(key, value) unless key == 'name' || key == 'action' + end + f.action(pkg_action) +end if node['nodejs'].key?('npm_packages') diff --git a/cookbooks/nodejs/recipes/repo.rb b/cookbooks/nodejs/recipes/repo.rb new file mode 100644 index 0000000..6ac4ca2 --- /dev/null +++ b/cookbooks/nodejs/recipes/repo.rb @@ -0,0 +1,20 @@ +case node['platform_family'] +when 'debian' + package 'nodejs-apt-transport-https' do + package_name 'apt-transport-https' + end + + apt_repository 'node.js' do + uri node['nodejs']['repo'] + distribution node['lsb']['codename'] + components ['main'] + keyserver node['nodejs']['keyserver'] + key node['nodejs']['key'] + end +when 'rhel', 'amazon' + yum_repository 'node.js' do + description 'nodesource.com nodejs repository' + baseurl node['nodejs']['repo'] + gpgkey node['nodejs']['key'] + end +end diff --git a/cookbooks/nodejs/resources/npm_package.rb b/cookbooks/nodejs/resources/npm_package.rb new file mode 100644 index 0000000..7bd170a --- /dev/null +++ b/cookbooks/nodejs/resources/npm_package.rb @@ -0,0 +1,100 @@ +# +# Cookbook:: nodejs +# Resource:: npm +# +# Author:: Sergey Balbeko +# +# Copyright:: 2012-2017, Sergey Balbeko +# +# 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. +# + +resource_name :npm_package + +# backwards compatibility for the old resource name +provides :nodejs_npm + +property :package, name_property: true +property :version, String +property :path, String +property :url, String +property :json, [String, true] +property :npm_token, String +property :options, Array, default: [] +property :user, String +property :group, String + +def initialize(*args) + super + @run_context.include_recipe 'nodejs::npm' if node['nodejs']['manage_node'] +end + +action :install do + execute "install NPM package #{new_resource.package}" do + cwd new_resource.path + command "npm install #{npm_options}" + user new_resource.user + group new_resource.group + environment npm_env_vars + not_if { package_installed? } + end +end + +action :uninstall do + execute "uninstall NPM package #{new_resource.package}" do + cwd new_resource.path + command "npm uninstall #{npm_options}" + user new_resource.user + group new_resource.group + environment npm_env_vars + only_if { package_installed? } + end +end + +action_class do + include NodeJs::Helper + + def npm_env_vars + env_vars = {} + env_vars['HOME'] = ::Dir.home(new_resource.user) if new_resource.user + env_vars['USER'] = new_resource.user if new_resource.user + env_vars['NPM_TOKEN'] = new_resource.npm_token if new_resource.npm_token + + env_vars + end + + def package_installed? + new_resource.package && npm_package_installed?(new_resource.package, new_resource.version, new_resource.path, new_resource.npm_token) + end + + def npm_options + options = '' + options << ' -global' unless new_resource.path + new_resource.options.each do |option| + options << " #{option}" + end + options << " #{npm_package}" + end + + def npm_package + if new_resource.json + new_resource.json.is_a?(String) ? new_resource.json : nil + elsif new_resource.url + new_resource.url + elsif new_resource.package + new_resource.version ? "#{new_resource.package}@#{new_resource.version}" : new_resource.package + else + Chef::Log.error("No good options found to install #{new_resource.package}") + end + end +end diff --git a/cookbooks/ntp/CHANGELOG.md b/cookbooks/ntp/CHANGELOG.md new file mode 100644 index 0000000..290eb68 --- /dev/null +++ b/cookbooks/ntp/CHANGELOG.md @@ -0,0 +1,274 @@ +# ntp Cookbook CHANGELOG + +This file is used to list changes made in each version of the ntp cookbook. + +## 3.4.0 (2017-05-06) + +- Ensure metadata compatibility with older Chef 12 releases +- Testing updates for Chef 13 +- Test with Delivery local mode instead of a Rakefile +- Use a SPDX standard license string +- Remove xcp as a platform in the metadata +- Added requestkey attribute + +## 3.3.1 (2016-12-21) + +- Fix resource cloning warning in recipe[default] + +## 3.3.0 (2016-12-16) + +- Add Mac OS X client config support + +## 3.2.1 (2016-11-23) + +- Update leap seconds file to version 3676924800 + +## 3.2.0 (2016-09-28) + +- Remove support for Arch +- Remove legacy apparmor config that wasn't used +- Don't install ntpdate (and uninstall it) on Ubuntu 16.04+ +- Expand specs and avoid deprecation warnings + +## 3.1.0 (2016-09-16) + +- Require Chef 12.1 not 12.0 +- Remove the dependency on the Windows cookbook + +## 3.0.0 (2016-09-07) + +- Require Chef 12+ + +## 2.0.3 (2016-08-31) + +- Remove minitest tests from the undo recipe + +## 2.0.2 (2016-08-30) + +- Replace node.set with node.normal to avoid deprecation notices + +## 2.0.1 (2016-08-29) + +- Update the leap seconds file +- Remove node name from configs +- Switch to cookstyle and use the Rakefile directly for testing in Travis CI +- Update platforms we test on +- Fix failing Chefspecs and avoid deprecation warnings during spec runs + +## v2.0.0 (2016-05-18) + +- Remove the undo recipe. This functionality is better suited for a custom cookbook that matches the needs of individual organizations +- Removed the installation of the visual studio 2008 runtime that was only necessary for Windows 2003. +- Fixed the forced clock syncing on FreeBSD hosts + +## v1.11.1 (2016-05-12) + +- Ownership of this cookbook has been transferred back to Chef Software. + +## v1.11.0 (2016-03-29) + +- When force setting the clock run ntp as the ntp user to ensure we don't set file ownership to root +- Added optional support for orphan mode +- Require windows cookbook 1.38.0 to resolve several issues with the older cookbook versions +- Add support for using keys + +## v1.10.1 (2016-02-04) + +- Update the Readme to include openSUSE and Arch Linux +- Guard the timeout set in the service to prevent failures on old chef releases + +## v1.10.0 (2016-02-04) + +- Fixed compatibility with FreeBSD hosts by skipping the sync with the hardware clock and using the proper path to the "true" command +- Fixed compatibility with Windows by extending the service start timeout, introducing retries, and excluding Windows from the hardware sync logic +- Changed the default array of packages to install from ntp and ntpdate to just ntp. ntpdate is used on Debian and modern RHEL/Fedora hosts only. This gives us out of the box support for Arch and Suse +- Ensure that Fedora systems also install ntpdate +- Updated test dependencies to the latest +- Updated test documentation to point to the official Chef testing documentation +- Expanded the Test Kitchen config with better support for FreeBSD/Fedora and new Windows boxes + +## v1.9.2 (2016-02-04) + +- **PR [#121]** - Remove nomodify config from loopback + +## v1.9.1 (2016-01-07) + +- **PR [#132]** - Update ntp.leapseconds + +## v1.9.0 (2015-12-16) + +- **PR [#111]** - Fix duplication of localhost listen directive in template +- **PR [#127]** - Set `var_owner` on FreeBSD to root instead of default ntp +- **PR [#117]** - Document node['ntp']['ignore'] +- **PR [#118]** - Add attributes to support pld-linux +- **PR [#120]** - Fix links to Github PRs in the Changelog +- **PR [#124]** - Additional fix for apparmor issue gmiranda23#103 +- Depend on windows cookbook instead of suggesting. Suggests doesn't actually do anything +- Fix / expand apparmor specs to pass and test the auto apparmor config logic +- Enable Travis CI and update the travis.yml file to run full integration tests with Kitchen Docker so we test all PRs on Ubuntu 12.04/14.04 and CentOS 6.7 / 7.1 +- Reformat all markdown files +- Update all references to Opscode to be Chef Software. +- Update copyright dates and contact e-mails +- Expanded platforms in the Test Kitchen config +- Added new supermarket issues_url and source_url metadata +- Update the Berkfile API url and removed version pins on the testing cookbooks +- Remove yum from the Berksfile as it isn't actually used +- Use the standard Chef testing Rakefile +- Remove the attribute documentation from the metadata as it is quickly out of sync +- Resolve rubocop warnings and include the standard Chef rubocop.yml file +- Update development deps in the Gemfile to the latest releases +- Remove the outdated contributing.md doc from the Opscode days + +## v1.8.6 (2015-05-14) + +- **PR [#102](102)** - Update leapseconds file to 3660249600 (through C49) +- Gemfile parity with ChefDK 0.5.1 +- .kitchen.yml platform updates to current bento boxes + +## v1.8.4 (2015-04-17) + +- **PR [#101]** - add logfile attribute + +## v1.8.2 (2015-04-15) + +- **PR [#100]** - Sort peers & servers for consistency + +## v1.8.0 (2015-04-13) + +- Chefspec 4.0 updates +- Rubocop updates +- **PR [#85]** - Update leapseconds for June 2015 leapsecond +- **PR [#70]** - Allow setting tinker options in attributes +- **PR [#84]** - Add attributes for tinker option customization +- **PR [#88]** - Attribute sets noquery for localhost lines +- **PR [#89]** - ntp.leapseconds notifies ntp service with delayed restart +- **PR [#91]** - Allow ntp.conf update to restart immediate +- **PR [#95]** - Add preferred ntp server support +- **PR [#96]** - Add restrict default attribute +- **PR [#72]** - Move high stratum real CMOs to an attribute +- **PR [#98]** - Bump test-kitchen gem version +- **PR [#99]** - Lazy attribute for leapfile_enabled + +## v1.7.0 (2014-12-10) + +- Added CentOS 7 support for test-kitchen +- **PR [#37]** - Check that apparmor exists before enabling service +- **PR [#45]** - Statistics logging switch (not available for Windows) +- **PR [#57]** - Move include statement on helper outside 'windows?' check +- **PR [#71]** - Ability to listen more than one interface +- **PR [#73]** - Fix appamor configuration for Ubuntu +- **PR [#74]** - Remove is_server from example +- **PR [#75]** - Add more settings for server and peer declarations +- **PR [#83]** - Fix apparmor spec tests + +## v1.6.8 (2014-12-04) + +- **PR [#81]** - Update to berkshelf3 + +## v1.6.6 (2014-12-02) + +- **PR [#76]** - Overhauled Testing +- **PR [#68]** - Updated Leapseconds +- **PR [#51]** - Berksfile source deprecation + +## v1.6.5 (2014-09-25) + +- Ensure that ntp version is captured + +## v1.6.4 (2014-07-02) + +- Leapseconds File Expired, update to 3626380800 +- **[COOK-3887](https://tickets.opscode.com/browse/COOK-3887)** - Trivial changes to achieve Gentoo support +- **[COOK-1876](https://tickets.opscode.com/browse/COOK-1876)** - ntp leapfile assumes ntpd >= 4.2.6 syntax + +## v1.6.2 (2014-03-19) + +- [COOK-4162] - change "No NTP servers specified" message to :debug + +## v1.6.0 (2014-02-21) + +### Improvement + +- **[COOK-4346](https://tickets.opscode.com/browse/COOK-4346)** - Solaris 11 support for ntp +- **[COOK-4339](https://tickets.opscode.com/browse/COOK-4339)** - Disable Monitoring by Default +- **[COOK-3604](https://tickets.opscode.com/browse/COOK-3604)** - Enable listening on specific interfaces + +### Bug + +- **[COOK-4106](https://tickets.opscode.com/browse/COOK-4106)** - Check for default content in ntp.conf +- **[COOK-4087](https://tickets.opscode.com/browse/COOK-4087)** - quote option in readme +- **[COOK-3797](https://tickets.opscode.com/browse/COOK-3797)** - Cookbook fails to upload due to 1.9.x syntax +- **[COOK-3023](https://tickets.opscode.com/browse/COOK-3023)** - NTP leapseconds file denied by Ubuntu apparmor profile + +## v1.5.4 (2013-12-29) + +[COOK-4007]- update to 3612902400 + +## v1.5.2 + +### Bug + +- **[COOK-3797](https://tickets.opscode.com/browse/COOK-3797)** - Add /spec to Chefignore + +## v1.5.0 + +### Improvement + +- **[COOK-3651](https://tickets.opscode.com/browse/COOK-3651)** - Refactor and clean up +- **[COOK-3630](https://tickets.opscode.com/browse/COOK-3630)** - Switch NTP cookbook linting from Tailor to Rubocop +- **[COOK-3273](https://tickets.opscode.com/browse/COOK-3273)** - Add tests + +### New Feature + +- **[COOK-3636](https://tickets.opscode.com/browse/COOK-3636)** - Allow ntp cookbook to update clock to ntp servers + +### Bug + +- **[COOK-3410](https://tickets.opscode.com/browse/COOK-3410)** - Remove redundant ntpdate/disable recipes +- **[COOK-1170](https://tickets.opscode.com/browse/COOK-1170)** - Allow redefining NTP servers in a role + +## v1.4.0 + +### Improvement + +- **[COOK-3365](https://tickets.opscode.com/browse/COOK-3365)** - Update ntp leapseconds file to version 3597177600 +- **[COOK-1674](https://tickets.opscode.com/browse/COOK-1674)** - Add Windows support + +## v1.3.2 + +- [COOK-2024] - update leapfile for IERS Bulletin C + +## v1.3.0 + +- [COOK-1404] - add leapfile for handling leap seconds + +## v1.2.0 + +- [COOK-1184] - Add recipe to disable NTP completely +- [COOK-1298] - Refactor into a reference cookbook for testing + +## v1.1.8 + +- [COOK-1158] - RHEL family >= 6 has ntpdate package + +## v1.1.6 + +- Related to changes in COOK-1124, fix group for freebsd and else + +## v1.1.4 + +- [COOK-1124] - parameterised driftfile and statsdir to be configurable by platform + +## v1.1.2 + +- [COOK-952] - freebsd support +- [COOK-949] - check for any virtual system not just vmware + +## v1.1.0 + +- Fixes COOK-376 (use LAN peers, iburst option, LAN restriction attribute) + +## v1.0.1 + +- Support scientific linux +- Use service name attribute in resource (fixes EL derivatives) diff --git a/cookbooks/ntp/CONTRIBUTING.md b/cookbooks/ntp/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/ntp/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/cookbooks/ntp/MAINTAINERS.md b/cookbooks/ntp/MAINTAINERS.md new file mode 100644 index 0000000..645ed14 --- /dev/null +++ b/cookbooks/ntp/MAINTAINERS.md @@ -0,0 +1,15 @@ + + +# Maintainers + +This file lists how this cookbook project is maintained. When making changes to the system, this file tells you who needs to review your patch - you need a review from an existing maintainer for the cookbook to provide a :+1: on your pull request. Additionally, you need to not receive a veto from a Lieutenant or the Project Lead. + +Check out [How Cookbooks are Maintained](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD) for details on the process and how to become a maintainer or the project lead. + +# Project Maintainer +* [Tim Smith](https://github.com/tas50) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) diff --git a/cookbooks/ntp/README.md b/cookbooks/ntp/README.md new file mode 100644 index 0000000..af671cb --- /dev/null +++ b/cookbooks/ntp/README.md @@ -0,0 +1,305 @@ +# NTP Cookbook + +[![Build Status](https://travis-ci.org/chef-cookbooks/ntp.svg?branch=master)](http://travis-ci.org/chef-cookbooks/ntp) [![Cookbook Version](https://img.shields.io/cookbook/v/ntp.svg)](https://supermarket.chef.io/cookbooks/ntp) + +Installs and configures ntp. On Windows systems it uses the Meinberg port of the standard NTPd client to Windows. + +## Requirements + +### Platforms + +- Debian-family Linux Distributions +- RedHat-family Linux Distributions +- Fedora +- Gentoo Linux +- openSUSE +- FreeBSD +- Windows 2008 R2+ +- Mac OS X 10.11+ + +### Chef + +- Chef 12.1+ + +### Cookbooks + +- none + +## Attributes + +### Recommended tunables + +- `ntp['servers']` - (applies to NTP Servers and Clients) + + - Array, should be a list of upstream NTP servers that will be considered authoritative by the local NTP daemon. The local NTP daemon will act as a client, adjusting local time to match time data retrieved from the upstream NTP servers. + + The NTP protocol works best with at least 4 servers. The ntp daemon will disregard any server after the 10th listed, but will continue monitoring all listed servers. For more information, see [Upstream Server Time Quantity](http://support.ntp.org/bin/view/Support/SelectingOffsiteNTPServers#Section_5.3.3.) at [support.ntp.org](http://support.ntp.org). + +- `ntp['peers']` - (applies to NTP Servers ONLY) + + - Array, should be a list of local NTP peers. For more information, see [Designing Your NTP Network](http://support.ntp.org/bin/view/Support/DesigningYourNTPNetwork) at [support.ntp.org](http://support.ntp.org). + +- `ntp['restrictions']` - (applies to NTP Servers only) + + - Array, should be a list of restrict lines to define access to NTP clients on your LAN. + +- `ntp['sync_clock']` (applies to NTP Servers and Clients) + + - Boolean. Defaults to false. Forces the ntp daemon to be halted, an ntp -q command to be issued, and the ntp daemon to be restarted again on every Chef-client run. Will have no effect if drift is over 1000 seconds. + +- `ntp['sync_hw_clock']` (applies to NTP Servers and Clients) + + - Boolean. Defaults to false. On *nix-based systems, forces the 'hwclock --systohc' command to be issued on every Chef-client run. This will sync the hardware clock to the system clock. + - Not available on Windows. + +- `ntp['restrict_default']` + + - String. Defaults to 'kod notrap nomodify nopeer noquery'. Set to 'ignore' to [further lock down access](http://support.ntp.org/bin/view/Support/AccessRestrictions#Section_6.5.1.1.2.). + +- `ntp["listen_network"]` / `ntp["listen"]` + + - String, optional attribute. Default is for NTP to listen on all addresses. + - `ntp["listen_network"]` should be set to 'primary' to listen on the node's primary IP address as determined by ohai, or set to a CIDR (eg: '192.168.4.0/24') to listen on the last node address on that CIDR. + - `ntp["listen"]` can be set to a specific address (eg: '192.168.4.10') instead of `ntp["listen_network"]` to force listening on a specific address. + - If both `ntp["listen"]` and `ntp["listen_network"]` are set then `ntp["listen"]` will always win. + +- `ntp["ignore"]` + + - Array, interface names to ignore from listening. Can be used to disable listening wildcard interfaces (eg: ['wildcard', '::1']), can be combined with `ntp["listen"]` + +- `ntp["statistics"]` + + - Boolean. Default to true. Enable/disable statistics data logging into `ntp['statsdir']`. + - Not available on Windows. + +- `ntp['conf_restart_immediate']` + + - Boolean. Defaults to false. Restarts NTP service immediately after a config update if true. Otherwise it is a delayed restart. + +- `ntp['peer']['disable_tinker_panic_on_virtualization_guest']` (applies to virtualized hosts only) + + - Boolean. Defaults to true. Sets tinker panic to 0\. NTP default it 1000\. (See p. 23 for explanation on disabling panic) (Note: this overrides `ntp['tinker']['panic']` attribute) + +- `ntp['peer']['use_iburst']` (applies to NTP Servers ONLY) + + - Boolean. Defaults to true. Enables iburst in peer declaration. + +- `ntp['peer']['use_burst']` (applies to NTP Servers ONLY) + + - Boolean. Defaults to false. Enables burst in peer declaration. + +- `ntp['peer']['minpoll']` (applies to NTP Servers ONLY) + + - Boolean. Defaults to 6 (ntp default). Specify the minimum poll intervals for NTP messages, in seconds to the power of two. + +- `ntp['peer']['maxpoll']` (applies to NTP Servers ONLY) + + - Boolean. Defaults to 10 (ntp default). Specify the maximum poll intervals for NTP messages, in seconds to the power of two. + +- `ntp['server']['prefer']` (applies to NTP Servers and Clients) + + - String. Defaults to emtpy string. The server from `ntp['servers']` to prefer getting the time from. + +- `ntp['server']['use_iburst']` (applies to NTP Servers and Clients) + + - Boolean. Defaults to true. Enables iburst in server declaration. + +- `ntp['server']['use_burst']` (applies to NTP Servers and Clients) + + - Boolean. Defaults to false. Enables burst in server declaration. + +- `ntp['server']['minpoll']` (applies to NTP Servers and Clients) + + - Boolean. Defaults to 6 (ntp default). Specify the minimum poll intervals for NTP messages, in seconds to the power of two. + +- `ntp['server']['maxpoll']` (applies to NTP Servers and Clients) + + - Boolean. Defaults to 10 (ntp default). Specify the maximum poll intervals for NTP messages, in seconds to the power of two. + +- `ntp['tinker']['allan']` + + - Number. Defaults to 1500 (ntp default). Spedifies the Allan intercept, which is a parameter of the PLL/FLL clock discipline algorithm, in seconds. + +- `ntp['tinker']['dispersion']` + + - Number. Defaults to 15 (ntp default). Specifies the dispersion increase rate in parts-per-million (PPM). + +- `ntp['tinker']['panic']` + + - Number. Defaults to 1000 (ntp default). Spedifies the panic threshold in seconds. If set to zero, the panic sanity check is disabled and a clock offset of any value will be accepted. + +- `ntp['tinker']['step']` + + - Number. Defaults to 0.128 (ntp default). Spedifies the step threshold in seconds. If set to zero, step adjustments will never occur. Note: The kernel time discipline is disabled if the step threshold is set to zero or greater than 0.5 s. + +- `ntp['tinker']['stepout']` + + - Number. Defaults to 900 (ntp default). Specifies the stepout threshold in seconds. If set to zero, popcorn spikes will not be suppressed. + +- `ntp['localhost']['noquery']` (applies to NTP Servers and Clients) + + - Boolean. Defaults to false. Set to true if using ntp < 4.2.8 or any unpatched ntp version to mitigate CVE-2014-9293 / CVE-2014-9294 / CVE-2014-9295 + +- `ntp['orphan']['enabled']` + + - Boolean, enables orphan mode if set to true + +- `ntp['orphan']['stratum']` + + - Number. Defaults to 5, recommended value for stratum is 2 more than the worst-case externally-reachable source of time + +### Automatically Set Attributes + +These attributes are set based on platform / system information provided by Ohai + +- `ntp['packages']` + + - Array, the packages to install + - Default, ntp for everything, ntpdate depending on platform. Not applicable for + - Windows nodes + +- `ntp['service']` + + - String, the service to act on + - Default, ntp, NTP, or ntpd, depending on platform + +- `ntp['varlibdir']` + + - String, the path to /var/lib files such as the driftfile. + - Default, platform-specific location. Not applicable for Windows nodes + +- `ntp['driftfile']` + + - String, the path to the frequency file. + - Default, platform-specific location. + +- `ntp['conffile']` + + - String, the path to the ntp configuration file. + - Default, platform-specific location. + +- `ntp['statsdir']` + + - String, the directory path for files created by the statistics facility. + - Default, platform-specific location. Not applicable for Windows nodes + +- `ntp['conf_owner'] and ntp['conf_group']` + + - String, the owner and group of the sysconf directory files, such as /etc/ntp.conf. + - Default, platform-specific root:root or root:wheel. + +- `ntp['var_owner'] and ntp['var_group']` + + - String, the owner and group of the /var/lib directory files, such as /var/lib/ntp. + - Default, platform-specific ntp:ntp or root:wheel. Not applicable for Windows nodes + +- `ntp['leapfile']` + + - String, the path to the ntp leapfile. + - Default, /etc/ntp.leapseconds. + +- `ntp['package_url']` + + - String, the URL to the the Meinberg NTPd client installation package. + - Default, Meinberg site download URL + - Windows platform only + +- `ntp['vs_runtime_url']` + + - String, the URL to the the Visual Studio C++ 2008 runtime libraries that are required for the Meinberg NTP client. + - Default, Microsoft site download URL + - Windows platform only + +- `ntp['vs_runtime_productname']` + + - String, the installation name of the Visual Studio C++ Runtimes file. + - Default, "Microsoft Visual C++ 2008 Redistributable - x86 9.0.21022" + - Windows platform only + +- `ntp['sync_hw_clock']` + + - Boolean, determines if the ntpdate command is issued to sync the hardware clock + - Default, false + - Not applicable for Windows nodes + +- `ntp['apparmor_enabled']` + + - Boolean, enables configuration of apparmor if set to true + - Defaults to false and will make no provisions for apparmor. + - If a platform has apparmor enabled (currently Ubuntu) default will become true. + +- `ntp['use_cmos']` + + - Boolean, uses a high stratum undisciplined clock for machines with real CMOS clock. + - Defaults to true unless a platform appears to be virtualized according to Ohai. + +## Usage + +### default recipe + +Set up the ntp attributes in a role. For example in a base.rb role applied to all nodes: + +```ruby +name 'base' +description 'Role applied to all systems' +default_attributes( + 'ntp' => { + 'servers' => ['time0.int.example.org', 'time1.int.example.org'] + } +) +``` + +Then in an ntpserver.rb role that is applied to NTP servers (e.g., time.int.example.org): + +```ruby +name 'ntp_server' +description 'Role applied to the system that should be an NTP server.' +default_attributes( + 'ntp' => { + 'servers' => ['0.pool.ntp.org', '1.pool.ntp.org'], + 'peers' => ['time0.int.example.org', 'time1.int.example.org'], + 'restrictions' => ['10.0.0.0 mask 255.0.0.0 nomodify notrap'] + } +) +``` + +The timeX.int.example.org used in these roles should be the names or IP addresses of internal NTP servers. Then simply add ntp, or `ntp::default` to your run_list to apply the ntp daemon's configuration. + +### windows_client recipe + +Windows only. Apply on a Windows host to install the Meinberg NTPd client. + +### mac_os_x_client recipe + +Mac OS X only. Apply on a Mac OS X host to configure NTP. + +## License & Authors + +- Author:: Joshua Timberman ([joshua@chef.io](mailto:joshua@chef.io)) +- Contributor:: Eric G. Wolfe ([wolfe21@marshall.edu](mailto:wolfe21@marshall.edu)) +- Contributor:: Fletcher Nichol ([fletcher@nichol.ca](mailto:fletcher@nichol.ca)) +- Contributor:: Tim Smith ([tsmith@chef.io](mailto:tsmith@chef.io)) +- Contributor:: Charles Johnson ([charles@chef.io](mailto:charles@chef.io)) +- Contributor:: Brad Knowles ([bknowles@momentumsi.com](mailto:bknowles@momentumsi.com)) + +```text +Copyright 2009-2016, Chef Software, Inc. +Copyright 2012, Eric G. Wolfe +Copyright 2012, Fletcher Nichol +Copyright 2012, Webtrends, Inc. +Copyright 2013, Limelight Networks, Inc. +Copyright 2013, Brad Knowles +Copyright 2013, Brad Beam + +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/cookbooks/ntp/attributes/default.rb b/cookbooks/ntp/attributes/default.rb new file mode 100644 index 0000000..671a974 --- /dev/null +++ b/cookbooks/ntp/attributes/default.rb @@ -0,0 +1,130 @@ +# +# Cookbook:: ntp +# Attributes:: default +# +# Author:: Joshua Timberman () +# Author:: Tim Smith () +# Author:: Charles Johnson () +# +# Copyright:: 2009-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# default attributes for all platforms +default['ntp']['servers'] = [] # The default recipe sets a list of common NTP servers (COOK-1170) +default['ntp']['peers'] = [] +default['ntp']['restrictions'] = [] +default['ntp']['tinker'] = { 'panic' => 0 } + +# set `restrict default` for IPv4 and IPv6 +default['ntp']['restrict_default'] = 'kod notrap nomodify nopeer noquery' + +# internal attributes +default['ntp']['packages'] = %w(ntp) +default['ntp']['service'] = 'ntpd' +default['ntp']['varlibdir'] = '/var/lib/ntp' +default['ntp']['driftfile'] = "#{node['ntp']['varlibdir']}/ntp.drift" +default['ntp']['logfile'] = nil +default['ntp']['conffile'] = '/etc/ntp.conf' +default['ntp']['statsdir'] = '/var/log/ntpstats/' +default['ntp']['conf_owner'] = 'root' +default['ntp']['conf_group'] = 'root' +default['ntp']['var_owner'] = 'ntp' +default['ntp']['var_group'] = 'ntp' +default['ntp']['leapfile'] = '/etc/ntp.leapseconds' +default['ntp']['sync_clock'] = false +default['ntp']['sync_hw_clock'] = false +default['ntp']['listen'] = nil +default['ntp']['listen_network'] = nil +default['ntp']['ignore'] = nil +default['ntp']['apparmor_enabled'] = false +default['ntp']['monitor'] = false +default['ntp']['statistics'] = true +default['ntp']['conf_restart_immediate'] = false +default['ntp']['keys'] = nil +default['ntp']['trustedkey'] = nil +default['ntp']['requestkey'] = nil + +# See http://www.vmware.com/vmtn/resources/238 p. 23 for explanation +default['ntp']['disable_tinker_panic_on_virtualization_guest'] = true + +default['ntp']['peer']['key'] = nil +default['ntp']['peer']['use_iburst'] = true +default['ntp']['peer']['use_burst'] = false +default['ntp']['peer']['minpoll'] = 6 +default['ntp']['peer']['maxpoll'] = 10 + +default['ntp']['server']['prefer'] = '' +default['ntp']['server']['use_iburst'] = true +default['ntp']['server']['use_burst'] = false +default['ntp']['server']['minpoll'] = 6 +default['ntp']['server']['maxpoll'] = 10 + +default['ntp']['tinker']['allan'] = 1500 +default['ntp']['tinker']['dispersion'] = 15 +default['ntp']['tinker']['panic'] = 1000 +default['ntp']['tinker']['step'] = 0.128 +default['ntp']['tinker']['stepout'] = 900 + +default['ntp']['orphan']['enabled'] = false +default['ntp']['orphan']['stratum'] = 5 # ntp recommends 2 more than the worst-case externally-reachable source of time + +# Set to true if using ntp < 4.2.8 or any unpatched ntp version to mitigate CVE-2014-9293 / CVE-2014-9294 / CVE-2014-9295 +default['ntp']['localhost']['noquery'] = false + +# overrides on a platform-by-platform basis +case node['platform_family'] +when 'debian' + default['ntp']['service'] = 'ntp' + default['ntp']['apparmor_enabled'] = true if File.exist? '/etc/init.d/apparmor' +when 'rhel', 'fedora' + default['ntp']['packages'] = %w(ntp ntpdate) if node['platform_version'].to_i >= 7 +when 'windows' + default['ntp']['service'] = 'NTP' + default['ntp']['driftfile'] = 'C:\\NTP\\ntp.drift' + default['ntp']['conffile'] = 'C:\\NTP\\etc\\ntp.conf' + default['ntp']['conf_owner'] = 'Administrators' + default['ntp']['conf_group'] = 'Administrators' + default['ntp']['package_url'] = 'https://www.meinbergglobal.com/download/ntp/windows/ntp-4.2.8p5-win32-setup.exe' + default['ntp']['statistics'] = false +when 'freebsd' + default['ntp']['varlibdir'] = '/var/db' + default['ntp']['driftfile'] = "#{node['ntp']['varlibdir']}/ntpd.drift" + default['ntp']['statsdir'] = "#{node['ntp']['varlibdir']}/ntpstats" + default['ntp']['conf_group'] = 'wheel' + default['ntp']['var_owner'] = 'root' + default['ntp']['var_group'] = 'wheel' +when 'gentoo' + default['ntp']['leapfile'] = "#{node['ntp']['varlibdir']}/ntp.leapseconds" +when 'solaris2' + default['ntp']['service'] = 'ntp' + default['ntp']['varlibdir'] = '/var/ntp' + default['ntp']['conffile'] = '/etc/inet/ntp.conf' + default['ntp']['statsdir'] = "#{node['ntp']['varlibdir']}/ntpstats/" + default['ntp']['conf_owner'] = 'root' + default['ntp']['conf_group'] = 'root' + default['ntp']['var_owner'] = 'root' + default['ntp']['var_group'] = 'sys' + default['ntp']['leapfile'] = '/etc/inet/ntp.leap' +when 'pld' + default['ntp']['packages'] = %w(ntpd) + default['ntp']['conffile'] = '/etc/ntp/ntp.conf' + default['ntp']['leapfile'] = '/etc/ntp/ntp.leapseconds' + default['ntp']['driftfile'] = "#{node['ntp']['varlibdir']}/drift" + default['ntp']['var_owner'] = 'root' +end + +unless node['platform'] == 'windows' + default['ntp']['use_cmos'] = !node['virtualization'] || node['virtualization']['role'] != 'guest' ? true : false +end diff --git a/cookbooks/ntp/files/default/ntp.ini b/cookbooks/ntp/files/default/ntp.ini new file mode 100644 index 0000000..11498b4 --- /dev/null +++ b/cookbooks/ntp/files/default/ntp.ini @@ -0,0 +1,23 @@ +[Installer] +InstallDir=C:\NTP +UpgradeMode=Reinstall +Logfile=C:\NTP\install.log +Silent=yes + +[Components] +InstallDocs=yes +InstallTools=yes +InstallOpenSSL=yes +CreateStartMenuEntries=yes + +[Service] +ModifyFirewall=yes +ServiceAccount=@SYSTEM +DisableOthers=yes +AllowBigInitialTimestep=yes +EnableMMTimer=yes +AutoStart=yes +StartAfterInstallation=yes + +[Configuration] +UseConfigFile=C:\NTP\ntp.conf diff --git a/cookbooks/ntp/files/default/ntp.leapseconds b/cookbooks/ntp/files/default/ntp.leapseconds new file mode 100644 index 0000000..22fa785 --- /dev/null +++ b/cookbooks/ntp/files/default/ntp.leapseconds @@ -0,0 +1,250 @@ +# +# In the following text, the symbol '#' introduces +# a comment, which continues from that symbol until +# the end of the line. A plain comment line has a +# whitespace character following the comment indicator. +# There are also special comment lines defined below. +# A special comment will always have a non-whitespace +# character in column 2. +# +# A blank line should be ignored. +# +# The following table shows the corrections that must +# be applied to compute International Atomic Time (TAI) +# from the Coordinated Universal Time (UTC) values that +# are transmitted by almost all time services. +# +# The first column shows an epoch as a number of seconds +# since 1 January 1900, 00:00:00 (1900.0 is also used to +# indicate the same epoch.) Both of these time stamp formats +# ignore the complexities of the time scales that were +# used before the current definition of UTC at the start +# of 1972. (See note 3 below.) +# The second column shows the number of seconds that +# must be added to UTC to compute TAI for any timestamp +# at or after that epoch. The value on each line is +# valid from the indicated initial instant until the +# epoch given on the next one or indefinitely into the +# future if there is no next line. +# (The comment on each line shows the representation of +# the corresponding initial epoch in the usual +# day-month-year format. The epoch always begins at +# 00:00:00 UTC on the indicated day. See Note 5 below.) +# +# Important notes: +# +# 1. Coordinated Universal Time (UTC) is often referred to +# as Greenwich Mean Time (GMT). The GMT time scale is no +# longer used, and the use of GMT to designate UTC is +# discouraged. +# +# 2. The UTC time scale is realized by many national +# laboratories and timing centers. Each laboratory +# identifies its realization with its name: Thus +# UTC(NIST), UTC(USNO), etc. The differences among +# these different realizations are typically on the +# order of a few nanoseconds (i.e., 0.000 000 00x s) +# and can be ignored for many purposes. These differences +# are tabulated in Circular T, which is published monthly +# by the International Bureau of Weights and Measures +# (BIPM). See www.bipm.org for more information. +# +# 3. The current definition of the relationship between UTC +# and TAI dates from 1 January 1972. A number of different +# time scales were in use before that epoch, and it can be +# quite difficult to compute precise timestamps and time +# intervals in those "prehistoric" days. For more information, +# consult: +# +# The Explanatory Supplement to the Astronomical +# Ephemeris. +# or +# Terry Quinn, "The BIPM and the Accurate Measurement +# of Time," Proc. of the IEEE, Vol. 79, pp. 894-905, +# July, 1991. +# +# 4. The decision to insert a leap second into UTC is currently +# the responsibility of the International Earth Rotation and +# Reference Systems Service. (The name was changed from the +# International Earth Rotation Service, but the acronym IERS +# is still used.) +# +# Leap seconds are announced by the IERS in its Bulletin C. +# +# See www.iers.org for more details. +# +# Every national laboratory and timing center uses the +# data from the BIPM and the IERS to construct UTC(lab), +# their local realization of UTC. +# +# Although the definition also includes the possibility +# of dropping seconds ("negative" leap seconds), this has +# never been done and is unlikely to be necessary in the +# foreseeable future. +# +# 5. If your system keeps time as the number of seconds since +# some epoch (e.g., NTP timestamps), then the algorithm for +# assigning a UTC time stamp to an event that happens during a positive +# leap second is not well defined. The official name of that leap +# second is 23:59:60, but there is no way of representing that time +# in these systems. +# Many systems of this type effectively stop the system clock for +# one second during the leap second and use a time that is equivalent +# to 23:59:59 UTC twice. For these systems, the corresponding TAI +# timestamp would be obtained by advancing to the next entry in the +# following table when the time equivalent to 23:59:59 UTC +# is used for the second time. Thus the leap second which +# occurred on 30 June 1972 at 23:59:59 UTC would have TAI +# timestamps computed as follows: +# +# ... +# 30 June 1972 23:59:59 (2287785599, first time): TAI= UTC + 10 seconds +# 30 June 1972 23:59:60 (2287785599,second time): TAI= UTC + 11 seconds +# 1 July 1972 00:00:00 (2287785600) TAI= UTC + 11 seconds +# ... +# +# If your system realizes the leap second by repeating 00:00:00 UTC twice +# (this is possible but not usual), then the advance to the next entry +# in the table must occur the second time that a time equivalent to +# 00:00:00 UTC is used. Thus, using the same example as above: +# +# ... +# 30 June 1972 23:59:59 (2287785599): TAI= UTC + 10 seconds +# 30 June 1972 23:59:60 (2287785600, first time): TAI= UTC + 10 seconds +# 1 July 1972 00:00:00 (2287785600,second time): TAI= UTC + 11 seconds +# ... +# +# in both cases the use of timestamps based on TAI produces a smooth +# time scale with no discontinuity in the time interval. However, +# although the long-term behavior of the time scale is correct in both +# methods, the second method is technically not correct because it adds +# the extra second to the wrong day. +# +# This complexity would not be needed for negative leap seconds (if they +# are ever used). The UTC time would skip 23:59:59 and advance from +# 23:59:58 to 00:00:00 in that case. The TAI offset would decrease by +# 1 second at the same instant. This is a much easier situation to deal +# with, since the difficulty of unambiguously representing the epoch +# during the leap second does not arise. +# +# Some systems implement leap seconds by amortizing the leap second +# over the last few minutes of the day. The frequency of the local +# clock is decreased (or increased) to realize the positive (or +# negative) leap second. This method removes the time step described +# above. Although the long-term behavior of the time scale is correct +# in this case, this method introduces an error during the adjustment +# period both in time and in frequency with respect to the official +# definition of UTC. +# +# Questions or comments to: +# Judah Levine +# Time and Frequency Division +# NIST +# Boulder, Colorado +# Judah.Levine@nist.gov +# +# Last Update of leap second values: 8 July 2016 +# +# The following line shows this last update date in NTP timestamp +# format. This is the date on which the most recent change to +# the leap second data was added to the file. This line can +# be identified by the unique pair of characters in the first two +# columns as shown below. +# +#$ 3676924800 +# +# The NTP timestamps are in units of seconds since the NTP epoch, +# which is 1 January 1900, 00:00:00. The Modified Julian Day number +# corresponding to the NTP time stamp, X, can be computed as +# +# X/86400 + 15020 +# +# where the first term converts seconds to days and the second +# term adds the MJD corresponding to the time origin defined above. +# The integer portion of the result is the integer MJD for that +# day, and any remainder is the time of day, expressed as the +# fraction of the day since 0 hours UTC. The conversion from day +# fraction to seconds or to hours, minutes, and seconds may involve +# rounding or truncation, depending on the method used in the +# computation. +# +# The data in this file will be updated periodically as new leap +# seconds are announced. In addition to being entered on the line +# above, the update time (in NTP format) will be added to the basic +# file name leap-seconds to form the name leap-seconds.. +# In addition, the generic name leap-seconds.list will always point to +# the most recent version of the file. +# +# This update procedure will be performed only when a new leap second +# is announced. +# +# The following entry specifies the expiration date of the data +# in this file in units of seconds since the origin at the instant +# 1 January 1900, 00:00:00. This expiration date will be changed +# at least twice per year whether or not a new leap second is +# announced. These semi-annual changes will be made no later +# than 1 June and 1 December of each year to indicate what +# action (if any) is to be taken on 30 June and 31 December, +# respectively. (These are the customary effective dates for new +# leap seconds.) This expiration date will be identified by a +# unique pair of characters in columns 1 and 2 as shown below. +# In the unlikely event that a leap second is announced with an +# effective date other than 30 June or 31 December, then this +# file will be edited to include that leap second as soon as it is +# announced or at least one month before the effective date +# (whichever is later). +# If an announcement by the IERS specifies that no leap second is +# scheduled, then only the expiration date of the file will +# be advanced to show that the information in the file is still +# current -- the update time stamp, the data and the name of the file +# will not change. +# +# Updated through IERS Bulletin C52 +# File expires on: 28 June 2017 +# +#@ 3707596800 +# +2272060800 10 # 1 Jan 1972 +2287785600 11 # 1 Jul 1972 +2303683200 12 # 1 Jan 1973 +2335219200 13 # 1 Jan 1974 +2366755200 14 # 1 Jan 1975 +2398291200 15 # 1 Jan 1976 +2429913600 16 # 1 Jan 1977 +2461449600 17 # 1 Jan 1978 +2492985600 18 # 1 Jan 1979 +2524521600 19 # 1 Jan 1980 +2571782400 20 # 1 Jul 1981 +2603318400 21 # 1 Jul 1982 +2634854400 22 # 1 Jul 1983 +2698012800 23 # 1 Jul 1985 +2776982400 24 # 1 Jan 1988 +2840140800 25 # 1 Jan 1990 +2871676800 26 # 1 Jan 1991 +2918937600 27 # 1 Jul 1992 +2950473600 28 # 1 Jul 1993 +2982009600 29 # 1 Jul 1994 +3029443200 30 # 1 Jan 1996 +3076704000 31 # 1 Jul 1997 +3124137600 32 # 1 Jan 1999 +3345062400 33 # 1 Jan 2006 +3439756800 34 # 1 Jan 2009 +3550089600 35 # 1 Jul 2012 +3644697600 36 # 1 Jul 2015 +3692217600 37 # 1 Jan 2017 +# +# the following special comment contains the +# hash value of the data in this file computed +# use the secure hash algorithm as specified +# by FIPS 180-1. See the files in ~/pub/sha for +# the details of how this hash value is +# computed. Note that the hash computation +# ignores comments and whitespace characters +# in data lines. It includes the NTP values +# of both the last modification time and the +# expiration time of the file, but not the +# white space on those lines. +# the hash line is also ignored in the +# computation. +# +#h dacf2c42 2c4765d6 3c797af8 2cf630eb 699c8c67 diff --git a/cookbooks/ntp/files/default/usr.sbin.ntpd.apparmor b/cookbooks/ntp/files/default/usr.sbin.ntpd.apparmor new file mode 100644 index 0000000..7dfbeb0 --- /dev/null +++ b/cookbooks/ntp/files/default/usr.sbin.ntpd.apparmor @@ -0,0 +1,88 @@ +# vim:syntax=apparmor +# +# Maintained by Chef +# +# Updated for Ubuntu by: Jamie Strandboge +# ------------------------------------------------------------------ +# +# Copyright (C) 2002-2005 Novell/SUSE +# Copyright (C) 2009-2012 Canonical Ltd. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of version 2 of the GNU General Public +# License published by the Free Software Foundation. +# +# ------------------------------------------------------------------ + +#include +#include +/usr/sbin/ntpd { + #include + #include + #include + + capability ipc_lock, + capability net_bind_service, + capability setgid, + capability setuid, + capability sys_chroot, + capability sys_resource, + capability sys_time, + capability sys_nice, + + network inet dgram, + network inet6 dgram, + network inet stream, + network inet6 stream, + + @{PROC}/net/if_inet6 r, + @{PROC}/*/net/if_inet6 r, + @{NTPD_DEVICE} rw, + + /{,s}bin/ r, + /usr/{,s}bin/ r, + /usr/local/{,s}bin/ r, + /usr/sbin/ntpd rmix, + + /opt/chef/embedded/bin/ r, + + /etc/ntp.conf r, + /etc/ntp.conf.dhcp r, + /etc/ntpd.conf r, + /etc/ntpd.conf.tmp r, + /var/lib/ntp/ntp.conf.dhcp r, + + /etc/ntp.leapseconds r, + + /etc/ntp.keys r, + /etc/ntp/** r, + + /etc/ntp.drift rwl, + /etc/ntp.drift.TEMP rwl, + /etc/ntp/drift* rwl, + /var/lib/ntp/*drift rw, + /var/lib/ntp/*drift.TEMP rw, + + /var/log/ntp w, + /var/log/ntp.log w, + /var/log/ntpd w, + /var/log/ntpstats/clockstats* rwl, + /var/log/ntpstats/loopstats* rwl, + /var/log/ntpstats/peerstats* rwl, + /var/log/ntpstats/rawstats* rwl, + /var/log/ntpstats/sysstats* rwl, + + /{,var/}run/ntpd.pid w, + + # samba4 ntp signing socket + /{,var/}run/samba/ntp_signd/socket rw, + + # For use with clocks that report via shared memory (e.g. gpsd), + # you may need to give ntpd access to all of shared memory, though + # this can be considered dangerous. See https://launchpad.net/bugs/722815 + # for details. To enable, add this to local/usr.sbin.ntpd: + # capability ipc_owner, + + # Site-specific additions and overrides. See local/README for details. + #include +} diff --git a/cookbooks/ntp/libraries/ntp_helper.rb b/cookbooks/ntp/libraries/ntp_helper.rb new file mode 100644 index 0000000..8560994 --- /dev/null +++ b/cookbooks/ntp/libraries/ntp_helper.rb @@ -0,0 +1,49 @@ +# +# Author:: Julian C. Dunn () +# Cookbook:: ntp +# Library:: helper +# +# Copyright:: 2014-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require 'chef/mixin/shell_out' + +module Opscode + module Ntp + # Helper methods for ntp + module Helper + include Chef::Mixin::ShellOut + + def ntpd_supports_native_leapfiles + ntpd_version = determine_ntpd_version + if ntpd_version + ntpd_version =~ /ntpd.*(\d+\.\d+\.\d+)/ + # Abuse of Gem::Requirement, but it works + Gem::Requirement.new('>= 4.2.6').satisfied_by?(Gem::Version.new(Regexp.last_match(1))) + else + false + end + end + + private + + def determine_ntpd_version + cmd = shell_out!('ntpd --version 2>&1') + cmd.stdout.strip + rescue Errno::ENOENT, Mixlib::ShellOut::ShellCommandFailed + nil + end + end + end +end diff --git a/cookbooks/ntp/metadata.json b/cookbooks/ntp/metadata.json new file mode 100644 index 0000000..8791de2 --- /dev/null +++ b/cookbooks/ntp/metadata.json @@ -0,0 +1 @@ +{"name":"ntp","version":"3.4.0","description":"Installs and configures ntp as a client or server","long_description":"# NTP Cookbook\n\n[![Build Status](https://travis-ci.org/chef-cookbooks/ntp.svg?branch=master)](http://travis-ci.org/chef-cookbooks/ntp) [![Cookbook Version](https://img.shields.io/cookbook/v/ntp.svg)](https://supermarket.chef.io/cookbooks/ntp)\n\nInstalls and configures ntp. On Windows systems it uses the Meinberg port of the standard NTPd client to Windows.\n\n## Requirements\n\n### Platforms\n\n- Debian-family Linux Distributions\n- RedHat-family Linux Distributions\n- Fedora\n- Gentoo Linux\n- openSUSE\n- FreeBSD\n- Windows 2008 R2+\n- Mac OS X 10.11+\n\n### Chef\n\n- Chef 12.1+\n\n### Cookbooks\n\n- none\n\n## Attributes\n\n### Recommended tunables\n\n- `ntp['servers']` - (applies to NTP Servers and Clients)\n\n - Array, should be a list of upstream NTP servers that will be considered authoritative by the local NTP daemon. The local NTP daemon will act as a client, adjusting local time to match time data retrieved from the upstream NTP servers.\n\n The NTP protocol works best with at least 4 servers. The ntp daemon will disregard any server after the 10th listed, but will continue monitoring all listed servers. For more information, see [Upstream Server Time Quantity](http://support.ntp.org/bin/view/Support/SelectingOffsiteNTPServers#Section_5.3.3.) at [support.ntp.org](http://support.ntp.org).\n\n- `ntp['peers']` - (applies to NTP Servers ONLY)\n\n - Array, should be a list of local NTP peers. For more information, see [Designing Your NTP Network](http://support.ntp.org/bin/view/Support/DesigningYourNTPNetwork) at [support.ntp.org](http://support.ntp.org).\n\n- `ntp['restrictions']` - (applies to NTP Servers only)\n\n - Array, should be a list of restrict lines to define access to NTP clients on your LAN.\n\n- `ntp['sync_clock']` (applies to NTP Servers and Clients)\n\n - Boolean. Defaults to false. Forces the ntp daemon to be halted, an ntp -q command to be issued, and the ntp daemon to be restarted again on every Chef-client run. Will have no effect if drift is over 1000 seconds.\n\n- `ntp['sync_hw_clock']` (applies to NTP Servers and Clients)\n\n - Boolean. Defaults to false. On *nix-based systems, forces the 'hwclock --systohc' command to be issued on every Chef-client run. This will sync the hardware clock to the system clock.\n - Not available on Windows.\n\n- `ntp['restrict_default']`\n\n - String. Defaults to 'kod notrap nomodify nopeer noquery'. Set to 'ignore' to [further lock down access](http://support.ntp.org/bin/view/Support/AccessRestrictions#Section_6.5.1.1.2.).\n\n- `ntp[\"listen_network\"]` / `ntp[\"listen\"]`\n\n - String, optional attribute. Default is for NTP to listen on all addresses.\n - `ntp[\"listen_network\"]` should be set to 'primary' to listen on the node's primary IP address as determined by ohai, or set to a CIDR (eg: '192.168.4.0/24') to listen on the last node address on that CIDR.\n - `ntp[\"listen\"]` can be set to a specific address (eg: '192.168.4.10') instead of `ntp[\"listen_network\"]` to force listening on a specific address.\n - If both `ntp[\"listen\"]` and `ntp[\"listen_network\"]` are set then `ntp[\"listen\"]` will always win.\n\n- `ntp[\"ignore\"]`\n\n - Array, interface names to ignore from listening. Can be used to disable listening wildcard interfaces (eg: ['wildcard', '::1']), can be combined with `ntp[\"listen\"]`\n\n- `ntp[\"statistics\"]`\n\n - Boolean. Default to true. Enable/disable statistics data logging into `ntp['statsdir']`.\n - Not available on Windows.\n\n- `ntp['conf_restart_immediate']`\n\n - Boolean. Defaults to false. Restarts NTP service immediately after a config update if true. Otherwise it is a delayed restart.\n\n- `ntp['peer']['disable_tinker_panic_on_virtualization_guest']` (applies to virtualized hosts only)\n\n - Boolean. Defaults to true. Sets tinker panic to 0\\. NTP default it 1000\\. (See p. 23 for explanation on disabling panic) (Note: this overrides `ntp['tinker']['panic']` attribute)\n\n- `ntp['peer']['use_iburst']` (applies to NTP Servers ONLY)\n\n - Boolean. Defaults to true. Enables iburst in peer declaration.\n\n- `ntp['peer']['use_burst']` (applies to NTP Servers ONLY)\n\n - Boolean. Defaults to false. Enables burst in peer declaration.\n\n- `ntp['peer']['minpoll']` (applies to NTP Servers ONLY)\n\n - Boolean. Defaults to 6 (ntp default). Specify the minimum poll intervals for NTP messages, in seconds to the power of two.\n\n- `ntp['peer']['maxpoll']` (applies to NTP Servers ONLY)\n\n - Boolean. Defaults to 10 (ntp default). Specify the maximum poll intervals for NTP messages, in seconds to the power of two.\n\n- `ntp['server']['prefer']` (applies to NTP Servers and Clients)\n\n - String. Defaults to emtpy string. The server from `ntp['servers']` to prefer getting the time from.\n\n- `ntp['server']['use_iburst']` (applies to NTP Servers and Clients)\n\n - Boolean. Defaults to true. Enables iburst in server declaration.\n\n- `ntp['server']['use_burst']` (applies to NTP Servers and Clients)\n\n - Boolean. Defaults to false. Enables burst in server declaration.\n\n- `ntp['server']['minpoll']` (applies to NTP Servers and Clients)\n\n - Boolean. Defaults to 6 (ntp default). Specify the minimum poll intervals for NTP messages, in seconds to the power of two.\n\n- `ntp['server']['maxpoll']` (applies to NTP Servers and Clients)\n\n - Boolean. Defaults to 10 (ntp default). Specify the maximum poll intervals for NTP messages, in seconds to the power of two.\n\n- `ntp['tinker']['allan']`\n\n - Number. Defaults to 1500 (ntp default). Spedifies the Allan intercept, which is a parameter of the PLL/FLL clock discipline algorithm, in seconds.\n\n- `ntp['tinker']['dispersion']`\n\n - Number. Defaults to 15 (ntp default). Specifies the dispersion increase rate in parts-per-million (PPM).\n\n- `ntp['tinker']['panic']`\n\n - Number. Defaults to 1000 (ntp default). Spedifies the panic threshold in seconds. If set to zero, the panic sanity check is disabled and a clock offset of any value will be accepted.\n\n- `ntp['tinker']['step']`\n\n - Number. Defaults to 0.128 (ntp default). Spedifies the step threshold in seconds. If set to zero, step adjustments will never occur. Note: The kernel time discipline is disabled if the step threshold is set to zero or greater than 0.5 s.\n\n- `ntp['tinker']['stepout']`\n\n - Number. Defaults to 900 (ntp default). Specifies the stepout threshold in seconds. If set to zero, popcorn spikes will not be suppressed.\n\n- `ntp['localhost']['noquery']` (applies to NTP Servers and Clients)\n\n - Boolean. Defaults to false. Set to true if using ntp < 4.2.8 or any unpatched ntp version to mitigate CVE-2014-9293 / CVE-2014-9294 / CVE-2014-9295\n\n- `ntp['orphan']['enabled']`\n\n - Boolean, enables orphan mode if set to true\n\n- `ntp['orphan']['stratum']`\n\n - Number. Defaults to 5, recommended value for stratum is 2 more than the worst-case externally-reachable source of time\n\n### Automatically Set Attributes\n\nThese attributes are set based on platform / system information provided by Ohai\n\n- `ntp['packages']`\n\n - Array, the packages to install\n - Default, ntp for everything, ntpdate depending on platform. Not applicable for\n - Windows nodes\n\n- `ntp['service']`\n\n - String, the service to act on\n - Default, ntp, NTP, or ntpd, depending on platform\n\n- `ntp['varlibdir']`\n\n - String, the path to /var/lib files such as the driftfile.\n - Default, platform-specific location. Not applicable for Windows nodes\n\n- `ntp['driftfile']`\n\n - String, the path to the frequency file.\n - Default, platform-specific location.\n\n- `ntp['conffile']`\n\n - String, the path to the ntp configuration file.\n - Default, platform-specific location.\n\n- `ntp['statsdir']`\n\n - String, the directory path for files created by the statistics facility.\n - Default, platform-specific location. Not applicable for Windows nodes\n\n- `ntp['conf_owner'] and ntp['conf_group']`\n\n - String, the owner and group of the sysconf directory files, such as /etc/ntp.conf.\n - Default, platform-specific root:root or root:wheel.\n\n- `ntp['var_owner'] and ntp['var_group']`\n\n - String, the owner and group of the /var/lib directory files, such as /var/lib/ntp.\n - Default, platform-specific ntp:ntp or root:wheel. Not applicable for Windows nodes\n\n- `ntp['leapfile']`\n\n - String, the path to the ntp leapfile.\n - Default, /etc/ntp.leapseconds.\n\n- `ntp['package_url']`\n\n - String, the URL to the the Meinberg NTPd client installation package.\n - Default, Meinberg site download URL\n - Windows platform only\n\n- `ntp['vs_runtime_url']`\n\n - String, the URL to the the Visual Studio C++ 2008 runtime libraries that are required for the Meinberg NTP client.\n - Default, Microsoft site download URL\n - Windows platform only\n\n- `ntp['vs_runtime_productname']`\n\n - String, the installation name of the Visual Studio C++ Runtimes file.\n - Default, \"Microsoft Visual C++ 2008 Redistributable - x86 9.0.21022\"\n - Windows platform only\n\n- `ntp['sync_hw_clock']`\n\n - Boolean, determines if the ntpdate command is issued to sync the hardware clock\n - Default, false\n - Not applicable for Windows nodes\n\n- `ntp['apparmor_enabled']`\n\n - Boolean, enables configuration of apparmor if set to true\n - Defaults to false and will make no provisions for apparmor.\n - If a platform has apparmor enabled (currently Ubuntu) default will become true.\n\n- `ntp['use_cmos']`\n\n - Boolean, uses a high stratum undisciplined clock for machines with real CMOS clock.\n - Defaults to true unless a platform appears to be virtualized according to Ohai.\n\n## Usage\n\n### default recipe\n\nSet up the ntp attributes in a role. For example in a base.rb role applied to all nodes:\n\n```ruby\nname 'base'\ndescription 'Role applied to all systems'\ndefault_attributes(\n 'ntp' => {\n 'servers' => ['time0.int.example.org', 'time1.int.example.org']\n }\n)\n```\n\nThen in an ntpserver.rb role that is applied to NTP servers (e.g., time.int.example.org):\n\n```ruby\nname 'ntp_server'\ndescription 'Role applied to the system that should be an NTP server.'\ndefault_attributes(\n 'ntp' => {\n 'servers' => ['0.pool.ntp.org', '1.pool.ntp.org'],\n 'peers' => ['time0.int.example.org', 'time1.int.example.org'],\n 'restrictions' => ['10.0.0.0 mask 255.0.0.0 nomodify notrap']\n }\n)\n```\n\nThe timeX.int.example.org used in these roles should be the names or IP addresses of internal NTP servers. Then simply add ntp, or `ntp::default` to your run_list to apply the ntp daemon's configuration.\n\n### windows_client recipe\n\nWindows only. Apply on a Windows host to install the Meinberg NTPd client.\n\n### mac_os_x_client recipe\n\nMac OS X only. Apply on a Mac OS X host to configure NTP.\n\n## License & Authors\n\n- Author:: Joshua Timberman ([joshua@chef.io](mailto:joshua@chef.io))\n- Contributor:: Eric G. Wolfe ([wolfe21@marshall.edu](mailto:wolfe21@marshall.edu))\n- Contributor:: Fletcher Nichol ([fletcher@nichol.ca](mailto:fletcher@nichol.ca))\n- Contributor:: Tim Smith ([tsmith@chef.io](mailto:tsmith@chef.io))\n- Contributor:: Charles Johnson ([charles@chef.io](mailto:charles@chef.io))\n- Contributor:: Brad Knowles ([bknowles@momentumsi.com](mailto:bknowles@momentumsi.com))\n\n```text\nCopyright 2009-2016, Chef Software, Inc.\nCopyright 2012, Eric G. Wolfe\nCopyright 2012, Fletcher Nichol\nCopyright 2012, Webtrends, Inc.\nCopyright 2013, Limelight Networks, Inc.\nCopyright 2013, Brad Knowles\nCopyright 2013, Brad Beam\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"amazon":">= 0.0.0","centos":">= 0.0.0","debian":">= 0.0.0","fedora":">= 0.0.0","freebsd":">= 0.0.0","gentoo":">= 0.0.0","redhat":">= 0.0.0","scientific":">= 0.0.0","solaris2":">= 0.0.0","oracle":">= 0.0.0","ubuntu":">= 0.0.0","windows":">= 0.0.0","mac_os_x":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{"ntp":"Installs and configures ntp either as a server or client"},"source_url":"https://github.com/chef-cookbooks/ntp","issues_url":"https://github.com/chef-cookbooks/ntp/issues","chef_version":[[">= 12.1"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/ntp/recipes/apparmor.rb b/cookbooks/ntp/recipes/apparmor.rb new file mode 100644 index 0000000..e5b19db --- /dev/null +++ b/cookbooks/ntp/recipes/apparmor.rb @@ -0,0 +1,30 @@ +# +# Cookbook:: ntp +# Recipe:: apparmor +# Author:: Scott Lampert () +# +# Copyright:: 2013-2017, Scott Lampert +# +# 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. + +service 'apparmor' do + action :nothing +end + +cookbook_file '/etc/apparmor.d/usr.sbin.ntpd' do + source 'usr.sbin.ntpd.apparmor' + owner 'root' + group 'root' + mode '0644' + notifies :restart, 'service[apparmor]' +end diff --git a/cookbooks/ntp/recipes/default.rb b/cookbooks/ntp/recipes/default.rb new file mode 100644 index 0000000..7b61f75 --- /dev/null +++ b/cookbooks/ntp/recipes/default.rb @@ -0,0 +1,129 @@ +# +# Cookbook:: ntp +# Recipe:: default +# Author:: Joshua Timberman () +# Author:: Tim Smith () +# +# Copyright:: 2009-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +::Chef::Resource.send(:include, Opscode::Ntp::Helper) + +case node['platform_family'] +when 'windows' + include_recipe 'ntp::windows_client' +when 'mac_os_x' + include_recipe 'ntp::mac_os_x_client' + # On OS X we only support simple client config and nothing more + return 0 +else + + node['ntp']['packages'].each do |ntppkg| + package ntppkg + end + + package 'Remove ntpdate' do + package_name 'ntpdate' + action :remove + only_if { node['platform_family'] == 'debian' && node['platform_version'].to_i >= 16 } + end + + [node['ntp']['varlibdir'], node['ntp']['statsdir']].each do |ntpdir| + directory ntpdir do + owner node['ntp']['var_owner'] + group node['ntp']['var_group'] + mode '0755' + end + end + + cookbook_file node['ntp']['leapfile'] do + owner node['ntp']['conf_owner'] + group node['ntp']['conf_group'] + mode '0644' + source 'ntp.leapseconds' + notifies :restart, "service[#{node['ntp']['service']}]" + end + + include_recipe 'ntp::apparmor' if node['ntp']['apparmor_enabled'] +end + +if node['ntp']['servers'].empty? + node.default['ntp']['servers'] = [ + '0.pool.ntp.org', + '1.pool.ntp.org', + '2.pool.ntp.org', + '3.pool.ntp.org', + ] + Chef::Log.debug 'No NTP servers specified, using default ntp.org server pools' +end + +if node['ntp']['listen'].nil? && !node['ntp']['listen_network'].nil? + if node['ntp']['listen_network'] == 'primary' + node.normal['ntp']['listen'] = node['ipaddress'] + else + require 'ipaddr' + net = IPAddr.new(node['ntp']['listen_network']) + + node['network']['interfaces'].each do |_iface, addrs| + addrs['addresses'].each do |ip, params| + addr = IPAddr.new(ip) if params['family'].eql?('inet') || params['family'].eql?('inet6') + node.normal['ntp']['listen'] = addr if net.include?(addr) + end + end + end +end + +node.default['ntp']['tinker']['panic'] = 0 if node['virtualization'] && + node['virtualization']['role'] == 'guest' && + node['ntp']['disable_tinker_panic_on_virtualization_guest'] + +template node['ntp']['conffile'] do + source 'ntp.conf.erb' + owner node['ntp']['conf_owner'] + group node['ntp']['conf_group'] + mode '0644' + notifies :restart, "service[#{node['ntp']['service']}]" unless node['ntp']['conf_restart_immediate'] + notifies :restart, "service[#{node['ntp']['service']}]", :immediately if node['ntp']['conf_restart_immediate'] + variables( + lazy { { ntpd_supports_native_leapfiles: ntpd_supports_native_leapfiles } } + ) +end + +if node['ntp']['sync_clock'] && !platform_family?('windows') + execute "Stop #{node['ntp']['service']} in preparation for ntpdate" do + command node['platform_family'] == 'freebsd' ? '/usr/bin/true' : '/bin/true' + action :run + notifies :stop, "service[#{node['ntp']['service']}]", :immediately + end + + execute 'Force sync system clock with ntp server' do + command node['platform_family'] == 'freebsd' ? 'ntpd -q' : "ntpd -q -u #{node['ntp']['var_owner']}" + action :run + notifies :start, "service[#{node['ntp']['service']}]" + end +end + +execute 'Force sync hardware clock with system clock' do + command 'hwclock --systohc' + action :run + only_if { node['ntp']['sync_hw_clock'] && !(platform_family?('windows') || platform_family?('freebsd')) } +end + +service node['ntp']['service'] do + supports status: true, restart: true + action [:enable, :start] + timeout 120 if platform_family?('windows') + retries 3 + retry_delay 5 +end diff --git a/cookbooks/ntp/recipes/mac_os_x_client.rb b/cookbooks/ntp/recipes/mac_os_x_client.rb new file mode 100644 index 0000000..a08dc05 --- /dev/null +++ b/cookbooks/ntp/recipes/mac_os_x_client.rb @@ -0,0 +1,32 @@ +# +# Cookbook:: ntp +# Recipe:: mac_os_x_client +# Author:: Antek S. Baranski () +# +# Copyright:: 2016-2017, Roblox, Inc +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Do not continue if trying to run the Mac OS X recipe on non-OS X platform +return 'The ntp::mac_os_x_client recipe only supports Mac OS X' unless platform_family?('mac_os_x') + +# Mac OS X 10.11+ does not allow for many NTP settings +execute 'systemsetup -setnetworktimeserver' do + command "systemsetup -setnetworktimeserver #{node['ntp']['servers'][0]}" + not_if "systemsetup -getnetworktimeserver | grep -F #{node['ntp']['servers'][0]}" +end + +execute 'systemsetup -setusingnetworktime' do + command 'systemsetup -setusingnetworktime on' + not_if 'systemsetup -getusingnetworktime | grep On' +end diff --git a/cookbooks/ntp/recipes/windows_client.rb b/cookbooks/ntp/recipes/windows_client.rb new file mode 100644 index 0000000..98a7213 --- /dev/null +++ b/cookbooks/ntp/recipes/windows_client.rb @@ -0,0 +1,45 @@ +# +# Cookbook:: ntp +# Recipe:: windows_client +# Author:: Tim Smith () +# +# Copyright:: 2012-2017, Webtrends, Inc +# Copyright:: 2013-2017, Limelight Networks, Inc +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Do not continue if trying to run the Windows recipe on non-Windows platform +return 'The ntp::windows_client recipe only supports Windows' unless platform_family?('windows') + +directory 'C:/NTP/etc' do + inherits true + action :create + recursive true +end + +cookbook_file 'C:/NTP/ntp.ini' do + source 'ntp.ini' + inherits true + action :create +end + +unless File.exist?('C:/NTP/bin/ntpd.exe') + remote_file "#{Chef::Config[:file_cache_path]}/ntpd.exe" do + source node['ntp']['package_url'] + end + + execute 'ntpd_install' do + command "#{Chef::Config[:file_cache_path]}\\ntpd.exe /USEFILE=C:\\NTP\\ntp.ini" + returns [0, 2] + end +end diff --git a/cookbooks/ntp/templates/default/ntp.conf.erb b/cookbooks/ntp/templates/default/ntp.conf.erb new file mode 100644 index 0000000..23b6d2b --- /dev/null +++ b/cookbooks/ntp/templates/default/ntp.conf.erb @@ -0,0 +1,102 @@ +# Auto-generated by Chef. +# Local modifications will be overwritten. +# +<%# Windows OHAI does not support determining if a host is a guest %> +<% unless node['platform'] == 'windows' -%> +<%-%>tinker <%= node['ntp']['tinker'].flatten.join(' ') %> +<%-%>statsdir <%= node['ntp']['statsdir'] %> +<% if @ntpd_supports_native_leapfiles -%> +<%-%>leapfile <%= node['ntp']['leapfile'] %> +<% end -%> +<% end -%> +driftfile <%= node['ntp']['driftfile'] %> +<% if node['ntp']['logfile'] -%> +<%-%>logfile <%= node['ntp']['logfile'] %> +<% end -%> + +<%# Enable logs only if statistics option is defined %> +<% if node['ntp']['statistics'] -%> +<%-%>statistics loopstats peerstats clockstats +<%-%>filegen loopstats file loopstats type day enable +<%-%>filegen peerstats file peerstats type day enable +<%-%>filegen clockstats file clockstats type day enable +<% end -%> + +<%# If the ignore attribute is set on the node, then apply it %> +<% unless node['ntp']['ignore'].nil? -%> +<% Array(node['ntp']['ignore']).each do |ignore| -%> +interface ignore <%= ignore %> +<% end -%> +<% end -%> + +<%# If the listen attribute is set on the node, then apply it %> +<% unless node['ntp']['listen'].nil? -%> +<% Array(node['ntp']['listen']).each do |listen| -%> +interface listen <%= listen %> +<% end -%> +<%# The service must always listen on localhost %> +<% unless Array(node['ntp']['listen']).include? '127.0.0.1' -%> +interface listen 127.0.0.1 +<% end -%> +<% end -%> + +<% if node['ntp']['monitor'] -%> +enable monitor +<% else -%> +disable monitor +<% end -%> + +<%# If ntp.peers is not empty %> +<% unless node['ntp']['peers'].empty? -%> +<% node['ntp']['peers'].sort.each do |ntppeer| -%> +<%# Don't peer with ourself %> +<% if node['ipaddress'] != ntppeer && node['fqdn'] != ntppeer -%> +<% -%>peer <%= ntppeer %><% if key = node['ntp']['peer']['key'] -%> key <%= key %><% end -%><% if node['ntp']['peer']['use_iburst'] -%> iburst<% end -%><% if node['ntp']['peer']['use_burst'] -%> burst<% end -%> minpoll <%= node['ntp']['peer']['minpoll'] %> maxpoll <%= node['ntp']['peer']['maxpoll'] %> +<% -%>restrict <%= ntppeer %> nomodify +<% end -%> +<% end -%> +<% end -%> + +<%# Whether this is a client or server, we want upstream servers. %> +<%# We should guard the servers array against deep merge. %> +<%# This should keep authoritative local servers from being included twice. %> +<% ( node['ntp']['servers'] - node['ntp']['peers'] ).sort.each do |ntpserver| -%> +<%# Loop through defined servers, but don't try to upstream ourself %> +<% if node['ipaddress'] != ntpserver and node['fqdn'] != ntpserver -%> +<% -%>server <%= ntpserver %><% if node['ntp']['server']['use_iburst'] -%> iburst<% end -%><% if node['ntp']['server']['use_burst'] -%> burst<% end -%> minpoll <%= node['ntp']['server']['minpoll'] %> maxpoll <%= node['ntp']['server']['maxpoll'] %><% if node['ntp']['server']['prefer'] == ntpserver -%> prefer<% end -%> +<% -%>restrict <%= ntpserver %> nomodify notrap noquery +<% end -%> +<% end -%> + +restrict default <%= node['ntp']['restrict_default'] %> +restrict 127.0.0.1<%if node['ntp']['localhost']['noquery'] -%> noquery<% end -%> +restrict -6 default <%= node['ntp']['restrict_default'] %> +restrict -6 ::1<%if node['ntp']['localhost']['noquery'] -%> noquery<% end -%> + +<%# If this is a server with additional LAN restriction lines, put them here %> +<% unless node['ntp']['restrictions'].empty? -%> +<% node['ntp']['restrictions'].each do |restriction| -%> +<% -%>restrict <%= restriction %> +<% end -%> +<% end -%> + +<%# It is best practice to use a high stratum undisciplined clock, if you have a real CMOS clock %> +<%# Except cases where you have a low stratum server, or a virtualized system without a real CMOS clock %> +<% if node['ntp']['use_cmos'] -%> +<% -%>server 127.127.1.0 # local clock +<% -%>fudge 127.127.1.0 stratum 10 +<% end -%> + +<% if node['ntp']['orphan']['enabled'] -%> +tos orphan <%= node['ntp']['orphan']['stratum'] %> +<% end -%> + +<% if node['ntp']['keys'] -%> +keys <%= node['ntp']['keys'] %> +<% end -%> +<% if node['ntp']['trustedkey'] -%> +trustedkey <%= node['ntp']['trustedkey'] %> +<% end -%> +<% if node['ntp']['requestkey'] -%> +requestkey <%= node['ntp']['requestkey'] %> +<% end -%> diff --git a/cookbooks/ohai/CHANGELOG.md b/cookbooks/ohai/CHANGELOG.md new file mode 100644 index 0000000..8d3c45d --- /dev/null +++ b/cookbooks/ohai/CHANGELOG.md @@ -0,0 +1,195 @@ +# ohai Cookbook CHANGELOG + +This file is used to list changes made in each version of the ohai cookbook. + +## 5.2.5 (2018-09-04) + +- Add note that ohai_hint will be removed April 2019 when Chef 13 goes EOL as this resource now ships in Chef 14+ + +## 5.2.4 (2018-08-28) + +- Avoid deprecation warnings in Chef 14.3+ by not loading resources already in Chef + +## 5.2.3 (2018-06-08) + +- Make sure we properly compare a provided plugin path to the path on disk by stripping trailing slashes from the provided directory +- Don't reload ohai when the plugin exists in a subdirectory of the config's set plugin path + +## 5.2.2 (2018-02-15) + +- Remove ChefSpec matchers we no longer need since they're auto generated + +## 5.2.1 (2018-01-25) + +- Switch from a .foodcritic file to an inline comments which resolve Supermarket warnings +- Remove unused helper method + +## 5.2.0 (2017-08-17) + +- Resolve multiple issues with Windows paths that caused the cookbook to converge on every run or fail +- Move maintainer information to the readme +- Add testing on Chef 12.7 in Travis +- Move helpers to their own modules and add testing framework + +## 5.1.0 (2017-05-06) + +- Workaround action_class bug by requiring Chef 12.7+ + +## 5.0.4 (2017-04-25) + +- Fix lack of .rb extension when deleting plugins. + +## 5.0.3 (2017-04-06) + +- Use class_eval again in the custom resource to provide Chef 12.5/12.6 compatibility +- Remove kind_of and use name_property not name_attribute +- Fix failures on Chef 13 + +## 5.0.2 (2017-03-24) + +- Remove class_eval + +## 5.0.1 (2017-03-14) + +- Test with Delivery Local Mode +- Bump the dependency to 12.7+ due to failures on 12.5-12.6 + +## 5.0.0 (2017-02-23) + +- Require Chef 12.5+ and remove compat_resource dependency + +## 4.2.3 (2016-12-02) +- Prevent chef_version metadata from failing runs in Opsworks +- Better explain how to resolve the plugin_path issue +- Add suse as a supported platform +- Require at least compat_resource 12.14.7 + +## 4.2.2 (2016-09-19) +- Ignore case in plugin path check on Windows + +## 4.2.1 (2016-09-08) +- Fix typo in compile warning text +- Depend on the latest compat_resource (12.14) +- Remove Chef 11 compat in the metadata +- Require Chef 12.1 not 12.0 +- Define ohai_plugin matcher for Chefspec + +## v4.2.0 (2016-07-19) + +- Added the ability to specify the source cookbook for the cookbook_file or template used in the ohai_plugin resource. +- Added chef_version to the metadata +- Added testing on openSUSE and switched from Rubocop to Cookstyle + +## v4.1.1 (2016-06-16) + +- Fixed error in notifies reload for the delete action +- Bump the compat_resource requirement from 12.9+ to 12.10+ to prevent random failures + +## v4.1.0 (2016-05-26) + +- Added the ability to use templates and pass in variables with the plugin custom resource + +## v4.0.2 (2016-05-23) + +- Resolve failures on Windows nodes + +## v4.0.1 (2016-05-19) + +- Added .rb to the name of the plugins so they actually load +- Added testing to ensure the plugins are being loaded in the chef run + +## v4.0.0 (2016-05-18) + +### BREAKING CHANGE: + +The 4.0 release of the Ohai cookbook removes the previous cookbook_file behavior that required forking the cookbook and adding your own plugins. Instead the cookbook ships with a new ohai_plugin custom resource for installing plugins. In addition to this new custom resource the cookbook now requires Chef 12+. See the readme and test recipe for examples. If you require Chef 11 support you'll need to pin to version 3.0 in your environment. + +## v3.0.1 (2016-03-14) + +- Fixed the Chefspec matchers + +## v3.0.0 (2016-03-14) + +- Change the default value for `node['ohai']['hints_path']` to use the Ohai config value. This should be the same value in most use cases, but if a custom path is specified in the chef client config this value will get used automatically by the cookbook. +- Removed backwards compatibility with Chefspec < 4.1 in the matchers library +- Fix bad link to the custom Ohai plugin documentation in the readme +- Improve documentation for `node['ohai']['plugin_path']` + +## v2.1.0 (2016-01-26) + +- Properly handle creating ohai hints without specifying the content. Previously if the content wasn't specified a deprecation notice would be thrown and the file would not be created +- Simplified the test suite and added inspec tests to ensure hints are created, especially if the content is not specified +- Added FreeBSD and Windows as supported platform in the metadata and add them to the Test Kitchen config +- Add Test Kitchen integration tests to Travis CI +- Updated testing Gems to the latest releases in the Gemfile + +## v2.0.4 (2015-10-30) + +- Resolved deprecation warnings with the Chefspec matchers + +## v2.0.3 (2015-10-21) + +- Validate the hints before loading them to avoid failures +- Added supported platforms to the metadata +- Updated .gitignore file +- Updated Test Kitchen config for the latest platforms +- Added Chef standard Rubocop config +- Added Travis CI testing +- Added Berksfile +- Updated contributing and testing docs +- Added maintainers.md and maintainers.toml files +- Added Travis and cookbook version badges to the readme +- Expanded the requirements section in the readme and clarify the minimum supported Chef release is 11 +- Updated Opscode -> Chef Software +- Added a Rakefile for simplified testing +- Added a Chefignore file +- Resolved Rubocop warnings +- Added source_url and issues_url to the metadata +- Added Chefspec matchers +- Added basic convergence Chefspec test + +## v2.0.1 (2014-06-07) + +- [COOK-4683] Remove warnings about reopening resource + +Please note, this changes the name of a remote_directory resource. It is not expected that anyone would be explicitly notifying this resource but, please review [PR #16](https://github.com/chef-cookbooks/ohai/pull/16/files) for more info. + +## v2.0.0 (2014-02-25) + +'[COOK-3865] - create lwrp ohai_hint' + +## v1.1.12 + +- Dummy release due to a Community Site upload failure + +## v1.1.10 + +### Bug + +- **[COOK-3091](https://tickets.chef.io/browse/COOK-3091)** - Fix checking `Chef::Config[:config_file]` + +## v1.1.8 + +- [COOK-1918] - Ohai cookbook to distribute plugins fails on windows +- [COOK-2096] - Ohai cookbook sets unix-only default path attribute + +## v1.1.6 + +- [COOK-2057] - distribution from another cookbok fails if ohai attributes are loaded after the other cookbook + +## v1.1.4 + +- [COOK-1128] - readme update, Replace reference to deprecated chef cookbook with one to chef-client + +## v1.1.2 + +- [COOK-1424] - prevent plugin_path growth to infinity + +## v1.1.0 + +- [COOK-1174] - custom_plugins is only conditionally available +- [COOK-1383] - allow plugins from other cookbooks + +## v1.0.2 + +- [COOK-463] ohai cookbook default recipe should only reload plugins if there were updates diff --git a/cookbooks/ohai/CONTRIBUTING.md b/cookbooks/ohai/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/ohai/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/cookbooks/ohai/README.md b/cookbooks/ohai/README.md new file mode 100644 index 0000000..84c0113 --- /dev/null +++ b/cookbooks/ohai/README.md @@ -0,0 +1,138 @@ +# ohai Cookbook + +[![Build Status](https://travis-ci.org/chef-cookbooks/ohai.svg?branch=master)](https://travis-ci.org/chef-cookbooks/ohai) [![Build status](https://ci.appveyor.com/api/projects/status/lgok2kr6l007s8hf/branch/master?svg=true)](https://ci.appveyor.com/project/ChefWindowsCookbooks/ohai/branch/master) [![Cookbook Version](https://img.shields.io/cookbook/v/ohai.svg)](https://supermarket.chef.io/cookbooks/ohai) + +Contains custom resources for adding Ohai hints and installing custom Ohai plugins. Handles path creation as well as the reloading of Ohai so that new data will be available during the same run. + +NOTE: The ohai_hint resource shipped in Chef 14.0 (April 2018). When Chef 15.0 is released (April 2019) and Chef 13 goes EOL the ohai_hint resource will be removed from this cookbook. + +## Requirements + +### Platforms + +- Debian/Ubuntu +- RHEL/CentOS/Scientific/Amazon/Oracle +- openSUSE / SUSE Enterprise Linux +- FreeBSD +- Windows + +### Chef + +- Chef 12.7+ + +### Cookbooks + +- none + +## Custom Resources + +### `ohai_hint` + +Creates Ohai hint files, which are consumed by Ohai plugins in order to determine if they should run or not. + +#### Resource Attributes + +- `hint_name` - The name of hints file and key. Should be string, default is name of resource. +- `content` - Values of hints. It will be used as automatic attributes. Should be Hash, default is empty Hash +- `compile_time` - Should the resource run at compile time. This defaults to true + +#### Examples + +Hint file installed to the default directory: + +```ruby +ohai_hint 'ec2' +``` + +Hint file not installed at compile time: + +```ruby +ohai_hint 'ec2' do + compile_time false +end +``` + +Hint file installed with content: + +```ruby +ohai_hint 'raid_present' do + content Hash[:a, 'test_content'] +end +``` + +#### ChefSpec Matchers + +You can check for the creation or deletion of ohai hints with chefspec using these custom matches: + +- create_ohai_hint +- delete_ohai_hint + +### `ohai_plugin` + +Installs custom Ohai plugins. + +#### Resource Attributes + +- `plugin_name` - The name to give the plugin on the filesystem. Should be string, default is name of resource. +- `path` - The path to your custom plugin directory. Defaults to a directory named 'plugins' under the directory 'ohai' in the Chef config dir. +- `source_file` - The source file for the plugin in your cookbook if not NAME.rb. +- `cookbook` - The cookbook where the source file exists if not the cookbook where the ohai_plugin resource is running from. +- `resource` - The resource type for the plugin file. Either `:cookbook_file` or `:template`. Defaults to `:cookbook_file`. +- `variables` - Usable only if `resource` is `:template`. Defines the template's variables. +- `compile_time` - Should the resource run at compile time. This defaults to `true`. + +#### examples + +Simple Ohai plugin installation: + +```ruby +ohai_plugin 'my_custom_plugin' +``` + +Installation where the resource doesn't match the filename and you install to a custom plugins dir: + +```ruby +ohai_plugin 'My Ohai Plugin' do + name 'my_custom_plugin' + path '/my/custom/path/' +end +``` + +Installation using a template: + +```ruby +ohai_plugin 'My Templated Plugin' do + name 'templated_plugin' + resource :template + variables node_type: :web_server +end +``` + +#### ChefSpec Matchers + +You can check for the creation or deletion of ohai plugins with chefspec using these custom matches: + +- create_ohai_plugin +- delete_ohai_plugin + +## Maintainers + +This cookbook is maintained by Chef's Community Cookbook Engineering team. Our goal is to improve cookbook quality and to aid the community in contributing to cookbooks. To learn more about our team, process, and design goals see our [team documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/COOKBOOK_TEAM.MD). To learn more about contributing to cookbooks like this see our [contributing documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD), or if you have general questions about this cookbook come chat with us in #cookbok-engineering on the [Chef Community Slack](http://community-slack.chef.io/) + +## License + +**Copyright:** 2011-2016, Chef Software, Inc. + +``` +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/cookbooks/ohai/libraries/hint_helpers.rb b/cookbooks/ohai/libraries/hint_helpers.rb new file mode 100644 index 0000000..a0e58ba --- /dev/null +++ b/cookbooks/ohai/libraries/hint_helpers.rb @@ -0,0 +1,35 @@ +# +# Cookbook:: ohai +# Library:: hint_helpers +# +# Author:: Tim Smith () +# +# Copyright:: 2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +module OhaiCookbook + module HintHelpers + def ohai_hint_file_path(filename) + path = ::File.join(::Ohai::Config.ohai.hints_path.first, filename) + path << '.json' unless path.end_with?('.json') + path + end + + def format_content(content) + return '' if content.nil? || content.empty? + JSON.pretty_generate(content) + end + end +end diff --git a/cookbooks/ohai/libraries/plugin_helpers.rb b/cookbooks/ohai/libraries/plugin_helpers.rb new file mode 100644 index 0000000..218d550 --- /dev/null +++ b/cookbooks/ohai/libraries/plugin_helpers.rb @@ -0,0 +1,77 @@ +# +# Cookbook:: ohai +# Library:: plugin_helpers +# +# Author:: Tim Smith () +# +# Copyright:: 2017-2018, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +module OhaiCookbook + module PluginHelpers + # return the path property if specified or + # CHEF_CONFIG_PATH/ohai/plugins if a path isn't specified + def desired_plugin_path + if new_resource.path + new_resource.path.chomp('/') # if the user gave us /foo/bar/ we need /foo/bar for later comparison + else + ::File.join(chef_config_path, 'ohai', 'plugins') + end + end + + # return the chef config files dir or fail hard + def chef_config_path + if Chef::Config['config_file'] + ::File.dirname(Chef::Config['config_file']) + else + Chef::Application.fatal!("No chef config file defined. Are you running \ + chef-solo? If so you will need to define a path for the ohai_plugin as the \ + path cannot be determined") + end + end + + # is the desired plugin dir in the ohai config plugin dir array? + def in_plugin_path?(path) + normalized_path = normalize_path(path) + # get the directory where we plan to stick the plugin (not the actual file path) + desired_dir = ::File.directory?(normalized_path) ? normalized_path : ::File.dirname(normalized_path) + ::Ohai::Config.ohai['plugin_path'].map { |x| normalize_path(x) }.any? do |d| + desired_dir.start_with?(d) + end + end + + # return path to lower and with forward slashes so we can compare it + # this works around the 3 different way we can represent windows paths + def normalize_path(path) + path.downcase.gsub(/\\+/, '/') + end + + def add_to_plugin_path(path) + ::Ohai::Config.ohai['plugin_path'] << path # new format + end + + # we need to warn the user that unless the path for this plugin is in Ohai's + # plugin path already we're going to have to reload Ohai on every Chef run. + # Ideally in future versions of Ohai /etc/chef/ohai/plugins is in the path. + def plugin_path_warning + Chef::Log.warn("The Ohai plugin_path does not include #{desired_plugin_path}. \ +Ohai will reload on each chef-client run in order to add this directory to the \ +path unless you modify your client.rb configuration to add this directory to \ +plugin_path. The plugin_path can be set via the chef-client::config recipe. \ +See 'Ohai Settings' at https://docs.chef.io/config_rb_client.html#ohai-settings \ +for more details.") + end + end +end diff --git a/cookbooks/ohai/metadata.json b/cookbooks/ohai/metadata.json new file mode 100644 index 0000000..61cb9db --- /dev/null +++ b/cookbooks/ohai/metadata.json @@ -0,0 +1 @@ +{"name":"ohai","version":"5.2.5","description":"Provides custom resources for installing Ohai hints and plugins","long_description":"# ohai Cookbook\n\n[![Build Status](https://travis-ci.org/chef-cookbooks/ohai.svg?branch=master)](https://travis-ci.org/chef-cookbooks/ohai) [![Build status](https://ci.appveyor.com/api/projects/status/lgok2kr6l007s8hf/branch/master?svg=true)](https://ci.appveyor.com/project/ChefWindowsCookbooks/ohai/branch/master) [![Cookbook Version](https://img.shields.io/cookbook/v/ohai.svg)](https://supermarket.chef.io/cookbooks/ohai)\n\nContains custom resources for adding Ohai hints and installing custom Ohai plugins. Handles path creation as well as the reloading of Ohai so that new data will be available during the same run.\n\nNOTE: The ohai_hint resource shipped in Chef 14.0 (April 2018). When Chef 15.0 is released (April 2019) and Chef 13 goes EOL the ohai_hint resource will be removed from this cookbook.\n\n## Requirements\n\n### Platforms\n\n- Debian/Ubuntu\n- RHEL/CentOS/Scientific/Amazon/Oracle\n- openSUSE / SUSE Enterprise Linux\n- FreeBSD\n- Windows\n\n### Chef\n\n- Chef 12.7+\n\n### Cookbooks\n\n- none\n\n## Custom Resources\n\n### `ohai_hint`\n\nCreates Ohai hint files, which are consumed by Ohai plugins in order to determine if they should run or not.\n\n#### Resource Attributes\n\n- `hint_name` - The name of hints file and key. Should be string, default is name of resource.\n- `content` - Values of hints. It will be used as automatic attributes. Should be Hash, default is empty Hash\n- `compile_time` - Should the resource run at compile time. This defaults to true\n\n#### Examples\n\nHint file installed to the default directory:\n\n```ruby\nohai_hint 'ec2'\n```\n\nHint file not installed at compile time:\n\n```ruby\nohai_hint 'ec2' do\n compile_time false\nend\n```\n\nHint file installed with content:\n\n```ruby\nohai_hint 'raid_present' do\n content Hash[:a, 'test_content']\nend\n```\n\n#### ChefSpec Matchers\n\nYou can check for the creation or deletion of ohai hints with chefspec using these custom matches:\n\n- create_ohai_hint\n- delete_ohai_hint\n\n### `ohai_plugin`\n\nInstalls custom Ohai plugins.\n\n#### Resource Attributes\n\n- `plugin_name` - The name to give the plugin on the filesystem. Should be string, default is name of resource.\n- `path` - The path to your custom plugin directory. Defaults to a directory named 'plugins' under the directory 'ohai' in the Chef config dir.\n- `source_file` - The source file for the plugin in your cookbook if not NAME.rb.\n- `cookbook` - The cookbook where the source file exists if not the cookbook where the ohai_plugin resource is running from.\n- `resource` - The resource type for the plugin file. Either `:cookbook_file` or `:template`. Defaults to `:cookbook_file`.\n- `variables` - Usable only if `resource` is `:template`. Defines the template's variables.\n- `compile_time` - Should the resource run at compile time. This defaults to `true`.\n\n#### examples\n\nSimple Ohai plugin installation:\n\n```ruby\nohai_plugin 'my_custom_plugin'\n```\n\nInstallation where the resource doesn't match the filename and you install to a custom plugins dir:\n\n```ruby\nohai_plugin 'My Ohai Plugin' do\n name 'my_custom_plugin'\n path '/my/custom/path/'\nend\n```\n\nInstallation using a template:\n\n```ruby\nohai_plugin 'My Templated Plugin' do\n name 'templated_plugin'\n resource :template\n variables node_type: :web_server\nend\n```\n\n#### ChefSpec Matchers\n\nYou can check for the creation or deletion of ohai plugins with chefspec using these custom matches:\n\n- create_ohai_plugin\n- delete_ohai_plugin\n\n## Maintainers\n\nThis cookbook is maintained by Chef's Community Cookbook Engineering team. Our goal is to improve cookbook quality and to aid the community in contributing to cookbooks. To learn more about our team, process, and design goals see our [team documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/COOKBOOK_TEAM.MD). To learn more about contributing to cookbooks like this see our [contributing documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD), or if you have general questions about this cookbook come chat with us in #cookbok-engineering on the [Chef Community Slack](http://community-slack.chef.io/)\n\n## License\n\n**Copyright:** 2011-2016, Chef Software, Inc.\n\n```\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"ubuntu":">= 0.0.0","debian":">= 0.0.0","centos":">= 0.0.0","redhat":">= 0.0.0","amazon":">= 0.0.0","scientific":">= 0.0.0","fedora":">= 0.0.0","oracle":">= 0.0.0","suse":">= 0.0.0","opensuse":">= 0.0.0","opensuseleap":">= 0.0.0","freebsd":">= 0.0.0","windows":">= 0.0.0","zlinux":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/chef-cookbooks/ohai","issues_url":"https://github.com/chef-cookbooks/ohai/issues","chef_version":[[">= 12.7"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/ohai/recipes/default.rb b/cookbooks/ohai/recipes/default.rb new file mode 100644 index 0000000..6f83639 --- /dev/null +++ b/cookbooks/ohai/recipes/default.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: ohai +# Recipe:: default +# +# Copyright:: 2011-2017, Chef Software, Inc +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +Chef::Log.warn('The Ohai cookbook default recipe has no content as of the 4.0 release. See the readme for instructions on using the custom resources.') diff --git a/cookbooks/ohai/resources/hint.rb b/cookbooks/ohai/resources/hint.rb new file mode 100644 index 0000000..b257b9b --- /dev/null +++ b/cookbooks/ohai/resources/hint.rb @@ -0,0 +1,42 @@ + +chef_version_for_provides '< 14.0' if respond_to?(:chef_version_for_provides) +resource_name :ohai_hint + +property :hint_name, String, name_property: true +property :content, Hash +property :compile_time, [true, false], default: true + +action :create do + directory ::Ohai::Config.ohai.hints_path.first do + action :create + recursive true + end + + file ohai_hint_file_path(new_resource.hint_name) do + action :create + content format_content(new_resource.content) + end +end + +action :delete do + file ohai_hint_file_path(new_resource.hint_name) do # ~FC009 + action :delete + notifies :reload, ohai[reload ohai post hint removal] + end + + ohai 'reload ohai post hint removal' do + action :nothing + end +end + +action_class do + include OhaiCookbook::HintHelpers +end + +# this resource forces itself to run at compile_time +def after_created + return unless compile_time + Array(action).each do |action| + run_action(action) + end +end diff --git a/cookbooks/ohai/resources/plugin.rb b/cookbooks/ohai/resources/plugin.rb new file mode 100644 index 0000000..cf6b754 --- /dev/null +++ b/cookbooks/ohai/resources/plugin.rb @@ -0,0 +1,69 @@ +property :plugin_name, String, name_property: true +property :path, String +property :source_file, String +property :cookbook, String +property :resource, [:cookbook_file, :template], default: :cookbook_file +property :variables, Hash +property :compile_time, [true, false], default: true + +action :create do + # why create_if_missing you ask? + # no one can agree on perms and this allows them to manage the perms elsewhere + directory desired_plugin_path do + action :create + recursive true + not_if { ::File.exist?(desired_plugin_path) } + end + + if new_resource.resource.eql?(:cookbook_file) + cookbook_file ::File.join(desired_plugin_path, new_resource.plugin_name + '.rb') do + cookbook new_resource.cookbook + source new_resource.source_file || "#{new_resource.plugin_name}.rb" + notifies :reload, "ohai[#{new_resource.plugin_name}]", :immediately + end + elsif new_resource.resource.eql?(:template) + template ::File.join(desired_plugin_path, new_resource.plugin_name + '.rb') do + cookbook new_resource.cookbook + source new_resource.source_file || "#{new_resource.plugin_name}.rb" + variables new_resource.variables + notifies :reload, "ohai[#{new_resource.plugin_name}]", :immediately + end + end + + # Add the plugin path to the ohai plugin path if need be and warn + # the user that this is going to result in a reload every run + unless in_plugin_path?(desired_plugin_path) + plugin_path_warning + Chef::Log.warn("Adding #{desired_plugin_path} to the Ohai plugin path for this chef-client run only") + add_to_plugin_path(desired_plugin_path) + reload_required = true + end + + ohai new_resource.plugin_name do + action :nothing + action :reload if reload_required + end +end + +action :delete do + file ::File.join(desired_plugin_path, new_resource.plugin_name + '.rb') do + action :delete + notifies :reload, 'ohai[reload ohai post plugin removal]' + end + + ohai 'reload ohai post plugin removal' do + action :nothing + end +end + +action_class do + include OhaiCookbook::PluginHelpers +end + +# this resource forces itself to run at compile_time +def after_created + return unless compile_time + Array(action).each do |action| + run_action(action) + end +end diff --git a/cookbooks/openssl/CHANGELOG.md b/cookbooks/openssl/CHANGELOG.md new file mode 100644 index 0000000..9b72498 --- /dev/null +++ b/cookbooks/openssl/CHANGELOG.md @@ -0,0 +1,217 @@ +# openssl Cookbook CHANGELOG + +This file is used to list changes made in each version of the openssl cookbook. + +## 8.5.5 (2018-09-04) + +All resources in this cookbook are now built into Chef 14.4+. When Chef 15.4 is released (April 2019) the resources will be removed from this cookbook as all users should be running Chef 14.4 or later at that point. + +## 8.5.4 (2018-08-29) + +- Add missing email documentation for the request property +- Fix x509_crl to work on non-Linux platforms +- Attribute -> Property in the readme +- revokation -> revocation in the readme +- Update group/owner documentation +- Avoid deprecation warnings on Chef 14.3+ + +## 8.5.3 (2018-08-15) + +- Call ::OpenSSL not OpenSSL to be more defensive in the helpers + +## 8.5.2 (2018-08-14) + +- Back out mode change in ec_private_key + +## 8.5.1 (2018-08-14) + +- Add license headers to the resources +- Remove default_action setup from the resources since this is done automatically in custom resources now +- Make sure to use the path name_property when creating the ec public key file +- Make sure we're using openssl and not Chef's Openssl class +- Simplify how we handle user/group properties + +## 8.5.0 (2018-08-02) + +- Use the system provided owner/group defaults in resources +- Added new openssl_x509_crl resource +- Fix openssl_ec_public_key with documentation & tests +- Few corrections in the documentation +- Fix backward compatibility with chef client 12 + +## 8.4.0 (2018-07-30) + +This release is brought to you by Institut National de l'Audiovisuel, which contributed the following changes: + +- openssl_x509 is renamed to openssl_x509_certificate with backwards compatibility for the old name +- openssl_x509_certificate can now generate a signed certificate with a provided CA cert & key +- openssl_x509_certificate now support x509 extensions +- openssl_x509_certificate now support x509 csr +- openssl_x509_certificate now generate a random serial for the certificate +- openssl_x509_certificate expires has now a default value : 365 +- country field is now mandatory in x509_request +- the private key file is not rewrited in x509_request if it already exist + +## 8.3.0 (2018-07-25) + +- Add resource x509_request + +## 8.2.0 (2018-07-23) + +- Add ec_private_key & ec_public_key resources + +## 8.1.2 (2018-02-09) + +- Fix typo in resources that caused failures on Windows. +- Properly reference key_cipher in the readme + +## 8.1.1 (2018-01-05) + +- Add YARD comments to all the helpers +- Move valid ciphers directly into the equal_to check +- Remove the Chefspec matchers since modern ChefSpec does this automatically +- Fix failures on Windows nodes + +## 8.1.0 (2017-12-28) + +- Adding x509 support for /ST and /L +- Allow passing private key content to rsa_public_key resource via property +- Fix openssl_rsa_public_key converging on every run +- Fix undefied method "cipher" error in openssl_rsa_private_key resource + +## 8.0.0 (2017-12-11) + +- Added a new openssl_rsa_public_key resource which generates a public key from a private key +- Rename openssl_rsa_key to openssl_rsa_private_key, while still allowing the old name to function. This resource actually generates private keys, but the previous name didn't make that clear +- Added owner, group, and mode properties to all of the resources so you could control who owned the files you generated +- Set the default modes of generated files to 640 instead of 644 +- Set the files to generate using node['root_group'] not 'root' for compatibility on other *nix systems such as FreeBSD and macOS +- Added a new property to openssl_rsa_private_key for specifying the cipher to use +- Converted integration tests to InSpec and moved all resources to a single Kitchen suite for quicker testing +- Added a force property to allow overwriting any existing key that may exist +- Fixed upgrade recipe failures on Debian 9 +- Added a new path property which allows you to set the path there instead of in the resource's name +- Improved input validation in some of the helpers +- Added a deprecation message in Opscode::OpenSSL::Password helper "secure_password" and removed readme documentation +- Added a warning in the upgrade recipe if we're on an unsupported platform +- Switched the upgrade recipe to a multipackage upgrade to speed up Chef runs + +## 7.1.0 (2017-05-30) + +- Add supported platforms to the metdata +- Fix amazon support +- Remove class_eval usage and require Chef 12.7+ + +## 7.0.1 (2017-03-21) + +- Fix compatibility with Chef 12.5.1 + +## 7.0.0 (2017-03-06) + +- Converted LWRPs to custom resources, increasing the chef-client dependency to 12.5+. This fixes the bus where each resource notified on every run even if it didn't actually update the files on disk. +- Added testing for Chef 13 +- Test with Local Delivery instead of Rake + +## 6.1.1 (2017-01-19) + +- Resolve deprecation warnings in chefspec +- Use proper ::File class and fix ^2 validation of dhparam key length +- Disable .zero? in cookstyle for now + +## 6.1.0 (2017-01-18) + +- [#37] Support for Subject Alternative Names on generated self-signed certificates +- rubocop +- Cookstyle fixes + +## 6.0.0 (2016-09-08) + +- Update the minimum chef release to 12.1 + +## 5.0.1 (2016-09-01) +- Update docs from node.normal as node.set has been deprecated +- Testing updates + +## 5.0.0 (2016-08-27) + +- Remove the need for the chef-sugar cookbook +- Remove the default['openssl']['packages'] attribute in the upgrades recipe and instead use the correct openssl packages based on platform +- Remove support for Debian 6 and Ubuntu 10.04 in the upgrade recipe +- Add support for Fedora and Suse in the upgrade recipe +- Prevent errors with unset variable in error raising within the random password helper +- Add cookstyle and resolve all warnings +- Add testing, contributing, and maintainers documentation +- Add integration testing in Travis CI with kitchen-dokken +- Add issues_url, source_url and chef_version metadata +- Update the requirements section of the README +- Update the Chefspecs to avoid errors and run using caching for faster runs +- Add issues and PR templates for Github + +## v4.4.0 (2015-08-28) + +- NEW: x509 certificates are now signed via SHA-256 instead of SHA-1 +- FIX: gen_dhparam error now correctly fails with TypeError instead of ArgumentError if Generator argument isn't an integer + +## v4.3.2 (2015-08-01) + +- FIX: Updated changelog + +## v4.3 (2015-08-01) + +- NEW: Add rsa_key lwrp +- FIX: dhparam lwrp now correctly honors the generator parameter + +## v4.2 (2015-06-23) + +- NEW: Add dhparam lwrp +- FIX: x509 lwrp now updates resource count correctly + +## v4.1.2 (2015-06-20) + +- Add Serverspec suite +- Removed update suite from .kitchen.yml +- Add explicit license to test cookbook recipes +- Add Whyrun support to x509 LWRP +- Expand Chefspec tests for x509 LWRP to step_into LWRP +- Add helper library +- Update x509 LWRP to verify existing keys, if specified + +## v4.1.1 (2015-06-11) + +- README.md fixes + +## v4.1.0 (2015-06-11) + +- Add new random_password Mixin (Thanks, Seth!) +- Rewritten README.md +- Refactor specs +- Clear Rubocop violations + +## v4.0.0 (2015-02-19) + +- Reverting to Opscode module namespace + +## v3.0.2 (2015-12-18) + +- Accidently released 2.0.2 as 3.0.2 +- Re-namespaced `Opscode::OpenSSL::Password` module as `Chef::OpenSSL::Password` + +## v2.0.2 (2014-12-30) + +- Call cert.to_pem before recipe DSL + +## v2.0.0 (2014-06-11) + +- # 1 - **[COOK-847](https://tickets.chef.io/browse/COOK-847)** - Add LWRP for generating self signed certs + +- # 4 - **[COOK-4715](https://tickets.chef.io/browse/COOK-4715)** - add upgrade recipe and complete test harness + +## v1.1.0 + +### Improvement + +- **[COOK-3222](https://tickets.chef.io/browse/COOK-3222)** - Allow setting length for `secure_password` + +## v1.0.2 + +- Add name attribute to metadata diff --git a/cookbooks/openssl/CONTRIBUTING.md b/cookbooks/openssl/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/openssl/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/cookbooks/openssl/README.md b/cookbooks/openssl/README.md new file mode 100644 index 0000000..f279d10 --- /dev/null +++ b/cookbooks/openssl/README.md @@ -0,0 +1,416 @@ +# OpenSSL Cookbook + +[![Build Status](https://travis-ci.org/chef-cookbooks/openssl.svg?branch=master)](http://travis-ci.org/chef-cookbooks/openssl) [![Cookbook Version](https://img.shields.io/cookbook/v/openssl.svg)](https://supermarket.chef.io/cookbooks/openssl) + +This cookbook provides tools for working with the Ruby OpenSSL library. It includes: + +- A library method to generate secure random passwords in recipes, using the Ruby SecureRandom library. +- A resource for generating RSA private keys. +- A resource for generating RSA public keys. +- A resource for generating EC private keys. +- A resource for generating EC public keys. +- A resource for generating x509 certificates. +- A resource for generating x509 requests. +- A resource for generating x509 crl. +- A resource for generating dhparam.pem files. +- An attribute-driven recipe for upgrading OpenSSL packages. + +NOTE: All resources in this cookbook are now built-into Chef 14.4 and later so this cookbook is no longer necessary to use those resources. When Chef 15.4 is released (Aug 2019) the resources will be removed from this cookbook as all users should be running Chef 14.4 or later. + +## Platforms + +- Debian / Ubuntu derivatives +- Fedora +- FreeBSD +- macOS +- openSUSE / SUSE Linux Enterprises +- RHEL/CentOS/Scientific/Amazon/Oracle +- Solaris + +## Chef + +- Chef 12.7+ + +## Cookbooks + +- none + +## Attributes + +- `node['openssl']['restart_services']` - An array of service resources that depend on the openssl packages. This array is empty by default, as Chef has no reasonable way to detect which applications or services are compiled against these packages. _Note_ Each service listed in this array should represent a "`service`" resource specified in the recipes of the node's run list. + +## Recipes + +### upgrade + +The upgrade recipe iterates over the list of packages in the `node['openssl']['packages']` attribute, and manages them with the `:upgrade` action. Each package will send a `:restart` notification to service resources named in the `node['openssl']['restart_services']` attribute. + +#### Example Usage + +In this example, assume the node is running the `stats_collector` daemon, which depends on the openssl library. Imagine that a new openssl vulnerability has been disclosed, and the operating system vendor has released an update to openssl to address this vulnerability. In order to protect the node, an administrator crafts this recipe: + +```ruby +node.default['openssl']['restart_services'] = ['stats_collector'] + +# other recipe code here... +service 'stats_collector' do + action [:enable, :start] +end + +include_recipe 'openssl::upgrade' +``` + +When executed, this recipe will ensure that openssl is upgraded to the latest version, and that the `stats_collector` service is restarted to pick up the latest security fixes released in the openssl package. + +## Libraries + +There are two mixins packaged with this cookbook. + +### random_password (`OpenSSLCookbook::RandomPassword`) + +The `RandomPassword` mixin can be used to generate secure random passwords in Chef cookbooks, usually for assignment to a variable or an attribute. `random_password` uses Ruby's SecureRandom library and is customizable. + +#### Example Usage + +```ruby +Chef::Recipe.send(:include, OpenSSLCookbook::RandomPassword) +node.normal['my_secure_attribute'] = random_password +node.normal_unless['my_secure_attribute'] = random_password +node.normal['my_secure_attribute'] = random_password(length: 50) +node.normal['my_secure_attribute'] = random_password(length: 50, mode: :base64) +node.normal['my_secure_attribute'] = random_password(length: 50, mode: :base64, encoding: 'ASCII') +``` + +Note that node attributes are widely accessible. Storing unencrypted passwords in node attributes, as in this example, carries risk. + +## Resources + +### openssl_x509_certificate + +This resource generates signed or self-signed, PEM-formatted x509 certificates. If no existing key is specified, the resource will automatically generate a passwordless key with the certificate. If a CA private key and certificate are provided, the certificate will be signed with them. + +Note: This resource was renamed from openssl_x509 to openssl_x509_certificate. The legacy name will continue to function, but cookbook code should be updated for the new resource name. + +#### Properties + +Name | Type | Description +------------------ | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +`path` | String (Optional) | Optional path to write the file to if you'd like to specify it here instead of in the resource name +`common_name` | String (Optional) | Value for the `CN` certificate field. +`org` | String (Optional) | Value for the `O` certificate field. +`org_unit` | String (Optional) | Value for the `OU` certificate field. +`city` | String (Optional) | Value for the `L` certificate field. +`state` | String (Optional) | Value for the `ST` certificate field. +`country` | String (Optional) | Value for the `C` ssl field. +`email` | String (Optional) | Value for the `email` ssl field. +`expire` | Integer (Optional) | Value representing the number of days from _now_ through which the issued certificate cert will remain valid. The certificate will expire after this period. _Default: 365 +`extensions` | Hash (Optional) | Hash of X509 Extensions entries, in format `{ 'keyUsage' => { 'values' => %w( keyEncipherment digitalSignature), 'critical' => true } }` _Default: empty_ +`subject_alt_name` | Array (Optional) | Array of _Subject Alternative Name_ entries, in format `DNS:example.com` or `IP:1.2.3.4` _Default: empty_ +`key_file` | String (Optional) | The path to a certificate key file on the filesystem. If the `key_file` property is specified, the resource will attempt to source a key from this location. If no key file is found, the resource will generate a new key file at this location. If the `key_file` property is not specified, the resource will generate a key file in the same directory as the generated certificate, with the same name as the generated certificate. +`key_pass` | String (Optional) | The passphrase for an existing key's passphrase +`key_type` | String (Optional) | The desired type of the generated key (rsa or ec). _Default: rsa_ +`key_length` | Integer (Optional) | The desired Bit Length of the generated key (if key_type is equal to 'rsa'). _Default: 2048_ +`key_curve` | String (Optional) | The desired curve of the generated key (if key_type is equal to 'ec'). Run `openssl ecparam -list_curves` to see available options. _Default: prime256v1_ +`csr_file` | String (Optional) | The path to a X509 Certificate Request (CSR) on the filesystem. If the `csr_file` property is specified, the resource will attempt to source a CSR from this location. If no CSR file is found, the resource will generate a Self-Signed Certificate and the certificate fields must be specified (common_name at last). +`ca_cert_file` | String (Optional) | The path to the CA X509 Certificate on the filesystem. If the `ca_cert_file` property is specified, the `ca_key_file` property must also be specified, the certificate will be signed with them. +`ca_key_file` | String (Optional) | The path to the CA private key on the filesystem. If the `ca_key_file` property is specified, the `ca_cert_file' property must also be specified, the certificate will be signed with them. +`ca_key_pass` | String (Optional) | The passphrase for CA private key's passphrase +`owner` | String (optional) | The owner of all files created by the resource. +`group` | String (optional) | The group of all files created by the resource. +`mode` | String or Integer (Optional) | The permission mode of all files created by the resource. + +#### Example Usage + +In this example, an administrator wishes to create a self-signed x509 certificate for use with a web server. In order to create the certificate, the administrator crafts this recipe: + +```ruby +openssl_x509 '/etc/httpd/ssl/mycert.pem' do + common_name 'www.f00bar.com' + org 'Foo Bar' + org_unit 'Lab' + country 'US' +end +``` + +When executed, this recipe will generate a key certificate at `/etc/httpd/ssl/mycert.key`. It will then use that key to generate a new certificate file at `/etc/httpd/ssl/mycert.pem`. + +In this example, an administrator wishes to create a x509 certificate signed with a CA certificate and key. In order to create the certificate, the administrator crafts this recipe: + +```ruby +openssl_x509_certificate '/etc/ssl_test/my_signed_cert.crt' do + common_name 'www.f00bar.com' + ca_key_file '/etc/ssl_test/my_ca.key' + ca_cert_file '/etc/ssl_test/my_ca.crt' + expire 365 + extensions( + 'keyUsage' => { + 'values' => %w( + keyEncipherment + digitalSignature), + 'critical' => true, + }, + 'extendedKeyUsage' => { + 'values' => %w(serverAuth), + 'critical' => false, + } + ) + subject_alt_name ['IP:127.0.0.1', 'DNS:localhost.localdomain'] +end +``` + +When executed, this recipe will generate a key certificate at `/etc/ssl_test/my_signed_cert.key`. It will then use that key to generate a CSR and signed it with `my_ca.key/my_ca.crt`. A new certificate file at `/etc/ssl_test/my_signed_cert.cert` will be created as a result. + + +### openssl_x509_request + +This resource generates PEM-formatted x509 certificates requests. If no existing key is specified, the resource will automatically generate a passwordless key with the certificate. + +#### Properties + +Name | Type | Description +--------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- +`path` | String (Optional) | Optional path to write the file to if you'd like to specify it here instead of in the resource name +`common_name` | String (Required) | Value for the `CN` certificate field. +`org` | String (Optional) | Value for the `O` certificate field. +`org_unit` | String (Optional) | Value for the `OU` certificate field. +`city` | String (Optional) | Value for the `L` certificate field. +`state` | String (Optional) | Value for the `ST` certificate field. +`country` | String (Optional) | Value for the `C` ssl field. +`email` | String (Optional) | Value for the `email` ssl field. +`key_file` | String (Optional) | The path to a certificate key file on the filesystem. If the `key_file` property is specified, the resource will attempt to source a key from this location. If no key file is found, the resource will generate a new key file at this location. If the `key_file` property is not specified, the resource will generate a key file in the same directory as the generated certificate, with the same name as the generated certificate. +`key_pass` | String (Optional) | The passphrase for an existing key's passphrase +`key_type` | String (Optional) | The desired type of the generated key (rsa or ec). _Default: ec_ +`key_length` | Integer (Optional) | The desired Bit Length of the generated key (if key_type is equal to 'rsa'). _Default: 2048_ +`key_curve` | String (Optional) | The desired curve of the generated key (if key_type is equal to 'ec'). Run `openssl ecparam -list_curves` to see available options. _Default: prime256v1 +`owner` | String (optional) | The owner of all files created by the resource. +`group` | String (optional) | The group of all files created by the resource. +`mode` | String or Integer (Optional) | The permission mode of all files created by the resource. + +#### Example Usage + +In this example, an administrator wishes to create a x509 CRL. In order to create the CRL, the administrator crafts this recipe: + +```ruby +openssl_x509_request '/etc/ssl_test/my_ec_request.csr' do + common_name 'myecrequest.example.com' + org 'Test Kitchen Example' + org_unit 'Kitchens' + country 'UK' +end +``` + +When executed, this recipe will generate a key certificate at `/etc/httpd/ssl/my_ec_request.key`. It will then use that key to generate a new csr file at `/etc/ssl_test/my_ec_request.csr`. + +### openssl_x509_crl + +This resource generates PEM-formatted x509 CRL. + +#### Properties + +Name | Type | Description +--------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- +`path` | String (Optional) | Optional path to write the file to if you'd like to specify it here instead of in the resource name +`serial_to_revoke` | String or Integer(Optional) | Serial of the X509 Certificate to revoke +`revocation_reason` | String or Integer(Optional) | [Reason of the revocation]((https://en.wikipedia.org/wiki/Certificate_revocation_list#Reasons_for_revocation)) _Default: 0_ +`expire` | Integer (Optional) | Value representing the number of days from _now_ through which the issued CRL will remain valid. The CRL will expire after this period. _Default: 8_ +`renewal_threshold` | Integer (Optional) | Number of days before the expiration. It this threshold is reached, the CRL will be renewed _Default: 1_ +`ca_cert_file` | String (Required) | The path to the CA X509 Certificate on the filesystem. If the `ca_cert_file` property is specified, the `ca_key_file` property must also be specified, the CRL will be signed with them. +`ca_key_file` | String (Required) | The path to the CA private key on the filesystem. If the `ca_key_file` property is specified, the `ca_cert_file' property must also be specified, the CRL will be signed with them. +`ca_key_pass` | String (Optional) | The passphrase for CA private key's passphrase +`owner` | String (optional) | The owner of all files created by the resource. +`group` | String (optional) | The group of all files created by the resource. +`mode` | String or Integer (Optional) | The permission mode of all files created by the resource. + + +#### Example Usage + +In this example, an administrator wishes to create an empty X509 CRL. In order to create the CRL, the administrator crafts this recipe: + +```ruby +openssl_x509_crl '/etc/ssl_test/my_ca.crl' do + ca_cert_file '/etc/ssl_test/my_ca.crt' + ca_key_file '/etc/ssl_test/my_ca.key' +end +``` + +When executed, this recipe will generate a new CRL file at `/etc/ssl_test/my_ca.crl`. + +In this example, an administrator wishes to revoke a certificate in an existing X509 CRL. + +```ruby +openssl_x509_crl '/etc/ssl_test/my_ca.crl' do + ca_cert_file '/etc/ssl_test/my_ca.crt' + ca_key_file '/etc/ssl_test/my_ca.key' + serial_to_revoke C7BCB6602A2E4251EF4E2827A228CB52BC0CEA2F +end +``` + +### openssl_dhparam + +This resource generates dhparam.pem files. If a valid dhparam.pem file is found at the specified location, no new file will be created. If a file is found at the specified location but it is not a valid dhparam file, it will be overwritten. + +#### Properties + +Name | Type | Description +------------ | ---------------------------- | --------------------------------------------------------------------------------------------------- +`path` | String (Optional) | Optional path to write the file to if you'd like to specify it here instead of in the resource name +`key_length` | Integer (Optional) | The desired Bit Length of the generated key. _Default: 2048_ +`generator` | Integer (Optional) | The desired Diffie-Hellmann generator. Can be _2_ or _5_. +`owner` | String (optional) | The owner of all files created by the resource. +`group` | String (optional) | The group of all files created by the resource. +`mode` | String or Integer (Optional) | The permission mode of all files created by the resource. _Default: "0640"_ + +#### Example Usage + +In this example, an administrator wishes to create a dhparam.pem file for use with a web server. In order to create the .pem file, the administrator crafts this recipe: + +```ruby +openssl_dhparam '/etc/httpd/ssl/dhparam.pem' do + key_length 2048 + generator 2 +end +``` + +When executed, this recipe will generate a dhparam file at `/etc/httpd/ssl/dhparam.pem`. + +### openssl_rsa_private_key + +This resource generates rsa private key files. If a valid rsa key file can be opened at the specified location, no new file will be created. If the RSA key file cannot be opened, either because it does not exist or because the password to the RSA key file does not match the password in the recipe, it will be overwritten. + +Note: This resource was renamed from openssl_rsa_key to openssl_rsa_private_key. The legacy name will continue to function, but cookbook code should be updated for the new resource name. + +#### Properties + +Name | Type | Description +------------ | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- +`path` | String (Optional) | Optional path to write the file to if you'd like to specify it here instead of in the resource name +`key_length` | Integer (Optional) | The desired Bit Length of the generated key. _Default: 2048_ +`key_cipher` | String (Optional) | The designed cipher to use when generating your key. Run `openssl list-cipher-algorithms` to see available options. _Default: des3_ +`key_pass` | String (Optional) | The desired passphrase for the key. +`owner` | String (optional) | The owner of all files created by the resource. +`group` | String (optional) | The group of all files created by the resource. +`mode` | String or Integer (Optional) | The permission mode of all files created by the resource. _Default: "0640"_ +`force` | true/false (Optional) | Force creating the key even if the existing key exists. _Default: false_ + +#### Example Usage + +In this example, an administrator wishes to create a new RSA private key file in order to generate other certificates and public keys. In order to create the key file, the administrator crafts this recipe: + +```ruby +openssl_rsa_private_key '/etc/httpd/ssl/server.key' do + key_length 2048 +end +``` + +When executed, this recipe will generate a passwordless RSA key file at `/etc/httpd/ssl/server.key`. + +### openssl_rsa_public_key + +This resource generates rsa public key files given a private key. + +#### Properties + +Name | Type | Description +--------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- +`path` | String (Optional) | Optional path to write the file to if you'd like to specify it here instead of in the resource name +`private_key_path` | String (Required unless private_key_content used) | The path to the private key to generate the public key from +`private_key_content` | String (Required unless private_key_path used) | The content of the private key including new lines. Used if you don't want to write a private key to disk and use `private_key_path`. +`private_key_pass` | String (Optional) | The passphrase of the provided private key +`owner` | String (optional) | The owner of all files created by the resource. +`group` | String (optional) | The group of all files created by the resource. +`mode` | String or Integer (Optional) | The permission mode of all files created by the resource. _Default: "0640"_ + +**Note**: To use `private_key_content` the private key string must be properly formatted including new lines. The easiest way to get the right string is to run the following from irb (/opt/chefdk/embedded/bin/irb from ChefDK) + +```ruby +File.read('/foo/bar/private.pem') +``` + +#### Example Usage + +```ruby +openssl_rsa_public_key '/etc/foo/something.pub' do + priv_key_path '/etc/foo/something.pem' +end +``` + +### openssl_ec_private_key + +This resource generates ec private key files. If a valid ec key file can be opened at the specified location, no new file will be created. If the EC key file cannot be opened, either because it does not exist or because the password to the EC key file does not match the password in the recipe, it will be overwritten. + +#### Properties + +Name | Type | Description +------------ | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- +`path` | String (Optional) | Optional path to write the file to if you'd like to specify it here instead of in the resource name +`key_curve` | String (Optional) | The desired curve of the generated key. Run `openssl ecparam -list_curves` to see available options. _Default: prime256v1 +`key_cipher` | String (Optional) | The designed cipher to use when generating your key. Run `openssl list-cipher-algorithms` to see available options. _Default: des3_ +`key_pass` | String (Optional) | The desired passphrase for the key. +`owner` | String (optional) | The owner of all files created by the resource. +`group` | String (optional) | The group of all files created by the resource. +`mode` | String or Integer (Optional) | The permission mode of all files created by the resource. _Default: "0640"_ +`force` | true/false (Optional) | Force creating the key even if the existing key exists. _Default: false_ + +#### Example Usage + +In this example, an administrator wishes to create a new EC private key file in order to generate other certificates and public keys. In order to create the key file, the administrator crafts this recipe: + +```ruby +openssl_ec_private_key '/etc/httpd/ssl/server.key' do + key_curve "prime256v1' +end +``` + +When executed, this recipe will generate a passwordless EC key file at `/etc/httpd/ssl/server.key`. + +### openssl_ec_public_key + +This resource generates ec public key files given a private key. + +#### Properties + +Name | Type | Description +--------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- +`path` | String (Optional) | Optional path to write the file to if you'd like to specify it here instead of in the resource name +`private_key_path` | String (Required unless private_key_content used) | The path to the private key to generate the public key from +`private_key_content` | String (Required unless private_key_path used) | The content of the private key including new lines. Used if you don't want to write a private key to disk and use `private_key_path`. +`private_key_pass` | String (Optional) | The passphrase of the provided private key +`owner` | String (optional) | The owner of all files created by the resource. _Default: "root"_ +`group` | String (optional) | The group of all files created by the resource. _Default: "root or wheel depending on platform"_ +`mode` | String or Integer (Optional) | The permission mode of all files created by the resource. _Default: "0640"_ + +**Note**: To use `private_key_content` the private key string must be properly formatted including new lines. The easiest way to get the right string is to run the following from irb (/opt/chefdk/embedded/bin/irb from ChefDK) + +```ruby +File.read('/foo/bar/private.pem') +``` + +#### Example Usage + +```ruby +openssl_ec_public_key '/etc/foo/something.pub' do + priv_key_path '/etc/foo/something.pem' +end +``` + +## Maintainers + +This cookbook is maintained by Chef's Community Cookbook Engineering team. Our goal is to improve cookbook quality and to aid the community in contributing to cookbooks. To learn more about our team, process, and design goals see our [team documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/COOKBOOK_TEAM.MD). To learn more about contributing to cookbooks like this see our [contributing documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD), or if you have general questions about this cookbook come chat with us in #cookbok-engineering on the [Chef Community Slack](http://community-slack.chef.io/) + +## License + +**Copyright:** 2009-2018, Chef Software, Inc. + +``` +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/cookbooks/openssl/attributes/default.rb b/cookbooks/openssl/attributes/default.rb new file mode 100644 index 0000000..b22f210 --- /dev/null +++ b/cookbooks/openssl/attributes/default.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: openssl +# Attributes:: default +# +# Copyright:: 2014-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +default['openssl']['restart_services'] = [] diff --git a/cookbooks/openssl/libraries/helpers.rb b/cookbooks/openssl/libraries/helpers.rb new file mode 100644 index 0000000..e6386d3 --- /dev/null +++ b/cookbooks/openssl/libraries/helpers.rb @@ -0,0 +1,399 @@ +# +# License:: Apache License, Version 2.0 +# +# 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. +# + +module OpenSSLCookbook + # Helper functions for the OpenSSL cookbook. + module Helpers + def self.included(_base) + require 'openssl' unless defined?(::OpenSSL) + end + + # determine the key filename from the cert filename + # @param [String] cert_filename the path to the certfile + # @return [String] the path to the keyfile + def get_key_filename(cert_filename) + cert_file_path, cert_filename = ::File.split(cert_filename) + cert_filename = ::File.basename(cert_filename, ::File.extname(cert_filename)) + cert_file_path + ::File::SEPARATOR + cert_filename + '.key' + end + + # is the key length a valid key length + # @param [Integer] number + # @return [Boolean] is length valid + def key_length_valid?(number) + number >= 1024 && (number & (number - 1) == 0) + end + + # validate a dhparam file from path + # @param [String] dhparam_pem_path the path to the pem file + # @return [Boolean] is the key valid + def dhparam_pem_valid?(dhparam_pem_path) + # Check if the dhparam.pem file exists + # Verify the dhparam.pem file contains a key + return false unless ::File.exist?(dhparam_pem_path) + dhparam = ::OpenSSL::PKey::DH.new File.read(dhparam_pem_path) + dhparam.params_ok? + end + + # given either a key file path or key file content see if it's actually + # a private key + # @param [String] key_file the path to the keyfile or the key contents + # @param [String] key_password optional password to the keyfile + # @return [Boolean] is the key valid? + def priv_key_file_valid?(key_file, key_password = nil) + # if the file exists try to read the content + # if not assume we were passed the key and set the string to the content + key_content = ::File.exist?(key_file) ? File.read(key_file) : key_file + + begin + key = ::OpenSSL::PKey.read key_content, key_password + rescue ::OpenSSL::PKey::PKeyError, ArgumentError + return false + end + + if key.is_a?(::OpenSSL::PKey::EC) + key.private_key? + else + key.private? + end + end + + # given a crl file path see if it's actually a crl + # @param [String] crl_file the path to the crlfile + # @return [Boolean] is the key valid? + def crl_file_valid?(crl_file) + begin + ::OpenSSL::X509::CRL.new ::File.read(crl_file) + rescue ::OpenSSL::X509::CRLError, Errno::ENOENT + return false + end + true + end + + # check is a serial given is revoked in a crl given + # @param [OpenSSL::X509::CRL] crl X509 CRL to check + # @param [String, Integer] serial X509 Certificate Serial Number + # @return [true, false] + def serial_revoked?(crl, serial) + raise TypeError, 'crl must be a Ruby OpenSSL::X509::CRL object' unless crl.is_a?(::OpenSSL::X509::CRL) + raise TypeError, 'serial must be a Ruby String or Integer object' unless serial.is_a?(String) || serial.is_a?(Integer) + + serial_to_verify = if serial.is_a?(String) + serial.to_i(16) + else + serial + end + status = false + crl.revoked.each do |revoked| + status = true if revoked.serial == serial_to_verify + end + status + end + + # generate a dhparam file + # @param [String] key_length the length of the key + # @param [Integer] generator the dhparam generator to use + # @return [OpenSSL::PKey::DH] + def gen_dhparam(key_length, generator) + raise ArgumentError, 'Key length must be a power of 2 greater than or equal to 1024' unless key_length_valid?(key_length) + raise TypeError, 'Generator must be an integer' unless generator.is_a?(Integer) + + ::OpenSSL::PKey::DH.new(key_length, generator) + end + + # generate an RSA private key given key length + # @param [Integer] key_length the key length of the private key + # @return [OpenSSL::PKey::DH] + def gen_rsa_priv_key(key_length) + raise ArgumentError, 'Key length must be a power of 2 greater than or equal to 1024' unless key_length_valid?(key_length) + + ::OpenSSL::PKey::RSA.new(key_length) + end + + # generate pem format of the public key given a private key + # @param [String] priv_key either the contents of the private key or the path to the file + # @param [String] priv_key_password optional password for the private key + # @return [String] pem format of the public key + def gen_rsa_pub_key(priv_key, priv_key_password = nil) + # if the file exists try to read the content + # if not assume we were passed the key and set the string to the content + key_content = ::File.exist?(priv_key) ? File.read(priv_key) : priv_key + key = ::OpenSSL::PKey::RSA.new key_content, priv_key_password + key.public_key.to_pem + end + + # generate a pem file given a cipher, key, an optional key_password + # @param [OpenSSL::PKey::RSA] rsa_key the private key object + # @param [String] key_password the password for the private key + # @param [String] key_cipher the cipher to use + # @return [String] pem contents + def encrypt_rsa_key(rsa_key, key_password, key_cipher) + raise TypeError, 'rsa_key must be a Ruby OpenSSL::PKey::RSA object' unless rsa_key.is_a?(::OpenSSL::PKey::RSA) + raise TypeError, 'key_password must be a string' unless key_password.is_a?(String) + raise TypeError, 'key_cipher must be a string' unless key_cipher.is_a?(String) + raise ArgumentError, 'Specified key_cipher is not available on this system' unless ::OpenSSL::Cipher.ciphers.include?(key_cipher) + + cipher = ::OpenSSL::Cipher.new(key_cipher) + rsa_key.to_pem(cipher, key_password) + end + + # generate an ec private key given curve type + # @param [String] curve the kind of curve to use + # @return [OpenSSL::PKey::DH] + def gen_ec_priv_key(curve) + raise TypeError, 'curve must be a string' unless curve.is_a?(String) + raise ArgumentError, 'Specified curve is not available on this system' unless curve == 'prime256v1' || curve == 'secp384r1' || curve == 'secp521r1' + ::OpenSSL::PKey::EC.new(curve).generate_key + end + + # generate pem format of the public key given a private key + # @param [String] priv_key either the contents of the private key or the path to the file + # @param [String] priv_key_password optional password for the private key + # @return [String] pem format of the public key + def gen_ec_pub_key(priv_key, priv_key_password = nil) + # if the file exists try to read the content + # if not assume we were passed the key and set the string to the content + key_content = ::File.exist?(priv_key) ? File.read(priv_key) : priv_key + key = ::OpenSSL::PKey::EC.new key_content, priv_key_password + + # Get curve type (prime256v1...) + group = ::OpenSSL::PKey::EC::Group.new(key.group.curve_name) + # Get Generator point & public point (priv * generator) + generator = group.generator + pub_point = generator.mul(key.private_key) + key.public_key = pub_point + + # Public Key in pem + public_key = ::OpenSSL::PKey::EC.new + public_key.group = group + public_key.public_key = pub_point + public_key.to_pem + end + + # generate a pem file given a cipher, key, an optional key_password + # @param [OpenSSL::PKey::EC] ec_key the private key object + # @param [String] key_password the password for the private key + # @param [String] key_cipher the cipher to use + # @return [String] pem contents + def encrypt_ec_key(ec_key, key_password, key_cipher) + raise TypeError, 'ec_key must be a Ruby OpenSSL::PKey::EC object' unless ec_key.is_a?(::OpenSSL::PKey::EC) + raise TypeError, 'key_password must be a string' unless key_password.is_a?(String) + raise TypeError, 'key_cipher must be a string' unless key_cipher.is_a?(String) + raise ArgumentError, 'Specified key_cipher is not available on this system' unless ::OpenSSL::Cipher.ciphers.include?(key_cipher) + + cipher = ::OpenSSL::Cipher.new(key_cipher) + ec_key.to_pem(cipher, key_password) + end + + # generate a csr pem file given a subject and a private key + # @param [OpenSSL::X509::Name] subject the x509 subject object + # @param [OpenSSL::PKey::EC, OpenSSL::PKey::RSA] key the private key object + # @return [OpenSSL::X509::Request] + def gen_x509_request(subject, key) + raise TypeError, 'subject must be a Ruby OpenSSL::X509::Name object' unless subject.is_a?(::OpenSSL::X509::Name) + raise TypeError, 'key must be a Ruby OpenSSL::PKey::EC or a Ruby OpenSSL::PKey::RSA object' unless key.is_a?(::OpenSSL::PKey::EC) || key.is_a?(::OpenSSL::PKey::RSA) + + request = ::OpenSSL::X509::Request.new + request.version = 0 + request.subject = subject + request.public_key = key + + # Chef 12 backward compatibility + ::OpenSSL::PKey::EC.send(:alias_method, :private?, :private_key?) + + request.sign(key, ::OpenSSL::Digest::SHA256.new) + request + end + + # generate an array of X509 Extensions given a hash of extensions + # @param [Hash] extensions hash of extensions + # @return [Array] + def gen_x509_extensions(extensions) + raise TypeError, 'extensions must be a Ruby Hash object' unless extensions.is_a?(Hash) + + exts = [] + extensions.each do |ext_name, ext_prop| + raise TypeError, "#{ext_name} must contain a Ruby Hash" unless ext_prop.is_a?(Hash) + raise ArgumentError, "keys in #{ext_name} must be 'values' and 'critical'" unless ext_prop.key?('values') && ext_prop.key?('critical') + raise TypeError, "the key 'values' must contain a Ruby Arrays" unless ext_prop['values'].is_a?(Array) + raise TypeError, "the key 'critical' must be a Ruby Boolean true/false" unless ext_prop['critical'].is_a?(TrueClass) || ext_prop['critical'].is_a?(FalseClass) + + exts << ::OpenSSL::X509::ExtensionFactory.new.create_extension(ext_name, ext_prop['values'].join(','), ext_prop['critical']) + end + exts + end + + # generate a random Serial + # @return [Integer] + def gen_serial + ::OpenSSL::BN.generate_prime(160) + end + + # generate a Certificate given a X509 request + # @param [OpenSSL::X509::Request] request X509 Certificate Request + # @param [Array] extension Array of X509 Certificate Extension + # @param [Hash] info issuer & validity + # @param [OpenSSL::PKey::EC, OpenSSL::PKey::RSA] key private key to sign with + # @return [OpenSSL::X509::Certificate] + def gen_x509_cert(request, extension, info, key) + raise TypeError, 'request must be a Ruby OpenSSL::X509::Request' unless request.is_a?(::OpenSSL::X509::Request) + raise TypeError, 'extension must be a Ruby Array' unless extension.is_a?(Array) + raise TypeError, 'info must be a Ruby Hash' unless info.is_a?(Hash) + raise TypeError, 'key must be a Ruby OpenSSL::PKey::EC object or a Ruby OpenSSL::PKey::RSA object' unless key.is_a?(::OpenSSL::PKey::EC) || key.is_a?(::OpenSSL::PKey::RSA) + + raise ArgumentError, 'info must contain a validity' unless info.key?('validity') + raise TypeError, 'info[\'validity\'] must be a Ruby Integer object' unless info['validity'].is_a?(Integer) + + cert = ::OpenSSL::X509::Certificate.new + ef = ::OpenSSL::X509::ExtensionFactory.new + + cert.serial = gen_serial() + cert.version = 2 + cert.subject = request.subject + cert.public_key = request.public_key + cert.not_before = Time.now + cert.not_after = cert.not_before + info['validity'] * 24 * 60 * 60 + + if info['issuer'].nil? + cert.issuer = request.subject + ef.issuer_certificate = cert + extension << ef.create_extension('basicConstraints', 'CA:TRUE', true) + else + raise TypeError, 'info[\'issuer\'] must be a Ruby OpenSSL::X509::Certificate object' unless info['issuer'].is_a?(::OpenSSL::X509::Certificate) + cert.issuer = info['issuer'].subject + ef.issuer_certificate = info['issuer'] + end + ef.subject_certificate = cert + ef.config = ::OpenSSL::Config.load(::OpenSSL::Config::DEFAULT_CONFIG_FILE) + + cert.extensions = extension + cert.add_extension ef.create_extension('subjectKeyIdentifier', 'hash') + cert.add_extension ef.create_extension('authorityKeyIdentifier', + 'keyid:always,issuer:always') + + cert.sign(key, ::OpenSSL::Digest::SHA256.new) + cert + end + + # generate a X509 CRL given a CA + # @param [OpenSSL::PKey::EC, OpenSSL::PKey::RSA] ca_private_key private key from the CA + # @param [Hash] info issuer & validity + # @return [OpenSSL::X509::CRL] + def gen_x509_crl(ca_private_key, info) + raise TypeError, 'ca_private_key must be a Ruby OpenSSL::PKey::EC object or a Ruby OpenSSL::PKey::RSA object' unless ca_private_key.is_a?(::OpenSSL::PKey::EC) || ca_private_key.is_a?(::OpenSSL::PKey::RSA) + raise TypeError, 'info must be a Ruby Hash' unless info.is_a?(Hash) + + raise ArgumentError, 'info must contain a issuer and a validity' unless info.key?('issuer') && info.key?('validity') + raise TypeError, 'info[\'issuer\'] must be a Ruby OpenSSL::X509::Certificate object' unless info['issuer'].is_a?(::OpenSSL::X509::Certificate) + raise TypeError, 'info[\'validity\'] must be a Ruby Integer object' unless info['validity'].is_a?(Integer) + + crl = ::OpenSSL::X509::CRL.new + ef = ::OpenSSL::X509::ExtensionFactory.new + + crl.version = 1 + crl.issuer = info['issuer'].subject + crl.last_update = Time.now + crl.next_update = Time.now + 3600 * 24 * info['validity'] + + ef.config = ::OpenSSL::Config.load(::OpenSSL::Config::DEFAULT_CONFIG_FILE) + ef.issuer_certificate = info['issuer'] + + crl.add_extension ::OpenSSL::X509::Extension.new('crlNumber', ::OpenSSL::ASN1::Integer(1)) + crl.add_extension ef.create_extension('authorityKeyIdentifier', + 'keyid:always,issuer:always') + crl.sign(ca_private_key, ::OpenSSL::Digest::SHA256.new) + crl + end + + # generate the next CRL number available for a X509 CRL given + # @param [OpenSSL::X509::CRL] crl x509 CRL + # @return [Integer] + def get_next_crl_number(crl) + raise TypeError, 'crl must be a Ruby OpenSSL::X509::CRL object' unless crl.is_a?(::OpenSSL::X509::CRL) + crlnum = 1 + crl.extensions.each do |e| + crlnum = e.value if e.oid == 'crlNumber' + end + crlnum.to_i + 1 + end + + # add a serial given in the crl given + # @param [Hash] revoke_info serial to revoke & revokation reason + # @param [OpenSSL::X509::CRL] crl X509 CRL + # @param [OpenSSL::PKey::EC, OpenSSL::PKey::RSA] ca_private_key private key from the CA + # @param [Hash] info issuer & validity + # @return [OpenSSL::X509::CRL] + def revoke_x509_crl(revoke_info, crl, ca_private_key, info) + raise TypeError, 'revoke_info must be a Ruby Hash oject' unless revoke_info.is_a?(Hash) + raise TypeError, 'crl must be a Ruby OpenSSL::X509::CRL object' unless crl.is_a?(::OpenSSL::X509::CRL) + raise TypeError, 'ca_private_key must be a Ruby OpenSSL::PKey::EC object or a Ruby OpenSSL::PKey::RSA object' unless ca_private_key.is_a?(::OpenSSL::PKey::EC) || ca_private_key.is_a?(::OpenSSL::PKey::RSA) + raise TypeError, 'info must be a Ruby Hash' unless info.is_a?(Hash) + + raise ArgumentError, 'revoke_info must contain a serial and a reason' unless revoke_info.key?('serial') && revoke_info.key?('reason') + raise TypeError, 'revoke_info[\'serial\'] must be a Ruby String or Integer object' unless revoke_info['serial'].is_a?(String) || revoke_info['serial'].is_a?(Integer) + raise TypeError, 'revoke_info[\'reason\'] must be a Ruby Integer object' unless revoke_info['reason'].is_a?(Integer) + + raise ArgumentError, 'info must contain a issuer and a validity' unless info.key?('issuer') && info.key?('validity') + raise TypeError, 'info[\'issuer\'] must be a Ruby OpenSSL::X509::Certificate object' unless info['issuer'].is_a?(::OpenSSL::X509::Certificate) + raise TypeError, 'info[\'validity\'] must be a Ruby Integer object' unless info['validity'].is_a?(Integer) + + revoked = ::OpenSSL::X509::Revoked.new + revoked.serial = if revoke_info['serial'].is_a?(String) + revoke_info['serial'].to_i(16) + else + revoke_info['serial'] + end + revoked.time = Time.now + + ext = ::OpenSSL::X509::Extension.new('CRLReason', + ::OpenSSL::ASN1::Enumerated(revoke_info['reason'])) + revoked.add_extension(ext) + crl.add_revoked(revoked) + + crl = renew_x509_crl(crl, ca_private_key, info) + crl + end + + # renew a X509 crl given + # @param [OpenSSL::X509::CRL] crl CRL to renew + # @param [OpenSSL::PKey::EC, OpenSSL::PKey::RSA] ca_private_key private key from the CA + # @param [Hash] info issuer & validity + # @return [OpenSSL::X509::CRL] + def renew_x509_crl(crl, ca_private_key, info) + raise TypeError, 'crl must be a Ruby OpenSSL::X509::CRL object' unless crl.is_a?(::OpenSSL::X509::CRL) + raise TypeError, 'ca_private_key must be a Ruby OpenSSL::PKey::EC object or a Ruby OpenSSL::PKey::RSA object' unless ca_private_key.is_a?(::OpenSSL::PKey::EC) || ca_private_key.is_a?(::OpenSSL::PKey::RSA) + raise TypeError, 'info must be a Ruby Hash' unless info.is_a?(Hash) + + raise ArgumentError, 'info must contain a issuer and a validity' unless info.key?('issuer') && info.key?('validity') + raise TypeError, 'info[\'issuer\'] must be a Ruby OpenSSL::X509::Certificate object' unless info['issuer'].is_a?(::OpenSSL::X509::Certificate) + raise TypeError, 'info[\'validity\'] must be a Ruby Integer object' unless info['validity'].is_a?(Integer) + + crl.last_update = Time.now + crl.next_update = crl.last_update + 3600 * 24 * info['validity'] + + ef = ::OpenSSL::X509::ExtensionFactory.new + ef.config = ::OpenSSL::Config.load(::OpenSSL::Config::DEFAULT_CONFIG_FILE) + ef.issuer_certificate = info['issuer'] + + crl.extensions = [ ::OpenSSL::X509::Extension.new('crlNumber', + ::OpenSSL::ASN1::Integer(get_next_crl_number(crl)))] + crl.add_extension ef.create_extension('authorityKeyIdentifier', + 'keyid:always,issuer:always') + crl.sign(ca_private_key, ::OpenSSL::Digest::SHA256.new) + crl + end + end +end diff --git a/cookbooks/openssl/libraries/random_password.rb b/cookbooks/openssl/libraries/random_password.rb new file mode 100644 index 0000000..89dbee9 --- /dev/null +++ b/cookbooks/openssl/libraries/random_password.rb @@ -0,0 +1,82 @@ +# +# Cookbook:: openssl +# Library:: random_password +# Author:: Seth Vargo +# +# Copyright:: 2015-2017, Seth Vargo +# +# 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. +# rubocop:disable UnusedMethodArgument, Style/RaiseArgs + +module OpenSSLCookbook + module RandomPassword + # Override the included method to require securerandom if it is not defined. + # This avoids the need to load the class on each Chef run unless the user is + # explicitly requiring it. + def self.included(base) + require 'securerandom' unless defined?(SecureRandom) + end + + class InvalidPasswordMode < StandardError + def initialize(given, _acceptable = nil) + super <<-EOH +The given password mode '#{given}' is not valid. Valid password modes are :hex, +:base64, and :random_bytes! +EOH + end + end + + # + # Generates a random password using {SecureRandom}. + # + # @example Generating a random (hex) password (of 20 characters) + # random_password #=> "1930e99aa035083bdd93d1d8f11cb7ac8f625c9c" + # + # @example Generating a random base64 password that is 50 characters + # random_password(mode: :base64, length: 50) #=> "72o5oVbKHHEVYj1nOgFB2EijnzZfnrbfasVuF+oRH8wMgb0QWoYZF/OkrQricp1ENoI=" + # + # @example Generate a password with a forced encoding + # random_password(encoding: "ASCII") + # + # @param [Hash] options + # @option options [Fixnum] :length + # the number of bits to use in the password + # @option options [Symbol] :mode + # the type of random password to generate - valid values are + # `:hex`, `:base64`, or `:random_bytes` + # @option options [String, Symbol, Constant] :encoding + # the encoding to force (default is "UTF-8") + # + # @return [String] + # + def random_password(options = {}) + length = options[:length] || 20 + mode = options[:mode] || :hex + encoding = options[:encoding] || 'UTF-8' + + # Convert to a "proper" length, since the size is actually in bytes + length = case mode + when :hex + length / 2 + when :base64 + length * 3 / 4 + when :random_bytes + length + else + raise InvalidPasswordMode.new(mode) + end + + SecureRandom.send(mode, length).force_encoding(encoding) + end + end +end diff --git a/cookbooks/openssl/libraries/secure_password.rb b/cookbooks/openssl/libraries/secure_password.rb new file mode 100644 index 0000000..acc7809 --- /dev/null +++ b/cookbooks/openssl/libraries/secure_password.rb @@ -0,0 +1,40 @@ +# +# Cookbook:: openssl +# Library:: secure_password +# Author:: Joshua Timberman +# +# Copyright:: 2009-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include OpenSSLCookbook::Helpers + +module Opscode + module OpenSSL + # Generate secure passwords with OpenSSL + module Password + def secure_password(length = 20) + Chef::Log.warn('The Opscode::OpenSSL::Password helper "secure_password" has been deprecated. Use the random_password method in OpenSSLCookbook::RandomPassword instead.') + + pw = '' + + while pw.length < length + pw << ::OpenSSL::Random.random_bytes(1).gsub(/\W/, '') + end + + pw + end + end + end +end diff --git a/cookbooks/openssl/metadata.json b/cookbooks/openssl/metadata.json new file mode 100644 index 0000000..0e11c2b --- /dev/null +++ b/cookbooks/openssl/metadata.json @@ -0,0 +1 @@ +{"name":"openssl","version":"8.5.5","description":"Resources and libraries for interacting with certificates, keys, passwords, and dhparam files.","long_description":"# OpenSSL Cookbook\n\n[![Build Status](https://travis-ci.org/chef-cookbooks/openssl.svg?branch=master)](http://travis-ci.org/chef-cookbooks/openssl) [![Cookbook Version](https://img.shields.io/cookbook/v/openssl.svg)](https://supermarket.chef.io/cookbooks/openssl)\n\nThis cookbook provides tools for working with the Ruby OpenSSL library. It includes:\n\n- A library method to generate secure random passwords in recipes, using the Ruby SecureRandom library.\n- A resource for generating RSA private keys.\n- A resource for generating RSA public keys.\n- A resource for generating EC private keys.\n- A resource for generating EC public keys.\n- A resource for generating x509 certificates.\n- A resource for generating x509 requests.\n- A resource for generating x509 crl.\n- A resource for generating dhparam.pem files.\n- An attribute-driven recipe for upgrading OpenSSL packages.\n\nNOTE: All resources in this cookbook are now built-into Chef 14.4 and later so this cookbook is no longer necessary to use those resources. When Chef 15.4 is released (Aug 2019) the resources will be removed from this cookbook as all users should be running Chef 14.4 or later.\n\n## Platforms\n\n- Debian / Ubuntu derivatives\n- Fedora\n- FreeBSD\n- macOS\n- openSUSE / SUSE Linux Enterprises\n- RHEL/CentOS/Scientific/Amazon/Oracle\n- Solaris\n\n## Chef\n\n- Chef 12.7+\n\n## Cookbooks\n\n- none\n\n## Attributes\n\n- `node['openssl']['restart_services']` - An array of service resources that depend on the openssl packages. This array is empty by default, as Chef has no reasonable way to detect which applications or services are compiled against these packages. _Note_ Each service listed in this array should represent a \"`service`\" resource specified in the recipes of the node's run list.\n\n## Recipes\n\n### upgrade\n\nThe upgrade recipe iterates over the list of packages in the `node['openssl']['packages']` attribute, and manages them with the `:upgrade` action. Each package will send a `:restart` notification to service resources named in the `node['openssl']['restart_services']` attribute.\n\n#### Example Usage\n\nIn this example, assume the node is running the `stats_collector` daemon, which depends on the openssl library. Imagine that a new openssl vulnerability has been disclosed, and the operating system vendor has released an update to openssl to address this vulnerability. In order to protect the node, an administrator crafts this recipe:\n\n```ruby\nnode.default['openssl']['restart_services'] = ['stats_collector']\n\n# other recipe code here...\nservice 'stats_collector' do\n action [:enable, :start]\nend\n\ninclude_recipe 'openssl::upgrade'\n```\n\nWhen executed, this recipe will ensure that openssl is upgraded to the latest version, and that the `stats_collector` service is restarted to pick up the latest security fixes released in the openssl package.\n\n## Libraries\n\nThere are two mixins packaged with this cookbook.\n\n### random_password (`OpenSSLCookbook::RandomPassword`)\n\nThe `RandomPassword` mixin can be used to generate secure random passwords in Chef cookbooks, usually for assignment to a variable or an attribute. `random_password` uses Ruby's SecureRandom library and is customizable.\n\n#### Example Usage\n\n```ruby\nChef::Recipe.send(:include, OpenSSLCookbook::RandomPassword)\nnode.normal['my_secure_attribute'] = random_password\nnode.normal_unless['my_secure_attribute'] = random_password\nnode.normal['my_secure_attribute'] = random_password(length: 50)\nnode.normal['my_secure_attribute'] = random_password(length: 50, mode: :base64)\nnode.normal['my_secure_attribute'] = random_password(length: 50, mode: :base64, encoding: 'ASCII')\n```\n\nNote that node attributes are widely accessible. Storing unencrypted passwords in node attributes, as in this example, carries risk.\n\n## Resources\n\n### openssl_x509_certificate\n\nThis resource generates signed or self-signed, PEM-formatted x509 certificates. If no existing key is specified, the resource will automatically generate a passwordless key with the certificate. If a CA private key and certificate are provided, the certificate will be signed with them.\n\nNote: This resource was renamed from openssl_x509 to openssl_x509_certificate. The legacy name will continue to function, but cookbook code should be updated for the new resource name.\n\n#### Properties\n\nName | Type | Description\n------------------ | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n`path` | String (Optional) | Optional path to write the file to if you'd like to specify it here instead of in the resource name\n`common_name` | String (Optional) | Value for the `CN` certificate field.\n`org` | String (Optional) | Value for the `O` certificate field.\n`org_unit` | String (Optional) | Value for the `OU` certificate field.\n`city` | String (Optional) | Value for the `L` certificate field.\n`state` | String (Optional) | Value for the `ST` certificate field.\n`country` | String (Optional) | Value for the `C` ssl field.\n`email` | String (Optional) | Value for the `email` ssl field.\n`expire` | Integer (Optional) | Value representing the number of days from _now_ through which the issued certificate cert will remain valid. The certificate will expire after this period. _Default: 365\n`extensions` | Hash (Optional) | Hash of X509 Extensions entries, in format `{ 'keyUsage' => { 'values' => %w( keyEncipherment digitalSignature), 'critical' => true } }` _Default: empty_\n`subject_alt_name` | Array (Optional) | Array of _Subject Alternative Name_ entries, in format `DNS:example.com` or `IP:1.2.3.4` _Default: empty_\n`key_file` | String (Optional) | The path to a certificate key file on the filesystem. If the `key_file` property is specified, the resource will attempt to source a key from this location. If no key file is found, the resource will generate a new key file at this location. If the `key_file` property is not specified, the resource will generate a key file in the same directory as the generated certificate, with the same name as the generated certificate.\n`key_pass` | String (Optional) | The passphrase for an existing key's passphrase\n`key_type` | String (Optional) | The desired type of the generated key (rsa or ec). _Default: rsa_\n`key_length` | Integer (Optional) | The desired Bit Length of the generated key (if key_type is equal to 'rsa'). _Default: 2048_\n`key_curve` | String (Optional) | The desired curve of the generated key (if key_type is equal to 'ec'). Run `openssl ecparam -list_curves` to see available options. _Default: prime256v1_\n`csr_file` | String (Optional) | The path to a X509 Certificate Request (CSR) on the filesystem. If the `csr_file` property is specified, the resource will attempt to source a CSR from this location. If no CSR file is found, the resource will generate a Self-Signed Certificate and the certificate fields must be specified (common_name at last).\n`ca_cert_file` | String (Optional) | The path to the CA X509 Certificate on the filesystem. If the `ca_cert_file` property is specified, the `ca_key_file` property must also be specified, the certificate will be signed with them.\n`ca_key_file` | String (Optional) | The path to the CA private key on the filesystem. If the `ca_key_file` property is specified, the `ca_cert_file' property must also be specified, the certificate will be signed with them.\n`ca_key_pass` | String (Optional) | The passphrase for CA private key's passphrase\n`owner` | String (optional) | The owner of all files created by the resource.\n`group` | String (optional) | The group of all files created by the resource.\n`mode` | String or Integer (Optional) | The permission mode of all files created by the resource.\n\n#### Example Usage\n\nIn this example, an administrator wishes to create a self-signed x509 certificate for use with a web server. In order to create the certificate, the administrator crafts this recipe:\n\n```ruby\nopenssl_x509 '/etc/httpd/ssl/mycert.pem' do\n common_name 'www.f00bar.com'\n org 'Foo Bar'\n org_unit 'Lab'\n country 'US'\nend\n```\n\nWhen executed, this recipe will generate a key certificate at `/etc/httpd/ssl/mycert.key`. It will then use that key to generate a new certificate file at `/etc/httpd/ssl/mycert.pem`.\n\nIn this example, an administrator wishes to create a x509 certificate signed with a CA certificate and key. In order to create the certificate, the administrator crafts this recipe:\n\n```ruby\nopenssl_x509_certificate '/etc/ssl_test/my_signed_cert.crt' do\n common_name 'www.f00bar.com'\n ca_key_file '/etc/ssl_test/my_ca.key'\n ca_cert_file '/etc/ssl_test/my_ca.crt'\n expire 365\n extensions(\n 'keyUsage' => {\n 'values' => %w(\n keyEncipherment\n digitalSignature),\n 'critical' => true,\n },\n 'extendedKeyUsage' => {\n 'values' => %w(serverAuth),\n 'critical' => false,\n }\n )\n subject_alt_name ['IP:127.0.0.1', 'DNS:localhost.localdomain']\nend\n```\n\nWhen executed, this recipe will generate a key certificate at `/etc/ssl_test/my_signed_cert.key`. It will then use that key to generate a CSR and signed it with `my_ca.key/my_ca.crt`. A new certificate file at `/etc/ssl_test/my_signed_cert.cert` will be created as a result.\n\n\n### openssl_x509_request\n\nThis resource generates PEM-formatted x509 certificates requests. If no existing key is specified, the resource will automatically generate a passwordless key with the certificate.\n\n#### Properties\n\nName | Type | Description\n--------------------- | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------\n`path` | String (Optional) | Optional path to write the file to if you'd like to specify it here instead of in the resource name\n`common_name` | String (Required) | Value for the `CN` certificate field.\n`org` | String (Optional) | Value for the `O` certificate field.\n`org_unit` | String (Optional) | Value for the `OU` certificate field.\n`city` | String (Optional) | Value for the `L` certificate field.\n`state` | String (Optional) | Value for the `ST` certificate field.\n`country` | String (Optional) | Value for the `C` ssl field.\n`email` | String (Optional) | Value for the `email` ssl field.\n`key_file` | String (Optional) | The path to a certificate key file on the filesystem. If the `key_file` property is specified, the resource will attempt to source a key from this location. If no key file is found, the resource will generate a new key file at this location. If the `key_file` property is not specified, the resource will generate a key file in the same directory as the generated certificate, with the same name as the generated certificate.\n`key_pass` | String (Optional) | The passphrase for an existing key's passphrase\n`key_type` | String (Optional) | The desired type of the generated key (rsa or ec). _Default: ec_\n`key_length` | Integer (Optional) | The desired Bit Length of the generated key (if key_type is equal to 'rsa'). _Default: 2048_\n`key_curve` | String (Optional) | The desired curve of the generated key (if key_type is equal to 'ec'). Run `openssl ecparam -list_curves` to see available options. _Default: prime256v1\n`owner` | String (optional) | The owner of all files created by the resource.\n`group` | String (optional) | The group of all files created by the resource.\n`mode` | String or Integer (Optional) | The permission mode of all files created by the resource.\n\n#### Example Usage\n\nIn this example, an administrator wishes to create a x509 CRL. In order to create the CRL, the administrator crafts this recipe:\n\n```ruby\nopenssl_x509_request '/etc/ssl_test/my_ec_request.csr' do\n common_name 'myecrequest.example.com'\n org 'Test Kitchen Example'\n org_unit 'Kitchens'\n country 'UK'\nend\n```\n\nWhen executed, this recipe will generate a key certificate at `/etc/httpd/ssl/my_ec_request.key`. It will then use that key to generate a new csr file at `/etc/ssl_test/my_ec_request.csr`.\n\n### openssl_x509_crl\n\nThis resource generates PEM-formatted x509 CRL.\n\n#### Properties\n\nName | Type | Description\n--------------------- | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------\n`path` | String (Optional) | Optional path to write the file to if you'd like to specify it here instead of in the resource name\n`serial_to_revoke` | String or Integer(Optional) | Serial of the X509 Certificate to revoke\n`revocation_reason` | String or Integer(Optional) | [Reason of the revocation]((https://en.wikipedia.org/wiki/Certificate_revocation_list#Reasons_for_revocation)) _Default: 0_\n`expire` | Integer (Optional) | Value representing the number of days from _now_ through which the issued CRL will remain valid. The CRL will expire after this period. _Default: 8_\n`renewal_threshold` | Integer (Optional) | Number of days before the expiration. It this threshold is reached, the CRL will be renewed _Default: 1_\n`ca_cert_file` | String (Required) | The path to the CA X509 Certificate on the filesystem. If the `ca_cert_file` property is specified, the `ca_key_file` property must also be specified, the CRL will be signed with them.\n`ca_key_file` | String (Required) | The path to the CA private key on the filesystem. If the `ca_key_file` property is specified, the `ca_cert_file' property must also be specified, the CRL will be signed with them.\n`ca_key_pass` | String (Optional) | The passphrase for CA private key's passphrase\n`owner` | String (optional) | The owner of all files created by the resource.\n`group` | String (optional) | The group of all files created by the resource.\n`mode` | String or Integer (Optional) | The permission mode of all files created by the resource.\n\n\n#### Example Usage\n\nIn this example, an administrator wishes to create an empty X509 CRL. In order to create the CRL, the administrator crafts this recipe:\n\n```ruby\nopenssl_x509_crl '/etc/ssl_test/my_ca.crl' do\n ca_cert_file '/etc/ssl_test/my_ca.crt'\n ca_key_file '/etc/ssl_test/my_ca.key'\nend\n```\n\nWhen executed, this recipe will generate a new CRL file at `/etc/ssl_test/my_ca.crl`.\n\nIn this example, an administrator wishes to revoke a certificate in an existing X509 CRL.\n\n```ruby\nopenssl_x509_crl '/etc/ssl_test/my_ca.crl' do\n ca_cert_file '/etc/ssl_test/my_ca.crt'\n ca_key_file '/etc/ssl_test/my_ca.key'\n serial_to_revoke C7BCB6602A2E4251EF4E2827A228CB52BC0CEA2F\nend\n```\n\n### openssl_dhparam\n\nThis resource generates dhparam.pem files. If a valid dhparam.pem file is found at the specified location, no new file will be created. If a file is found at the specified location but it is not a valid dhparam file, it will be overwritten.\n\n#### Properties\n\nName | Type | Description\n------------ | ---------------------------- | ---------------------------------------------------------------------------------------------------\n`path` | String (Optional) | Optional path to write the file to if you'd like to specify it here instead of in the resource name\n`key_length` | Integer (Optional) | The desired Bit Length of the generated key. _Default: 2048_\n`generator` | Integer (Optional) | The desired Diffie-Hellmann generator. Can be _2_ or _5_.\n`owner` | String (optional) | The owner of all files created by the resource.\n`group` | String (optional) | The group of all files created by the resource.\n`mode` | String or Integer (Optional) | The permission mode of all files created by the resource. _Default: \"0640\"_\n\n#### Example Usage\n\nIn this example, an administrator wishes to create a dhparam.pem file for use with a web server. In order to create the .pem file, the administrator crafts this recipe:\n\n```ruby\nopenssl_dhparam '/etc/httpd/ssl/dhparam.pem' do\n key_length 2048\n generator 2\nend\n```\n\nWhen executed, this recipe will generate a dhparam file at `/etc/httpd/ssl/dhparam.pem`.\n\n### openssl_rsa_private_key\n\nThis resource generates rsa private key files. If a valid rsa key file can be opened at the specified location, no new file will be created. If the RSA key file cannot be opened, either because it does not exist or because the password to the RSA key file does not match the password in the recipe, it will be overwritten.\n\nNote: This resource was renamed from openssl_rsa_key to openssl_rsa_private_key. The legacy name will continue to function, but cookbook code should be updated for the new resource name.\n\n#### Properties\n\nName | Type | Description\n------------ | ---------------------------- | -----------------------------------------------------------------------------------------------------------------------------------\n`path` | String (Optional) | Optional path to write the file to if you'd like to specify it here instead of in the resource name\n`key_length` | Integer (Optional) | The desired Bit Length of the generated key. _Default: 2048_\n`key_cipher` | String (Optional) | The designed cipher to use when generating your key. Run `openssl list-cipher-algorithms` to see available options. _Default: des3_\n`key_pass` | String (Optional) | The desired passphrase for the key.\n`owner` | String (optional) | The owner of all files created by the resource.\n`group` | String (optional) | The group of all files created by the resource.\n`mode` | String or Integer (Optional) | The permission mode of all files created by the resource. _Default: \"0640\"_\n`force` | true/false (Optional) | Force creating the key even if the existing key exists. _Default: false_\n\n#### Example Usage\n\nIn this example, an administrator wishes to create a new RSA private key file in order to generate other certificates and public keys. In order to create the key file, the administrator crafts this recipe:\n\n```ruby\nopenssl_rsa_private_key '/etc/httpd/ssl/server.key' do\n key_length 2048\nend\n```\n\nWhen executed, this recipe will generate a passwordless RSA key file at `/etc/httpd/ssl/server.key`.\n\n### openssl_rsa_public_key\n\nThis resource generates rsa public key files given a private key.\n\n#### Properties\n\nName | Type | Description\n--------------------- | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------\n`path` | String (Optional) | Optional path to write the file to if you'd like to specify it here instead of in the resource name\n`private_key_path` | String (Required unless private_key_content used) | The path to the private key to generate the public key from\n`private_key_content` | String (Required unless private_key_path used) | The content of the private key including new lines. Used if you don't want to write a private key to disk and use `private_key_path`.\n`private_key_pass` | String (Optional) | The passphrase of the provided private key\n`owner` | String (optional) | The owner of all files created by the resource.\n`group` | String (optional) | The group of all files created by the resource.\n`mode` | String or Integer (Optional) | The permission mode of all files created by the resource. _Default: \"0640\"_\n\n**Note**: To use `private_key_content` the private key string must be properly formatted including new lines. The easiest way to get the right string is to run the following from irb (/opt/chefdk/embedded/bin/irb from ChefDK)\n\n```ruby\nFile.read('/foo/bar/private.pem')\n```\n\n#### Example Usage\n\n```ruby\nopenssl_rsa_public_key '/etc/foo/something.pub' do\n priv_key_path '/etc/foo/something.pem'\nend\n```\n\n### openssl_ec_private_key\n\nThis resource generates ec private key files. If a valid ec key file can be opened at the specified location, no new file will be created. If the EC key file cannot be opened, either because it does not exist or because the password to the EC key file does not match the password in the recipe, it will be overwritten.\n\n#### Properties\n\nName | Type | Description\n------------ | ---------------------------- | -----------------------------------------------------------------------------------------------------------------------------------\n`path` | String (Optional) | Optional path to write the file to if you'd like to specify it here instead of in the resource name\n`key_curve` | String (Optional) | The desired curve of the generated key. Run `openssl ecparam -list_curves` to see available options. _Default: prime256v1\n`key_cipher` | String (Optional) | The designed cipher to use when generating your key. Run `openssl list-cipher-algorithms` to see available options. _Default: des3_\n`key_pass` | String (Optional) | The desired passphrase for the key.\n`owner` | String (optional) | The owner of all files created by the resource.\n`group` | String (optional) | The group of all files created by the resource.\n`mode` | String or Integer (Optional) | The permission mode of all files created by the resource. _Default: \"0640\"_\n`force` | true/false (Optional) | Force creating the key even if the existing key exists. _Default: false_\n\n#### Example Usage\n\nIn this example, an administrator wishes to create a new EC private key file in order to generate other certificates and public keys. In order to create the key file, the administrator crafts this recipe:\n\n```ruby\nopenssl_ec_private_key '/etc/httpd/ssl/server.key' do\n key_curve \"prime256v1'\nend\n```\n\nWhen executed, this recipe will generate a passwordless EC key file at `/etc/httpd/ssl/server.key`.\n\n### openssl_ec_public_key\n\nThis resource generates ec public key files given a private key.\n\n#### Properties\n\nName | Type | Description\n--------------------- | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------\n`path` | String (Optional) | Optional path to write the file to if you'd like to specify it here instead of in the resource name\n`private_key_path` | String (Required unless private_key_content used) | The path to the private key to generate the public key from\n`private_key_content` | String (Required unless private_key_path used) | The content of the private key including new lines. Used if you don't want to write a private key to disk and use `private_key_path`.\n`private_key_pass` | String (Optional) | The passphrase of the provided private key\n`owner` | String (optional) | The owner of all files created by the resource. _Default: \"root\"_\n`group` | String (optional) | The group of all files created by the resource. _Default: \"root or wheel depending on platform\"_\n`mode` | String or Integer (Optional) | The permission mode of all files created by the resource. _Default: \"0640\"_\n\n**Note**: To use `private_key_content` the private key string must be properly formatted including new lines. The easiest way to get the right string is to run the following from irb (/opt/chefdk/embedded/bin/irb from ChefDK)\n\n```ruby\nFile.read('/foo/bar/private.pem')\n```\n\n#### Example Usage\n\n```ruby\nopenssl_ec_public_key '/etc/foo/something.pub' do\n priv_key_path '/etc/foo/something.pem'\nend\n```\n\n## Maintainers\n\nThis cookbook is maintained by Chef's Community Cookbook Engineering team. Our goal is to improve cookbook quality and to aid the community in contributing to cookbooks. To learn more about our team, process, and design goals see our [team documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/COOKBOOK_TEAM.MD). To learn more about contributing to cookbooks like this see our [contributing documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD), or if you have general questions about this cookbook come chat with us in #cookbok-engineering on the [Chef Community Slack](http://community-slack.chef.io/)\n\n## License\n\n**Copyright:** 2009-2018, Chef Software, Inc.\n\n```\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"amazon":">= 0.0.0","centos":">= 0.0.0","debian":">= 0.0.0","fedora":">= 0.0.0","freebsd":">= 0.0.0","opensuse":">= 0.0.0","opensuseleap":">= 0.0.0","oracle":">= 0.0.0","redhat":">= 0.0.0","scientific":">= 0.0.0","solaris2":">= 0.0.0","suse":">= 0.0.0","ubuntu":">= 0.0.0","zlinux":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{"openssl::upgrade":"Upgrade OpenSSL library and restart dependent services"},"source_url":"https://github.com/chef-cookbooks/openssl","issues_url":"https://github.com/chef-cookbooks/openssl/issues","chef_version":[[">= 12.7"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/openssl/recipes/default.rb b/cookbooks/openssl/recipes/default.rb new file mode 100644 index 0000000..0311040 --- /dev/null +++ b/cookbooks/openssl/recipes/default.rb @@ -0,0 +1,18 @@ +# +# Cookbook Name:: openssl +# Recipe:: default +# +# Copyright 2009-2016, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# diff --git a/cookbooks/openssl/recipes/upgrade.rb b/cookbooks/openssl/recipes/upgrade.rb new file mode 100644 index 0000000..cd05c97 --- /dev/null +++ b/cookbooks/openssl/recipes/upgrade.rb @@ -0,0 +1,42 @@ +# +# Cookbook:: openssl +# Recipe:: upgrade +# +# Copyright:: 2015-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +case node['platform_family'] +when 'debian', 'ubuntu' + packages = if platform?('debian') && node['platform_version'].to_i >= 9 + %w(libssl1.0.2 openssl) + else + %w(libssl1.0.0 openssl) + end +when 'rhel', 'fedora', 'suse', 'amazon' + packages = %w(openssl) +else + packages = [] +end + +if packages.empty? + Chef::Log.warn("The openssl::upgrade recipe does not currently support #{node['platform']}. If you believe it could please open a PR at https://github.com/chef-cookbooks/openssl") +else + package packages do + action :upgrade + node['openssl']['restart_services'].each do |ssl_svc| + notifies :restart, "service[#{ssl_svc}]" + end + end +end diff --git a/cookbooks/openssl/resources/dhparam.rb b/cookbooks/openssl/resources/dhparam.rb new file mode 100644 index 0000000..f06e6ad --- /dev/null +++ b/cookbooks/openssl/resources/dhparam.rb @@ -0,0 +1,48 @@ +# +# Copyright:: Copyright 2009-2018, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +chef_version_for_provides '< 14.0' if respond_to?(:chef_version_for_provides) +resource_name :openssl_dhparam + +include OpenSSLCookbook::Helpers + +property :path, String, name_property: true +property :key_length, equal_to: [1024, 2048, 4096, 8192], default: 2048 +property :generator, equal_to: [2, 5], default: 2 +property :owner, String +property :group, String +property :mode, [Integer, String], default: '0640' + +action :create do + unless dhparam_pem_valid?(new_resource.path) + converge_by("Create a dhparam file #{new_resource.path}") do + dhparam_content = gen_dhparam(new_resource.key_length, new_resource.generator).to_pem + + log "Generating #{new_resource.key_length} bit "\ + "dhparam file at #{new_resource.path}, this may take some time" + + file new_resource.path do + action :create + owner new_resource.owner unless new_resource.owner.nil? + group new_resource.group unless new_resource.group.nil? + mode new_resource.mode + sensitive true + content dhparam_content + end + end + end +end diff --git a/cookbooks/openssl/resources/ec_private_key.rb b/cookbooks/openssl/resources/ec_private_key.rb new file mode 100644 index 0000000..6d214f3 --- /dev/null +++ b/cookbooks/openssl/resources/ec_private_key.rb @@ -0,0 +1,55 @@ +# +# Copyright:: Copyright 2018, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +chef_version_for_provides '< 14.4' if respond_to?(:chef_version_for_provides) +resource_name :openssl_ec_private_key + +include OpenSSLCookbook::Helpers + +property :path, String, name_property: true +property :key_curve, equal_to: %w(secp384r1 secp521r1 prime256v1 secp224r1 secp256k1), default: 'prime256v1' +property :key_pass, String +property :key_cipher, String, default: 'des3', equal_to: ::OpenSSL::Cipher.ciphers +property :owner, String +property :group, String +property :mode, [Integer, String], default: '0640' +property :force, [true, false], default: false + +action :create do + unless new_resource.force || priv_key_file_valid?(new_resource.path, new_resource.key_pass) + converge_by("Create an EC private key #{new_resource.path}") do + log "Generating an #{new_resource.key_curve} "\ + "EC key file at #{new_resource.name}, this may take some time" + + if new_resource.key_pass + unencrypted_ec_key = gen_ec_priv_key(new_resource.key_curve) + ec_key_content = encrypt_ec_key(unencrypted_ec_key, new_resource.key_pass, new_resource.key_cipher) + else + ec_key_content = gen_ec_priv_key(new_resource.key_curve).to_pem + end + + file new_resource.path do + action :create + owner new_resource.owner unless new_resource.owner.nil? + group new_resource.group unless new_resource.group.nil? + mode new_resource.mode + sensitive true + content ec_key_content + end + end + end +end diff --git a/cookbooks/openssl/resources/ec_public_key.rb b/cookbooks/openssl/resources/ec_public_key.rb new file mode 100644 index 0000000..3e8d4b3 --- /dev/null +++ b/cookbooks/openssl/resources/ec_public_key.rb @@ -0,0 +1,45 @@ +# +# Copyright:: Copyright 2018, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +chef_version_for_provides '< 14.4' if respond_to?(:chef_version_for_provides) +resource_name :openssl_ec_public_key + +include OpenSSLCookbook::Helpers + +property :path, String, name_property: true +property :private_key_path, String +property :private_key_content, String +property :private_key_pass, String +property :owner, String +property :group, String +property :mode, [Integer, String], default: '0640' + +action :create do + raise ArgumentError, "You cannot specify both 'private_key_path' and 'private_key_content' properties at the same time." if new_resource.private_key_path && new_resource.private_key_content + raise ArgumentError, "You must specify the private key with either 'private_key_path' or 'private_key_content' properties." unless new_resource.private_key_path || new_resource.private_key_content + raise "#{new_resource.private_key_path} not a valid private EC key or password is invalid" unless priv_key_file_valid?((new_resource.private_key_path || new_resource.private_key_content), new_resource.private_key_pass) + + ec_key_content = gen_ec_pub_key((new_resource.private_key_path || new_resource.private_key_content), new_resource.private_key_pass) + + file new_resource.path do + action :create + owner new_resource.owner unless new_resource.owner.nil? + group new_resource.group unless new_resource.group.nil? + mode new_resource.mode + content ec_key_content + end +end diff --git a/cookbooks/openssl/resources/rsa_private_key.rb b/cookbooks/openssl/resources/rsa_private_key.rb new file mode 100644 index 0000000..b72c267 --- /dev/null +++ b/cookbooks/openssl/resources/rsa_private_key.rb @@ -0,0 +1,55 @@ +# +# License:: Apache License, Version 2.0 +# +# 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. +# + +chef_version_for_provides '< 14.0' if respond_to?(:chef_version_for_provides) +resource_name :openssl_rsa_private_key +provides :openssl_rsa_key # legacy name + +include OpenSSLCookbook::Helpers + +property :path, String, name_property: true +property :key_length, equal_to: [1024, 2048, 4096, 8192], default: 2048 +property :key_pass, String +property :key_cipher, String, default: 'des3', equal_to: ::OpenSSL::Cipher.ciphers +property :owner, String +property :group, String +property :mode, [Integer, String], default: '0640' +property :force, [true, false], default: false + +action :create do + unless new_resource.force || priv_key_file_valid?(new_resource.path, new_resource.key_pass) + converge_by("Create an RSA private key #{new_resource.path}") do + log "Generating #{new_resource.key_length} bit "\ + "RSA key file at #{new_resource.path}, this may take some time" + + if new_resource.key_pass + unencrypted_rsa_key = gen_rsa_priv_key(new_resource.key_length) + rsa_key_content = encrypt_rsa_key(unencrypted_rsa_key, new_resource.key_pass, new_resource.key_cipher) + else + rsa_key_content = gen_rsa_priv_key(new_resource.key_length).to_pem + end + + file new_resource.path do + action :create + owner new_resource.owner unless new_resource.owner.nil? + group new_resource.group unless new_resource.group.nil? + mode new_resource.mode + sensitive true + content rsa_key_content + end + end + end +end diff --git a/cookbooks/openssl/resources/rsa_public_key.rb b/cookbooks/openssl/resources/rsa_public_key.rb new file mode 100644 index 0000000..83552ef --- /dev/null +++ b/cookbooks/openssl/resources/rsa_public_key.rb @@ -0,0 +1,45 @@ +# +# Copyright:: Copyright 2018, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# 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. +# + +chef_version_for_provides '< 14.0' if respond_to?(:chef_version_for_provides) +resource_name :openssl_rsa_public_key + +include OpenSSLCookbook::Helpers + +property :path, String, name_property: true +property :private_key_path, String +property :private_key_content, String +property :private_key_pass, String +property :owner, String +property :group, String +property :mode, [Integer, String], default: '0640' + +action :create do + raise ArgumentError, "You cannot specify both 'private_key_path' and 'private_key_content' properties at the same time." if new_resource.private_key_path && new_resource.private_key_content + raise ArgumentError, "You must specify the private key with either 'private_key_path' or 'private_key_content' properties." unless new_resource.private_key_path || new_resource.private_key_content + raise "#{new_resource.private_key_path} not a valid private RSA key or password is invalid" unless priv_key_file_valid?((new_resource.private_key_path || new_resource.private_key_content), new_resource.private_key_pass) + + rsa_key_content = gen_rsa_pub_key((new_resource.private_key_path || new_resource.private_key_content), new_resource.private_key_pass) + + file new_resource.path do + action :create + owner new_resource.owner unless new_resource.owner.nil? + group new_resource.group unless new_resource.group.nil? + mode new_resource.mode + content rsa_key_content + end +end diff --git a/cookbooks/openssl/resources/x509_certificate.rb b/cookbooks/openssl/resources/x509_certificate.rb new file mode 100644 index 0000000..71bb91f --- /dev/null +++ b/cookbooks/openssl/resources/x509_certificate.rb @@ -0,0 +1,151 @@ +# +# License:: Apache License, Version 2.0 +# +# 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. +# + +chef_version_for_provides '< 14.4' if respond_to?(:chef_version_for_provides) +resource_name :openssl_x509_certificate + +provides :openssl_x509 # legacy_name + +include OpenSSLCookbook::Helpers + +property :path, String, name_property: true +property :owner, String +property :group, String +property :expire, Integer, default: 365 +property :mode, [Integer, String], default: '0644' +property :country, String +property :state, String +property :city, String +property :org, String +property :org_unit, String +property :common_name, String +property :email, String +property :extensions, Hash, default: {} +property :subject_alt_name, Array, default: [] +property :key_file, String +property :key_pass, String +property :key_type, equal_to: %w(rsa ec), default: 'rsa' +property :key_length, equal_to: [1024, 2048, 4096, 8192], default: 2048 +property :key_curve, equal_to: %w(secp384r1 secp521r1 prime256v1), default: 'prime256v1' +property :csr_file, String +property :ca_cert_file, String +property :ca_key_file, String +property :ca_key_pass, String + +action :create do + unless ::File.exist? new_resource.path + converge_by("Create #{@new_resource}") do + file new_resource.path do + action :create_if_missing + mode new_resource.mode + owner new_resource.owner unless new_resource.owner.nil? + group new_resource.group unless new_resource.group.nil? + sensitive true + content cert.to_pem + end + + if new_resource.csr_file.nil? + file new_resource.key_file do + action :create_if_missing + mode new_resource.mode + owner new_resource.owner unless new_resource.owner.nil? + group new_resource.group unless new_resource.group.nil? + sensitive true + content key.to_pem + end + end + end + end +end + +action_class do + def generate_key_file + unless new_resource.key_file + path, file = ::File.split(new_resource.path) + filename = ::File.basename(file, ::File.extname(file)) + new_resource.key_file path + '/' + filename + '.key' + end + new_resource.key_file + end + + def key + @key ||= if priv_key_file_valid?(generate_key_file, new_resource.key_pass) + ::OpenSSL::PKey.read ::File.read(generate_key_file), new_resource.key_pass + elsif new_resource.key_type == 'rsa' + gen_rsa_priv_key(new_resource.key_length) + else + gen_ec_priv_key(new_resource.key_curve) + end + @key + end + + def request + request = if new_resource.csr_file.nil? + gen_x509_request(subject, key) + else + ::OpenSSL::X509::Request.new ::File.read(new_resource.csr_file) + end + request + end + + def subject + subject = ::OpenSSL::X509::Name.new() + subject.add_entry('C', new_resource.country) unless new_resource.country.nil? + subject.add_entry('ST', new_resource.state) unless new_resource.state.nil? + subject.add_entry('L', new_resource.city) unless new_resource.city.nil? + subject.add_entry('O', new_resource.org) unless new_resource.org.nil? + subject.add_entry('OU', new_resource.org_unit) unless new_resource.org_unit.nil? + subject.add_entry('CN', new_resource.common_name) + subject.add_entry('emailAddress', new_resource.email) unless new_resource.email.nil? + subject + end + + def ca_private_key + ca_private_key = if new_resource.csr_file.nil? + key + else + ::OpenSSL::PKey.read ::File.read(new_resource.ca_key_file), new_resource.ca_key_pass + end + ca_private_key + end + + def ca_info + # Will contain issuer (if any) & expiration + ca_info = {} + + unless new_resource.ca_cert_file.nil? + ca_info['issuer'] = ::OpenSSL::X509::Certificate.new ::File.read(new_resource.ca_cert_file) + end + ca_info['validity'] = new_resource.expire + + ca_info + end + + def extensions + extensions = gen_x509_extensions(new_resource.extensions) + + unless new_resource.subject_alt_name.empty? + extensions += gen_x509_extensions('subjectAltName' => { 'values' => new_resource.subject_alt_name, 'critical' => false }) + end + + extensions + end + + def cert + cert = gen_x509_cert(request, extensions, ca_info, ca_private_key) + cert + end +end diff --git a/cookbooks/openssl/resources/x509_crl.rb b/cookbooks/openssl/resources/x509_crl.rb new file mode 100644 index 0000000..50ad7d9 --- /dev/null +++ b/cookbooks/openssl/resources/x509_crl.rb @@ -0,0 +1,88 @@ +# +# License:: Apache License, Version 2.0 +# +# 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. +# + +chef_version_for_provides '< 14.4' if respond_to?(:chef_version_for_provides) +resource_name :openssl_x509_crl + +include OpenSSLCookbook::Helpers + +property :path, String, name_property: true +property :serial_to_revoke, [Integer, String] +property :revocation_reason, Integer, default: 0 +property :expire, Integer, default: 8 +property :renewal_threshold, Integer, default: 1 +property :ca_cert_file, String, required: true +property :ca_key_file, String, required: true +property :ca_key_pass, String +property :owner, String +property :group, String +property :mode, String + +action :create do + file new_resource.path do + owner new_resource.owner unless new_resource.owner.nil? + group new_resource.group unless new_resource.group.nil? + mode new_resource.mode unless new_resource.mode.nil? + content crl.to_pem + action :create + end +end + +action_class do + def crl_info + # Will contain issuer & expiration + crl_info = {} + + crl_info['issuer'] = ::OpenSSL::X509::Certificate.new ::File.read(new_resource.ca_cert_file) + crl_info['validity'] = new_resource.expire + + crl_info + end + + def revoke_info + # Will contain Serial to revoke & reason + revoke_info = {} + + revoke_info['serial'] = new_resource.serial_to_revoke + revoke_info['reason'] = new_resource.revocation_reason + + revoke_info + end + + def ca_private_key + ca_private_key = ::OpenSSL::PKey.read ::File.read(new_resource.ca_key_file), new_resource.ca_key_pass + ca_private_key + end + + def crl + if crl_file_valid?(new_resource.path) + crl = ::OpenSSL::X509::CRL.new ::File.read(new_resource.path) + else + log "Creating a CRL #{new_resource.path} for CA #{new_resource.ca_cert_file}" + crl = gen_x509_crl(ca_private_key, crl_info) + end + + if !new_resource.serial_to_revoke.nil? && serial_revoked?(crl, new_resource.serial_to_revoke) == false + log "Revoking serial #{new_resource.serial_to_revoke} in CRL #{new_resource.path}" + crl = revoke_x509_crl(revoke_info, crl, ca_private_key, crl_info) + elsif crl.next_update <= Time.now + 3600 * 24 * new_resource.renewal_threshold + log "Renewing CRL for CA #{new_resource.ca_cert_file}" + crl = renew_x509_crl(crl, ca_private_key, crl_info) + end + + crl + end +end diff --git a/cookbooks/openssl/resources/x509_request.rb b/cookbooks/openssl/resources/x509_request.rb new file mode 100644 index 0000000..12ca083 --- /dev/null +++ b/cookbooks/openssl/resources/x509_request.rb @@ -0,0 +1,98 @@ +# +# License:: Apache License, Version 2.0 +# +# 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. +# + +chef_version_for_provides '< 14.4' if respond_to?(:chef_version_for_provides) +resource_name :openssl_x509_request + +include OpenSSLCookbook::Helpers + +property :path, String, name_property: true +property :owner, String +property :group, String +property :mode, [Integer, String], default: '0644' +property :country, String +property :state, String +property :city, String +property :org, String +property :org_unit, String +property :common_name, String, required: true +property :email, String +property :key_file, String +property :key_pass, String +property :key_type, equal_to: %w(rsa ec), default: 'ec' +property :key_length, equal_to: [1024, 2048, 4096, 8192], default: 2048 +property :key_curve, equal_to: %w(secp384r1 secp521r1 prime256v1), default: 'prime256v1' + +action :create do + unless ::File.exist? new_resource.path + converge_by("Create CSR #{@new_resource}") do + file new_resource.name do + owner new_resource.owner unless new_resource.owner.nil? + group new_resource.group unless new_resource.group.nil? + mode new_resource.mode + content csr.to_pem + action :create + end + + file new_resource.key_file do + mode new_resource.mode + owner new_resource.owner unless new_resource.owner.nil? + group new_resource.group unless new_resource.group.nil? + content key.to_pem + sensitive true + action :create_if_missing + end + end + end +end + +action_class do + def generate_key_file + unless new_resource.key_file + path, file = ::File.split(new_resource.path) + filename = ::File.basename(file, ::File.extname(file)) + new_resource.key_file path + '/' + filename + '.key' + end + new_resource.key_file + end + + def key + @key ||= if priv_key_file_valid?(generate_key_file, new_resource.key_pass) + ::OpenSSL::PKey.read ::File.read(generate_key_file), new_resource.key_pass + elsif new_resource.key_type == 'rsa' + gen_rsa_priv_key(new_resource.key_length) + else + gen_ec_priv_key(new_resource.key_curve) + end + @key + end + + def subject + csr_subject = ::OpenSSL::X509::Name.new() + csr_subject.add_entry('C', new_resource.country) unless new_resource.country.nil? + csr_subject.add_entry('ST', new_resource.state) unless new_resource.state.nil? + csr_subject.add_entry('L', new_resource.city) unless new_resource.city.nil? + csr_subject.add_entry('O', new_resource.org) unless new_resource.org.nil? + csr_subject.add_entry('OU', new_resource.org_unit) unless new_resource.org_unit.nil? + csr_subject.add_entry('CN', new_resource.common_name) + csr_subject.add_entry('emailAddress', new_resource.email) unless new_resource.email.nil? + csr_subject + end + + def csr + gen_x509_request(subject, key) + end +end diff --git a/cookbooks/php-fpm/.foodcritic b/cookbooks/php-fpm/.foodcritic new file mode 100644 index 0000000..55a27da --- /dev/null +++ b/cookbooks/php-fpm/.foodcritic @@ -0,0 +1 @@ +~FC015 diff --git a/cookbooks/php-fpm/README.md b/cookbooks/php-fpm/README.md new file mode 100644 index 0000000..a503473 --- /dev/null +++ b/cookbooks/php-fpm/README.md @@ -0,0 +1,142 @@ +[![Build Status](https://travis-ci.org/yevgenko/cookbook-php-fpm.svg?branch=master)](https://travis-ci.org/yevgenko/cookbook-php-fpm) + +# Description + +Installs and configures PHP-FPM (FastCGI Process Manager), an alternative PHP FastCGI implementation with some additional features useful for sites of any size, especially busier sites. It's like the `unicorn` of the PHP world dawg. + +# Requirements + +## Platform + +- Debian, Ubuntu +- CentOS, Red Hat, Fedora +- Amazon Linux + +## Cookbooks + +- none + +## Chef + +- 12.14 or later + +# Description + +Creates a PHP-FPM configuration file at the path specified. Meant to be deployed with a service init scheme/supervisor such as runit. Please see the `application::php-fpm` recipe for a complete working example. In depth information about PHP-FPM's configuration values can be [found in the PHP-FPM documentation](http://php.net/manual/en/install.fpm.configuration.php). + +# Usage + +Simply include the recipe where you want PHP-FPM installed. Default pool **www** will be created. To disable pool creation set default['php-fpm']['pools'] to false. + +To customize settings and pools you can override default attributes. + +## Usage in roles: + +```ruby +name "php-fpm" +description "php fpm role" +run_list "recipe[php-fpm]" +override_attributes "php-fpm" => { + "pools" => { + "default" => { + :enable => true + }, + "www" => { + :enable => "true", + :cookbook => "another-cookbook", + :process_manager => "dynamic", + :max_requests => 5000, + :php_options => { 'php_admin_flag[log_errors]' => 'on', 'php_admin_value[memory_limit]' => '32M' } + } + } +} +``` + +# Creating pools in recipes + +## Create PHP-FPM pool named 'www' with default settings: + +```ruby +php_fpm_pool "www" +``` + +## Create PHP-FPM pool named 'www' with custom settings: + +```ruby +php_fpm_pool "www" do + cookbook "another-cookbook" # get template from another cookbook + process_manager "dynamic" + max_requests 5000 + php_options 'php_admin_flag[log_errors]' => 'on', 'php_admin_value[memory_limit]' => '32M' +end +``` + +## Delete PHP-FPM pool named 'www': + +```ruby +php_fpm_pool "www" do + enable false +end +``` + +# Development + +## Requirements + +- [Docker](https://www.docker.com/) + +## Setup + +To get all dependencies: + +``` +bundle install +``` + +## Test + +To see available platforms: + +``` +bundle exec rake -T +``` + +To test particular platform: + +``` +bundle exec rake kitchen:default-ubuntu-1604 +``` + +To test all platforms: + +``` +bundle exec rake kitchen:all +``` + +## Publishing (maintainers only!) + +Bump version in metadata.rb, commit and push to master! + +``` +bundle exec rake publish +``` + +as a result new tag will be created and pushed to github as well as new version will be published on + +# Contributing + +Please do not bump version when proposing a change, no other rules ;) + +# License and Author + +Author:: Seth Chisamore ([schisamo@chef.io](mailto:schisamo@chef.io)) + +Copyright:: 2011-2017, Chef Software, Inc + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +``` +http://www.apache.org/licenses/LICENSE-2.0 +``` + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/cookbooks/php-fpm/attributes/default.rb b/cookbooks/php-fpm/attributes/default.rb new file mode 100644 index 0000000..e77c7ed --- /dev/null +++ b/cookbooks/php-fpm/attributes/default.rb @@ -0,0 +1,71 @@ +case node['platform_family'] +when 'rhel', 'fedora' + user = 'apache' + group = 'apache' + conf_dir = '/etc/php.d' + pool_conf_dir = '/etc/php-fpm.d' + conf_file = '/etc/php-fpm.conf' + error_log = '/var/log/php-fpm/error.log' + pid = '/var/run/php-fpm/php-fpm.pid' +else + user = 'www-data' + group = 'www-data' + if platform?('ubuntu') && node['platform_version'].to_f >= 16.04 + php_conf_dir = '/etc/php/7.0' + php_fpm_name = 'php7.0-fpm' + else + php_conf_dir = '/etc/php5' + php_fpm_name = 'php5-fpm' + end + conf_dir = "#{php_conf_dir}/fpm/conf.d" + pool_conf_dir = "#{php_conf_dir}/fpm/pool.d" + conf_file = "#{php_conf_dir}/fpm/php-fpm.conf" + error_log = "/var/log/#{php_fpm_name}.log" + pid = "/var/run/#{php_fpm_name}.pid" +end + +default['php-fpm']['user'] = user +default['php-fpm']['group'] = group +default['php-fpm']['conf_dir'] = conf_dir +default['php-fpm']['pool_conf_dir'] = pool_conf_dir +default['php-fpm']['conf_file'] = conf_file +default['php-fpm']['pid'] = pid +default['php-fpm']['log_dir'] = '/var/log/php-fpm' +default['php-fpm']['error_log'] = error_log +default['php-fpm']['log_level'] = 'notice' +default['php-fpm']['emergency_restart_threshold'] = 0 +default['php-fpm']['emergency_restart_interval'] = 0 +default['php-fpm']['process_control_timeout'] = 0 +default['php-fpm']['process_manager'] = 'ondemand' +default['php-fpm']['max_children'] = 50 +default['php-fpm']['start_servers'] = 5 +default['php-fpm']['min_spare_servers'] = 5 +default['php-fpm']['max_spare_servers'] = 35 +default['php-fpm']['max_requests'] = 0 +default['php-fpm']['request_terminate_timeout'] = 0 +default['php-fpm']['catch_workers_output'] = 'no' +default['php-fpm']['security_limit_extensions'] = '.php' +default['php-fpm']['listen_mode'] = '0660' +default['php-fpm']['listen'] = '/var/run/php-fpm-%{pool_name}.sock' + +default['php-fpm']['pools'] = { + 'www' => { + enable: true, + }, +} + +default['php-fpm']['skip_repository_install'] = false +default['php-fpm']['installation_action'] = :install +default['php-fpm']['version'] = nil + +case node['platform_family'] +when 'rhel' + default['php-fpm']['yum_url'] = 'http://rpms.famillecollet.com/enterprise/$releasever/remi/$basearch/' + default['php-fpm']['yum_mirrorlist'] = 'http://rpms.famillecollet.com/enterprise/$releasever/remi/mirror' +when 'fedora' + default['php-fpm']['skip_repository_install'] = true +end + +default['php-fpm']['dotdeb_repository']['uri'] = 'http://packages.dotdeb.org' +default['php-fpm']['dotdeb_repository']['key'] = 'http://www.dotdeb.org/dotdeb.gpg' +default['php-fpm']['dotdeb-php53_repository']['uri'] = 'http://php53.dotdeb.org' diff --git a/cookbooks/php-fpm/definitions/php_fpm_pool.rb b/cookbooks/php-fpm/definitions/php_fpm_pool.rb new file mode 100644 index 0000000..12fc383 --- /dev/null +++ b/cookbooks/php-fpm/definitions/php_fpm_pool.rb @@ -0,0 +1,65 @@ +# +# Cookbook Name:: php-fpm +# Definition:: php_fpm_pool +# +# Copyright 2008-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +define :php_fpm_pool, template: 'pool.conf.erb', enable: true do + pool_name = params[:name] + + conf_file = "#{node['php-fpm']['pool_conf_dir']}/#{pool_name}.conf" + + if params[:enable] + template conf_file do + only_if "test -d #{node['php-fpm']['pool_conf_dir']} || mkdir -p #{node['php-fpm']['pool_conf_dir']}" + source params[:template] + owner 'root' + group 'root' + mode '0644' + cookbook params[:cookbook] || 'php-fpm' + variables( + pool_name: pool_name, + listen: params[:listen] || node['php-fpm']['listen'].gsub(/%{pool_name}/, pool_name), + listen_owner: params[:listen_owner] || node['php-fpm']['listen_owner'] || node['php-fpm']['user'], + listen_group: params[:listen_group] || node['php-fpm']['listen_group'] || node['php-fpm']['group'], + listen_mode: params[:listen_mode] || node['php-fpm']['listen_mode'], + allowed_clients: params[:allowed_clients], + user: params[:user] || node['php-fpm']['user'], + group: params[:group] || node['php-fpm']['group'], + process_manager: params[:process_manager] || node['php-fpm']['process_manager'], + max_children: params[:max_children] || node['php-fpm']['max_children'], + start_servers: params[:start_servers] || node['php-fpm']['start_servers'], + min_spare_servers: params[:min_spare_servers] || node['php-fpm']['min_spare_servers'], + max_spare_servers: params[:max_spare_servers] || node['php-fpm']['max_spare_servers'], + max_requests: params[:max_requests] || node['php-fpm']['max_requests'], + catch_workers_output: params[:catch_workers_output] || node['php-fpm']['catch_workers_output'], + security_limit_extensions: params[:security_limit_extensions] || node['php-fpm']['security_limit_extensions'], + access_log: params[:access_log] || false, + slowlog: params[:slowlog] || false, + request_slowlog_timeout: params[:request_slowlog_timeout] || false, + php_options: params[:php_options] || {}, + request_terminate_timeout: params[:request_terminate_timeout] || node['php-fpm']['request_terminate_timeout'], + params: params + ) + notifies :restart, 'service[php-fpm]' + end + else + cookbook_file conf_file do + action :delete + notifies :restart, 'service[php-fpm]' + end + end +end diff --git a/cookbooks/php-fpm/metadata.json b/cookbooks/php-fpm/metadata.json new file mode 100644 index 0000000..5fc4dbe --- /dev/null +++ b/cookbooks/php-fpm/metadata.json @@ -0,0 +1 @@ +{"name":"php-fpm","version":"0.8.0","description":"Installs/Configures php-fpm","long_description":"[![Build Status](https://travis-ci.org/yevgenko/cookbook-php-fpm.svg?branch=master)](https://travis-ci.org/yevgenko/cookbook-php-fpm)\n\n# Description\n\nInstalls and configures PHP-FPM (FastCGI Process Manager), an alternative PHP FastCGI implementation with some additional features useful for sites of any size, especially busier sites. It's like the `unicorn` of the PHP world dawg.\n\n# Requirements\n\n## Platform\n\n- Debian, Ubuntu\n- CentOS, Red Hat, Fedora\n- Amazon Linux\n\n## Cookbooks\n\n- none\n\n## Chef\n\n- 12.14 or later\n\n# Description\n\nCreates a PHP-FPM configuration file at the path specified. Meant to be deployed with a service init scheme/supervisor such as runit. Please see the `application::php-fpm` recipe for a complete working example. In depth information about PHP-FPM's configuration values can be [found in the PHP-FPM documentation](http://php.net/manual/en/install.fpm.configuration.php).\n\n# Usage\n\nSimply include the recipe where you want PHP-FPM installed. Default pool **www** will be created. To disable pool creation set default['php-fpm']['pools'] to false.\n\nTo customize settings and pools you can override default attributes.\n\n## Usage in roles:\n\n```ruby\nname \"php-fpm\"\ndescription \"php fpm role\"\nrun_list \"recipe[php-fpm]\"\noverride_attributes \"php-fpm\" => {\n \"pools\" => {\n \"default\" => {\n :enable => true\n },\n \"www\" => {\n :enable => \"true\",\n :cookbook => \"another-cookbook\",\n :process_manager => \"dynamic\",\n :max_requests => 5000,\n :php_options => { 'php_admin_flag[log_errors]' => 'on', 'php_admin_value[memory_limit]' => '32M' }\n }\n }\n}\n```\n\n# Creating pools in recipes\n\n## Create PHP-FPM pool named 'www' with default settings:\n\n```ruby\nphp_fpm_pool \"www\"\n```\n\n## Create PHP-FPM pool named 'www' with custom settings:\n\n```ruby\nphp_fpm_pool \"www\" do\n cookbook \"another-cookbook\" # get template from another cookbook\n process_manager \"dynamic\"\n max_requests 5000\n php_options 'php_admin_flag[log_errors]' => 'on', 'php_admin_value[memory_limit]' => '32M'\nend\n```\n\n## Delete PHP-FPM pool named 'www':\n\n```ruby\nphp_fpm_pool \"www\" do\n enable false\nend\n```\n\n# Development\n\n## Requirements\n\n- [Docker](https://www.docker.com/)\n\n## Setup\n\nTo get all dependencies:\n\n```\nbundle install\n```\n\n## Test\n\nTo see available platforms:\n\n```\nbundle exec rake -T\n```\n\nTo test particular platform:\n\n```\nbundle exec rake kitchen:default-ubuntu-1604\n```\n\nTo test all platforms:\n\n```\nbundle exec rake kitchen:all\n```\n\n## Publishing (maintainers only!)\n\nBump version in metadata.rb, commit and push to master!\n\n```\nbundle exec rake publish\n```\n\nas a result new tag will be created and pushed to github as well as new version will be published on \n\n# Contributing\n\nPlease do not bump version when proposing a change, no other rules ;)\n\n# License and Author\n\nAuthor:: Seth Chisamore ([schisamo@chef.io](mailto:schisamo@chef.io))\n\nCopyright:: 2011-2017, Chef Software, Inc\n\nLicensed 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\n\n```\nhttp://www.apache.org/licenses/LICENSE-2.0\n```\n\nUnless 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.\n","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"debian":">= 0.0.0","ubuntu":">= 0.0.0","centos":">= 0.0.0","redhat":">= 0.0.0","fedora":">= 0.0.0","amazon":">= 0.0.0","oracle":">= 0.0.0","scientific":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/yevgenko/cookbook-php-fpm","issues_url":"https://github.com/yevgenko/cookbook-php-fpm/issues","chef_version":[[">= 12.14"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/php-fpm/recipes/configure.rb b/cookbooks/php-fpm/recipes/configure.rb new file mode 100644 index 0000000..26bfb8d --- /dev/null +++ b/cookbooks/php-fpm/recipes/configure.rb @@ -0,0 +1,43 @@ +# +# Author:: Seth Chisamore () +# Cookbook Name:: php-fpm +# Recipe:: package +# +# Copyright 2011-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +template node['php-fpm']['conf_file'] do + source 'php-fpm.conf.erb' + mode 00644 + owner 'root' + group 'root' + notifies :restart, 'service[php-fpm]' +end + +if node['php-fpm']['pools'] + node['php-fpm']['pools'].each do |pool| + if pool.is_a?(Array) + pool_name = pool[0] + pool = pool[1] + else + pool_name = pool[:name] + end + php_fpm_pool pool_name do + pool.each do |k, v| + params[k.to_sym] = v + end + end + end +end diff --git a/cookbooks/php-fpm/recipes/default.rb b/cookbooks/php-fpm/recipes/default.rb new file mode 100644 index 0000000..652298a --- /dev/null +++ b/cookbooks/php-fpm/recipes/default.rb @@ -0,0 +1,22 @@ +# +# Author:: Seth Chisamore () +# Cookbook Name:: php-fpm +# Recipe:: default +# +# Copyright 2011-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'php-fpm::install' +include_recipe 'php-fpm::configure' diff --git a/cookbooks/php-fpm/recipes/install.rb b/cookbooks/php-fpm/recipes/install.rb new file mode 100644 index 0000000..5249919 --- /dev/null +++ b/cookbooks/php-fpm/recipes/install.rb @@ -0,0 +1,59 @@ +# +# Author:: Seth Chisamore () +# Cookbook Name:: php-fpm +# Recipe:: package +# +# Copyright 2011-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'php-fpm::repository' unless node['php-fpm']['skip_repository_install'] + +php_fpm_package_name = if node['php-fpm']['package_name'].nil? + if platform_family?('rhel', 'fedora') + 'php-fpm' + elsif platform?('ubuntu') && node['platform_version'].to_f >= 16.04 + 'php7.0-fpm' + else + 'php5-fpm' + end + else + node['php-fpm']['package_name'] + end + +package php_fpm_package_name do + action node['php-fpm']['installation_action'] + version node['php-fpm']['version'] if node['php-fpm']['version'] +end + +php_fpm_service_name = if node['php-fpm']['service_name'].nil? + php_fpm_package_name + else + node['php-fpm']['service_name'] + end + +service_provider = nil +# this is actually already done in chef, but is kept here for older chef releases +if platform?('ubuntu') && node['platform_version'].to_f.between?(13.10, 14.10) + service_provider = ::Chef::Provider::Service::Upstart +end + +directory node['php-fpm']['log_dir'] + +service 'php-fpm' do + provider service_provider if service_provider + service_name php_fpm_service_name + supports start: true, stop: true, restart: true, reload: true + action [:enable, :start] +end diff --git a/cookbooks/php-fpm/recipes/repository.rb b/cookbooks/php-fpm/recipes/repository.rb new file mode 100644 index 0000000..a0a6c0c --- /dev/null +++ b/cookbooks/php-fpm/recipes/repository.rb @@ -0,0 +1,54 @@ +# +# Author:: Seth Chisamore () +# Cookbook Name:: php-fpm +# Recipe:: package +# +# Copyright 2011-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +case node['platform'] +when 'debian' + # Configure Dotdeb repos + # TODO: move this to it's own 'dotdeb' cookbook? + # http://www.dotdeb.org/instructions/ + if node['platform_version'].to_f >= 8.0 + apt_repository 'dotdeb' do + uri node['php-fpm']['dotdeb_repository']['uri'] + distribution 'jessie' + components ['all'] + key node['php-fpm']['dotdeb_repository']['key'] + action :add + end + elsif node['platform_version'].to_f >= 7.0 + apt_repository 'dotdeb' do + uri node['php-fpm']['dotdeb_repository']['uri'] + distribution 'wheezy' + components ['all'] + key node['php-fpm']['dotdeb_repository']['key'] + action :add + end + end + +when 'amazon', 'fedora', 'centos', 'redhat', 'scientific', 'oracle' + unless platform?('centos', 'redhat') && node['platform_version'].to_f >= 6.4 # ~FC024 + yum_repository 'remi' do + description 'Remi' + url node['php-fpm']['yum_url'] + mirrorlist node['php-fpm']['yum_mirrorlist'] + gpgkey 'http://rpms.famillecollet.com/RPM-GPG-KEY-remi' + action :add + end + end +end diff --git a/cookbooks/php-fpm/recipes/test.rb b/cookbooks/php-fpm/recipes/test.rb new file mode 100644 index 0000000..eff3d5f --- /dev/null +++ b/cookbooks/php-fpm/recipes/test.rb @@ -0,0 +1,3 @@ +include_recipe 'php-fpm::default' + +package 'net-tools' diff --git a/cookbooks/php-fpm/templates/php-fpm.conf.erb b/cookbooks/php-fpm/templates/php-fpm.conf.erb new file mode 100644 index 0000000..900eb7c --- /dev/null +++ b/cookbooks/php-fpm/templates/php-fpm.conf.erb @@ -0,0 +1,60 @@ +;;;;;;;;;;;;;;;;;;;;; +; FPM Configuration ; +;;;;;;;;;;;;;;;;;;;;; + +; All relative paths in this configuration file are relative to PHP's install +; prefix. + +; Include one or more files. If glob(3) exists, it is used to include a bunch of +; files from a glob(3) pattern. This directive can be used everywhere in the +; file. +include = <%= "#{node['php-fpm']['pool_conf_dir']}/*.conf" %> + +;;;;;;;;;;;;;;;;;; +; Global Options ; +;;;;;;;;;;;;;;;;;; + +[global] +; Pid file +; Default Value: none +pid = <%= node['php-fpm']['pid'] %> + +; Error log file +; Default Value: /var/log/php-fpm.log +error_log = <%= node['php-fpm']['error_log'] %> + +; Log level +; Possible Values: alert, error, warning, notice, debug +; Default Value: notice +log_level = <%= node['php-fpm']['log_level'] %> + +; If this number of child processes exit with SIGSEGV or SIGBUS within the time +; interval set by emergency_restart_interval then FPM will restart. A value +; of '0' means 'Off'. +; Default Value: 0 +emergency_restart_threshold = <%= node['php-fpm']['emergency_restart_threshold'] %> + +; Interval of time used by emergency_restart_interval to determine when +; a graceful restart will be initiated. This can be useful to work around +; accidental corruptions in an accelerator's shared memory. +; Available Units: s(econds), m(inutes), h(ours), or d(ays) +; Default Unit: seconds +; Default Value: 0 +emergency_restart_interval = <%= node['php-fpm']['emergency_restart_interval'] %> + +; Time limit for child processes to wait for a reaction on signals from master. +; Available units: s(econds), m(inutes), h(ours), or d(ays) +; Default Unit: seconds +; Default Value: 0 +process_control_timeout = <%= node['php-fpm']['process_control_timeout'] %> + +; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging. +; Default Value: yes +daemonize = yes + +;;;;;;;;;;;;;;;;;;;; +; Pool Definitions ; +;;;;;;;;;;;;;;;;;;;; + +; See <%= "#{node['php-fpm']['pool_conf_dir']}/*.conf" %> + diff --git a/cookbooks/php-fpm/templates/pool.conf.erb b/cookbooks/php-fpm/templates/pool.conf.erb new file mode 100644 index 0000000..ec4fbf3 --- /dev/null +++ b/cookbooks/php-fpm/templates/pool.conf.erb @@ -0,0 +1,424 @@ +; Start a new pool named '<%= @pool_name %>'. +; the variable $pool can we used in any directive and will be replaced by the +; pool name ('<%= @pool_name %>' here) +[<%= @pool_name %>] + +; Per pool prefix +; It only applies on the following directives: +; - 'slowlog' +; - 'listen' (unixsocket) +; - 'chroot' +; - 'chdir' +; - 'php_values' +; - 'php_admin_values' +; When not set, the global prefix (or /usr) applies instead. +; Note: This directive can also be relative to the global prefix. +; Default Value: none +;prefix = /path/to/pools/$pool + +; Unix user/group of processes +; Note: The user is mandatory. If the group is not set, the default user's group +; will be used. +user = <%= @user %> +group = <%= @group %> + +; The address on which to accept FastCGI requests. +; Valid syntaxes are: +; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific address on +; a specific port; +; 'port' - to listen on a TCP socket to all addresses on a +; specific port; +; '/path/to/unix/socket' - to listen on a unix socket. +; Note: This value is mandatory. +listen = <%= @listen %> + +; Set listen(2) backlog. +; Default Value: 128 (-1 on FreeBSD and OpenBSD) +;listen.backlog = 128 + +; Set permissions for unix socket, if one is used. In Linux, read/write +; permissions must be set in order to allow connections from a web server. Many +; BSD-derived systems allow connections regardless of permissions. +; Default Values: user and group are set as the running user +; mode is set to 0666 + +;listen.owner = nobody +<% unless @listen_owner.nil? %> +listen.owner = <%= @listen_owner %> +<% end %> + +;listen.group = nobody +<% unless @listen_group.nil? %> +listen.group = <%= @listen_group %> +<% end %> + +listen.mode = <%= @listen_mode %> + +; List of ipv4 addresses of FastCGI clients which are allowed to connect. +; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original +; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address +; must be separated by a comma. If this value is left blank, connections will be +; accepted from any ip address. +; Default Value: any +listen.allowed_clients = <%= @allowed_clients ? ([@allowed_clients].flatten.join(',')) : "127.0.0.1" %> + +; Specify the nice(2) priority to apply to the pool processes (only if set) +; The value can vary from -19 (highest priority) to 20 (lower priority) +; Note: - It will only work if the FPM master process is launched as root +; - The pool processes will inherit the master process priority +; unless it specified otherwise +; Default Value: no set +; priority = -19 + +; Choose how the process manager will control the number of child processes. +; Possible Values: +; static - a fixed number (pm.max_children) of child processes; +; dynamic - the number of child processes are set dynamically based on the +; following directives. With this process management, there will be +; always at least 1 children. +; pm.max_children - the maximum number of children that can +; be alive at the same time. +; pm.start_servers - the number of children created on startup. +; pm.min_spare_servers - the minimum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is less than this +; number then some children will be created. +; pm.max_spare_servers - the maximum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is greater than this +; number then some children will be killed. +; ondemand - no children are created at startup. Children will be forked when +; new requests will connect. The following parameter are used: +; pm.max_children - the maximum number of children that +; can be alive at the same time. +; pm.process_idle_timeout - The number of seconds after which +; an idle process will be killed. +; Note: This value is mandatory. +pm = <%= @process_manager %> + +; The number of child processes to be created when pm is set to 'static' and the +; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'. +; This value sets the limit on the number of simultaneous requests that will be +; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. +; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP +; CGI. The below defaults are based on a server without much resources. Don't +; forget to tweak pm.* to fit your needs. +; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand' +; Note: This value is mandatory. +pm.max_children = <%= @max_children %> + +<% if @process_manager == "dynamic" %> +; The number of child processes created on startup. +; Note: Used only when pm is set to 'dynamic' +; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 +<% if @start_servers %> +pm.start_servers = <%= @start_servers %> +<% end %> + +; The desired minimum number of idle server processes. +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.min_spare_servers = <%= @min_spare_servers %> + +; The desired maximum number of idle server processes. +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.max_spare_servers = <%= @max_spare_servers %> +<% end %> + +<% if @process_manager == "ondemand" %> +; The number of seconds after which an idle process will be killed. +; Note: Used only when pm is set to 'ondemand' +; Default Value: 10s +;pm.process_idle_timeout = 10s; +<% end %> + +; The number of requests each child process should execute before respawning. +; This can be useful to work around memory leaks in 3rd party libraries. For +; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS. +; Default Value: 0 +pm.max_requests = <%= @max_requests %> + +; The URI to view the FPM status page. If this value is not set, no URI will be +; recognized as a status page. It shows the following informations: +; pool - the name of the pool; +; process manager - static, dynamic or ondemand; +; start time - the date and time FPM has started; +; start since - number of seconds since FPM has started; +; accepted conn - the number of request accepted by the pool; +; listen queue - the number of request in the queue of pending +; connections (see backlog in listen(2)); +; max listen queue - the maximum number of requests in the queue +; of pending connections since FPM has started; +; listen queue len - the size of the socket queue of pending connections; +; idle processes - the number of idle processes; +; active processes - the number of active processes; +; total processes - the number of idle + active processes; +; max active processes - the maximum number of active processes since FPM +; has started; +; max children reached - number of times, the process limit has been reached, +; when pm tries to start more children (works only for +; pm 'dynamic' and 'ondemand'); +; Value are updated in real time. +; Example output: +; pool: www +; process manager: static +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 62636 +; accepted conn: 190460 +; listen queue: 0 +; max listen queue: 1 +; listen queue len: 42 +; idle processes: 4 +; active processes: 11 +; total processes: 15 +; max active processes: 12 +; max children reached: 0 +; +; By default the status page output is formatted as text/plain. Passing either +; 'html', 'xml' or 'json' in the query string will return the corresponding +; output syntax. Example: +; http://www.foo.bar/status +; http://www.foo.bar/status?json +; http://www.foo.bar/status?html +; http://www.foo.bar/status?xml +; +; By default the status page only outputs short status. Passing 'full' in the +; query string will also return status for each pool process. +; Example: +; http://www.foo.bar/status?full +; http://www.foo.bar/status?json&full +; http://www.foo.bar/status?html&full +; http://www.foo.bar/status?xml&full +; The Full status returns for each process: +; pid - the PID of the process; +; state - the state of the process (Idle, Running, ...); +; start time - the date and time the process has started; +; start since - the number of seconds since the process has started; +; requests - the number of requests the process has served; +; request duration - the duration in ms of the requests; +; request method - the request method (GET, POST, ...); +; request URI - the request URI with the query string; +; content length - the content length of the request (only with POST); +; user - the user (PHP_AUTH_USER) (or '-' if not set); +; script - the main script called (or '-' if not set); +; last request cpu - the %cpu the last request consumed +; it's always 0 if the process is not in Idle state +; because CPU calculation is done when the request +; processing has terminated; +; last request memory - the max amount of memory the last request consumed +; it's always 0 if the process is not in Idle state +; because memory calculation is done when the request +; processing has terminated; +; If the process is in Idle state, then informations are related to the +; last request the process has served. Otherwise informations are related to +; the current request being served. +; Example output: +; ************************ +; pid: 31330 +; state: Running +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 63087 +; requests: 12808 +; request duration: 1250261 +; request method: GET +; request URI: /test_mem.php?N=10000 +; content length: 0 +; user: - +; script: /home/fat/web/docs/php/test_mem.php +; last request cpu: 0.00 +; last request memory: 0 +; +; Note: There is a real-time FPM status monitoring sample web page available +; It's available in: ${prefix}/share/fpm/status.html +; +; Note: The value must start with a leading slash (/). The value can be +; anything, but it may not be a good idea to use the .php extension or it +; may conflict with a real PHP file. +; Default Value: not set +;pm.status_path = /status + +; The ping URI to call the monitoring page of FPM. If this value is not set, no +; URI will be recognized as a ping page. This could be used to test from outside +; that FPM is alive and responding, or to +; - create a graph of FPM availability (rrd or such); +; - remove a server from a group if it is not responding (load balancing); +; - trigger alerts for the operating team (24/7). +; Note: The value must start with a leading slash (/). The value can be +; anything, but it may not be a good idea to use the .php extension or it +; may conflict with a real PHP file. +; Default Value: not set +;ping.path = /ping + +; This directive may be used to customize the response of a ping request. The +; response is formatted as text/plain with a 200 response code. +; Default Value: pong +;ping.response = pong + +; The access log file +; Default: not set +<% if @access_log %> +access.log = <%= node['php-fpm']['log_dir'] %>/$pool.access.log +<% end %> + +; The access log format. +; The following syntax is allowed +; %%: the '%' character +; %C: %CPU used by the request +; it can accept the following format: +; - %{user}C for user CPU only +; - %{system}C for system CPU only +; - %{total}C for user + system CPU (default) +; %d: time taken to serve the request +; it can accept the following format: +; - %{seconds}d (default) +; - %{miliseconds}d +; - %{mili}d +; - %{microseconds}d +; - %{micro}d +; %e: an environment variable (same as $_ENV or $_SERVER) +; it must be associated with embraces to specify the name of the env +; variable. Some exemples: +; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e +; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e +; %f: script filename +; %l: content-length of the request (for POST request only) +; %m: request method +; %M: peak of memory allocated by PHP +; it can accept the following format: +; - %{bytes}M (default) +; - %{kilobytes}M +; - %{kilo}M +; - %{megabytes}M +; - %{mega}M +; %n: pool name +; %o: output header +; it must be associated with embraces to specify the name of the header: +; - %{Content-Type}o +; - %{X-Powered-By}o +; - %{Transfert-Encoding}o +; - .... +; %p: PID of the child that serviced the request +; %P: PID of the parent of the child that serviced the request +; %q: the query string +; %Q: the '?' character if query string exists +; %r: the request URI (without the query string, see %q and %Q) +; %R: remote IP address +; %s: status (response code) +; %t: server time the request was received +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; %T: time the log has been written (the request has finished) +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; %u: remote user +; +; Default: "%R - %u %t \"%m %r\" %s" +;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%" + +; The log file for slow requests +; Default Value: not set +; Note: slowlog is mandatory if request_slowlog_timeout is set +<% if @slowlog %> +slowlog = <%= @slowlog %> +<% else %> +;slowlog = log/$pool.log.slow +<% end %> + +; The timeout for serving a single request after which a PHP backtrace will be +; dumped to the 'slowlog' file. A value of '0s' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +<% if @request_slowlog_timeout %> +request_slowlog_timeout = <%=@request_slowlog_timeout %> +<% else %> +;request_slowlog_timeout = 0 +<% end %> + +; The timeout for serving a single request after which the worker process will +; be killed. This option should be used when the 'max_execution_time' ini option +; does not stop script execution for some reason. A value of '0' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +request_terminate_timeout = <%=@request_terminate_timeout %> + +; Set open file descriptor rlimit. +; Default Value: system defined value +;rlimit_files = 1024 + +; Set max core size rlimit. +; Possible Values: 'unlimited' or an integer greater or equal to 0 +; Default Value: system defined value +;rlimit_core = 0 + +; Chroot to this directory at the start. This value must be defined as an +; absolute path. When this value is not set, chroot is not used. +; Note: you can prefix with '$prefix' to chroot to the pool prefix or one +; of its subdirectories. If the pool prefix is not set, the global prefix +; will be used instead. +; Note: chrooting is a great security feature and should be used whenever +; possible. However, all PHP paths will be relative to the chroot +; (error_log, sessions.save_path, ...). +; Default Value: not set +;chroot = + +; Chdir to this directory at the start. +; Note: relative path can be used. +; Default Value: current directory or / when chroot +;chdir = / + +; Redirect worker stdout and stderr into main error log. If not set, stdout and +; stderr will be redirected to /dev/null according to FastCGI specs. +; Note: on highloaded environement, this can cause some delay in the page +; process time (several ms). +; Default Value: no +catch_workers_output = <%= @catch_workers_output %> + +<% if node['platform'] != 'ubuntu' && node['platform_version'] != '10.04' %> +; Limits the extensions of the main script FPM will allow to parse. This can +; prevent configuration mistakes on the web server side. You should only limit +; FPM to .php extensions to prevent malicious users to use other extensions to +; exectute php code. +; Note: set an empty value to allow all extensions. +; Default Value: .php +;security.limit_extensions = .php .php3 .php4 .php5 +security.limit_extensions = <%=@security_limit_extensions %> +<% end %> + +; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from +; the current environment. +; Default Value: clean env +;env[HOSTNAME] = $HOSTNAME +;env[PATH] = /usr/local/bin:/usr/bin:/bin +;env[TMP] = /tmp +;env[TMPDIR] = /tmp +;env[TEMP] = /tmp + +; Additional php.ini defines, specific to this pool of workers. These settings +; overwrite the values previously defined in the php.ini. The directives are the +; same as the PHP SAPI: +; php_value/php_flag - you can set classic ini defines which can +; be overwritten from PHP call 'ini_set'. +; php_admin_value/php_admin_flag - these directives won't be overwritten by +; PHP call 'ini_set' +; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no. + +; Defining 'extension' will load the corresponding shared extension from +; extension_dir. Defining 'disable_functions' or 'disable_classes' will not +; overwrite previously defined php.ini values, but will append the new value +; instead. + +; Note: path INI options can be relative and will be expanded with the prefix +; (pool, global or /usr) + +; Default Value: nothing is defined by default except the values in php.ini and +; specified at startup with the -d argument +;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com +;php_flag[display_errors] = off +;php_admin_value[error_log] = /var/log/fpm-php.www.log +;php_admin_flag[log_errors] = on +;php_admin_value[memory_limit] = 32M + +<% @php_options.each do |name,value| %> +<%= "#{name} = #{value}" %> +<% end %> diff --git a/cookbooks/php/CHANGELOG.md b/cookbooks/php/CHANGELOG.md new file mode 100644 index 0000000..ae0c697 --- /dev/null +++ b/cookbooks/php/CHANGELOG.md @@ -0,0 +1,338 @@ +# php Cookbook CHANGELOG + +This file is used to list changes made in each version of the php cookbook. + +## 6.1.1 (2018-08-07) + +- Pass in missing argument to manage_pecl_ini method when trying to remove a module + +## 6.1.0 (2018-07-24) + +- Allow default recipe to skip pear channel configuration + +## 6.0.0 (2018-04-16) + +### Breaking Change + +This release removes the previous recipes in this cookbook for setting up various PEAR extensions. These should now be setup using the php_pear module directly and not done by adding various recipes / manipulating attributes + +### Other Changes + +- Use the build_essential resource directly so we can call this from Chef itself on Chef 14 +- Add specs for additional platforms +- Move the helpers back into the resources which makes them easier to ship in Chef later +- Break out logic in the channel resource into a helper +- Add support for Amazon Linux 2 + +## 5.1.0 (2018-04-05) + +- Don't eval the action_class +- use php pear binary property in all recipes +- Remove incorrect not_if in the php_pear resource +- More testing updates +- Initial support for Ubuntu 18.04 + +## 5.0.0 (2018-02-15) + +- Simplify this cookbook to remove the dependency on mysql cookbook, and remove the database dependencies in the recipes and attributes. This will allow folks who are using the mysql cookbook to be able to upgrade as needed (or pin to earlier versions). As this is a big change, pin to an earlier version if you need the mysql support that was previously available in this cookbook. Future versions may contain a resource that allows for recompiling php with the necessary extensions. +- Usage of `node['php']['pear']` in the php_pear resource has been replaced with a new 'binary' property for specifying the path to the binary +- Added a new `priority` property to the php_pear resource + +## 4.6.0 (2018-02-07) + +- Converted the php_pear resource to a custom resource +- Moved all helper logic out of the resource and into its own helper library file +- Fix source install on Ubuntu by making sure we have xml2-config package +- Remove options that are no longer recognised by the php installer when installing from source +- Remove matchers as we no longer require them with a modern ChefDK + +## 4.5.0 (2017-07-11) + +- Add reinstall chefspec matcher +- Switch from maintainers files to a simple readme section +- Remove allow_call_time_pass_reference and y2k_compliance config on Debian/Ubuntu as no supported PHP version supports it +- Initial Debian 9 support + +## 4.4.0 (2017-06-27) + +- Add a reinstall action to php_pear +- Added additional specs for package installs on different platforms + +## 4.3.0 (2017-06-27) + +- Remove fallback default php attributes that were used if we were on an unsupported platform. If we don't know the platform we don't support it and we should fail until we add proper support +- Add a few attributes needed for fpm support on opensuse. This is a work in progress to get full PHP support on opensuse +- Install xml deps and avoid using xml cookbook since it's been deprecated +- Expand the php_pear testing +- Remove double logging and log the correct package name in php_pear resource +- Cleanup readme example codes, improve formatting and remove references to LWRPs as they are just resources now + +## 4.2.0 (2017-05-30) + +- Make sure package intalls, php-fpm, and source installs work on Amazon linux +- Avoid symlink warning in the converges +- Simplify the package install logic +- Rename the inspec test to match the suite name so it actually runs +- Test on FreeBSD 11 / Amazon Linux +- Install 5.6.30 by default on source installs + +## 4.1.0 (2017-05-30) + +- Remove class_eval usage and require Chef 12.7+ + +## 4.0.0 (2017-04-20) + +- Fix pear_channel resource to not fail on Chef 12.5 and 12.6 +- Remove support for RHEL 5 as it is now EOL +- Resolve Amazon Linux failures on Chef 13 +- Convert fpm_pool to a custom resource +- Fix php_pear failures on Chef 13 +- Remove non-functional support for Windows +- Remove redundant Ubuntu version checks in the php_pear provider +- Expand testing to test all of the resources + +## 3.1.1 (2017-04-20) + +- Use the cookbook attribute as the default value of pear_channel pear property to provide better platform support + +## 3.1.0 (2017-04-10) + +- Use multi-package installs on supported platform_family(rhel debian suse amazon) +- Use a SPDX standardized license string in the metadata +- Update specs for the new Fauxhai data + +## 3.0.0 (2017-03-27) + +- Converted pear_channel LWRP into custom resource +- Removed use of pear node attribute from pear_channel resource +- Fix cookstyle issue with missing line on metadata.rb +- Clean up kitchen.dokken.yml file to eliminate duplication of testing suites. +- Eliminate duplicated resource from test cookbook that is in the default recipe. +- Rename php-test to standard cookbook testing cookbook of "test" +- Remove EOL ubuntu platform logic + +**NOTE** Windows package installation is currently broken. + +## 2.2.1 (2017-02-21) + +- Fix double definition of ['php']['packages'] for rhel. + +## 2.2.0 (2016-12-12) + +- Use multipackage for installs to speed up chef runs +- Use all CPUs when building from source +- Remove need for apt/yum in testing +- Add opensuse to the metadata +- Migrate to inspec for integration testing + +## 2.1.1 (2016-09-15) + +- Fix recompile un-pack php creates +- Resolve cookstyle warnings + +## 2.1.0 (2016-09-14) + +- Fix source php version check +- Require Chef 12.1 not 12.0 + +## 2.0.0 (2016-09-07) + +- Require Chef 12+ +- Remove the dependency on the Windows cookbook which isn't necessary with Chef 12+ + +## 1.10.1 (2016-08-30) + +- [fix] bug fixes related with Ubuntu 16.04 and PHP 7 support +- adding validator to listen attribute +- Fix node.foo.bar warnings + +## v1.10.0 (2016-07-27) + +- PR #167 Preventing user specified pool of www from being deleted at the end of the chef run on the first install +- PR #122 Add recipe for php module_imap +- PR #172 Fix uninstall action for resource php_fpm_pool + +## v1.9.0 (2016-05-12) + +Special thanks to @ThatGerber for getting the PR for this release together + +- Added support for Ubuntu 16.04 and PHP 7 +- Added support for different listen user/groups with FPM +- Cleaned up resource notification in the pear_channel provider to simplify code +- Fixed Ubuntu 14.04+ not being able to find the GMP library + +## v1.8.0 (2016-02-25) + +- Bumped the source install default version from 5.5.9 to 5.6.13 +- Added a chefignore file to limit the files uploaded to the Chef server +- Added source_url and issues_url to the metadata.rb +- Added additional Chefspec matchers +- Added a Chef standard rubocop.yml file and resolved warnings +- Added serverspec for integration testing +- Remove legacy cloud Test Kitchen configs +- Added testing in Travis CI with kitchen-docker +- Added additional test suites to the Test Kitchen config +- Updated contributing and testing documentation +- Updated testing gem dependencies to the latest +- Added maintainers.md and maintainers.toml files +- Remove gitter chat from the readme +- Add cookbook version badge to the readme +- Added Fedora as a supported platform in the readme +- Add missing cookbook dependencies to the readme + +## v1.7.2 (2015-8-24) + +- Correct spelling in fpm_pool_start_servers (was servres) + +## v1.7.1 (2015-8-17) + +- Correct permissions on ext_conf_dir folder (644 -> 755) + +## v1.7.0 (2015-7-31) + +- NOTICE - This version changes the way the ['php']['directives'] is placed into configuration files. Quotes are no longer automatically placed around these aditional directives. Please take care when rolling out this version. +- Allow additional PHP FPM config +- Add recipe to recompile PHP from source +- Move source dependencies to attributes file +- Misc bug fixes + +## v1.6.0 (2015-7-6) + +- Added ChefSpec matchers +- Added basic PHP-FPM Support (Pre-Release) +- Added support for FreeBSD +- Updated cookbook to use MySQL 6.0 cookbook +- Update cookbook to use php5enmod on supported platforms +- Allow users to override php-mysql package + +## v1.5.0 (2014-10-06) + +- Adding package_options attribute, utilizing in package resource + +## v1.4.6 (2014-03-19) + +- [COOK-4436] - Test this cookbook, not yum. Also test Fedora 20. +- [COOK-4427] - Add oracle as supported operating system + +## v1.4.4 (2014-03-12) + +- [COOK-4393] - Fix convergence bug in source install + +## v1.4.2 (2014-02-27) + +[COOK-4300] - Simplified and fixed pear/pecl logic. [Fixes #56 / #57] + +## v1.4.0 (2014-02-27) + +[COOK-3639] - Allow users to specify php.ini source template + +## v1.3.14 (2014-02-21) + +### Bug + +- **[COOK-4186](https://tickets.opscode.com/browse/COOK-4186)** - Upgrade_package concatenates an empty version string when version is not set or is empty. + +## v1.3.12 (2014-01-28) + +Fix github issue 'Cannot find a resource for preferred_state' + +## v1.3.10 + +Fixing my stove + +## v1.3.8 + +Version bump to ensure artifact sanity + +## v1.3.6 + +Version bump for toolchain + +## v1.3.4 + +Adding platform_family check to include_recipe in source.rb + +## v1.3.2 + +Fixing style cops. Updating test harness + +## v1.3.0 + +### Bug + +- **[COOK-3479](https://tickets.opscode.com/browse/COOK-3479)** - Added Windows support to PHP +- **[COOK-2909](https://tickets.opscode.com/browse/COOK-2909)** - Warnings about Chef::Exceptions::ShellCommandFailed is deprecated + +## v1.2.6 + +### Bug + +- **[COOK-3628](https://tickets.opscode.com/browse/COOK-3628)** - Fix PHP download URL +- **[COOK-3568](https://tickets.opscode.com/browse/COOK-3568)** - Fix Test Kitchen tests +- **[COOK-3402](https://tickets.opscode.com/browse/COOK-3402)** - When the `ext_dir` setting is present, configure php properly for the source recipe +- **[COOK-2926](https://tickets.opscode.com/browse/COOK-2926)** - Fix pear package detection when installing specific version + +## v1.2.4 + +### Improvement + +- **[COOK-3047](https://tickets.opscode.com/browse/COOK-3047)** - Sort directives in `php.ini` +- **[COOK-2928](https://tickets.opscode.com/browse/COOK-2928)** - Abstract `php.ini` directives into variables + +### Bug + +- **[COOK-2378](https://tickets.opscode.com/browse/COOK-2378)** - Fix `php_pear` for libevent + +## v1.2.2 + +### Bug + +- [COOK-3050]: `lib_dir` declared in wrong place for redhat +- [COOK-3102]: remove fileinfo recipe from php cookbook + +### Improvement + +- [COOK-3101]: use a method to abstract range of "el 5" versions in php recipes + +## v1.2.0 + +### Improvement + +- [COOK-2516]: Better support for SUSE distribution for php cookbook +- [COOK-3035]: update php::source to install 5.4.15 by default + +### Bug + +- [COOK-2463]: PHP PEAR Provider Installs Most Recent Version, Without Respect to Preferred State +- [COOK-2514]: php_pear: does not handle more exotic version strings + +## v1.1.8 + +- [COOK-1998] - Enable override of PHP packages in attributes + +## v1.1.6 + +- [COOK-2324] - adds Oracle linux support + +## v1.1.4 + +- [COOK-2106] - `php_pear` cannot find available packages + +## v1.1.2 + +- [COOK-1803] - use better regexp to match package name +- [COOK-1926] - support Amazon linux + +## v1.1.0 + +- [COOK-543] - php.ini template should be configurable +- [COOK-1067] - support for PECL zend extensions +- [COOK-1193] - update package names for EPEL 6 +- [COOK-1348] - rescue Mixlib::ShellOut::ShellCommandFailed (chef 0.10.10) +- [COOK-1465] - fix pear extension template + +## v1.0.2 + +- [COOK-993] Add mhash-devel to centos php source libs +- [COOK-989] - bump version of php to 5.3.10 +- Also download the .tar.gz instead of .tar.bz2 as bzip2 may not be in the base OS (e.g., CentOS 6 minimal) diff --git a/cookbooks/php/CONTRIBUTING.md b/cookbooks/php/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/php/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/cookbooks/php/README.md b/cookbooks/php/README.md new file mode 100644 index 0000000..6bd2873 --- /dev/null +++ b/cookbooks/php/README.md @@ -0,0 +1,263 @@ +# php Cookbook + +[![Build Status](https://travis-ci.org/chef-cookbooks/php.svg?branch=master)](http://travis-ci.org/chef-cookbooks/php) [![Cookbook Version](https://img.shields.io/cookbook/v/php.svg)](https://supermarket.chef.io/cookbooks/php) + +It installs and configures PHP and the PEAR package management system. Also includes resources for managing PEAR (and PECL) packages, PECL channels, and PHP-FPM pools. + +## Requirements + +### Platforms + +- Debian, Ubuntu +- CentOS, Red Hat, Oracle, Scientific, Amazon Linux +- Fedora + +### Chef + +- Chef 12.7+ + +### Cookbooks + +- build-essential + +## Attributes + +- `node['php']['install_method']` = method to install php with, default `package`. +- `node['php']['directives']` = Hash of directives and values to append to `php.ini`, default `{}`. +- `node['php']['pear_setup']` = Boolean value to determine whether to set up pear repositories. Default: `true` +- `node['php']['pear_channels']` = List of external pear channels to add if `node['php']['pear_setup]` is true. Default: `['pear.php.net', 'pecl.php.net']` + +The file also contains the following attribute types: + +- platform specific locations and settings. +- source installation settings + +## Resources + +This cookbook includes resources for managing: + +- PEAR channels +- PEAR/PECL packages + +### `php_pear_channel` + +[PEAR Channels](http://pear.php.net/manual/en/guide.users.commandline.channels.php) are alternative sources for PEAR packages. This resource provides and easy way to manage these channels. + +#### Actions + +- `:discover`: Initialize a channel from its server. +- `:add`: Add a channel to the channel list, usually only used to add private channels. Public channels are usually added using the `:discover` action +- `:update`: Update an existing channel +- `:remove`: Remove a channel from the List + +#### Properties + +- `channel_name`: name attribute. The name of the channel to discover +- `channel_xml`: the channel.xml file of the channel you are adding +- `binary`: pear binary, default: pear + +#### Examples + +```ruby +# discover the horde channel +php_pear_channel "pear.horde.org" do + action :discover +end + +# download xml then add the symfony channel +remote_file "#{Chef::Config[:file_cache_path]}/symfony-channel.xml" do + source 'http://pear.symfony-project.com/channel.xml' + mode '0644' +end +php_pear_channel 'symfony' do + channel_xml "#{Chef::Config[:file_cache_path]}/symfony-channel.xml" + action :add +end + +# update the main pear channel +php_pear_channel 'pear.php.net' do + action :update +end + +# update the main pecl channel +php_pear_channel 'pecl.php.net' do + action :update +end +``` + +### `php_pear` + +[PEAR](http://pear.php.net/) is a framework and distribution system for reusable PHP components. [PECL](http://pecl.php.net/) is a repository for PHP Extensions. PECL contains C extensions for compiling into PHP. As C programs, PECL extensions run more efficiently than PEAR packages. PEARs and PECLs use the same packaging and distribution system. As such this resource is clever enough to abstract away the small differences and can be used for managing either. This resource also creates the proper module .ini file for each PECL extension at the correct location for each supported platform. + +#### Actions + +- `:install`: Install a pear package - if version is provided, install that specific version +- `:upgrade`: Upgrade a pear package - if version is provided, upgrade to that specific version +- `:remove`: Remove a pear package +- `:reinstall`: Force install of the package even if the same version is already installed. Note: This will converge on every Chef run and is probably not what you want. +- `:purge`: An alias for remove as the two behave the same in pear + +#### Properties + +- `package_name`: name attribute. The name of the pear package to install +- `version`: the version of the pear package to install/upgrade. If no version is given latest is assumed. +- `channel`: +- `options`: Add additional options to the underlying pear package command +- `directives`: extra extension directives (settings) for a pecl. on most platforms these usually get rendered into the extension's .ini file +- `zend_extensions`: extension filenames which should be loaded with zend_extension. +- `preferred_state`: PEAR by default installs stable packages only, this allows you to install pear packages in a devel, alpha or beta state +- `binary`: The pear binary to use, by default pear, can be overridden if the binary is not called pear, e.g. pear7 + +#### Examples + +```ruby +# upgrade a pear +php_pear 'XML_RPC' do + action :upgrade +end + +# install a specific version +php_pear 'XML_RPC' do + version '1.5.4' + action :install +end + +# install the mongodb pecl +php_pear 'Install mongo but use a different resource name' do + package_name 'mongo' + action :install +end + +# install the xdebug pecl +php_pear 'xdebug' do + # Specify that xdebug.so must be loaded as a zend extension + zend_extensions ['xdebug.so'] + action :install +end + +# install apc pecl with directives +php_pear 'apc' do + action :install + directives(shm_size: 128, enable_cli: 1) +end + +# install using the pear-7 binary +php_pear 'apc' do + action :install + binary 'pear7' +end + +# install the beta version of Horde_Url +# from the horde channel +hc = php_pear_channel 'pear.horde.org' do + action :discover +end + +php_pear 'Horde_Url' do + preferred_state 'beta' + channel hc.channel_name + action :install +end + +# install the YAML pear from the symfony project +sc = php_pear_channel 'pear.symfony-project.com' do + action :discover +end + +php_pear 'YAML' do + channel sc.channel_name + action :install +end +``` + +### `php_fpm_pool` + +Installs the `php-fpm` package appropriate for your distro (if using packages) and configures a FPM pool for you. Currently only supported in Debian-family operating systems and CentOS 7 (or at least tested with such, YMMV if you are using source). + +Please consider FPM functionally pre-release, and test it thoroughly in your environment before using it in production + +More info: + +#### Actions + +- `:install`: Installs the FPM pool (default). +- `:uninstall`: Removes the FPM pool. + +#### Attribute Parameters + +- `pool_name`: name attribute. The name of the FPM pool. +- `listen`: The listen address. Default: `/var/run/php5-fpm.sock` +- `user`: The user to run the FPM under. Default should be the webserver user for your distro. +- `group`: The group to run the FPM under. Default should be the webserver group for your distro. +- `process_manager`: Process manager to use - see . Default: `dynamic` +- `max_children`: Max children to scale to. Default: 5 +- `start_servers`: Number of servers to start the pool with. Default: 2 +- `min_spare_servers`: Minimum number of servers to have as spares. Default: 1 +- `max_spare_servers`: Maximum number of servers to have as spares. Default: 3 +- `chdir`: The startup working directory of the pool. Default: `/` +- `additional_config`: Additional parameters in JSON. Default: {} + +#### Examples + +```ruby +# Install a FPM pool named "default" +php_fpm_pool 'default' do + action :install +end +``` + +## Recipes + +### default + +Include the default recipe in a run list, to get `php`. By default `php` is installed from packages but this can be changed by using the `install_method` attribute. + +### package + +This recipe installs PHP from packages. + +### source + +This recipe installs PHP from source. + +## Usage + +Simply include the `php` recipe where ever you would like php installed. To install from source override the `node['php']['install_method']` attribute with in a role or wrapper cookbook: + +### Role example: + +```ruby +name 'php' +description 'Install php from source' +override_attributes( + 'php' => { + 'install_method' => 'source', + } +) +run_list( + 'recipe[php]' +) +``` + +## Maintainers + +This cookbook is maintained by Chef's Community Cookbook Engineering team. Our goal is to improve cookbook quality and to aid the community in contributing to cookbooks. To learn more about our team, process, and design goals see our [team documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/COOKBOOK_TEAM.MD). To learn more about contributing to cookbooks like this see our [contributing documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD), or if you have general questions about this cookbook come chat with us in #cookbok-engineering on the [Chef Community Slack](http://community-slack.chef.io/) + +## License + +**Copyright:** 2011-2018, Chef Software, Inc. +**Copyright:** 2018, Oracle and/or its affiliates. All rights reserved + +``` +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/cookbooks/php/attributes/default.rb b/cookbooks/php/attributes/default.rb new file mode 100644 index 0000000..f12383d --- /dev/null +++ b/cookbooks/php/attributes/default.rb @@ -0,0 +1,190 @@ +# +# Cookbook:: php +# Attributes:: default +# +# Copyright:: 2011-2018, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +lib_dir = 'lib' +default['php']['install_method'] = 'package' +default['php']['directives'] = {} +default['php']['bin'] = 'php' + +default['php']['pecl'] = 'pecl' + +default['php']['version'] = '5.6.30' + +default['php']['pear'] = '/usr/bin/pear' +default['php']['pear_setup'] = true +default['php']['pear_channels'] = [ + 'pear.php.net', + 'pecl.php.net', +] + +default['php']['url'] = 'http://us1.php.net/get' +default['php']['checksum'] = '8bc7d93e4c840df11e3d9855dcad15c1b7134e8acf0cf3b90b932baea2d0bde2' +default['php']['prefix_dir'] = '/usr/local' +default['php']['enable_mod'] = '/usr/sbin/php5enmod' +default['php']['disable_mod'] = '/usr/sbin/php5dismod' + +default['php']['ini']['template'] = 'php.ini.erb' +default['php']['ini']['cookbook'] = 'php' + +default['php']['fpm_socket'] = '/var/run/php5-fpm.sock' + +case node['platform_family'] +when 'rhel', 'fedora', 'amazon' + lib_dir = node['kernel']['machine'] =~ /x86_64/ ? 'lib64' : 'lib' + default['php']['conf_dir'] = '/etc' + default['php']['ext_conf_dir'] = '/etc/php.d' + default['php']['fpm_user'] = 'nobody' + default['php']['fpm_group'] = 'nobody' + default['php']['fpm_listen_user'] = 'nobody' + default['php']['fpm_listen_group'] = 'nobody' + default['php']['ext_dir'] = "/usr/#{lib_dir}/php/modules" + if node['platform'] == 'amazon' # amazon names their packages with versions on 201X amazon + default['php']['src_deps'] = %w(bzip2-devel libc-client-devel curl-devel freetype-devel gmp-devel libjpeg-devel krb5-devel libmcrypt-devel libpng-devel openssl-devel t1lib-devel libxml2-devel libxslt-devel zlib-devel) + + if node['platform_version'].to_i == 2 + default['php']['packages'] = %w(php php-devel php-pear) + default['php']['fpm_package'] = 'php-fpm' + else + default['php']['packages'] = %w(php56 php56-devel php-pear) + default['php']['fpm_package'] = 'php56-fpm' + end + else # redhat does not name their packages with version on RHEL 6+ + default['php']['src_deps'] = %w(bzip2-devel libc-client-devel curl-devel freetype-devel gmp-devel libjpeg-devel krb5-devel libmcrypt-devel libpng-devel openssl-devel t1lib-devel libxml2-devel libxslt-devel zlib-devel mhash-devel) + default['php']['packages'] = %w(php php-devel php-cli php-pear) + default['php']['fpm_package'] = 'php-fpm' + end + default['php']['fpm_pooldir'] = '/etc/php-fpm.d' + default['php']['fpm_default_conf'] = '/etc/php-fpm.d/www.conf' + default['php']['fpm_service'] = 'php-fpm' + if node['php']['install_method'] == 'package' + default['php']['fpm_user'] = 'apache' + default['php']['fpm_group'] = 'apache' + default['php']['fpm_listen_user'] = 'apache' + default['php']['fpm_listen_group'] = 'apache' + end +when 'debian' + default['php']['conf_dir'] = '/etc/php5/cli' + default['php']['ext_conf_dir'] = '/etc/php5/conf.d' + default['php']['src_deps'] = %w(libbz2-dev libc-client2007e-dev libcurl4-gnutls-dev libfreetype6-dev libgmp3-dev libjpeg62-dev libkrb5-dev libmcrypt-dev libpng12-dev libssl-dev libt1-dev libxml2-dev libxslt-dev zlib1g-dev) + default['php']['packages'] = %w(php5-cgi php5 php5-dev php5-cli php-pear) + default['php']['fpm_package'] = 'php5-fpm' + default['php']['fpm_pooldir'] = '/etc/php5/fpm/pool.d' + default['php']['fpm_user'] = 'www-data' + default['php']['fpm_group'] = 'www-data' + default['php']['fpm_listen_user'] = 'www-data' + default['php']['fpm_listen_group'] = 'www-data' + default['php']['fpm_service'] = 'php5-fpm' + default['php']['fpm_default_conf'] = '/etc/php5/fpm/pool.d/www.conf' + + if (platform?('debian') && node['platform_version'].to_i >= 9) || + (platform?('ubuntu') && node['platform_version'].to_f == 16.04) + default['php']['version'] = '7.0.4' + default['php']['checksum'] = 'f6cdac2fd37da0ac0bbcee0187d74b3719c2f83973dfe883d5cde81c356fe0a8' + default['php']['conf_dir'] = '/etc/php/7.0/cli' + default['php']['src_deps'] = %w(libbz2-dev libc-client2007e-dev libcurl4-gnutls-dev libfreetype6-dev libgmp3-dev libjpeg62-dev libkrb5-dev libmcrypt-dev libpng12-dev libssl-dev pkg-config libxml2-dev) + default['php']['packages'] = %w(php7.0-cgi php7.0 php7.0-dev php7.0-cli php-pear) + default['php']['fpm_package'] = 'php7.0-fpm' + default['php']['fpm_pooldir'] = '/etc/php/7.0/fpm/pool.d' + default['php']['fpm_service'] = 'php7.0-fpm' + default['php']['fpm_socket'] = '/var/run/php/php7.0-fpm.sock' + default['php']['fpm_default_conf'] = '/etc/php/7.0/fpm/pool.d/www.conf' + default['php']['enable_mod'] = '/usr/sbin/phpenmod' + default['php']['disable_mod'] = '/usr/sbin/phpdismod' + default['php']['ext_conf_dir'] = '/etc/php/7.0/mods-available' + elsif platform?('ubuntu') && node['platform_version'].to_f >= 18.04 + default['php']['version'] = '7.0.4' + default['php']['checksum'] = 'f6cdac2fd37da0ac0bbcee0187d74b3719c2f83973dfe883d5cde81c356fe0a8' + default['php']['conf_dir'] = '/etc/php/7.2/cli' + default['php']['src_deps'] = %w(libbz2-dev libc-client2007e-dev libcurl4-gnutls-dev libfreetype6-dev libgmp3-dev libjpeg62-dev libkrb5-dev libmcrypt-dev libpng12-dev libssl-dev pkg-config libxml2-dev) + default['php']['packages'] = %w(php7.2-cgi php7.2 php7.2-dev php7.2-cli php-pear) + default['php']['fpm_package'] = 'php7.2-fpm' + default['php']['fpm_pooldir'] = '/etc/php/7.2/fpm/pool.d' + default['php']['fpm_service'] = 'php7.2-fpm' + default['php']['fpm_socket'] = '/var/run/php/php7.2-fpm.sock' + default['php']['fpm_default_conf'] = '/etc/php/7.2/fpm/pool.d/www.conf' + default['php']['enable_mod'] = '/usr/sbin/phpenmod' + default['php']['disable_mod'] = '/usr/sbin/phpdismod' + default['php']['ext_conf_dir'] = '/etc/php/7.2/mods-available' + end + + case node['platform'] + when 'ubuntu' + case node['platform_version'].to_f + when 13.04..15.10 + default['php']['ext_conf_dir'] = '/etc/php5/mods-available' + end + when 'debian' + if node['platform_version'].to_i == 8 + default['php']['ext_conf_dir'] = '/etc/php5/mods-available' + end + end +when 'suse' + default['php']['conf_dir'] = '/etc/php5/cli' + default['php']['ext_conf_dir'] = '/etc/php5/conf.d' + default['php']['src_deps'] = %w(libbz2-dev libc-client2007e-dev libcurl4-gnutls-dev libfreetype6-dev libgmp3-dev libjpeg62-dev libkrb5-dev libmcrypt-dev libpng12-dev libssl-dev libt1-dev libxml2-devel libxslt-devel zlib-devel) + default['php']['fpm_default_conf'] = '/etc/php-fpm.d/www.conf' + default['php']['fpm_pooldir'] = '/etc/php5/fpm' + default['php']['fpm_service'] = 'php-fpm' + default['php']['fpm_package'] = 'php5-fpm' + default['php']['fpm_user'] = 'wwwrun' + default['php']['fpm_group'] = 'www' + default['php']['fpm_listen_user'] = 'wwwrun' + default['php']['fpm_listen_group'] = 'www' + default['php']['packages'] = %w(apache2-mod_php5 php5-pear) + lib_dir = node['kernel']['machine'] =~ /x86_64/ ? 'lib64' : 'lib' +when 'freebsd' + default['php']['conf_dir'] = '/usr/local/etc' + default['php']['ext_conf_dir'] = '/usr/local/etc/php' + default['php']['src_deps'] = %w(libbz2-dev libc-client2007e-dev libcurl4-gnutls-dev libfreetype6-dev libgmp3-dev libjpeg62-dev libkrb5-dev libmcrypt-dev libpng12-dev libssl-dev libt1-dev) + default['php']['fpm_user'] = 'www' + default['php']['fpm_group'] = 'www' + default['php']['fpm_listen_user'] = 'www' + default['php']['fpm_listen_group'] = 'www' + default['php']['packages'] = %w( php56 pear ) +end + +default['php']['configure_options'] = %W(--prefix=#{node['php']['prefix_dir']} + --with-libdir=#{lib_dir} + --with-config-file-path=#{node['php']['conf_dir']} + --with-config-file-scan-dir=#{node['php']['ext_conf_dir']} + --with-pear + --enable-fpm + --with-fpm-user=#{node['php']['fpm_user']} + --with-fpm-group=#{node['php']['fpm_group']} + --with-zlib + --with-openssl + --with-kerberos + --with-bz2 + --with-curl + --enable-ftp + --enable-zip + --enable-exif + --with-gd + --enable-gd-native-ttf + --with-gettext + --with-gmp + --with-mhash + --with-iconv + --with-imap + --with-imap-ssl + --enable-sockets + --enable-soap + --with-xmlrpc + --with-mcrypt + --enable-mbstring) diff --git a/cookbooks/php/metadata.json b/cookbooks/php/metadata.json new file mode 100644 index 0000000..5f11b3d --- /dev/null +++ b/cookbooks/php/metadata.json @@ -0,0 +1 @@ +{"name":"php","version":"6.1.1","description":"Installs and maintains php and php modules","long_description":"# php Cookbook\n\n[![Build Status](https://travis-ci.org/chef-cookbooks/php.svg?branch=master)](http://travis-ci.org/chef-cookbooks/php) [![Cookbook Version](https://img.shields.io/cookbook/v/php.svg)](https://supermarket.chef.io/cookbooks/php)\n\nIt installs and configures PHP and the PEAR package management system. Also includes resources for managing PEAR (and PECL) packages, PECL channels, and PHP-FPM pools.\n\n## Requirements\n\n### Platforms\n\n- Debian, Ubuntu\n- CentOS, Red Hat, Oracle, Scientific, Amazon Linux\n- Fedora\n\n### Chef\n\n- Chef 12.7+\n\n### Cookbooks\n\n- build-essential\n\n## Attributes\n\n- `node['php']['install_method']` = method to install php with, default `package`.\n- `node['php']['directives']` = Hash of directives and values to append to `php.ini`, default `{}`.\n- `node['php']['pear_setup']` = Boolean value to determine whether to set up pear repositories. Default: `true`\n- `node['php']['pear_channels']` = List of external pear channels to add if `node['php']['pear_setup]` is true. Default: `['pear.php.net', 'pecl.php.net']`\n\nThe file also contains the following attribute types:\n\n- platform specific locations and settings.\n- source installation settings\n\n## Resources\n\nThis cookbook includes resources for managing:\n\n- PEAR channels\n- PEAR/PECL packages\n\n### `php_pear_channel`\n\n[PEAR Channels](http://pear.php.net/manual/en/guide.users.commandline.channels.php) are alternative sources for PEAR packages. This resource provides and easy way to manage these channels.\n\n#### Actions\n\n- `:discover`: Initialize a channel from its server.\n- `:add`: Add a channel to the channel list, usually only used to add private channels. Public channels are usually added using the `:discover` action\n- `:update`: Update an existing channel\n- `:remove`: Remove a channel from the List\n\n#### Properties\n\n- `channel_name`: name attribute. The name of the channel to discover\n- `channel_xml`: the channel.xml file of the channel you are adding\n- `binary`: pear binary, default: pear\n\n#### Examples\n\n```ruby\n# discover the horde channel\nphp_pear_channel \"pear.horde.org\" do\n action :discover\nend\n\n# download xml then add the symfony channel\nremote_file \"#{Chef::Config[:file_cache_path]}/symfony-channel.xml\" do\n source 'http://pear.symfony-project.com/channel.xml'\n mode '0644'\nend\nphp_pear_channel 'symfony' do\n channel_xml \"#{Chef::Config[:file_cache_path]}/symfony-channel.xml\"\n action :add\nend\n\n# update the main pear channel\nphp_pear_channel 'pear.php.net' do\n action :update\nend\n\n# update the main pecl channel\nphp_pear_channel 'pecl.php.net' do\n action :update\nend\n```\n\n### `php_pear`\n\n[PEAR](http://pear.php.net/) is a framework and distribution system for reusable PHP components. [PECL](http://pecl.php.net/) is a repository for PHP Extensions. PECL contains C extensions for compiling into PHP. As C programs, PECL extensions run more efficiently than PEAR packages. PEARs and PECLs use the same packaging and distribution system. As such this resource is clever enough to abstract away the small differences and can be used for managing either. This resource also creates the proper module .ini file for each PECL extension at the correct location for each supported platform.\n\n#### Actions\n\n- `:install`: Install a pear package - if version is provided, install that specific version\n- `:upgrade`: Upgrade a pear package - if version is provided, upgrade to that specific version\n- `:remove`: Remove a pear package\n- `:reinstall`: Force install of the package even if the same version is already installed. Note: This will converge on every Chef run and is probably not what you want.\n- `:purge`: An alias for remove as the two behave the same in pear\n\n#### Properties\n\n- `package_name`: name attribute. The name of the pear package to install\n- `version`: the version of the pear package to install/upgrade. If no version is given latest is assumed.\n- `channel`:\n- `options`: Add additional options to the underlying pear package command\n- `directives`: extra extension directives (settings) for a pecl. on most platforms these usually get rendered into the extension's .ini file\n- `zend_extensions`: extension filenames which should be loaded with zend_extension.\n- `preferred_state`: PEAR by default installs stable packages only, this allows you to install pear packages in a devel, alpha or beta state\n- `binary`: The pear binary to use, by default pear, can be overridden if the binary is not called pear, e.g. pear7\n\n#### Examples\n\n```ruby\n# upgrade a pear\nphp_pear 'XML_RPC' do\n action :upgrade\nend\n\n# install a specific version\nphp_pear 'XML_RPC' do\n version '1.5.4'\n action :install\nend\n\n# install the mongodb pecl\nphp_pear 'Install mongo but use a different resource name' do\n package_name 'mongo'\n action :install\nend\n\n# install the xdebug pecl\nphp_pear 'xdebug' do\n # Specify that xdebug.so must be loaded as a zend extension\n zend_extensions ['xdebug.so']\n action :install\nend\n\n# install apc pecl with directives\nphp_pear 'apc' do\n action :install\n directives(shm_size: 128, enable_cli: 1)\nend\n\n# install using the pear-7 binary\nphp_pear 'apc' do\n action :install\n binary 'pear7'\nend\n\n# install the beta version of Horde_Url\n# from the horde channel\nhc = php_pear_channel 'pear.horde.org' do\n action :discover\nend\n\nphp_pear 'Horde_Url' do\n preferred_state 'beta'\n channel hc.channel_name\n action :install\nend\n\n# install the YAML pear from the symfony project\nsc = php_pear_channel 'pear.symfony-project.com' do\n action :discover\nend\n\nphp_pear 'YAML' do\n channel sc.channel_name\n action :install\nend\n```\n\n### `php_fpm_pool`\n\nInstalls the `php-fpm` package appropriate for your distro (if using packages) and configures a FPM pool for you. Currently only supported in Debian-family operating systems and CentOS 7 (or at least tested with such, YMMV if you are using source).\n\nPlease consider FPM functionally pre-release, and test it thoroughly in your environment before using it in production\n\nMore info: \n\n#### Actions\n\n- `:install`: Installs the FPM pool (default).\n- `:uninstall`: Removes the FPM pool.\n\n#### Attribute Parameters\n\n- `pool_name`: name attribute. The name of the FPM pool.\n- `listen`: The listen address. Default: `/var/run/php5-fpm.sock`\n- `user`: The user to run the FPM under. Default should be the webserver user for your distro.\n- `group`: The group to run the FPM under. Default should be the webserver group for your distro.\n- `process_manager`: Process manager to use - see . Default: `dynamic`\n- `max_children`: Max children to scale to. Default: 5\n- `start_servers`: Number of servers to start the pool with. Default: 2\n- `min_spare_servers`: Minimum number of servers to have as spares. Default: 1\n- `max_spare_servers`: Maximum number of servers to have as spares. Default: 3\n- `chdir`: The startup working directory of the pool. Default: `/`\n- `additional_config`: Additional parameters in JSON. Default: {}\n\n#### Examples\n\n```ruby\n# Install a FPM pool named \"default\"\nphp_fpm_pool 'default' do\n action :install\nend\n```\n\n## Recipes\n\n### default\n\nInclude the default recipe in a run list, to get `php`. By default `php` is installed from packages but this can be changed by using the `install_method` attribute.\n\n### package\n\nThis recipe installs PHP from packages.\n\n### source\n\nThis recipe installs PHP from source.\n\n## Usage\n\nSimply include the `php` recipe where ever you would like php installed. To install from source override the `node['php']['install_method']` attribute with in a role or wrapper cookbook:\n\n### Role example:\n\n```ruby\nname 'php'\ndescription 'Install php from source'\noverride_attributes(\n 'php' => {\n 'install_method' => 'source',\n }\n)\nrun_list(\n 'recipe[php]'\n)\n```\n\n## Maintainers\n\nThis cookbook is maintained by Chef's Community Cookbook Engineering team. Our goal is to improve cookbook quality and to aid the community in contributing to cookbooks. To learn more about our team, process, and design goals see our [team documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/COOKBOOK_TEAM.MD). To learn more about contributing to cookbooks like this see our [contributing documentation](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD), or if you have general questions about this cookbook come chat with us in #cookbok-engineering on the [Chef Community Slack](http://community-slack.chef.io/)\n\n## License\n\n**Copyright:** 2011-2018, Chef Software, Inc.\n**Copyright:** 2018, Oracle and/or its affiliates. All rights reserved\n\n```\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"amazon":">= 0.0.0","centos":">= 0.0.0","debian":">= 0.0.0","fedora":">= 0.0.0","oracle":">= 0.0.0","redhat":">= 0.0.0","scientific":">= 0.0.0","suse":">= 0.0.0","opensuse":">= 0.0.0","opensuseleap":">= 0.0.0","ubuntu":">= 0.0.0"},"dependencies":{"build-essential":">= 5.0","yum-epel":">= 0.0.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{"php":"Installs php","php::package":"Installs php using packages.","php::source":"Installs php from source."},"source_url":"https://github.com/chef-cookbooks/php","issues_url":"https://github.com/chef-cookbooks/php/issues","chef_version":[[">= 12.7"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/php/recipes/default.rb b/cookbooks/php/recipes/default.rb new file mode 100644 index 0000000..7692ca4 --- /dev/null +++ b/cookbooks/php/recipes/default.rb @@ -0,0 +1,33 @@ +# +# Author:: Joshua Timberman () +# Author:: Seth Chisamore () +# Cookbook:: php +# Recipe:: default +# +# Copyright:: 2009-2018, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe "php::#{node['php']['install_method']}" + +# update the main channels +node['php']['pear_channels'].each do |channel| + php_pear_channel channel do + binary node['php']['pear'] + action :update + only_if { node['php']['pear_setup'] } + end +end + +include_recipe 'php::ini' diff --git a/cookbooks/php/recipes/ini.rb b/cookbooks/php/recipes/ini.rb new file mode 100644 index 0000000..df348d7 --- /dev/null +++ b/cookbooks/php/recipes/ini.rb @@ -0,0 +1,29 @@ +# +# Author:: Christo De Lange () +# Cookbook:: php +# Recipe:: ini +# +# Copyright:: 2011-2018, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +template "#{node['php']['conf_dir']}/php.ini" do + source node['php']['ini']['template'] + cookbook node['php']['ini']['cookbook'] + owner 'root' + group node['root_group'] + mode '0644' + manage_symlink_source true + variables(directives: node['php']['directives']) +end diff --git a/cookbooks/php/recipes/package.rb b/cookbooks/php/recipes/package.rb new file mode 100644 index 0000000..b361ff2 --- /dev/null +++ b/cookbooks/php/recipes/package.rb @@ -0,0 +1,34 @@ +# +# Author:: Seth Chisamore () +# Author:: Lucas Hansen () +# Cookbook:: php +# Recipe:: package +# +# Copyright:: 2013-2018, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if platform_family?('rhel', 'debian', 'amazon', 'suse') + package node['php']['packages'] do + options node['php']['package_options'] + end +else + node['php']['packages'].each do |pkg| + package pkg do + options node['php']['package_options'] + end + end +end + +include_recipe 'php::ini' diff --git a/cookbooks/php/recipes/recompile.rb b/cookbooks/php/recipes/recompile.rb new file mode 100644 index 0000000..46398cb --- /dev/null +++ b/cookbooks/php/recipes/recompile.rb @@ -0,0 +1,51 @@ +# +# Author:: David Kinzer () +# Cookbook:: php +# Recipe:: recompile +# +# Copyright:: 2014-2018, David Kinzer +# +# 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. +# + +version = node['php']['version'] +configure_options = node['php']['configure_options'].join(' ') +ext_dir_prefix = node['php']['ext_dir'] ? "EXTENSION_DIR=#{node['php']['ext_dir']}" : '' + +node['php']['src_deps'].each do |pkg| + package pkg do + action 'install' + end +end + +remote_file "#{Chef::Config[:file_cache_path]}/php-#{version}.tar.gz" do + source "#{node['php']['url']}/php-#{version}.tar.gz/from/this/mirror" + checksum node['php']['checksum'] + mode '0644' + action 'create_if_missing' +end + +bash 'un-pack php' do + cwd Chef::Config[:file_cache_path] + code "tar -zxf php-#{version}.tar.gz" + creates "#{Chef::Config[:file_cache_path]}/php-#{version}" +end + +bash 're-build php' do + cwd "#{Chef::Config[:file_cache_path]}/php-#{version}" + code <<-EOF + (make clean) + (#{ext_dir_prefix} ./configure #{configure_options}) + (make -j #{node['cpu']['total']} && make install) + EOF +end diff --git a/cookbooks/php/recipes/source.rb b/cookbooks/php/recipes/source.rb new file mode 100644 index 0000000..407fab9 --- /dev/null +++ b/cookbooks/php/recipes/source.rb @@ -0,0 +1,80 @@ +# +# Author:: Seth Chisamore () +# Cookbook:: php +# Recipe:: source +# +# Copyright:: 2011-2018, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +configure_options = node['php']['configure_options'].join(' ') + +build_essential 'install compilation tools' +include_recipe 'yum-epel' if node['platform_family'] == 'rhel' + +package node['php']['src_deps'] + +version = node['php']['version'] + +remote_file "#{Chef::Config[:file_cache_path]}/php-#{version}.tar.gz" do + source "#{node['php']['url']}/php-#{version}.tar.gz/from/this/mirror" + checksum node['php']['checksum'] + mode '0644' + not_if "$(which #{node['php']['bin']}) --version | grep #{version}" +end + +if node['php']['ext_dir'] + directory node['php']['ext_dir'] do + owner 'root' + group 'root' + mode '0755' + recursive true + end + ext_dir_prefix = "EXTENSION_DIR=#{node['php']['ext_dir']}" +else + ext_dir_prefix = '' +end + +# PHP is unable to find the GMP library in 16.04. The symlink brings the file +# inside of the include libraries. +link '/usr/include/gmp.h' do + to '/usr/include/x86_64-linux-gnu/gmp.h' + only_if { node['platform_family'] == 'debian' && node['platform_version'].to_f >= 14.04 } +end + +bash 'build php' do + cwd Chef::Config[:file_cache_path] + code <<-EOF + tar -zxf php-#{version}.tar.gz + (cd php-#{version} && #{ext_dir_prefix} ./configure #{configure_options}) + (cd php-#{version} && make -j #{node['cpu']['total']} && make install) + EOF + not_if "$(which #{node['php']['bin']}) --version | grep #{version}" +end + +directory node['php']['conf_dir'] do + owner 'root' + group 'root' + mode '0755' + recursive true +end + +directory node['php']['ext_conf_dir'] do + owner 'root' + group 'root' + mode '0755' + recursive true +end + +include_recipe 'php::ini' diff --git a/cookbooks/php/resources/fpm_pool.rb b/cookbooks/php/resources/fpm_pool.rb new file mode 100644 index 0000000..87570c8 --- /dev/null +++ b/cookbooks/php/resources/fpm_pool.rb @@ -0,0 +1,97 @@ +# +# Author:: Chris Marchesi +# Cookbook:: php +# Resource:: fpm_pool +# +# Copyright:: 2015-2018, Chef Software, Inc +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +property :pool_name, String, name_property: true +property :listen, String, default: lazy { node['php']['fpm_socket'] } +property :user, String, default: lazy { node['php']['fpm_user'] } +property :group, String, default: lazy { node['php']['fpm_group'] } +property :listen_user, String, default: lazy { node['php']['fpm_listen_user'] } +property :listen_group, String, default: lazy { node['php']['fpm_listen_group'] } +property :process_manager, String, default: 'dynamic' +property :max_children, Integer, default: 5 +property :start_servers, Integer, default: 2 +property :min_spare_servers, Integer, default: 1 +property :max_spare_servers, Integer, default: 3 +property :chdir, String, default: '/' +property :additional_config, Hash, default: {} + +action :install do + # Ensure the FPM pacakge is installed, and the service is registered + install_fpm_package + register_fpm_service + # I wanted to have this as a function in itself, but doing this seems to + # break testing suites? + template "#{node['php']['fpm_pooldir']}/#{new_resource.pool_name}.conf" do + source 'fpm-pool.conf.erb' + action :create + cookbook 'php' + variables( + fpm_pool_name: new_resource.pool_name, + fpm_pool_user: new_resource.user, + fpm_pool_group: new_resource.group, + fpm_pool_listen: new_resource.listen, + fpm_pool_listen_user: new_resource.listen_user, + fpm_pool_listen_group: new_resource.listen_group, + fpm_pool_manager: new_resource.process_manager, + fpm_pool_max_children: new_resource.max_children, + fpm_pool_start_servers: new_resource.start_servers, + fpm_pool_min_spare_servers: new_resource.min_spare_servers, + fpm_pool_max_spare_servers: new_resource.max_spare_servers, + fpm_pool_chdir: new_resource.chdir, + fpm_pool_additional_config: new_resource.additional_config + ) + notifies :restart, "service[#{node['php']['fpm_service']}]" + end +end + +action :uninstall do + # Ensure the FPM pacakge is installed, and the service is registered + register_fpm_service + # Delete the FPM pool. + file "#{node['php']['fpm_pooldir']}/#{new_resource.pool_name}.conf" do + action :delete + end +end + +action_class do + def install_fpm_package + # Install the FPM pacakge for this platform, if it's available + # Fail the run if it's an unsupported OS (FPM pacakge name not populated) + # also, this is skipped for source + return if node['php']['install_method'] == 'source' + + raise 'PHP-FPM package not found (you probably have an unsupported distro)' if node['php']['fpm_package'].nil? + + file node['php']['fpm_default_conf'] do + action :nothing + end + + package node['php']['fpm_package'] do + action :install + notifies :delete, "file[#{node['php']['fpm_default_conf']}]", :immediately + end + end + + def register_fpm_service + service node['php']['fpm_service'] do + action :enable + end + end +end diff --git a/cookbooks/php/resources/pear.rb b/cookbooks/php/resources/pear.rb new file mode 100644 index 0000000..c4aea46 --- /dev/null +++ b/cookbooks/php/resources/pear.rb @@ -0,0 +1,280 @@ +# +# Author:: Seth Chisamore +# Cookbook:: php +# Resource:: pear +# +# Copyright:: 2011-2018, Chef Software, Inc +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +property :package_name, String, name_property: true +property :version, [String, nil], default: nil +property :channel, String +property :options, String +property :directives, Hash, default: {} +property :zend_extensions, Array, default: [] +property :preferred_state, String, default: 'stable' +property :binary, String, default: 'pear' +property :priority, [String, nil], default: nil + +def current_installed_version(new_resource) + version_check_cmd = "#{new_resource.binary} -d" + version_check_cmd << " preferred_state=#{new_resource.preferred_state}" + version_check_cmd << " list#{expand_channel(new_resource.channel)}" + p = shell_out(version_check_cmd) + response = nil + response = grep_for_version(p.stdout, new_resource.package_name) if p.stdout =~ /\.?Installed packages/i + response +end + +def expand_channel(channel) + channel ? " -c #{channel}" : '' +end + +def grep_for_version(stdout, package) + version = nil + stdout.split(/\n/).grep(/^#{package}\s/i).each do |m| + # XML_RPC 1.5.4 stable + # mongo 1.1.4/(1.1.4 stable) 1.1.4 MongoDB database driver + # Horde_Url -n/a-/(1.0.0beta1 beta) Horde Url class + # Horde_Url 1.0.0beta1 (beta) 1.0.0beta1 Horde Url class + version = m.split(/\s+/)[1].strip + version = if version.split(%r{/\//})[0] =~ /.\./ + # 1.1.4/(1.1.4 stable) + version.split(%r{/\//})[0] + else + # -n/a-/(1.0.0beta1 beta) + version.split(%r{/(.*)\/\((.*)/}).last.split(/\s/)[0] + end + end + version +end + +load_current_value do |new_resource| + unless current_installed_version(new_resource).nil? + version(current_installed_version(new_resource)) + Chef::Log.debug("Current version is #{version}") if version + end +end + +action :install do + # If we specified a version, and it's not the current version, move to the specified version + install_version = new_resource.version unless new_resource.version.nil? || new_resource.version == current_resource.version + # Check if the version we want is already installed + versions_match = candidate_version == current_installed_version(new_resource) + + # If it's not installed at all or an upgrade, install it + if install_version || new_resource.version.nil? && !versions_match + converge_by("install package #{new_resource.package_name} #{install_version}") do + info_output = "Installing #{new_resource.package_name}" + info_output << " version #{install_version}" if install_version && !install_version.empty? + Chef::Log.info(info_output) + install_package(new_resource.package_name, install_version) + end + end +end + +# reinstall is just an install that always fires +action :reinstall do + install_version = new_resource.version unless new_resource.version.nil? + converge_by("reinstall package #{new_resource.package_name} #{install_version}") do + info_output = "Installing #{new_resource.package_name}" + info_output << " version #{install_version}" if install_version && !install_version.empty? + Chef::Log.info(info_output) + install_package(new_resource.package_name, install_version, force: true) + end +end + +action :upgrade do + if current_resource.version != candidate_version + orig_version = @current_resource.version || 'uninstalled' + description = "upgrade package #{new_resource.package_name} version from #{orig_version} to #{candidate_version}" + converge_by(description) do + upgrade_package(new_resource.package_name, candidate_version) + end + end +end + +action :remove do + if removing_package? + converge_by("remove package #{new_resource.package_name}") do + remove_package(@current_resource.package_name, new_resource.version) + end + end +end + +action :purge do + if removing_package? + converge_by("purge package #{new_resource.package_name}") do + remove_package(@current_resource.package_name, new_resource.version) + end + end +end + +action_class do + def expand_options(options) + options ? " #{options}" : '' + end + + def candidate_version + candidate_version_cmd = "#{new_resource.binary} -d " + candidate_version_cmd << "preferred_state=#{new_resource.preferred_state}" + candidate_version_cmd << " search#{expand_channel(new_resource.channel)}" + candidate_version_cmd << " #{new_resource.package_name}" + p = shell_out(candidate_version_cmd) + response = nil + response = grep_for_version(p.stdout, new_resource.package_name) if p.stdout =~ /\.?Matched packages/i + response + end + + def install_package(name, version, **opts) + command = "printf \"\r\" | #{new_resource.binary} -d" + command << " preferred_state=#{new_resource.preferred_state}" + command << " install -a#{expand_options(new_resource.options)}" + command << ' -f' if opts[:force] # allows us to force a reinstall + command << " #{prefix_channel(new_resource.channel)}#{name}" + command << "-#{version}" if version && !version.empty? + pear_shell_out(command) + manage_pecl_ini(name, :create, new_resource.directives, new_resource.zend_extensions, new_resource.priority) if pecl? + enable_package(name) + end + + def upgrade_package(name, version) + command = "printf \"\r\" | #{new_resource.binary} -d" + command << " preferred_state=#{new_resource.preferred_state}" + command << " upgrade -a#{expand_options(new_resource.options)}" + command << " #{prefix_channel(new_resource.channel)}#{name}" + command << "-#{version}" if version && !version.empty? + pear_shell_out(command) + manage_pecl_ini(name, :create, new_resource.directives, new_resource.zend_extensions, new_resource.priority) if pecl? + enable_package(name) + end + + def remove_package(name, version) + command = "#{new_resource.binary} uninstall" + command << " #{expand_options(new_resource.options)}" + command << " #{prefix_channel(new_resource.channel)}#{name}" + command << "-#{version}" if version && !version.empty? + pear_shell_out(command) + disable_package(name) + manage_pecl_ini(name, :delete, nil, nil, nil) if pecl? + end + + def enable_package(name) + execute "#{node['php']['enable_mod']} #{name}" do + only_if { platform?('ubuntu') && ::File.exist?(node['php']['enable_mod']) } + end + end + + def disable_package(name) + execute "#{node['php']['disable_mod']} #{name}" do + only_if { platform?('ubuntu') && ::File.exist?(node['php']['disable_mod']) } + end + end + + def pear_shell_out(command) + p = shell_out!(command) + # pear/pecl commands return a 0 on failures...we'll grep for it + p.invalid! if p.stdout.split('\n').last =~ /^ERROR:.+/i + p + end + + def prefix_channel(channel) + channel ? "#{channel}/" : '' + end + + def removing_package? + if new_resource.version.nil? + true # remove any version of a package + else + new_resource.version == @current_resource.version # we don't have the version we want to remove + end + end + + def extension_dir + @extension_dir ||= begin + # Consider using "pecl config-get ext_dir". It is more cross-platform. + # p = shell_out("php-config --extension-dir") + p = shell_out("#{node['php']['pecl']} config-get ext_dir") + p.stdout.strip + end + end + + def get_extension_files(name) + files = [] + + p = shell_out("#{new_resource.binary} list-files #{name}") + p.stdout.each_line.grep(/^src\s+.*\.so$/i).each do |line| + files << line.split[1] + end + + files + end + + def pecl? + @pecl ||= + begin + # search as a pear first since most 3rd party channels will report pears as pecls! + search_args = '' + search_args << " -d preferred_state=#{new_resource.preferred_state}" + search_args << " search#{expand_channel(new_resource.channel)} #{new_resource.package_name}" + + if grep_for_version(shell_out(new_resource.binary + search_args).stdout, new_resource.package_name) + false + elsif grep_for_version(shell_out(node['php']['pecl'] + search_args).stdout, new_resource.package_name) + true + else + raise "Package #{new_resource.package_name} not found in either PEAR or PECL." + end + end + end + + def manage_pecl_ini(name, action, directives, zend_extensions, priority) + ext_prefix = extension_dir + ext_prefix << ::File::SEPARATOR if ext_prefix[-1].chr != ::File::SEPARATOR + + files = get_extension_files(name) + + extensions = Hash[ + files.map do |filepath| + rel_file = filepath.clone + rel_file.slice! ext_prefix if rel_file.start_with? ext_prefix + zend = zend_extensions.include?(rel_file) + [(zend ? filepath : rel_file), zend] + end + ] + + directory node['php']['ext_conf_dir'] do + owner 'root' + group 'root' + mode '0755' + recursive true + end + + template "#{node['php']['ext_conf_dir']}/#{name}.ini" do + source 'extension.ini.erb' + cookbook 'php' + owner 'root' + group 'root' + mode '0644' + variables( + name: name, + extensions: extensions, + directives: directives, + priority: priority + ) + action action + end + end +end diff --git a/cookbooks/php/resources/pear_channel.rb b/cookbooks/php/resources/pear_channel.rb new file mode 100644 index 0000000..96a244e --- /dev/null +++ b/cookbooks/php/resources/pear_channel.rb @@ -0,0 +1,89 @@ +# +# Author:: Seth Chisamore +# Author:: Jennifer Davis +# Cookbook:: php +# Resource:: pear_channel +# +# Copyright:: 2011-2018, Chef Software, Inc +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +property :channel_xml, String +property :channel_name, String, name_property: true +property :binary, String, default: 'pear' +# TODO: add authenticated channel support! +# property :username, :kind_of => String +# property :password, :kind_of => String + +action :discover do + unless exists? + Chef::Log.info("Discovering pear channel #{new_resource}") + execute "#{new_resource.binary} channel-discover #{new_resource.channel_name}" do + action :run + end + end +end + +action :add do + unless exists? + Chef::Log.info("Adding pear channel #{new_resource} from #{new_resource.channel_xml}") + execute "#{new_resource.binary} channel-add #{new_resource.channel_xml}" do + action :run + end + end +end + +action :update do + if exists? && update_needed? + converge_by("update pear channel #{new_resource}") do + Chef::Log.info("Updating pear channel #{new_resource}") + shell_out!("#{new_resource.binary} channel-update #{new_resource.channel_name}") + end + end +end + +action :remove do + if exists? + Chef::Log.info("Deleting pear channel #{new_resource}") + execute "#{new_resource.binary} channel-delete #{new_resource.channel_name}" do + action :run + end + end +end + +action_class do + # determine if the channel needs to be updated by searching for a bogus package + # in that channel and looking for the text prompting the user to update the channel + # in the CLI output + # @return [Boolean] does the channel need to be updated + def update_needed? + begin + return true if shell_out("#{new_resource.binary} search -c #{new_resource.channel_name} NNNNNN").stdout =~ /channel-update/ + rescue Chef::Exceptions::CommandTimeout + # CentOS can hang on 'pear search' if a channel needs updating + Chef::Log.info("Timed out checking if channel-update needed...forcing update of pear channel #{new_resource.channel_name}") + return true + end + false + end + + # run pear channel-info to see if the channel has been setup or not + # @return [Boolean] does the channel exist locally + def exists? + shell_out!("#{new_resource.binary} channel-info #{new_resource.channel_name}") + true + rescue Mixlib::ShellOut::ShellCommandFailed + false + end +end diff --git a/cookbooks/php/templates/centos/php.ini.erb b/cookbooks/php/templates/centos/php.ini.erb new file mode 100644 index 0000000..a9e5d16 --- /dev/null +++ b/cookbooks/php/templates/centos/php.ini.erb @@ -0,0 +1,1225 @@ +[PHP] + +;;;;;;;;;;;;;;;;;;; +; About php.ini ; +;;;;;;;;;;;;;;;;;;; +; This file controls many aspects of PHP's behavior. In order for PHP to +; read it, it must be named 'php.ini'. PHP looks for it in the current +; working directory, in the path designated by the environment variable +; PHPRC, and in the path that was defined in compile time (in that order). +; Under Windows, the compile-time path is the Windows directory. The +; path in which the php.ini file is looked for can be overridden using +; the -c argument in command line mode. +; +; The syntax of the file is extremely simple. Whitespace and Lines +; beginning with a semicolon are silently ignored (as you probably guessed). +; Section headers (e.g. [Foo]) are also silently ignored, even though +; they might mean something in the future. +; +; Directives are specified using the following syntax: +; directive = value +; Directive names are *case sensitive* - foo=bar is different from FOO=bar. +; +; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one +; of the INI constants (On, Off, True, False, Yes, No and None) or an expression +; (e.g. E_ALL & ~E_NOTICE), or a quoted string ("foo"). +; +; Expressions in the INI file are limited to bitwise operators and parentheses: +; | bitwise OR +; & bitwise AND +; ~ bitwise NOT +; ! boolean NOT +; +; Boolean flags can be turned on using the values 1, On, True or Yes. +; They can be turned off using the values 0, Off, False or No. +; +; An empty string can be denoted by simply not writing anything after the equal +; sign, or by using the None keyword: +; +; foo = ; sets foo to an empty string +; foo = none ; sets foo to an empty string +; foo = "none" ; sets foo to the string 'none' +; +; If you use constants in your value, and these constants belong to a +; dynamically loaded extension (either a PHP extension or a Zend extension), +; you may only use these constants *after* the line that loads the extension. +; +; +;;;;;;;;;;;;;;;;;;; +; About this file ; +;;;;;;;;;;;;;;;;;;; +; This is the recommended, PHP 5-style version of the php.ini-dist file. It +; sets some non standard settings, that make PHP more efficient, more secure, +; and encourage cleaner coding. +; +; The price is that with these settings, PHP may be incompatible with some +; applications, and sometimes, more difficult to develop with. Using this +; file is warmly recommended for production sites. As all of the changes from +; the standard settings are thoroughly documented, you can go over each one, +; and decide whether you want to use it or not. +; +; For general information about the php.ini file, please consult the php.ini-dist +; file, included in your PHP distribution. +; +; This file is different from the php.ini-dist file in the fact that it features +; different values for several directives, in order to improve performance, while +; possibly breaking compatibility with the standard out-of-the-box behavior of +; PHP. Please make sure you read what's different, and modify your scripts +; accordingly, if you decide to use this file instead. +; +; - register_globals = Off [Security, Performance] +; Global variables are no longer registered for input data (POST, GET, cookies, +; environment and other server variables). Instead of using $foo, you must use +; you can use $_REQUEST["foo"] (includes any variable that arrives through the +; request, namely, POST, GET and cookie variables), or use one of the specific +; $_GET["foo"], $_POST["foo"], $_COOKIE["foo"] or $_FILES["foo"], depending +; on where the input originates. Also, you can look at the +; import_request_variables() function. +; Note that register_globals is going to be depracated (i.e., turned off by +; default) in the next version of PHP, because it often leads to security bugs. +; Read http://php.net/manual/en/security.registerglobals.php for further +; information. +; - register_long_arrays = Off [Performance] +; Disables registration of the older (and deprecated) long predefined array +; variables ($HTTP_*_VARS). Instead, use the superglobals that were +; introduced in PHP 4.1.0 +; - display_errors = Off [Security] +; With this directive set to off, errors that occur during the execution of +; scripts will no longer be displayed as a part of the script output, and thus, +; will no longer be exposed to remote users. With some errors, the error message +; content may expose information about your script, web server, or database +; server that may be exploitable for hacking. Production sites should have this +; directive set to off. +; - log_errors = On [Security] +; This directive complements the above one. Any errors that occur during the +; execution of your script will be logged (typically, to your server's error log, +; but can be configured in several ways). Along with setting display_errors to off, +; this setup gives you the ability to fully understand what may have gone wrong, +; without exposing any sensitive information to remote users. +; - output_buffering = 4096 [Performance] +; Set a 4KB output buffer. Enabling output buffering typically results in less +; writes, and sometimes less packets sent on the wire, which can often lead to +; better performance. The gain this directive actually yields greatly depends +; on which Web server you're working with, and what kind of scripts you're using. +; - register_argc_argv = Off [Performance] +; Disables registration of the somewhat redundant $argv and $argc global +; variables. +; - magic_quotes_gpc = Off [Performance] +; Input data is no longer escaped with slashes so that it can be sent into +; SQL databases without further manipulation. Instead, you should use the +; function addslashes() on each input element you wish to send to a database. +; - variables_order = "GPCS" [Performance] +; The environment variables are not hashed into the $_ENV. To access +; environment variables, you can use getenv() instead. +; - error_reporting = E_ALL [Code Cleanliness, Security(?)] +; By default, PHP surpresses errors of type E_NOTICE. These error messages +; are emitted for non-critical errors, but that could be a symptom of a bigger +; problem. Most notably, this will cause error messages about the use +; of uninitialized variables to be displayed. +; - allow_call_time_pass_reference = Off [Code cleanliness] +; It's not possible to decide to force a variable to be passed by reference +; when calling a function. The PHP 4 style to do this is by making the +; function require the relevant argument by reference. + + +;;;;;;;;;;;;;;;;;;;; +; Language Options ; +;;;;;;;;;;;;;;;;;;;; + +; Enable the PHP scripting language engine under Apache. +engine = On + +; Enable compatibility mode with Zend Engine 1 (PHP 4.x) +zend.ze1_compatibility_mode = Off + +; Allow the tags are recognized. +; NOTE: Using short tags should be avoided when developing applications or +; libraries that are meant for redistribution, or deployment on PHP +; servers which are not under your control, because short tags may not +; be supported on the target server. For portable, redistributable code, +; be sure not to use short tags. +short_open_tag = On + +; Allow ASP-style <% %> tags. +asp_tags = Off + +; The number of significant digits displayed in floating point numbers. +precision = 14 + +; Enforce year 2000 compliance (will cause problems with non-compliant browsers) +y2k_compliance = On + +; Output buffering allows you to send header lines (including cookies) even +; after you send body content, at the price of slowing PHP's output layer a +; bit. You can enable output buffering during runtime by calling the output +; buffering functions. You can also enable output buffering for all files by +; setting this directive to On. If you wish to limit the size of the buffer +; to a certain size - you can use a maximum number of bytes instead of 'On', as +; a value for this directive (e.g., output_buffering=4096). +output_buffering = 4096 + +; You can redirect all of the output of your scripts to a function. For +; example, if you set output_handler to "mb_output_handler", character +; encoding will be transparently converted to the specified encoding. +; Setting any output handler automatically turns on output buffering. +; Note: People who wrote portable scripts should not depend on this ini +; directive. Instead, explicitly set the output handler using ob_start(). +; Using this ini directive may cause problems unless you know what script +; is doing. +; Note: You cannot use both "mb_output_handler" with "ob_iconv_handler" +; and you cannot use both "ob_gzhandler" and "zlib.output_compression". +; Note: output_handler must be empty if this is set 'On' !!!! +; Instead you must use zlib.output_handler. +;output_handler = + +; Transparent output compression using the zlib library +; Valid values for this option are 'off', 'on', or a specific buffer size +; to be used for compression (default is 4KB) +; Note: Resulting chunk size may vary due to nature of compression. PHP +; outputs chunks that are few hundreds bytes each as a result of +; compression. If you prefer a larger chunk size for better +; performance, enable output_buffering in addition. +; Note: You need to use zlib.output_handler instead of the standard +; output_handler, or otherwise the output will be corrupted. +zlib.output_compression = Off + +; You cannot specify additional output handlers if zlib.output_compression +; is activated here. This setting does the same as output_handler but in +; a different order. +;zlib.output_handler = + +; Implicit flush tells PHP to tell the output layer to flush itself +; automatically after every output block. This is equivalent to calling the +; PHP function flush() after each and every call to print() or echo() and each +; and every HTML block. Turning this option on has serious performance +; implications and is generally recommended for debugging purposes only. +implicit_flush = Off + +; The unserialize callback function will be called (with the undefined class' +; name as parameter), if the unserializer finds an undefined class +; which should be instantiated. +; A warning appears if the specified function is not defined, or if the +; function doesn't include/implement the missing class. +; So only set this entry, if you really want to implement such a +; callback-function. +unserialize_callback_func= + +; When floats & doubles are serialized store serialize_precision significant +; digits after the floating point. The default value ensures that when floats +; are decoded with unserialize, the data will remain the same. +serialize_precision = 100 + +; Whether to enable the ability to force arguments to be passed by reference +; at function call time. This method is deprecated and is likely to be +; unsupported in future versions of PHP/Zend. The encouraged method of +; specifying which arguments should be passed by reference is in the function +; declaration. You're encouraged to try and turn this option Off and make +; sure your scripts work properly with it in order to ensure they will work +; with future versions of the language (you will receive a warning each time +; you use this feature, and the argument will be passed by value instead of by +; reference). +allow_call_time_pass_reference = Off + +; +; Safe Mode +; +safe_mode = Off + +; By default, Safe Mode does a UID compare check when +; opening files. If you want to relax this to a GID compare, +; then turn on safe_mode_gid. +safe_mode_gid = Off + +; When safe_mode is on, UID/GID checks are bypassed when +; including files from this directory and its subdirectories. +; (directory must also be in include_path or full path must +; be used when including) +safe_mode_include_dir = + +; When safe_mode is on, only executables located in the safe_mode_exec_dir +; will be allowed to be executed via the exec family of functions. +safe_mode_exec_dir = + +; Setting certain environment variables may be a potential security breach. +; This directive contains a comma-delimited list of prefixes. In Safe Mode, +; the user may only alter environment variables whose names begin with the +; prefixes supplied here. By default, users will only be able to set +; environment variables that begin with PHP_ (e.g. PHP_FOO=BAR). +; +; Note: If this directive is empty, PHP will let the user modify ANY +; environment variable! +safe_mode_allowed_env_vars = PHP_ + +; This directive contains a comma-delimited list of environment variables that +; the end user won't be able to change using putenv(). These variables will be +; protected even if safe_mode_allowed_env_vars is set to allow to change them. +safe_mode_protected_env_vars = LD_LIBRARY_PATH + +; open_basedir, if set, limits all file operations to the defined directory +; and below. This directive makes most sense if used in a per-directory +; or per-virtualhost web server configuration file. This directive is +; *NOT* affected by whether Safe Mode is turned On or Off. +;open_basedir = + +; This directive allows you to disable certain functions for security reasons. +; It receives a comma-delimited list of function names. This directive is +; *NOT* affected by whether Safe Mode is turned On or Off. +disable_functions = + +; This directive allows you to disable certain classes for security reasons. +; It receives a comma-delimited list of class names. This directive is +; *NOT* affected by whether Safe Mode is turned On or Off. +disable_classes = + +; Colors for Syntax Highlighting mode. Anything that's acceptable in +; would work. +;highlight.string = #DD0000 +;highlight.comment = #FF9900 +;highlight.keyword = #007700 +;highlight.bg = #FFFFFF +;highlight.default = #0000BB +;highlight.html = #000000 + +; If enabled, the request will be allowed to complete even if the user aborts +; the request. Consider enabling it if executing long request, which may end up +; being interrupted by the user or a browser timing out. +; ignore_user_abort = On + +; Determines the size of the realpath cache to be used by PHP. This value should +; be increased on systems where PHP opens many files to reflect the quantity of +; the file operations performed. +; realpath_cache_size=16k + +; Duration of time, in seconds for which to cache realpath information for a given +; file or directory. For systems with rarely changing files, consider increasing this +; value. +; realpath_cache_ttl=120 + +; +; Misc +; +; Decides whether PHP may expose the fact that it is installed on the server +; (e.g. by adding its signature to the Web server header). It is no security +; threat in any way, but it makes it possible to determine whether you use PHP +; on your server or not. +expose_php = On + + +;;;;;;;;;;;;;;;;;;; +; Resource Limits ; +;;;;;;;;;;;;;;;;;;; + +max_execution_time = 30 ; Maximum execution time of each script, in seconds +max_input_time = 60 ; Maximum amount of time each script may spend parsing request data +memory_limit = 128M ; Maximum amount of memory a script may consume + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Error handling and logging ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; error_reporting is a bit-field. Or each number up to get desired error +; reporting level +; E_ALL - All errors and warnings (doesn't include E_STRICT) +; E_ERROR - fatal run-time errors +; E_WARNING - run-time warnings (non-fatal errors) +; E_PARSE - compile-time parse errors +; E_NOTICE - run-time notices (these are warnings which often result +; from a bug in your code, but it's possible that it was +; intentional (e.g., using an uninitialized variable and +; relying on the fact it's automatically initialized to an +; empty string) +; E_STRICT - run-time notices, enable to have PHP suggest changes +; to your code which will ensure the best interoperability +; and forward compatibility of your code +; E_CORE_ERROR - fatal errors that occur during PHP's initial startup +; E_CORE_WARNING - warnings (non-fatal errors) that occur during PHP's +; initial startup +; E_COMPILE_ERROR - fatal compile-time errors +; E_COMPILE_WARNING - compile-time warnings (non-fatal errors) +; E_USER_ERROR - user-generated error message +; E_USER_WARNING - user-generated warning message +; E_USER_NOTICE - user-generated notice message +; +; Examples: +; +; - Show all errors, except for notices and coding standards warnings +; +;error_reporting = E_ALL & ~E_NOTICE +; +; - Show all errors, except for notices +; +;error_reporting = E_ALL & ~E_NOTICE | E_STRICT +; +; - Show only errors +; +;error_reporting = E_COMPILE_ERROR|E_ERROR|E_CORE_ERROR +; +; - Show all errors, except coding standards warnings +; +error_reporting = E_ALL + +; Print out errors (as a part of the output). For production web sites, +; you're strongly encouraged to turn this feature off, and use error logging +; instead (see below). Keeping display_errors enabled on a production web site +; may reveal security information to end users, such as file paths on your Web +; server, your database schema or other information. +display_errors = Off + +; Even when display_errors is on, errors that occur during PHP's startup +; sequence are not displayed. It's strongly recommended to keep +; display_startup_errors off, except for when debugging. +display_startup_errors = Off + +; Log errors into a log file (server-specific log, stderr, or error_log (below)) +; As stated above, you're strongly advised to use error logging in place of +; error displaying on production web sites. +log_errors = On + +; Set maximum length of log_errors. In error_log information about the source is +; added. The default is 1024 and 0 allows to not apply any maximum length at all. +log_errors_max_len = 1024 + +; Do not log repeated messages. Repeated errors must occur in same file on same +; line until ignore_repeated_source is set true. +ignore_repeated_errors = Off + +; Ignore source of message when ignoring repeated messages. When this setting +; is On you will not log errors with repeated messages from different files or +; sourcelines. +ignore_repeated_source = Off + +; If this parameter is set to Off, then memory leaks will not be shown (on +; stdout or in the log). This has only effect in a debug compile, and if +; error reporting includes E_WARNING in the allowed list +report_memleaks = On + +; Store the last error/warning message in $php_errormsg (boolean). +track_errors = Off + +; Disable the inclusion of HTML tags in error messages. +; Note: Never use this feature for production boxes. +;html_errors = Off + +; If html_errors is set On PHP produces clickable error messages that direct +; to a page describing the error or function causing the error in detail. +; You can download a copy of the PHP manual from http://www.php.net/docs.php +; and change docref_root to the base URL of your local copy including the +; leading '/'. You must also specify the file extension being used including +; the dot. +; Note: Never use this feature for production boxes. +;docref_root = "/phpmanual/" +;docref_ext = .html + +; String to output before an error message. +;error_prepend_string = "" + +; String to output after an error message. +;error_append_string = "" + +; Log errors to specified file. +;error_log = filename + +; Log errors to syslog (Event Log on NT, not valid in Windows 95). +;error_log = syslog + + +;;;;;;;;;;;;;;;;; +; Data Handling ; +;;;;;;;;;;;;;;;;; +; +; Note - track_vars is ALWAYS enabled as of PHP 4.0.3 + +; The separator used in PHP generated URLs to separate arguments. +; Default is "&". +;arg_separator.output = "&" + +; List of separator(s) used by PHP to parse input URLs into variables. +; Default is "&". +; NOTE: Every character in this directive is considered as separator! +;arg_separator.input = ";&" + +; This directive describes the order in which PHP registers GET, POST, Cookie, +; Environment and Built-in variables (G, P, C, E & S respectively, often +; referred to as EGPCS or GPC). Registration is done from left to right, newer +; values override older values. +variables_order = "EGPCS" + +; Whether or not to register the EGPCS variables as global variables. You may +; want to turn this off if you don't want to clutter your scripts' global scope +; with user data. This makes most sense when coupled with track_vars - in which +; case you can access all of the GPC variables through the $HTTP_*_VARS[], +; variables. +; +; You should do your best to write your scripts so that they do not require +; register_globals to be on; Using form variables as globals can easily lead +; to possible security problems, if the code is not very well thought of. +register_globals = Off + +; Whether or not to register the old-style input arrays, HTTP_GET_VARS +; and friends. If you're not using them, it's recommended to turn them off, +; for performance reasons. +register_long_arrays = Off + +; This directive tells PHP whether to declare the argv&argc variables (that +; would contain the GET information). If you don't use these variables, you +; should turn it off for increased performance. +register_argc_argv = Off + +; When enabled, the SERVER and ENV variables are created when they're first +; used (Just In Time) instead of when the script starts. If these variables +; are not used within a script, having this directive on will result in a +; performance gain. The PHP directives register_globals, register_long_arrays, +; and register_argc_argv must be disabled for this directive to have any affect. +auto_globals_jit = On + +; Maximum size of POST data that PHP will accept. +post_max_size = 8M + +; Magic quotes +; + +; Magic quotes for incoming GET/POST/Cookie data. +magic_quotes_gpc = Off + +; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc. +magic_quotes_runtime = Off + +; Use Sybase-style magic quotes (escape ' with '' instead of \'). +magic_quotes_sybase = Off + +; Automatically add files before or after any PHP document. +auto_prepend_file = +auto_append_file = + +; As of 4.0b4, PHP always outputs a character encoding by default in +; the Content-type: header. To disable sending of the charset, simply +; set it to be empty. +; +; PHP's built-in default is text/html +default_mimetype = "text/html" +;default_charset = "iso-8859-1" + +; Always populate the $HTTP_RAW_POST_DATA variable. +;always_populate_raw_post_data = On + + +;;;;;;;;;;;;;;;;;;;;;;;;; +; Paths and Directories ; +;;;;;;;;;;;;;;;;;;;;;;;;; + +; UNIX: "/path1:/path2" +;include_path = ".:/php/includes" +; +; Windows: "\path1;\path2" +;include_path = ".;c:\php\includes" + +; The root of the PHP pages, used only if nonempty. +; if PHP was not compiled with FORCE_REDIRECT, you SHOULD set doc_root +; if you are running php as a CGI under any web server (other than IIS) +; see documentation for security issues. The alternate is to use the +; cgi.force_redirect configuration below +doc_root = + +; The directory under which PHP opens the script using /~username used only +; if nonempty. +user_dir = + +; Directory in which the loadable extensions (modules) reside. +extension_dir = "<%= node['php']['ext_dir'] %>" + +; Whether or not to enable the dl() function. The dl() function does NOT work +; properly in multithreaded servers, such as IIS or Zeus, and is automatically +; disabled on them. +enable_dl = On + +; cgi.force_redirect is necessary to provide security running PHP as a CGI under +; most web servers. Left undefined, PHP turns this on by default. You can +; turn it off here AT YOUR OWN RISK +; **You CAN safely turn this off for IIS, in fact, you MUST.** +; cgi.force_redirect = 1 + +; if cgi.nph is enabled it will force cgi to always sent Status: 200 with +; every request. +; cgi.nph = 1 + +; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape +; (iPlanet) web servers, you MAY need to set an environment variable name that PHP +; will look for to know it is OK to continue execution. Setting this variable MAY +; cause security issues, KNOW WHAT YOU ARE DOING FIRST. +; cgi.redirect_status_env = ; + +; FastCGI under IIS (on WINNT based OS) supports the ability to impersonate +; security tokens of the calling client. This allows IIS to define the +; security context that the request runs under. mod_fastcgi under Apache +; does not currently support this feature (03/17/2002) +; Set to 1 if running under IIS. Default is zero. +; fastcgi.impersonate = 1; + +; Disable logging through FastCGI connection +; fastcgi.log = 0 + +; cgi.rfc2616_headers configuration option tells PHP what type of headers to +; use when sending HTTP response code. If it's set 0 PHP sends Status: header that +; is supported by Apache. When this option is set to 1 PHP will send +; RFC2616 compliant header. +; Default is zero. +;cgi.rfc2616_headers = 0 + + +;;;;;;;;;;;;;;;; +; File Uploads ; +;;;;;;;;;;;;;;;; + +; Whether to allow HTTP file uploads. +file_uploads = On + +; Temporary directory for HTTP uploaded files (will use system default if not +; specified). +;upload_tmp_dir = + +; Maximum allowed size for uploaded files. +upload_max_filesize = 2M + + +;;;;;;;;;;;;;;;;;; +; Fopen wrappers ; +;;;;;;;;;;;;;;;;;; + +; Whether to allow the treatment of URLs (like http:// or ftp://) as files. +allow_url_fopen = On + +; Define the anonymous ftp password (your email address) +;from="john@doe.com" + +; Define the User-Agent string +; user_agent="PHP" + +; Default timeout for socket based streams (seconds) +default_socket_timeout = 60 + +; If your scripts have to deal with files from Macintosh systems, +; or you are running on a Mac and need to deal with files from +; unix or win32 systems, setting this flag will cause PHP to +; automatically detect the EOL character in those files so that +; fgets() and file() will work regardless of the source of the file. +; auto_detect_line_endings = Off + + +;;;;;;;;;;;;;;;;;;;;;; +; Dynamic Extensions ; +;;;;;;;;;;;;;;;;;;;;;; +; +; If you wish to have an extension loaded automatically, use the following +; syntax: +; +; extension=modulename.extension +; +; For example: +; +; extension=msql.so +; +; Note that it should be the name of the module only; no directory information +; needs to go here. Specify the location of the extension with the +; extension_dir directive above. + + +;;;; +; Note: packaged extension modules are now loaded via the .ini files +; found in the directory /etc/php.d; these are loaded by default. +;;;; + + +;;;;;;;;;;;;;;;;;;; +; Module Settings ; +;;;;;;;;;;;;;;;;;;; + +[Date] +; Defines the default timezone used by the date functions +;date.timezone = + +[Syslog] +; Whether or not to define the various syslog variables (e.g. $LOG_PID, +; $LOG_CRON, etc.). Turning it off is a good idea performance-wise. In +; runtime, you can define these variables by calling define_syslog_variables(). +define_syslog_variables = Off + +[mail function] +; For Win32 only. +SMTP = localhost +smtp_port = 25 + +; For Win32 only. +;sendmail_from = me@example.com + +; For Unix only. You may supply arguments as well (default: "sendmail -t -i"). +sendmail_path = /usr/sbin/sendmail -t -i + +; Force the addition of the specified parameters to be passed as extra parameters +; to the sendmail binary. These parameters will always replace the value of +; the 5th parameter to mail(), even in safe mode. +;mail.force_extra_parameters = + +[SQL] +sql.safe_mode = Off + +[ODBC] +;odbc.default_db = Not yet implemented +;odbc.default_user = Not yet implemented +;odbc.default_pw = Not yet implemented + +; Allow or prevent persistent links. +odbc.allow_persistent = On + +; Check that a connection is still valid before reuse. +odbc.check_persistent = On + +; Maximum number of persistent links. -1 means no limit. +odbc.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +odbc.max_links = -1 + +; Handling of LONG fields. Returns number of bytes to variables. 0 means +; passthru. +odbc.defaultlrl = 4096 + +; Handling of binary data. 0 means passthru, 1 return as is, 2 convert to char. +; See the documentation on odbc_binmode and odbc_longreadlen for an explanation +; of uodbc.defaultlrl and uodbc.defaultbinmode +odbc.defaultbinmode = 1 + +[MySQL] +; Allow or prevent persistent links. +mysql.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +mysql.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +mysql.max_links = -1 + +; Default port number for mysql_connect(). If unset, mysql_connect() will use +; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the +; compile-time value defined MYSQL_PORT (in that order). Win32 will only look +; at MYSQL_PORT. +mysql.default_port = + +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +mysql.default_socket = + +; Default host for mysql_connect() (doesn't apply in safe mode). +mysql.default_host = + +; Default user for mysql_connect() (doesn't apply in safe mode). +mysql.default_user = + +; Default password for mysql_connect() (doesn't apply in safe mode). +; Note that this is generally a *bad* idea to store passwords in this file. +; *Any* user with PHP access can run 'echo get_cfg_var("mysql.default_password") +; and reveal this password! And of course, any users with read access to this +; file will be able to reveal the password as well. +mysql.default_password = + +; Maximum time (in secondes) for connect timeout. -1 means no limit +mysql.connect_timeout = 60 + +; Trace mode. When trace_mode is active (=On), warnings for table/index scans and +; SQL-Errors will be displayed. +mysql.trace_mode = Off + +[MySQLi] + +; Maximum number of links. -1 means no limit. +mysqli.max_links = -1 + +; Default port number for mysqli_connect(). If unset, mysqli_connect() will use +; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the +; compile-time value defined MYSQL_PORT (in that order). Win32 will only look +; at MYSQL_PORT. +mysqli.default_port = 3306 + +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +mysqli.default_socket = + +; Default host for mysql_connect() (doesn't apply in safe mode). +mysqli.default_host = + +; Default user for mysql_connect() (doesn't apply in safe mode). +mysqli.default_user = + +; Default password for mysqli_connect() (doesn't apply in safe mode). +; Note that this is generally a *bad* idea to store passwords in this file. +; *Any* user with PHP access can run 'echo get_cfg_var("mysqli.default_pw") +; and reveal this password! And of course, any users with read access to this +; file will be able to reveal the password as well. +mysqli.default_pw = + +; Allow or prevent reconnect +mysqli.reconnect = Off + +[mSQL] +; Allow or prevent persistent links. +msql.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +msql.max_persistent = -1 + +; Maximum number of links (persistent+non persistent). -1 means no limit. +msql.max_links = -1 + +[PostgresSQL] +; Allow or prevent persistent links. +pgsql.allow_persistent = On + +; Detect broken persistent links always with pg_pconnect(). +; Auto reset feature requires a little overheads. +pgsql.auto_reset_persistent = Off + +; Maximum number of persistent links. -1 means no limit. +pgsql.max_persistent = -1 + +; Maximum number of links (persistent+non persistent). -1 means no limit. +pgsql.max_links = -1 + +; Ignore PostgreSQL backends Notice message or not. +; Notice message logging require a little overheads. +pgsql.ignore_notice = 0 + +; Log PostgreSQL backends Noitce message or not. +; Unless pgsql.ignore_notice=0, module cannot log notice message. +pgsql.log_notice = 0 + +[Sybase] +; Allow or prevent persistent links. +sybase.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +sybase.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +sybase.max_links = -1 + +;sybase.interface_file = "/usr/sybase/interfaces" + +; Minimum error severity to display. +sybase.min_error_severity = 10 + +; Minimum message severity to display. +sybase.min_message_severity = 10 + +; Compatability mode with old versions of PHP 3.0. +; If on, this will cause PHP to automatically assign types to results according +; to their Sybase type, instead of treating them all as strings. This +; compatability mode will probably not stay around forever, so try applying +; whatever necessary changes to your code, and turn it off. +sybase.compatability_mode = Off + +[Sybase-CT] +; Allow or prevent persistent links. +sybct.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +sybct.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +sybct.max_links = -1 + +; Minimum server message severity to display. +sybct.min_server_severity = 10 + +; Minimum client message severity to display. +sybct.min_client_severity = 10 + +[bcmath] +; Number of decimal digits for all bcmath functions. +bcmath.scale = 0 + +[browscap] +;browscap = extra/browscap.ini + +[Informix] +; Default host for ifx_connect() (doesn't apply in safe mode). +ifx.default_host = + +; Default user for ifx_connect() (doesn't apply in safe mode). +ifx.default_user = + +; Default password for ifx_connect() (doesn't apply in safe mode). +ifx.default_password = + +; Allow or prevent persistent links. +ifx.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +ifx.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +ifx.max_links = -1 + +; If on, select statements return the contents of a text blob instead of its id. +ifx.textasvarchar = 0 + +; If on, select statements return the contents of a byte blob instead of its id. +ifx.byteasvarchar = 0 + +; Trailing blanks are stripped from fixed-length char columns. May help the +; life of Informix SE users. +ifx.charasvarchar = 0 + +; If on, the contents of text and byte blobs are dumped to a file instead of +; keeping them in memory. +ifx.blobinfile = 0 + +; NULL's are returned as empty strings, unless this is set to 1. In that case, +; NULL's are returned as string 'NULL'. +ifx.nullformat = 0 + +[Session] +; Handler used to store/retrieve data. +session.save_handler = files + +; Argument passed to save_handler. In the case of files, this is the path +; where data files are stored. Note: Windows users have to change this +; variable in order to use PHP's session functions. +; +; As of PHP 4.0.1, you can define the path as: +; +; session.save_path = "N;/path" +; +; where N is an integer. Instead of storing all the session files in +; /path, what this will do is use subdirectories N-levels deep, and +; store the session data in those directories. This is useful if you +; or your OS have problems with lots of files in one directory, and is +; a more efficient layout for servers that handle lots of sessions. +; +; NOTE 1: PHP will not create this directory structure automatically. +; You can use the script in the ext/session dir for that purpose. +; NOTE 2: See the section on garbage collection below if you choose to +; use subdirectories for session storage +; +; The file storage module creates files using mode 600 by default. +; You can change that by using +; +; session.save_path = "N;MODE;/path" +; +; where MODE is the octal representation of the mode. Note that this +; does not overwrite the process's umask. +session.save_path = "/var/lib/php/session" + +; Whether to use cookies. +session.use_cookies = 1 + +; This option enables administrators to make their users invulnerable to +; attacks which involve passing session ids in URLs; defaults to 0. +; session.use_only_cookies = 1 + +; Name of the session (used as cookie name). +session.name = PHPSESSID + +; Initialize session on request startup. +session.auto_start = 0 + +; Lifetime in seconds of cookie or, if 0, until browser is restarted. +session.cookie_lifetime = 0 + +; The path for which the cookie is valid. +session.cookie_path = / + +; The domain for which the cookie is valid. +session.cookie_domain = + +; Handler used to serialize data. php is the standard serializer of PHP. +session.serialize_handler = php + +; Define the probability that the 'garbage collection' process is started +; on every session initialization. +; The probability is calculated by using gc_probability/gc_divisor, +; e.g. 1/100 means there is a 1% chance that the GC process starts +; on each request. + +session.gc_probability = 1 +session.gc_divisor = 1000 + +; After this number of seconds, stored data will be seen as 'garbage' and +; cleaned up by the garbage collection process. +session.gc_maxlifetime = 1440 + +; NOTE: If you are using the subdirectory option for storing session files +; (see session.save_path above), then garbage collection does *not* +; happen automatically. You will need to do your own garbage +; collection through a shell script, cron entry, or some other method. +; For example, the following script would is the equivalent of +; setting session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes): +; cd /path/to/sessions; find -cmin +24 | xargs rm + +; PHP 4.2 and less have an undocumented feature/bug that allows you to +; to initialize a session variable in the global scope, albeit register_globals +; is disabled. PHP 4.3 and later will warn you, if this feature is used. +; You can disable the feature and the warning separately. At this time, +; the warning is only displayed, if bug_compat_42 is enabled. + +session.bug_compat_42 = 0 +session.bug_compat_warn = 1 + +; Check HTTP Referer to invalidate externally stored URLs containing ids. +; HTTP_REFERER has to contain this substring for the session to be +; considered as valid. +session.referer_check = + +; How many bytes to read from the file. +session.entropy_length = 0 + +; Specified here to create the session id. +session.entropy_file = + +;session.entropy_length = 16 + +;session.entropy_file = /dev/urandom + +; Set to {nocache,private,public,} to determine HTTP caching aspects +; or leave this empty to avoid sending anti-caching headers. +session.cache_limiter = nocache + +; Document expires after n minutes. +session.cache_expire = 180 + +; trans sid support is disabled by default. +; Use of trans sid may risk your users security. +; Use this option with caution. +; - User may send URL contains active session ID +; to other person via. email/irc/etc. +; - URL that contains active session ID may be stored +; in publically accessible computer. +; - User may access your site with the same session ID +; always using URL stored in browser's history or bookmarks. +session.use_trans_sid = 0 + +; Select a hash function +; 0: MD5 (128 bits) +; 1: SHA-1 (160 bits) +session.hash_function = 0 + +; Define how many bits are stored in each character when converting +; the binary hash data to something readable. +; +; 4 bits: 0-9, a-f +; 5 bits: 0-9, a-v +; 6 bits: 0-9, a-z, A-Z, "-", "," +session.hash_bits_per_character = 5 + +; The URL rewriter will look for URLs in a defined set of HTML tags. +; form/fieldset are special; if you include them here, the rewriter will +; add a hidden field with the info which is otherwise appended +; to URLs. If you want XHTML conformity, remove the form entry. +; Note that all valid entries require a "=", even if no value follows. +url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry" + +[MSSQL] +; Allow or prevent persistent links. +mssql.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +mssql.max_persistent = -1 + +; Maximum number of links (persistent+non persistent). -1 means no limit. +mssql.max_links = -1 + +; Minimum error severity to display. +mssql.min_error_severity = 10 + +; Minimum message severity to display. +mssql.min_message_severity = 10 + +; Compatability mode with old versions of PHP 3.0. +mssql.compatability_mode = Off + +; Connect timeout +;mssql.connect_timeout = 5 + +; Query timeout +;mssql.timeout = 60 + +; Valid range 0 - 2147483647. Default = 4096. +;mssql.textlimit = 4096 + +; Valid range 0 - 2147483647. Default = 4096. +;mssql.textsize = 4096 + +; Limits the number of records in each batch. 0 = all records in one batch. +;mssql.batchsize = 0 + +; Specify how datetime and datetim4 columns are returned +; On => Returns data converted to SQL server settings +; Off => Returns values as YYYY-MM-DD hh:mm:ss +;mssql.datetimeconvert = On + +; Use NT authentication when connecting to the server +mssql.secure_connection = Off + +; Specify max number of processes. -1 = library default +; msdlib defaults to 25 +; FreeTDS defaults to 4096 +;mssql.max_procs = -1 + +; Specify client character set. +; If empty or not set the client charset from freetds.comf is used +; This is only used when compiled with FreeTDS +;mssql.charset = "ISO-8859-1" + +[Assertion] +; Assert(expr); active by default. +;assert.active = On + +; Issue a PHP warning for each failed assertion. +;assert.warning = On + +; Don't bail out by default. +;assert.bail = Off + +; User-function to be called if an assertion fails. +;assert.callback = 0 + +; Eval the expression with current error_reporting(). Set to true if you want +; error_reporting(0) around the eval(). +;assert.quiet_eval = 0 + +[Verisign Payflow Pro] +; Default Payflow Pro server. +pfpro.defaulthost = "test-payflow.verisign.com" + +; Default port to connect to. +pfpro.defaultport = 443 + +; Default timeout in seconds. +pfpro.defaulttimeout = 30 + +; Default proxy IP address (if required). +;pfpro.proxyaddress = + +; Default proxy port. +;pfpro.proxyport = + +; Default proxy logon. +;pfpro.proxylogon = + +; Default proxy password. +;pfpro.proxypassword = + +[COM] +; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs +;com.typelib_file = +; allow Distributed-COM calls +;com.allow_dcom = true +; autoregister constants of a components typlib on com_load() +;com.autoregister_typelib = true +; register constants casesensitive +;com.autoregister_casesensitive = false +; show warnings on duplicate constat registrations +;com.autoregister_verbose = true + +[mbstring] +; language for internal character representation. +;mbstring.language = Japanese + +; internal/script encoding. +; Some encoding cannot work as internal encoding. +; (e.g. SJIS, BIG5, ISO-2022-*) +;mbstring.internal_encoding = EUC-JP + +; http input encoding. +;mbstring.http_input = auto + +; http output encoding. mb_output_handler must be +; registered as output buffer to function +;mbstring.http_output = SJIS + +; enable automatic encoding translation according to +; mbstring.internal_encoding setting. Input chars are +; converted to internal encoding by setting this to On. +; Note: Do _not_ use automatic encoding translation for +; portable libs/applications. +;mbstring.encoding_translation = Off + +; automatic encoding detection order. +; auto means +;mbstring.detect_order = auto + +; substitute_character used when character cannot be converted +; one from another +;mbstring.substitute_character = none; + +; overload(replace) single byte functions by mbstring functions. +; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(), +; etc. Possible values are 0,1,2,4 or combination of them. +; For example, 7 for overload everything. +; 0: No overload +; 1: Overload mail() function +; 2: Overload str*() functions +; 4: Overload ereg*() functions +;mbstring.func_overload = 0 + +; enable strict encoding detection. +;mbstring.strict_encoding = Off + +[FrontBase] +;fbsql.allow_persistent = On +;fbsql.autocommit = On +;fbsql.default_database = +;fbsql.default_database_password = +;fbsql.default_host = +;fbsql.default_password = +;fbsql.default_user = "_SYSTEM" +;fbsql.generate_warnings = Off +;fbsql.max_connections = 128 +;fbsql.max_links = 128 +;fbsql.max_persistent = -1 +;fbsql.max_results = 128 +;fbsql.batchSize = 1000 + +[gd] +; Tell the jpeg decode to libjpeg warnings and try to create +; a gd image. The warning will then be displayed as notices +; disabled by default +;gd.jpeg_ignore_warning = 0 + +[exif] +; Exif UNICODE user comments are handled as UCS-2BE/UCS-2LE and JIS as JIS. +; With mbstring support this will automatically be converted into the encoding +; given by corresponding encode setting. When empty mbstring.internal_encoding +; is used. For the decode settings you can distinguish between motorola and +; intel byte order. A decode setting cannot be empty. +;exif.encode_unicode = ISO-8859-15 +;exif.decode_unicode_motorola = UCS-2BE +;exif.decode_unicode_intel = UCS-2LE +;exif.encode_jis = +;exif.decode_jis_motorola = JIS +;exif.decode_jis_intel = JIS + +[Tidy] +; The path to a default tidy configuration file to use when using tidy +;tidy.default_config = /usr/local/lib/php/default.tcfg + +; Should tidy clean and repair output automatically? +; WARNING: Do not use this option if you are generating non-html content +; such as dynamic images +tidy.clean_output = Off + +[soap] +; Enables or disables WSDL caching feature. +soap.wsdl_cache_enabled=1 +; Sets the directory name where SOAP extension will put cache files. +soap.wsdl_cache_dir="/tmp" +; (time to live) Sets the number of second while cached file will be used +; instead of original one. +soap.wsdl_cache_ttl=86400 + +; Local Variables: +; tab-width: 4 +; End: + +<% @directives.sort_by { |key, val| key }.each do |directive, value| -%> +<%= "#{directive}=#{value}" %> +<% end -%> diff --git a/cookbooks/php/templates/debian/php.ini.erb b/cookbooks/php/templates/debian/php.ini.erb new file mode 100644 index 0000000..9d47d75 --- /dev/null +++ b/cookbooks/php/templates/debian/php.ini.erb @@ -0,0 +1,1834 @@ +[PHP] + +;;;;;;;;;;;;;;;;;;; +; About php.ini ; +;;;;;;;;;;;;;;;;;;; +; PHP's initialization file, generally called php.ini, is responsible for +; configuring many of the aspects of PHP's behavior. + +; PHP attempts to find and load this configuration from a number of locations. +; The following is a summary of its search order: +; 1. SAPI module specific location. +; 2. The PHPRC environment variable. (As of PHP 5.2.0) +; 3. A number of predefined registry keys on Windows (As of PHP 5.2.0) +; 4. Current working directory (except CLI) +; 5. The web server's directory (for SAPI modules), or directory of PHP +; (otherwise in Windows) +; 6. The directory from the --with-config-file-path compile time option, or the +; Windows directory (C:\windows or C:\winnt) +; See the PHP docs for more specific information. +; http://php.net/configuration.file + +; The syntax of the file is extremely simple. Whitespace and Lines +; beginning with a semicolon are silently ignored (as you probably guessed). +; Section headers (e.g. [Foo]) are also silently ignored, even though +; they might mean something in the future. + +; Directives following the section heading [PATH=/www/mysite] only +; apply to PHP files in the /www/mysite directory. Directives +; following the section heading [HOST=www.example.com] only apply to +; PHP files served from www.example.com. Directives set in these +; special sections cannot be overridden by user-defined INI files or +; at runtime. Currently, [PATH=] and [HOST=] sections only work under +; CGI/FastCGI. +; http://php.net/ini.sections + +; Directives are specified using the following syntax: +; directive = value +; Directive names are *case sensitive* - foo=bar is different from FOO=bar. +; Directives are variables used to configure PHP or PHP extensions. +; There is no name validation. If PHP can't find an expected +; directive because it is not set or is mistyped, a default value will be used. + +; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one +; of the INI constants (On, Off, True, False, Yes, No and None) or an expression +; (e.g. E_ALL & ~E_NOTICE), a quoted string ("bar"), or a reference to a +; previously set variable or directive (e.g. ${foo}) + +; Expressions in the INI file are limited to bitwise operators and parentheses: +; | bitwise OR +; ^ bitwise XOR +; & bitwise AND +; ~ bitwise NOT +; ! boolean NOT + +; Boolean flags can be turned on using the values 1, On, True or Yes. +; They can be turned off using the values 0, Off, False or No. + +; An empty string can be denoted by simply not writing anything after the equal +; sign, or by using the None keyword: + +; foo = ; sets foo to an empty string +; foo = None ; sets foo to an empty string +; foo = "None" ; sets foo to the string 'None' + +; If you use constants in your value, and these constants belong to a +; dynamically loaded extension (either a PHP extension or a Zend extension), +; you may only use these constants *after* the line that loads the extension. + +;;;;;;;;;;;;;;;;;;; +; About this file ; +;;;;;;;;;;;;;;;;;;; +; PHP comes packaged with two INI files. One that is recommended to be used +; in production environments and one that is recommended to be used in +; development environments. + +; php.ini-production contains settings which hold security, performance and +; best practices at its core. But please be aware, these settings may break +; compatibility with older or less security conscience applications. We +; recommending using the production ini in production and testing environments. + +; php.ini-development is very similar to its production variant, except it's +; much more verbose when it comes to errors. We recommending using the +; development version only in development environments as errors shown to +; application users can inadvertently leak otherwise secure information. + +;;;;;;;;;;;;;;;;;;; +; Quick Reference ; +;;;;;;;;;;;;;;;;;;; +; The following are all the settings which are different in either the production +; or development versions of the INIs with respect to PHP's default behavior. +; Please see the actual settings later in the document for more details as to why +; we recommend these changes in PHP's behavior. + +; display_errors +; Default Value: On +; Development Value: On +; Production Value: Off + +; display_startup_errors +; Default Value: Off +; Development Value: On +; Production Value: Off + +; error_reporting +; Default Value: E_ALL & ~E_NOTICE +; Development Value: E_ALL | E_STRICT +; Production Value: E_ALL & ~E_DEPRECATED + +; html_errors +; Default Value: On +; Development Value: On +; Production value: Off + +; log_errors +; Default Value: Off +; Development Value: On +; Production Value: On + +; magic_quotes_gpc +; Default Value: On +; Development Value: Off +; Production Value: Off + +; max_input_time +; Default Value: -1 (Unlimited) +; Development Value: 60 (60 seconds) +; Production Value: 60 (60 seconds) + +; output_buffering +; Default Value: Off +; Development Value: 4096 +; Production Value: 4096 + +; register_argc_argv +; Default Value: On +; Development Value: Off +; Production Value: Off + +; register_long_arrays +; Default Value: On +; Development Value: Off +; Production Value: Off + +; request_order +; Default Value: None +; Development Value: "GP" +; Production Value: "GP" + +; session.bug_compat_42 +; Default Value: On +; Development Value: On +; Production Value: Off + +; session.bug_compat_warn +; Default Value: On +; Development Value: On +; Production Value: Off + +; session.gc_divisor +; Default Value: 100 +; Development Value: 1000 +; Production Value: 1000 + +; session.hash_bits_per_character +; Default Value: 4 +; Development Value: 5 +; Production Value: 5 + +; short_open_tag +; Default Value: On +; Development Value: Off +; Production Value: Off + +; track_errors +; Default Value: Off +; Development Value: On +; Production Value: Off + +; url_rewriter.tags +; Default Value: "a=href,area=href,frame=src,form=,fieldset=" +; Development Value: "a=href,area=href,frame=src,input=src,form=fakeentry" +; Production Value: "a=href,area=href,frame=src,input=src,form=fakeentry" + +; variables_order +; Default Value: "EGPCS" +; Development Value: "GPCS" +; Production Value: "GPCS" + +;;;;;;;;;;;;;;;;;;;; +; php.ini Options ; +;;;;;;;;;;;;;;;;;;;; +; Name for user-defined php.ini (.htaccess) files. Default is ".user.ini" +;user_ini.filename = ".user.ini" + +; To disable this feature set this option to empty value +;user_ini.filename = + +; TTL for user-defined php.ini files (time-to-live) in seconds. Default is 300 seconds (5 minutes) +;user_ini.cache_ttl = 300 + +;;;;;;;;;;;;;;;;;;;; +; Language Options ; +;;;;;;;;;;;;;;;;;;;; + +; Enable the PHP scripting language engine under Apache. +; http://php.net/engine +engine = On + +; This directive determines whether or not PHP will recognize code between +; tags as PHP source which should be processed as such. It's been +; recommended for several years that you not use the short tag "short cut" and +; instead to use the full tag combination. With the wide spread use +; of XML and use of these tags by other languages, the server can become easily +; confused and end up parsing the wrong code in the wrong context. But because +; this short cut has been a feature for such a long time, it's currently still +; supported for backwards compatibility, but we recommend you don't use them. +; Default Value: On +; Development Value: Off +; Production Value: Off +; http://php.net/short-open-tag +short_open_tag = On + +; Allow ASP-style <% %> tags. +; http://php.net/asp-tags +asp_tags = Off + +; The number of significant digits displayed in floating point numbers. +; http://php.net/precision +precision = 14 + +; Output buffering is a mechanism for controlling how much output data +; (excluding headers and cookies) PHP should keep internally before pushing that +; data to the client. If your application's output exceeds this setting, PHP +; will send that data in chunks of roughly the size you specify. +; Turning on this setting and managing its maximum buffer size can yield some +; interesting side-effects depending on your application and web server. +; You may be able to send headers and cookies after you've already sent output +; through print or echo. You also may see performance benefits if your server is +; emitting less packets due to buffered output versus PHP streaming the output +; as it gets it. On production servers, 4096 bytes is a good setting for performance +; reasons. +; Note: Output buffering can also be controlled via Output Buffering Control +; functions. +; Possible Values: +; On = Enabled and buffer is unlimited. (Use with caution) +; Off = Disabled +; Integer = Enables the buffer and sets its maximum size in bytes. +; Note: This directive is hardcoded to Off for the CLI SAPI +; Default Value: Off +; Development Value: 4096 +; Production Value: 4096 +; http://php.net/output-buffering +output_buffering = 4096 + +; You can redirect all of the output of your scripts to a function. For +; example, if you set output_handler to "mb_output_handler", character +; encoding will be transparently converted to the specified encoding. +; Setting any output handler automatically turns on output buffering. +; Note: People who wrote portable scripts should not depend on this ini +; directive. Instead, explicitly set the output handler using ob_start(). +; Using this ini directive may cause problems unless you know what script +; is doing. +; Note: You cannot use both "mb_output_handler" with "ob_iconv_handler" +; and you cannot use both "ob_gzhandler" and "zlib.output_compression". +; Note: output_handler must be empty if this is set 'On' !!!! +; Instead you must use zlib.output_handler. +; http://php.net/output-handler +;output_handler = + +; Transparent output compression using the zlib library +; Valid values for this option are 'off', 'on', or a specific buffer size +; to be used for compression (default is 4KB) +; Note: Resulting chunk size may vary due to nature of compression. PHP +; outputs chunks that are few hundreds bytes each as a result of +; compression. If you prefer a larger chunk size for better +; performance, enable output_buffering in addition. +; Note: You need to use zlib.output_handler instead of the standard +; output_handler, or otherwise the output will be corrupted. +; http://php.net/zlib.output-compression +zlib.output_compression = Off + +; http://php.net/zlib.output-compression-level +;zlib.output_compression_level = -1 + +; You cannot specify additional output handlers if zlib.output_compression +; is activated here. This setting does the same as output_handler but in +; a different order. +; http://php.net/zlib.output-handler +;zlib.output_handler = + +; Implicit flush tells PHP to tell the output layer to flush itself +; automatically after every output block. This is equivalent to calling the +; PHP function flush() after each and every call to print() or echo() and each +; and every HTML block. Turning this option on has serious performance +; implications and is generally recommended for debugging purposes only. +; http://php.net/implicit-flush +; Note: This directive is hardcoded to On for the CLI SAPI +implicit_flush = Off + +; The unserialize callback function will be called (with the undefined class' +; name as parameter), if the unserializer finds an undefined class +; which should be instantiated. A warning appears if the specified function is +; not defined, or if the function doesn't include/implement the missing class. +; So only set this entry, if you really want to implement such a +; callback-function. +unserialize_callback_func = + +; When floats & doubles are serialized store serialize_precision significant +; digits after the floating point. The default value ensures that when floats +; are decoded with unserialize, the data will remain the same. +serialize_precision = 100 + +; Safe Mode +; http://php.net/safe-mode +safe_mode = Off + +; By default, Safe Mode does a UID compare check when +; opening files. If you want to relax this to a GID compare, +; then turn on safe_mode_gid. +; http://php.net/safe-mode-gid +safe_mode_gid = Off + +; When safe_mode is on, UID/GID checks are bypassed when +; including files from this directory and its subdirectories. +; (directory must also be in include_path or full path must +; be used when including) +; http://php.net/safe-mode-include-dir +safe_mode_include_dir = + +; When safe_mode is on, only executables located in the safe_mode_exec_dir +; will be allowed to be executed via the exec family of functions. +; http://php.net/safe-mode-exec-dir +safe_mode_exec_dir = + +; Setting certain environment variables may be a potential security breach. +; This directive contains a comma-delimited list of prefixes. In Safe Mode, +; the user may only alter environment variables whose names begin with the +; prefixes supplied here. By default, users will only be able to set +; environment variables that begin with PHP_ (e.g. PHP_FOO=BAR). +; Note: If this directive is empty, PHP will let the user modify ANY +; environment variable! +; http://php.net/safe-mode-allowed-env-vars +safe_mode_allowed_env_vars = PHP_ + +; This directive contains a comma-delimited list of environment variables that +; the end user won't be able to change using putenv(). These variables will be +; protected even if safe_mode_allowed_env_vars is set to allow to change them. +; http://php.net/safe-mode-protected-env-vars +safe_mode_protected_env_vars = LD_LIBRARY_PATH + +; open_basedir, if set, limits all file operations to the defined directory +; and below. This directive makes most sense if used in a per-directory +; or per-virtualhost web server configuration file. This directive is +; *NOT* affected by whether Safe Mode is turned On or Off. +; http://php.net/open-basedir +;open_basedir = + +; This directive allows you to disable certain functions for security reasons. +; It receives a comma-delimited list of function names. This directive is +; *NOT* affected by whether Safe Mode is turned On or Off. +; http://php.net/disable-functions +disable_functions = + +; This directive allows you to disable certain classes for security reasons. +; It receives a comma-delimited list of class names. This directive is +; *NOT* affected by whether Safe Mode is turned On or Off. +; http://php.net/disable-classes +disable_classes = + +; Colors for Syntax Highlighting mode. Anything that's acceptable in +; would work. +; http://php.net/syntax-highlighting +;highlight.string = #DD0000 +;highlight.comment = #FF9900 +;highlight.keyword = #007700 +;highlight.bg = #FFFFFF +;highlight.default = #0000BB +;highlight.html = #000000 + +; If enabled, the request will be allowed to complete even if the user aborts +; the request. Consider enabling it if executing long requests, which may end up +; being interrupted by the user or a browser timing out. PHP's default behavior +; is to disable this feature. +; http://php.net/ignore-user-abort +;ignore_user_abort = On + +; Determines the size of the realpath cache to be used by PHP. This value should +; be increased on systems where PHP opens many files to reflect the quantity of +; the file operations performed. +; http://php.net/realpath-cache-size +;realpath_cache_size = 16k + +; Duration of time, in seconds for which to cache realpath information for a given +; file or directory. For systems with rarely changing files, consider increasing this +; value. +; http://php.net/realpath-cache-ttl +;realpath_cache_ttl = 120 + +;;;;;;;;;;;;;;;;; +; Miscellaneous ; +;;;;;;;;;;;;;;;;; + +; Decides whether PHP may expose the fact that it is installed on the server +; (e.g. by adding its signature to the Web server header). It is no security +; threat in any way, but it makes it possible to determine whether you use PHP +; on your server or not. +; http://php.net/expose-php +expose_php = On + +;;;;;;;;;;;;;;;;;;; +; Resource Limits ; +;;;;;;;;;;;;;;;;;;; + +; Maximum execution time of each script, in seconds +; http://php.net/max-execution-time +; Note: This directive is hardcoded to 0 for the CLI SAPI +max_execution_time = 30 + +; Maximum amount of time each script may spend parsing request data. It's a good +; idea to limit this time on productions servers in order to eliminate unexpectedly +; long running scripts. +; Note: This directive is hardcoded to -1 for the CLI SAPI +; Default Value: -1 (Unlimited) +; Development Value: 60 (60 seconds) +; Production Value: 60 (60 seconds) +; http://php.net/max-input-time +max_input_time = 60 + +; Maximum input variable nesting level +; http://php.net/max-input-nesting-level +;max_input_nesting_level = 64 + +; Maximum amount of memory a script may consume (128MB) +; http://php.net/memory-limit +memory_limit = -1 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Error handling and logging ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; This directive informs PHP of which errors, warnings and notices you would like +; it to take action for. The recommended way of setting values for this +; directive is through the use of the error level constants and bitwise +; operators. The error level constants are below here for convenience as well as +; some common settings and their meanings. +; By default, PHP is set to take action on all errors, notices and warnings EXCEPT +; those related to E_NOTICE and E_STRICT, which together cover best practices and +; recommended coding standards in PHP. For performance reasons, this is the +; recommend error reporting setting. Your production server shouldn't be wasting +; resources complaining about best practices and coding standards. That's what +; development servers and development settings are for. +; Note: The php.ini-development file has this setting as E_ALL | E_STRICT. This +; means it pretty much reports everything which is exactly what you want during +; development and early testing. +; +; Error Level Constants: +; E_ALL - All errors and warnings (includes E_STRICT as of PHP 6.0.0) +; E_ERROR - fatal run-time errors +; E_RECOVERABLE_ERROR - almost fatal run-time errors +; E_WARNING - run-time warnings (non-fatal errors) +; E_PARSE - compile-time parse errors +; E_NOTICE - run-time notices (these are warnings which often result +; from a bug in your code, but it's possible that it was +; intentional (e.g., using an uninitialized variable and +; relying on the fact it's automatically initialized to an +; empty string) +; E_STRICT - run-time notices, enable to have PHP suggest changes +; to your code which will ensure the best interoperability +; and forward compatibility of your code +; E_CORE_ERROR - fatal errors that occur during PHP's initial startup +; E_CORE_WARNING - warnings (non-fatal errors) that occur during PHP's +; initial startup +; E_COMPILE_ERROR - fatal compile-time errors +; E_COMPILE_WARNING - compile-time warnings (non-fatal errors) +; E_USER_ERROR - user-generated error message +; E_USER_WARNING - user-generated warning message +; E_USER_NOTICE - user-generated notice message +; E_DEPRECATED - warn about code that will not work in future versions +; of PHP +; E_USER_DEPRECATED - user-generated deprecation warnings +; +; Common Values: +; E_ALL & ~E_NOTICE (Show all errors, except for notices and coding standards warnings.) +; E_ALL & ~E_NOTICE | E_STRICT (Show all errors, except for notices) +; E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR (Show only errors) +; E_ALL | E_STRICT (Show all errors, warnings and notices including coding standards.) +; Default Value: E_ALL & ~E_NOTICE +; Development Value: E_ALL | E_STRICT +; Production Value: E_ALL & ~E_DEPRECATED +; http://php.net/error-reporting +error_reporting = E_ALL & ~E_DEPRECATED + +; This directive controls whether or not and where PHP will output errors, +; notices and warnings too. Error output is very useful during development, but +; it could be very dangerous in production environments. Depending on the code +; which is triggering the error, sensitive information could potentially leak +; out of your application such as database usernames and passwords or worse. +; It's recommended that errors be logged on production servers rather than +; having the errors sent to STDOUT. +; Possible Values: +; Off = Do not display any errors +; stderr = Display errors to STDERR (affects only CGI/CLI binaries!) +; On or stdout = Display errors to STDOUT +; Default Value: On +; Development Value: On +; Production Value: Off +; http://php.net/display-errors +display_errors = Off + +; The display of errors which occur during PHP's startup sequence are handled +; separately from display_errors. PHP's default behavior is to suppress those +; errors from clients. Turning the display of startup errors on can be useful in +; debugging configuration problems. But, it's strongly recommended that you +; leave this setting off on production servers. +; Default Value: Off +; Development Value: On +; Production Value: Off +; http://php.net/display-startup-errors +display_startup_errors = Off + +; Besides displaying errors, PHP can also log errors to locations such as a +; server-specific log, STDERR, or a location specified by the error_log +; directive found below. While errors should not be displayed on productions +; servers they should still be monitored and logging is a great way to do that. +; Default Value: Off +; Development Value: On +; Production Value: On +; http://php.net/log-errors +log_errors = On + +; Set maximum length of log_errors. In error_log information about the source is +; added. The default is 1024 and 0 allows to not apply any maximum length at all. +; http://php.net/log-errors-max-len +log_errors_max_len = 1024 + +; Do not log repeated messages. Repeated errors must occur in same file on same +; line unless ignore_repeated_source is set true. +; http://php.net/ignore-repeated-errors +ignore_repeated_errors = Off + +; Ignore source of message when ignoring repeated messages. When this setting +; is On you will not log errors with repeated messages from different files or +; source lines. +; http://php.net/ignore-repeated-source +ignore_repeated_source = Off + +; If this parameter is set to Off, then memory leaks will not be shown (on +; stdout or in the log). This has only effect in a debug compile, and if +; error reporting includes E_WARNING in the allowed list +; http://php.net/report-memleaks +report_memleaks = On + +; This setting is on by default. +;report_zend_debug = 0 + +; Store the last error/warning message in $php_errormsg (boolean). Setting this value +; to On can assist in debugging and is appropriate for development servers. It should +; however be disabled on production servers. +; Default Value: Off +; Development Value: On +; Production Value: Off +; http://php.net/track-errors +track_errors = Off + +; Turn off normal error reporting and emit XML-RPC error XML +; http://php.net/xmlrpc-errors +;xmlrpc_errors = 0 + +; An XML-RPC faultCode +;xmlrpc_error_number = 0 + +; When PHP displays or logs an error, it has the capability of inserting html +; links to documentation related to that error. This directive controls whether +; those HTML links appear in error messages or not. For performance and security +; reasons, it's recommended you disable this on production servers. +; Note: This directive is hardcoded to Off for the CLI SAPI +; Default Value: On +; Development Value: On +; Production value: Off +; http://php.net/html-errors +html_errors = Off + +; If html_errors is set On PHP produces clickable error messages that direct +; to a page describing the error or function causing the error in detail. +; You can download a copy of the PHP manual from http://php.net/docs +; and change docref_root to the base URL of your local copy including the +; leading '/'. You must also specify the file extension being used including +; the dot. PHP's default behavior is to leave these settings empty. +; Note: Never use this feature for production boxes. +; http://php.net/docref-root +; Examples +;docref_root = "/phpmanual/" + +; http://php.net/docref-ext +;docref_ext = .html + +; String to output before an error message. PHP's default behavior is to leave +; this setting blank. +; http://php.net/error-prepend-string +; Example: +;error_prepend_string = "" + +; String to output after an error message. PHP's default behavior is to leave +; this setting blank. +; http://php.net/error-append-string +; Example: +;error_append_string = "" + +; Log errors to specified file. PHP's default behavior is to leave this value +; empty. +; http://php.net/error-log +; Example: +;error_log = php_errors.log +; Log errors to syslog (Event Log on NT, not valid in Windows 95). +;error_log = syslog + +;;;;;;;;;;;;;;;;; +; Data Handling ; +;;;;;;;;;;;;;;;;; + +; The separator used in PHP generated URLs to separate arguments. +; PHP's default setting is "&". +; http://php.net/arg-separator.output +; Example: +;arg_separator.output = "&" + +; List of separator(s) used by PHP to parse input URLs into variables. +; PHP's default setting is "&". +; NOTE: Every character in this directive is considered as separator! +; http://php.net/arg-separator.input +; Example: +;arg_separator.input = ";&" + +; This directive determines which super global arrays are registered when PHP +; starts up. If the register_globals directive is enabled, it also determines +; what order variables are populated into the global space. G,P,C,E & S are +; abbreviations for the following respective super globals: GET, POST, COOKIE, +; ENV and SERVER. There is a performance penalty paid for the registration of +; these arrays and because ENV is not as commonly used as the others, ENV is +; is not recommended on productions servers. You can still get access to +; the environment variables through getenv() should you need to. +; Default Value: "EGPCS" +; Development Value: "GPCS" +; Production Value: "GPCS"; +; http://php.net/variables-order +variables_order = "GPCS" + +; This directive determines which super global data (G,P,C,E & S) should +; be registered into the super global array REQUEST. If so, it also determines +; the order in which that data is registered. The values for this directive are +; specified in the same manner as the variables_order directive, EXCEPT one. +; Leaving this value empty will cause PHP to use the value set in the +; variables_order directive. It does not mean it will leave the super globals +; array REQUEST empty. +; Default Value: None +; Development Value: "GP" +; Production Value: "GP" +; http://php.net/request-order +request_order = "GP" + +; Whether or not to register the EGPCS variables as global variables. You may +; want to turn this off if you don't want to clutter your scripts' global scope +; with user data. +; You should do your best to write your scripts so that they do not require +; register_globals to be on; Using form variables as globals can easily lead +; to possible security problems, if the code is not very well thought of. +; http://php.net/register-globals +register_globals = Off + +; Determines whether the deprecated long $HTTP_*_VARS type predefined variables +; are registered by PHP or not. As they are deprecated, we obviously don't +; recommend you use them. They are on by default for compatibility reasons but +; they are not recommended on production servers. +; Default Value: On +; Development Value: Off +; Production Value: Off +; http://php.net/register-long-arrays +register_long_arrays = Off + +; This directive determines whether PHP registers $argv & $argc each time it +; runs. $argv contains an array of all the arguments passed to PHP when a script +; is invoked. $argc contains an integer representing the number of arguments +; that were passed when the script was invoked. These arrays are extremely +; useful when running scripts from the command line. When this directive is +; enabled, registering these variables consumes CPU cycles and memory each time +; a script is executed. For performance reasons, this feature should be disabled +; on production servers. +; Note: This directive is hardcoded to On for the CLI SAPI +; Default Value: On +; Development Value: Off +; Production Value: Off +; http://php.net/register-argc-argv +register_argc_argv = Off + +; When enabled, the SERVER and ENV variables are created when they're first +; used (Just In Time) instead of when the script starts. If these variables +; are not used within a script, having this directive on will result in a +; performance gain. The PHP directives register_globals, register_long_arrays, +; and register_argc_argv must be disabled for this directive to have any affect. +; http://php.net/auto-globals-jit +auto_globals_jit = On + +; Maximum size of POST data that PHP will accept. +; http://php.net/post-max-size +post_max_size = 8M + +; Magic quotes are a preprocessing feature of PHP where PHP will attempt to +; escape any character sequences in GET, POST, COOKIE and ENV data which might +; otherwise corrupt data being placed in resources such as databases before +; making that data available to you. Because of character encoding issues and +; non-standard SQL implementations across many databases, it's not currently +; possible for this feature to be 100% accurate. PHP's default behavior is to +; enable the feature. We strongly recommend you use the escaping mechanisms +; designed specifically for the database your using instead of relying on this +; feature. Also note, this feature has been deprecated as of PHP 5.3.0 and is +; scheduled for removal in PHP 6. +; Default Value: On +; Development Value: Off +; Production Value: Off +; http://php.net/magic-quotes-gpc +magic_quotes_gpc = Off + +; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc. +; http://php.net/magic-quotes-runtime +magic_quotes_runtime = Off + +; Use Sybase-style magic quotes (escape ' with '' instead of \'). +; http://php.net/magic-quotes-sybase +magic_quotes_sybase = Off + +; Automatically add files before PHP document. +; http://php.net/auto-prepend-file +auto_prepend_file = + +; Automatically add files after PHP document. +; http://php.net/auto-append-file +auto_append_file = + +; By default, PHP will output a character encoding using +; the Content-type: header. To disable sending of the charset, simply +; set it to be empty. +; +; PHP's built-in default is text/html +; http://php.net/default-mimetype +default_mimetype = "text/html" + +; PHP's default character set is set to empty. +; http://php.net/default-charset +;default_charset = "iso-8859-1" + +; Always populate the $HTTP_RAW_POST_DATA variable. PHP's default behavior is +; to disable this feature. +; http://php.net/always-populate-raw-post-data +;always_populate_raw_post_data = On + +;;;;;;;;;;;;;;;;;;;;;;;;; +; Paths and Directories ; +;;;;;;;;;;;;;;;;;;;;;;;;; + +; UNIX: "/path1:/path2" +;include_path = ".:/usr/share/php" +; +; Windows: "\path1;\path2" +;include_path = ".;c:\php\includes" +; +; PHP's default setting for include_path is ".;/path/to/php/pear" +; http://php.net/include-path + +; The root of the PHP pages, used only if nonempty. +; if PHP was not compiled with FORCE_REDIRECT, you SHOULD set doc_root +; if you are running php as a CGI under any web server (other than IIS) +; see documentation for security issues. The alternate is to use the +; cgi.force_redirect configuration below +; http://php.net/doc-root +doc_root = + +; The directory under which PHP opens the script using /~username used only +; if nonempty. +; http://php.net/user-dir +user_dir = + +; Directory in which the loadable extensions (modules) reside. +; http://php.net/extension-dir +; extension_dir = "./" +; On windows: +; extension_dir = "ext" + +; Whether or not to enable the dl() function. The dl() function does NOT work +; properly in multithreaded servers, such as IIS or Zeus, and is automatically +; disabled on them. +; http://php.net/enable-dl +enable_dl = Off + +; cgi.force_redirect is necessary to provide security running PHP as a CGI under +; most web servers. Left undefined, PHP turns this on by default. You can +; turn it off here AT YOUR OWN RISK +; **You CAN safely turn this off for IIS, in fact, you MUST.** +; http://php.net/cgi.force-redirect +;cgi.force_redirect = 1 + +; if cgi.nph is enabled it will force cgi to always sent Status: 200 with +; every request. PHP's default behavior is to disable this feature. +;cgi.nph = 1 + +; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape +; (iPlanet) web servers, you MAY need to set an environment variable name that PHP +; will look for to know it is OK to continue execution. Setting this variable MAY +; cause security issues, KNOW WHAT YOU ARE DOING FIRST. +; http://php.net/cgi.redirect-status-env +;cgi.redirect_status_env = ; + +; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's +; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok +; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting +; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting +; of zero causes PHP to behave as before. Default is 1. You should fix your scripts +; to use SCRIPT_FILENAME rather than PATH_TRANSLATED. +; http://php.net/cgi.fix-pathinfo +;cgi.fix_pathinfo=1 + +; FastCGI under IIS (on WINNT based OS) supports the ability to impersonate +; security tokens of the calling client. This allows IIS to define the +; security context that the request runs under. mod_fastcgi under Apache +; does not currently support this feature (03/17/2002) +; Set to 1 if running under IIS. Default is zero. +; http://php.net/fastcgi.impersonate +;fastcgi.impersonate = 1; + +; Disable logging through FastCGI connection. PHP's default behavior is to enable +; this feature. +;fastcgi.logging = 0 + +; cgi.rfc2616_headers configuration option tells PHP what type of headers to +; use when sending HTTP response code. If it's set 0 PHP sends Status: header that +; is supported by Apache. When this option is set to 1 PHP will send +; RFC2616 compliant header. +; Default is zero. +; http://php.net/cgi.rfc2616-headers +;cgi.rfc2616_headers = 0 + +;;;;;;;;;;;;;;;; +; File Uploads ; +;;;;;;;;;;;;;;;; + +; Whether to allow HTTP file uploads. +; http://php.net/file-uploads +file_uploads = On + +; Temporary directory for HTTP uploaded files (will use system default if not +; specified). +; http://php.net/upload-tmp-dir +;upload_tmp_dir = + +; Maximum allowed size for uploaded files. +; http://php.net/upload-max-filesize +upload_max_filesize = 2M + +; Maximum number of files that can be uploaded via a single request +max_file_uploads = 20 + +;;;;;;;;;;;;;;;;;; +; Fopen wrappers ; +;;;;;;;;;;;;;;;;;; + +; Whether to allow the treatment of URLs (like http:// or ftp://) as files. +; http://php.net/allow-url-fopen +allow_url_fopen = On + +; Whether to allow include/require to open URLs (like http:// or ftp://) as files. +; http://php.net/allow-url-include +allow_url_include = Off + +; Define the anonymous ftp password (your email address). PHP's default setting +; for this is empty. +; http://php.net/from +;from="john@doe.com" + +; Define the User-Agent string. PHP's default setting for this is empty. +; http://php.net/user-agent +;user_agent="PHP" + +; Default timeout for socket based streams (seconds) +; http://php.net/default-socket-timeout +default_socket_timeout = 60 + +; If your scripts have to deal with files from Macintosh systems, +; or you are running on a Mac and need to deal with files from +; unix or win32 systems, setting this flag will cause PHP to +; automatically detect the EOL character in those files so that +; fgets() and file() will work regardless of the source of the file. +; http://php.net/auto-detect-line-endings +;auto_detect_line_endings = Off + +;;;;;;;;;;;;;;;;;;;;;; +; Dynamic Extensions ; +;;;;;;;;;;;;;;;;;;;;;; + +; If you wish to have an extension loaded automatically, use the following +; syntax: +; +; extension=modulename.extension +; +; For example, on Windows: +; +; extension=msql.dll +; +; ... or under UNIX: +; +; extension=msql.so +; +; ... or with a path: +; +; extension=/path/to/extension/msql.so +; +; If you only provide the name of the extension, PHP will look for it in its +; default extension directory. +; + +;;;;;;;;;;;;;;;;;;; +; Module Settings ; +;;;;;;;;;;;;;;;;;;; + +[Date] +; Defines the default timezone used by the date functions +; http://php.net/date.timezone +;date.timezone = + +; http://php.net/date.default-latitude +;date.default_latitude = 31.7667 + +; http://php.net/date.default-longitude +;date.default_longitude = 35.2333 + +; http://php.net/date.sunrise-zenith +;date.sunrise_zenith = 90.583333 + +; http://php.net/date.sunset-zenith +;date.sunset_zenith = 90.583333 + +[filter] +; http://php.net/filter.default +;filter.default = unsafe_raw + +; http://php.net/filter.default-flags +;filter.default_flags = + +[iconv] +;iconv.input_encoding = ISO-8859-1 +;iconv.internal_encoding = ISO-8859-1 +;iconv.output_encoding = ISO-8859-1 + +[intl] +;intl.default_locale = +; This directive allows you to produce PHP errors when some error +; happens within intl functions. The value is the level of the error produced. +; Default is 0, which does not produce any errors. +;intl.error_level = E_WARNING + +[sqlite] +; http://php.net/sqlite.assoc-case +;sqlite.assoc_case = 0 + +[sqlite3] +;sqlite3.extension_dir = + +[Pcre] +;PCRE library backtracking limit. +; http://php.net/pcre.backtrack-limit +;pcre.backtrack_limit=100000 + +;PCRE library recursion limit. +;Please note that if you set this value to a high number you may consume all +;the available process stack and eventually crash PHP (due to reaching the +;stack size limit imposed by the Operating System). +; http://php.net/pcre.recursion-limit +;pcre.recursion_limit=100000 + +[Pdo] +; Whether to pool ODBC connections. Can be one of "strict", "relaxed" or "off" +; http://php.net/pdo-odbc.connection-pooling +;pdo_odbc.connection_pooling=strict + +;pdo_odbc.db2_instance_name + +[Pdo_mysql] +; If mysqlnd is used: Number of cache slots for the internal result set cache +; http://php.net/pdo_mysql.cache_size +pdo_mysql.cache_size = 2000 + +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +; http://php.net/pdo_mysql.default-socket +pdo_mysql.default_socket= + +[Phar] +; http://php.net/phar.readonly +;phar.readonly = On + +; http://php.net/phar.require-hash +;phar.require_hash = On + +;phar.cache_list = + +[Syslog] +; Whether or not to define the various syslog variables (e.g. $LOG_PID, +; $LOG_CRON, etc.). Turning it off is a good idea performance-wise. In +; runtime, you can define these variables by calling define_syslog_variables(). +; http://php.net/define-syslog-variables +define_syslog_variables = Off + +[mail function] +; For Win32 only. +; http://php.net/smtp +SMTP = localhost +; http://php.net/smtp-port +smtp_port = 25 + +; For Win32 only. +; http://php.net/sendmail-from +;sendmail_from = me@example.com + +; For Unix only. You may supply arguments as well (default: "sendmail -t -i"). +; http://php.net/sendmail-path +;sendmail_path = + +; Force the addition of the specified parameters to be passed as extra parameters +; to the sendmail binary. These parameters will always replace the value of +; the 5th parameter to mail(), even in safe mode. +;mail.force_extra_parameters = + +; Add X-PHP-Originating-Script: that will include uid of the script followed by the filename +mail.add_x_header = On + +; Log all mail() calls including the full path of the script, line #, to address and headers +;mail.log = + +[SQL] +; http://php.net/sql.safe-mode +sql.safe_mode = Off + +[ODBC] +; http://php.net/odbc.default-db +;odbc.default_db = Not yet implemented + +; http://php.net/odbc.default-user +;odbc.default_user = Not yet implemented + +; http://php.net/odbc.default-pw +;odbc.default_pw = Not yet implemented + +; Controls the ODBC cursor model. +; Default: SQL_CURSOR_STATIC (default). +;odbc.default_cursortype + +; Allow or prevent persistent links. +; http://php.net/odbc.allow-persistent +odbc.allow_persistent = On + +; Check that a connection is still valid before reuse. +; http://php.net/odbc.check-persistent +odbc.check_persistent = On + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/odbc.max-persistent +odbc.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +; http://php.net/odbc.max-links +odbc.max_links = -1 + +; Handling of LONG fields. Returns number of bytes to variables. 0 means +; passthru. +; http://php.net/odbc.defaultlrl +odbc.defaultlrl = 4096 + +; Handling of binary data. 0 means passthru, 1 return as is, 2 convert to char. +; See the documentation on odbc_binmode and odbc_longreadlen for an explanation +; of odbc.defaultlrl and odbc.defaultbinmode +; http://php.net/odbc.defaultbinmode +odbc.defaultbinmode = 1 + +;birdstep.max_links = -1 + +[Interbase] +; Allow or prevent persistent links. +ibase.allow_persistent = 1 + +; Maximum number of persistent links. -1 means no limit. +ibase.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +ibase.max_links = -1 + +; Default database name for ibase_connect(). +;ibase.default_db = + +; Default username for ibase_connect(). +;ibase.default_user = + +; Default password for ibase_connect(). +;ibase.default_password = + +; Default charset for ibase_connect(). +;ibase.default_charset = + +; Default timestamp format. +ibase.timestampformat = "%Y-%m-%d %H:%M:%S" + +; Default date format. +ibase.dateformat = "%Y-%m-%d" + +; Default time format. +ibase.timeformat = "%H:%M:%S" + +[MySQL] +; Allow accessing, from PHP's perspective, local files with LOAD DATA statements +; http://php.net/mysql.allow_local_infile +mysql.allow_local_infile = On + +; Allow or prevent persistent links. +; http://php.net/mysql.allow-persistent +mysql.allow_persistent = On + +; If mysqlnd is used: Number of cache slots for the internal result set cache +; http://php.net/mysql.cache_size +mysql.cache_size = 2000 + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/mysql.max-persistent +mysql.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +; http://php.net/mysql.max-links +mysql.max_links = -1 + +; Default port number for mysql_connect(). If unset, mysql_connect() will use +; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the +; compile-time value defined MYSQL_PORT (in that order). Win32 will only look +; at MYSQL_PORT. +; http://php.net/mysql.default-port +mysql.default_port = + +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +; http://php.net/mysql.default-socket +mysql.default_socket = + +; Default host for mysql_connect() (doesn't apply in safe mode). +; http://php.net/mysql.default-host +mysql.default_host = + +; Default user for mysql_connect() (doesn't apply in safe mode). +; http://php.net/mysql.default-user +mysql.default_user = + +; Default password for mysql_connect() (doesn't apply in safe mode). +; Note that this is generally a *bad* idea to store passwords in this file. +; *Any* user with PHP access can run 'echo get_cfg_var("mysql.default_password") +; and reveal this password! And of course, any users with read access to this +; file will be able to reveal the password as well. +; http://php.net/mysql.default-password +mysql.default_password = + +; Maximum time (in seconds) for connect timeout. -1 means no limit +; http://php.net/mysql.connect-timeout +mysql.connect_timeout = 60 + +; Trace mode. When trace_mode is active (=On), warnings for table/index scans and +; SQL-Errors will be displayed. +; http://php.net/mysql.trace-mode +mysql.trace_mode = Off + +[MySQLi] + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/mysqli.max-persistent +mysqli.max_persistent = -1 + +; Allow accessing, from PHP's perspective, local files with LOAD DATA statements +; http://php.net/mysqli.allow_local_infile +;mysqli.allow_local_infile = On + +; Allow or prevent persistent links. +; http://php.net/mysqli.allow-persistent +mysqli.allow_persistent = On + +; Maximum number of links. -1 means no limit. +; http://php.net/mysqli.max-links +mysqli.max_links = -1 + +; If mysqlnd is used: Number of cache slots for the internal result set cache +; http://php.net/mysqli.cache_size +mysqli.cache_size = 2000 + +; Default port number for mysqli_connect(). If unset, mysqli_connect() will use +; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the +; compile-time value defined MYSQL_PORT (in that order). Win32 will only look +; at MYSQL_PORT. +; http://php.net/mysqli.default-port +mysqli.default_port = 3306 + +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +; http://php.net/mysqli.default-socket +mysqli.default_socket = + +; Default host for mysql_connect() (doesn't apply in safe mode). +; http://php.net/mysqli.default-host +mysqli.default_host = + +; Default user for mysql_connect() (doesn't apply in safe mode). +; http://php.net/mysqli.default-user +mysqli.default_user = + +; Default password for mysqli_connect() (doesn't apply in safe mode). +; Note that this is generally a *bad* idea to store passwords in this file. +; *Any* user with PHP access can run 'echo get_cfg_var("mysqli.default_pw") +; and reveal this password! And of course, any users with read access to this +; file will be able to reveal the password as well. +; http://php.net/mysqli.default-pw +mysqli.default_pw = + +; Allow or prevent reconnect +mysqli.reconnect = Off + +[mysqlnd] +; Enable / Disable collection of general statstics by mysqlnd which can be +; used to tune and monitor MySQL operations. +; http://php.net/mysqlnd.collect_statistics +mysqlnd.collect_statistics = On + +; Enable / Disable collection of memory usage statstics by mysqlnd which can be +; used to tune and monitor MySQL operations. +; http://php.net/mysqlnd.collect_memory_statistics +mysqlnd.collect_memory_statistics = Off + +; Size of a pre-allocated buffer used when sending commands to MySQL in bytes. +; http://php.net/mysqlnd.net_cmd_buffer_size +;mysqlnd.net_cmd_buffer_size = 2048 + +; Size of a pre-allocated buffer used for reading data sent by the server in +; bytes. +; http://php.net/mysqlnd.net_read_buffer_size +;mysqlnd.net_read_buffer_size = 32768 + +[OCI8] + +; Connection: Enables privileged connections using external +; credentials (OCI_SYSOPER, OCI_SYSDBA) +; http://php.net/oci8.privileged-connect +;oci8.privileged_connect = Off + +; Connection: The maximum number of persistent OCI8 connections per +; process. Using -1 means no limit. +; http://php.net/oci8.max-persistent +;oci8.max_persistent = -1 + +; Connection: The maximum number of seconds a process is allowed to +; maintain an idle persistent connection. Using -1 means idle +; persistent connections will be maintained forever. +; http://php.net/oci8.persistent-timeout +;oci8.persistent_timeout = -1 + +; Connection: The number of seconds that must pass before issuing a +; ping during oci_pconnect() to check the connection validity. When +; set to 0, each oci_pconnect() will cause a ping. Using -1 disables +; pings completely. +; http://php.net/oci8.ping-interval +;oci8.ping_interval = 60 + +; Connection: Set this to a user chosen connection class to be used +; for all pooled server requests with Oracle 11g Database Resident +; Connection Pooling (DRCP). To use DRCP, this value should be set to +; the same string for all web servers running the same application, +; the database pool must be configured, and the connection string must +; specify to use a pooled server. +;oci8.connection_class = + +; High Availability: Using On lets PHP receive Fast Application +; Notification (FAN) events generated when a database node fails. The +; database must also be configured to post FAN events. +;oci8.events = Off + +; Tuning: This option enables statement caching, and specifies how +; many statements to cache. Using 0 disables statement caching. +; http://php.net/oci8.statement-cache-size +;oci8.statement_cache_size = 20 + +; Tuning: Enables statement prefetching and sets the default number of +; rows that will be fetched automatically after statement execution. +; http://php.net/oci8.default-prefetch +;oci8.default_prefetch = 100 + +; Compatibility. Using On means oci_close() will not close +; oci_connect() and oci_new_connect() connections. +; http://php.net/oci8.old-oci-close-semantics +;oci8.old_oci_close_semantics = Off + +[PostgresSQL] +; Allow or prevent persistent links. +; http://php.net/pgsql.allow-persistent +pgsql.allow_persistent = On + +; Detect broken persistent links always with pg_pconnect(). +; Auto reset feature requires a little overheads. +; http://php.net/pgsql.auto-reset-persistent +pgsql.auto_reset_persistent = Off + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/pgsql.max-persistent +pgsql.max_persistent = -1 + +; Maximum number of links (persistent+non persistent). -1 means no limit. +; http://php.net/pgsql.max-links +pgsql.max_links = -1 + +; Ignore PostgreSQL backends Notice message or not. +; Notice message logging require a little overheads. +; http://php.net/pgsql.ignore-notice +pgsql.ignore_notice = 0 + +; Log PostgreSQL backends Noitce message or not. +; Unless pgsql.ignore_notice=0, module cannot log notice message. +; http://php.net/pgsql.log-notice +pgsql.log_notice = 0 + +[Sybase-CT] +; Allow or prevent persistent links. +; http://php.net/sybct.allow-persistent +sybct.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/sybct.max-persistent +sybct.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +; http://php.net/sybct.max-links +sybct.max_links = -1 + +; Minimum server message severity to display. +; http://php.net/sybct.min-server-severity +sybct.min_server_severity = 10 + +; Minimum client message severity to display. +; http://php.net/sybct.min-client-severity +sybct.min_client_severity = 10 + +; Set per-context timeout +; http://php.net/sybct.timeout +;sybct.timeout= + +;sybct.packet_size + +; The maximum time in seconds to wait for a connection attempt to succeed before returning failure. +; Default: one minute +;sybct.login_timeout= + +; The name of the host you claim to be connecting from, for display by sp_who. +; Default: none +;sybct.hostname= + +; Allows you to define how often deadlocks are to be retried. -1 means "forever". +; Default: 0 +;sybct.deadlock_retry_count= + +[bcmath] +; Number of decimal digits for all bcmath functions. +; http://php.net/bcmath.scale +bcmath.scale = 0 + +[browscap] +; http://php.net/browscap +;browscap = extra/browscap.ini + +[Session] +; Handler used to store/retrieve data. +; http://php.net/session.save-handler +session.save_handler = files + +; Argument passed to save_handler. In the case of files, this is the path +; where data files are stored. Note: Windows users have to change this +; variable in order to use PHP's session functions. +; +; The path can be defined as: +; +; session.save_path = "N;/path" +; +; where N is an integer. Instead of storing all the session files in +; /path, what this will do is use subdirectories N-levels deep, and +; store the session data in those directories. This is useful if you +; or your OS have problems with lots of files in one directory, and is +; a more efficient layout for servers that handle lots of sessions. +; +; NOTE 1: PHP will not create this directory structure automatically. +; You can use the script in the ext/session dir for that purpose. +; NOTE 2: See the section on garbage collection below if you choose to +; use subdirectories for session storage +; +; The file storage module creates files using mode 600 by default. +; You can change that by using +; +; session.save_path = "N;MODE;/path" +; +; where MODE is the octal representation of the mode. Note that this +; does not overwrite the process's umask. +; http://php.net/session.save-path +;session.save_path = "/tmp" + +; Whether to use cookies. +; http://php.net/session.use-cookies +session.use_cookies = 1 + +; http://php.net/session.cookie-secure +;session.cookie_secure = + +; This option forces PHP to fetch and use a cookie for storing and maintaining +; the session id. We encourage this operation as it's very helpful in combatting +; session hijacking when not specifying and managing your own session id. It is +; not the end all be all of session hijacking defense, but it's a good start. +; http://php.net/session.use-only-cookies +session.use_only_cookies = 1 + +; Name of the session (used as cookie name). +; http://php.net/session.name +session.name = PHPSESSID + +; Initialize session on request startup. +; http://php.net/session.auto-start +session.auto_start = 0 + +; Lifetime in seconds of cookie or, if 0, until browser is restarted. +; http://php.net/session.cookie-lifetime +session.cookie_lifetime = 0 + +; The path for which the cookie is valid. +; http://php.net/session.cookie-path +session.cookie_path = / + +; The domain for which the cookie is valid. +; http://php.net/session.cookie-domain +session.cookie_domain = + +; Whether or not to add the httpOnly flag to the cookie, which makes it inaccessible to browser scripting languages such as JavaScript. +; http://php.net/session.cookie-httponly +session.cookie_httponly = + +; Handler used to serialize data. php is the standard serializer of PHP. +; http://php.net/session.serialize-handler +session.serialize_handler = php + +; Defines the probability that the 'garbage collection' process is started +; on every session initialization. The probability is calculated by using +; gc_probability/gc_divisor. Where session.gc_probability is the numerator +; and gc_divisor is the denominator in the equation. Setting this value to 1 +; when the session.gc_divisor value is 100 will give you approximately a 1% chance +; the gc will run on any give request. +; Default Value: 1 +; Development Value: 1 +; Production Value: 1 +; http://php.net/session.gc-probability +session.gc_probability = 1 + +; Defines the probability that the 'garbage collection' process is started on every +; session initialization. The probability is calculated by using the following equation: +; gc_probability/gc_divisor. Where session.gc_probability is the numerator and +; session.gc_divisor is the denominator in the equation. Setting this value to 1 +; when the session.gc_divisor value is 100 will give you approximately a 1% chance +; the gc will run on any give request. Increasing this value to 1000 will give you +; a 0.1% chance the gc will run on any give request. For high volume production servers, +; this is a more efficient approach. +; Default Value: 100 +; Development Value: 1000 +; Production Value: 1000 +; http://php.net/session.gc-divisor +session.gc_divisor = 1000 + +; After this number of seconds, stored data will be seen as 'garbage' and +; cleaned up by the garbage collection process. +; http://php.net/session.gc-maxlifetime +session.gc_maxlifetime = 1440 + +; NOTE: If you are using the subdirectory option for storing session files +; (see session.save_path above), then garbage collection does *not* +; happen automatically. You will need to do your own garbage +; collection through a shell script, cron entry, or some other method. +; For example, the following script would is the equivalent of +; setting session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes): +; cd /path/to/sessions; find -cmin +24 | xargs rm + +; PHP 4.2 and less have an undocumented feature/bug that allows you to +; to initialize a session variable in the global scope, even when register_globals +; is disabled. PHP 4.3 and later will warn you, if this feature is used. +; You can disable the feature and the warning separately. At this time, +; the warning is only displayed, if bug_compat_42 is enabled. This feature +; introduces some serious security problems if not handled correctly. It's +; recommended that you do not use this feature on production servers. But you +; should enable this on development servers and enable the warning as well. If you +; do not enable the feature on development servers, you won't be warned when it's +; used and debugging errors caused by this can be difficult to track down. +; Default Value: On +; Development Value: On +; Production Value: Off +; http://php.net/session.bug-compat-42 +session.bug_compat_42 = Off + +; This setting controls whether or not you are warned by PHP when initializing a +; session value into the global space. session.bug_compat_42 must be enabled before +; these warnings can be issued by PHP. See the directive above for more information. +; Default Value: On +; Development Value: On +; Production Value: Off +; http://php.net/session.bug-compat-warn +session.bug_compat_warn = Off + +; Check HTTP Referer to invalidate externally stored URLs containing ids. +; HTTP_REFERER has to contain this substring for the session to be +; considered as valid. +; http://php.net/session.referer-check +session.referer_check = + +; How many bytes to read from the file. +; http://php.net/session.entropy-length +session.entropy_length = 0 + +; Specified here to create the session id. +; http://php.net/session.entropy-file +;session.entropy_file = /dev/urandom +session.entropy_file = + +; http://php.net/session.entropy-length +;session.entropy_length = 16 + +; Set to {nocache,private,public,} to determine HTTP caching aspects +; or leave this empty to avoid sending anti-caching headers. +; http://php.net/session.cache-limiter +session.cache_limiter = nocache + +; Document expires after n minutes. +; http://php.net/session.cache-expire +session.cache_expire = 180 + +; trans sid support is disabled by default. +; Use of trans sid may risk your users security. +; Use this option with caution. +; - User may send URL contains active session ID +; to other person via. email/irc/etc. +; - URL that contains active session ID may be stored +; in publically accessible computer. +; - User may access your site with the same session ID +; always using URL stored in browser's history or bookmarks. +; http://php.net/session.use-trans-sid +session.use_trans_sid = 0 + +; Select a hash function for use in generating session ids. +; Possible Values +; 0 (MD5 128 bits) +; 1 (SHA-1 160 bits) +; This option may also be set to the name of any hash function supported by +; the hash extension. A list of available hashes is returned by the hash_alogs() +; function. +; http://php.net/session.hash-function +session.hash_function = 0 + +; Define how many bits are stored in each character when converting +; the binary hash data to something readable. +; Possible values: +; 4 (4 bits: 0-9, a-f) +; 5 (5 bits: 0-9, a-v) +; 6 (6 bits: 0-9, a-z, A-Z, "-", ",") +; Default Value: 4 +; Development Value: 5 +; Production Value: 5 +; http://php.net/session.hash-bits-per-character +session.hash_bits_per_character = 5 + +; The URL rewriter will look for URLs in a defined set of HTML tags. +; form/fieldset are special; if you include them here, the rewriter will +; add a hidden field with the info which is otherwise appended +; to URLs. If you want XHTML conformity, remove the form entry. +; Note that all valid entries require a "=", even if no value follows. +; Default Value: "a=href,area=href,frame=src,form=,fieldset=" +; Development Value: "a=href,area=href,frame=src,input=src,form=fakeentry" +; Production Value: "a=href,area=href,frame=src,input=src,form=fakeentry" +; http://php.net/url-rewriter.tags +url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry" + +[MSSQL] +; Allow or prevent persistent links. +mssql.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +mssql.max_persistent = -1 + +; Maximum number of links (persistent+non persistent). -1 means no limit. +mssql.max_links = -1 + +; Minimum error severity to display. +mssql.min_error_severity = 10 + +; Minimum message severity to display. +mssql.min_message_severity = 10 + +; Compatibility mode with old versions of PHP 3.0. +mssql.compatability_mode = Off + +; Connect timeout +;mssql.connect_timeout = 5 + +; Query timeout +;mssql.timeout = 60 + +; Valid range 0 - 2147483647. Default = 4096. +;mssql.textlimit = 4096 + +; Valid range 0 - 2147483647. Default = 4096. +;mssql.textsize = 4096 + +; Limits the number of records in each batch. 0 = all records in one batch. +;mssql.batchsize = 0 + +; Specify how datetime and datetim4 columns are returned +; On => Returns data converted to SQL server settings +; Off => Returns values as YYYY-MM-DD hh:mm:ss +;mssql.datetimeconvert = On + +; Use NT authentication when connecting to the server +mssql.secure_connection = Off + +; Specify max number of processes. -1 = library default +; msdlib defaults to 25 +; FreeTDS defaults to 4096 +;mssql.max_procs = -1 + +; Specify client character set. +; If empty or not set the client charset from freetds.comf is used +; This is only used when compiled with FreeTDS +;mssql.charset = "ISO-8859-1" + +[Assertion] +; Assert(expr); active by default. +; http://php.net/assert.active +;assert.active = On + +; Issue a PHP warning for each failed assertion. +; http://php.net/assert.warning +;assert.warning = On + +; Don't bail out by default. +; http://php.net/assert.bail +;assert.bail = Off + +; User-function to be called if an assertion fails. +; http://php.net/assert.callback +;assert.callback = 0 + +; Eval the expression with current error_reporting(). Set to true if you want +; error_reporting(0) around the eval(). +; http://php.net/assert.quiet-eval +;assert.quiet_eval = 0 + +[COM] +; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs +; http://php.net/com.typelib-file +;com.typelib_file = + +; allow Distributed-COM calls +; http://php.net/com.allow-dcom +;com.allow_dcom = true + +; autoregister constants of a components typlib on com_load() +; http://php.net/com.autoregister-typelib +;com.autoregister_typelib = true + +; register constants casesensitive +; http://php.net/com.autoregister-casesensitive +;com.autoregister_casesensitive = false + +; show warnings on duplicate constant registrations +; http://php.net/com.autoregister-verbose +;com.autoregister_verbose = true + +; The default character set code-page to use when passing strings to and from COM objects. +; Default: system ANSI code page +;com.code_page= + +[mbstring] +; language for internal character representation. +; http://php.net/mbstring.language +;mbstring.language = Japanese + +; internal/script encoding. +; Some encoding cannot work as internal encoding. +; (e.g. SJIS, BIG5, ISO-2022-*) +; http://php.net/mbstring.internal-encoding +;mbstring.internal_encoding = EUC-JP + +; http input encoding. +; http://php.net/mbstring.http-input +;mbstring.http_input = auto + +; http output encoding. mb_output_handler must be +; registered as output buffer to function +; http://php.net/mbstring.http-output +;mbstring.http_output = SJIS + +; enable automatic encoding translation according to +; mbstring.internal_encoding setting. Input chars are +; converted to internal encoding by setting this to On. +; Note: Do _not_ use automatic encoding translation for +; portable libs/applications. +; http://php.net/mbstring.encoding-translation +;mbstring.encoding_translation = Off + +; automatic encoding detection order. +; auto means +; http://php.net/mbstring.detect-order +;mbstring.detect_order = auto + +; substitute_character used when character cannot be converted +; one from another +; http://php.net/mbstring.substitute-character +;mbstring.substitute_character = none; + +; overload(replace) single byte functions by mbstring functions. +; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(), +; etc. Possible values are 0,1,2,4 or combination of them. +; For example, 7 for overload everything. +; 0: No overload +; 1: Overload mail() function +; 2: Overload str*() functions +; 4: Overload ereg*() functions +; http://php.net/mbstring.func-overload +;mbstring.func_overload = 0 + +; enable strict encoding detection. +;mbstring.strict_detection = Off + +; This directive specifies the regex pattern of content types for which mb_output_handler() +; is activated. +; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml) +;mbstring.http_output_conv_mimetype= + +; Allows to set script encoding. Only affects if PHP is compiled with --enable-zend-multibyte +; Default: "" +;mbstring.script_encoding= + +[gd] +; Tell the jpeg decode to ignore warnings and try to create +; a gd image. The warning will then be displayed as notices +; disabled by default +; http://php.net/gd.jpeg-ignore-warning +;gd.jpeg_ignore_warning = 0 + +[exif] +; Exif UNICODE user comments are handled as UCS-2BE/UCS-2LE and JIS as JIS. +; With mbstring support this will automatically be converted into the encoding +; given by corresponding encode setting. When empty mbstring.internal_encoding +; is used. For the decode settings you can distinguish between motorola and +; intel byte order. A decode setting cannot be empty. +; http://php.net/exif.encode-unicode +;exif.encode_unicode = ISO-8859-15 + +; http://php.net/exif.decode-unicode-motorola +;exif.decode_unicode_motorola = UCS-2BE + +; http://php.net/exif.decode-unicode-intel +;exif.decode_unicode_intel = UCS-2LE + +; http://php.net/exif.encode-jis +;exif.encode_jis = + +; http://php.net/exif.decode-jis-motorola +;exif.decode_jis_motorola = JIS + +; http://php.net/exif.decode-jis-intel +;exif.decode_jis_intel = JIS + +[Tidy] +; The path to a default tidy configuration file to use when using tidy +; http://php.net/tidy.default-config +;tidy.default_config = /usr/local/lib/php/default.tcfg + +; Should tidy clean and repair output automatically? +; WARNING: Do not use this option if you are generating non-html content +; such as dynamic images +; http://php.net/tidy.clean-output +tidy.clean_output = Off + +[soap] +; Enables or disables WSDL caching feature. +; http://php.net/soap.wsdl-cache-enabled +soap.wsdl_cache_enabled=1 + +; Sets the directory name where SOAP extension will put cache files. +; http://php.net/soap.wsdl-cache-dir +soap.wsdl_cache_dir="/tmp" + +; (time to live) Sets the number of second while cached file will be used +; instead of original one. +; http://php.net/soap.wsdl-cache-ttl +soap.wsdl_cache_ttl=86400 + +; Sets the size of the cache limit. (Max. number of WSDL files to cache) +soap.wsdl_cache_limit = 5 + +[sysvshm] +; A default size of the shared memory segment +;sysvshm.init_mem = 10000 + +[ldap] +; Sets the maximum number of open links or -1 for unlimited. +ldap.max_links = -1 + +[mcrypt] +; For more information about mcrypt settings see http://php.net/mcrypt-module-open + +; Directory where to load mcrypt algorithms +; Default: Compiled in into libmcrypt (usually /usr/local/lib/libmcrypt) +;mcrypt.algorithms_dir= + +; Directory where to load mcrypt modes +; Default: Compiled in into libmcrypt (usually /usr/local/lib/libmcrypt) +;mcrypt.modes_dir= + +[dba] +;dba.default_handler= + +; Local Variables: +; tab-width: 4 +; End: + +<% @directives.sort_by { |key, val| key }.each do |directive, value| -%> +<%= "#{directive}=#{value}" %> +<% end -%> diff --git a/cookbooks/php/templates/default/extension.ini.erb b/cookbooks/php/templates/default/extension.ini.erb new file mode 100644 index 0000000..13c5122 --- /dev/null +++ b/cookbooks/php/templates/default/extension.ini.erb @@ -0,0 +1,7 @@ +; configuration for php <%= @name %> module +<% @extensions.each do |filepath, zend| -%> +<%= 'zend_' if zend %>extension=<%= filepath %> +<% end -%> +<% @directives.each do |k,v| -%> +<%= "#{@name}.#{k}=#{v}" %> +<% end -%> diff --git a/cookbooks/php/templates/default/fpm-pool.conf.erb b/cookbooks/php/templates/default/fpm-pool.conf.erb new file mode 100644 index 0000000..71ad207 --- /dev/null +++ b/cookbooks/php/templates/default/fpm-pool.conf.erb @@ -0,0 +1,15 @@ +[<%= @fpm_pool_name %>] +user = <%= @fpm_pool_user %> +group = <%= @fpm_pool_group %> +listen = <%= @fpm_pool_listen %> +listen.owner = <%= @fpm_pool_listen_user %> +listen.group = <%= @fpm_pool_listen_group %> +pm = <%= @fpm_pool_manager %> +pm.max_children = <%= @fpm_pool_max_children %> +pm.start_servers = <%= @fpm_pool_start_servers %> +pm.min_spare_servers = <%= @fpm_pool_min_spare_servers %> +pm.max_spare_servers = <%= @fpm_pool_max_spare_servers %> +chdir = <%= @fpm_pool_chdir %> +<% @fpm_pool_additional_config.each do |key, value| %> +<%= key %> = <%= value %> +<% end %> diff --git a/cookbooks/php/templates/default/php.ini.erb b/cookbooks/php/templates/default/php.ini.erb new file mode 100644 index 0000000..6c3f990 --- /dev/null +++ b/cookbooks/php/templates/default/php.ini.erb @@ -0,0 +1,1877 @@ +[PHP] + +;;;;;;;;;;;;;;;;;;; +; About php.ini ; +;;;;;;;;;;;;;;;;;;; +; PHP's initialization file, generally called php.ini, is responsible for +; configuring many of the aspects of PHP's behavior. + +; PHP attempts to find and load this configuration from a number of locations. +; The following is a summary of its search order: +; 1. SAPI module specific location. +; 2. The PHPRC environment variable. (As of PHP 5.2.0) +; 3. A number of predefined registry keys on Windows (As of PHP 5.2.0) +; 4. Current working directory (except CLI) +; 5. The web server's directory (for SAPI modules), or directory of PHP +; (otherwise in Windows) +; 6. The directory from the --with-config-file-path compile time option, or the +; Windows directory (C:\windows or C:\winnt) +; See the PHP docs for more specific information. +; http://php.net/configuration.file + +; The syntax of the file is extremely simple. Whitespace and Lines +; beginning with a semicolon are silently ignored (as you probably guessed). +; Section headers (e.g. [Foo]) are also silently ignored, even though +; they might mean something in the future. + +; Directives following the section heading [PATH=/www/mysite] only +; apply to PHP files in the /www/mysite directory. Directives +; following the section heading [HOST=www.example.com] only apply to +; PHP files served from www.example.com. Directives set in these +; special sections cannot be overridden by user-defined INI files or +; at runtime. Currently, [PATH=] and [HOST=] sections only work under +; CGI/FastCGI. +; http://php.net/ini.sections + +; Directives are specified using the following syntax: +; directive = value +; Directive names are *case sensitive* - foo=bar is different from FOO=bar. +; Directives are variables used to configure PHP or PHP extensions. +; There is no name validation. If PHP can't find an expected +; directive because it is not set or is mistyped, a default value will be used. + +; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one +; of the INI constants (On, Off, True, False, Yes, No and None) or an expression +; (e.g. E_ALL & ~E_NOTICE), a quoted string ("bar"), or a reference to a +; previously set variable or directive (e.g. ${foo}) + +; Expressions in the INI file are limited to bitwise operators and parentheses: +; | bitwise OR +; ^ bitwise XOR +; & bitwise AND +; ~ bitwise NOT +; ! boolean NOT + +; Boolean flags can be turned on using the values 1, On, True or Yes. +; They can be turned off using the values 0, Off, False or No. + +; An empty string can be denoted by simply not writing anything after the equal +; sign, or by using the None keyword: + +; foo = ; sets foo to an empty string +; foo = None ; sets foo to an empty string +; foo = "None" ; sets foo to the string 'None' + +; If you use constants in your value, and these constants belong to a +; dynamically loaded extension (either a PHP extension or a Zend extension), +; you may only use these constants *after* the line that loads the extension. + +;;;;;;;;;;;;;;;;;;; +; About this file ; +;;;;;;;;;;;;;;;;;;; +; PHP comes packaged with two INI files. One that is recommended to be used +; in production environments and one that is recommended to be used in +; development environments. + +; php.ini-production contains settings which hold security, performance and +; best practices at its core. But please be aware, these settings may break +; compatibility with older or less security conscience applications. We +; recommending using the production ini in production and testing environments. + +; php.ini-development is very similar to its production variant, except it's +; much more verbose when it comes to errors. We recommending using the +; development version only in development environments as errors shown to +; application users can inadvertently leak otherwise secure information. + +;;;;;;;;;;;;;;;;;;; +; Quick Reference ; +;;;;;;;;;;;;;;;;;;; +; The following are all the settings which are different in either the production +; or development versions of the INIs with respect to PHP's default behavior. +; Please see the actual settings later in the document for more details as to why +; we recommend these changes in PHP's behavior. + +; display_errors +; Default Value: On +; Development Value: On +; Production Value: Off + +; display_startup_errors +; Default Value: Off +; Development Value: On +; Production Value: Off + +; error_reporting +; Default Value: E_ALL & ~E_NOTICE +; Development Value: E_ALL | E_STRICT +; Production Value: E_ALL & ~E_DEPRECATED + +; html_errors +; Default Value: On +; Development Value: On +; Production value: Off + +; log_errors +; Default Value: Off +; Development Value: On +; Production Value: On + +; magic_quotes_gpc +; Default Value: On +; Development Value: Off +; Production Value: Off + +; max_input_time +; Default Value: -1 (Unlimited) +; Development Value: 60 (60 seconds) +; Production Value: 60 (60 seconds) + +; output_buffering +; Default Value: Off +; Development Value: 4096 +; Production Value: 4096 + +; register_argc_argv +; Default Value: On +; Development Value: Off +; Production Value: Off + +; register_long_arrays +; Default Value: On +; Development Value: Off +; Production Value: Off + +; request_order +; Default Value: None +; Development Value: "GP" +; Production Value: "GP" + +; session.bug_compat_42 +; Default Value: On +; Development Value: On +; Production Value: Off + +; session.bug_compat_warn +; Default Value: On +; Development Value: On +; Production Value: Off + +; session.gc_divisor +; Default Value: 100 +; Development Value: 1000 +; Production Value: 1000 + +; session.hash_bits_per_character +; Default Value: 4 +; Development Value: 5 +; Production Value: 5 + +; short_open_tag +; Default Value: On +; Development Value: Off +; Production Value: Off + +; track_errors +; Default Value: Off +; Development Value: On +; Production Value: Off + +; url_rewriter.tags +; Default Value: "a=href,area=href,frame=src,form=,fieldset=" +; Development Value: "a=href,area=href,frame=src,input=src,form=fakeentry" +; Production Value: "a=href,area=href,frame=src,input=src,form=fakeentry" + +; variables_order +; Default Value: "EGPCS" +; Development Value: "GPCS" +; Production Value: "GPCS" + +;;;;;;;;;;;;;;;;;;;; +; php.ini Options ; +;;;;;;;;;;;;;;;;;;;; +; Name for user-defined php.ini (.htaccess) files. Default is ".user.ini" +;user_ini.filename = ".user.ini" + +; To disable this feature set this option to empty value +;user_ini.filename = + +; TTL for user-defined php.ini files (time-to-live) in seconds. Default is 300 seconds (5 minutes) +;user_ini.cache_ttl = 300 + +;;;;;;;;;;;;;;;;;;;; +; Language Options ; +;;;;;;;;;;;;;;;;;;;; + +; Enable the PHP scripting language engine under Apache. +; http://php.net/engine +engine = On + +; This directive determines whether or not PHP will recognize code between +; tags as PHP source which should be processed as such. It's been +; recommended for several years that you not use the short tag "short cut" and +; instead to use the full tag combination. With the wide spread use +; of XML and use of these tags by other languages, the server can become easily +; confused and end up parsing the wrong code in the wrong context. But because +; this short cut has been a feature for such a long time, it's currently still +; supported for backwards compatibility, but we recommend you don't use them. +; Default Value: On +; Development Value: Off +; Production Value: Off +; http://php.net/short-open-tag +short_open_tag = Off + +; Allow ASP-style <% %> tags. +; http://php.net/asp-tags +asp_tags = Off + +; The number of significant digits displayed in floating point numbers. +; http://php.net/precision +precision = 14 + +; Output buffering is a mechanism for controlling how much output data +; (excluding headers and cookies) PHP should keep internally before pushing that +; data to the client. If your application's output exceeds this setting, PHP +; will send that data in chunks of roughly the size you specify. +; Turning on this setting and managing its maximum buffer size can yield some +; interesting side-effects depending on your application and web server. +; You may be able to send headers and cookies after you've already sent output +; through print or echo. You also may see performance benefits if your server is +; emitting less packets due to buffered output versus PHP streaming the output +; as it gets it. On production servers, 4096 bytes is a good setting for performance +; reasons. +; Note: Output buffering can also be controlled via Output Buffering Control +; functions. +; Possible Values: +; On = Enabled and buffer is unlimited. (Use with caution) +; Off = Disabled +; Integer = Enables the buffer and sets its maximum size in bytes. +; Note: This directive is hardcoded to Off for the CLI SAPI +; Default Value: Off +; Development Value: 4096 +; Production Value: 4096 +; http://php.net/output-buffering +output_buffering = 4096 + +; You can redirect all of the output of your scripts to a function. For +; example, if you set output_handler to "mb_output_handler", character +; encoding will be transparently converted to the specified encoding. +; Setting any output handler automatically turns on output buffering. +; Note: People who wrote portable scripts should not depend on this ini +; directive. Instead, explicitly set the output handler using ob_start(). +; Using this ini directive may cause problems unless you know what script +; is doing. +; Note: You cannot use both "mb_output_handler" with "ob_iconv_handler" +; and you cannot use both "ob_gzhandler" and "zlib.output_compression". +; Note: output_handler must be empty if this is set 'On' !!!! +; Instead you must use zlib.output_handler. +; http://php.net/output-handler +;output_handler = + +; Transparent output compression using the zlib library +; Valid values for this option are 'off', 'on', or a specific buffer size +; to be used for compression (default is 4KB) +; Note: Resulting chunk size may vary due to nature of compression. PHP +; outputs chunks that are few hundreds bytes each as a result of +; compression. If you prefer a larger chunk size for better +; performance, enable output_buffering in addition. +; Note: You need to use zlib.output_handler instead of the standard +; output_handler, or otherwise the output will be corrupted. +; http://php.net/zlib.output-compression +zlib.output_compression = Off + +; http://php.net/zlib.output-compression-level +;zlib.output_compression_level = -1 + +; You cannot specify additional output handlers if zlib.output_compression +; is activated here. This setting does the same as output_handler but in +; a different order. +; http://php.net/zlib.output-handler +;zlib.output_handler = + +; Implicit flush tells PHP to tell the output layer to flush itself +; automatically after every output block. This is equivalent to calling the +; PHP function flush() after each and every call to print() or echo() and each +; and every HTML block. Turning this option on has serious performance +; implications and is generally recommended for debugging purposes only. +; http://php.net/implicit-flush +; Note: This directive is hardcoded to On for the CLI SAPI +implicit_flush = Off + +; The unserialize callback function will be called (with the undefined class' +; name as parameter), if the unserializer finds an undefined class +; which should be instantiated. A warning appears if the specified function is +; not defined, or if the function doesn't include/implement the missing class. +; So only set this entry, if you really want to implement such a +; callback-function. +unserialize_callback_func = + +; When floats & doubles are serialized store serialize_precision significant +; digits after the floating point. The default value ensures that when floats +; are decoded with unserialize, the data will remain the same. +serialize_precision = 100 + +; Safe Mode +; http://php.net/safe-mode +safe_mode = Off + +; By default, Safe Mode does a UID compare check when +; opening files. If you want to relax this to a GID compare, +; then turn on safe_mode_gid. +; http://php.net/safe-mode-gid +safe_mode_gid = Off + +; When safe_mode is on, UID/GID checks are bypassed when +; including files from this directory and its subdirectories. +; (directory must also be in include_path or full path must +; be used when including) +; http://php.net/safe-mode-include-dir +safe_mode_include_dir = + +; When safe_mode is on, only executables located in the safe_mode_exec_dir +; will be allowed to be executed via the exec family of functions. +; http://php.net/safe-mode-exec-dir +safe_mode_exec_dir = + +; Setting certain environment variables may be a potential security breach. +; This directive contains a comma-delimited list of prefixes. In Safe Mode, +; the user may only alter environment variables whose names begin with the +; prefixes supplied here. By default, users will only be able to set +; environment variables that begin with PHP_ (e.g. PHP_FOO=BAR). +; Note: If this directive is empty, PHP will let the user modify ANY +; environment variable! +; http://php.net/safe-mode-allowed-env-vars +safe_mode_allowed_env_vars = PHP_ + +; This directive contains a comma-delimited list of environment variables that +; the end user won't be able to change using putenv(). These variables will be +; protected even if safe_mode_allowed_env_vars is set to allow to change them. +; http://php.net/safe-mode-protected-env-vars +safe_mode_protected_env_vars = LD_LIBRARY_PATH + +; open_basedir, if set, limits all file operations to the defined directory +; and below. This directive makes most sense if used in a per-directory +; or per-virtualhost web server configuration file. This directive is +; *NOT* affected by whether Safe Mode is turned On or Off. +; http://php.net/open-basedir +;open_basedir = + +; This directive allows you to disable certain functions for security reasons. +; It receives a comma-delimited list of function names. This directive is +; *NOT* affected by whether Safe Mode is turned On or Off. +; http://php.net/disable-functions +disable_functions = + +; This directive allows you to disable certain classes for security reasons. +; It receives a comma-delimited list of class names. This directive is +; *NOT* affected by whether Safe Mode is turned On or Off. +; http://php.net/disable-classes +disable_classes = + +; Colors for Syntax Highlighting mode. Anything that's acceptable in +; would work. +; http://php.net/syntax-highlighting +;highlight.string = #DD0000 +;highlight.comment = #FF9900 +;highlight.keyword = #007700 +;highlight.bg = #FFFFFF +;highlight.default = #0000BB +;highlight.html = #000000 + +; If enabled, the request will be allowed to complete even if the user aborts +; the request. Consider enabling it if executing long requests, which may end up +; being interrupted by the user or a browser timing out. PHP's default behavior +; is to disable this feature. +; http://php.net/ignore-user-abort +;ignore_user_abort = On + +; Determines the size of the realpath cache to be used by PHP. This value should +; be increased on systems where PHP opens many files to reflect the quantity of +; the file operations performed. +; http://php.net/realpath-cache-size +;realpath_cache_size = 16k + +; Duration of time, in seconds for which to cache realpath information for a given +; file or directory. For systems with rarely changing files, consider increasing this +; value. +; http://php.net/realpath-cache-ttl +;realpath_cache_ttl = 120 + +;;;;;;;;;;;;;;;;; +; Miscellaneous ; +;;;;;;;;;;;;;;;;; + +; Decides whether PHP may expose the fact that it is installed on the server +; (e.g. by adding its signature to the Web server header). It is no security +; threat in any way, but it makes it possible to determine whether you use PHP +; on your server or not. +; http://php.net/expose-php +expose_php = On + +;;;;;;;;;;;;;;;;;;; +; Resource Limits ; +;;;;;;;;;;;;;;;;;;; + +; Maximum execution time of each script, in seconds +; http://php.net/max-execution-time +; Note: This directive is hardcoded to 0 for the CLI SAPI +max_execution_time = 30 + +; Maximum amount of time each script may spend parsing request data. It's a good +; idea to limit this time on productions servers in order to eliminate unexpectedly +; long running scripts. +; Note: This directive is hardcoded to -1 for the CLI SAPI +; Default Value: -1 (Unlimited) +; Development Value: 60 (60 seconds) +; Production Value: 60 (60 seconds) +; http://php.net/max-input-time +max_input_time = 60 + +; Maximum input variable nesting level +; http://php.net/max-input-nesting-level +;max_input_nesting_level = 64 + +; Maximum amount of memory a script may consume (128MB) +; http://php.net/memory-limit +memory_limit = 128M + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Error handling and logging ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; This directive informs PHP of which errors, warnings and notices you would like +; it to take action for. The recommended way of setting values for this +; directive is through the use of the error level constants and bitwise +; operators. The error level constants are below here for convenience as well as +; some common settings and their meanings. +; By default, PHP is set to take action on all errors, notices and warnings EXCEPT +; those related to E_NOTICE and E_STRICT, which together cover best practices and +; recommended coding standards in PHP. For performance reasons, this is the +; recommend error reporting setting. Your production server shouldn't be wasting +; resources complaining about best practices and coding standards. That's what +; development servers and development settings are for. +; Note: The php.ini-development file has this setting as E_ALL | E_STRICT. This +; means it pretty much reports everything which is exactly what you want during +; development and early testing. +; +; Error Level Constants: +; E_ALL - All errors and warnings (includes E_STRICT as of PHP 6.0.0) +; E_ERROR - fatal run-time errors +; E_RECOVERABLE_ERROR - almost fatal run-time errors +; E_WARNING - run-time warnings (non-fatal errors) +; E_PARSE - compile-time parse errors +; E_NOTICE - run-time notices (these are warnings which often result +; from a bug in your code, but it's possible that it was +; intentional (e.g., using an uninitialized variable and +; relying on the fact it's automatically initialized to an +; empty string) +; E_STRICT - run-time notices, enable to have PHP suggest changes +; to your code which will ensure the best interoperability +; and forward compatibility of your code +; E_CORE_ERROR - fatal errors that occur during PHP's initial startup +; E_CORE_WARNING - warnings (non-fatal errors) that occur during PHP's +; initial startup +; E_COMPILE_ERROR - fatal compile-time errors +; E_COMPILE_WARNING - compile-time warnings (non-fatal errors) +; E_USER_ERROR - user-generated error message +; E_USER_WARNING - user-generated warning message +; E_USER_NOTICE - user-generated notice message +; E_DEPRECATED - warn about code that will not work in future versions +; of PHP +; E_USER_DEPRECATED - user-generated deprecation warnings +; +; Common Values: +; E_ALL & ~E_NOTICE (Show all errors, except for notices and coding standards warnings.) +; E_ALL & ~E_NOTICE | E_STRICT (Show all errors, except for notices) +; E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR (Show only errors) +; E_ALL | E_STRICT (Show all errors, warnings and notices including coding standards.) +; Default Value: E_ALL & ~E_NOTICE +; Development Value: E_ALL | E_STRICT +; Production Value: E_ALL & ~E_DEPRECATED +; http://php.net/error-reporting +error_reporting = E_ALL & ~E_DEPRECATED + +; This directive controls whether or not and where PHP will output errors, +; notices and warnings too. Error output is very useful during development, but +; it could be very dangerous in production environments. Depending on the code +; which is triggering the error, sensitive information could potentially leak +; out of your application such as database usernames and passwords or worse. +; It's recommended that errors be logged on production servers rather than +; having the errors sent to STDOUT. +; Possible Values: +; Off = Do not display any errors +; stderr = Display errors to STDERR (affects only CGI/CLI binaries!) +; On or stdout = Display errors to STDOUT +; Default Value: On +; Development Value: On +; Production Value: Off +; http://php.net/display-errors +display_errors = Off + +; The display of errors which occur during PHP's startup sequence are handled +; separately from display_errors. PHP's default behavior is to suppress those +; errors from clients. Turning the display of startup errors on can be useful in +; debugging configuration problems. But, it's strongly recommended that you +; leave this setting off on production servers. +; Default Value: Off +; Development Value: On +; Production Value: Off +; http://php.net/display-startup-errors +display_startup_errors = Off + +; Besides displaying errors, PHP can also log errors to locations such as a +; server-specific log, STDERR, or a location specified by the error_log +; directive found below. While errors should not be displayed on productions +; servers they should still be monitored and logging is a great way to do that. +; Default Value: Off +; Development Value: On +; Production Value: On +; http://php.net/log-errors +log_errors = On + +; Set maximum length of log_errors. In error_log information about the source is +; added. The default is 1024 and 0 allows to not apply any maximum length at all. +; http://php.net/log-errors-max-len +log_errors_max_len = 1024 + +; Do not log repeated messages. Repeated errors must occur in same file on same +; line unless ignore_repeated_source is set true. +; http://php.net/ignore-repeated-errors +ignore_repeated_errors = Off + +; Ignore source of message when ignoring repeated messages. When this setting +; is On you will not log errors with repeated messages from different files or +; source lines. +; http://php.net/ignore-repeated-source +ignore_repeated_source = Off + +; If this parameter is set to Off, then memory leaks will not be shown (on +; stdout or in the log). This has only effect in a debug compile, and if +; error reporting includes E_WARNING in the allowed list +; http://php.net/report-memleaks +report_memleaks = On + +; This setting is on by default. +;report_zend_debug = 0 + +; Store the last error/warning message in $php_errormsg (boolean). Setting this value +; to On can assist in debugging and is appropriate for development servers. It should +; however be disabled on production servers. +; Default Value: Off +; Development Value: On +; Production Value: Off +; http://php.net/track-errors +track_errors = Off + +; Turn off normal error reporting and emit XML-RPC error XML +; http://php.net/xmlrpc-errors +;xmlrpc_errors = 0 + +; An XML-RPC faultCode +;xmlrpc_error_number = 0 + +; When PHP displays or logs an error, it has the capability of inserting html +; links to documentation related to that error. This directive controls whether +; those HTML links appear in error messages or not. For performance and security +; reasons, it's recommended you disable this on production servers. +; Note: This directive is hardcoded to Off for the CLI SAPI +; Default Value: On +; Development Value: On +; Production value: Off +; http://php.net/html-errors +html_errors = Off + +; If html_errors is set On PHP produces clickable error messages that direct +; to a page describing the error or function causing the error in detail. +; You can download a copy of the PHP manual from http://php.net/docs +; and change docref_root to the base URL of your local copy including the +; leading '/'. You must also specify the file extension being used including +; the dot. PHP's default behavior is to leave these settings empty. +; Note: Never use this feature for production boxes. +; http://php.net/docref-root +; Examples +;docref_root = "/phpmanual/" + +; http://php.net/docref-ext +;docref_ext = .html + +; String to output before an error message. PHP's default behavior is to leave +; this setting blank. +; http://php.net/error-prepend-string +; Example: +;error_prepend_string = "" + +; String to output after an error message. PHP's default behavior is to leave +; this setting blank. +; http://php.net/error-append-string +; Example: +;error_append_string = "" + +; Log errors to specified file. PHP's default behavior is to leave this value +; empty. +; http://php.net/error-log +; Example: +;error_log = php_errors.log +; Log errors to syslog (Event Log on NT, not valid in Windows 95). +;error_log = syslog + +;;;;;;;;;;;;;;;;; +; Data Handling ; +;;;;;;;;;;;;;;;;; + +; The separator used in PHP generated URLs to separate arguments. +; PHP's default setting is "&". +; http://php.net/arg-separator.output +; Example: +;arg_separator.output = "&" + +; List of separator(s) used by PHP to parse input URLs into variables. +; PHP's default setting is "&". +; NOTE: Every character in this directive is considered as separator! +; http://php.net/arg-separator.input +; Example: +;arg_separator.input = ";&" + +; This directive determines which super global arrays are registered when PHP +; starts up. If the register_globals directive is enabled, it also determines +; what order variables are populated into the global space. G,P,C,E & S are +; abbreviations for the following respective super globals: GET, POST, COOKIE, +; ENV and SERVER. There is a performance penalty paid for the registration of +; these arrays and because ENV is not as commonly used as the others, ENV is +; is not recommended on productions servers. You can still get access to +; the environment variables through getenv() should you need to. +; Default Value: "EGPCS" +; Development Value: "GPCS" +; Production Value: "GPCS"; +; http://php.net/variables-order +variables_order = "GPCS" + +; This directive determines which super global data (G,P,C,E & S) should +; be registered into the super global array REQUEST. If so, it also determines +; the order in which that data is registered. The values for this directive are +; specified in the same manner as the variables_order directive, EXCEPT one. +; Leaving this value empty will cause PHP to use the value set in the +; variables_order directive. It does not mean it will leave the super globals +; array REQUEST empty. +; Default Value: None +; Development Value: "GP" +; Production Value: "GP" +; http://php.net/request-order +request_order = "GP" + +; Whether or not to register the EGPCS variables as global variables. You may +; want to turn this off if you don't want to clutter your scripts' global scope +; with user data. +; You should do your best to write your scripts so that they do not require +; register_globals to be on; Using form variables as globals can easily lead +; to possible security problems, if the code is not very well thought of. +; http://php.net/register-globals +register_globals = Off + +; Determines whether the deprecated long $HTTP_*_VARS type predefined variables +; are registered by PHP or not. As they are deprecated, we obviously don't +; recommend you use them. They are on by default for compatibility reasons but +; they are not recommended on production servers. +; Default Value: On +; Development Value: Off +; Production Value: Off +; http://php.net/register-long-arrays +register_long_arrays = Off + +; This directive determines whether PHP registers $argv & $argc each time it +; runs. $argv contains an array of all the arguments passed to PHP when a script +; is invoked. $argc contains an integer representing the number of arguments +; that were passed when the script was invoked. These arrays are extremely +; useful when running scripts from the command line. When this directive is +; enabled, registering these variables consumes CPU cycles and memory each time +; a script is executed. For performance reasons, this feature should be disabled +; on production servers. +; Note: This directive is hardcoded to On for the CLI SAPI +; Default Value: On +; Development Value: Off +; Production Value: Off +; http://php.net/register-argc-argv +register_argc_argv = Off + +; When enabled, the SERVER and ENV variables are created when they're first +; used (Just In Time) instead of when the script starts. If these variables +; are not used within a script, having this directive on will result in a +; performance gain. The PHP directives register_globals, register_long_arrays, +; and register_argc_argv must be disabled for this directive to have any affect. +; http://php.net/auto-globals-jit +auto_globals_jit = On + +; Maximum size of POST data that PHP will accept. +; http://php.net/post-max-size +post_max_size = 8M + +; Magic quotes are a preprocessing feature of PHP where PHP will attempt to +; escape any character sequences in GET, POST, COOKIE and ENV data which might +; otherwise corrupt data being placed in resources such as databases before +; making that data available to you. Because of character encoding issues and +; non-standard SQL implementations across many databases, it's not currently +; possible for this feature to be 100% accurate. PHP's default behavior is to +; enable the feature. We strongly recommend you use the escaping mechanisms +; designed specifically for the database your using instead of relying on this +; feature. Also note, this feature has been deprecated as of PHP 5.3.0 and is +; scheduled for removal in PHP 6. +; Default Value: On +; Development Value: Off +; Production Value: Off +; http://php.net/magic-quotes-gpc +magic_quotes_gpc = Off + +; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc. +; http://php.net/magic-quotes-runtime +magic_quotes_runtime = Off + +; Use Sybase-style magic quotes (escape ' with '' instead of \'). +; http://php.net/magic-quotes-sybase +magic_quotes_sybase = Off + +; Automatically add files before PHP document. +; http://php.net/auto-prepend-file +auto_prepend_file = + +; Automatically add files after PHP document. +; http://php.net/auto-append-file +auto_append_file = + +; By default, PHP will output a character encoding using +; the Content-type: header. To disable sending of the charset, simply +; set it to be empty. +; +; PHP's built-in default is text/html +; http://php.net/default-mimetype +default_mimetype = "text/html" + +; PHP's default character set is set to empty. +; http://php.net/default-charset +;default_charset = "iso-8859-1" + +; Always populate the $HTTP_RAW_POST_DATA variable. PHP's default behavior is +; to disable this feature. +; http://php.net/always-populate-raw-post-data +;always_populate_raw_post_data = On + +;;;;;;;;;;;;;;;;;;;;;;;;; +; Paths and Directories ; +;;;;;;;;;;;;;;;;;;;;;;;;; + +; UNIX: "/path1:/path2" +;include_path = ".:/php/includes" +; +; Windows: "\path1;\path2" +;include_path = ".;c:\php\includes" +; +; PHP's default setting for include_path is ".;/path/to/php/pear" +; http://php.net/include-path + +; The root of the PHP pages, used only if nonempty. +; if PHP was not compiled with FORCE_REDIRECT, you SHOULD set doc_root +; if you are running php as a CGI under any web server (other than IIS) +; see documentation for security issues. The alternate is to use the +; cgi.force_redirect configuration below +; http://php.net/doc-root +doc_root = + +; The directory under which PHP opens the script using /~username used only +; if nonempty. +; http://php.net/user-dir +user_dir = + +; Directory in which the loadable extensions (modules) reside. +; http://php.net/extension-dir +; extension_dir = "./" +; On windows: +; extension_dir = "ext" + +; Whether or not to enable the dl() function. The dl() function does NOT work +; properly in multithreaded servers, such as IIS or Zeus, and is automatically +; disabled on them. +; http://php.net/enable-dl +enable_dl = Off + +; cgi.force_redirect is necessary to provide security running PHP as a CGI under +; most web servers. Left undefined, PHP turns this on by default. You can +; turn it off here AT YOUR OWN RISK +; **You CAN safely turn this off for IIS, in fact, you MUST.** +; http://php.net/cgi.force-redirect +;cgi.force_redirect = 1 + +; if cgi.nph is enabled it will force cgi to always sent Status: 200 with +; every request. PHP's default behavior is to disable this feature. +;cgi.nph = 1 + +; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape +; (iPlanet) web servers, you MAY need to set an environment variable name that PHP +; will look for to know it is OK to continue execution. Setting this variable MAY +; cause security issues, KNOW WHAT YOU ARE DOING FIRST. +; http://php.net/cgi.redirect-status-env +;cgi.redirect_status_env = ; + +; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's +; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok +; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting +; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting +; of zero causes PHP to behave as before. Default is 1. You should fix your scripts +; to use SCRIPT_FILENAME rather than PATH_TRANSLATED. +; http://php.net/cgi.fix-pathinfo +;cgi.fix_pathinfo=1 + +; FastCGI under IIS (on WINNT based OS) supports the ability to impersonate +; security tokens of the calling client. This allows IIS to define the +; security context that the request runs under. mod_fastcgi under Apache +; does not currently support this feature (03/17/2002) +; Set to 1 if running under IIS. Default is zero. +; http://php.net/fastcgi.impersonate +;fastcgi.impersonate = 1; + +; Disable logging through FastCGI connection. PHP's default behavior is to enable +; this feature. +;fastcgi.logging = 0 + +; cgi.rfc2616_headers configuration option tells PHP what type of headers to +; use when sending HTTP response code. If it's set 0 PHP sends Status: header that +; is supported by Apache. When this option is set to 1 PHP will send +; RFC2616 compliant header. +; Default is zero. +; http://php.net/cgi.rfc2616-headers +;cgi.rfc2616_headers = 0 + +;;;;;;;;;;;;;;;; +; File Uploads ; +;;;;;;;;;;;;;;;; + +; Whether to allow HTTP file uploads. +; http://php.net/file-uploads +file_uploads = On + +; Temporary directory for HTTP uploaded files (will use system default if not +; specified). +; http://php.net/upload-tmp-dir +;upload_tmp_dir = + +; Maximum allowed size for uploaded files. +; http://php.net/upload-max-filesize +upload_max_filesize = 2M + +; Maximum number of files that can be uploaded via a single request +max_file_uploads = 20 + +;;;;;;;;;;;;;;;;;; +; Fopen wrappers ; +;;;;;;;;;;;;;;;;;; + +; Whether to allow the treatment of URLs (like http:// or ftp://) as files. +; http://php.net/allow-url-fopen +allow_url_fopen = On + +; Whether to allow include/require to open URLs (like http:// or ftp://) as files. +; http://php.net/allow-url-include +allow_url_include = Off + +; Define the anonymous ftp password (your email address). PHP's default setting +; for this is empty. +; http://php.net/from +;from="john@doe.com" + +; Define the User-Agent string. PHP's default setting for this is empty. +; http://php.net/user-agent +;user_agent="PHP" + +; Default timeout for socket based streams (seconds) +; http://php.net/default-socket-timeout +default_socket_timeout = 60 + +; If your scripts have to deal with files from Macintosh systems, +; or you are running on a Mac and need to deal with files from +; unix or win32 systems, setting this flag will cause PHP to +; automatically detect the EOL character in those files so that +; fgets() and file() will work regardless of the source of the file. +; http://php.net/auto-detect-line-endings +;auto_detect_line_endings = Off + +;;;;;;;;;;;;;;;;;;;;;; +; Dynamic Extensions ; +;;;;;;;;;;;;;;;;;;;;;; + +; If you wish to have an extension loaded automatically, use the following +; syntax: +; +; extension=modulename.extension +; +; For example, on Windows: +; +; extension=msql.dll +; +; ... or under UNIX: +; +; extension=msql.so +; +; ... or with a path: +; +; extension=/path/to/extension/msql.so +; +; If you only provide the name of the extension, PHP will look for it in its +; default extension directory. +; +; Windows Extensions +; Note that ODBC support is built in, so no dll is needed for it. +; Note that many DLL files are located in the extensions/ (PHP 4) ext/ (PHP 5) +; extension folders as well as the separate PECL DLL download (PHP 5). +; Be sure to appropriately set the extension_dir directive. +; +;extension=php_bz2.dll +;extension=php_curl.dll +;extension=php_fileinfo.dll +;extension=php_gd2.dll +;extension=php_gettext.dll +;extension=php_gmp.dll +;extension=php_intl.dll +;extension=php_imap.dll +;extension=php_interbase.dll +;extension=php_ldap.dll +;extension=php_mbstring.dll +;extension=php_exif.dll ; Must be after mbstring as it depends on it +;extension=php_mysql.dll +;extension=php_mysqli.dll +;extension=php_oci8.dll ; Use with Oracle 10gR2 Instant Client +;extension=php_oci8_11g.dll ; Use with Oracle 11g Instant Client +;extension=php_openssl.dll +;extension=php_pdo_firebird.dll +;extension=php_pdo_mssql.dll +;extension=php_pdo_mysql.dll +;extension=php_pdo_oci.dll +;extension=php_pdo_odbc.dll +;extension=php_pdo_pgsql.dll +;extension=php_pdo_sqlite.dll +;extension=php_pgsql.dll +;extension=php_pspell.dll +;extension=php_shmop.dll +;extension=php_snmp.dll +;extension=php_soap.dll +;extension=php_sockets.dll +;extension=php_sqlite.dll +;extension=php_sqlite3.dll +;extension=php_sybase_ct.dll +;extension=php_tidy.dll +;extension=php_xmlrpc.dll +;extension=php_xsl.dll +;extension=php_zip.dll + +;;;;;;;;;;;;;;;;;;; +; Module Settings ; +;;;;;;;;;;;;;;;;;;; + +[Date] +; Defines the default timezone used by the date functions +; http://php.net/date.timezone +;date.timezone = + +; http://php.net/date.default-latitude +;date.default_latitude = 31.7667 + +; http://php.net/date.default-longitude +;date.default_longitude = 35.2333 + +; http://php.net/date.sunrise-zenith +;date.sunrise_zenith = 90.583333 + +; http://php.net/date.sunset-zenith +;date.sunset_zenith = 90.583333 + +[filter] +; http://php.net/filter.default +;filter.default = unsafe_raw + +; http://php.net/filter.default-flags +;filter.default_flags = + +[iconv] +;iconv.input_encoding = ISO-8859-1 +;iconv.internal_encoding = ISO-8859-1 +;iconv.output_encoding = ISO-8859-1 + +[intl] +;intl.default_locale = +; This directive allows you to produce PHP errors when some error +; happens within intl functions. The value is the level of the error produced. +; Default is 0, which does not produce any errors. +;intl.error_level = E_WARNING + +[sqlite] +; http://php.net/sqlite.assoc-case +;sqlite.assoc_case = 0 + +[sqlite3] +;sqlite3.extension_dir = + +[Pcre] +;PCRE library backtracking limit. +; http://php.net/pcre.backtrack-limit +;pcre.backtrack_limit=100000 + +;PCRE library recursion limit. +;Please note that if you set this value to a high number you may consume all +;the available process stack and eventually crash PHP (due to reaching the +;stack size limit imposed by the Operating System). +; http://php.net/pcre.recursion-limit +;pcre.recursion_limit=100000 + +[Pdo] +; Whether to pool ODBC connections. Can be one of "strict", "relaxed" or "off" +; http://php.net/pdo-odbc.connection-pooling +;pdo_odbc.connection_pooling=strict + +;pdo_odbc.db2_instance_name + +[Pdo_mysql] +; If mysqlnd is used: Number of cache slots for the internal result set cache +; http://php.net/pdo_mysql.cache_size +pdo_mysql.cache_size = 2000 + +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +; http://php.net/pdo_mysql.default-socket +pdo_mysql.default_socket= + +[Phar] +; http://php.net/phar.readonly +;phar.readonly = On + +; http://php.net/phar.require-hash +;phar.require_hash = On + +;phar.cache_list = + +[Syslog] +; Whether or not to define the various syslog variables (e.g. $LOG_PID, +; $LOG_CRON, etc.). Turning it off is a good idea performance-wise. In +; runtime, you can define these variables by calling define_syslog_variables(). +; http://php.net/define-syslog-variables +define_syslog_variables = Off + +[mail function] +; For Win32 only. +; http://php.net/smtp +SMTP = localhost +; http://php.net/smtp-port +smtp_port = 25 + +; For Win32 only. +; http://php.net/sendmail-from +;sendmail_from = me@example.com + +; For Unix only. You may supply arguments as well (default: "sendmail -t -i"). +; http://php.net/sendmail-path +;sendmail_path = + +; Force the addition of the specified parameters to be passed as extra parameters +; to the sendmail binary. These parameters will always replace the value of +; the 5th parameter to mail(), even in safe mode. +;mail.force_extra_parameters = + +; Add X-PHP-Originating-Script: that will include uid of the script followed by the filename +mail.add_x_header = On + +; The path to a log file that will log all mail() calls. Log entries include +; the full path of the script, line number, To address and headers. +;mail.log = + +[SQL] +; http://php.net/sql.safe-mode +sql.safe_mode = Off + +[ODBC] +; http://php.net/odbc.default-db +;odbc.default_db = Not yet implemented + +; http://php.net/odbc.default-user +;odbc.default_user = Not yet implemented + +; http://php.net/odbc.default-pw +;odbc.default_pw = Not yet implemented + +; Controls the ODBC cursor model. +; Default: SQL_CURSOR_STATIC (default). +;odbc.default_cursortype + +; Allow or prevent persistent links. +; http://php.net/odbc.allow-persistent +odbc.allow_persistent = On + +; Check that a connection is still valid before reuse. +; http://php.net/odbc.check-persistent +odbc.check_persistent = On + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/odbc.max-persistent +odbc.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +; http://php.net/odbc.max-links +odbc.max_links = -1 + +; Handling of LONG fields. Returns number of bytes to variables. 0 means +; passthru. +; http://php.net/odbc.defaultlrl +odbc.defaultlrl = 4096 + +; Handling of binary data. 0 means passthru, 1 return as is, 2 convert to char. +; See the documentation on odbc_binmode and odbc_longreadlen for an explanation +; of odbc.defaultlrl and odbc.defaultbinmode +; http://php.net/odbc.defaultbinmode +odbc.defaultbinmode = 1 + +;birdstep.max_links = -1 + +[Interbase] +; Allow or prevent persistent links. +ibase.allow_persistent = 1 + +; Maximum number of persistent links. -1 means no limit. +ibase.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +ibase.max_links = -1 + +; Default database name for ibase_connect(). +;ibase.default_db = + +; Default username for ibase_connect(). +;ibase.default_user = + +; Default password for ibase_connect(). +;ibase.default_password = + +; Default charset for ibase_connect(). +;ibase.default_charset = + +; Default timestamp format. +ibase.timestampformat = "%Y-%m-%d %H:%M:%S" + +; Default date format. +ibase.dateformat = "%Y-%m-%d" + +; Default time format. +ibase.timeformat = "%H:%M:%S" + +[MySQL] +; Allow accessing, from PHP's perspective, local files with LOAD DATA statements +; http://php.net/mysql.allow_local_infile +mysql.allow_local_infile = On + +; Allow or prevent persistent links. +; http://php.net/mysql.allow-persistent +mysql.allow_persistent = On + +; If mysqlnd is used: Number of cache slots for the internal result set cache +; http://php.net/mysql.cache_size +mysql.cache_size = 2000 + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/mysql.max-persistent +mysql.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +; http://php.net/mysql.max-links +mysql.max_links = -1 + +; Default port number for mysql_connect(). If unset, mysql_connect() will use +; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the +; compile-time value defined MYSQL_PORT (in that order). Win32 will only look +; at MYSQL_PORT. +; http://php.net/mysql.default-port +mysql.default_port = + +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +; http://php.net/mysql.default-socket +mysql.default_socket = + +; Default host for mysql_connect() (doesn't apply in safe mode). +; http://php.net/mysql.default-host +mysql.default_host = + +; Default user for mysql_connect() (doesn't apply in safe mode). +; http://php.net/mysql.default-user +mysql.default_user = + +; Default password for mysql_connect() (doesn't apply in safe mode). +; Note that this is generally a *bad* idea to store passwords in this file. +; *Any* user with PHP access can run 'echo get_cfg_var("mysql.default_password") +; and reveal this password! And of course, any users with read access to this +; file will be able to reveal the password as well. +; http://php.net/mysql.default-password +mysql.default_password = + +; Maximum time (in seconds) for connect timeout. -1 means no limit +; http://php.net/mysql.connect-timeout +mysql.connect_timeout = 60 + +; Trace mode. When trace_mode is active (=On), warnings for table/index scans and +; SQL-Errors will be displayed. +; http://php.net/mysql.trace-mode +mysql.trace_mode = Off + +[MySQLi] + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/mysqli.max-persistent +mysqli.max_persistent = -1 + +; Allow accessing, from PHP's perspective, local files with LOAD DATA statements +; http://php.net/mysqli.allow_local_infile +;mysqli.allow_local_infile = On + +; Allow or prevent persistent links. +; http://php.net/mysqli.allow-persistent +mysqli.allow_persistent = On + +; Maximum number of links. -1 means no limit. +; http://php.net/mysqli.max-links +mysqli.max_links = -1 + +; If mysqlnd is used: Number of cache slots for the internal result set cache +; http://php.net/mysqli.cache_size +mysqli.cache_size = 2000 + +; Default port number for mysqli_connect(). If unset, mysqli_connect() will use +; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the +; compile-time value defined MYSQL_PORT (in that order). Win32 will only look +; at MYSQL_PORT. +; http://php.net/mysqli.default-port +mysqli.default_port = 3306 + +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +; http://php.net/mysqli.default-socket +mysqli.default_socket = + +; Default host for mysql_connect() (doesn't apply in safe mode). +; http://php.net/mysqli.default-host +mysqli.default_host = + +; Default user for mysql_connect() (doesn't apply in safe mode). +; http://php.net/mysqli.default-user +mysqli.default_user = + +; Default password for mysqli_connect() (doesn't apply in safe mode). +; Note that this is generally a *bad* idea to store passwords in this file. +; *Any* user with PHP access can run 'echo get_cfg_var("mysqli.default_pw") +; and reveal this password! And of course, any users with read access to this +; file will be able to reveal the password as well. +; http://php.net/mysqli.default-pw +mysqli.default_pw = + +; Allow or prevent reconnect +mysqli.reconnect = Off + +[mysqlnd] +; Enable / Disable collection of general statstics by mysqlnd which can be +; used to tune and monitor MySQL operations. +; http://php.net/mysqlnd.collect_statistics +mysqlnd.collect_statistics = On + +; Enable / Disable collection of memory usage statstics by mysqlnd which can be +; used to tune and monitor MySQL operations. +; http://php.net/mysqlnd.collect_memory_statistics +mysqlnd.collect_memory_statistics = Off + +; Size of a pre-allocated buffer used when sending commands to MySQL in bytes. +; http://php.net/mysqlnd.net_cmd_buffer_size +;mysqlnd.net_cmd_buffer_size = 2048 + +; Size of a pre-allocated buffer used for reading data sent by the server in +; bytes. +; http://php.net/mysqlnd.net_read_buffer_size +;mysqlnd.net_read_buffer_size = 32768 + +[OCI8] + +; Connection: Enables privileged connections using external +; credentials (OCI_SYSOPER, OCI_SYSDBA) +; http://php.net/oci8.privileged-connect +;oci8.privileged_connect = Off + +; Connection: The maximum number of persistent OCI8 connections per +; process. Using -1 means no limit. +; http://php.net/oci8.max-persistent +;oci8.max_persistent = -1 + +; Connection: The maximum number of seconds a process is allowed to +; maintain an idle persistent connection. Using -1 means idle +; persistent connections will be maintained forever. +; http://php.net/oci8.persistent-timeout +;oci8.persistent_timeout = -1 + +; Connection: The number of seconds that must pass before issuing a +; ping during oci_pconnect() to check the connection validity. When +; set to 0, each oci_pconnect() will cause a ping. Using -1 disables +; pings completely. +; http://php.net/oci8.ping-interval +;oci8.ping_interval = 60 + +; Connection: Set this to a user chosen connection class to be used +; for all pooled server requests with Oracle 11g Database Resident +; Connection Pooling (DRCP). To use DRCP, this value should be set to +; the same string for all web servers running the same application, +; the database pool must be configured, and the connection string must +; specify to use a pooled server. +;oci8.connection_class = + +; High Availability: Using On lets PHP receive Fast Application +; Notification (FAN) events generated when a database node fails. The +; database must also be configured to post FAN events. +;oci8.events = Off + +; Tuning: This option enables statement caching, and specifies how +; many statements to cache. Using 0 disables statement caching. +; http://php.net/oci8.statement-cache-size +;oci8.statement_cache_size = 20 + +; Tuning: Enables statement prefetching and sets the default number of +; rows that will be fetched automatically after statement execution. +; http://php.net/oci8.default-prefetch +;oci8.default_prefetch = 100 + +; Compatibility. Using On means oci_close() will not close +; oci_connect() and oci_new_connect() connections. +; http://php.net/oci8.old-oci-close-semantics +;oci8.old_oci_close_semantics = Off + +[PostgresSQL] +; Allow or prevent persistent links. +; http://php.net/pgsql.allow-persistent +pgsql.allow_persistent = On + +; Detect broken persistent links always with pg_pconnect(). +; Auto reset feature requires a little overheads. +; http://php.net/pgsql.auto-reset-persistent +pgsql.auto_reset_persistent = Off + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/pgsql.max-persistent +pgsql.max_persistent = -1 + +; Maximum number of links (persistent+non persistent). -1 means no limit. +; http://php.net/pgsql.max-links +pgsql.max_links = -1 + +; Ignore PostgreSQL backends Notice message or not. +; Notice message logging require a little overheads. +; http://php.net/pgsql.ignore-notice +pgsql.ignore_notice = 0 + +; Log PostgreSQL backends Notice message or not. +; Unless pgsql.ignore_notice=0, module cannot log notice message. +; http://php.net/pgsql.log-notice +pgsql.log_notice = 0 + +[Sybase-CT] +; Allow or prevent persistent links. +; http://php.net/sybct.allow-persistent +sybct.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/sybct.max-persistent +sybct.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +; http://php.net/sybct.max-links +sybct.max_links = -1 + +; Minimum server message severity to display. +; http://php.net/sybct.min-server-severity +sybct.min_server_severity = 10 + +; Minimum client message severity to display. +; http://php.net/sybct.min-client-severity +sybct.min_client_severity = 10 + +; Set per-context timeout +; http://php.net/sybct.timeout +;sybct.timeout= + +;sybct.packet_size + +; The maximum time in seconds to wait for a connection attempt to succeed before returning failure. +; Default: one minute +;sybct.login_timeout= + +; The name of the host you claim to be connecting from, for display by sp_who. +; Default: none +;sybct.hostname= + +; Allows you to define how often deadlocks are to be retried. -1 means "forever". +; Default: 0 +;sybct.deadlock_retry_count= + +[bcmath] +; Number of decimal digits for all bcmath functions. +; http://php.net/bcmath.scale +bcmath.scale = 0 + +[browscap] +; http://php.net/browscap +;browscap = extra/browscap.ini + +[Session] +; Handler used to store/retrieve data. +; http://php.net/session.save-handler +session.save_handler = files + +; Argument passed to save_handler. In the case of files, this is the path +; where data files are stored. Note: Windows users have to change this +; variable in order to use PHP's session functions. +; +; The path can be defined as: +; +; session.save_path = "N;/path" +; +; where N is an integer. Instead of storing all the session files in +; /path, what this will do is use subdirectories N-levels deep, and +; store the session data in those directories. This is useful if you +; or your OS have problems with lots of files in one directory, and is +; a more efficient layout for servers that handle lots of sessions. +; +; NOTE 1: PHP will not create this directory structure automatically. +; You can use the script in the ext/session dir for that purpose. +; NOTE 2: See the section on garbage collection below if you choose to +; use subdirectories for session storage +; +; The file storage module creates files using mode 600 by default. +; You can change that by using +; +; session.save_path = "N;MODE;/path" +; +; where MODE is the octal representation of the mode. Note that this +; does not overwrite the process's umask. +; http://php.net/session.save-path +;session.save_path = "/tmp" + +; Whether to use cookies. +; http://php.net/session.use-cookies +session.use_cookies = 1 + +; http://php.net/session.cookie-secure +;session.cookie_secure = + +; This option forces PHP to fetch and use a cookie for storing and maintaining +; the session id. We encourage this operation as it's very helpful in combatting +; session hijacking when not specifying and managing your own session id. It is +; not the end all be all of session hijacking defense, but it's a good start. +; http://php.net/session.use-only-cookies +session.use_only_cookies = 1 + +; Name of the session (used as cookie name). +; http://php.net/session.name +session.name = PHPSESSID + +; Initialize session on request startup. +; http://php.net/session.auto-start +session.auto_start = 0 + +; Lifetime in seconds of cookie or, if 0, until browser is restarted. +; http://php.net/session.cookie-lifetime +session.cookie_lifetime = 0 + +; The path for which the cookie is valid. +; http://php.net/session.cookie-path +session.cookie_path = / + +; The domain for which the cookie is valid. +; http://php.net/session.cookie-domain +session.cookie_domain = + +; Whether or not to add the httpOnly flag to the cookie, which makes it inaccessible to browser scripting languages such as JavaScript. +; http://php.net/session.cookie-httponly +session.cookie_httponly = + +; Handler used to serialize data. php is the standard serializer of PHP. +; http://php.net/session.serialize-handler +session.serialize_handler = php + +; Defines the probability that the 'garbage collection' process is started +; on every session initialization. The probability is calculated by using +; gc_probability/gc_divisor. Where session.gc_probability is the numerator +; and gc_divisor is the denominator in the equation. Setting this value to 1 +; when the session.gc_divisor value is 100 will give you approximately a 1% chance +; the gc will run on any give request. +; Default Value: 1 +; Development Value: 1 +; Production Value: 1 +; http://php.net/session.gc-probability +session.gc_probability = 1 + +; Defines the probability that the 'garbage collection' process is started on every +; session initialization. The probability is calculated by using the following equation: +; gc_probability/gc_divisor. Where session.gc_probability is the numerator and +; session.gc_divisor is the denominator in the equation. Setting this value to 1 +; when the session.gc_divisor value is 100 will give you approximately a 1% chance +; the gc will run on any give request. Increasing this value to 1000 will give you +; a 0.1% chance the gc will run on any give request. For high volume production servers, +; this is a more efficient approach. +; Default Value: 100 +; Development Value: 1000 +; Production Value: 1000 +; http://php.net/session.gc-divisor +session.gc_divisor = 1000 + +; After this number of seconds, stored data will be seen as 'garbage' and +; cleaned up by the garbage collection process. +; http://php.net/session.gc-maxlifetime +session.gc_maxlifetime = 1440 + +; NOTE: If you are using the subdirectory option for storing session files +; (see session.save_path above), then garbage collection does *not* +; happen automatically. You will need to do your own garbage +; collection through a shell script, cron entry, or some other method. +; For example, the following script would is the equivalent of +; setting session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes): +; find /path/to/sessions -cmin +24 | xargs rm + +; PHP 4.2 and less have an undocumented feature/bug that allows you to +; to initialize a session variable in the global scope, even when register_globals +; is disabled. PHP 4.3 and later will warn you, if this feature is used. +; You can disable the feature and the warning separately. At this time, +; the warning is only displayed, if bug_compat_42 is enabled. This feature +; introduces some serious security problems if not handled correctly. It's +; recommended that you do not use this feature on production servers. But you +; should enable this on development servers and enable the warning as well. If you +; do not enable the feature on development servers, you won't be warned when it's +; used and debugging errors caused by this can be difficult to track down. +; Default Value: On +; Development Value: On +; Production Value: Off +; http://php.net/session.bug-compat-42 +session.bug_compat_42 = Off + +; This setting controls whether or not you are warned by PHP when initializing a +; session value into the global space. session.bug_compat_42 must be enabled before +; these warnings can be issued by PHP. See the directive above for more information. +; Default Value: On +; Development Value: On +; Production Value: Off +; http://php.net/session.bug-compat-warn +session.bug_compat_warn = Off + +; Check HTTP Referer to invalidate externally stored URLs containing ids. +; HTTP_REFERER has to contain this substring for the session to be +; considered as valid. +; http://php.net/session.referer-check +session.referer_check = + +; How many bytes to read from the file. +; http://php.net/session.entropy-length +session.entropy_length = 0 + +; Specified here to create the session id. +; http://php.net/session.entropy-file +; On systems that don't have /dev/urandom /dev/arandom can be used +; On windows, setting the entropy_length setting will activate the +; Windows random source (using the CryptoAPI) +;session.entropy_file = /dev/urandom + +; Set to {nocache,private,public,} to determine HTTP caching aspects +; or leave this empty to avoid sending anti-caching headers. +; http://php.net/session.cache-limiter +session.cache_limiter = nocache + +; Document expires after n minutes. +; http://php.net/session.cache-expire +session.cache_expire = 180 + +; trans sid support is disabled by default. +; Use of trans sid may risk your users security. +; Use this option with caution. +; - User may send URL contains active session ID +; to other person via. email/irc/etc. +; - URL that contains active session ID may be stored +; in publically accessible computer. +; - User may access your site with the same session ID +; always using URL stored in browser's history or bookmarks. +; http://php.net/session.use-trans-sid +session.use_trans_sid = 0 + +; Select a hash function for use in generating session ids. +; Possible Values +; 0 (MD5 128 bits) +; 1 (SHA-1 160 bits) +; This option may also be set to the name of any hash function supported by +; the hash extension. A list of available hashes is returned by the hash_algos() +; function. +; http://php.net/session.hash-function +session.hash_function = 0 + +; Define how many bits are stored in each character when converting +; the binary hash data to something readable. +; Possible values: +; 4 (4 bits: 0-9, a-f) +; 5 (5 bits: 0-9, a-v) +; 6 (6 bits: 0-9, a-z, A-Z, "-", ",") +; Default Value: 4 +; Development Value: 5 +; Production Value: 5 +; http://php.net/session.hash-bits-per-character +session.hash_bits_per_character = 5 + +; The URL rewriter will look for URLs in a defined set of HTML tags. +; form/fieldset are special; if you include them here, the rewriter will +; add a hidden field with the info which is otherwise appended +; to URLs. If you want XHTML conformity, remove the form entry. +; Note that all valid entries require a "=", even if no value follows. +; Default Value: "a=href,area=href,frame=src,form=,fieldset=" +; Development Value: "a=href,area=href,frame=src,input=src,form=fakeentry" +; Production Value: "a=href,area=href,frame=src,input=src,form=fakeentry" +; http://php.net/url-rewriter.tags +url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry" + +[MSSQL] +; Allow or prevent persistent links. +mssql.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +mssql.max_persistent = -1 + +; Maximum number of links (persistent+non persistent). -1 means no limit. +mssql.max_links = -1 + +; Minimum error severity to display. +mssql.min_error_severity = 10 + +; Minimum message severity to display. +mssql.min_message_severity = 10 + +; Compatibility mode with old versions of PHP 3.0. +mssql.compatability_mode = Off + +; Connect timeout +;mssql.connect_timeout = 5 + +; Query timeout +;mssql.timeout = 60 + +; Valid range 0 - 2147483647. Default = 4096. +;mssql.textlimit = 4096 + +; Valid range 0 - 2147483647. Default = 4096. +;mssql.textsize = 4096 + +; Limits the number of records in each batch. 0 = all records in one batch. +;mssql.batchsize = 0 + +; Specify how datetime and datetim4 columns are returned +; On => Returns data converted to SQL server settings +; Off => Returns values as YYYY-MM-DD hh:mm:ss +;mssql.datetimeconvert = On + +; Use NT authentication when connecting to the server +mssql.secure_connection = Off + +; Specify max number of processes. -1 = library default +; msdlib defaults to 25 +; FreeTDS defaults to 4096 +;mssql.max_procs = -1 + +; Specify client character set. +; If empty or not set the client charset from freetds.comf is used +; This is only used when compiled with FreeTDS +;mssql.charset = "ISO-8859-1" + +[Assertion] +; Assert(expr); active by default. +; http://php.net/assert.active +;assert.active = On + +; Issue a PHP warning for each failed assertion. +; http://php.net/assert.warning +;assert.warning = On + +; Don't bail out by default. +; http://php.net/assert.bail +;assert.bail = Off + +; User-function to be called if an assertion fails. +; http://php.net/assert.callback +;assert.callback = 0 + +; Eval the expression with current error_reporting(). Set to true if you want +; error_reporting(0) around the eval(). +; http://php.net/assert.quiet-eval +;assert.quiet_eval = 0 + +[COM] +; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs +; http://php.net/com.typelib-file +;com.typelib_file = + +; allow Distributed-COM calls +; http://php.net/com.allow-dcom +;com.allow_dcom = true + +; autoregister constants of a components typlib on com_load() +; http://php.net/com.autoregister-typelib +;com.autoregister_typelib = true + +; register constants casesensitive +; http://php.net/com.autoregister-casesensitive +;com.autoregister_casesensitive = false + +; show warnings on duplicate constant registrations +; http://php.net/com.autoregister-verbose +;com.autoregister_verbose = true + +; The default character set code-page to use when passing strings to and from COM objects. +; Default: system ANSI code page +;com.code_page= + +[mbstring] +; language for internal character representation. +; http://php.net/mbstring.language +;mbstring.language = Japanese + +; internal/script encoding. +; Some encoding cannot work as internal encoding. +; (e.g. SJIS, BIG5, ISO-2022-*) +; http://php.net/mbstring.internal-encoding +;mbstring.internal_encoding = EUC-JP + +; http input encoding. +; http://php.net/mbstring.http-input +;mbstring.http_input = auto + +; http output encoding. mb_output_handler must be +; registered as output buffer to function +; http://php.net/mbstring.http-output +;mbstring.http_output = SJIS + +; enable automatic encoding translation according to +; mbstring.internal_encoding setting. Input chars are +; converted to internal encoding by setting this to On. +; Note: Do _not_ use automatic encoding translation for +; portable libs/applications. +; http://php.net/mbstring.encoding-translation +;mbstring.encoding_translation = Off + +; automatic encoding detection order. +; auto means +; http://php.net/mbstring.detect-order +;mbstring.detect_order = auto + +; substitute_character used when character cannot be converted +; one from another +; http://php.net/mbstring.substitute-character +;mbstring.substitute_character = none; + +; overload(replace) single byte functions by mbstring functions. +; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(), +; etc. Possible values are 0,1,2,4 or combination of them. +; For example, 7 for overload everything. +; 0: No overload +; 1: Overload mail() function +; 2: Overload str*() functions +; 4: Overload ereg*() functions +; http://php.net/mbstring.func-overload +;mbstring.func_overload = 0 + +; enable strict encoding detection. +;mbstring.strict_detection = Off + +; This directive specifies the regex pattern of content types for which mb_output_handler() +; is activated. +; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml) +;mbstring.http_output_conv_mimetype= + +; Allows to set script encoding. Only affects if PHP is compiled with --enable-zend-multibyte +; Default: "" +;mbstring.script_encoding= + +[gd] +; Tell the jpeg decode to ignore warnings and try to create +; a gd image. The warning will then be displayed as notices +; disabled by default +; http://php.net/gd.jpeg-ignore-warning +;gd.jpeg_ignore_warning = 0 + +[exif] +; Exif UNICODE user comments are handled as UCS-2BE/UCS-2LE and JIS as JIS. +; With mbstring support this will automatically be converted into the encoding +; given by corresponding encode setting. When empty mbstring.internal_encoding +; is used. For the decode settings you can distinguish between motorola and +; intel byte order. A decode setting cannot be empty. +; http://php.net/exif.encode-unicode +;exif.encode_unicode = ISO-8859-15 + +; http://php.net/exif.decode-unicode-motorola +;exif.decode_unicode_motorola = UCS-2BE + +; http://php.net/exif.decode-unicode-intel +;exif.decode_unicode_intel = UCS-2LE + +; http://php.net/exif.encode-jis +;exif.encode_jis = + +; http://php.net/exif.decode-jis-motorola +;exif.decode_jis_motorola = JIS + +; http://php.net/exif.decode-jis-intel +;exif.decode_jis_intel = JIS + +[Tidy] +; The path to a default tidy configuration file to use when using tidy +; http://php.net/tidy.default-config +;tidy.default_config = /usr/local/lib/php/default.tcfg + +; Should tidy clean and repair output automatically? +; WARNING: Do not use this option if you are generating non-html content +; such as dynamic images +; http://php.net/tidy.clean-output +tidy.clean_output = Off + +[soap] +; Enables or disables WSDL caching feature. +; http://php.net/soap.wsdl-cache-enabled +soap.wsdl_cache_enabled=1 + +; Sets the directory name where SOAP extension will put cache files. +; http://php.net/soap.wsdl-cache-dir +soap.wsdl_cache_dir="/tmp" + +; (time to live) Sets the number of second while cached file will be used +; instead of original one. +; http://php.net/soap.wsdl-cache-ttl +soap.wsdl_cache_ttl=86400 + +; Sets the size of the cache limit. (Max. number of WSDL files to cache) +soap.wsdl_cache_limit = 5 + +[sysvshm] +; A default size of the shared memory segment +;sysvshm.init_mem = 10000 + +[ldap] +; Sets the maximum number of open links or -1 for unlimited. +ldap.max_links = -1 + +[mcrypt] +; For more information about mcrypt settings see http://php.net/mcrypt-module-open + +; Directory where to load mcrypt algorithms +; Default: Compiled in into libmcrypt (usually /usr/local/lib/libmcrypt) +;mcrypt.algorithms_dir= + +; Directory where to load mcrypt modes +; Default: Compiled in into libmcrypt (usually /usr/local/lib/libmcrypt) +;mcrypt.modes_dir= + +[dba] +;dba.default_handler= + +; Local Variables: +; tab-width: 4 +; End: + +<% @directives.sort_by { |key, val| key }.each do |directive, value| -%> +<%= "#{directive}=#{value}" %> +<% end -%> diff --git a/cookbooks/php/templates/redhat/php.ini.erb b/cookbooks/php/templates/redhat/php.ini.erb new file mode 100644 index 0000000..a9e5d16 --- /dev/null +++ b/cookbooks/php/templates/redhat/php.ini.erb @@ -0,0 +1,1225 @@ +[PHP] + +;;;;;;;;;;;;;;;;;;; +; About php.ini ; +;;;;;;;;;;;;;;;;;;; +; This file controls many aspects of PHP's behavior. In order for PHP to +; read it, it must be named 'php.ini'. PHP looks for it in the current +; working directory, in the path designated by the environment variable +; PHPRC, and in the path that was defined in compile time (in that order). +; Under Windows, the compile-time path is the Windows directory. The +; path in which the php.ini file is looked for can be overridden using +; the -c argument in command line mode. +; +; The syntax of the file is extremely simple. Whitespace and Lines +; beginning with a semicolon are silently ignored (as you probably guessed). +; Section headers (e.g. [Foo]) are also silently ignored, even though +; they might mean something in the future. +; +; Directives are specified using the following syntax: +; directive = value +; Directive names are *case sensitive* - foo=bar is different from FOO=bar. +; +; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one +; of the INI constants (On, Off, True, False, Yes, No and None) or an expression +; (e.g. E_ALL & ~E_NOTICE), or a quoted string ("foo"). +; +; Expressions in the INI file are limited to bitwise operators and parentheses: +; | bitwise OR +; & bitwise AND +; ~ bitwise NOT +; ! boolean NOT +; +; Boolean flags can be turned on using the values 1, On, True or Yes. +; They can be turned off using the values 0, Off, False or No. +; +; An empty string can be denoted by simply not writing anything after the equal +; sign, or by using the None keyword: +; +; foo = ; sets foo to an empty string +; foo = none ; sets foo to an empty string +; foo = "none" ; sets foo to the string 'none' +; +; If you use constants in your value, and these constants belong to a +; dynamically loaded extension (either a PHP extension or a Zend extension), +; you may only use these constants *after* the line that loads the extension. +; +; +;;;;;;;;;;;;;;;;;;; +; About this file ; +;;;;;;;;;;;;;;;;;;; +; This is the recommended, PHP 5-style version of the php.ini-dist file. It +; sets some non standard settings, that make PHP more efficient, more secure, +; and encourage cleaner coding. +; +; The price is that with these settings, PHP may be incompatible with some +; applications, and sometimes, more difficult to develop with. Using this +; file is warmly recommended for production sites. As all of the changes from +; the standard settings are thoroughly documented, you can go over each one, +; and decide whether you want to use it or not. +; +; For general information about the php.ini file, please consult the php.ini-dist +; file, included in your PHP distribution. +; +; This file is different from the php.ini-dist file in the fact that it features +; different values for several directives, in order to improve performance, while +; possibly breaking compatibility with the standard out-of-the-box behavior of +; PHP. Please make sure you read what's different, and modify your scripts +; accordingly, if you decide to use this file instead. +; +; - register_globals = Off [Security, Performance] +; Global variables are no longer registered for input data (POST, GET, cookies, +; environment and other server variables). Instead of using $foo, you must use +; you can use $_REQUEST["foo"] (includes any variable that arrives through the +; request, namely, POST, GET and cookie variables), or use one of the specific +; $_GET["foo"], $_POST["foo"], $_COOKIE["foo"] or $_FILES["foo"], depending +; on where the input originates. Also, you can look at the +; import_request_variables() function. +; Note that register_globals is going to be depracated (i.e., turned off by +; default) in the next version of PHP, because it often leads to security bugs. +; Read http://php.net/manual/en/security.registerglobals.php for further +; information. +; - register_long_arrays = Off [Performance] +; Disables registration of the older (and deprecated) long predefined array +; variables ($HTTP_*_VARS). Instead, use the superglobals that were +; introduced in PHP 4.1.0 +; - display_errors = Off [Security] +; With this directive set to off, errors that occur during the execution of +; scripts will no longer be displayed as a part of the script output, and thus, +; will no longer be exposed to remote users. With some errors, the error message +; content may expose information about your script, web server, or database +; server that may be exploitable for hacking. Production sites should have this +; directive set to off. +; - log_errors = On [Security] +; This directive complements the above one. Any errors that occur during the +; execution of your script will be logged (typically, to your server's error log, +; but can be configured in several ways). Along with setting display_errors to off, +; this setup gives you the ability to fully understand what may have gone wrong, +; without exposing any sensitive information to remote users. +; - output_buffering = 4096 [Performance] +; Set a 4KB output buffer. Enabling output buffering typically results in less +; writes, and sometimes less packets sent on the wire, which can often lead to +; better performance. The gain this directive actually yields greatly depends +; on which Web server you're working with, and what kind of scripts you're using. +; - register_argc_argv = Off [Performance] +; Disables registration of the somewhat redundant $argv and $argc global +; variables. +; - magic_quotes_gpc = Off [Performance] +; Input data is no longer escaped with slashes so that it can be sent into +; SQL databases without further manipulation. Instead, you should use the +; function addslashes() on each input element you wish to send to a database. +; - variables_order = "GPCS" [Performance] +; The environment variables are not hashed into the $_ENV. To access +; environment variables, you can use getenv() instead. +; - error_reporting = E_ALL [Code Cleanliness, Security(?)] +; By default, PHP surpresses errors of type E_NOTICE. These error messages +; are emitted for non-critical errors, but that could be a symptom of a bigger +; problem. Most notably, this will cause error messages about the use +; of uninitialized variables to be displayed. +; - allow_call_time_pass_reference = Off [Code cleanliness] +; It's not possible to decide to force a variable to be passed by reference +; when calling a function. The PHP 4 style to do this is by making the +; function require the relevant argument by reference. + + +;;;;;;;;;;;;;;;;;;;; +; Language Options ; +;;;;;;;;;;;;;;;;;;;; + +; Enable the PHP scripting language engine under Apache. +engine = On + +; Enable compatibility mode with Zend Engine 1 (PHP 4.x) +zend.ze1_compatibility_mode = Off + +; Allow the tags are recognized. +; NOTE: Using short tags should be avoided when developing applications or +; libraries that are meant for redistribution, or deployment on PHP +; servers which are not under your control, because short tags may not +; be supported on the target server. For portable, redistributable code, +; be sure not to use short tags. +short_open_tag = On + +; Allow ASP-style <% %> tags. +asp_tags = Off + +; The number of significant digits displayed in floating point numbers. +precision = 14 + +; Enforce year 2000 compliance (will cause problems with non-compliant browsers) +y2k_compliance = On + +; Output buffering allows you to send header lines (including cookies) even +; after you send body content, at the price of slowing PHP's output layer a +; bit. You can enable output buffering during runtime by calling the output +; buffering functions. You can also enable output buffering for all files by +; setting this directive to On. If you wish to limit the size of the buffer +; to a certain size - you can use a maximum number of bytes instead of 'On', as +; a value for this directive (e.g., output_buffering=4096). +output_buffering = 4096 + +; You can redirect all of the output of your scripts to a function. For +; example, if you set output_handler to "mb_output_handler", character +; encoding will be transparently converted to the specified encoding. +; Setting any output handler automatically turns on output buffering. +; Note: People who wrote portable scripts should not depend on this ini +; directive. Instead, explicitly set the output handler using ob_start(). +; Using this ini directive may cause problems unless you know what script +; is doing. +; Note: You cannot use both "mb_output_handler" with "ob_iconv_handler" +; and you cannot use both "ob_gzhandler" and "zlib.output_compression". +; Note: output_handler must be empty if this is set 'On' !!!! +; Instead you must use zlib.output_handler. +;output_handler = + +; Transparent output compression using the zlib library +; Valid values for this option are 'off', 'on', or a specific buffer size +; to be used for compression (default is 4KB) +; Note: Resulting chunk size may vary due to nature of compression. PHP +; outputs chunks that are few hundreds bytes each as a result of +; compression. If you prefer a larger chunk size for better +; performance, enable output_buffering in addition. +; Note: You need to use zlib.output_handler instead of the standard +; output_handler, or otherwise the output will be corrupted. +zlib.output_compression = Off + +; You cannot specify additional output handlers if zlib.output_compression +; is activated here. This setting does the same as output_handler but in +; a different order. +;zlib.output_handler = + +; Implicit flush tells PHP to tell the output layer to flush itself +; automatically after every output block. This is equivalent to calling the +; PHP function flush() after each and every call to print() or echo() and each +; and every HTML block. Turning this option on has serious performance +; implications and is generally recommended for debugging purposes only. +implicit_flush = Off + +; The unserialize callback function will be called (with the undefined class' +; name as parameter), if the unserializer finds an undefined class +; which should be instantiated. +; A warning appears if the specified function is not defined, or if the +; function doesn't include/implement the missing class. +; So only set this entry, if you really want to implement such a +; callback-function. +unserialize_callback_func= + +; When floats & doubles are serialized store serialize_precision significant +; digits after the floating point. The default value ensures that when floats +; are decoded with unserialize, the data will remain the same. +serialize_precision = 100 + +; Whether to enable the ability to force arguments to be passed by reference +; at function call time. This method is deprecated and is likely to be +; unsupported in future versions of PHP/Zend. The encouraged method of +; specifying which arguments should be passed by reference is in the function +; declaration. You're encouraged to try and turn this option Off and make +; sure your scripts work properly with it in order to ensure they will work +; with future versions of the language (you will receive a warning each time +; you use this feature, and the argument will be passed by value instead of by +; reference). +allow_call_time_pass_reference = Off + +; +; Safe Mode +; +safe_mode = Off + +; By default, Safe Mode does a UID compare check when +; opening files. If you want to relax this to a GID compare, +; then turn on safe_mode_gid. +safe_mode_gid = Off + +; When safe_mode is on, UID/GID checks are bypassed when +; including files from this directory and its subdirectories. +; (directory must also be in include_path or full path must +; be used when including) +safe_mode_include_dir = + +; When safe_mode is on, only executables located in the safe_mode_exec_dir +; will be allowed to be executed via the exec family of functions. +safe_mode_exec_dir = + +; Setting certain environment variables may be a potential security breach. +; This directive contains a comma-delimited list of prefixes. In Safe Mode, +; the user may only alter environment variables whose names begin with the +; prefixes supplied here. By default, users will only be able to set +; environment variables that begin with PHP_ (e.g. PHP_FOO=BAR). +; +; Note: If this directive is empty, PHP will let the user modify ANY +; environment variable! +safe_mode_allowed_env_vars = PHP_ + +; This directive contains a comma-delimited list of environment variables that +; the end user won't be able to change using putenv(). These variables will be +; protected even if safe_mode_allowed_env_vars is set to allow to change them. +safe_mode_protected_env_vars = LD_LIBRARY_PATH + +; open_basedir, if set, limits all file operations to the defined directory +; and below. This directive makes most sense if used in a per-directory +; or per-virtualhost web server configuration file. This directive is +; *NOT* affected by whether Safe Mode is turned On or Off. +;open_basedir = + +; This directive allows you to disable certain functions for security reasons. +; It receives a comma-delimited list of function names. This directive is +; *NOT* affected by whether Safe Mode is turned On or Off. +disable_functions = + +; This directive allows you to disable certain classes for security reasons. +; It receives a comma-delimited list of class names. This directive is +; *NOT* affected by whether Safe Mode is turned On or Off. +disable_classes = + +; Colors for Syntax Highlighting mode. Anything that's acceptable in +; would work. +;highlight.string = #DD0000 +;highlight.comment = #FF9900 +;highlight.keyword = #007700 +;highlight.bg = #FFFFFF +;highlight.default = #0000BB +;highlight.html = #000000 + +; If enabled, the request will be allowed to complete even if the user aborts +; the request. Consider enabling it if executing long request, which may end up +; being interrupted by the user or a browser timing out. +; ignore_user_abort = On + +; Determines the size of the realpath cache to be used by PHP. This value should +; be increased on systems where PHP opens many files to reflect the quantity of +; the file operations performed. +; realpath_cache_size=16k + +; Duration of time, in seconds for which to cache realpath information for a given +; file or directory. For systems with rarely changing files, consider increasing this +; value. +; realpath_cache_ttl=120 + +; +; Misc +; +; Decides whether PHP may expose the fact that it is installed on the server +; (e.g. by adding its signature to the Web server header). It is no security +; threat in any way, but it makes it possible to determine whether you use PHP +; on your server or not. +expose_php = On + + +;;;;;;;;;;;;;;;;;;; +; Resource Limits ; +;;;;;;;;;;;;;;;;;;; + +max_execution_time = 30 ; Maximum execution time of each script, in seconds +max_input_time = 60 ; Maximum amount of time each script may spend parsing request data +memory_limit = 128M ; Maximum amount of memory a script may consume + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Error handling and logging ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; error_reporting is a bit-field. Or each number up to get desired error +; reporting level +; E_ALL - All errors and warnings (doesn't include E_STRICT) +; E_ERROR - fatal run-time errors +; E_WARNING - run-time warnings (non-fatal errors) +; E_PARSE - compile-time parse errors +; E_NOTICE - run-time notices (these are warnings which often result +; from a bug in your code, but it's possible that it was +; intentional (e.g., using an uninitialized variable and +; relying on the fact it's automatically initialized to an +; empty string) +; E_STRICT - run-time notices, enable to have PHP suggest changes +; to your code which will ensure the best interoperability +; and forward compatibility of your code +; E_CORE_ERROR - fatal errors that occur during PHP's initial startup +; E_CORE_WARNING - warnings (non-fatal errors) that occur during PHP's +; initial startup +; E_COMPILE_ERROR - fatal compile-time errors +; E_COMPILE_WARNING - compile-time warnings (non-fatal errors) +; E_USER_ERROR - user-generated error message +; E_USER_WARNING - user-generated warning message +; E_USER_NOTICE - user-generated notice message +; +; Examples: +; +; - Show all errors, except for notices and coding standards warnings +; +;error_reporting = E_ALL & ~E_NOTICE +; +; - Show all errors, except for notices +; +;error_reporting = E_ALL & ~E_NOTICE | E_STRICT +; +; - Show only errors +; +;error_reporting = E_COMPILE_ERROR|E_ERROR|E_CORE_ERROR +; +; - Show all errors, except coding standards warnings +; +error_reporting = E_ALL + +; Print out errors (as a part of the output). For production web sites, +; you're strongly encouraged to turn this feature off, and use error logging +; instead (see below). Keeping display_errors enabled on a production web site +; may reveal security information to end users, such as file paths on your Web +; server, your database schema or other information. +display_errors = Off + +; Even when display_errors is on, errors that occur during PHP's startup +; sequence are not displayed. It's strongly recommended to keep +; display_startup_errors off, except for when debugging. +display_startup_errors = Off + +; Log errors into a log file (server-specific log, stderr, or error_log (below)) +; As stated above, you're strongly advised to use error logging in place of +; error displaying on production web sites. +log_errors = On + +; Set maximum length of log_errors. In error_log information about the source is +; added. The default is 1024 and 0 allows to not apply any maximum length at all. +log_errors_max_len = 1024 + +; Do not log repeated messages. Repeated errors must occur in same file on same +; line until ignore_repeated_source is set true. +ignore_repeated_errors = Off + +; Ignore source of message when ignoring repeated messages. When this setting +; is On you will not log errors with repeated messages from different files or +; sourcelines. +ignore_repeated_source = Off + +; If this parameter is set to Off, then memory leaks will not be shown (on +; stdout or in the log). This has only effect in a debug compile, and if +; error reporting includes E_WARNING in the allowed list +report_memleaks = On + +; Store the last error/warning message in $php_errormsg (boolean). +track_errors = Off + +; Disable the inclusion of HTML tags in error messages. +; Note: Never use this feature for production boxes. +;html_errors = Off + +; If html_errors is set On PHP produces clickable error messages that direct +; to a page describing the error or function causing the error in detail. +; You can download a copy of the PHP manual from http://www.php.net/docs.php +; and change docref_root to the base URL of your local copy including the +; leading '/'. You must also specify the file extension being used including +; the dot. +; Note: Never use this feature for production boxes. +;docref_root = "/phpmanual/" +;docref_ext = .html + +; String to output before an error message. +;error_prepend_string = "" + +; String to output after an error message. +;error_append_string = "" + +; Log errors to specified file. +;error_log = filename + +; Log errors to syslog (Event Log on NT, not valid in Windows 95). +;error_log = syslog + + +;;;;;;;;;;;;;;;;; +; Data Handling ; +;;;;;;;;;;;;;;;;; +; +; Note - track_vars is ALWAYS enabled as of PHP 4.0.3 + +; The separator used in PHP generated URLs to separate arguments. +; Default is "&". +;arg_separator.output = "&" + +; List of separator(s) used by PHP to parse input URLs into variables. +; Default is "&". +; NOTE: Every character in this directive is considered as separator! +;arg_separator.input = ";&" + +; This directive describes the order in which PHP registers GET, POST, Cookie, +; Environment and Built-in variables (G, P, C, E & S respectively, often +; referred to as EGPCS or GPC). Registration is done from left to right, newer +; values override older values. +variables_order = "EGPCS" + +; Whether or not to register the EGPCS variables as global variables. You may +; want to turn this off if you don't want to clutter your scripts' global scope +; with user data. This makes most sense when coupled with track_vars - in which +; case you can access all of the GPC variables through the $HTTP_*_VARS[], +; variables. +; +; You should do your best to write your scripts so that they do not require +; register_globals to be on; Using form variables as globals can easily lead +; to possible security problems, if the code is not very well thought of. +register_globals = Off + +; Whether or not to register the old-style input arrays, HTTP_GET_VARS +; and friends. If you're not using them, it's recommended to turn them off, +; for performance reasons. +register_long_arrays = Off + +; This directive tells PHP whether to declare the argv&argc variables (that +; would contain the GET information). If you don't use these variables, you +; should turn it off for increased performance. +register_argc_argv = Off + +; When enabled, the SERVER and ENV variables are created when they're first +; used (Just In Time) instead of when the script starts. If these variables +; are not used within a script, having this directive on will result in a +; performance gain. The PHP directives register_globals, register_long_arrays, +; and register_argc_argv must be disabled for this directive to have any affect. +auto_globals_jit = On + +; Maximum size of POST data that PHP will accept. +post_max_size = 8M + +; Magic quotes +; + +; Magic quotes for incoming GET/POST/Cookie data. +magic_quotes_gpc = Off + +; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc. +magic_quotes_runtime = Off + +; Use Sybase-style magic quotes (escape ' with '' instead of \'). +magic_quotes_sybase = Off + +; Automatically add files before or after any PHP document. +auto_prepend_file = +auto_append_file = + +; As of 4.0b4, PHP always outputs a character encoding by default in +; the Content-type: header. To disable sending of the charset, simply +; set it to be empty. +; +; PHP's built-in default is text/html +default_mimetype = "text/html" +;default_charset = "iso-8859-1" + +; Always populate the $HTTP_RAW_POST_DATA variable. +;always_populate_raw_post_data = On + + +;;;;;;;;;;;;;;;;;;;;;;;;; +; Paths and Directories ; +;;;;;;;;;;;;;;;;;;;;;;;;; + +; UNIX: "/path1:/path2" +;include_path = ".:/php/includes" +; +; Windows: "\path1;\path2" +;include_path = ".;c:\php\includes" + +; The root of the PHP pages, used only if nonempty. +; if PHP was not compiled with FORCE_REDIRECT, you SHOULD set doc_root +; if you are running php as a CGI under any web server (other than IIS) +; see documentation for security issues. The alternate is to use the +; cgi.force_redirect configuration below +doc_root = + +; The directory under which PHP opens the script using /~username used only +; if nonempty. +user_dir = + +; Directory in which the loadable extensions (modules) reside. +extension_dir = "<%= node['php']['ext_dir'] %>" + +; Whether or not to enable the dl() function. The dl() function does NOT work +; properly in multithreaded servers, such as IIS or Zeus, and is automatically +; disabled on them. +enable_dl = On + +; cgi.force_redirect is necessary to provide security running PHP as a CGI under +; most web servers. Left undefined, PHP turns this on by default. You can +; turn it off here AT YOUR OWN RISK +; **You CAN safely turn this off for IIS, in fact, you MUST.** +; cgi.force_redirect = 1 + +; if cgi.nph is enabled it will force cgi to always sent Status: 200 with +; every request. +; cgi.nph = 1 + +; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape +; (iPlanet) web servers, you MAY need to set an environment variable name that PHP +; will look for to know it is OK to continue execution. Setting this variable MAY +; cause security issues, KNOW WHAT YOU ARE DOING FIRST. +; cgi.redirect_status_env = ; + +; FastCGI under IIS (on WINNT based OS) supports the ability to impersonate +; security tokens of the calling client. This allows IIS to define the +; security context that the request runs under. mod_fastcgi under Apache +; does not currently support this feature (03/17/2002) +; Set to 1 if running under IIS. Default is zero. +; fastcgi.impersonate = 1; + +; Disable logging through FastCGI connection +; fastcgi.log = 0 + +; cgi.rfc2616_headers configuration option tells PHP what type of headers to +; use when sending HTTP response code. If it's set 0 PHP sends Status: header that +; is supported by Apache. When this option is set to 1 PHP will send +; RFC2616 compliant header. +; Default is zero. +;cgi.rfc2616_headers = 0 + + +;;;;;;;;;;;;;;;; +; File Uploads ; +;;;;;;;;;;;;;;;; + +; Whether to allow HTTP file uploads. +file_uploads = On + +; Temporary directory for HTTP uploaded files (will use system default if not +; specified). +;upload_tmp_dir = + +; Maximum allowed size for uploaded files. +upload_max_filesize = 2M + + +;;;;;;;;;;;;;;;;;; +; Fopen wrappers ; +;;;;;;;;;;;;;;;;;; + +; Whether to allow the treatment of URLs (like http:// or ftp://) as files. +allow_url_fopen = On + +; Define the anonymous ftp password (your email address) +;from="john@doe.com" + +; Define the User-Agent string +; user_agent="PHP" + +; Default timeout for socket based streams (seconds) +default_socket_timeout = 60 + +; If your scripts have to deal with files from Macintosh systems, +; or you are running on a Mac and need to deal with files from +; unix or win32 systems, setting this flag will cause PHP to +; automatically detect the EOL character in those files so that +; fgets() and file() will work regardless of the source of the file. +; auto_detect_line_endings = Off + + +;;;;;;;;;;;;;;;;;;;;;; +; Dynamic Extensions ; +;;;;;;;;;;;;;;;;;;;;;; +; +; If you wish to have an extension loaded automatically, use the following +; syntax: +; +; extension=modulename.extension +; +; For example: +; +; extension=msql.so +; +; Note that it should be the name of the module only; no directory information +; needs to go here. Specify the location of the extension with the +; extension_dir directive above. + + +;;;; +; Note: packaged extension modules are now loaded via the .ini files +; found in the directory /etc/php.d; these are loaded by default. +;;;; + + +;;;;;;;;;;;;;;;;;;; +; Module Settings ; +;;;;;;;;;;;;;;;;;;; + +[Date] +; Defines the default timezone used by the date functions +;date.timezone = + +[Syslog] +; Whether or not to define the various syslog variables (e.g. $LOG_PID, +; $LOG_CRON, etc.). Turning it off is a good idea performance-wise. In +; runtime, you can define these variables by calling define_syslog_variables(). +define_syslog_variables = Off + +[mail function] +; For Win32 only. +SMTP = localhost +smtp_port = 25 + +; For Win32 only. +;sendmail_from = me@example.com + +; For Unix only. You may supply arguments as well (default: "sendmail -t -i"). +sendmail_path = /usr/sbin/sendmail -t -i + +; Force the addition of the specified parameters to be passed as extra parameters +; to the sendmail binary. These parameters will always replace the value of +; the 5th parameter to mail(), even in safe mode. +;mail.force_extra_parameters = + +[SQL] +sql.safe_mode = Off + +[ODBC] +;odbc.default_db = Not yet implemented +;odbc.default_user = Not yet implemented +;odbc.default_pw = Not yet implemented + +; Allow or prevent persistent links. +odbc.allow_persistent = On + +; Check that a connection is still valid before reuse. +odbc.check_persistent = On + +; Maximum number of persistent links. -1 means no limit. +odbc.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +odbc.max_links = -1 + +; Handling of LONG fields. Returns number of bytes to variables. 0 means +; passthru. +odbc.defaultlrl = 4096 + +; Handling of binary data. 0 means passthru, 1 return as is, 2 convert to char. +; See the documentation on odbc_binmode and odbc_longreadlen for an explanation +; of uodbc.defaultlrl and uodbc.defaultbinmode +odbc.defaultbinmode = 1 + +[MySQL] +; Allow or prevent persistent links. +mysql.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +mysql.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +mysql.max_links = -1 + +; Default port number for mysql_connect(). If unset, mysql_connect() will use +; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the +; compile-time value defined MYSQL_PORT (in that order). Win32 will only look +; at MYSQL_PORT. +mysql.default_port = + +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +mysql.default_socket = + +; Default host for mysql_connect() (doesn't apply in safe mode). +mysql.default_host = + +; Default user for mysql_connect() (doesn't apply in safe mode). +mysql.default_user = + +; Default password for mysql_connect() (doesn't apply in safe mode). +; Note that this is generally a *bad* idea to store passwords in this file. +; *Any* user with PHP access can run 'echo get_cfg_var("mysql.default_password") +; and reveal this password! And of course, any users with read access to this +; file will be able to reveal the password as well. +mysql.default_password = + +; Maximum time (in secondes) for connect timeout. -1 means no limit +mysql.connect_timeout = 60 + +; Trace mode. When trace_mode is active (=On), warnings for table/index scans and +; SQL-Errors will be displayed. +mysql.trace_mode = Off + +[MySQLi] + +; Maximum number of links. -1 means no limit. +mysqli.max_links = -1 + +; Default port number for mysqli_connect(). If unset, mysqli_connect() will use +; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the +; compile-time value defined MYSQL_PORT (in that order). Win32 will only look +; at MYSQL_PORT. +mysqli.default_port = 3306 + +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +mysqli.default_socket = + +; Default host for mysql_connect() (doesn't apply in safe mode). +mysqli.default_host = + +; Default user for mysql_connect() (doesn't apply in safe mode). +mysqli.default_user = + +; Default password for mysqli_connect() (doesn't apply in safe mode). +; Note that this is generally a *bad* idea to store passwords in this file. +; *Any* user with PHP access can run 'echo get_cfg_var("mysqli.default_pw") +; and reveal this password! And of course, any users with read access to this +; file will be able to reveal the password as well. +mysqli.default_pw = + +; Allow or prevent reconnect +mysqli.reconnect = Off + +[mSQL] +; Allow or prevent persistent links. +msql.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +msql.max_persistent = -1 + +; Maximum number of links (persistent+non persistent). -1 means no limit. +msql.max_links = -1 + +[PostgresSQL] +; Allow or prevent persistent links. +pgsql.allow_persistent = On + +; Detect broken persistent links always with pg_pconnect(). +; Auto reset feature requires a little overheads. +pgsql.auto_reset_persistent = Off + +; Maximum number of persistent links. -1 means no limit. +pgsql.max_persistent = -1 + +; Maximum number of links (persistent+non persistent). -1 means no limit. +pgsql.max_links = -1 + +; Ignore PostgreSQL backends Notice message or not. +; Notice message logging require a little overheads. +pgsql.ignore_notice = 0 + +; Log PostgreSQL backends Noitce message or not. +; Unless pgsql.ignore_notice=0, module cannot log notice message. +pgsql.log_notice = 0 + +[Sybase] +; Allow or prevent persistent links. +sybase.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +sybase.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +sybase.max_links = -1 + +;sybase.interface_file = "/usr/sybase/interfaces" + +; Minimum error severity to display. +sybase.min_error_severity = 10 + +; Minimum message severity to display. +sybase.min_message_severity = 10 + +; Compatability mode with old versions of PHP 3.0. +; If on, this will cause PHP to automatically assign types to results according +; to their Sybase type, instead of treating them all as strings. This +; compatability mode will probably not stay around forever, so try applying +; whatever necessary changes to your code, and turn it off. +sybase.compatability_mode = Off + +[Sybase-CT] +; Allow or prevent persistent links. +sybct.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +sybct.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +sybct.max_links = -1 + +; Minimum server message severity to display. +sybct.min_server_severity = 10 + +; Minimum client message severity to display. +sybct.min_client_severity = 10 + +[bcmath] +; Number of decimal digits for all bcmath functions. +bcmath.scale = 0 + +[browscap] +;browscap = extra/browscap.ini + +[Informix] +; Default host for ifx_connect() (doesn't apply in safe mode). +ifx.default_host = + +; Default user for ifx_connect() (doesn't apply in safe mode). +ifx.default_user = + +; Default password for ifx_connect() (doesn't apply in safe mode). +ifx.default_password = + +; Allow or prevent persistent links. +ifx.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +ifx.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +ifx.max_links = -1 + +; If on, select statements return the contents of a text blob instead of its id. +ifx.textasvarchar = 0 + +; If on, select statements return the contents of a byte blob instead of its id. +ifx.byteasvarchar = 0 + +; Trailing blanks are stripped from fixed-length char columns. May help the +; life of Informix SE users. +ifx.charasvarchar = 0 + +; If on, the contents of text and byte blobs are dumped to a file instead of +; keeping them in memory. +ifx.blobinfile = 0 + +; NULL's are returned as empty strings, unless this is set to 1. In that case, +; NULL's are returned as string 'NULL'. +ifx.nullformat = 0 + +[Session] +; Handler used to store/retrieve data. +session.save_handler = files + +; Argument passed to save_handler. In the case of files, this is the path +; where data files are stored. Note: Windows users have to change this +; variable in order to use PHP's session functions. +; +; As of PHP 4.0.1, you can define the path as: +; +; session.save_path = "N;/path" +; +; where N is an integer. Instead of storing all the session files in +; /path, what this will do is use subdirectories N-levels deep, and +; store the session data in those directories. This is useful if you +; or your OS have problems with lots of files in one directory, and is +; a more efficient layout for servers that handle lots of sessions. +; +; NOTE 1: PHP will not create this directory structure automatically. +; You can use the script in the ext/session dir for that purpose. +; NOTE 2: See the section on garbage collection below if you choose to +; use subdirectories for session storage +; +; The file storage module creates files using mode 600 by default. +; You can change that by using +; +; session.save_path = "N;MODE;/path" +; +; where MODE is the octal representation of the mode. Note that this +; does not overwrite the process's umask. +session.save_path = "/var/lib/php/session" + +; Whether to use cookies. +session.use_cookies = 1 + +; This option enables administrators to make their users invulnerable to +; attacks which involve passing session ids in URLs; defaults to 0. +; session.use_only_cookies = 1 + +; Name of the session (used as cookie name). +session.name = PHPSESSID + +; Initialize session on request startup. +session.auto_start = 0 + +; Lifetime in seconds of cookie or, if 0, until browser is restarted. +session.cookie_lifetime = 0 + +; The path for which the cookie is valid. +session.cookie_path = / + +; The domain for which the cookie is valid. +session.cookie_domain = + +; Handler used to serialize data. php is the standard serializer of PHP. +session.serialize_handler = php + +; Define the probability that the 'garbage collection' process is started +; on every session initialization. +; The probability is calculated by using gc_probability/gc_divisor, +; e.g. 1/100 means there is a 1% chance that the GC process starts +; on each request. + +session.gc_probability = 1 +session.gc_divisor = 1000 + +; After this number of seconds, stored data will be seen as 'garbage' and +; cleaned up by the garbage collection process. +session.gc_maxlifetime = 1440 + +; NOTE: If you are using the subdirectory option for storing session files +; (see session.save_path above), then garbage collection does *not* +; happen automatically. You will need to do your own garbage +; collection through a shell script, cron entry, or some other method. +; For example, the following script would is the equivalent of +; setting session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes): +; cd /path/to/sessions; find -cmin +24 | xargs rm + +; PHP 4.2 and less have an undocumented feature/bug that allows you to +; to initialize a session variable in the global scope, albeit register_globals +; is disabled. PHP 4.3 and later will warn you, if this feature is used. +; You can disable the feature and the warning separately. At this time, +; the warning is only displayed, if bug_compat_42 is enabled. + +session.bug_compat_42 = 0 +session.bug_compat_warn = 1 + +; Check HTTP Referer to invalidate externally stored URLs containing ids. +; HTTP_REFERER has to contain this substring for the session to be +; considered as valid. +session.referer_check = + +; How many bytes to read from the file. +session.entropy_length = 0 + +; Specified here to create the session id. +session.entropy_file = + +;session.entropy_length = 16 + +;session.entropy_file = /dev/urandom + +; Set to {nocache,private,public,} to determine HTTP caching aspects +; or leave this empty to avoid sending anti-caching headers. +session.cache_limiter = nocache + +; Document expires after n minutes. +session.cache_expire = 180 + +; trans sid support is disabled by default. +; Use of trans sid may risk your users security. +; Use this option with caution. +; - User may send URL contains active session ID +; to other person via. email/irc/etc. +; - URL that contains active session ID may be stored +; in publically accessible computer. +; - User may access your site with the same session ID +; always using URL stored in browser's history or bookmarks. +session.use_trans_sid = 0 + +; Select a hash function +; 0: MD5 (128 bits) +; 1: SHA-1 (160 bits) +session.hash_function = 0 + +; Define how many bits are stored in each character when converting +; the binary hash data to something readable. +; +; 4 bits: 0-9, a-f +; 5 bits: 0-9, a-v +; 6 bits: 0-9, a-z, A-Z, "-", "," +session.hash_bits_per_character = 5 + +; The URL rewriter will look for URLs in a defined set of HTML tags. +; form/fieldset are special; if you include them here, the rewriter will +; add a hidden field with the info which is otherwise appended +; to URLs. If you want XHTML conformity, remove the form entry. +; Note that all valid entries require a "=", even if no value follows. +url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry" + +[MSSQL] +; Allow or prevent persistent links. +mssql.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +mssql.max_persistent = -1 + +; Maximum number of links (persistent+non persistent). -1 means no limit. +mssql.max_links = -1 + +; Minimum error severity to display. +mssql.min_error_severity = 10 + +; Minimum message severity to display. +mssql.min_message_severity = 10 + +; Compatability mode with old versions of PHP 3.0. +mssql.compatability_mode = Off + +; Connect timeout +;mssql.connect_timeout = 5 + +; Query timeout +;mssql.timeout = 60 + +; Valid range 0 - 2147483647. Default = 4096. +;mssql.textlimit = 4096 + +; Valid range 0 - 2147483647. Default = 4096. +;mssql.textsize = 4096 + +; Limits the number of records in each batch. 0 = all records in one batch. +;mssql.batchsize = 0 + +; Specify how datetime and datetim4 columns are returned +; On => Returns data converted to SQL server settings +; Off => Returns values as YYYY-MM-DD hh:mm:ss +;mssql.datetimeconvert = On + +; Use NT authentication when connecting to the server +mssql.secure_connection = Off + +; Specify max number of processes. -1 = library default +; msdlib defaults to 25 +; FreeTDS defaults to 4096 +;mssql.max_procs = -1 + +; Specify client character set. +; If empty or not set the client charset from freetds.comf is used +; This is only used when compiled with FreeTDS +;mssql.charset = "ISO-8859-1" + +[Assertion] +; Assert(expr); active by default. +;assert.active = On + +; Issue a PHP warning for each failed assertion. +;assert.warning = On + +; Don't bail out by default. +;assert.bail = Off + +; User-function to be called if an assertion fails. +;assert.callback = 0 + +; Eval the expression with current error_reporting(). Set to true if you want +; error_reporting(0) around the eval(). +;assert.quiet_eval = 0 + +[Verisign Payflow Pro] +; Default Payflow Pro server. +pfpro.defaulthost = "test-payflow.verisign.com" + +; Default port to connect to. +pfpro.defaultport = 443 + +; Default timeout in seconds. +pfpro.defaulttimeout = 30 + +; Default proxy IP address (if required). +;pfpro.proxyaddress = + +; Default proxy port. +;pfpro.proxyport = + +; Default proxy logon. +;pfpro.proxylogon = + +; Default proxy password. +;pfpro.proxypassword = + +[COM] +; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs +;com.typelib_file = +; allow Distributed-COM calls +;com.allow_dcom = true +; autoregister constants of a components typlib on com_load() +;com.autoregister_typelib = true +; register constants casesensitive +;com.autoregister_casesensitive = false +; show warnings on duplicate constat registrations +;com.autoregister_verbose = true + +[mbstring] +; language for internal character representation. +;mbstring.language = Japanese + +; internal/script encoding. +; Some encoding cannot work as internal encoding. +; (e.g. SJIS, BIG5, ISO-2022-*) +;mbstring.internal_encoding = EUC-JP + +; http input encoding. +;mbstring.http_input = auto + +; http output encoding. mb_output_handler must be +; registered as output buffer to function +;mbstring.http_output = SJIS + +; enable automatic encoding translation according to +; mbstring.internal_encoding setting. Input chars are +; converted to internal encoding by setting this to On. +; Note: Do _not_ use automatic encoding translation for +; portable libs/applications. +;mbstring.encoding_translation = Off + +; automatic encoding detection order. +; auto means +;mbstring.detect_order = auto + +; substitute_character used when character cannot be converted +; one from another +;mbstring.substitute_character = none; + +; overload(replace) single byte functions by mbstring functions. +; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(), +; etc. Possible values are 0,1,2,4 or combination of them. +; For example, 7 for overload everything. +; 0: No overload +; 1: Overload mail() function +; 2: Overload str*() functions +; 4: Overload ereg*() functions +;mbstring.func_overload = 0 + +; enable strict encoding detection. +;mbstring.strict_encoding = Off + +[FrontBase] +;fbsql.allow_persistent = On +;fbsql.autocommit = On +;fbsql.default_database = +;fbsql.default_database_password = +;fbsql.default_host = +;fbsql.default_password = +;fbsql.default_user = "_SYSTEM" +;fbsql.generate_warnings = Off +;fbsql.max_connections = 128 +;fbsql.max_links = 128 +;fbsql.max_persistent = -1 +;fbsql.max_results = 128 +;fbsql.batchSize = 1000 + +[gd] +; Tell the jpeg decode to libjpeg warnings and try to create +; a gd image. The warning will then be displayed as notices +; disabled by default +;gd.jpeg_ignore_warning = 0 + +[exif] +; Exif UNICODE user comments are handled as UCS-2BE/UCS-2LE and JIS as JIS. +; With mbstring support this will automatically be converted into the encoding +; given by corresponding encode setting. When empty mbstring.internal_encoding +; is used. For the decode settings you can distinguish between motorola and +; intel byte order. A decode setting cannot be empty. +;exif.encode_unicode = ISO-8859-15 +;exif.decode_unicode_motorola = UCS-2BE +;exif.decode_unicode_intel = UCS-2LE +;exif.encode_jis = +;exif.decode_jis_motorola = JIS +;exif.decode_jis_intel = JIS + +[Tidy] +; The path to a default tidy configuration file to use when using tidy +;tidy.default_config = /usr/local/lib/php/default.tcfg + +; Should tidy clean and repair output automatically? +; WARNING: Do not use this option if you are generating non-html content +; such as dynamic images +tidy.clean_output = Off + +[soap] +; Enables or disables WSDL caching feature. +soap.wsdl_cache_enabled=1 +; Sets the directory name where SOAP extension will put cache files. +soap.wsdl_cache_dir="/tmp" +; (time to live) Sets the number of second while cached file will be used +; instead of original one. +soap.wsdl_cache_ttl=86400 + +; Local Variables: +; tab-width: 4 +; End: + +<% @directives.sort_by { |key, val| key }.each do |directive, value| -%> +<%= "#{directive}=#{value}" %> +<% end -%> diff --git a/cookbooks/php/templates/ubuntu/php.ini.erb b/cookbooks/php/templates/ubuntu/php.ini.erb new file mode 100644 index 0000000..9d47d75 --- /dev/null +++ b/cookbooks/php/templates/ubuntu/php.ini.erb @@ -0,0 +1,1834 @@ +[PHP] + +;;;;;;;;;;;;;;;;;;; +; About php.ini ; +;;;;;;;;;;;;;;;;;;; +; PHP's initialization file, generally called php.ini, is responsible for +; configuring many of the aspects of PHP's behavior. + +; PHP attempts to find and load this configuration from a number of locations. +; The following is a summary of its search order: +; 1. SAPI module specific location. +; 2. The PHPRC environment variable. (As of PHP 5.2.0) +; 3. A number of predefined registry keys on Windows (As of PHP 5.2.0) +; 4. Current working directory (except CLI) +; 5. The web server's directory (for SAPI modules), or directory of PHP +; (otherwise in Windows) +; 6. The directory from the --with-config-file-path compile time option, or the +; Windows directory (C:\windows or C:\winnt) +; See the PHP docs for more specific information. +; http://php.net/configuration.file + +; The syntax of the file is extremely simple. Whitespace and Lines +; beginning with a semicolon are silently ignored (as you probably guessed). +; Section headers (e.g. [Foo]) are also silently ignored, even though +; they might mean something in the future. + +; Directives following the section heading [PATH=/www/mysite] only +; apply to PHP files in the /www/mysite directory. Directives +; following the section heading [HOST=www.example.com] only apply to +; PHP files served from www.example.com. Directives set in these +; special sections cannot be overridden by user-defined INI files or +; at runtime. Currently, [PATH=] and [HOST=] sections only work under +; CGI/FastCGI. +; http://php.net/ini.sections + +; Directives are specified using the following syntax: +; directive = value +; Directive names are *case sensitive* - foo=bar is different from FOO=bar. +; Directives are variables used to configure PHP or PHP extensions. +; There is no name validation. If PHP can't find an expected +; directive because it is not set or is mistyped, a default value will be used. + +; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one +; of the INI constants (On, Off, True, False, Yes, No and None) or an expression +; (e.g. E_ALL & ~E_NOTICE), a quoted string ("bar"), or a reference to a +; previously set variable or directive (e.g. ${foo}) + +; Expressions in the INI file are limited to bitwise operators and parentheses: +; | bitwise OR +; ^ bitwise XOR +; & bitwise AND +; ~ bitwise NOT +; ! boolean NOT + +; Boolean flags can be turned on using the values 1, On, True or Yes. +; They can be turned off using the values 0, Off, False or No. + +; An empty string can be denoted by simply not writing anything after the equal +; sign, or by using the None keyword: + +; foo = ; sets foo to an empty string +; foo = None ; sets foo to an empty string +; foo = "None" ; sets foo to the string 'None' + +; If you use constants in your value, and these constants belong to a +; dynamically loaded extension (either a PHP extension or a Zend extension), +; you may only use these constants *after* the line that loads the extension. + +;;;;;;;;;;;;;;;;;;; +; About this file ; +;;;;;;;;;;;;;;;;;;; +; PHP comes packaged with two INI files. One that is recommended to be used +; in production environments and one that is recommended to be used in +; development environments. + +; php.ini-production contains settings which hold security, performance and +; best practices at its core. But please be aware, these settings may break +; compatibility with older or less security conscience applications. We +; recommending using the production ini in production and testing environments. + +; php.ini-development is very similar to its production variant, except it's +; much more verbose when it comes to errors. We recommending using the +; development version only in development environments as errors shown to +; application users can inadvertently leak otherwise secure information. + +;;;;;;;;;;;;;;;;;;; +; Quick Reference ; +;;;;;;;;;;;;;;;;;;; +; The following are all the settings which are different in either the production +; or development versions of the INIs with respect to PHP's default behavior. +; Please see the actual settings later in the document for more details as to why +; we recommend these changes in PHP's behavior. + +; display_errors +; Default Value: On +; Development Value: On +; Production Value: Off + +; display_startup_errors +; Default Value: Off +; Development Value: On +; Production Value: Off + +; error_reporting +; Default Value: E_ALL & ~E_NOTICE +; Development Value: E_ALL | E_STRICT +; Production Value: E_ALL & ~E_DEPRECATED + +; html_errors +; Default Value: On +; Development Value: On +; Production value: Off + +; log_errors +; Default Value: Off +; Development Value: On +; Production Value: On + +; magic_quotes_gpc +; Default Value: On +; Development Value: Off +; Production Value: Off + +; max_input_time +; Default Value: -1 (Unlimited) +; Development Value: 60 (60 seconds) +; Production Value: 60 (60 seconds) + +; output_buffering +; Default Value: Off +; Development Value: 4096 +; Production Value: 4096 + +; register_argc_argv +; Default Value: On +; Development Value: Off +; Production Value: Off + +; register_long_arrays +; Default Value: On +; Development Value: Off +; Production Value: Off + +; request_order +; Default Value: None +; Development Value: "GP" +; Production Value: "GP" + +; session.bug_compat_42 +; Default Value: On +; Development Value: On +; Production Value: Off + +; session.bug_compat_warn +; Default Value: On +; Development Value: On +; Production Value: Off + +; session.gc_divisor +; Default Value: 100 +; Development Value: 1000 +; Production Value: 1000 + +; session.hash_bits_per_character +; Default Value: 4 +; Development Value: 5 +; Production Value: 5 + +; short_open_tag +; Default Value: On +; Development Value: Off +; Production Value: Off + +; track_errors +; Default Value: Off +; Development Value: On +; Production Value: Off + +; url_rewriter.tags +; Default Value: "a=href,area=href,frame=src,form=,fieldset=" +; Development Value: "a=href,area=href,frame=src,input=src,form=fakeentry" +; Production Value: "a=href,area=href,frame=src,input=src,form=fakeentry" + +; variables_order +; Default Value: "EGPCS" +; Development Value: "GPCS" +; Production Value: "GPCS" + +;;;;;;;;;;;;;;;;;;;; +; php.ini Options ; +;;;;;;;;;;;;;;;;;;;; +; Name for user-defined php.ini (.htaccess) files. Default is ".user.ini" +;user_ini.filename = ".user.ini" + +; To disable this feature set this option to empty value +;user_ini.filename = + +; TTL for user-defined php.ini files (time-to-live) in seconds. Default is 300 seconds (5 minutes) +;user_ini.cache_ttl = 300 + +;;;;;;;;;;;;;;;;;;;; +; Language Options ; +;;;;;;;;;;;;;;;;;;;; + +; Enable the PHP scripting language engine under Apache. +; http://php.net/engine +engine = On + +; This directive determines whether or not PHP will recognize code between +; tags as PHP source which should be processed as such. It's been +; recommended for several years that you not use the short tag "short cut" and +; instead to use the full tag combination. With the wide spread use +; of XML and use of these tags by other languages, the server can become easily +; confused and end up parsing the wrong code in the wrong context. But because +; this short cut has been a feature for such a long time, it's currently still +; supported for backwards compatibility, but we recommend you don't use them. +; Default Value: On +; Development Value: Off +; Production Value: Off +; http://php.net/short-open-tag +short_open_tag = On + +; Allow ASP-style <% %> tags. +; http://php.net/asp-tags +asp_tags = Off + +; The number of significant digits displayed in floating point numbers. +; http://php.net/precision +precision = 14 + +; Output buffering is a mechanism for controlling how much output data +; (excluding headers and cookies) PHP should keep internally before pushing that +; data to the client. If your application's output exceeds this setting, PHP +; will send that data in chunks of roughly the size you specify. +; Turning on this setting and managing its maximum buffer size can yield some +; interesting side-effects depending on your application and web server. +; You may be able to send headers and cookies after you've already sent output +; through print or echo. You also may see performance benefits if your server is +; emitting less packets due to buffered output versus PHP streaming the output +; as it gets it. On production servers, 4096 bytes is a good setting for performance +; reasons. +; Note: Output buffering can also be controlled via Output Buffering Control +; functions. +; Possible Values: +; On = Enabled and buffer is unlimited. (Use with caution) +; Off = Disabled +; Integer = Enables the buffer and sets its maximum size in bytes. +; Note: This directive is hardcoded to Off for the CLI SAPI +; Default Value: Off +; Development Value: 4096 +; Production Value: 4096 +; http://php.net/output-buffering +output_buffering = 4096 + +; You can redirect all of the output of your scripts to a function. For +; example, if you set output_handler to "mb_output_handler", character +; encoding will be transparently converted to the specified encoding. +; Setting any output handler automatically turns on output buffering. +; Note: People who wrote portable scripts should not depend on this ini +; directive. Instead, explicitly set the output handler using ob_start(). +; Using this ini directive may cause problems unless you know what script +; is doing. +; Note: You cannot use both "mb_output_handler" with "ob_iconv_handler" +; and you cannot use both "ob_gzhandler" and "zlib.output_compression". +; Note: output_handler must be empty if this is set 'On' !!!! +; Instead you must use zlib.output_handler. +; http://php.net/output-handler +;output_handler = + +; Transparent output compression using the zlib library +; Valid values for this option are 'off', 'on', or a specific buffer size +; to be used for compression (default is 4KB) +; Note: Resulting chunk size may vary due to nature of compression. PHP +; outputs chunks that are few hundreds bytes each as a result of +; compression. If you prefer a larger chunk size for better +; performance, enable output_buffering in addition. +; Note: You need to use zlib.output_handler instead of the standard +; output_handler, or otherwise the output will be corrupted. +; http://php.net/zlib.output-compression +zlib.output_compression = Off + +; http://php.net/zlib.output-compression-level +;zlib.output_compression_level = -1 + +; You cannot specify additional output handlers if zlib.output_compression +; is activated here. This setting does the same as output_handler but in +; a different order. +; http://php.net/zlib.output-handler +;zlib.output_handler = + +; Implicit flush tells PHP to tell the output layer to flush itself +; automatically after every output block. This is equivalent to calling the +; PHP function flush() after each and every call to print() or echo() and each +; and every HTML block. Turning this option on has serious performance +; implications and is generally recommended for debugging purposes only. +; http://php.net/implicit-flush +; Note: This directive is hardcoded to On for the CLI SAPI +implicit_flush = Off + +; The unserialize callback function will be called (with the undefined class' +; name as parameter), if the unserializer finds an undefined class +; which should be instantiated. A warning appears if the specified function is +; not defined, or if the function doesn't include/implement the missing class. +; So only set this entry, if you really want to implement such a +; callback-function. +unserialize_callback_func = + +; When floats & doubles are serialized store serialize_precision significant +; digits after the floating point. The default value ensures that when floats +; are decoded with unserialize, the data will remain the same. +serialize_precision = 100 + +; Safe Mode +; http://php.net/safe-mode +safe_mode = Off + +; By default, Safe Mode does a UID compare check when +; opening files. If you want to relax this to a GID compare, +; then turn on safe_mode_gid. +; http://php.net/safe-mode-gid +safe_mode_gid = Off + +; When safe_mode is on, UID/GID checks are bypassed when +; including files from this directory and its subdirectories. +; (directory must also be in include_path or full path must +; be used when including) +; http://php.net/safe-mode-include-dir +safe_mode_include_dir = + +; When safe_mode is on, only executables located in the safe_mode_exec_dir +; will be allowed to be executed via the exec family of functions. +; http://php.net/safe-mode-exec-dir +safe_mode_exec_dir = + +; Setting certain environment variables may be a potential security breach. +; This directive contains a comma-delimited list of prefixes. In Safe Mode, +; the user may only alter environment variables whose names begin with the +; prefixes supplied here. By default, users will only be able to set +; environment variables that begin with PHP_ (e.g. PHP_FOO=BAR). +; Note: If this directive is empty, PHP will let the user modify ANY +; environment variable! +; http://php.net/safe-mode-allowed-env-vars +safe_mode_allowed_env_vars = PHP_ + +; This directive contains a comma-delimited list of environment variables that +; the end user won't be able to change using putenv(). These variables will be +; protected even if safe_mode_allowed_env_vars is set to allow to change them. +; http://php.net/safe-mode-protected-env-vars +safe_mode_protected_env_vars = LD_LIBRARY_PATH + +; open_basedir, if set, limits all file operations to the defined directory +; and below. This directive makes most sense if used in a per-directory +; or per-virtualhost web server configuration file. This directive is +; *NOT* affected by whether Safe Mode is turned On or Off. +; http://php.net/open-basedir +;open_basedir = + +; This directive allows you to disable certain functions for security reasons. +; It receives a comma-delimited list of function names. This directive is +; *NOT* affected by whether Safe Mode is turned On or Off. +; http://php.net/disable-functions +disable_functions = + +; This directive allows you to disable certain classes for security reasons. +; It receives a comma-delimited list of class names. This directive is +; *NOT* affected by whether Safe Mode is turned On or Off. +; http://php.net/disable-classes +disable_classes = + +; Colors for Syntax Highlighting mode. Anything that's acceptable in +; would work. +; http://php.net/syntax-highlighting +;highlight.string = #DD0000 +;highlight.comment = #FF9900 +;highlight.keyword = #007700 +;highlight.bg = #FFFFFF +;highlight.default = #0000BB +;highlight.html = #000000 + +; If enabled, the request will be allowed to complete even if the user aborts +; the request. Consider enabling it if executing long requests, which may end up +; being interrupted by the user or a browser timing out. PHP's default behavior +; is to disable this feature. +; http://php.net/ignore-user-abort +;ignore_user_abort = On + +; Determines the size of the realpath cache to be used by PHP. This value should +; be increased on systems where PHP opens many files to reflect the quantity of +; the file operations performed. +; http://php.net/realpath-cache-size +;realpath_cache_size = 16k + +; Duration of time, in seconds for which to cache realpath information for a given +; file or directory. For systems with rarely changing files, consider increasing this +; value. +; http://php.net/realpath-cache-ttl +;realpath_cache_ttl = 120 + +;;;;;;;;;;;;;;;;; +; Miscellaneous ; +;;;;;;;;;;;;;;;;; + +; Decides whether PHP may expose the fact that it is installed on the server +; (e.g. by adding its signature to the Web server header). It is no security +; threat in any way, but it makes it possible to determine whether you use PHP +; on your server or not. +; http://php.net/expose-php +expose_php = On + +;;;;;;;;;;;;;;;;;;; +; Resource Limits ; +;;;;;;;;;;;;;;;;;;; + +; Maximum execution time of each script, in seconds +; http://php.net/max-execution-time +; Note: This directive is hardcoded to 0 for the CLI SAPI +max_execution_time = 30 + +; Maximum amount of time each script may spend parsing request data. It's a good +; idea to limit this time on productions servers in order to eliminate unexpectedly +; long running scripts. +; Note: This directive is hardcoded to -1 for the CLI SAPI +; Default Value: -1 (Unlimited) +; Development Value: 60 (60 seconds) +; Production Value: 60 (60 seconds) +; http://php.net/max-input-time +max_input_time = 60 + +; Maximum input variable nesting level +; http://php.net/max-input-nesting-level +;max_input_nesting_level = 64 + +; Maximum amount of memory a script may consume (128MB) +; http://php.net/memory-limit +memory_limit = -1 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Error handling and logging ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; This directive informs PHP of which errors, warnings and notices you would like +; it to take action for. The recommended way of setting values for this +; directive is through the use of the error level constants and bitwise +; operators. The error level constants are below here for convenience as well as +; some common settings and their meanings. +; By default, PHP is set to take action on all errors, notices and warnings EXCEPT +; those related to E_NOTICE and E_STRICT, which together cover best practices and +; recommended coding standards in PHP. For performance reasons, this is the +; recommend error reporting setting. Your production server shouldn't be wasting +; resources complaining about best practices and coding standards. That's what +; development servers and development settings are for. +; Note: The php.ini-development file has this setting as E_ALL | E_STRICT. This +; means it pretty much reports everything which is exactly what you want during +; development and early testing. +; +; Error Level Constants: +; E_ALL - All errors and warnings (includes E_STRICT as of PHP 6.0.0) +; E_ERROR - fatal run-time errors +; E_RECOVERABLE_ERROR - almost fatal run-time errors +; E_WARNING - run-time warnings (non-fatal errors) +; E_PARSE - compile-time parse errors +; E_NOTICE - run-time notices (these are warnings which often result +; from a bug in your code, but it's possible that it was +; intentional (e.g., using an uninitialized variable and +; relying on the fact it's automatically initialized to an +; empty string) +; E_STRICT - run-time notices, enable to have PHP suggest changes +; to your code which will ensure the best interoperability +; and forward compatibility of your code +; E_CORE_ERROR - fatal errors that occur during PHP's initial startup +; E_CORE_WARNING - warnings (non-fatal errors) that occur during PHP's +; initial startup +; E_COMPILE_ERROR - fatal compile-time errors +; E_COMPILE_WARNING - compile-time warnings (non-fatal errors) +; E_USER_ERROR - user-generated error message +; E_USER_WARNING - user-generated warning message +; E_USER_NOTICE - user-generated notice message +; E_DEPRECATED - warn about code that will not work in future versions +; of PHP +; E_USER_DEPRECATED - user-generated deprecation warnings +; +; Common Values: +; E_ALL & ~E_NOTICE (Show all errors, except for notices and coding standards warnings.) +; E_ALL & ~E_NOTICE | E_STRICT (Show all errors, except for notices) +; E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR (Show only errors) +; E_ALL | E_STRICT (Show all errors, warnings and notices including coding standards.) +; Default Value: E_ALL & ~E_NOTICE +; Development Value: E_ALL | E_STRICT +; Production Value: E_ALL & ~E_DEPRECATED +; http://php.net/error-reporting +error_reporting = E_ALL & ~E_DEPRECATED + +; This directive controls whether or not and where PHP will output errors, +; notices and warnings too. Error output is very useful during development, but +; it could be very dangerous in production environments. Depending on the code +; which is triggering the error, sensitive information could potentially leak +; out of your application such as database usernames and passwords or worse. +; It's recommended that errors be logged on production servers rather than +; having the errors sent to STDOUT. +; Possible Values: +; Off = Do not display any errors +; stderr = Display errors to STDERR (affects only CGI/CLI binaries!) +; On or stdout = Display errors to STDOUT +; Default Value: On +; Development Value: On +; Production Value: Off +; http://php.net/display-errors +display_errors = Off + +; The display of errors which occur during PHP's startup sequence are handled +; separately from display_errors. PHP's default behavior is to suppress those +; errors from clients. Turning the display of startup errors on can be useful in +; debugging configuration problems. But, it's strongly recommended that you +; leave this setting off on production servers. +; Default Value: Off +; Development Value: On +; Production Value: Off +; http://php.net/display-startup-errors +display_startup_errors = Off + +; Besides displaying errors, PHP can also log errors to locations such as a +; server-specific log, STDERR, or a location specified by the error_log +; directive found below. While errors should not be displayed on productions +; servers they should still be monitored and logging is a great way to do that. +; Default Value: Off +; Development Value: On +; Production Value: On +; http://php.net/log-errors +log_errors = On + +; Set maximum length of log_errors. In error_log information about the source is +; added. The default is 1024 and 0 allows to not apply any maximum length at all. +; http://php.net/log-errors-max-len +log_errors_max_len = 1024 + +; Do not log repeated messages. Repeated errors must occur in same file on same +; line unless ignore_repeated_source is set true. +; http://php.net/ignore-repeated-errors +ignore_repeated_errors = Off + +; Ignore source of message when ignoring repeated messages. When this setting +; is On you will not log errors with repeated messages from different files or +; source lines. +; http://php.net/ignore-repeated-source +ignore_repeated_source = Off + +; If this parameter is set to Off, then memory leaks will not be shown (on +; stdout or in the log). This has only effect in a debug compile, and if +; error reporting includes E_WARNING in the allowed list +; http://php.net/report-memleaks +report_memleaks = On + +; This setting is on by default. +;report_zend_debug = 0 + +; Store the last error/warning message in $php_errormsg (boolean). Setting this value +; to On can assist in debugging and is appropriate for development servers. It should +; however be disabled on production servers. +; Default Value: Off +; Development Value: On +; Production Value: Off +; http://php.net/track-errors +track_errors = Off + +; Turn off normal error reporting and emit XML-RPC error XML +; http://php.net/xmlrpc-errors +;xmlrpc_errors = 0 + +; An XML-RPC faultCode +;xmlrpc_error_number = 0 + +; When PHP displays or logs an error, it has the capability of inserting html +; links to documentation related to that error. This directive controls whether +; those HTML links appear in error messages or not. For performance and security +; reasons, it's recommended you disable this on production servers. +; Note: This directive is hardcoded to Off for the CLI SAPI +; Default Value: On +; Development Value: On +; Production value: Off +; http://php.net/html-errors +html_errors = Off + +; If html_errors is set On PHP produces clickable error messages that direct +; to a page describing the error or function causing the error in detail. +; You can download a copy of the PHP manual from http://php.net/docs +; and change docref_root to the base URL of your local copy including the +; leading '/'. You must also specify the file extension being used including +; the dot. PHP's default behavior is to leave these settings empty. +; Note: Never use this feature for production boxes. +; http://php.net/docref-root +; Examples +;docref_root = "/phpmanual/" + +; http://php.net/docref-ext +;docref_ext = .html + +; String to output before an error message. PHP's default behavior is to leave +; this setting blank. +; http://php.net/error-prepend-string +; Example: +;error_prepend_string = "" + +; String to output after an error message. PHP's default behavior is to leave +; this setting blank. +; http://php.net/error-append-string +; Example: +;error_append_string = "" + +; Log errors to specified file. PHP's default behavior is to leave this value +; empty. +; http://php.net/error-log +; Example: +;error_log = php_errors.log +; Log errors to syslog (Event Log on NT, not valid in Windows 95). +;error_log = syslog + +;;;;;;;;;;;;;;;;; +; Data Handling ; +;;;;;;;;;;;;;;;;; + +; The separator used in PHP generated URLs to separate arguments. +; PHP's default setting is "&". +; http://php.net/arg-separator.output +; Example: +;arg_separator.output = "&" + +; List of separator(s) used by PHP to parse input URLs into variables. +; PHP's default setting is "&". +; NOTE: Every character in this directive is considered as separator! +; http://php.net/arg-separator.input +; Example: +;arg_separator.input = ";&" + +; This directive determines which super global arrays are registered when PHP +; starts up. If the register_globals directive is enabled, it also determines +; what order variables are populated into the global space. G,P,C,E & S are +; abbreviations for the following respective super globals: GET, POST, COOKIE, +; ENV and SERVER. There is a performance penalty paid for the registration of +; these arrays and because ENV is not as commonly used as the others, ENV is +; is not recommended on productions servers. You can still get access to +; the environment variables through getenv() should you need to. +; Default Value: "EGPCS" +; Development Value: "GPCS" +; Production Value: "GPCS"; +; http://php.net/variables-order +variables_order = "GPCS" + +; This directive determines which super global data (G,P,C,E & S) should +; be registered into the super global array REQUEST. If so, it also determines +; the order in which that data is registered. The values for this directive are +; specified in the same manner as the variables_order directive, EXCEPT one. +; Leaving this value empty will cause PHP to use the value set in the +; variables_order directive. It does not mean it will leave the super globals +; array REQUEST empty. +; Default Value: None +; Development Value: "GP" +; Production Value: "GP" +; http://php.net/request-order +request_order = "GP" + +; Whether or not to register the EGPCS variables as global variables. You may +; want to turn this off if you don't want to clutter your scripts' global scope +; with user data. +; You should do your best to write your scripts so that they do not require +; register_globals to be on; Using form variables as globals can easily lead +; to possible security problems, if the code is not very well thought of. +; http://php.net/register-globals +register_globals = Off + +; Determines whether the deprecated long $HTTP_*_VARS type predefined variables +; are registered by PHP or not. As they are deprecated, we obviously don't +; recommend you use them. They are on by default for compatibility reasons but +; they are not recommended on production servers. +; Default Value: On +; Development Value: Off +; Production Value: Off +; http://php.net/register-long-arrays +register_long_arrays = Off + +; This directive determines whether PHP registers $argv & $argc each time it +; runs. $argv contains an array of all the arguments passed to PHP when a script +; is invoked. $argc contains an integer representing the number of arguments +; that were passed when the script was invoked. These arrays are extremely +; useful when running scripts from the command line. When this directive is +; enabled, registering these variables consumes CPU cycles and memory each time +; a script is executed. For performance reasons, this feature should be disabled +; on production servers. +; Note: This directive is hardcoded to On for the CLI SAPI +; Default Value: On +; Development Value: Off +; Production Value: Off +; http://php.net/register-argc-argv +register_argc_argv = Off + +; When enabled, the SERVER and ENV variables are created when they're first +; used (Just In Time) instead of when the script starts. If these variables +; are not used within a script, having this directive on will result in a +; performance gain. The PHP directives register_globals, register_long_arrays, +; and register_argc_argv must be disabled for this directive to have any affect. +; http://php.net/auto-globals-jit +auto_globals_jit = On + +; Maximum size of POST data that PHP will accept. +; http://php.net/post-max-size +post_max_size = 8M + +; Magic quotes are a preprocessing feature of PHP where PHP will attempt to +; escape any character sequences in GET, POST, COOKIE and ENV data which might +; otherwise corrupt data being placed in resources such as databases before +; making that data available to you. Because of character encoding issues and +; non-standard SQL implementations across many databases, it's not currently +; possible for this feature to be 100% accurate. PHP's default behavior is to +; enable the feature. We strongly recommend you use the escaping mechanisms +; designed specifically for the database your using instead of relying on this +; feature. Also note, this feature has been deprecated as of PHP 5.3.0 and is +; scheduled for removal in PHP 6. +; Default Value: On +; Development Value: Off +; Production Value: Off +; http://php.net/magic-quotes-gpc +magic_quotes_gpc = Off + +; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc. +; http://php.net/magic-quotes-runtime +magic_quotes_runtime = Off + +; Use Sybase-style magic quotes (escape ' with '' instead of \'). +; http://php.net/magic-quotes-sybase +magic_quotes_sybase = Off + +; Automatically add files before PHP document. +; http://php.net/auto-prepend-file +auto_prepend_file = + +; Automatically add files after PHP document. +; http://php.net/auto-append-file +auto_append_file = + +; By default, PHP will output a character encoding using +; the Content-type: header. To disable sending of the charset, simply +; set it to be empty. +; +; PHP's built-in default is text/html +; http://php.net/default-mimetype +default_mimetype = "text/html" + +; PHP's default character set is set to empty. +; http://php.net/default-charset +;default_charset = "iso-8859-1" + +; Always populate the $HTTP_RAW_POST_DATA variable. PHP's default behavior is +; to disable this feature. +; http://php.net/always-populate-raw-post-data +;always_populate_raw_post_data = On + +;;;;;;;;;;;;;;;;;;;;;;;;; +; Paths and Directories ; +;;;;;;;;;;;;;;;;;;;;;;;;; + +; UNIX: "/path1:/path2" +;include_path = ".:/usr/share/php" +; +; Windows: "\path1;\path2" +;include_path = ".;c:\php\includes" +; +; PHP's default setting for include_path is ".;/path/to/php/pear" +; http://php.net/include-path + +; The root of the PHP pages, used only if nonempty. +; if PHP was not compiled with FORCE_REDIRECT, you SHOULD set doc_root +; if you are running php as a CGI under any web server (other than IIS) +; see documentation for security issues. The alternate is to use the +; cgi.force_redirect configuration below +; http://php.net/doc-root +doc_root = + +; The directory under which PHP opens the script using /~username used only +; if nonempty. +; http://php.net/user-dir +user_dir = + +; Directory in which the loadable extensions (modules) reside. +; http://php.net/extension-dir +; extension_dir = "./" +; On windows: +; extension_dir = "ext" + +; Whether or not to enable the dl() function. The dl() function does NOT work +; properly in multithreaded servers, such as IIS or Zeus, and is automatically +; disabled on them. +; http://php.net/enable-dl +enable_dl = Off + +; cgi.force_redirect is necessary to provide security running PHP as a CGI under +; most web servers. Left undefined, PHP turns this on by default. You can +; turn it off here AT YOUR OWN RISK +; **You CAN safely turn this off for IIS, in fact, you MUST.** +; http://php.net/cgi.force-redirect +;cgi.force_redirect = 1 + +; if cgi.nph is enabled it will force cgi to always sent Status: 200 with +; every request. PHP's default behavior is to disable this feature. +;cgi.nph = 1 + +; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape +; (iPlanet) web servers, you MAY need to set an environment variable name that PHP +; will look for to know it is OK to continue execution. Setting this variable MAY +; cause security issues, KNOW WHAT YOU ARE DOING FIRST. +; http://php.net/cgi.redirect-status-env +;cgi.redirect_status_env = ; + +; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's +; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok +; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting +; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting +; of zero causes PHP to behave as before. Default is 1. You should fix your scripts +; to use SCRIPT_FILENAME rather than PATH_TRANSLATED. +; http://php.net/cgi.fix-pathinfo +;cgi.fix_pathinfo=1 + +; FastCGI under IIS (on WINNT based OS) supports the ability to impersonate +; security tokens of the calling client. This allows IIS to define the +; security context that the request runs under. mod_fastcgi under Apache +; does not currently support this feature (03/17/2002) +; Set to 1 if running under IIS. Default is zero. +; http://php.net/fastcgi.impersonate +;fastcgi.impersonate = 1; + +; Disable logging through FastCGI connection. PHP's default behavior is to enable +; this feature. +;fastcgi.logging = 0 + +; cgi.rfc2616_headers configuration option tells PHP what type of headers to +; use when sending HTTP response code. If it's set 0 PHP sends Status: header that +; is supported by Apache. When this option is set to 1 PHP will send +; RFC2616 compliant header. +; Default is zero. +; http://php.net/cgi.rfc2616-headers +;cgi.rfc2616_headers = 0 + +;;;;;;;;;;;;;;;; +; File Uploads ; +;;;;;;;;;;;;;;;; + +; Whether to allow HTTP file uploads. +; http://php.net/file-uploads +file_uploads = On + +; Temporary directory for HTTP uploaded files (will use system default if not +; specified). +; http://php.net/upload-tmp-dir +;upload_tmp_dir = + +; Maximum allowed size for uploaded files. +; http://php.net/upload-max-filesize +upload_max_filesize = 2M + +; Maximum number of files that can be uploaded via a single request +max_file_uploads = 20 + +;;;;;;;;;;;;;;;;;; +; Fopen wrappers ; +;;;;;;;;;;;;;;;;;; + +; Whether to allow the treatment of URLs (like http:// or ftp://) as files. +; http://php.net/allow-url-fopen +allow_url_fopen = On + +; Whether to allow include/require to open URLs (like http:// or ftp://) as files. +; http://php.net/allow-url-include +allow_url_include = Off + +; Define the anonymous ftp password (your email address). PHP's default setting +; for this is empty. +; http://php.net/from +;from="john@doe.com" + +; Define the User-Agent string. PHP's default setting for this is empty. +; http://php.net/user-agent +;user_agent="PHP" + +; Default timeout for socket based streams (seconds) +; http://php.net/default-socket-timeout +default_socket_timeout = 60 + +; If your scripts have to deal with files from Macintosh systems, +; or you are running on a Mac and need to deal with files from +; unix or win32 systems, setting this flag will cause PHP to +; automatically detect the EOL character in those files so that +; fgets() and file() will work regardless of the source of the file. +; http://php.net/auto-detect-line-endings +;auto_detect_line_endings = Off + +;;;;;;;;;;;;;;;;;;;;;; +; Dynamic Extensions ; +;;;;;;;;;;;;;;;;;;;;;; + +; If you wish to have an extension loaded automatically, use the following +; syntax: +; +; extension=modulename.extension +; +; For example, on Windows: +; +; extension=msql.dll +; +; ... or under UNIX: +; +; extension=msql.so +; +; ... or with a path: +; +; extension=/path/to/extension/msql.so +; +; If you only provide the name of the extension, PHP will look for it in its +; default extension directory. +; + +;;;;;;;;;;;;;;;;;;; +; Module Settings ; +;;;;;;;;;;;;;;;;;;; + +[Date] +; Defines the default timezone used by the date functions +; http://php.net/date.timezone +;date.timezone = + +; http://php.net/date.default-latitude +;date.default_latitude = 31.7667 + +; http://php.net/date.default-longitude +;date.default_longitude = 35.2333 + +; http://php.net/date.sunrise-zenith +;date.sunrise_zenith = 90.583333 + +; http://php.net/date.sunset-zenith +;date.sunset_zenith = 90.583333 + +[filter] +; http://php.net/filter.default +;filter.default = unsafe_raw + +; http://php.net/filter.default-flags +;filter.default_flags = + +[iconv] +;iconv.input_encoding = ISO-8859-1 +;iconv.internal_encoding = ISO-8859-1 +;iconv.output_encoding = ISO-8859-1 + +[intl] +;intl.default_locale = +; This directive allows you to produce PHP errors when some error +; happens within intl functions. The value is the level of the error produced. +; Default is 0, which does not produce any errors. +;intl.error_level = E_WARNING + +[sqlite] +; http://php.net/sqlite.assoc-case +;sqlite.assoc_case = 0 + +[sqlite3] +;sqlite3.extension_dir = + +[Pcre] +;PCRE library backtracking limit. +; http://php.net/pcre.backtrack-limit +;pcre.backtrack_limit=100000 + +;PCRE library recursion limit. +;Please note that if you set this value to a high number you may consume all +;the available process stack and eventually crash PHP (due to reaching the +;stack size limit imposed by the Operating System). +; http://php.net/pcre.recursion-limit +;pcre.recursion_limit=100000 + +[Pdo] +; Whether to pool ODBC connections. Can be one of "strict", "relaxed" or "off" +; http://php.net/pdo-odbc.connection-pooling +;pdo_odbc.connection_pooling=strict + +;pdo_odbc.db2_instance_name + +[Pdo_mysql] +; If mysqlnd is used: Number of cache slots for the internal result set cache +; http://php.net/pdo_mysql.cache_size +pdo_mysql.cache_size = 2000 + +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +; http://php.net/pdo_mysql.default-socket +pdo_mysql.default_socket= + +[Phar] +; http://php.net/phar.readonly +;phar.readonly = On + +; http://php.net/phar.require-hash +;phar.require_hash = On + +;phar.cache_list = + +[Syslog] +; Whether or not to define the various syslog variables (e.g. $LOG_PID, +; $LOG_CRON, etc.). Turning it off is a good idea performance-wise. In +; runtime, you can define these variables by calling define_syslog_variables(). +; http://php.net/define-syslog-variables +define_syslog_variables = Off + +[mail function] +; For Win32 only. +; http://php.net/smtp +SMTP = localhost +; http://php.net/smtp-port +smtp_port = 25 + +; For Win32 only. +; http://php.net/sendmail-from +;sendmail_from = me@example.com + +; For Unix only. You may supply arguments as well (default: "sendmail -t -i"). +; http://php.net/sendmail-path +;sendmail_path = + +; Force the addition of the specified parameters to be passed as extra parameters +; to the sendmail binary. These parameters will always replace the value of +; the 5th parameter to mail(), even in safe mode. +;mail.force_extra_parameters = + +; Add X-PHP-Originating-Script: that will include uid of the script followed by the filename +mail.add_x_header = On + +; Log all mail() calls including the full path of the script, line #, to address and headers +;mail.log = + +[SQL] +; http://php.net/sql.safe-mode +sql.safe_mode = Off + +[ODBC] +; http://php.net/odbc.default-db +;odbc.default_db = Not yet implemented + +; http://php.net/odbc.default-user +;odbc.default_user = Not yet implemented + +; http://php.net/odbc.default-pw +;odbc.default_pw = Not yet implemented + +; Controls the ODBC cursor model. +; Default: SQL_CURSOR_STATIC (default). +;odbc.default_cursortype + +; Allow or prevent persistent links. +; http://php.net/odbc.allow-persistent +odbc.allow_persistent = On + +; Check that a connection is still valid before reuse. +; http://php.net/odbc.check-persistent +odbc.check_persistent = On + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/odbc.max-persistent +odbc.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +; http://php.net/odbc.max-links +odbc.max_links = -1 + +; Handling of LONG fields. Returns number of bytes to variables. 0 means +; passthru. +; http://php.net/odbc.defaultlrl +odbc.defaultlrl = 4096 + +; Handling of binary data. 0 means passthru, 1 return as is, 2 convert to char. +; See the documentation on odbc_binmode and odbc_longreadlen for an explanation +; of odbc.defaultlrl and odbc.defaultbinmode +; http://php.net/odbc.defaultbinmode +odbc.defaultbinmode = 1 + +;birdstep.max_links = -1 + +[Interbase] +; Allow or prevent persistent links. +ibase.allow_persistent = 1 + +; Maximum number of persistent links. -1 means no limit. +ibase.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +ibase.max_links = -1 + +; Default database name for ibase_connect(). +;ibase.default_db = + +; Default username for ibase_connect(). +;ibase.default_user = + +; Default password for ibase_connect(). +;ibase.default_password = + +; Default charset for ibase_connect(). +;ibase.default_charset = + +; Default timestamp format. +ibase.timestampformat = "%Y-%m-%d %H:%M:%S" + +; Default date format. +ibase.dateformat = "%Y-%m-%d" + +; Default time format. +ibase.timeformat = "%H:%M:%S" + +[MySQL] +; Allow accessing, from PHP's perspective, local files with LOAD DATA statements +; http://php.net/mysql.allow_local_infile +mysql.allow_local_infile = On + +; Allow or prevent persistent links. +; http://php.net/mysql.allow-persistent +mysql.allow_persistent = On + +; If mysqlnd is used: Number of cache slots for the internal result set cache +; http://php.net/mysql.cache_size +mysql.cache_size = 2000 + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/mysql.max-persistent +mysql.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +; http://php.net/mysql.max-links +mysql.max_links = -1 + +; Default port number for mysql_connect(). If unset, mysql_connect() will use +; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the +; compile-time value defined MYSQL_PORT (in that order). Win32 will only look +; at MYSQL_PORT. +; http://php.net/mysql.default-port +mysql.default_port = + +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +; http://php.net/mysql.default-socket +mysql.default_socket = + +; Default host for mysql_connect() (doesn't apply in safe mode). +; http://php.net/mysql.default-host +mysql.default_host = + +; Default user for mysql_connect() (doesn't apply in safe mode). +; http://php.net/mysql.default-user +mysql.default_user = + +; Default password for mysql_connect() (doesn't apply in safe mode). +; Note that this is generally a *bad* idea to store passwords in this file. +; *Any* user with PHP access can run 'echo get_cfg_var("mysql.default_password") +; and reveal this password! And of course, any users with read access to this +; file will be able to reveal the password as well. +; http://php.net/mysql.default-password +mysql.default_password = + +; Maximum time (in seconds) for connect timeout. -1 means no limit +; http://php.net/mysql.connect-timeout +mysql.connect_timeout = 60 + +; Trace mode. When trace_mode is active (=On), warnings for table/index scans and +; SQL-Errors will be displayed. +; http://php.net/mysql.trace-mode +mysql.trace_mode = Off + +[MySQLi] + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/mysqli.max-persistent +mysqli.max_persistent = -1 + +; Allow accessing, from PHP's perspective, local files with LOAD DATA statements +; http://php.net/mysqli.allow_local_infile +;mysqli.allow_local_infile = On + +; Allow or prevent persistent links. +; http://php.net/mysqli.allow-persistent +mysqli.allow_persistent = On + +; Maximum number of links. -1 means no limit. +; http://php.net/mysqli.max-links +mysqli.max_links = -1 + +; If mysqlnd is used: Number of cache slots for the internal result set cache +; http://php.net/mysqli.cache_size +mysqli.cache_size = 2000 + +; Default port number for mysqli_connect(). If unset, mysqli_connect() will use +; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the +; compile-time value defined MYSQL_PORT (in that order). Win32 will only look +; at MYSQL_PORT. +; http://php.net/mysqli.default-port +mysqli.default_port = 3306 + +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +; http://php.net/mysqli.default-socket +mysqli.default_socket = + +; Default host for mysql_connect() (doesn't apply in safe mode). +; http://php.net/mysqli.default-host +mysqli.default_host = + +; Default user for mysql_connect() (doesn't apply in safe mode). +; http://php.net/mysqli.default-user +mysqli.default_user = + +; Default password for mysqli_connect() (doesn't apply in safe mode). +; Note that this is generally a *bad* idea to store passwords in this file. +; *Any* user with PHP access can run 'echo get_cfg_var("mysqli.default_pw") +; and reveal this password! And of course, any users with read access to this +; file will be able to reveal the password as well. +; http://php.net/mysqli.default-pw +mysqli.default_pw = + +; Allow or prevent reconnect +mysqli.reconnect = Off + +[mysqlnd] +; Enable / Disable collection of general statstics by mysqlnd which can be +; used to tune and monitor MySQL operations. +; http://php.net/mysqlnd.collect_statistics +mysqlnd.collect_statistics = On + +; Enable / Disable collection of memory usage statstics by mysqlnd which can be +; used to tune and monitor MySQL operations. +; http://php.net/mysqlnd.collect_memory_statistics +mysqlnd.collect_memory_statistics = Off + +; Size of a pre-allocated buffer used when sending commands to MySQL in bytes. +; http://php.net/mysqlnd.net_cmd_buffer_size +;mysqlnd.net_cmd_buffer_size = 2048 + +; Size of a pre-allocated buffer used for reading data sent by the server in +; bytes. +; http://php.net/mysqlnd.net_read_buffer_size +;mysqlnd.net_read_buffer_size = 32768 + +[OCI8] + +; Connection: Enables privileged connections using external +; credentials (OCI_SYSOPER, OCI_SYSDBA) +; http://php.net/oci8.privileged-connect +;oci8.privileged_connect = Off + +; Connection: The maximum number of persistent OCI8 connections per +; process. Using -1 means no limit. +; http://php.net/oci8.max-persistent +;oci8.max_persistent = -1 + +; Connection: The maximum number of seconds a process is allowed to +; maintain an idle persistent connection. Using -1 means idle +; persistent connections will be maintained forever. +; http://php.net/oci8.persistent-timeout +;oci8.persistent_timeout = -1 + +; Connection: The number of seconds that must pass before issuing a +; ping during oci_pconnect() to check the connection validity. When +; set to 0, each oci_pconnect() will cause a ping. Using -1 disables +; pings completely. +; http://php.net/oci8.ping-interval +;oci8.ping_interval = 60 + +; Connection: Set this to a user chosen connection class to be used +; for all pooled server requests with Oracle 11g Database Resident +; Connection Pooling (DRCP). To use DRCP, this value should be set to +; the same string for all web servers running the same application, +; the database pool must be configured, and the connection string must +; specify to use a pooled server. +;oci8.connection_class = + +; High Availability: Using On lets PHP receive Fast Application +; Notification (FAN) events generated when a database node fails. The +; database must also be configured to post FAN events. +;oci8.events = Off + +; Tuning: This option enables statement caching, and specifies how +; many statements to cache. Using 0 disables statement caching. +; http://php.net/oci8.statement-cache-size +;oci8.statement_cache_size = 20 + +; Tuning: Enables statement prefetching and sets the default number of +; rows that will be fetched automatically after statement execution. +; http://php.net/oci8.default-prefetch +;oci8.default_prefetch = 100 + +; Compatibility. Using On means oci_close() will not close +; oci_connect() and oci_new_connect() connections. +; http://php.net/oci8.old-oci-close-semantics +;oci8.old_oci_close_semantics = Off + +[PostgresSQL] +; Allow or prevent persistent links. +; http://php.net/pgsql.allow-persistent +pgsql.allow_persistent = On + +; Detect broken persistent links always with pg_pconnect(). +; Auto reset feature requires a little overheads. +; http://php.net/pgsql.auto-reset-persistent +pgsql.auto_reset_persistent = Off + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/pgsql.max-persistent +pgsql.max_persistent = -1 + +; Maximum number of links (persistent+non persistent). -1 means no limit. +; http://php.net/pgsql.max-links +pgsql.max_links = -1 + +; Ignore PostgreSQL backends Notice message or not. +; Notice message logging require a little overheads. +; http://php.net/pgsql.ignore-notice +pgsql.ignore_notice = 0 + +; Log PostgreSQL backends Noitce message or not. +; Unless pgsql.ignore_notice=0, module cannot log notice message. +; http://php.net/pgsql.log-notice +pgsql.log_notice = 0 + +[Sybase-CT] +; Allow or prevent persistent links. +; http://php.net/sybct.allow-persistent +sybct.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/sybct.max-persistent +sybct.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +; http://php.net/sybct.max-links +sybct.max_links = -1 + +; Minimum server message severity to display. +; http://php.net/sybct.min-server-severity +sybct.min_server_severity = 10 + +; Minimum client message severity to display. +; http://php.net/sybct.min-client-severity +sybct.min_client_severity = 10 + +; Set per-context timeout +; http://php.net/sybct.timeout +;sybct.timeout= + +;sybct.packet_size + +; The maximum time in seconds to wait for a connection attempt to succeed before returning failure. +; Default: one minute +;sybct.login_timeout= + +; The name of the host you claim to be connecting from, for display by sp_who. +; Default: none +;sybct.hostname= + +; Allows you to define how often deadlocks are to be retried. -1 means "forever". +; Default: 0 +;sybct.deadlock_retry_count= + +[bcmath] +; Number of decimal digits for all bcmath functions. +; http://php.net/bcmath.scale +bcmath.scale = 0 + +[browscap] +; http://php.net/browscap +;browscap = extra/browscap.ini + +[Session] +; Handler used to store/retrieve data. +; http://php.net/session.save-handler +session.save_handler = files + +; Argument passed to save_handler. In the case of files, this is the path +; where data files are stored. Note: Windows users have to change this +; variable in order to use PHP's session functions. +; +; The path can be defined as: +; +; session.save_path = "N;/path" +; +; where N is an integer. Instead of storing all the session files in +; /path, what this will do is use subdirectories N-levels deep, and +; store the session data in those directories. This is useful if you +; or your OS have problems with lots of files in one directory, and is +; a more efficient layout for servers that handle lots of sessions. +; +; NOTE 1: PHP will not create this directory structure automatically. +; You can use the script in the ext/session dir for that purpose. +; NOTE 2: See the section on garbage collection below if you choose to +; use subdirectories for session storage +; +; The file storage module creates files using mode 600 by default. +; You can change that by using +; +; session.save_path = "N;MODE;/path" +; +; where MODE is the octal representation of the mode. Note that this +; does not overwrite the process's umask. +; http://php.net/session.save-path +;session.save_path = "/tmp" + +; Whether to use cookies. +; http://php.net/session.use-cookies +session.use_cookies = 1 + +; http://php.net/session.cookie-secure +;session.cookie_secure = + +; This option forces PHP to fetch and use a cookie for storing and maintaining +; the session id. We encourage this operation as it's very helpful in combatting +; session hijacking when not specifying and managing your own session id. It is +; not the end all be all of session hijacking defense, but it's a good start. +; http://php.net/session.use-only-cookies +session.use_only_cookies = 1 + +; Name of the session (used as cookie name). +; http://php.net/session.name +session.name = PHPSESSID + +; Initialize session on request startup. +; http://php.net/session.auto-start +session.auto_start = 0 + +; Lifetime in seconds of cookie or, if 0, until browser is restarted. +; http://php.net/session.cookie-lifetime +session.cookie_lifetime = 0 + +; The path for which the cookie is valid. +; http://php.net/session.cookie-path +session.cookie_path = / + +; The domain for which the cookie is valid. +; http://php.net/session.cookie-domain +session.cookie_domain = + +; Whether or not to add the httpOnly flag to the cookie, which makes it inaccessible to browser scripting languages such as JavaScript. +; http://php.net/session.cookie-httponly +session.cookie_httponly = + +; Handler used to serialize data. php is the standard serializer of PHP. +; http://php.net/session.serialize-handler +session.serialize_handler = php + +; Defines the probability that the 'garbage collection' process is started +; on every session initialization. The probability is calculated by using +; gc_probability/gc_divisor. Where session.gc_probability is the numerator +; and gc_divisor is the denominator in the equation. Setting this value to 1 +; when the session.gc_divisor value is 100 will give you approximately a 1% chance +; the gc will run on any give request. +; Default Value: 1 +; Development Value: 1 +; Production Value: 1 +; http://php.net/session.gc-probability +session.gc_probability = 1 + +; Defines the probability that the 'garbage collection' process is started on every +; session initialization. The probability is calculated by using the following equation: +; gc_probability/gc_divisor. Where session.gc_probability is the numerator and +; session.gc_divisor is the denominator in the equation. Setting this value to 1 +; when the session.gc_divisor value is 100 will give you approximately a 1% chance +; the gc will run on any give request. Increasing this value to 1000 will give you +; a 0.1% chance the gc will run on any give request. For high volume production servers, +; this is a more efficient approach. +; Default Value: 100 +; Development Value: 1000 +; Production Value: 1000 +; http://php.net/session.gc-divisor +session.gc_divisor = 1000 + +; After this number of seconds, stored data will be seen as 'garbage' and +; cleaned up by the garbage collection process. +; http://php.net/session.gc-maxlifetime +session.gc_maxlifetime = 1440 + +; NOTE: If you are using the subdirectory option for storing session files +; (see session.save_path above), then garbage collection does *not* +; happen automatically. You will need to do your own garbage +; collection through a shell script, cron entry, or some other method. +; For example, the following script would is the equivalent of +; setting session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes): +; cd /path/to/sessions; find -cmin +24 | xargs rm + +; PHP 4.2 and less have an undocumented feature/bug that allows you to +; to initialize a session variable in the global scope, even when register_globals +; is disabled. PHP 4.3 and later will warn you, if this feature is used. +; You can disable the feature and the warning separately. At this time, +; the warning is only displayed, if bug_compat_42 is enabled. This feature +; introduces some serious security problems if not handled correctly. It's +; recommended that you do not use this feature on production servers. But you +; should enable this on development servers and enable the warning as well. If you +; do not enable the feature on development servers, you won't be warned when it's +; used and debugging errors caused by this can be difficult to track down. +; Default Value: On +; Development Value: On +; Production Value: Off +; http://php.net/session.bug-compat-42 +session.bug_compat_42 = Off + +; This setting controls whether or not you are warned by PHP when initializing a +; session value into the global space. session.bug_compat_42 must be enabled before +; these warnings can be issued by PHP. See the directive above for more information. +; Default Value: On +; Development Value: On +; Production Value: Off +; http://php.net/session.bug-compat-warn +session.bug_compat_warn = Off + +; Check HTTP Referer to invalidate externally stored URLs containing ids. +; HTTP_REFERER has to contain this substring for the session to be +; considered as valid. +; http://php.net/session.referer-check +session.referer_check = + +; How many bytes to read from the file. +; http://php.net/session.entropy-length +session.entropy_length = 0 + +; Specified here to create the session id. +; http://php.net/session.entropy-file +;session.entropy_file = /dev/urandom +session.entropy_file = + +; http://php.net/session.entropy-length +;session.entropy_length = 16 + +; Set to {nocache,private,public,} to determine HTTP caching aspects +; or leave this empty to avoid sending anti-caching headers. +; http://php.net/session.cache-limiter +session.cache_limiter = nocache + +; Document expires after n minutes. +; http://php.net/session.cache-expire +session.cache_expire = 180 + +; trans sid support is disabled by default. +; Use of trans sid may risk your users security. +; Use this option with caution. +; - User may send URL contains active session ID +; to other person via. email/irc/etc. +; - URL that contains active session ID may be stored +; in publically accessible computer. +; - User may access your site with the same session ID +; always using URL stored in browser's history or bookmarks. +; http://php.net/session.use-trans-sid +session.use_trans_sid = 0 + +; Select a hash function for use in generating session ids. +; Possible Values +; 0 (MD5 128 bits) +; 1 (SHA-1 160 bits) +; This option may also be set to the name of any hash function supported by +; the hash extension. A list of available hashes is returned by the hash_alogs() +; function. +; http://php.net/session.hash-function +session.hash_function = 0 + +; Define how many bits are stored in each character when converting +; the binary hash data to something readable. +; Possible values: +; 4 (4 bits: 0-9, a-f) +; 5 (5 bits: 0-9, a-v) +; 6 (6 bits: 0-9, a-z, A-Z, "-", ",") +; Default Value: 4 +; Development Value: 5 +; Production Value: 5 +; http://php.net/session.hash-bits-per-character +session.hash_bits_per_character = 5 + +; The URL rewriter will look for URLs in a defined set of HTML tags. +; form/fieldset are special; if you include them here, the rewriter will +; add a hidden field with the info which is otherwise appended +; to URLs. If you want XHTML conformity, remove the form entry. +; Note that all valid entries require a "=", even if no value follows. +; Default Value: "a=href,area=href,frame=src,form=,fieldset=" +; Development Value: "a=href,area=href,frame=src,input=src,form=fakeentry" +; Production Value: "a=href,area=href,frame=src,input=src,form=fakeentry" +; http://php.net/url-rewriter.tags +url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry" + +[MSSQL] +; Allow or prevent persistent links. +mssql.allow_persistent = On + +; Maximum number of persistent links. -1 means no limit. +mssql.max_persistent = -1 + +; Maximum number of links (persistent+non persistent). -1 means no limit. +mssql.max_links = -1 + +; Minimum error severity to display. +mssql.min_error_severity = 10 + +; Minimum message severity to display. +mssql.min_message_severity = 10 + +; Compatibility mode with old versions of PHP 3.0. +mssql.compatability_mode = Off + +; Connect timeout +;mssql.connect_timeout = 5 + +; Query timeout +;mssql.timeout = 60 + +; Valid range 0 - 2147483647. Default = 4096. +;mssql.textlimit = 4096 + +; Valid range 0 - 2147483647. Default = 4096. +;mssql.textsize = 4096 + +; Limits the number of records in each batch. 0 = all records in one batch. +;mssql.batchsize = 0 + +; Specify how datetime and datetim4 columns are returned +; On => Returns data converted to SQL server settings +; Off => Returns values as YYYY-MM-DD hh:mm:ss +;mssql.datetimeconvert = On + +; Use NT authentication when connecting to the server +mssql.secure_connection = Off + +; Specify max number of processes. -1 = library default +; msdlib defaults to 25 +; FreeTDS defaults to 4096 +;mssql.max_procs = -1 + +; Specify client character set. +; If empty or not set the client charset from freetds.comf is used +; This is only used when compiled with FreeTDS +;mssql.charset = "ISO-8859-1" + +[Assertion] +; Assert(expr); active by default. +; http://php.net/assert.active +;assert.active = On + +; Issue a PHP warning for each failed assertion. +; http://php.net/assert.warning +;assert.warning = On + +; Don't bail out by default. +; http://php.net/assert.bail +;assert.bail = Off + +; User-function to be called if an assertion fails. +; http://php.net/assert.callback +;assert.callback = 0 + +; Eval the expression with current error_reporting(). Set to true if you want +; error_reporting(0) around the eval(). +; http://php.net/assert.quiet-eval +;assert.quiet_eval = 0 + +[COM] +; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs +; http://php.net/com.typelib-file +;com.typelib_file = + +; allow Distributed-COM calls +; http://php.net/com.allow-dcom +;com.allow_dcom = true + +; autoregister constants of a components typlib on com_load() +; http://php.net/com.autoregister-typelib +;com.autoregister_typelib = true + +; register constants casesensitive +; http://php.net/com.autoregister-casesensitive +;com.autoregister_casesensitive = false + +; show warnings on duplicate constant registrations +; http://php.net/com.autoregister-verbose +;com.autoregister_verbose = true + +; The default character set code-page to use when passing strings to and from COM objects. +; Default: system ANSI code page +;com.code_page= + +[mbstring] +; language for internal character representation. +; http://php.net/mbstring.language +;mbstring.language = Japanese + +; internal/script encoding. +; Some encoding cannot work as internal encoding. +; (e.g. SJIS, BIG5, ISO-2022-*) +; http://php.net/mbstring.internal-encoding +;mbstring.internal_encoding = EUC-JP + +; http input encoding. +; http://php.net/mbstring.http-input +;mbstring.http_input = auto + +; http output encoding. mb_output_handler must be +; registered as output buffer to function +; http://php.net/mbstring.http-output +;mbstring.http_output = SJIS + +; enable automatic encoding translation according to +; mbstring.internal_encoding setting. Input chars are +; converted to internal encoding by setting this to On. +; Note: Do _not_ use automatic encoding translation for +; portable libs/applications. +; http://php.net/mbstring.encoding-translation +;mbstring.encoding_translation = Off + +; automatic encoding detection order. +; auto means +; http://php.net/mbstring.detect-order +;mbstring.detect_order = auto + +; substitute_character used when character cannot be converted +; one from another +; http://php.net/mbstring.substitute-character +;mbstring.substitute_character = none; + +; overload(replace) single byte functions by mbstring functions. +; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(), +; etc. Possible values are 0,1,2,4 or combination of them. +; For example, 7 for overload everything. +; 0: No overload +; 1: Overload mail() function +; 2: Overload str*() functions +; 4: Overload ereg*() functions +; http://php.net/mbstring.func-overload +;mbstring.func_overload = 0 + +; enable strict encoding detection. +;mbstring.strict_detection = Off + +; This directive specifies the regex pattern of content types for which mb_output_handler() +; is activated. +; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml) +;mbstring.http_output_conv_mimetype= + +; Allows to set script encoding. Only affects if PHP is compiled with --enable-zend-multibyte +; Default: "" +;mbstring.script_encoding= + +[gd] +; Tell the jpeg decode to ignore warnings and try to create +; a gd image. The warning will then be displayed as notices +; disabled by default +; http://php.net/gd.jpeg-ignore-warning +;gd.jpeg_ignore_warning = 0 + +[exif] +; Exif UNICODE user comments are handled as UCS-2BE/UCS-2LE and JIS as JIS. +; With mbstring support this will automatically be converted into the encoding +; given by corresponding encode setting. When empty mbstring.internal_encoding +; is used. For the decode settings you can distinguish between motorola and +; intel byte order. A decode setting cannot be empty. +; http://php.net/exif.encode-unicode +;exif.encode_unicode = ISO-8859-15 + +; http://php.net/exif.decode-unicode-motorola +;exif.decode_unicode_motorola = UCS-2BE + +; http://php.net/exif.decode-unicode-intel +;exif.decode_unicode_intel = UCS-2LE + +; http://php.net/exif.encode-jis +;exif.encode_jis = + +; http://php.net/exif.decode-jis-motorola +;exif.decode_jis_motorola = JIS + +; http://php.net/exif.decode-jis-intel +;exif.decode_jis_intel = JIS + +[Tidy] +; The path to a default tidy configuration file to use when using tidy +; http://php.net/tidy.default-config +;tidy.default_config = /usr/local/lib/php/default.tcfg + +; Should tidy clean and repair output automatically? +; WARNING: Do not use this option if you are generating non-html content +; such as dynamic images +; http://php.net/tidy.clean-output +tidy.clean_output = Off + +[soap] +; Enables or disables WSDL caching feature. +; http://php.net/soap.wsdl-cache-enabled +soap.wsdl_cache_enabled=1 + +; Sets the directory name where SOAP extension will put cache files. +; http://php.net/soap.wsdl-cache-dir +soap.wsdl_cache_dir="/tmp" + +; (time to live) Sets the number of second while cached file will be used +; instead of original one. +; http://php.net/soap.wsdl-cache-ttl +soap.wsdl_cache_ttl=86400 + +; Sets the size of the cache limit. (Max. number of WSDL files to cache) +soap.wsdl_cache_limit = 5 + +[sysvshm] +; A default size of the shared memory segment +;sysvshm.init_mem = 10000 + +[ldap] +; Sets the maximum number of open links or -1 for unlimited. +ldap.max_links = -1 + +[mcrypt] +; For more information about mcrypt settings see http://php.net/mcrypt-module-open + +; Directory where to load mcrypt algorithms +; Default: Compiled in into libmcrypt (usually /usr/local/lib/libmcrypt) +;mcrypt.algorithms_dir= + +; Directory where to load mcrypt modes +; Default: Compiled in into libmcrypt (usually /usr/local/lib/libmcrypt) +;mcrypt.modes_dir= + +[dba] +;dba.default_handler= + +; Local Variables: +; tab-width: 4 +; End: + +<% @directives.sort_by { |key, val| key }.each do |directive, value| -%> +<%= "#{directive}=#{value}" %> +<% end -%> diff --git a/cookbooks/poise-archive/CHANGELOG.md b/cookbooks/poise-archive/CHANGELOG.md new file mode 100644 index 0000000..25c32a6 --- /dev/null +++ b/cookbooks/poise-archive/CHANGELOG.md @@ -0,0 +1,43 @@ +# Poise-Archive Changelog + +## v1.5.0 + +* Support for 7-Zip unpacking archives on drives other than the system root. +* Chef 13 support. + +## v1.4.0 + +* Added support for using 7-Zip on Windows. +* Fixed handling of `.tar.xz` archives on RHEL and CentOS. + +## v1.3.0 + +* Add support for unpacking directly from a URL. + +## v1.2.1 + +* [#1](https://github.com/poise/poise-archive/issues/1) Restore file permissions + for ZIP files. + +## v1.2.0 + +* Add back a tar-binary provider called `GnuTar`, used by default on Linux. +* Support for ZIP files via RubyZip. +* Full Windows support, including with the `user` and `group` properties. + +## v1.1.2 + +* Fix compat with older Ruby that doesn't include `Entry#symlink?`. + +## v1.1.1 + +* Fix GNU tar longlink extension. + +## v1.1.0 + +* Scrap the original tar implementation in favor of a 100% pure-Ruby solution. + This should work on all platforms exactly the same. Hopefully. + +## v1.0.0 + +* Initial release! diff --git a/cookbooks/poise-archive/README.md b/cookbooks/poise-archive/README.md new file mode 100644 index 0000000..46893e6 --- /dev/null +++ b/cookbooks/poise-archive/README.md @@ -0,0 +1,103 @@ +# Poise-Archive Cookbook + +[![Build Status](https://img.shields.io/travis/poise/poise-archive.svg)](https://travis-ci.org/poise/poise-archive) +[![Gem Version](https://img.shields.io/gem/v/poise-archive.svg)](https://rubygems.org/gems/poise-archive) +[![Cookbook Version](https://img.shields.io/cookbook/v/poise-archive.svg)](https://supermarket.chef.io/cookbooks/poise-archive) +[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-archive.svg)](https://codecov.io/github/poise/poise-archive) +[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-archive.svg)](https://gemnasium.com/poise/poise-archive) +[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) + +A [Chef](https://www.chef.io/) cookbook to unpack file archives. + +It supports `.tar`, `.tar.gz`, `.tar.bz2`, and `.zip` archive files. + +## Quick Start + +To download an unpack and archive: + +```ruby +poise_archive 'https://example.com/myapp.tgz' do + destination '/opt/myapp' +end +``` + +## Requirements + +Chef 12.1 or newer is required. + +## Platforms + +This cookbook supports all platforms (including Windows) but some Unix platforms +(Solaris, AIX) may see very slow tar file unpacking when using the pure-Ruby fallback +implementation. + +## Resources + +### `poise_archive` + +The `poise_archive` resource unpacks file archives. + +```ruby +poise_archive '/tmp/myapp-1.2.0.tar' do + destination '/srv/myapp-1.2.0' +end +``` + +A URL can also be passed as the source path, optionally with extra properties to +be merged with `source_properties`. + +```ruby +poise_archive 'http://example.com/myapp-1.2.0.zip' do + destination '/srv/myapp-1.2.0' +end + +poise_archive ['http://example.com/myapp-1.2.0.zip', {headers: {'Authentication' => '...'}}] do + destination '/srv/myapp-1.2.0' +end +``` + +#### Actions + +* `:unpack` – Unpack the archive. *(default)* + +#### Properties + +* `path` – Path to the archive. If relative, it is taken as a file inside + `Chef::Config[:file_cache_path]`. If a URL, it is downloaded to a cache file + first. *(name attribute)* +* `destination` – Path to unpack the archive to. If not specified, the path of + the archive without the file extension is used. Required when unpacking from + a URL. *(default: auto)* +* `group` – Group to run the unpack as. +* `keep_existing` – Keep existing files in the destination directory when + unpacking. *(default: false)* +* `source_properties` – Property key/value pairs to be applied to the + `remote_file` file resource when downloading a URL. *(default: {retries: 5})* +* `strip_components` – Number of intermediary directories to skip when + unpacking. Works like GNU tar's `--strip-components`. *(default: 1)* +* `user` – User to run the unpack as. + +## Sponsors + +Development sponsored by [Bloomberg](http://www.bloomberg.com/company/technology/). + +The Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/). + +## License + +Copyright 2016-2017, Noah Kantrowitz + +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. + +BZip2 implementation is based on RBzip2. Copyright Sebastian Staudt, Brian Lopez. +RBzip2 code used under the terms of the new BSD license. diff --git a/cookbooks/poise-archive/attributes/default.rb b/cookbooks/poise-archive/attributes/default.rb new file mode 100644 index 0000000..5c92d99 --- /dev/null +++ b/cookbooks/poise-archive/attributes/default.rb @@ -0,0 +1,18 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +default['poise-archive']['seven_zip']['version'] = '16.04' +default['poise-archive']['seven_zip']['url'] = 'http://www.7-zip.org/a/7z%{version_tag}%{arch_tag}.exe' diff --git a/cookbooks/poise-archive/files/halite_gem/poise_archive.rb b/cookbooks/poise-archive/files/halite_gem/poise_archive.rb new file mode 100644 index 0000000..e796045 --- /dev/null +++ b/cookbooks/poise-archive/files/halite_gem/poise_archive.rb @@ -0,0 +1,21 @@ +# +# Copyright 2016-2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseArchive + autoload :Resources, 'poise_archive/resources' + autoload :VERSION, 'poise_archive/version' +end diff --git a/cookbooks/poise-archive/files/halite_gem/poise_archive/archive_providers.rb b/cookbooks/poise-archive/files/halite_gem/poise_archive/archive_providers.rb new file mode 100644 index 0000000..8d0d29f --- /dev/null +++ b/cookbooks/poise-archive/files/halite_gem/poise_archive/archive_providers.rb @@ -0,0 +1,38 @@ +# +# Copyright 2016-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/platform/provider_priority_map' + +require 'poise_archive/archive_providers/gnu_tar' +require 'poise_archive/archive_providers/seven_zip' +require 'poise_archive/archive_providers/tar' +require 'poise_archive/archive_providers/zip' + + +module PoiseArchive + # Providers for the poise_archive resource. + # + # @since 1.0.0 + module ArchiveProviders + # Set up priority maps + Chef::Platform::ProviderPriorityMap.instance.priority(:poise_archive, [ + PoiseArchive::ArchiveProviders::Zip, + PoiseArchive::ArchiveProviders::GnuTar, + PoiseArchive::ArchiveProviders::SevenZip, + PoiseArchive::ArchiveProviders::Tar, + ]) + end +end diff --git a/cookbooks/poise-archive/files/halite_gem/poise_archive/archive_providers/base.rb b/cookbooks/poise-archive/files/halite_gem/poise_archive/archive_providers/base.rb new file mode 100644 index 0000000..a249e72 --- /dev/null +++ b/cookbooks/poise-archive/files/halite_gem/poise_archive/archive_providers/base.rb @@ -0,0 +1,132 @@ +# +# Copyright 2016-2017, Noah Kantrowitz +# +# 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. +# + +require 'fileutils' + +require 'chef/provider' +require 'poise' + + +module PoiseArchive + module ArchiveProviders + # The provider base class for `poise_archive`. + # + # @see PoiseArchive::Resources::PoiseArchive::Resource + # @provides poise_archive + class Base < Chef::Provider + include Poise + + # Set the file extension this provider will handle. + # + # @param match [RegExp] Regular expression to match against the archive + # file name. + # @return [void] + # @example + # class MyProvider < Base + # provides_extension(/\.hqx$/) + # end + def self.provides_extension(match) + provides(:poise_archive) + @provides_extension = match + end + + # Override normal provider resolution to also check file extension if one + # was specified in the provider. + # + # @api private + def self.provides?(node, resource) + super && (!@provides_extension || @provides_extension.match(resource.path)) + end + + # `unpack` action for `poise_archive`. + # + # @return [void] + def action_unpack + if new_resource.is_url? + download_resource = download_file + # Check if the download resource updated, if not don't run the rest + # of the unpack for idempotence. I could also check + # new_resource.updated? but this seems more future proof. + return if !download_resource.updated_by_last_action? + end + converge_by("unpack archive #{new_resource.path} to #{new_resource.destination}") do + notifying_block do + create_directory + end + empty_directory + unpack_archive + end + end + + private + + # Download the source file to a cache path. + # + # @return [Chef::Resource] + def download_file + # resource_state used for closure breaking on the notifying block. + resource_state = [] + notifying_block do + # TODO handle cookbook:// for cookbook_file "downloads". + resource_state << remote_file(new_resource.absolute_path) do + source new_resource.path + retries 5 # As a default, could be overridden by source_properties. + new_resource.merged_source_properties.each do |key, value| + send(key, value) + end + end + end + # Return the download resource for state tracking. + resource_state.first + end + + # Make sure the destination directory exists. + # + # @return [void] + def create_directory + directory new_resource.destination do + group new_resource.group if new_resource.group + owner new_resource.user if new_resource.user + # There is explicitly no mode being set here. If a non-default mode + # is needed, you should manage that outside of poise_archive. + end + end + + # Remove all existing content from the destination so we can unpack the + # new content. + # + # @return [void] + def empty_directory + # If you want to keep it, not my problem. + return if new_resource.keep_existing + dest = new_resource.destination + Dir.entries(dest).each do |entry| + next if entry == '.' || entry == '..' + FileUtils.remove_entry_secure(::File.join(dest, entry)) + end + end + + # Run the provider-specific unpack behavior. + # + # @abstract + # @return [void] + def unpack_archive + raise NotImplementedError + end + + end + end +end diff --git a/cookbooks/poise-archive/files/halite_gem/poise_archive/archive_providers/gnu_tar.rb b/cookbooks/poise-archive/files/halite_gem/poise_archive/archive_providers/gnu_tar.rb new file mode 100644 index 0000000..196f844 --- /dev/null +++ b/cookbooks/poise-archive/files/halite_gem/poise_archive/archive_providers/gnu_tar.rb @@ -0,0 +1,88 @@ +# +# Copyright 2016-2017, Noah Kantrowitz +# +# 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. +# + +require 'fileutils' +require 'tmpdir' + +require 'poise_archive/archive_providers/base' + + +module PoiseArchive + module ArchiveProviders + # The `gnu_tar` provider class for `poise_archive` to install from TAR + # archives using GNU's tar executable. + # + # @see PoiseArchive::Resources::PoiseArchive::Resource + # @provides poise_archive + class GnuTar < Base + provides_extension(/\.t(ar|gz|bz|xz)/) + + # Only use this if we are on Linux. Everyone else gets the slow Ruby code. + # + # @api private + def self.provides?(node, _resource) + super && node['os'] == 'linux' + end + + private + + def unpack_archive + notifying_block do + install_prereqs + end + unpack_tar + end + + # Install any needed prereqs. + # + # @return [void] + def install_prereqs + utils = ['tar'] + utils << 'bzip2' if new_resource.absolute_path =~ /\.t?bz/ + if new_resource.absolute_path =~ /\.t?xz/ + xz_package = node.value_for_platform_family( + debian: 'xz-utils', + rhel: 'xz', + ) + utils << xz_package if xz_package + end + # This is a resource. + package utils + end + + # Unpack the archive and process `strip_components`. + # + # @return [void] + def unpack_tar + # Build the tar command. + cmd = %w{tar} + cmd << "--strip-components=#{new_resource.strip_components}" if new_resource.strip_components && new_resource.strip_components > 0 + cmd << if new_resource.absolute_path =~ /\.t?gz/ + '-xzvf' + elsif new_resource.absolute_path =~ /\.t?bz/ + '-xjvf' + elsif new_resource.absolute_path =~ /\.t?xz/ + '-xJvf' + else + '-xvf' + end + cmd << new_resource.absolute_path + poise_shell_out!(cmd, cwd: new_resource.destination, group: new_resource.group, user: new_resource.user) + end + + end + end +end diff --git a/cookbooks/poise-archive/files/halite_gem/poise_archive/archive_providers/seven_zip.rb b/cookbooks/poise-archive/files/halite_gem/poise_archive/archive_providers/seven_zip.rb new file mode 100644 index 0000000..9206525 --- /dev/null +++ b/cookbooks/poise-archive/files/halite_gem/poise_archive/archive_providers/seven_zip.rb @@ -0,0 +1,183 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'fileutils' +require 'tmpdir' + + +require 'poise_archive/archive_providers/base' + + +module PoiseArchive + module ArchiveProviders + # The `seven_zip` provider class for `poise_archive` to upack archives + # using 7-Zip. + # + # @since 1.4.0 + # @see PoiseArchive::Resources::PoiseArchive::Resource + # @provides poise_archive + class SevenZip < Base + provides_extension(/\.(t(ar|gz|bz|xz)|zip|7z)/) + + # Only works on Windows, because use less silly things elsewhere. + # + # @api private + def self.provides?(node, _resource) + super && node['platform_family'] == 'windows' + end + + private + + def unpack_archive + notifying_block do + install_seven_zip + end + # Create a temp directory to unpack in to. Do I want to try and force + # this to be on the same filesystem as the target? + self.class.mktmpdir do |tmpdir| + unpack_using_seven_zip(tmpdir) + chown_files(tmpdir) if new_resource.user || new_resource.group + move_files(tmpdir) + end + end + + # Install 7-Zip to a cache folder. + # + # @api private + # @return [void] + def install_seven_zip + url = seven_zip_url + path = "#{Chef::Config[:file_cache_path]}/#{url.split(/\//).last}" + + install = execute "#{windows_path(path)} /S /D=#{seven_zip_home}" do + action :nothing + end + + remote_file path do + source url + notifies :run, install, :immediately + end + end + + # Unpack the whole archive to a temp directory. + # + # @api private + # @param tmpdir [String] Temp directory to unpack to. + # @return [void] + def unpack_using_seven_zip(tmpdir) + if new_resource.absolute_path =~ /\.t(ar\.)?(gz|bz(2)?|xz)$/ + # 7-Zip doesn't know to unpack both levels of the archive on its own + # so we need to handle this more explicitly. + shell_out!("#{seven_zip_home}\\7z.exe x -so \"#{windows_path(new_resource.absolute_path)}\" | #{seven_zip_home}\\7z.exe x -si -ttar -o\"#{windows_path(tmpdir)}\"") + else + shell_out!("#{seven_zip_home}\\7z.exe x -o\"#{windows_path(tmpdir)}\" \"#{windows_path(new_resource.absolute_path)}\"") + end + end + + # Fix file ownership if requested. + # + # @api private + # @param tmpdir [String] Temp directory to change ownership in. + # @return [void] + def chown_files(tmpdir) + notifying_block do + Dir["#{tmpdir}/**/*"].each do |path| + declare_resource(::File.directory?(path) ? :directory : :file, path) do + owner new_resource.user if new_resource.user + group new_resource.group if new_resource.group + end + end + end + end + + # Manual implementation of --strip-components since 7-Zip doesn't support + # it internally. + # + # @api private + # @param tmpdir [String] Temp directory to move from. + # @return [void] + def move_files(tmpdir) + entries_at_depth(tmpdir, new_resource.strip_components).each do |source| + target = ::File.join(new_resource.destination, ::File.basename(source)) + FileUtils.mv(source, target, secure: true) + end + end + + # Compute the URL to download the 7-Zip installer from. + # + # @api private + # @return [String] + def seven_zip_url + node['poise-archive']['seven_zip']['url'] % { + version: node['poise-archive']['seven_zip']['version'], + version_tag: node['poise-archive']['seven_zip']['version'].gsub(/\./, ''), + arch: node['kernel']['machine'], + arch_tag: node['kernel']['machine'] == 'x86_64' ? '-x64' : '', + } + end + + # Path to install 7-Zip in to. + # + # @api private + # @return [String] + def seven_zip_home + "#{windows_path(Chef::Config[:file_cache_path])}\\seven_zip_#{node['poise-archive']['seven_zip']['version']}" + end + + # Flip the slashes in a path because 7z wants "normal" paths. + # + # @api private + # @param path [String] Path to convert. + # @return [String] + def windows_path(path) + path.gsub(/\//, '\\') + end + + # Find the absolute paths for entries under a path at a depth. + # + # @api private + # @param path [String] Base path to search under. + # @param depth [Integer] Number of intermediary directories to skip. + # @return [Array] + def entries_at_depth(path, depth) + entries = [path] + current_depth = 0 + while current_depth <= depth + entries.map! do |ent| + if ::File.directory?(ent) + Dir.entries(ent).select {|e| e != '.' && e != '..' }.map {|e| ::File.join(ent, e) } + else + [] + end + end + entries.flatten! + current_depth += 1 + end + entries + end + + # Indirection so I can stub this for testing without breaking RSpec. + # + # @api private + def self.mktmpdir(*args, &block) + # :nocov: + Dir.mktmpdir(*args, &block) + # :nocov: + end + + end + end +end diff --git a/cookbooks/poise-archive/files/halite_gem/poise_archive/archive_providers/tar.rb b/cookbooks/poise-archive/files/halite_gem/poise_archive/archive_providers/tar.rb new file mode 100644 index 0000000..50c3643 --- /dev/null +++ b/cookbooks/poise-archive/files/halite_gem/poise_archive/archive_providers/tar.rb @@ -0,0 +1,158 @@ +# +# Copyright 2016-2017, Noah Kantrowitz +# +# 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. +# + +require 'rubygems/package' +require 'zlib' + +require 'poise_archive/archive_providers/base' +require 'poise_archive/bzip2' + + +module PoiseArchive + module ArchiveProviders + # The `tar` provider class for `poise_archive` to install from tar archives. + # + # @see PoiseArchive::Resources::PoiseArchive::Resource + # @provides poise_archive + class Tar < Base + provides_extension(/\.t(ar|gz|bz)/) + + # Hack that GNU tar uses for paths over 100 bytes. + # + # @api private + # @see #unpack_tar + TAR_LONGLINK = '././@LongLink' + + private + + def unpack_archive + unpack_tar + chown_entries if new_resource.user || new_resource.group + end + + # Unpack the archive. + # + # @return [void] + def unpack_tar + @tar_entry_paths = [] + tar_each_with_longlink do |entry| + entry_name = entry.full_name.split(/\//).drop(new_resource.strip_components).join('/') + # If strip_components wiped out the name, don't process this entry. + next if entry_name.empty? + dest = ::File.join(new_resource.destination, entry_name) + if entry.directory? + Dir.mkdir(dest, entry.header.mode) + @tar_entry_paths << [:directory, dest] + elsif entry.file? + ::File.open(dest, 'wb', entry.header.mode) do |dest_f| + while buf = entry.read(4096) + dest_f.write(buf) + end + end + @tar_entry_paths << [:file, dest] + elsif entry.header.typeflag == '2' # symlink? is new in Ruby 2.0, apparently. + ::File.symlink(entry.header.linkname, dest) + @tar_entry_paths << [:link, dest] + else + raise RuntimeError.new("Unknown tar entry type #{entry.header.typeflag.inspect} in #{new_resource.path}") + end + end + end + + def tar_each_with_longlink(&block) + entry_name = nil + tar_each do |entry| + if entry.full_name == TAR_LONGLINK + # Stash the longlink name so it will be used for the next entry. + entry_name = entry.read.strip + # And then skip forward because this isn't a real block. + next + end + # For entries not preceded by a longlink block, use the normal name. + entry_name ||= entry.full_name + # Make the entry return the correct name. + entry.define_singleton_method(:full_name) { entry_name } + block.call(entry) + # Reset entry_name for the next entry. + entry_name = nil + end + end + + # Sequence the opening, iteration, and closing. + # + # @param block [Proc] Block to process each tar entry. + # @return [void] + def tar_each(&block) + # In case of extreme weirdness where this happens twice. + close_file! + open_file! + @tar_reader.each(&block) + ensure + close_file! + end + + # Open a file handle of the correct flavor. + # + # @return [void] + def open_file! + @raw_file = ::File.open(new_resource.absolute_path, 'rb') + @file = case new_resource.absolute_path + when /\.tar$/ + nil # So it uses @raw_file instead. + when /\.t?gz/ + Zlib::GzipReader.wrap(@raw_file) + when /\.t?bz/ + # This can't take a block, hence the gross non-block forms for everything. + PoiseArchive::Bzip2::Decompressor.new(@raw_file) + else + raise RuntimeError.new("Unknown or unsupported file extension for #{new_resource.path}") + end + @tar_reader = Gem::Package::TarReader.new(@file || @raw_file) + end + + # Close all the various file handles. + # + # @return [void] + def close_file! + if @tar_reader + @tar_reader.close + @tar_reader = nil + end + if @file + @file.close + @file = nil + end + if @raw_file + @raw_file.close unless @raw_file.closed? + @raw_file = nil + end + end + + def chown_entries + paths = @tar_entry_paths + notifying_block do + paths.each do |type, path| + send(type, path) do + group new_resource.group + owner new_resource.user + end + end + end + end + + end + end +end diff --git a/cookbooks/poise-archive/files/halite_gem/poise_archive/archive_providers/zip.rb b/cookbooks/poise-archive/files/halite_gem/poise_archive/archive_providers/zip.rb new file mode 100644 index 0000000..2dba06d --- /dev/null +++ b/cookbooks/poise-archive/files/halite_gem/poise_archive/archive_providers/zip.rb @@ -0,0 +1,97 @@ +# +# Copyright 2016-2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_archive/archive_providers/base' + + +module PoiseArchive + module ArchiveProviders + # The `zip` provider class for `poise_archive` to install from ZIP archives. + # + # @see PoiseArchive::Resources::PoiseArchive::Resource + # @provides poise_archive + class Zip < Base + provides_extension(/\.zip$/) + + private + + def unpack_archive + check_rubyzip + unpack_zip + chown_entries if new_resource.user || new_resource.group + end + + def check_rubyzip + require 'zip' + rescue LoadError + notifying_block do + install_rubyzip + end + require 'zip' + end + + def install_rubyzip + chef_gem 'rubyzip' + end + + def unpack_zip + @zip_entry_paths = [] + ::Zip::File.open(new_resource.absolute_path) do |zip_file| + zip_file.each do |entry| + entry_name = entry.name.split(/\//).drop(new_resource.strip_components).join('/') + # If strip_components wiped out the name, don't process this entry. + next if entry_name.empty? + entry_path = ::File.join(new_resource.destination, entry_name) + # Ensure parent directories exist because some ZIP files don't + # include those for some reason. + ensure_directory(entry_path) + entry.extract(entry_path) + # Make sure we restore file permissions. RubyZip won't do this + # unless we also turn on UID/GID restoration, which we don't want. + # Mask filters out setuid and setgid bits because no. + ::File.chmod(entry.unix_perms & 01777, entry_path) if !node.platform_family?('windows') && entry.unix_perms + @zip_entry_paths << [entry.directory? ? :directory : entry.file? ? :file : :link, entry_path] + end + end + end + + # Make sure all enclosing directories exist before writing a path. + # + # @param oath [String] Path to check. + def ensure_directory(path) + base = ::File.dirname(path) + unless ::File.exist?(base) + ensure_directory(base) + Dir.mkdir(base) + @zip_entry_paths << [:directory, base] + end + end + + def chown_entries + paths = @zip_entry_paths + notifying_block do + paths.each do |type, path| + send(type, path) do + group new_resource.group + owner new_resource.user + end + end + end + end + + end + end +end diff --git a/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2.rb b/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2.rb new file mode 100644 index 0000000..4e1ecfc --- /dev/null +++ b/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2.rb @@ -0,0 +1,16 @@ +# This code is free software; you can redistribute it and/or modify it under +# the terms of the new BSD License. +# +# Copyright (c) 2013, Sebastian Staudt + + +module PoiseArchive::Bzip2 + + autoload :CRC, 'poise_archive/bzip2/crc' + autoload :Constants, 'poise_archive/bzip2/constants' + autoload :Decompressor, 'poise_archive/bzip2/decompressor' + autoload :IO, 'poise_archive/bzip2/io' + autoload :InputData, 'poise_archive/bzip2/input_data' + autoload :OutputData, 'poise_archive/bzip2/output_data' + +end diff --git a/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2/LICENSE b/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2/LICENSE new file mode 100755 index 0000000..ba9a1a4 --- /dev/null +++ b/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2011, Sebastian Staudt +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +* Neither the name of the author nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2/constants.rb b/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2/constants.rb new file mode 100755 index 0000000..102c620 --- /dev/null +++ b/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2/constants.rb @@ -0,0 +1,83 @@ +# This code is free software; you can redistribute it and/or modify it under +# the terms of the new BSD License. +# +# Copyright (c) 2011-2013, Sebastian Staudt + + +module PoiseArchive::Bzip2::Constants + + BASEBLOCKSIZE = 100000 + MAX_ALPHA_SIZE = 258 + MAX_CODE_LEN = 23 + RUNA = 0 + RUNB = 1 + N_GROUPS = 6 + G_SIZE = 50 + N_ITERS = 4 + MAX_SELECTORS = (2 + (900000 / G_SIZE)) + NUM_OVERSHOOT_BYTES = 20 + + EOF = 0 + START_BLOCK_STATE = 1 + RAND_PART_A_STATE = 2 + RAND_PART_B_STATE = 3 + RAND_PART_C_STATE = 4 + NO_RAND_PART_A_STATE = 5 + NO_RAND_PART_B_STATE = 6 + NO_RAND_PART_C_STATE = 7 + + RNUMS = [ + 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, 985, 724, 205, 454, 863, + 491, 741, 242, 949, 214, 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, + 419, 436, 278, 496, 867, 210, 399, 680, 480, 51, 878, 465, 811, 169, 869, + 675, 611, 697, 867, 561, 862, 687, 507, 283, 482, 129, 807, 591, 733, 623, + 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, 170, 607, 520, 932, 727, + 476, 693, 425, 174, 647, 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, + 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, 641, 801, 220, 162, 819, + 984, 589, 513, 495, 799, 161, 604, 958, 533, 221, 400, 386, 867, 600, 782, + 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, 98, 553, 163, 354, 666, + 933, 424, 341, 533, 870, 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, + 469, 68, 770, 919, 190, 373, 294, 822, 808, 206, 184, 943, 795, 384, 383, + 461, 404, 758, 839, 887, 715, 67, 618, 276, 204, 918, 873, 777, 604, 560, + 951, 160, 578, 722, 79, 804, 96, 409, 713, 940, 652, 934, 970, 447, 318, + 353, 859, 672, 112, 785, 645, 863, 803, 350, 139, 93, 354, 99, 820, 908, + 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, 653, 282, 762, 623, 680, + 81, 927, 626, 789, 125, 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, + 170, 774, 972, 275, 999, 639, 495, 78, 352, 126, 857, 956, 358, 619, 580, + 124, 737, 594, 701, 612, 669, 112, 134, 694, 363, 992, 809, 743, 168, 974, + 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, 344, 805, 988, 739, 511, + 655, 814, 334, 249, 515, 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, + 433, 837, 553, 268, 926, 240, 102, 654, 459, 51, 686, 754, 806, 760, 493, + 403, 415, 394, 687, 700, 946, 670, 656, 610, 738, 392, 760, 799, 887, 653, + 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, 680, 879, 194, 572, 640, + 724, 926, 56, 204, 700, 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, + 297, 59, 87, 824, 713, 663, 412, 693, 342, 606, 134, 108, 571, 364, 631, + 212, 174, 643, 304, 329, 343, 97, 430, 751, 497, 314, 983, 374, 822, 928, + 140, 206, 73, 263, 980, 736, 876, 478, 430, 305, 170, 514, 364, 692, 829, + 82, 855, 953, 676, 246, 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, + 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, 896, 831, 547, 261, 524, + 462, 293, 465, 502, 56, 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, + 768, 550, 608, 933, 378, 286, 215, 979, 792, 961, 61, 688, 793, 644, 986, + 403, 106, 366, 905, 644, 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, + 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, 920, 176, 193, 713, 857, + 265, 203, 50, 668, 108, 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, + 936, 638 + ] + + MIN_BLOCK_SIZE = 1 + MAX_BLOCK_SIZE = 9 + SETMASK = (1 << 21) + CLEARMASK = (~SETMASK) + GREATER_ICOST = 15 + LESSER_ICOST = 0 + SMALL_THRESH = 20 + DEPTH_THRESH = 10 + WORK_FACTOR = 30 + QSORT_STACK_SIZE = 1000 + + INCS = [ + 1, 4, 13, 40, 121, 364, 1093, 3280, 9841, 29524, 88573, 265720, 797161, + 2391484 + ] + +end diff --git a/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2/crc.rb b/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2/crc.rb new file mode 100755 index 0000000..c09f71d --- /dev/null +++ b/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2/crc.rb @@ -0,0 +1,73 @@ +# This code is free software; you can redistribute it and/or modify it under +# the terms of the new BSD License. +# +# Copyright (c) 2011-2013, Sebastian Staudt + + +class PoiseArchive::Bzip2::CRC + + CRC32_TABLE = [ + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, + 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, + 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, + 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, + 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, + 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, + 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, + 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, + 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, + 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, + 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, + 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, + 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, + 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, + 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, + 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, + 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, + 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, + 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, + 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, + 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, + 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 + ] + + attr_accessor :global_crc + + def initialize + initialize_crc + end + + def initialize_crc + @global_crc = 0xffffffff + end + + def final_crc + @global_crc ^ 0xffffffff + end + + def update_crc(in_ch) + @global_crc = ((@global_crc << 8) & 0xffffffff) ^ CRC32_TABLE[(@global_crc >> 24) ^ in_ch] + end + +end diff --git a/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2/decompressor.rb b/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2/decompressor.rb new file mode 100755 index 0000000..201fa3e --- /dev/null +++ b/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2/decompressor.rb @@ -0,0 +1,704 @@ +# This code is free software; you can redistribute it and/or modify it under +# the terms of the new BSD License. +# +# Copyright (c) 2011-2013, Sebastian Staudt + + +class PoiseArchive::Bzip2::Decompressor + + include PoiseArchive::Bzip2::Constants + + def initialize(io) + @buff = 0 + @bytes_read = 0 + @computed_combined_crc = 0 + @crc = PoiseArchive::Bzip2::CRC.new + @current_char = -1 + @io = io + @live = 0 + @stored_combined_crc = 0 + @su_t_pos = 0 + init + end + + def count(read) + @bytes_read += read if read != -1 + end + + # ADDED METHODS + def pos + @bytes_read + end + + def eof? + @current_state == EOF + end + # /ADDED METHODS + + def read(length = nil) + raise 'stream closed' if @io.nil? + + if length == 1 + r = read0 + count (r < 0 ? -1 : 1) + r + else + r = '' + if length == nil + while true do + b = read0 + break if b < 0 + r << b.chr + end + count r.size # ADDED LINE + elsif length > 0 + length.times do + b = read0 + break if b < 0 + r << b.chr + end + count r.size + end + r + end + end + + def read0 + ret_char = @current_char + + if @current_state == RAND_PART_B_STATE + setup_rand_part_b + elsif @current_state == NO_RAND_PART_B_STATE + setup_no_rand_part_b + elsif @current_state == RAND_PART_C_STATE + setup_rand_part_c + elsif @current_state == NO_RAND_PART_C_STATE + setup_no_rand_part_c + elsif @current_state == EOF + return -1 + else + raise 'illegal state' + end + + ret_char + end + + def make_maps + in_use = @data.in_use + seq_to_unseq = @data.seq_to_unseq + + n_in_use_shadow = 0 + + 256.times do |i| + if in_use[i] + seq_to_unseq[n_in_use_shadow] = i + n_in_use_shadow += 1 + end + end + + @n_in_use = n_in_use_shadow + end + + def init + check_magic + + block_size = @io.read(1).to_i + raise 'Illegal block size.' if block_size < 1 || block_size > 9 + @block_size = block_size + + init_block + setup_block + end + + def check_magic + raise 'Magic number does not match "BZh".' unless @io.read(3) == 'BZh' + end + + def init_block + magic = [ubyte, ubyte, ubyte, ubyte, ubyte, ubyte] + + if magic == [0x17, 0x72, 0x45, 0x38, 0x50, 0x90] + complete + elsif magic != [0x31, 0x41, 0x59, 0x26, 0x53, 0x59] + @current_state = EOF + + raise 'Bad block header.' + else + @stored_block_crc = int + @block_randomised = bit + + @data = PoiseArchive::Bzip2::InputData.new @block_size if @data.nil? + + get_and_move_to_front_decode + + @crc.initialize_crc + @current_state = START_BLOCK_STATE + end + end + + def end_block + @computed_block_crc = @crc.final_crc + + if @stored_block_crc != @computed_block_crc + @computed_combined_crc = (@stored_combined_crc << 1) | (@stored_combined_crc >> 31) + @computed_combined_crc ^= @stored_block_crc + + raise 'BZip2 CRC error' + end + + @computed_combined_crc = (@computed_combined_crc << 1) | (@computed_combined_crc >> 31) + @computed_combined_crc ^= @computed_block_crc + end + + def complete + @stored_combined_crc = int + @current_state = EOF + @data = nil + + raise 'BZip2 CRC error' if @stored_combined_crc != @computed_combined_crc + end + + def close + if @io != $stdin + @io = nil + @data = nil + end + end + + def r(n) + live_shadow = @live + buff_shadow = @buff + + if live_shadow < n + begin + thech = @io.readbyte + + raise 'unexpected end of stream' if thech < 0 + + buff_shadow = (buff_shadow << 8) | thech + live_shadow += 8 + end while live_shadow < n + + @buff = buff_shadow + end + + @live = live_shadow - n + + (buff_shadow >> (live_shadow - n)) & ((1 << n) - 1) + end + + def bit + r(1) != 0 + end + + def ubyte + r 8 + end + + def int + (((((r(8) << 8) | r(8)) << 8) | r(8)) << 8) | r(8) + end + + def create_decode_tables(limit, base, perm, length, min_len, max_len, alpha_size) + pp = 0 + (min_len..max_len).each do |i| + alpha_size.times do |j| + if length[j] == i + perm[pp] = j + pp += 1 + end + end + end + + MAX_CODE_LEN.downto 1 do |i| + base[i] = 0 + limit[i] = 0 + end + + alpha_size.times do |i| + base[length[i] + 1] += 1 + end + + b = 0 + 1.upto(MAX_CODE_LEN - 1) do |i| + b += base[i] + base[i] = b + end + + vec = 0 + min_len.upto(max_len) do |i| + b = base[i] + nb = base[i + 1] + vec += nb - b + b = nb + limit[i] = vec - 1 + vec = vec << 1 + end + + (min_len + 1).upto(max_len) do |i| + base[i] = ((limit[i - 1] + 1) << 1) - base[i] + end + end + + def receive_decoding_tables + in_use = @data.in_use + pos = @data.receive_decoding_tables_pos + selector = @data.selector + selector_mtf = @data.selector_mtf + + in_use16 = 0 + + 16.times do |i| + in_use16 |= 1 << i if bit + end + + 255.downto(0) do |i| + in_use[i] = false + end + + 16.times do |i| + if (in_use16 & (1 << i)) != 0 + i16 = i << 4 + 16.times do |j| + in_use[i16 + j] = true if bit + end + end + end + + make_maps + alpha_size = @n_in_use + 2 + + groups = r 3 + selectors = r 15 + + selectors.times do |i| + j = 0 + while bit + j += 1 + end + selector_mtf[i] = j + end + + groups.downto(0) do |v| + pos[v] = v + end + + selectors.times do |i| + v = selector_mtf[i] & 0xff + tmp = pos[v] + + while v > 0 do + pos[v] = pos[v -= 1] + end + + pos[0] = tmp + selector[i] = tmp + end + + len = @data.temp_char_array_2d + + groups.times do |t| + curr = r 5 + len_t = len[t] + alpha_size.times do |i| + while bit + curr += bit ? -1 : 1 + end + len_t[i] = curr + end + @data.temp_char_array_2d[t] = len_t + end + + create_huffman_decoding_tables alpha_size, groups + end + + def create_huffman_decoding_tables(alpha_size, groups) + len = @data.temp_char_array_2d + min_lens = @data.min_lens + limit = @data.limit + base = @data.base + perm = @data.perm + + groups.times do |t| + min_len = 32 + max_len = 0 + len_t = len[t] + + (alpha_size - 1).downto 0 do |i| + lent = len_t[i] + max_len = lent if lent > max_len + min_len = lent if lent < min_len + end + + create_decode_tables limit[t], base[t], perm[t], len[t], min_len, max_len, alpha_size + min_lens[t] = min_len + end + end + + def get_and_move_to_front_decode + @orig_ptr = r 24 + receive_decoding_tables + + ll8 = @data.ll8 + unzftab = @data.unzftab + selector = @data.selector + seq_to_unseq = @data.seq_to_unseq + yy = @data.get_and_move_to_front_decode_yy + min_lens = @data.min_lens + limit = @data.limit + base = @data.base + perm = @data.perm + limit_last = @block_size * BASEBLOCKSIZE + + 256.downto(0) do |i| + yy[i] = i + unzftab[i] = 0 + end + + group_no = 0 + group_pos = G_SIZE - 1 + eob = @n_in_use + 1 + next_sym = get_and_move_to_front_decode0 0 + buff_shadow = @buff + live_shadow = @live + last_shadow = -1 + zt = selector[group_no] & 0xff + base_zt = base[zt] + limit_zt = limit[zt] + perm_zt = perm[zt] + min_lens_zt = min_lens[zt] + + while next_sym != eob + if (next_sym == RUNA) || (next_sym == RUNB) + s = -1 + + n = 1 + while true do + if next_sym == RUNA + s += n + elsif next_sym == RUNB + s += n << 1 + else + break + end + + if group_pos == 0 + group_pos = G_SIZE - 1 + group_no += 1 + zt = selector[group_no] & 0xff + base_zt = base[zt] + limit_zt = limit[zt] + perm_zt = perm[zt] + min_lens_zt = min_lens[zt] + else + group_pos -= 1 + end + + zn = min_lens_zt + + while live_shadow < zn + thech = @io.readbyte + + raise 'unexpected end of stream' if thech < 0 + + buff_shadow = ((buff_shadow << 8) & 0xffffffff) | thech + live_shadow += 8 + end + + zvec = ((buff_shadow >> (live_shadow - zn)) & 0xffffffff) & ((1 << zn) - 1) + live_shadow -= zn + + while zvec > limit_zt[zn] + zn += 1 + + while live_shadow < 1 + thech = @io.readbyte + + raise 'unexpected end of stream' if thech < 0 + + buff_shadow = ((buff_shadow << 8) & 0xffffffff) | thech + live_shadow += 8 + end + + live_shadow -= 1 + zvec = (zvec << 1) | ((buff_shadow >> live_shadow) & 1) + end + + next_sym = perm_zt[zvec - base_zt[zn]] + + n = n << 1 + end + + ch = seq_to_unseq[yy[0]] + unzftab[ch & 0xff] += s + 1 + + while s >= 0 + last_shadow += 1 + ll8[last_shadow] = ch + s -= 1 + end + + raise 'block overrun' if last_shadow >= limit_last + else + last_shadow += 1 + raise 'block overrun' if last_shadow >= limit_last + + tmp = yy[next_sym - 1] + unzftab[seq_to_unseq[tmp] & 0xff] += 1 + ll8[last_shadow] = seq_to_unseq[tmp] + + yy[1, next_sym - 1] = yy[0, next_sym - 1] + yy[0] = tmp + + if group_pos == 0 + group_pos = G_SIZE - 1 + group_no += 1 + zt = selector[group_no] & 0xff + base_zt = base[zt] + limit_zt = limit[zt] + perm_zt = perm[zt] + min_lens_zt = min_lens[zt] + else + group_pos -= 1 + end + + zn = min_lens_zt + + while live_shadow < zn + thech = @io.readbyte + + raise 'unexpected end of stream' if thech < 0 + + buff_shadow = ((buff_shadow << 8) & 0xffffffff) | thech + live_shadow += 8 + end + zvec = (buff_shadow >> (live_shadow - zn)) & ((1 << zn) - 1) + live_shadow -= zn + + while zvec > limit_zt[zn] + zn += 1 + while live_shadow < 1 + thech = @io.readbyte + + raise 'unexpected end of stream' if thech < 0 + + buff_shadow = ((buff_shadow << 8) & 0xffffffff) | thech + live_shadow += 8 + end + live_shadow -= 1 + zvec = (zvec << 1) | ((buff_shadow >> live_shadow) & 1) + end + + next_sym = perm_zt[zvec - base_zt[zn]] + end + end + + @last = last_shadow + @live = live_shadow + @buff = buff_shadow + end + + def get_and_move_to_front_decode0(group_no) + zt = @data.selector[group_no] & 0xff + limit_zt = @data.limit[zt] + zn = @data.min_lens[zt] + zvec = r zn + live_shadow = @live + buff_shadow = @buff + + while zvec > limit_zt[zn] + zn += 1 + + while live_shadow < 1 + thech = @io.readbyte + + raise 'unexpected end of stream' if thech < 0 + + buff_shadow = ((buff_shadow << 8) & 0xffffffff) | thech + live_shadow += 8 + end + + live_shadow -=1 + zvec = (zvec << 1) | ((buff_shadow >> live_shadow) & 1) + end + + @live = live_shadow + @buff = buff_shadow + + @data.perm[zt][zvec - @data.base[zt][zn]] + end + + def setup_block + return if @data.nil? + + cftab = @data.cftab + tt = @data.init_tt @last + 1 + ll8 = @data.ll8 + cftab[0] = 0 + cftab[1, 256] = @data.unzftab[0, 256] + + c = cftab[0] + 1.upto(256) do |i| + c += cftab[i] + cftab[i] = c + end + + last_shadow = @last + (last_shadow + 1).times do |i| + cftab_i = ll8[i] & 0xff + tt[cftab[cftab_i]] = i + cftab[cftab_i] += 1 + end + + raise 'stream corrupted' if @orig_ptr < 0 || @orig_ptr >= tt.size + + @su_t_pos = tt[@orig_ptr] + @su_count = 0 + @su_i2 = 0 + @su_ch2 = 256 + + if @block_randomised + @su_r_n_to_go = 0 + @su_r_t_pos = 0 + + setup_rand_part_a + else + setup_no_rand_part_a + end + end + + def setup_rand_part_a + if @su_i2 <= @last + @su_ch_prev = @su_ch2 + su_ch2_shadow = @data.ll8[@su_t_pos] & 0xff + @su_t_pos = @data.tt[@su_t_pos] + + if @su_r_n_to_go == 0 + @su_r_n_to_go = RNUMS[@su_r_t_pos] - 1 + @su_r_t_pos += 1 + @su_r_t_pos = 0 if @su_r_t_pos == 512 + else + @su_r_n_to_go -= 1 + end + + @su_ch2 = su_ch2_shadow ^= (@su_r_n_to_go == 1) ? 1 : 0 + @su_i2 += 1 + @current_char = su_ch2_shadow + @current_state = RAND_PART_B_STATE + @crc.update_crc su_ch2_shadow + else + end_block + init_block + setup_block + end + end + + def setup_no_rand_part_a + if @su_i2 <= @last + @su_ch_prev = @su_ch2 + su_ch2_shadow = @data.ll8[@su_t_pos] & 0xff + @su_ch2 = su_ch2_shadow + @su_t_pos = @data.tt[@su_t_pos] + @su_i2 += 1 + @current_char = su_ch2_shadow + @current_state = NO_RAND_PART_B_STATE + @crc.update_crc su_ch2_shadow + else + @current_state = NO_RAND_PART_A_STATE + end_block + init_block + setup_block + end + end + + def setup_rand_part_b + if @su_ch2 != @su_ch_prev + @current_state = RAND_PART_A_STATE + @su_count = 1 + setup_rand_part_a + else + @su_count += 1 + if @su_count >= 4 + @su_z = @data.ll8[@su_t_pos] & 0xff + @su_t_pos = @data.tt[@su_t_pos] + + if @su_r_n_to_go == 0 + @su_r_n_to_go = RNUMS[@su_r_t_pos] - 1 + @su_r_t_pos += 1 + @su_r_t_pos = 0 if @su_r_t_pos == 512 + else + @su_r_n_to_go -= 1 + end + + @su_j2 = 0 + @current_state = RAND_PART_C_STATE + @su_z ^= 1 if @su_r_n_to_go == 1 + setup_rand_part_c + else + @current_state = RAND_PART_A_STATE + setup_rand_part_a + end + end + end + + def setup_rand_part_c + if @su_j2 < @su_z + @current_char = @su_ch2 + @crc.update_crc @su_ch2 + @su_j2 += 1 + else + @current_state = RAND_PART_A_STATE + @su_i2 += 1 + @su_count = 0 + setup_rand_part_a + end + end + + def setup_no_rand_part_b + if @su_ch2 != @su_ch_prev + @su_count = 1 + setup_no_rand_part_a + else + @su_count += 1 + if @su_count >= 4 + @su_z = @data.ll8[@su_t_pos] & 0xff + @su_t_pos = @data.tt[@su_t_pos] + @su_j2 = 0 + setup_no_rand_part_c + else + setup_no_rand_part_a + end + end + end + + def setup_no_rand_part_c + if @su_j2 < @su_z + su_ch2_shadow = @su_ch2 + @current_char = su_ch2_shadow + @crc.update_crc su_ch2_shadow + @su_j2 += 1 + @current_state = NO_RAND_PART_C_STATE + else + @su_i2 += 1 + @su_count = 0 + setup_no_rand_part_a + end + end + + def size + if @io.is_a? StringIO + @io.size + elsif @io.is_a? File + @io.stat.size + end + end + + def uncompressed + @last + 1 + end + + def inspect + "#<#{self.class}: @io=#{@io.inspect} size=#{size} uncompressed=#{uncompressed}>" + end + +end diff --git a/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2/input_data.rb b/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2/input_data.rb new file mode 100755 index 0000000..a3ef7d2 --- /dev/null +++ b/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2/input_data.rb @@ -0,0 +1,43 @@ +# This code is free software; you can redistribute it and/or modify it under +# the terms of the new BSD License. +# +# Copyright (c) 2011-2013, Sebastian Staudt + + +class PoiseArchive::Bzip2::InputData + + include PoiseArchive::Bzip2::Constants + + attr_reader :base, :cftab, :get_and_move_to_front_decode_yy, :in_use, + :limit, :ll8, :min_lens, :perm, :receive_decoding_tables_pos, + :selector, :selector_mtf, :seq_to_unseq, :temp_char_array_2d, + :unzftab, :tt + + def initialize(block_size) + @in_use = Array.new 256, false + + @seq_to_unseq = Array.new 256, 0 + @selector = Array.new MAX_SELECTORS, 0 + @selector_mtf = Array.new MAX_SELECTORS, 0 + + @unzftab = Array.new 256, 0 + + @base = Array.new(N_GROUPS) { Array.new(MAX_ALPHA_SIZE, 0) } + @limit = Array.new(N_GROUPS) { Array.new(MAX_ALPHA_SIZE, 0) } + @perm = Array.new(N_GROUPS) { Array.new(MAX_ALPHA_SIZE, 0) } + @min_lens = Array.new N_GROUPS, 0 + + @cftab = Array.new 257, 0 + @get_and_move_to_front_decode_yy = Array.new 256 + @temp_char_array_2d = Array.new(N_GROUPS) { Array.new(MAX_ALPHA_SIZE, 0) } + @receive_decoding_tables_pos = Array.new N_GROUPS, 0 + + @ll8 = Array.new block_size * BASEBLOCKSIZE + end + + def init_tt(size) + @tt = Array.new(size) if @tt.nil? || @tt.size < size + @tt + end + +end diff --git a/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2/output_data.rb b/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2/output_data.rb new file mode 100755 index 0000000..20f890f --- /dev/null +++ b/cookbooks/poise-archive/files/halite_gem/poise_archive/bzip2/output_data.rb @@ -0,0 +1,57 @@ +# This code is free software; you can redistribute it and/or modify it under +# the terms of the new BSD License. +# +# Copyright (c) 2011-2013, Sebastian Staudt + + +class PoiseArchive::Bzip2::OutputData + + include PoiseArchive::Bzip2::Constants + + attr_reader :block, :ftab, :fmap, :generate_mtf_values_yy, :heap, :in_use, + :main_sort_big_done, :main_sort_copy, :main_sort_running_order, + :mtf_freq, :parent, :quadrant, :selector, :selector_mtf, + :send_mtf_values_code, :send_mtf_values_cost, + :send_mtf_values_fave, :send_mtf_values_len, + :send_mtf_values_rfreq, :send_mtf_values2_pos, + :send_mtf_values4_in_use_16, :sfmap, :stack_dd, :stack_hh, + :stack_ll, :unseq_to_seq, :weight + + def initialize(block_size) + n = block_size * BASEBLOCKSIZE + @block = Array.new n + 1 + NUM_OVERSHOOT_BYTES, 0 + @fmap = Array.new n, 0 + @selector = Array.new MAX_SELECTORS + @selector_mtf = Array.new MAX_SELECTORS + @sfmap = Array.new 2 * n + @quadrant = @sfmap + + @in_use = Array.new 256 + @mtf_freq = Array.new MAX_ALPHA_SIZE, 0 + @unseq_to_seq = Array.new 256 + + @generate_mtf_values_yy = Array.new 256 + @send_mtf_values_code = Array.new(N_GROUPS) { Array.new MAX_ALPHA_SIZE } + @send_mtf_values_cost = Array.new N_GROUPS + @send_mtf_values_fave = Array.new N_GROUPS + @send_mtf_values_len = Array.new(N_GROUPS) { Array.new MAX_ALPHA_SIZE } + @send_mtf_values_rfreq = Array.new(N_GROUPS) { Array.new MAX_ALPHA_SIZE } + @send_mtf_values2_pos = Array.new N_GROUPS + @send_mtf_values4_in_use_16 = Array.new 16 + + @stack_dd = Array.new QSORT_STACK_SIZE + @stack_hh = Array.new QSORT_STACK_SIZE + @stack_ll = Array.new QSORT_STACK_SIZE + + @main_sort_big_done = Array.new 256 + @main_sort_copy = Array.new 256 + @main_sort_running_order = Array.new 256 + + @heap = Array.new MAX_ALPHA_SIZE + 2 + @parent = Array.new MAX_ALPHA_SIZE + 2 + @weight = Array.new MAX_ALPHA_SIZE + 2 + + @ftab = Array.new 65537 + end + +end diff --git a/cookbooks/poise-archive/files/halite_gem/poise_archive/cheftie.rb b/cookbooks/poise-archive/files/halite_gem/poise_archive/cheftie.rb new file mode 100644 index 0000000..cb3be2d --- /dev/null +++ b/cookbooks/poise-archive/files/halite_gem/poise_archive/cheftie.rb @@ -0,0 +1,18 @@ +# +# Copyright 2016-2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_archive/resources' +require 'poise_archive/archive_providers' diff --git a/cookbooks/poise-archive/files/halite_gem/poise_archive/resources.rb b/cookbooks/poise-archive/files/halite_gem/poise_archive/resources.rb new file mode 100644 index 0000000..d9ebb4a --- /dev/null +++ b/cookbooks/poise-archive/files/halite_gem/poise_archive/resources.rb @@ -0,0 +1,26 @@ +# +# Copyright 2016-2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_archive/resources/poise_archive' + + +module PoiseArchive + # Chef resources and providers for poise-archive. + # + # @since 1.0.0 + module Resources + end +end diff --git a/cookbooks/poise-archive/files/halite_gem/poise_archive/resources/poise_archive.rb b/cookbooks/poise-archive/files/halite_gem/poise_archive/resources/poise_archive.rb new file mode 100644 index 0000000..7186d6c --- /dev/null +++ b/cookbooks/poise-archive/files/halite_gem/poise_archive/resources/poise_archive.rb @@ -0,0 +1,151 @@ +# +# Copyright 2016-2017, Noah Kantrowitz +# +# 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. +# + +require 'base64' +require 'uri' + +require 'chef/resource' +require 'poise' + + +module PoiseArchive + module Resources + # (see PoiseArchive::Resource) + # @since 1.0.0 + module PoiseArchive + # A `poise_archive` resource to unpack archives. + # + # @provides poise_archive + # @action unpack + # @example + # poise_archive '/opt/myapp.tgz' + # @example Downloading from a URL with options + # poise_archive ['http://example.com/myapp.zip', {headers: {'Authentication' => '...'}}] do + # destination '/opt/myapp' + # end + class Resource < Chef::Resource + include Poise + provides(:poise_archive) + actions(:unpack) + + # @!attribute path + # Path to the archive. If relative, it is taken as a file inside + # `Chef::Config[:file_cache_path]`. Can also be a URL to download the + # archive from. + # @return [String, Array] + attribute(:path, kind_of: String, default: lazy { @raw_name.is_a?(Array) ? @raw_name[0] : name }, required: true) + # @!attribute destination + # Path to unpack the archive to. If not specified, the path of the + # archive without the file extension is used. + # @return [String, nil, false] + attribute(:destination, kind_of: [String, NilClass, FalseClass], default: lazy { default_destination }) + # @!attribute group + # Group to run the unpack as. + # @return [String, Integer, nil, false] + attribute(:group, kind_of: [String, Integer, NilClass, FalseClass]) + # @!attribute keep_existing + # Keep existing files in the destination directory when unpacking. + # @return [Boolean] + attribute(:keep_existing, equal_to: [true, false], default: false) + # @!attribute source_properties + # Properties to pass through to the underlying download resource if + # using one. Merged with the array form of {#name}. + # @return [Hash] + attribute(:source_properties, option_collector: true, forced_keys: %i{retries}) + # @!attribute strip_components + # Number of intermediary directories to skip when unpacking. Works + # like GNU tar's --strip-components. + # @return [Integer] + attribute(:strip_components, kind_of: Integer, default: 1) + # @!attribute user + # User to run the unpack as. + # @return [String, Integer, nil, false] + attribute(:user, kind_of: [String, Integer, NilClass, FalseClass]) + + # Alias for the forgetful. + # @api private + alias_method :owner, :user + + def initialize(name, run_context) + @raw_name = name # Capture this before it gets coerced to a string. + super + end + + # Regexp for URL-like paths. + # @api private + URL_PATHS = %r{^(\w+:)?//} + + # Check if the source path is a URL. + # + # @api private + # @return [Boolean] + def is_url? + path =~ URL_PATHS + end + + # Expand a relative file path against `Chef::Config[:file_cache_path]`. + # For URLs it returns the cache file path. + # + # @api private + # @return [String] + def absolute_path + if is_url? + # Use the last path component without the query string plus the name + # of the resource in Base64. This should be both mildly readable and + # also unique per invocation. + url_part = URI(path).path.split(/\//).last + base64_name = Base64.strict_encode64(name).gsub(/\=/, '') + ::File.join(Chef::Config[:file_cache_path], "#{base64_name}_#{url_part}") + else + ::File.expand_path(path, Chef::Config[:file_cache_path]) + end + end + + # Merge the explicit source properties with the array form of the name. + # + # @api private + # @return [Hash] + def merged_source_properties + if @raw_name.is_a?(Array) && @raw_name[1] + source_properties.merge(@raw_name[1]) + else + source_properties + end + end + + private + + # Filename components to ignore. + # @api private + BASENAME_IGNORE = /(\.(t?(ar|gz|bz2?|xz)|zip))+$/ + + # Default value for the {#destination} property + # + # @api private + # @return [String] + def default_destination + if is_url? + raise ValueError.new("Destination for URL-based archive #{self} must be specified explicitly") + else + ::File.join(::File.dirname(absolute_path), ::File.basename(path).gsub(BASENAME_IGNORE, '')) + end + end + end + + # Providers can be found in archive_providers/. + end + end +end diff --git a/cookbooks/poise-archive/files/halite_gem/poise_archive/version.rb b/cookbooks/poise-archive/files/halite_gem/poise_archive/version.rb new file mode 100644 index 0000000..ba3e48e --- /dev/null +++ b/cookbooks/poise-archive/files/halite_gem/poise_archive/version.rb @@ -0,0 +1,20 @@ +# +# Copyright 2016-2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseArchive + VERSION = '1.5.0' +end diff --git a/cookbooks/poise-archive/libraries/default.rb b/cookbooks/poise-archive/libraries/default.rb new file mode 100644 index 0000000..01175df --- /dev/null +++ b/cookbooks/poise-archive/libraries/default.rb @@ -0,0 +1,19 @@ +# +# Copyright 2016-2017, Noah Kantrowitz +# +# 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. +# + +raise 'Halite is not compatible with no_lazy_load false, please set no_lazy_load true in your Chef configuration file.' unless Chef::Config[:no_lazy_load] +$LOAD_PATH << File.expand_path('../../files/halite_gem', __FILE__) +require "poise_archive/cheftie" diff --git a/cookbooks/poise-archive/metadata.json b/cookbooks/poise-archive/metadata.json new file mode 100644 index 0000000..c3e7b00 --- /dev/null +++ b/cookbooks/poise-archive/metadata.json @@ -0,0 +1 @@ +{"name":"poise-archive","version":"1.5.0","description":"A Chef cookbook for unpacking file archives like tar and zip.","long_description":"# Poise-Archive Cookbook\n\n[![Build Status](https://img.shields.io/travis/poise/poise-archive.svg)](https://travis-ci.org/poise/poise-archive)\n[![Gem Version](https://img.shields.io/gem/v/poise-archive.svg)](https://rubygems.org/gems/poise-archive)\n[![Cookbook Version](https://img.shields.io/cookbook/v/poise-archive.svg)](https://supermarket.chef.io/cookbooks/poise-archive)\n[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-archive.svg)](https://codecov.io/github/poise/poise-archive)\n[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-archive.svg)](https://gemnasium.com/poise/poise-archive)\n[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)\n\nA [Chef](https://www.chef.io/) cookbook to unpack file archives.\n\nIt supports `.tar`, `.tar.gz`, `.tar.bz2`, and `.zip` archive files.\n\n## Quick Start\n\nTo download an unpack and archive:\n\n```ruby\npoise_archive 'https://example.com/myapp.tgz' do\n destination '/opt/myapp'\nend\n```\n\n## Requirements\n\nChef 12.1 or newer is required.\n\n## Platforms\n\nThis cookbook supports all platforms (including Windows) but some Unix platforms\n(Solaris, AIX) may see very slow tar file unpacking when using the pure-Ruby fallback\nimplementation.\n\n## Resources\n\n### `poise_archive`\n\nThe `poise_archive` resource unpacks file archives.\n\n```ruby\npoise_archive '/tmp/myapp-1.2.0.tar' do\n destination '/srv/myapp-1.2.0'\nend\n```\n\nA URL can also be passed as the source path, optionally with extra properties to\nbe merged with `source_properties`.\n\n```ruby\npoise_archive 'http://example.com/myapp-1.2.0.zip' do\n destination '/srv/myapp-1.2.0'\nend\n\npoise_archive ['http://example.com/myapp-1.2.0.zip', {headers: {'Authentication' => '...'}}] do\n destination '/srv/myapp-1.2.0'\nend\n```\n\n#### Actions\n\n* `:unpack` – Unpack the archive. *(default)*\n\n#### Properties\n\n* `path` – Path to the archive. If relative, it is taken as a file inside\n `Chef::Config[:file_cache_path]`. If a URL, it is downloaded to a cache file\n first. *(name attribute)*\n* `destination` – Path to unpack the archive to. If not specified, the path of\n the archive without the file extension is used. Required when unpacking from\n a URL. *(default: auto)*\n* `group` – Group to run the unpack as.\n* `keep_existing` – Keep existing files in the destination directory when\n unpacking. *(default: false)*\n* `source_properties` – Property key/value pairs to be applied to the\n `remote_file` file resource when downloading a URL. *(default: {retries: 5})*\n* `strip_components` – Number of intermediary directories to skip when\n unpacking. Works like GNU tar's `--strip-components`. *(default: 1)*\n* `user` – User to run the unpack as.\n\n## Sponsors\n\nDevelopment sponsored by [Bloomberg](http://www.bloomberg.com/company/technology/).\n\nThe Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/).\n\n## License\n\nCopyright 2016-2017, Noah Kantrowitz\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nBZip2 implementation is based on RBzip2. Copyright Sebastian Staudt, Brian Lopez.\nRBzip2 code used under the terms of the new BSD license.\n","maintainer":"Noah Kantrowitz","maintainer_email":"noah@coderanger.net","license":"Apache 2.0","platforms":{},"dependencies":{"poise":"~> 2.6"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/poise/poise-archive","issues_url":"https://github.com/poise/poise-archive/issues","chef_version":[["< 14",">= 12.1"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/poise-build-essential/CHANGELOG.md b/cookbooks/poise-build-essential/CHANGELOG.md new file mode 100644 index 0000000..2e62ba5 --- /dev/null +++ b/cookbooks/poise-build-essential/CHANGELOG.md @@ -0,0 +1,5 @@ +# Poise-Build-Essential Changelog + +## v1.0.0 + +* Initial release! diff --git a/cookbooks/poise-build-essential/README.md b/cookbooks/poise-build-essential/README.md new file mode 100644 index 0000000..fd9979f --- /dev/null +++ b/cookbooks/poise-build-essential/README.md @@ -0,0 +1,85 @@ +# Poise-Build-Essential Cookbook + +[![Build Status](https://img.shields.io/travis/poise/poise-build-essential.svg)](https://travis-ci.org/poise/poise-build-essential) +[![Gem Version](https://img.shields.io/gem/v/poise-build-essential.svg)](https://rubygems.org/gems/poise-build-essential) +[![Cookbook Version](https://img.shields.io/cookbook/v/poise-build-essential.svg)](https://supermarket.chef.io/cookbooks/poise-build-essential) +[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-build-essential.svg)](https://codecov.io/github/poise/poise-build-essential) +[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-build-essential.svg)](https://gemnasium.com/poise/poise-build-essential) +[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) + +A [Chef](https://www.chef.io/) cookbook to install a C compiler and build tools.. + +## Quick Start + +To install a C compiler: + +```ruby +include_recipe 'poise-build-essential' +``` + +Or to install using a resource and at compile time: + +```ruby +poise_build_essential 'build_essential' do + action :nothing +end.run_action(:install) +``` + +## Recipes + +* `poise-build-essential::default` – Install a C compiler and build tools. + +## Attributes + +* `node['poise-build-essential']['action']` – Action to use. One of install, + upgrade, or remove. *(default: install)* +* `node['poise-build-essential']['allow_unsupported_platform']` – Whether or not + to raise an error on unsupported platforms. *(default: false)* + +## Resources + +### `poise_build_essential` + +The `poise_build_essential` resource installs a C compiler and build tools. + +```ruby +poise_build_essential 'build_essential' do + allow_unsupported_platform true +end +``` + +#### Actions + +* `:install` – Install a C compiler. *(default)* +* `:upgrade` – Install a C compiler using `package action :ugprade` rules. +* `:remove` – Remove a C compiler. + +#### Properties + +* `allow_unsupported_platform` – Whether or not to raise an error on unsupported + platforms. *(default: false)* + +## Sponsors + +Development sponsored by [SAP](https://www.sap.com/). + +The Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/). + +## License + +Some code copyright 2008-2017, Chef Software, Inc. Used under the terms of the +Apache License, Version 2.0. + +Copyright 2017, Noah Kantrowitz + +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/cookbooks/poise-build-essential/attributes/default.rb b/cookbooks/poise-build-essential/attributes/default.rb new file mode 100644 index 0000000..0b97ec0 --- /dev/null +++ b/cookbooks/poise-build-essential/attributes/default.rb @@ -0,0 +1,21 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +# Action to use. One of install, upgrade, or remove. +default['poise-build-essential']['action'] = 'install' + +# Whether or not to raise an error on unsupported platforms. +default['poise-build-essential']['allow_unsupported_platform'] = false diff --git a/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential.rb b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential.rb new file mode 100644 index 0000000..85106af --- /dev/null +++ b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential.rb @@ -0,0 +1,22 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseBuildEssential + autoload :BuildEssentialProviders, 'poise_build_essential/build_essential_providers' + autoload :Resources, 'poise_build_essential/resources' + autoload :VERSION, 'poise_build_essential/version' +end diff --git a/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers.rb b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers.rb new file mode 100644 index 0000000..d8cd687 --- /dev/null +++ b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers.rb @@ -0,0 +1,49 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/platform/provider_priority_map' + +require 'poise_build_essential/build_essential_providers/debian' +require 'poise_build_essential/build_essential_providers/freebsd' +require 'poise_build_essential/build_essential_providers/mac_os_x' +require 'poise_build_essential/build_essential_providers/omnios' +require 'poise_build_essential/build_essential_providers/rhel' +require 'poise_build_essential/build_essential_providers/smartos' +require 'poise_build_essential/build_essential_providers/solaris' +require 'poise_build_essential/build_essential_providers/suse' +# require 'poise_build_essential/build_essential_providers/windows' + + +module PoiseBuildEssential + # Inversion providers for the poise_build_essential resource. + # + # @since 1.0.0 + module BuildEssentialProviders + # Set up priority maps + Chef::Platform::ProviderPriorityMap.instance.priority(:poise_build_essential, [ + PoiseBuildEssential::BuildEssentialProviders::Debian, + PoiseBuildEssential::BuildEssentialProviders::FreeBSD, + PoiseBuildEssential::BuildEssentialProviders::MacOSX, + PoiseBuildEssential::BuildEssentialProviders::OmniOS, + PoiseBuildEssential::BuildEssentialProviders::RHEL, + PoiseBuildEssential::BuildEssentialProviders::SmartOS, + PoiseBuildEssential::BuildEssentialProviders::Solaris, + PoiseBuildEssential::BuildEssentialProviders::SUSE, + # PoiseBuildEssential::BuildEssentialProviders::Windows, + PoiseBuildEssential::BuildEssentialProviders::Base, + ]) + end +end diff --git a/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/base.rb b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/base.rb new file mode 100644 index 0000000..7c6e912 --- /dev/null +++ b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/base.rb @@ -0,0 +1,103 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/provider' +require 'poise' + + +module PoiseBuildEssential + module BuildEssentialProviders + # The provider base class for `poise_build_essential`. + # + # @see PoiseBuildEssential::Resources::PoiseBuildEssential::Resource + # @provides poise_build_essential + class Base < Chef::Provider + include Poise + provides(:poise_build_essential) + + # The `install` action for the `poise_build_essential` resource. + # + # @return [void] + def action_install + notifying_block do + install_build_essential + end + end + + # The `upgrade` action for the `poise_build_essential` resource. + # + # @return [void] + def action_upgrade + notifying_block do + upgrade_build_essential + end + end + + # The `remove` action for the `poise_build_essential` resource. + # + # @return [void] + def action_remove + notifying_block do + remove_build_essential + end + end + + private + + # Install C compiler and build tools. Must be implemented by subclasses. + # + # @abstract + def install_build_essential + unsupported_platform("Unknown platform for poise_build_eseential: #{node['platform']} (#{node['platform_family']})") + # Return an array so upgrade/remove also work. + [] + end + + # Upgrade C compiler and build tools. Must be implemented by subclasses. + # + # @abstract + def upgrade_build_essential + install_build_essential.tap do |installed| + Array(installed).each {|r| r.action(:upgrade) } + end + end + + # Uninstall C compiler and build tools. Must be implemented by subclasses. + # + # @abstract + def remove_build_essential + install_build_essential.tap do |installed| + Array(installed).each {|r| r.action(:remove) } + end + end + + # Helper method for either warning about an unsupported platform or raising + # an exception. + # + # @api private + # @param msg [String] Error message to display. + # @return [void] + def unsupported_platform(msg) + if new_resource.allow_unsupported_platform + Chef::Log.warn(msg) + else + raise RuntimeError.new(msg) + end + end + + end + end +end diff --git a/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/debian.rb b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/debian.rb new file mode 100644 index 0000000..9fd0bd9 --- /dev/null +++ b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/debian.rb @@ -0,0 +1,41 @@ +# +# Copyright 2008-2017, Chef Software, Inc. +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_build_essential/build_essential_providers/base' + + +module PoiseBuildEssential + module BuildEssentialProviders + # A provider for `poise_build_essential` to install on Debian platforms. + # + # @see PoiseBuildEssential::Resources::PoiseBuildEssential::Resource + # @provides poise_build_essential + class Debian < Base + provides(:poise_build_essential, platform_family: 'debian') + + private + + # (see Base#install_build_essential) + def install_build_essential + package %w{autoconf binutils-doc bison build-essential flex gettext ncurses-dev} + end + + end + end +end + + diff --git a/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/freebsd.rb b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/freebsd.rb new file mode 100644 index 0000000..d462c2b --- /dev/null +++ b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/freebsd.rb @@ -0,0 +1,46 @@ +# +# Copyright 2008-2017, Chef Software, Inc. +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_build_essential/build_essential_providers/base' + + +module PoiseBuildEssential + module BuildEssentialProviders + # A provider for `poise_build_essential` to install on FreeBSD platforms. + # + # @see PoiseBuildEssential::Resources::PoiseBuildEssential::Resource + # @provides poise_build_essential + class FreeBSD < Base + provides(:poise_build_essential, platform_family: 'freebsd') + + private + + # (see Base#install_build_essential) + def install_build_essential + pkgs = %w{devel/gmake devel/autoconf devel/m4 devel/gettext} + # Only install gcc on freebsd 9.x - 10 uses clang. + if node['platform_version'].to_i <= 9 + pkgs << 'lang/gcc49' + end + pkgs.map {|name| package name } + end + + end + end +end + + diff --git a/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/mac_os_x.rb b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/mac_os_x.rb new file mode 100644 index 0000000..ab2849c --- /dev/null +++ b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/mac_os_x.rb @@ -0,0 +1,66 @@ +# +# Copyright 2008-2017, Chef Software, Inc. +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_build_essential/build_essential_providers/base' + + +module PoiseBuildEssential + module BuildEssentialProviders + # A provider for `poise_build_essential` to install on macOS platforms. + # + # @see PoiseBuildEssential::Resources::PoiseBuildEssential::Resource + # @provides poise_build_essential + class MacOSX < Base + provides(:poise_build_essential, platform_family: 'mac_os_x') + + private + + # (see Base#install_build_essential) + def install_build_essential + # This script was graciously borrowed and modified from Tim Sutton's + # osx-vm-templates at https://github.com/timsutton/osx-vm-templates/blob/b001475df54a9808d3d56d06e71b8fa3001fff42/scripts/xcode-cli-tools.sh + execute 'install XCode Command Line tools' do + command <<-EOH +# create the placeholder file that's checked by CLI updates' .dist code +# in Apple's SUS catalog +touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress +# find the CLI Tools update +PROD=$(softwareupdate -l | grep "\*.*Command Line" | head -n 1 | awk -F"*" '{print $2}' | sed -e 's/^ *//' | tr -d '\n') +# install it +softwareupdate -i "$PROD" --verbose +# Remove the placeholder to prevent perpetual appearance in the update utility +rm -f /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress + EOH + not_if 'pkgutil --pkgs=com.apple.pkg.CLTools_Executables' + end + end + + # (see Base#upgrade_build_essential) + def upgrade_build_essential + # Make upgrade the same as install on Mac. + install_build_essential + end + + # (see Base#remove_build_essential) + def remove_build_essential + # Not sure how to do this, ignoring for now. + raise NotImplementedError + end + + end + end +end diff --git a/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/omnios.rb b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/omnios.rb new file mode 100644 index 0000000..3a22af0 --- /dev/null +++ b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/omnios.rb @@ -0,0 +1,46 @@ +# +# Copyright 2008-2017, Chef Software, Inc. +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_build_essential/build_essential_providers/base' + + +module PoiseBuildEssential + module BuildEssentialProviders + # A provider for `poise_build_essential` to install on OmniOS platforms. + # + # @see PoiseBuildEssential::Resources::PoiseBuildEssential::Resource + # @provides poise_build_essential + class OmniOS < Base + provides(:poise_build_essential, platform_family: 'omnios') + + private + + # (see Base#install_build_essential) + def install_build_essential + # Per OmniOS documentation, the gcc bin dir isn't in the default + # $PATH, so add it to the running process environment. + # http://omnios.omniti.com/wiki.php/DevEnv + ENV['PATH'] = "#{ENV['PATH']}:/opt/gcc-4.7.2/bin" + + %w{developer/gcc48 developer/object-file developer/linker + developer/library/lint developer/build/gnu-make system/header + system/library/math/header-math}.map {|name| package name } + end + + end + end +end diff --git a/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/rhel.rb b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/rhel.rb new file mode 100644 index 0000000..65052a5 --- /dev/null +++ b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/rhel.rb @@ -0,0 +1,46 @@ +# +# Copyright 2008-2017, Chef Software, Inc. +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_build_essential/build_essential_providers/base' + + +module PoiseBuildEssential + module BuildEssentialProviders + # A provider for `poise_build_essential` to install on RedHat and Fedora platforms. + # + # @see PoiseBuildEssential::Resources::PoiseBuildEssential::Resource + # @provides poise_build_essential + class RHEL < Base + provides(:poise_build_essential, platform_family: %w{rhel fedora}) + + private + + # (see Base#install_build_essential) + def install_build_essential + pkgs = %w{autoconf bison flex gcc gcc-c++ gettext kernel-devel make m4 ncurses-devel patch} + # Ensure GCC 4 is available on older pre-6 EL + if node['platform_family'] == 'rhel' && node['platform_version'].to_i < 6 + pkgs += %w{gcc44 gcc44-c++} + end + package pkgs + end + + end + end +end + + diff --git a/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/smartos.rb b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/smartos.rb new file mode 100644 index 0000000..8f45af1 --- /dev/null +++ b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/smartos.rb @@ -0,0 +1,39 @@ +# +# Copyright 2008-2017, Chef Software, Inc. +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_build_essential/build_essential_providers/base' + + +module PoiseBuildEssential + module BuildEssentialProviders + # A provider for `poise_build_essential` to install on SmartOS platforms. + # + # @see PoiseBuildEssential::Resources::PoiseBuildEssential::Resource + # @provides poise_build_essential + class SmartOS < Base + provides(:poise_build_essential, platform_family: 'smartos') + + private + + # (see Base#install_build_essential) + def install_build_essential + %w{autoconf binutils build-essential gcc47 gmake pkg-config}.map {|name| package name } + end + + end + end +end diff --git a/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/solaris.rb b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/solaris.rb new file mode 100644 index 0000000..2ef2b50 --- /dev/null +++ b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/solaris.rb @@ -0,0 +1,47 @@ +# +# Copyright 2008-2017, Chef Software, Inc. +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_build_essential/build_essential_providers/base' + + +module PoiseBuildEssential + module BuildEssentialProviders + # A provider for `poise_build_essential` to install on Solaris platforms. + # + # @see PoiseBuildEssential::Resources::PoiseBuildEssential::Resource + # @provides poise_build_essential + class Solaris < Base + provides(:poise_build_essential, platform_family: 'solaris2') + + private + + # (see Base#install_build_essential) + def install_build_essential + if node['platform_version'].to_f < 5.11 + unsupported_platform('poise_build_essential does not support Solaris before 11. You will need to install SUNWbison, SUNWgcc, SUNWggrp, SUNWgmake, and SUNWgtar from the Solaris DVD') + return [] + end + + # lock because we don't use gcc 5 yet. + [package('gcc') { version '4.8.2'} ] + \ + %w{autoconf automake bison gnu-coreutils flex gcc-3 gnu-grep gnu-make + gnu-patch gnu-tar make pkg-config ucb}.map {|name| package name } + end + + end + end +end diff --git a/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/suse.rb b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/suse.rb new file mode 100644 index 0000000..b734631 --- /dev/null +++ b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/suse.rb @@ -0,0 +1,43 @@ +# +# Copyright 2008-2017, Chef Software, Inc. +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_build_essential/build_essential_providers/base' + + +module PoiseBuildEssential + module BuildEssentialProviders + # A provider for `poise_build_essential` to install on SUSE platforms. + # + # @see PoiseBuildEssential::Resources::PoiseBuildEssential::Resource + # @provides poise_build_essential + class SUSE < Base + provides(:poise_build_essential, platform_family: 'suse') + + private + + # (see Base#install_build_essential) + def install_build_essential + pkgs = %w{autoconf bison flex gcc gcc-c++ kernel-default-devel make m4} + if node['platform_version'].to_i < 12 + pkgs += %w{gcc48 gcc48-c++} + end + package pkgs + end + + end + end +end diff --git a/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/windows.rb b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/windows.rb new file mode 100644 index 0000000..67251db --- /dev/null +++ b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/build_essential_providers/windows.rb @@ -0,0 +1,68 @@ +# +# Copyright 2008-2017, Chef Software, Inc. +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_build_essential/build_essential_providers/base' + + +module PoiseBuildEssential + module BuildEssentialProviders + # A provider for `poise_build_essential` to install on Windows platforms. + # + # @see PoiseBuildEssential::Resources::PoiseBuildEssential::Resource + # @provides poise_build_essential + class Windows < Base + provides(:poise_build_essential, platform_family: 'windows') + + private + + # (see Base#install_build_essential) + def install_build_essential + install_build_essential_packages + end + + # (see Base#upgrade_build_essential) + def upgrade_build_essential + # Upgrade and install are the same on Windows. (?) + install_build_essential + end + + # (see Base#remove_build_essential) + def remove_build_essential + raise NotImplementedError + end + + # Install MSYS2 packages needed for the build environment. + # + # @api private + # @return [Array] + def install_build_essential_packages + # TODO This probably won't work on 32-bit right now, fix that. + [ + 'base-devel', # Brings down msys based bash/make/awk/patch/stuff. + 'mingw-w64-x86_64-toolchain', # Puts 64-bit SEH mingw toolchain in msys2\mingw64. + 'mingw-w64-i686-toolchain' # Puts 32-bit DW2 mingw toolchain in msys2\ming32. + ].map do |pkg_group| + # The pacman package provider doesn't support groups, so going old-school. + poise_msys2_execute "pacman --sync #{pkg_group}" do + command ['pacman', '--sync', '--noconfirm', '--noprogressbar', '--needed', pkg_group] + end + end + end + + end + end +end diff --git a/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/cheftie.rb b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/cheftie.rb new file mode 100644 index 0000000..c771207 --- /dev/null +++ b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/cheftie.rb @@ -0,0 +1,18 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_build_essential/resources' +require 'poise_build_essential/build_essential_providers' diff --git a/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/resources.rb b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/resources.rb new file mode 100644 index 0000000..25c75d3 --- /dev/null +++ b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/resources.rb @@ -0,0 +1,26 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_build_essential/resources/poise_build_essential' + + +module PoiseBuildEssential + # Chef resources and providers for poise-build-essential. + # + # @since 1.0.0 + module Resources + end +end diff --git a/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/resources/poise_build_essential.rb b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/resources/poise_build_essential.rb new file mode 100644 index 0000000..e5e08cc --- /dev/null +++ b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/resources/poise_build_essential.rb @@ -0,0 +1,48 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/resource' +require 'poise' + + +module PoiseBuildEssential + module Resources + # (see PoiseBuildEssential::Resource) + # @since 1.0.0 + module PoiseBuildEssential + # A `poise_build_essential` resource to install a C compiler and build tools. + # + # @provides poise_build_essential + # @action install + # @action upgrade + # @action uninstall + # @example + # poise_build_essential 'build-essential' + class Resource < Chef::Resource + include Poise + provides(:poise_build_essential) + actions(:install, :upgrade, :remove) + + # @!attribute allow_unsupported_platform + # Whether or not to raise an error on unsupported platforms. + # @return [Boolean] + attribute(:allow_unsupported_platform, kind_of: [TrueClass, FalseClass], default: lazy { node['poise-build-essential']['allow_unsupported_platform'] }) + end + + # Providers can be found under build_essential_providers/. + end + end +end diff --git a/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/version.rb b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/version.rb new file mode 100644 index 0000000..58a1c80 --- /dev/null +++ b/cookbooks/poise-build-essential/files/halite_gem/poise_build_essential/version.rb @@ -0,0 +1,20 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseBuildEssential + VERSION = '1.0.0' +end diff --git a/cookbooks/poise-build-essential/libraries/default.rb b/cookbooks/poise-build-essential/libraries/default.rb new file mode 100644 index 0000000..4b0a953 --- /dev/null +++ b/cookbooks/poise-build-essential/libraries/default.rb @@ -0,0 +1,19 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +raise 'Halite is not compatible with no_lazy_load false, please set no_lazy_load true in your Chef configuration file.' unless Chef::Config[:no_lazy_load] +$LOAD_PATH << File.expand_path('../../files/halite_gem', __FILE__) +require "poise_build_essential/cheftie" diff --git a/cookbooks/poise-build-essential/metadata.json b/cookbooks/poise-build-essential/metadata.json new file mode 100644 index 0000000..c1ddba6 --- /dev/null +++ b/cookbooks/poise-build-essential/metadata.json @@ -0,0 +1 @@ +{"name":"poise-build-essential","version":"1.0.0","description":"A Chef cookbook to install a C compiler and build tools.","long_description":"# Poise-Build-Essential Cookbook\n\n[![Build Status](https://img.shields.io/travis/poise/poise-build-essential.svg)](https://travis-ci.org/poise/poise-build-essential)\n[![Gem Version](https://img.shields.io/gem/v/poise-build-essential.svg)](https://rubygems.org/gems/poise-build-essential)\n[![Cookbook Version](https://img.shields.io/cookbook/v/poise-build-essential.svg)](https://supermarket.chef.io/cookbooks/poise-build-essential)\n[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-build-essential.svg)](https://codecov.io/github/poise/poise-build-essential)\n[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-build-essential.svg)](https://gemnasium.com/poise/poise-build-essential)\n[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)\n\nA [Chef](https://www.chef.io/) cookbook to install a C compiler and build tools..\n\n## Quick Start\n\nTo install a C compiler:\n\n```ruby\ninclude_recipe 'poise-build-essential'\n```\n\nOr to install using a resource and at compile time:\n\n```ruby\npoise_build_essential 'build_essential' do\n action :nothing\nend.run_action(:install)\n```\n\n## Recipes\n\n* `poise-build-essential::default` – Install a C compiler and build tools.\n\n## Attributes\n\n* `node['poise-build-essential']['action']` – Action to use. One of install,\n upgrade, or remove. *(default: install)*\n* `node['poise-build-essential']['allow_unsupported_platform']` – Whether or not\n to raise an error on unsupported platforms. *(default: false)*\n\n## Resources\n\n### `poise_build_essential`\n\nThe `poise_build_essential` resource installs a C compiler and build tools.\n\n```ruby\npoise_build_essential 'build_essential' do\n allow_unsupported_platform true\nend\n```\n\n#### Actions\n\n* `:install` – Install a C compiler. *(default)*\n* `:upgrade` – Install a C compiler using `package action :ugprade` rules.\n* `:remove` – Remove a C compiler.\n\n#### Properties\n\n* `allow_unsupported_platform` – Whether or not to raise an error on unsupported\n platforms. *(default: false)*\n\n## Sponsors\n\nDevelopment sponsored by [SAP](https://www.sap.com/).\n\nThe Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/).\n\n## License\n\nSome code copyright 2008-2017, Chef Software, Inc. Used under the terms of the\nApache License, Version 2.0.\n\nCopyright 2017, Noah Kantrowitz\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","maintainer":"Noah Kantrowitz","maintainer_email":"noah@coderanger.net","license":"Apache 2.0","platforms":{},"dependencies":{"poise":"~> 2.6"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/poise/poise-build-essential","issues_url":"https://github.com/poise/poise-build-essential/issues","chef_version":[["< 14",">= 12.1"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/poise-build-essential/recipes/default.rb b/cookbooks/poise-build-essential/recipes/default.rb new file mode 100644 index 0000000..9c89821 --- /dev/null +++ b/cookbooks/poise-build-essential/recipes/default.rb @@ -0,0 +1,19 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +poise_build_essential 'build_essential' do + action node['poise-build-essential']['action'].to_sym +end diff --git a/cookbooks/poise-git/CHANGELOG.md b/cookbooks/poise-git/CHANGELOG.md new file mode 100644 index 0000000..d037b8c --- /dev/null +++ b/cookbooks/poise-git/CHANGELOG.md @@ -0,0 +1,5 @@ +# Poise-Git Changelog + +## v1.0.0 + +* Initial release! diff --git a/cookbooks/poise-git/README.md b/cookbooks/poise-git/README.md new file mode 100644 index 0000000..2d8a6e0 --- /dev/null +++ b/cookbooks/poise-git/README.md @@ -0,0 +1,151 @@ +# Poise-Git Cookbook + +[![Build Status](https://img.shields.io/travis/poise/poise-git.svg)](https://travis-ci.org/poise/poise-git) +[![Gem Version](https://img.shields.io/gem/v/poise-git.svg)](https://rubygems.org/gems/poise-git) +[![Cookbook Version](https://img.shields.io/cookbook/v/poise-git.svg)](https://supermarket.chef.io/cookbooks/poise-git) +[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-git.svg)](https://codecov.io/github/poise/poise-git) +[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-git.svg)](https://gemnasium.com/poise/poise-git) +[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) + +A [Chef](https://www.chef.io/) cookbook to manage [Git](https://git-scm.com/). + +## Quick Start + +To install Git and clone a repository using a deploy key from a data bag: + +```ruby +poise_git '/srv/myapp' do + repository 'git@github.com:example/myapp.git' + deploy_key data_bag_item('keys', 'myapp')['key'] +end +``` + +To install Git and clone a repository using a deploy key that already exists on +disk: + +```ruby +poise_git '/srv/myapp' do + repository 'git@github.com:example/myapp.git' + deploy_key '/path/to/mykey.pem' +end +``` + +## Recipes + +* `poise-git::default` – Install Git. + +## Attributes + +* `node['poise-git']['default_recipe']` – Recipe used by `poise_git` to install + Git if not already available. *(default: poise-git)* +* `node['poise-git']['provider']` – Default provider for `poise_git_client` resource + instances. *(default: auto)* +* `node['poise-git']['recipe'][*]` – All subkeys of `'recipe'` will be passed + as properties to the `poise_git_client` resource before installation when using + the `poise-git::default` recipe. + +## Resources + +### `poise_git` + +The `poise_git` resource extends the core `git` resource, adding a `deploy_key` +property to use SSH deploy keys automatically. + +```ruby +poise_git '/srv/myapp' do + repository 'git@github.com:example/myapp.git' + deploy_key 'mysecretkey' +end +``` + +The `poise_git` resource supports all the same actions and properties as the +core `git` resource. + +The `deploy_key` property can either be passed the absolute path to an existing +SSH key file, or the raw SSH private key text. + +### `poise_git_client` + +The `poise_git_client` resource installs Git. + +```ruby +poise_git_client 'git' +``` + +#### Actions + +* `:install` – Install Git. *(default)* +* `:uninstall` – Uninstall Git. + +#### Properties + +* `version` – Version of Git to install. If a partial version is given, use the + latest available version matching that prefix. *(name property)* + +#### Provider Options + +The `poise_git_client` resource uses provide options for per-provider configuration. See +[the poise-service documentation](https://github.com/poise/poise-service#service-options) +for more information on using provider options. + +## Git Client Providers + +### `system` + +The `system` provider installs Git using system packages. This is currently +only tested on platforms using `apt-get` and `yum` (Debian, Ubuntu, RHEL, CentOS +Amazon Linux, and Fedora) and is a default provider on those platforms. It may +work on other platforms but is untested. + +```ruby +poise_git_client 'git' do + provider :system +end +``` + +#### Options + +* `package_name` – Override auto-detection of the package name. +* `package_upgrade` – Install using action `:upgrade`. *(default: false)* +* `package_version` – Override auto-detection of the package version. + +### `dummy` + +The `dummy` provider supports using the `poise_git_client` resource with ChefSpec +or other testing frameworks to not actually install Git. It is used by default under +ChefSpec. It can also be used to manage the Git installation externally from +this cookbook. + +```ruby +poise_git_client 'git' do + provider :dummy + options git_binary: '/path/to/git' +end +``` + +#### Provider Options + +* `git_binary` – Path to the `git` executable. *(default: /git)* +* `git_environment` – Hash of environment variables to use with this Git. *(default: {})* + +## Sponsors + +Development sponsored by [SAP](https://www.sap.com/). + +The Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/). + +## License + +Copyright 2015-2017, Noah Kantrowitz + +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/cookbooks/poise-git/attributes/default.rb b/cookbooks/poise-git/attributes/default.rb new file mode 100644 index 0000000..ae15453 --- /dev/null +++ b/cookbooks/poise-git/attributes/default.rb @@ -0,0 +1,26 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +# Default recipe to use to install git. +default['poise-git']['default_recipe'] = 'poise-git' + +# Default inversion options. +default['poise-git']['provider'] = 'auto' +default['poise-git']['options'] = {} + +# Attributes for recipe[poise-git]. All values are nil because the actual +# defaults live in the resource. +default['poise-git']['recipe']['version'] = nil diff --git a/cookbooks/poise-git/files/halite_gem/poise_git.rb b/cookbooks/poise-git/files/halite_gem/poise_git.rb new file mode 100644 index 0000000..9da6e6a --- /dev/null +++ b/cookbooks/poise-git/files/halite_gem/poise_git.rb @@ -0,0 +1,24 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseGit + autoload :GitClientProviders, 'poise_git/git_client_providers' + autoload :GitCommandMixin, 'poise_git/git_command_mixin' + autoload :Resources, 'poise_git/resources' + autoload :SafeString, 'poise_git/safe_string' + autoload :VERSION, 'poise_git/version' +end diff --git a/cookbooks/poise-git/files/halite_gem/poise_git/cheftie.rb b/cookbooks/poise-git/files/halite_gem/poise_git/cheftie.rb new file mode 100644 index 0000000..54b295f --- /dev/null +++ b/cookbooks/poise-git/files/halite_gem/poise_git/cheftie.rb @@ -0,0 +1,18 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_git/resources' +require 'poise_git/git_client_providers' diff --git a/cookbooks/poise-git/files/halite_gem/poise_git/git_client_providers.rb b/cookbooks/poise-git/files/halite_gem/poise_git/git_client_providers.rb new file mode 100644 index 0000000..552a035 --- /dev/null +++ b/cookbooks/poise-git/files/halite_gem/poise_git/git_client_providers.rb @@ -0,0 +1,36 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/platform/provider_priority_map' + +require 'poise_git/git_client_providers/dummy' +require 'poise_git/git_client_providers/system' + + +module PoiseGit + # Inversion providers for the poise_git resource. + # + # @since 1.0.0 + module GitClientProviders + autoload :Base, 'poise_git/git_client_providers/base' + + # Set up priority maps + Chef::Platform::ProviderPriorityMap.instance.priority(:poise_git_client, [ + PoiseGit::GitClientProviders::Dummy, + PoiseGit::GitClientProviders::System, + ]) + end +end diff --git a/cookbooks/poise-git/files/halite_gem/poise_git/git_client_providers/base.rb b/cookbooks/poise-git/files/halite_gem/poise_git/git_client_providers/base.rb new file mode 100644 index 0000000..fdc370c --- /dev/null +++ b/cookbooks/poise-git/files/halite_gem/poise_git/git_client_providers/base.rb @@ -0,0 +1,93 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/provider' +require 'poise' + + +module PoiseGit + module GitClientProviders + # The provider base class for `poise_git_client`. + # + # @see PoiseGit::Resources::PoiseGitClient::Resource + # @provides poise_git_client + class Base < Chef::Provider + include Poise(inversion: :poise_git_client) + provides(:poise_git_client) + + # Set default inversion options. + # + # @api private + def self.default_inversion_options(node, new_resource) + super.merge({ + version: new_resource.version, + }) + end + + # The `install` action for the `poise_git_client` resource. + # + # @return [void] + def action_install + notifying_block do + install_git + end + end + + # The `uninstall` action for the `poise_git_client` resource. + # + # @return [void] + def action_uninstall + notifying_block do + uninstall_git + end + end + + # The path to the `git` binary. This is an output property. + # + # @abstract + # @return [String] + def git_binary + raise NotImplementedError + end + + # The environment variables for this Git. This is an output property. + # + # @return [Hash] + def git_environment + {} + end + + private + + # Install git. + # + # @abstract + # @return [void] + def install_git + raise NotImplementedError + end + + # Uninstall git. + # + # @abstract + # @return [void] + def uninstall_git + raise NotImplementedError + end + + end + end +end diff --git a/cookbooks/poise-git/files/halite_gem/poise_git/git_client_providers/dummy.rb b/cookbooks/poise-git/files/halite_gem/poise_git/git_client_providers/dummy.rb new file mode 100644 index 0000000..39f1194 --- /dev/null +++ b/cookbooks/poise-git/files/halite_gem/poise_git/git_client_providers/dummy.rb @@ -0,0 +1,79 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_git/git_client_providers/base' + + +module PoiseGit + module GitClientProviders + # Inversion provider for the `poise_git_client` resource to use a fake Git, + # for use in unit tests. + # + # @since 1.0.0 + # @see PoiseGit::Resources::PoiseGitClient::Resource + # @provides poise_git_client + class Dummy < Base + provides(:dummy) + + # Enable by default on ChefSpec. + # + # @api private + def self.provides_auto?(node, _resource) + node.platform?('chefspec') + end + + # Manual overrides for dummy data. + # + # @api private + def self.default_inversion_options(node, resource) + super.merge({ + git_binary: '/git', + git_environment: nil, + }) + end + + # The `install` action for the `poise_git_client` resource. + # + # @return [void] + def action_install + # This space left intentionally blank. + end + + # The `uninstall` action for the `poise_git_client` resource. + # + # @return [void] + def action_uninstall + # This space left intentionally blank. + end + + # Path to the non-existent Git. + # + # @return [String] + def git_binary + options['git_binary'] + end + + # Environment for the non-existent Git. + # + # @return [String] + def git_environment + options['git_environment'] || super + end + + end + end +end + diff --git a/cookbooks/poise-git/files/halite_gem/poise_git/git_client_providers/system.rb b/cookbooks/poise-git/files/halite_gem/poise_git/git_client_providers/system.rb new file mode 100644 index 0000000..812039d --- /dev/null +++ b/cookbooks/poise-git/files/halite_gem/poise_git/git_client_providers/system.rb @@ -0,0 +1,73 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_languages' + +require 'poise_git/git_client_providers/base' + + +module PoiseGit + module GitClientProviders + # A provider for `poise_git_client` to install from distro packages. + # + # @since 1.0.0 + # @see PoiseGit::Resources::PoiseGitClient::Resource + # @provides poise_git_client + class System < Base + include PoiseLanguages::System::Mixin + provides(:system) + packages('git', { + omnios: {default: %w{developer/versioning/git}}, + smartos: {default: %w{scmgit}}, + }) + + # Output value for the Git binary we are installing. + def git_binary + # What should this be for OmniOS and SmartOS? + "/usr/bin/git" + end + + private + + # Install git from system packages. + # + # @return [void] + def install_git + install_system_packages do + # Unlike language-ish packages, we don't need a headers package. + dev_package false + end + end + + # Remove git from system packages. + # + # @return [void] + def uninstall_git + uninstall_system_packages do + # Unlike language-ish packages, we don't need a headers package. + dev_package false + end + end + + def system_package_candidates(version) + # This is kind of silly, could use a refactor in the mixin but just + # moving on for right now. + node.value_for_platform(self.class.packages) || %w{git} + end + + end + end +end diff --git a/cookbooks/poise-git/files/halite_gem/poise_git/git_command_mixin.rb b/cookbooks/poise-git/files/halite_gem/poise_git/git_command_mixin.rb new file mode 100644 index 0000000..7e1d3f0 --- /dev/null +++ b/cookbooks/poise-git/files/halite_gem/poise_git/git_command_mixin.rb @@ -0,0 +1,37 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'poise/utils' +require 'poise_languages' + + +module PoiseGit + # Mixin for resources and providers which run Git commands. + # + # @since 1.0.0 + module GitCommandMixin + include Poise::Utils::ResourceProviderMixin + + # Mixin for resources which run Git commands. + module Resource + include PoiseLanguages::Command::Mixin::Resource(:git, runtime: :poise_git_client) + end + + module Provider + include PoiseLanguages::Command::Mixin::Provider(:git) + end + end +end diff --git a/cookbooks/poise-git/files/halite_gem/poise_git/resources.rb b/cookbooks/poise-git/files/halite_gem/poise_git/resources.rb new file mode 100644 index 0000000..ce7f5ab --- /dev/null +++ b/cookbooks/poise-git/files/halite_gem/poise_git/resources.rb @@ -0,0 +1,27 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_git/resources/poise_git_client' +require 'poise_git/resources/poise_git' + + +module PoiseGit + # Chef resources and providers for poise-git. + # + # @since 1.0.0 + module Resources + end +end diff --git a/cookbooks/poise-git/files/halite_gem/poise_git/resources/poise_git.rb b/cookbooks/poise-git/files/halite_gem/poise_git/resources/poise_git.rb new file mode 100644 index 0000000..9eb621d --- /dev/null +++ b/cookbooks/poise-git/files/halite_gem/poise_git/resources/poise_git.rb @@ -0,0 +1,252 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'shellwords' +require 'zlib' + +require 'chef/provider/git' +require 'chef/resource/git' +require 'poise' + +require 'poise_git/git_command_mixin' +require 'poise_git/safe_string' + + +module PoiseGit + module Resources + # (see PoiseGit::Resource) + # @since 1.0.0 + module PoiseGit + # A `poise_git` resource to manage Python installations using pip. + # + # @provides poise_git + # @action checkout + # @action export + # @action sync + # @example + # poise_git '/srv/myapp' do + # repository 'https://...' + # deploy_key data_bag_item('deploy_keys', 'myapp')['key'] + # end + class Resource < Chef::Resource::Git + include Poise + include ::PoiseGit::GitCommandMixin + provides(:poise_git) + # Manually create matchers because #actions is unreliable. + %i{checkout export sync}.each do |action| + Poise::Helpers::ChefspecMatchers.create_matcher(:poise_git, action) + end + + # @api private + def initialize(*args) + super + # Because the superclass declares this, we have to as well. Should be + # removable at some point when Chef makes everything use the provider + # resolver system instead. + @resource_name = :poise_git if defined?(@resource_name) && @resource_name + @provider = ::PoiseGit::Resources::PoiseGit::Provider if defined?(@provider) && @provider + end + + # @!attribute strict_ssh + # Enable strict SSH host key checking. Defaults to false. + # @return [Boolean] + attribute(:strict_ssh, equal_to: [true, false], default: false) + + # @!attribute deploy_key + # SSH deploy key as either a string value or a path to a key file. + # @return [String] + def deploy_key(val=nil) + # Use a SafeString for literal deploy keys so they aren't shown. + val = SafeString.new(val) if val && !deploy_key_is_local?(val) + set_or_return(:deploy_key, val, kind_of: String) + end + + # Default SSH wrapper path. + # + # @api private + # @return [String] + def ssh_wrapper_path + @ssh_wrapper_path ||= "#{Chef::Config[:file_cache_path]}/poise_git_wrapper_#{Zlib.crc32(name)}" + end + + # Guess if the deploy key is a local path or literal value. + # + # @api private + # @param key [String, nil] Key value to check. Defaults to self.key. + # @return [Boolean] + def deploy_key_is_local?(key=nil) + key ||= deploy_key + # Try to be mindful of Windows-y paths here even though they almost + # certainly won't actually work later on with ssh. + key && key =~ /\A(\/|[a-zA-Z]:)/ + end + + # Path to deploy key. + # + # @api private + # @return [String] + def deploy_key_path + @deploy_key_path ||= if deploy_key_is_local? + deploy_key + else + "#{Chef::Config[:file_cache_path]}/poise_git_deploy_#{Zlib.crc32(name)}" + end + end + + # Hook to force the git install via recipe if needed. + def after_created + if !parent_git && node['poise-git']['default_recipe'] + # Use the default recipe to give us a parent the next time we ask. + run_context.include_recipe(node['poise-git']['default_recipe']) + # Force it to re-expand the cache next time. + @parent_git = nil + end + super + end + + end + + # The default provider for the `poise_git` resource. + # + # @see Resource + class Provider < Chef::Provider::Git + include Poise + include ::PoiseGit::GitCommandMixin + provides(:poise_git) + + # @api private + def initialize(*args) + super + # Set the SSH wrapper path in a late-binding kind of way. This better + # supports situations where the user doesn't exist until Chef converges. + new_resource.ssh_wrapper(new_resource.ssh_wrapper_path) if new_resource.deploy_key + end + + # Hack our special login in before load_current_resource runs because that + # needs access to the git remote. + # + # @api private + def load_current_resource + create_deploy_key if new_resource.deploy_key + super + end + + # Like {#load_current_resource}, make sure git is installed since we might + # need it depending on the version of Chef. + # + # @api private + def define_resource_requirements + create_deploy_key if new_resource.deploy_key + super + end + + private + + # Install git and set up the deploy key if needed. Safe to call multiple + # times if needed. + # + # @api private + # @return [void] + def create_deploy_key + return if @create_deploy_key + Chef::Log.debug("[#{new_resource}] Creating deploy key") + old_why_run = Chef::Config[:why_run] + begin + # Forcibly disable why run support so these will always run, since + # we need to be able to talk to the git remote even just for the + # whyrun checks. + Chef::Config[:why_run] = false + notifying_block do + write_deploy_key + write_ssh_wrapper + end + ensure + Chef::Config[:why_run] = old_why_run + end + @create_deploy_key = true + end + + # Copy the deploy key to a file if needed. + # + # @api private + # @return [void] + def write_deploy_key + # Check if we have a local path or some actual content + return if new_resource.deploy_key_is_local? + file new_resource.deploy_key_path do + owner new_resource.user + group new_resource.group + mode '600' + content new_resource.deploy_key + sensitive true + end + end + + # Create the SSH wrapper script. + # + # @api private + # @return [void] + def write_ssh_wrapper + # Write out the GIT_SSH script, it should already be enabled above + file new_resource.ssh_wrapper_path do + owner new_resource.user + group new_resource.group + mode '700' + content %Q{#!/bin/sh\n/usr/bin/env ssh #{'-o "StrictHostKeyChecking=no" ' unless new_resource.strict_ssh}-i "#{new_resource.deploy_key_path}" $@\n} + end + end + + # Patch back in the `#git` from the git provider. This otherwise conflicts + # with the `#git` defined by the DSL, which gets included in such a way + # that the DSL takes priority. + # + # @api private + def git(*args, &block) + self.class.superclass.instance_method(:git).bind(self).call(*args, &block) + end + + # Trick all shell_out related things in the base class in to using + # my git_shell_out instead. + # + # @api private + def shell_out(*cmd, **options) + if @shell_out_hack_inner + # This is the real call. + super + else + # This ia call we want to intercept and send to our method. + begin + @shell_out_hack_inner = true + # Remove nils and flatten for compat with how core uses this method. + cmd.compact! + cmd.flatten! + # Reparse the command to get a clean array. + cmd = Shellwords.split(cmd.join(' ')) + # We'll add the git command back in ourselves. + cmd.shift if cmd.first == 'git' + # Push the yak stack. + git_shell_out(*cmd, **options) + ensure + @shell_out_hack_inner = false + end + end + end + + end + + end + end +end diff --git a/cookbooks/poise-git/files/halite_gem/poise_git/resources/poise_git_client.rb b/cookbooks/poise-git/files/halite_gem/poise_git/resources/poise_git_client.rb new file mode 100644 index 0000000..0a83d4f --- /dev/null +++ b/cookbooks/poise-git/files/halite_gem/poise_git/resources/poise_git_client.rb @@ -0,0 +1,82 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/resource' +require 'poise' + + +module PoiseGit + module Resources + # (see PoiseGitClient::Resource) + # @since 1.0.0 + module PoiseGitClient + # A `poise_git_client` resource to install a C compiler and build tools. + # + # @provides poise_git_client + # @action install + # @action uninstall + # @example + # poise_git_client 'git' + class Resource < Chef::Resource + include Poise(inversion: true, container: true) + provides(:poise_git_client) + actions(:install, :uninstall) + + # @!attribute version + # Version of Git to install. The version is prefix-matched so `'2'` + # will install the most recent Git 2.x, and so on. + # @return [String] + # @example Install any version + # poise_git_client 'any' do + # version '' + # end + # @example Install Git 2 + # poise_git_client '2' + attribute(:version, kind_of: String, default: lazy { default_version }) + + # The path to the `git` binary for this Git installation. This is + # an output property. + # + # @return [String] + # @example + # execute "#{resources('poise_git_client[git]').git_binary} init" + def git_binary + provider_for_action(:git_binary).git_binary + end + + # The environment variables for this Git installation. This is an + # output property. + # + # @return [Hash] + def git_environment + provider_for_action(:git_environment).git_environment + end + + private + + # Default value for the version property. Trims an optional `git-` from + # the resource name. + # + # @return [String] + def default_version + name[/^(git-?)?(.*)$/, 2] || '' + end + end + + # Providers can be found under git_client_providers/. + end + end +end diff --git a/cookbooks/poise-git/files/halite_gem/poise_git/safe_string.rb b/cookbooks/poise-git/files/halite_gem/poise_git/safe_string.rb new file mode 100644 index 0000000..347e54f --- /dev/null +++ b/cookbooks/poise-git/files/halite_gem/poise_git/safe_string.rb @@ -0,0 +1,25 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseGit + # A string that won't be shown in Chef error output + class SafeString < String + def to_text + '"suppressed sensitive value"' + end + end +end diff --git a/cookbooks/poise-git/files/halite_gem/poise_git/version.rb b/cookbooks/poise-git/files/halite_gem/poise_git/version.rb new file mode 100644 index 0000000..f998a84 --- /dev/null +++ b/cookbooks/poise-git/files/halite_gem/poise_git/version.rb @@ -0,0 +1,20 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseGit + VERSION = '1.0.0' +end diff --git a/cookbooks/poise-git/libraries/default.rb b/cookbooks/poise-git/libraries/default.rb new file mode 100644 index 0000000..b2f6163 --- /dev/null +++ b/cookbooks/poise-git/libraries/default.rb @@ -0,0 +1,19 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +raise 'Halite is not compatible with no_lazy_load false, please set no_lazy_load true in your Chef configuration file.' unless Chef::Config[:no_lazy_load] +$LOAD_PATH << File.expand_path('../../files/halite_gem', __FILE__) +require "poise_git/cheftie" diff --git a/cookbooks/poise-git/metadata.json b/cookbooks/poise-git/metadata.json new file mode 100644 index 0000000..610553d --- /dev/null +++ b/cookbooks/poise-git/metadata.json @@ -0,0 +1 @@ +{"name":"poise-git","version":"1.0.0","description":"A Chef cookbook for installing and using Git.","long_description":"# Poise-Git Cookbook\n\n[![Build Status](https://img.shields.io/travis/poise/poise-git.svg)](https://travis-ci.org/poise/poise-git)\n[![Gem Version](https://img.shields.io/gem/v/poise-git.svg)](https://rubygems.org/gems/poise-git)\n[![Cookbook Version](https://img.shields.io/cookbook/v/poise-git.svg)](https://supermarket.chef.io/cookbooks/poise-git)\n[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-git.svg)](https://codecov.io/github/poise/poise-git)\n[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-git.svg)](https://gemnasium.com/poise/poise-git)\n[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)\n\nA [Chef](https://www.chef.io/) cookbook to manage [Git](https://git-scm.com/).\n\n## Quick Start\n\nTo install Git and clone a repository using a deploy key from a data bag:\n\n```ruby\npoise_git '/srv/myapp' do\n repository 'git@github.com:example/myapp.git'\n deploy_key data_bag_item('keys', 'myapp')['key']\nend\n```\n\nTo install Git and clone a repository using a deploy key that already exists on\ndisk:\n\n```ruby\npoise_git '/srv/myapp' do\n repository 'git@github.com:example/myapp.git'\n deploy_key '/path/to/mykey.pem'\nend\n```\n\n## Recipes\n\n* `poise-git::default` – Install Git.\n\n## Attributes\n\n* `node['poise-git']['default_recipe']` – Recipe used by `poise_git` to install\n Git if not already available. *(default: poise-git)*\n* `node['poise-git']['provider']` – Default provider for `poise_git_client` resource\n instances. *(default: auto)*\n* `node['poise-git']['recipe'][*]` – All subkeys of `'recipe'` will be passed\n as properties to the `poise_git_client` resource before installation when using\n the `poise-git::default` recipe.\n\n## Resources\n\n### `poise_git`\n\nThe `poise_git` resource extends the core `git` resource, adding a `deploy_key`\nproperty to use SSH deploy keys automatically.\n\n```ruby\npoise_git '/srv/myapp' do\n repository 'git@github.com:example/myapp.git'\n deploy_key 'mysecretkey'\nend\n```\n\nThe `poise_git` resource supports all the same actions and properties as the\ncore `git` resource.\n\nThe `deploy_key` property can either be passed the absolute path to an existing\nSSH key file, or the raw SSH private key text.\n\n### `poise_git_client`\n\nThe `poise_git_client` resource installs Git.\n\n```ruby\npoise_git_client 'git'\n```\n\n#### Actions\n\n* `:install` – Install Git. *(default)*\n* `:uninstall` – Uninstall Git.\n\n#### Properties\n\n* `version` – Version of Git to install. If a partial version is given, use the\n latest available version matching that prefix. *(name property)*\n\n#### Provider Options\n\nThe `poise_git_client` resource uses provide options for per-provider configuration. See\n[the poise-service documentation](https://github.com/poise/poise-service#service-options)\nfor more information on using provider options.\n\n## Git Client Providers\n\n### `system`\n\nThe `system` provider installs Git using system packages. This is currently\nonly tested on platforms using `apt-get` and `yum` (Debian, Ubuntu, RHEL, CentOS\nAmazon Linux, and Fedora) and is a default provider on those platforms. It may\nwork on other platforms but is untested.\n\n```ruby\npoise_git_client 'git' do\n provider :system\nend\n```\n\n#### Options\n\n* `package_name` – Override auto-detection of the package name.\n* `package_upgrade` – Install using action `:upgrade`. *(default: false)*\n* `package_version` – Override auto-detection of the package version.\n\n### `dummy`\n\nThe `dummy` provider supports using the `poise_git_client` resource with ChefSpec\nor other testing frameworks to not actually install Git. It is used by default under\nChefSpec. It can also be used to manage the Git installation externally from\nthis cookbook.\n\n```ruby\npoise_git_client 'git' do\n provider :dummy\n options git_binary: '/path/to/git'\nend\n```\n\n#### Provider Options\n\n* `git_binary` – Path to the `git` executable. *(default: /git)*\n* `git_environment` – Hash of environment variables to use with this Git. *(default: {})*\n\n## Sponsors\n\nDevelopment sponsored by [SAP](https://www.sap.com/).\n\nThe Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/).\n\n## License\n\nCopyright 2015-2017, Noah Kantrowitz\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","maintainer":"Noah Kantrowitz","maintainer_email":"noah@coderanger.net","license":"Apache 2.0","platforms":{},"dependencies":{"poise":"~> 2.6","poise-languages":"~> 2.1"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/poise/poise-git","issues_url":"https://github.com/poise/poise-git/issues","chef_version":[["< 14",">= 12.1"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/poise-git/recipes/default.rb b/cookbooks/poise-git/recipes/default.rb new file mode 100644 index 0000000..a884efe --- /dev/null +++ b/cookbooks/poise-git/recipes/default.rb @@ -0,0 +1,22 @@ +# +# Copyright 2017, Noah Kantrowitz +# +# 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. +# + +poise_git_client 'git' do + node['poise-git']['recipe'].each do |key, value| + # Skip nils, use false if you want to disable something. + send(key, value) unless value.nil? + end +end diff --git a/cookbooks/poise-javascript/CHANGELOG.md b/cookbooks/poise-javascript/CHANGELOG.md new file mode 100644 index 0000000..6911f35 --- /dev/null +++ b/cookbooks/poise-javascript/CHANGELOG.md @@ -0,0 +1,21 @@ +# Poise-Javascript Changelog + +## v1.2.0 + +* Updated Node.js versions. The default version is now the Boron LTS series. +* Chef 13 support. + +## v1.1.0 + +* New version list for Node.js. +* Support new SCL structure and packages. + +## v1.0.1 + +* Update for Chef 12.6 compatibility. +* Update version list for `nodejs` provider. + +## v1.0.0 + +* Initial release! + diff --git a/cookbooks/poise-javascript/LICENSE b/cookbooks/poise-javascript/LICENSE new file mode 100644 index 0000000..11069ed --- /dev/null +++ b/cookbooks/poise-javascript/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/cookbooks/poise-javascript/README.md b/cookbooks/poise-javascript/README.md new file mode 100644 index 0000000..a8368f4 --- /dev/null +++ b/cookbooks/poise-javascript/README.md @@ -0,0 +1,332 @@ +# Poise-Javascript Cookbook + +[![Build Status](https://img.shields.io/travis/poise/poise-javascript.svg)](https://travis-ci.org/poise/poise-javascript) +[![Gem Version](https://img.shields.io/gem/v/poise-javascript.svg)](https://rubygems.org/gems/poise-javascript) +[![Cookbook Version](https://img.shields.io/cookbook/v/poise-javascript.svg)](https://supermarket.chef.io/cookbooks/poise-javascript) +[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-javascript.svg)](https://codecov.io/github/poise/poise-javascript) +[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-javascript.svg)](https://gemnasium.com/poise/poise-javascript) +[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) + +A [Chef](https://www.chef.io/) cookbook to provide a unified interface for +installing server-side JavaScript runtimes like Node.js and io.js. + +## Quick Start + +To install the latest available version of Node.js 0.12: + +```ruby +javascript_runtime '0.12' +``` + +## Supported JavaScript Runtimes + +This cookbook can install Node.js and io.js on Linux and OS X. + +## Requirements + +Chef 12.1 or newer is required. + +## Attributes + +Attributes are used to configure the default recipe. + +* `node['poise-javascript']['install_nodejs']` – Install a Node.js runtime. *(default: true)* +* `node['poise-javascript']['install_iojs']` – Install an io.js runtime. *(default: false)* + +## Recipes + +### `default` + +The default recipe installs Node.js or io.js based on the node attributes. It is +entirely optional and can be ignored in favor of direct use of the +`javascript_runtime` resource. + +## Resources + +### `javascript_runtime` + +The `javascript_runtime` resource installs a JavaScript interpreter. + +```ruby +javascript_runtime '0.12' +``` + +#### Actions + +* `:install` – Install the JavaScript interpreter. *(default)* +* `:uninstall` – Uninstall the JavaScript interpreter. + +#### Properties + +* `version` – Version of the runtime to install. If a partial version is given, + use the latest available version matching that prefix. *(name property)* + +#### Provider Options + +The `poise-javascript` library offers an additional way to pass configuration +information to the final provider called "options". Options are key/value pairs +that are passed down to the `javascript_runtime` provider and can be used to control how it +installs JavaScript. These can be set in the `javascript_runtime` +resource using the `options` method, in node attributes or via the +`javascript_runtime_options` resource. The options from all sources are merged +together in to a single hash. + +When setting options in the resource you can either set them for all providers: + +```ruby +javascript_runtime 'myapp' do + version '0.10' + options dev_package: false +end +``` + +or for a single provider: + +```ruby +javascript_runtime 'myapp' do + version '0.10' + options :system, dev_package: false +end +``` + +Setting via node attributes is generally how an end-user or application cookbook +will set options to customize installations in the library cookbooks they are using. +You can set options for all installations or for a single runtime: + +```ruby +# Global, for all installations. +override['poise-javascript']['options']['version'] = '0.10' +# Single installation. +override['poise-javascript']['myapp']['version'] = 'iojs' +``` + +The `javascript_runtime_options` resource is also available to set node attributes +for a specific installation in a DSL-friendly way: + +```ruby +javascript_runtime_options 'myapp' do + version 'iojs' +end +``` + +Unlike resource attributes, provider options can be different for each provider. +Not all providers support the same options so make sure to the check the +documentation for each provider to see what options the use. + +### `javascript_runtime_options` + +The `javascript_runtime_options` resource allows setting provider options in a +DSL-friendly way. See [the Provider Options](#provider-options) section for more +information about provider options overall. + +```ruby +javascript_runtime_options 'myapp' do + version 'iojs' +end +``` + +#### Actions + +* `:run` – Apply the provider options. *(default)* + +#### Properties + +* `resource` – Name of the `javascript_runtime` resource. *(name property)* +* `for_provider` – Provider to set options for. + +All other attribute keys will be used as options data. + +### `javascript_execute` + +The `javascript_execute` resource executes a JavaScript script using the configured runtime. + +```ruby +javascript_execute 'myapp.js' do + user 'myuser' +end +``` + +This uses the built-in `execute` resource and supports all the same properties. + +#### Actions + +* `:run` – Execute the script. *(default)* + +#### Properties + +* `command` – Script and arguments to run. Must not include the `node`. *(name attribute)* +* `javascript` – Name of the `javascript_runtime` resource to use. If not specified, the + most recently declared `javascript_runtime` will be used. Can also be set to the + full path to a `node` binary. + +For other properties see the [Chef documentation](https://docs.chef.io/resource_execute.html#attributes). + +### `node_package` + +The `node_package` resource installs Node.js packages using +[NPM](https://www.npmjs.com/). + +```ruby +node_package 'express' do + version '4.13.3' +end +``` + +This uses the built-in `package` resource and supports the same actions and +properties. Multi-package installs are supported using the standard syntax. + +#### Actions + +* `:install` – Install the package. *(default)* +* `:upgrade` – Upgrade the package. +* `:remove` – Uninstall the package. + +The `:purge` and `:reconfigure` actions are not supported. + +#### Properties + +* `group` – System group to install the package. +* `package_name` – Package or packages to install. *(name property)* +* `path` – Path to install the package in to. If unset install using `--global`. + *(default: nil)* +* `version` – Version or versions to install. +* `javascript` – Name of the `javascript_runtime` resource to use. If not specified, the + most recently declared `javascript_runtime` will be used. Can also be set to the + full path to a `node` binary. +* `unsafe_perm` – Enable `--unsafe-perm`. *(default: true)* +* `user` – System user to install the package. + +For other properties see the [Chef documentation](https://docs.chef.io/resource_package.html#attributes). +The `response_file`, `response_file_variables`, and `source` properties are not +supported. + +### `npm_install` + +The `npm_install` resource runs `npm install` for a package. + +```ruby +npm_install '/opt/myapp' +``` + +The underlying `npm install` command will run on every converge, but notifications +will only be triggered if a package is actually installed. + +#### Actions + +* `:install` – Run `npm install`. *(default)* + +#### Properties + +* `path` – Path to the package folder containing a `package.json`. *(name attribute)* +* `group` – System group to install the packages. +* `javascript` – Name of the `javascript_runtime` resource to use. If not specified, the + most recently declared `javascript_runtime` will be used. Can also be set to the + full path to a `node` binary. +* `production` – Enable production install mode. *(default: true)* +* `unsafe_perm` – Enable `--unsafe-perm`. *(default: true)* +* `user` – System user to install the packages. + +## Javascript Providers + +### Common Options + +These provider options are supported by all providers. + +* `version` – Override the runtime version. + +### `system` + +The `system` provider installs Node.js using system packages. This is currently +only tested on platforms using `apt-get` and `yum` (Debian, Ubuntu, RHEL, CentOS +Amazon Linux, and Fedora). It may work on other platforms but is untested. + +```ruby +javascript_runtime 'myapp' do + provider :system + version '0.10' +end +``` + +#### Options + +* `dev_package` – Install the package with the headers and other development + files. Can be set to a string to select the dev package specifically. + *(default: true)* +* `package_name` – Override auto-detection of the package name. +* `package_upgrade` – Install using action `:upgrade`. *(default: false)* +* `package_version` – Override auto-detection of the package version. + +### `scl` + +The `scl` provider installs Node.js using the [Software Collections](https://www.softwarecollections.org/) +packages. This is only available on RHEL and CentOS. SCL offers more +recent versions of Node.js than the system packages for the most part. If an SCL +package exists for the requests version, it will be used in preference to the +`system` provider. + +```ruby +javascript_runtime 'myapp' do + provider :scl + version '0.10' +end +``` + +### `nodejs` + +The `nodejs` provider installs Node.js from the static binaries on nodejs.org. +Support is included for Linux and OS X. + +```ruby +javascript_runtime 'myapp' do + provider :nodejs + version '0.12' +end +``` + +#### Options + +* `path` – Folder to install Node.js to. *(default: /opt/nodejs-)* +* `static_version` – Specific version number to use for computing the URL and + path. *(default: automatic from `version`)* +* `strip_components` – Value to pass to tar --strip-components. *(automatic)* +* `url` – URL template to download the archive from. *(default: automatic)* + +### `iojs` + +The `iojs` provider installs io.js from the static binaries on iojs.org. +Support is included for Linux and OS X. + +```ruby +javascript_runtime 'myapp' do + provider :iojs + version '3' +end +``` + +#### Options + +* `path` – Folder to install io.js to. *(default: /opt/iojs-)* +* `static_version` – Specific version number to use for computing the URL and + path. *(default: automatic from `version`)* +* `strip_components` – Value to pass to tar --strip-components. *(automatic)* +* `url` – URL template to download the archive from. *(default: automatic)* + +## Sponsors + +The Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/). + +## License + +Copyright 2015-2017, Noah Kantrowitz + +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/cookbooks/poise-javascript/attributes/default.rb b/cookbooks/poise-javascript/attributes/default.rb new file mode 100644 index 0000000..f9da36f --- /dev/null +++ b/cookbooks/poise-javascript/attributes/default.rb @@ -0,0 +1,23 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +# Default inversion options. +default['poise-javascript']['provider'] = 'auto' +default['poise-javascript']['options'] = {} + +# Used for the default recipe. +default['poise-javascript']['install_nodejs'] = true +default['poise-javascript']['install_iojs'] = false diff --git a/cookbooks/poise-javascript/files/halite_gem/poise_javascript.rb b/cookbooks/poise-javascript/files/halite_gem/poise_javascript.rb new file mode 100644 index 0000000..1625ad7 --- /dev/null +++ b/cookbooks/poise-javascript/files/halite_gem/poise_javascript.rb @@ -0,0 +1,24 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseJavascript + autoload :Error, 'poise_javascript/error' + autoload :Resources, 'poise_javascript/resources' + autoload :JavascriptCommandMixin, 'poise_javascript/javascript_command_mixin' + autoload :JavascriptProviders, 'poise_javascript/javascript_providers' + autoload :VERSION, 'poise_javascript/version' +end diff --git a/cookbooks/poise-javascript/files/halite_gem/poise_javascript/cheftie.rb b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/cheftie.rb new file mode 100644 index 0000000..45aa376 --- /dev/null +++ b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/cheftie.rb @@ -0,0 +1,18 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_javascript/resources' +require 'poise_javascript/javascript_providers' diff --git a/cookbooks/poise-javascript/files/halite_gem/poise_javascript/error.rb b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/error.rb new file mode 100644 index 0000000..b556b2d --- /dev/null +++ b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/error.rb @@ -0,0 +1,23 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_languages' + + +module PoiseJavascript + class Error < PoiseLanguages::Error + end +end diff --git a/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_command_mixin.rb b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_command_mixin.rb new file mode 100644 index 0000000..d3690a8 --- /dev/null +++ b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_command_mixin.rb @@ -0,0 +1,56 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'poise/utils' +require 'poise_languages' + + +module PoiseJavascript + # Mixin for resources and providers which run Javascript commands. + # + # @since 1.0.0 + module JavascriptCommandMixin + include Poise::Utils::ResourceProviderMixin + + # Mixin for resources which run Javascript commands. + module Resource + include PoiseLanguages::Command::Mixin::Resource(:javascript, default_binary: 'node') + + # @!attribute npm_binary + # Path to the npm binary. + # @return [String] + attribute(:npm_binary, kind_of: String, default: lazy { default_npm_binary }) + + private + + # Find the default gem binary. If there is a parent use that, otherwise + # use the same logic as {PoiseRuby::RubyProviders::Base#npm_binary}. + # + # @return [String] + def default_npm_binary + if parent_javascript + parent_javascript.npm_binary + else + ::File.expand_path('../npm', javascript) + end + end + end + + module Provider + include PoiseLanguages::Command::Mixin::Provider(:javascript) + end + end +end diff --git a/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers.rb b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers.rb new file mode 100644 index 0000000..7859cad --- /dev/null +++ b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers.rb @@ -0,0 +1,40 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/platform/provider_priority_map' + +require 'poise_javascript/javascript_providers/dummy' +require 'poise_javascript/javascript_providers/iojs' +require 'poise_javascript/javascript_providers/nodejs' +require 'poise_javascript/javascript_providers/scl' +require 'poise_javascript/javascript_providers/system' + + +module PoiseJavascript + # Inversion providers for the javascript_runtime resource. + # + # @since 1.0.0 + module JavascriptProviders + autoload :Base, 'poise_javascript/javascript_providers/base' + + Chef::Platform::ProviderPriorityMap.instance.priority(:javascript_runtime, [ + PoiseJavascript::JavascriptProviders::IOJS, + PoiseJavascript::JavascriptProviders::NodeJS, + PoiseJavascript::JavascriptProviders::Scl, + PoiseJavascript::JavascriptProviders::System, + ]) + end +end diff --git a/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers/base.rb b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers/base.rb new file mode 100644 index 0000000..55b2c0e --- /dev/null +++ b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers/base.rb @@ -0,0 +1,97 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/provider' +require 'poise' + + +module PoiseJavascript + module JavascriptProviders + class Base < Chef::Provider + include Poise(inversion: :javascript_runtime) + + # Set default inversion options. + # + # @api private + def self.default_inversion_options(node, new_resource) + super.merge({ + version: new_resource.version, + }) + end + + # The `install` action for the `javascript_runtime` resource. + # + # @return [void] + def action_install + notifying_block do + install_javascript + end + end + + # The `uninstall` action for the `javascript_runtime` resource. + # + # @abstract + # @return [void] + def action_uninstall + notifying_block do + uninstall_javascript + end + end + + # The path to the `javascript` binary. This is an output property. + # + # @abstract + # @return [String] + def javascript_binary + raise NotImplementedError + end + + # The environment variables for this Javascript. This is an output property. + # + # @return [Hash] + def javascript_environment + {} + end + + # The path to the `npm` binary. This is an output property. + # + # @abstract + # @return [String] + def npm_binary + ::File.expand_path(::File.join('..', 'npm'), javascript_binary) + end + + private + + # Install the Javascript runtime. Must be implemented by subclass. + # + # @abstract + # @return [void] + def install_javascript + raise NotImplementedError + end + + # Uninstall the Javascript runtime. Must be implemented by subclass. + # + # @abstract + # @return [void] + def uninstall_javascript + raise NotImplementedError + end + + end + end +end diff --git a/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers/dummy.rb b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers/dummy.rb new file mode 100644 index 0000000..9ef97c8 --- /dev/null +++ b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers/dummy.rb @@ -0,0 +1,77 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_javascript/javascript_providers/base' + + +module PoiseJavascript + module JavascriptProviders + # Inversion provider for the `javascript_runtime` resource to use a fake Javascript, + # for use in unit tests. + # + # @since 1.0.0 + # @provides dummy + class Dummy < Base + provides(:dummy) + + def self.default_inversion_options(node, resource) + super.merge({ + # Manual overrides for dummy data. + javascript_binary: ::File.join('', 'node'), + javascript_environment: nil, + npm_binary: nil, + }) + end + + # The `install` action for the `javascript_runtime` resource. + # + # @return [void] + def action_install + # This space left intentionally blank. + end + + # The `uninstall` action for the `javascript_runtime` resource. + # + # @return [void] + def action_uninstall + # This space left intentionally blank. + end + + # Path to the non-existent Javascript. + # + # @return [String] + def javascript_binary + options['javascript_binary'] + end + + # Environment for the non-existent Javascript. + # + # @return [String] + def javascript_environment + options['javascript_environment'] || super + end + + # Path to the non-existent npm. + # + # @return [String] + def npm_binary + options['npm_binary'] || super + end + + end + end +end + diff --git a/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers/iojs.rb b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers/iojs.rb new file mode 100644 index 0000000..c6cea34 --- /dev/null +++ b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers/iojs.rb @@ -0,0 +1,64 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/resource' +require 'poise_languages/static' + +require 'poise_javascript/error' +require 'poise_javascript/javascript_providers/base' + + +module PoiseJavascript + module JavascriptProviders + class IOJS < Base + provides(:iojs) + include PoiseLanguages::Static( + versions: %w{3.3.1 3.2.0 3.1.0 3.0.0 2.5.0 2.4.0 2.3.4 2.2.1 2.1.0 2.0.2 1.8.4 1.7.1 1.6.4 1.5.1 1.4.3 1.3.0 1.2.0 1.1.0 1.0.4}, + machines: %w{linux-i686 linux-x86_64 darwin-x86_64}, + url: 'https://iojs.org/dist/v%{version}/iojs-v%{version}-%{kernel}-%{machine}.tar.gz', + ) + + def self.provides_auto?(node, resource) + # Also work if we have a version starting with 1. 2. or 3. since that has + # to be io.js and no other mechanism supports that. + super || (resource.version.to_s =~ /^[123](\.|$)/ && static_machines.include?(static_machine_label(node))) + end + + MACHINE_LABELS = {'i386' => 'x86', 'i686' => 'x86', 'x86_64' => 'x64'} + + def static_url_variables + machine = node['kernel']['machine'] + super.merge(machine: MACHINE_LABELS[machine] || machine) + end + + def javascript_binary + ::File.join(static_folder, 'bin', 'iojs') + end + + private + + def install_javascript + install_static + end + + def uninstall_javascript + uninstall_static + end + + end + end +end + diff --git a/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers/nodejs.rb b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers/nodejs.rb new file mode 100644 index 0000000..ebeac3b --- /dev/null +++ b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers/nodejs.rb @@ -0,0 +1,65 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/resource' +require 'poise_languages/static' + +require 'poise_javascript/error' +require 'poise_javascript/javascript_providers/base' + + +module PoiseJavascript + module JavascriptProviders + class NodeJS < Base + provides(:nodejs) + include PoiseLanguages::Static( + # LTS version is first so that it is what you get for version ''. + versions: %w{8.11.1 10.0.0 9.11.1 9.10.1 9.9.0 9.8.0 9.7.1 9.6.1 9.5.0 9.4.0 9.3.0 9.2.1 9.1.0 9.0.0 8.10.0 8.9.4 8.8.1 8.7.0 8.6.0 8.5.0 8.4.0 8.3.0 8.2.1 8.1.4 8.0.0 7.10.1 7.9.0 7.8.0 7.7.4 7.6.0 7.5.0 7.4.0 7.3.0 7.2.1 7.1.0 7.0.0 6.14.2 6.13.1 6.12.3 6.11.5 6.10.3 6.9.5 6.8.1 6.7.0 6.6.0 6.5.0 6.4.0 6.3.1 6.2.2 6.1.0 6.0.0 5.12.0 5.11.1 5.10.1 5.9.1 5.8.0 5.7.1 5.6.0 5.5.0 5.4.1 5.3.0 5.2.0 5.1.1 5.0.0 4.9.1 4.8.7 4.7.3 4.6.2 4.5.0 4.4.7 4.3.2 4.2.6 4.1.2 4.0.0 0.12.18 0.11.16 0.10.48 0.9.12 0.8.28 0.7.12 0.6.21 0.5.10 0.4.12 0.3.8 0.2.6 0.1.104}, + machines: %w{linux-i686 linux-x86_64 linux-armv6l linux-armv7l linux-arm64 darwin-x86_64}, + url: 'https://nodejs.org/dist/v%{version}/node-v%{version}-%{kernel}-%{machine}.tar.gz', + ) + + def self.provides_auto?(node, resource) + # Also work if we have a blank or numeric-y version. This should make + # it the default provider on supported platforms. + super || (resource.version.to_s =~ /^(\d|$)/ && static_machines.include?(static_machine_label(node))) + end + + MACHINE_LABELS = {'i386' => 'x86', 'i686' => 'x86', 'x86_64' => 'x64'} + + def static_url_variables + machine = node['kernel']['machine'] + super.merge(machine: MACHINE_LABELS[machine] || machine) + end + + def javascript_binary + ::File.join(static_folder, 'bin', 'node') + end + + private + + def install_javascript + install_static + end + + def uninstall_javascript + uninstall_static + end + + end + end +end + diff --git a/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers/scl.rb b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers/scl.rb new file mode 100644 index 0000000..22066db --- /dev/null +++ b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers/scl.rb @@ -0,0 +1,53 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/resource' +require 'poise_languages' + +require 'poise_javascript/error' +require 'poise_javascript/javascript_providers/base' + + +module PoiseJavascript + module JavascriptProviders + class Scl < Base + include PoiseLanguages::Scl::Mixin + provides(:scl) + scl_package('4.4.2', 'rh-nodejs4', 'rh-nodejs4-nodejs-devel', '>= 7.0') + scl_package('0.10.35', 'nodejs010', 'nodejs010-nodejs-devel') + + def javascript_binary + ::File.join(scl_folder, 'root', 'usr', 'bin', 'node') + end + + def javascript_environment + scl_environment + end + + private + + def install_javascript + install_scl_package + end + + def uninstall_javascript + uninstall_scl_package + end + + end + end +end + diff --git a/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers/system.rb b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers/system.rb new file mode 100644 index 0000000..965fcc0 --- /dev/null +++ b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/javascript_providers/system.rb @@ -0,0 +1,71 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/resource' +require 'poise_languages' + +require 'poise_javascript/error' +require 'poise_javascript/javascript_providers/base' + + +module PoiseJavascript + module JavascriptProviders + class System < Base + include PoiseLanguages::System::Mixin + provides(:system) + packages('nodejs', { + debian: {default: %w{nodejs}}, + ubuntu: {default: %w{nodejs}}, + # Empty arrays because no package in the base OS. + redhat: {default: %w{}}, + centos: {default: %w{}}, + fedora: {default: %w{nodejs}}, + amazon: {default: %w{}}, + }) + + def self.provides_auto?(node, resource) + # Don't auto on platforms I know have no system package by default. Kind + # of pointless since the nodejs provider will hit on these platforms + # anyway so this shouldn't ever happen. + super && !node.platform_family?('rhel') && !node.platform?('amazon') + end + + def javascript_binary + # Debian and Ubuntu after 12.04 changed the binary name ಠ_ಠ. + binary_name = node.value_for_platform(debian: {default: 'nodejs'}, ubuntu: {'12.04' => 'node', default: 'nodejs'}, default: 'node') + ::File.join('', 'usr', 'bin', binary_name) + end + + private + + def install_javascript + install_system_packages + package %w{npm nodejs-legacy} if node.platform_family?('debian') + end + + def uninstall_javascript + uninstall_system_packages + package(%w{npm nodejs-legacy}) { action :purge } if node.platform_family?('debian') + end + + def system_package_candidates(version) + # Boring :-(. + %w{nodejs nodejs-legacy node} + end + + end + end +end diff --git a/cookbooks/poise-javascript/files/halite_gem/poise_javascript/resources.rb b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/resources.rb new file mode 100644 index 0000000..24a70b7 --- /dev/null +++ b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/resources.rb @@ -0,0 +1,29 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_javascript/resources/javascript_execute' +require 'poise_javascript/resources/javascript_runtime' +require 'poise_javascript/resources/node_package' +require 'poise_javascript/resources/npm_install' + + +module PoiseJavascript + # Chef resources and providers for poise-javascript. + # + # @since 1.0.0 + module Resources + end +end diff --git a/cookbooks/poise-javascript/files/halite_gem/poise_javascript/resources/javascript_execute.rb b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/resources/javascript_execute.rb new file mode 100644 index 0000000..f84e67e --- /dev/null +++ b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/resources/javascript_execute.rb @@ -0,0 +1,83 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/mixin/which' +require 'chef/provider/execute' +require 'chef/resource/execute' +require 'poise' + +require 'poise_javascript/javascript_command_mixin' + + +module PoiseJavascript + module Resources + # (see JavascriptExecute::Resource) + # @since 1.0.0 + module JavascriptExecute + # A `javascript_execute` resource to run Javascript scripts and commands. + # + # @provides javascript_execute + # @action run + # @example + # javascript_execute 'myapp.js' do + # user 'myuser' + # end + class Resource < Chef::Resource::Execute + include PoiseJavascript::JavascriptCommandMixin + provides(:javascript_execute) + actions(:run) + end + + # The default provider for `javascript_execute`. + # + # @see Resource + # @provides javascript_execute + class Provider < Chef::Provider::Execute + include Chef::Mixin::Which + provides(:javascript_execute) + + private + + # Command to pass to shell_out. + # + # @return [String, Array] + def command + if new_resource.command.is_a?(Array) + [new_resource.javascript] + new_resource.command + else + "#{new_resource.javascript} #{new_resource.command}" + end + end + + # Environment variables to pass to shell_out. + # + # @return [Hash] + def environment + if new_resource.parent_javascript + environment = new_resource.parent_javascript.javascript_environment + if new_resource.environment + environment = environment.merge(new_resource.environment) + end + environment + else + new_resource.environment + end + end + + end + end + end +end diff --git a/cookbooks/poise-javascript/files/halite_gem/poise_javascript/resources/javascript_runtime.rb b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/resources/javascript_runtime.rb new file mode 100644 index 0000000..da1d932 --- /dev/null +++ b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/resources/javascript_runtime.rb @@ -0,0 +1,85 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/resource' +require 'poise' + + +module PoiseJavascript + module Resources + # (see JavascriptRuntime::Resource) + # @since 1.0.0 + module JavascriptRuntime + # A `javascript_runtime` resource to manage Javascript installations. + # + # @provides javascript_runtime + # @action install + # @action uninstall + # @example + # javascript_runtime '2.7' + class Resource < Chef::Resource + include Poise(inversion: true, container: true) + provides(:javascript_runtime) + actions(:install, :uninstall) + + # @!attribute version + # Version of Javascript to install. This is generally a NodeJS version + # but because of io.js there are shenanigans. + # @return [String] + # @example Install any version + # javascript_runtime 'any' do + # version '' + # end + attribute(:version, kind_of: String, name_attribute: true) + + # The path to the `node` binary for this Javascript installation. This is + # an output property. + # + # @return [String] + # @example + # execute "#{resources('javascript_runtime[nodejs]').javascript_binary} myapp.js" + def javascript_binary + provider_for_action(:javascript_binary).javascript_binary + end + + # The environment variables for this Javascript installation. This is an + # output property. + # + # @return [Hash] + # @example + # execute '/opt/myapp.js' do + # environment resources('javascript_runtime[nodejs]').javascript_environment + # end + def javascript_environment + provider_for_action(:javascript_environment).javascript_environment + end + + # The path to the `npm` binary for this Javascript installation. This is + # an output property. Can raise an exception if NPM is not supported for + # this runtime. + # + # @return [String] + # @example + # execute "#{resources('javascript_runtime[nodejs]').npm_binary} install" + def npm_binary + provider_for_action(:npm_binary).npm_binary + end + end + + # Providers can be found under lib/poise_javascript/javascript_providers/ + end + end +end diff --git a/cookbooks/poise-javascript/files/halite_gem/poise_javascript/resources/javascript_runtime_test.rb b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/resources/javascript_runtime_test.rb new file mode 100644 index 0000000..0811ad6 --- /dev/null +++ b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/resources/javascript_runtime_test.rb @@ -0,0 +1,226 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/provider' +require 'chef/resource' +require 'poise' + + +module PoiseJavascript + module Resources + # (see JavascriptRuntimeTest::Resource) + # @since 1.0.0 + # @api private + module JavascriptRuntimeTest + # A `javascript_runtime_test` resource for integration testing of this + # cookbook. This is an internal API and can change at any time. + # + # @provides javascript_runtime_test + # @action run + class Resource < Chef::Resource + include Poise + provides(:javascript_runtime_test) + actions(:run) + + attribute(:version, kind_of: String, name_attribute: true) + attribute(:runtime_provider, kind_of: Symbol) + attribute(:path, kind_of: String, default: lazy { default_path }) + attribute(:test_yo, equal_to: [true, false], default: true) + + def default_path + ::File.join('', 'root', "javascript_test_#{name}") + end + end + + # The default provider for `javascript_runtime_test`. + # + # @see Resource + # @provides javascript_runtime_test + class Provider < Chef::Provider + include Poise + provides(:javascript_runtime_test) + + # The `run` action for the `javascript_runtime_test` resource. + # + # @return [void] + def action_run + notifying_block do + # Top level directory for this test. + directory new_resource.path + + # Install and log the version. + javascript_runtime new_resource.name do + provider new_resource.runtime_provider if new_resource.runtime_provider + version new_resource.version + end + test_version + + # Create a package and test npm_install. + pkg_path = ::File.join(new_resource.path, 'pkg') + directory pkg_path + file ::File.join(pkg_path, 'package.json') do + content <<-EOH +{ + "name": "mypkg", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \\"Error: no test specified\\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "express": "4.13.3" + }, + "devDependencies": { + "handlebars": "4.0.2" + } +} +EOH + end + npm_install pkg_path do + notifies :create, sentinel_file('npm_install_one'), :immediately + end + npm_install pkg_path+'2' do + path pkg_path + notifies :create, sentinel_file('npm_install_two'), :immediately + end + test_require('express', pkg_path) + test_require('handlebars', pkg_path) + + # Test node_package. + test1_path = ::File.join(new_resource.path, 'test1') + directory test1_path + node_package 'express' do + path test1_path + notifies :create, sentinel_file('test1_express_one'), :immediately + end + node_package 'express two' do + package_name 'express' + path test1_path + notifies :create, sentinel_file('test1_express_two'), :immediately + end + node_package %w{gulp less} do + path test1_path + notifies :create, sentinel_file('test1_multi'), :immediately + end + node_package %w{express bower} do + path test1_path + notifies :create, sentinel_file('test1_multi_overlap'), :immediately + end + node_package 'bower' do + path test1_path + notifies :create, sentinel_file('test1_bower'), :immediately + end + node_package 'yo' do + path test1_path + version '1.4.5' + end if new_resource.test_yo + node_package 'forever' do + path test1_path + version '0.13.0' + end + test_require('express', test1_path, 'node_package_express') + test_require('gulp', test1_path) + test_require('less', test1_path) + test_require('bower', test1_path) + if new_resource.test_yo + test_require('yo', test1_path) + else + file ::File.join(new_resource.path, 'no_yo') + end + test_require('forever', test1_path) + + # Check we don't get cross talk between paths. + test2_path = ::File.join(new_resource.path, 'test2') + directory test2_path + node_package 'express' do + path test2_path + notifies :create, sentinel_file('test2_express'), :immediately + end + + # Test global installs. + node_package 'grunt-cli' do + notifies :create, sentinel_file('grunt_one'), :immediately + end + node_package 'grunt-cli two' do + package_name 'grunt-cli' + notifies :create, sentinel_file('grunt_two'), :immediately + end + test_require('grunt-cli', new_resource.path) + javascript_execute 'grunt-cli --version' do + command lazy { + # Check local/bin first and then just bin/. + grunt_path = ::File.expand_path('../../local/bin/grunt', javascript) + grunt_path = ::File.expand_path('../grunt', javascript) unless ::File.exist?(grunt_path) + "#{grunt_path} --version > #{::File.join(new_resource.path, 'grunt_version')}" + } + end + + end + end + + def sentinel_file(name) + file ::File.join(new_resource.path, "sentinel_#{name}") do + action :nothing + end + end + + private + + def test_version(javascript: new_resource.name) + # Only queue up this resource once, the ivar is just for tracking. + @javascript_version_test ||= file ::File.join(new_resource.path, 'javascript_version.js') do + user 'root' + group 'root' + mode '644' + content <<-EOH +var fs = require('fs'); +fs.writeFileSync(process.argv[2], process.version); +EOH + end + + javascript_execute "#{@javascript_version_test.path} #{::File.join(new_resource.path, 'version')}" do + javascript javascript if javascript + end + end + + def test_require(name, cwd, path=name, javascript: new_resource.name) + javascript_require_test = file ::File.join(cwd, 'javascript_require.js') do + user 'root' + group 'root' + mode '644' + content <<-EOH +var fs = require('fs'); +try { + var version = require(process.argv[2] + '/package.json').version; + fs.writeFileSync(process.argv[3], version); +} catch(e) { +} +EOH + end + + javascript_execute "#{javascript_require_test.path} #{name} #{::File.join(new_resource.path, "require_#{path}")}" do + javascript javascript if javascript + cwd cwd + end + end + + end + end + end +end diff --git a/cookbooks/poise-javascript/files/halite_gem/poise_javascript/resources/node_package.rb b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/resources/node_package.rb new file mode 100644 index 0000000..c368942 --- /dev/null +++ b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/resources/node_package.rb @@ -0,0 +1,254 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/json_compat' +require 'chef/provider/package' +require 'chef/resource/package' +require 'poise' + +require 'poise_javascript/error' +require 'poise_javascript/javascript_command_mixin' + + +module PoiseJavascript + module Resources + # (see NodePackage::Resource) + # @since 1.0.0 + module NodePackage + # A `node_package` resource to manage Node.js packages using npm. + # + # @provides node_package + # @action install + # @action upgrade + # @action uninstall + # @example + # node_package 'express' do + # javascript '0.10' + # version '1.8.3' + # end + class Resource < Chef::Resource::Package + include PoiseJavascript::JavascriptCommandMixin + provides(:node_package) + # Manually create matchers because #actions is unreliable. + %i{install upgrade remove}.each do |action| + Poise::Helpers::ChefspecMatchers.create_matcher(:node_package, action) + end + + # @!attribute group + # System group to install the package. + # @return [String, Integer, nil] + attribute(:group, kind_of: [String, Integer, NilClass]) + # @!attribute path + # Path to install the package in to. If unset install using --global. + # @return [String, nil, false] + attribute(:path, kind_of: [String, NilClass, FalseClass]) + # @!attribute unsafe_perm + # Enable --unsafe-perm. + # @return [Boolean, nil] + attribute(:unsafe_perm, equal_to: [true, false, nil], default: true) + # @!attribute user + # System user to install the package. + # @return [String, Integer, nil] + attribute(:user, kind_of: [String, Integer, NilClass]) + + def initialize(*args) + super + # For older Chef. + @resource_name = :node_package + # We don't have these actions. + @allowed_actions.delete(:purge) + @allowed_actions.delete(:reconfig) + end + + # Upstream attribute we don't support. Sets are an error and gets always + # return nil. + # + # @api private + # @param arg [Object] Ignored + # @return [nil] + def response_file(arg=nil) + raise NoMethodError if arg + end + + # (see #response_file) + def response_file_variables(arg=nil) + raise NoMethodError if arg && arg != {} + end + end + + # The default provider for the `node_package` resource. + # + # @see Resource + class Provider < Chef::Provider::Package + include PoiseJavascript::JavascriptCommandMixin + provides(:node_package) + + # Load current and candidate versions for all needed packages. + # + # @api private + # @return [Chef::Resource] + def load_current_resource + @current_resource = new_resource.class.new(new_resource.name, run_context) + current_resource.package_name(new_resource.package_name) + check_package_versions(current_resource) + current_resource + end + + # Populate current and candidate versions for all needed packages. + # + # @api private + # @param resource [PoiseJavascript::Resources::NodePackage::Resource] + # Resource to load for. + # @return [void] + def check_package_versions(resource) + version_data = Hash.new {|hash, key| hash[key] = {current: nil, candidate: nil} } + # Get the version for everything currently installed. + list_args = npm_version?('>= 1.4.16') ? %w{--depth 0} : [] + npm_shell_out!('list', list_args).fetch('dependencies', {}).each do |pkg_name, pkg_data| + version_data[pkg_name][:current] = pkg_data['version'] + end + # If any requested packages are currently installed, run npm outdated + # to look for candidate versions. Older npm doesn't support --json + # here so you get slow behavior, sorry. + requested_packages = Set.new(Array(resource.package_name)) + if npm_version?('>= 1.3.16') && version_data.any? {|pkg_name, _pkg_vers| requested_packages.include?(pkg_name) } + outdated = npm_shell_out!('outdated', returns: [0, 1]) || {} + version_data.each do |pkg_name, pkg_vers| + pkg_vers[:candidate] = if outdated.include?(pkg_name) + outdated[pkg_name]['wanted'] + else + # If it was already installed and not listed in outdated, it + # must have been up to date already. + pkg_vers[:current] + end + end + end + # Check for candidates for anything else we didn't get from outdated. + requested_packages.each do |pkg_name| + version_data[pkg_name][:candidate] ||= npm_shell_out!('show', [pkg_name])['version'] + end + # Populate the current resource and candidate versions. Youch this is + # a gross mix of data flow. + if(resource.package_name.is_a?(Array)) + @candidate_version = [] + versions = [] + [resource.package_name].flatten.each do |name| + ver = version_data[name.downcase] + versions << ver[:current] + @candidate_version << ver[:candidate] + end + resource.version(versions) + else + ver = version_data[resource.package_name.downcase] + resource.version(ver[:current]) + @candidate_version = ver[:candidate] + end + end + + # Install package(s) using npm. + # + # @param name [String, Array] Name(s) of package(s). + # @param version [String, Array] Version(s) of package(s). + # @return [void] + def install_package(name, version) + args = [] + # Set --unsafe-perm unless the property is nil. + unless new_resource.unsafe_perm.nil? + args << '--unsafe-perm' + args << new_resource.unsafe_perm.to_s + end + # Build up the actual package install args. + if new_resource.source + args << new_resource.source + else + Array(name).zip(Array(version)) do |pkg_name, pkg_ver| + args << "#{pkg_name}@#{pkg_ver}" + end + end + npm_shell_out!('install', args, parse_json: false) + end + + # Upgrade and install are the same for NPM. + alias_method :upgrade_package, :install_package + + # Uninstall package(s) using npm. + # + # @param name [String, Array] Name(s) of package(s). + # @param version [String, Array] Version(s) of package(s). + # @return [void] + def remove_package(name, version) + npm_shell_out!('uninstall', [name].flatten, parse_json: false) + end + + private + + # Run an npm command. + # + # @param subcmd [String] Subcommand to run. + # @param args [Array] Command arguments. + # @param parse_json [Boolean] Parse the JSON on stdout. + # @return [Hash] + def npm_shell_out!(subcmd, args=[], parse_json: true, **kwargs) + cmd = [new_resource.npm_binary, subcmd, '--json'] + # If path is nil, we are in global mode. + cmd << '--global' unless new_resource.path + # Add the rest. + cmd.concat(args) + # If we are in global mode, cwd will be nil so probably just fine. Add + # the directory for the node binary to $PATH for post-install stuffs. + new_path = [::File.dirname(new_resource.javascript), ENV['PATH'].to_s].join(::File::PATH_SEPARATOR) + out = javascript_shell_out!(cmd, cwd: new_resource.path, group: new_resource.group, user: new_resource.user, environment: {'PATH' => new_path}, **kwargs) + if parse_json + # Parse the JSON. + if out.stdout.strip.empty? + {} + else + Chef::JSONCompat.parse(out.stdout) + end + else + out + end + end + + # Find the version of the current npm binary. + # + # @return [Gem::Version] + def npm_version + @npm_version ||= begin + out = javascript_shell_out!([new_resource.npm_binary, 'version']) + # Older NPM doesn't support --json here we get to regex! + # The line we want looks like: + # npm: '2.12.1' + if out.stdout =~ /npm: '([^']+)'/ + Gem::Version.new($1) + else + raise PoiseJavascript::Error.new("Unable to parse NPM version from #{out.stdout.inspect}") + end + end + end + + # Check the NPM version against a requirement. + # + # @param req [String] Requirement string in Gem::Requirement format. + # @return [Boolean] + def npm_version?(req) + Gem::Requirement.new(req).satisfied_by?(npm_version) + end + + end + end + end +end diff --git a/cookbooks/poise-javascript/files/halite_gem/poise_javascript/resources/npm_install.rb b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/resources/npm_install.rb new file mode 100644 index 0000000..6179a53 --- /dev/null +++ b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/resources/npm_install.rb @@ -0,0 +1,98 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/provider' +require 'chef/resource' +require 'poise' + +require 'poise_javascript/javascript_command_mixin' + + +module PoiseJavascript + module Resources + # (see NpmInstall::Resource) + # @since 1.0.0 + module NpmInstall + # A `npm_install` resource to install NPM packages based on a package.json. + # + # @provides npm_install + # @action install + # @example + # npm_install '/opt/myapp' + class Resource < Chef::Resource + include PoiseJavascript::JavascriptCommandMixin + provides(:npm_install) + actions(:install) + + # @!attribute path + # Directory to run `npm install` from. + # @return [String] + attribute(:path, kind_of: String, name_attribute: true) + # @!attribute group + # System group to install the packages. + # @return [String, Integer, nil] + attribute(:group, kind_of: [String, Integer, NilClass]) + # @!attribute production + # Enable production install mode. + # @return [Boolean] + attribute(:production, equal_to: [true, false], default: true) + # @!attribute timeout + # Command execution timeout. + # @return [Integer] + attribute(:timeout, kind_of: Integer, default: 900) + # @!attribute unsafe_perm + # Enable --unsafe-perm. + # @return [Boolean, nil] + attribute(:unsafe_perm, equal_to: [true, false, nil], default: true) + # @!attribute user + # System user to install the packages. + # @return [String, Integer, nil] + attribute(:user, kind_of: [String, Integer, NilClass]) + end + + # The default provider for `npm_install`. + # + # @see Resource + # @provides npm_install + class Provider < Chef::Provider + include Poise + include PoiseJavascript::JavascriptCommandMixin + provides(:npm_install) + + # The `install` action for the `npm_install` resource. + # + # @return [void] + def action_install + cmd = [new_resource.npm_binary, 'install', '--no-audit'] + cmd << '--production' if new_resource.production + # Set --unsafe-perm unless the property is nil. + unless new_resource.unsafe_perm.nil? + cmd << '--unsafe-perm' + cmd << new_resource.unsafe_perm.to_s + end + # Add the directory for the node binary to $PATH for post-install stuffs. + new_path = [::File.dirname(new_resource.javascript), ENV['PATH'].to_s].join(::File::PATH_SEPARATOR) + output = javascript_shell_out!(cmd, cwd: new_resource.path, user: new_resource.user, group: new_resource.group, environment: {'PATH' => new_path}, timeout: new_resource.timeout).stdout + unless output.strip.empty? || output.include?('up to date') + # Any output means it did something for old NPM, "up to date" for newer. + new_resource.updated_by_last_action(true) + end + end + + end + end + end +end diff --git a/cookbooks/poise-javascript/files/halite_gem/poise_javascript/version.rb b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/version.rb new file mode 100644 index 0000000..c60017a --- /dev/null +++ b/cookbooks/poise-javascript/files/halite_gem/poise_javascript/version.rb @@ -0,0 +1,20 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseJavascript + VERSION = '1.2.1.pre' +end diff --git a/cookbooks/poise-javascript/libraries/default.rb b/cookbooks/poise-javascript/libraries/default.rb new file mode 100644 index 0000000..1f32012 --- /dev/null +++ b/cookbooks/poise-javascript/libraries/default.rb @@ -0,0 +1,19 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +raise 'Halite is not compatible with no_lazy_load false, please set no_lazy_load true in your Chef configuration file.' unless Chef::Config[:no_lazy_load] +$LOAD_PATH << File.expand_path('../../files/halite_gem', __FILE__) +require "poise_javascript/cheftie" diff --git a/cookbooks/poise-javascript/metadata.json b/cookbooks/poise-javascript/metadata.json new file mode 100644 index 0000000..ac399e6 --- /dev/null +++ b/cookbooks/poise-javascript/metadata.json @@ -0,0 +1,49 @@ +{ + "name": "poise-javascript", + "description": "A Chef cookbook for managing Node.js and io.js installations.", + "long_description": "# Poise-Javascript Cookbook\n\n[![Build Status](https://img.shields.io/travis/poise/poise-javascript.svg)](https://travis-ci.org/poise/poise-javascript)\n[![Gem Version](https://img.shields.io/gem/v/poise-javascript.svg)](https://rubygems.org/gems/poise-javascript)\n[![Cookbook Version](https://img.shields.io/cookbook/v/poise-javascript.svg)](https://supermarket.chef.io/cookbooks/poise-javascript)\n[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-javascript.svg)](https://codecov.io/github/poise/poise-javascript)\n[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-javascript.svg)](https://gemnasium.com/poise/poise-javascript)\n[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)\n\nA [Chef](https://www.chef.io/) cookbook to provide a unified interface for\ninstalling server-side JavaScript runtimes like Node.js and io.js.\n\n## Quick Start\n\nTo install the latest available version of Node.js 0.12:\n\n```ruby\njavascript_runtime '0.12'\n```\n\n## Supported JavaScript Runtimes\n\nThis cookbook can install Node.js and io.js on Linux and OS X.\n\n## Requirements\n\nChef 12.1 or newer is required.\n\n## Attributes\n\nAttributes are used to configure the default recipe.\n\n* `node['poise-javascript']['install_nodejs']` – Install a Node.js runtime. *(default: true)*\n* `node['poise-javascript']['install_iojs']` – Install an io.js runtime. *(default: false)*\n\n## Recipes\n\n### `default`\n\nThe default recipe installs Node.js or io.js based on the node attributes. It is\nentirely optional and can be ignored in favor of direct use of the\n`javascript_runtime` resource.\n\n## Resources\n\n### `javascript_runtime`\n\nThe `javascript_runtime` resource installs a JavaScript interpreter.\n\n```ruby\njavascript_runtime '0.12'\n```\n\n#### Actions\n\n* `:install` – Install the JavaScript interpreter. *(default)*\n* `:uninstall` – Uninstall the JavaScript interpreter.\n\n#### Properties\n\n* `version` – Version of the runtime to install. If a partial version is given,\n use the latest available version matching that prefix. *(name property)*\n\n#### Provider Options\n\nThe `poise-javascript` library offers an additional way to pass configuration\ninformation to the final provider called \"options\". Options are key/value pairs\nthat are passed down to the `javascript_runtime` provider and can be used to control how it\ninstalls JavaScript. These can be set in the `javascript_runtime`\nresource using the `options` method, in node attributes or via the\n`javascript_runtime_options` resource. The options from all sources are merged\ntogether in to a single hash.\n\nWhen setting options in the resource you can either set them for all providers:\n\n```ruby\njavascript_runtime 'myapp' do\n version '0.10'\n options dev_package: false\nend\n```\n\nor for a single provider:\n\n```ruby\njavascript_runtime 'myapp' do\n version '0.10'\n options :system, dev_package: false\nend\n```\n\nSetting via node attributes is generally how an end-user or application cookbook\nwill set options to customize installations in the library cookbooks they are using.\nYou can set options for all installations or for a single runtime:\n\n```ruby\n# Global, for all installations.\noverride['poise-javascript']['options']['version'] = '0.10'\n# Single installation.\noverride['poise-javascript']['myapp']['version'] = 'iojs'\n```\n\nThe `javascript_runtime_options` resource is also available to set node attributes\nfor a specific installation in a DSL-friendly way:\n\n```ruby\njavascript_runtime_options 'myapp' do\n version 'iojs'\nend\n```\n\nUnlike resource attributes, provider options can be different for each provider.\nNot all providers support the same options so make sure to the check the\ndocumentation for each provider to see what options the use.\n\n### `javascript_runtime_options`\n\nThe `javascript_runtime_options` resource allows setting provider options in a\nDSL-friendly way. See [the Provider Options](#provider-options) section for more\ninformation about provider options overall.\n\n```ruby\njavascript_runtime_options 'myapp' do\n version 'iojs'\nend\n```\n\n#### Actions\n\n* `:run` – Apply the provider options. *(default)*\n\n#### Properties\n\n* `resource` – Name of the `javascript_runtime` resource. *(name property)*\n* `for_provider` – Provider to set options for.\n\nAll other attribute keys will be used as options data.\n\n### `javascript_execute`\n\nThe `javascript_execute` resource executes a JavaScript script using the configured runtime.\n\n```ruby\njavascript_execute 'myapp.js' do\n user 'myuser'\nend\n```\n\nThis uses the built-in `execute` resource and supports all the same properties.\n\n#### Actions\n\n* `:run` – Execute the script. *(default)*\n\n#### Properties\n\n* `command` – Script and arguments to run. Must not include the `node`. *(name attribute)*\n* `javascript` – Name of the `javascript_runtime` resource to use. If not specified, the\n most recently declared `javascript_runtime` will be used. Can also be set to the\n full path to a `node` binary.\n\nFor other properties see the [Chef documentation](https://docs.chef.io/resource_execute.html#attributes).\n\n### `node_package`\n\nThe `node_package` resource installs Node.js packages using\n[NPM](https://www.npmjs.com/).\n\n```ruby\nnode_package 'express' do\n version '4.13.3'\nend\n```\n\nThis uses the built-in `package` resource and supports the same actions and\nproperties. Multi-package installs are supported using the standard syntax.\n\n#### Actions\n\n* `:install` – Install the package. *(default)*\n* `:upgrade` – Upgrade the package.\n* `:remove` – Uninstall the package.\n\nThe `:purge` and `:reconfigure` actions are not supported.\n\n#### Properties\n\n* `group` – System group to install the package.\n* `package_name` – Package or packages to install. *(name property)*\n* `path` – Path to install the package in to. If unset install using `--global`.\n *(default: nil)*\n* `version` – Version or versions to install.\n* `javascript` – Name of the `javascript_runtime` resource to use. If not specified, the\n most recently declared `javascript_runtime` will be used. Can also be set to the\n full path to a `node` binary.\n* `unsafe_perm` – Enable `--unsafe-perm`. *(default: true)*\n* `user` – System user to install the package.\n\nFor other properties see the [Chef documentation](https://docs.chef.io/resource_package.html#attributes).\nThe `response_file`, `response_file_variables`, and `source` properties are not\nsupported.\n\n### `npm_install`\n\nThe `npm_install` resource runs `npm install` for a package.\n\n```ruby\nnpm_install '/opt/myapp'\n```\n\nThe underlying `npm install` command will run on every converge, but notifications\nwill only be triggered if a package is actually installed.\n\n#### Actions\n\n* `:install` – Run `npm install`. *(default)*\n\n#### Properties\n\n* `path` – Path to the package folder containing a `package.json`. *(name attribute)*\n* `group` – System group to install the packages.\n* `javascript` – Name of the `javascript_runtime` resource to use. If not specified, the\n most recently declared `javascript_runtime` will be used. Can also be set to the\n full path to a `node` binary.\n* `production` – Enable production install mode. *(default: true)*\n* `unsafe_perm` – Enable `--unsafe-perm`. *(default: true)*\n* `user` – System user to install the packages.\n\n## Javascript Providers\n\n### Common Options\n\nThese provider options are supported by all providers.\n\n* `version` – Override the runtime version.\n\n### `system`\n\nThe `system` provider installs Node.js using system packages. This is currently\nonly tested on platforms using `apt-get` and `yum` (Debian, Ubuntu, RHEL, CentOS\nAmazon Linux, and Fedora). It may work on other platforms but is untested.\n\n```ruby\njavascript_runtime 'myapp' do\n provider :system\n version '0.10'\nend\n```\n\n#### Options\n\n* `dev_package` – Install the package with the headers and other development\n files. Can be set to a string to select the dev package specifically.\n *(default: true)*\n* `package_name` – Override auto-detection of the package name.\n* `package_upgrade` – Install using action `:upgrade`. *(default: false)*\n* `package_version` – Override auto-detection of the package version.\n\n### `scl`\n\nThe `scl` provider installs Node.js using the [Software Collections](https://www.softwarecollections.org/)\npackages. This is only available on RHEL and CentOS. SCL offers more\nrecent versions of Node.js than the system packages for the most part. If an SCL\npackage exists for the requests version, it will be used in preference to the\n`system` provider.\n\n```ruby\njavascript_runtime 'myapp' do\n provider :scl\n version '0.10'\nend\n```\n\n### `nodejs`\n\nThe `nodejs` provider installs Node.js from the static binaries on nodejs.org.\nSupport is included for Linux and OS X.\n\n```ruby\njavascript_runtime 'myapp' do\n provider :nodejs\n version '0.12'\nend\n```\n\n#### Options\n\n* `path` – Folder to install Node.js to. *(default: /opt/nodejs-)*\n* `static_version` – Specific version number to use for computing the URL and\n path. *(default: automatic from `version`)*\n* `strip_components` – Value to pass to tar --strip-components. *(automatic)*\n* `url` – URL template to download the archive from. *(default: automatic)*\n\n### `iojs`\n\nThe `iojs` provider installs io.js from the static binaries on iojs.org.\nSupport is included for Linux and OS X.\n\n```ruby\njavascript_runtime 'myapp' do\n provider :iojs\n version '3'\nend\n```\n\n#### Options\n\n* `path` – Folder to install io.js to. *(default: /opt/iojs-)*\n* `static_version` – Specific version number to use for computing the URL and\n path. *(default: automatic from `version`)*\n* `strip_components` – Value to pass to tar --strip-components. *(automatic)*\n* `url` – URL template to download the archive from. *(default: automatic)*\n\n## Sponsors\n\nThe Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/).\n\n## License\n\nCopyright 2015-2017, Noah Kantrowitz\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n", + "maintainer": "Noah Kantrowitz", + "maintainer_email": "noah@coderanger.net", + "license": "Apache-2.0", + "platforms": { + "amazon": ">= 0.0.0", + "arch": ">= 0.0.0", + "centos": ">= 0.0.0", + "debian": ">= 0.0.0", + "fedora": ">= 0.0.0", + "gentoo": ">= 0.0.0", + "mac_os_x": ">= 0.0.0", + "opensuse": ">= 0.0.0", + "oracle": ">= 0.0.0", + "raspbian": ">= 0.0.0", + "redhat": ">= 0.0.0", + "slackware": ">= 0.0.0", + "suse": ">= 0.0.0", + "ubuntu": ">= 0.0.0" + }, + "dependencies": { + "poise": "~> 2.0", + "poise-languages": "~> 2.0" + }, + "providing": { + + }, + "recipes": { + + }, + "version": "1.2.1", + "source_url": "https://github.com/poise/poise-javascript", + "issues_url": "https://github.com/poise/poise-javascript/issues", + "privacy": false, + "chef_versions": [ + [ + ">= 12.14" + ] + ], + "ohai_versions": [ + + ], + "gems": [ + + ] +} diff --git a/cookbooks/poise-javascript/metadata.rb b/cookbooks/poise-javascript/metadata.rb new file mode 100644 index 0000000..fb9e66c --- /dev/null +++ b/cookbooks/poise-javascript/metadata.rb @@ -0,0 +1,42 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +name "poise-javascript" +version "1.2.1" +description "A Chef cookbook for managing Node.js and io.js installations." +long_description "# Poise-Javascript Cookbook\n\n[![Build Status](https://img.shields.io/travis/poise/poise-javascript.svg)](https://travis-ci.org/poise/poise-javascript)\n[![Gem Version](https://img.shields.io/gem/v/poise-javascript.svg)](https://rubygems.org/gems/poise-javascript)\n[![Cookbook Version](https://img.shields.io/cookbook/v/poise-javascript.svg)](https://supermarket.chef.io/cookbooks/poise-javascript)\n[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-javascript.svg)](https://codecov.io/github/poise/poise-javascript)\n[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-javascript.svg)](https://gemnasium.com/poise/poise-javascript)\n[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)\n\nA [Chef](https://www.chef.io/) cookbook to provide a unified interface for\ninstalling server-side JavaScript runtimes like Node.js and io.js.\n\n## Quick Start\n\nTo install the latest available version of Node.js 0.12:\n\n```ruby\njavascript_runtime '0.12'\n```\n\n## Supported JavaScript Runtimes\n\nThis cookbook can install Node.js and io.js on Linux and OS X.\n\n## Requirements\n\nChef 12.1 or newer is required.\n\n## Attributes\n\nAttributes are used to configure the default recipe.\n\n* `node['poise-javascript']['install_nodejs']` – Install a Node.js runtime. *(default: true)*\n* `node['poise-javascript']['install_iojs']` – Install an io.js runtime. *(default: false)*\n\n## Recipes\n\n### `default`\n\nThe default recipe installs Node.js or io.js based on the node attributes. It is\nentirely optional and can be ignored in favor of direct use of the\n`javascript_runtime` resource.\n\n## Resources\n\n### `javascript_runtime`\n\nThe `javascript_runtime` resource installs a JavaScript interpreter.\n\n```ruby\njavascript_runtime '0.12'\n```\n\n#### Actions\n\n* `:install` – Install the JavaScript interpreter. *(default)*\n* `:uninstall` – Uninstall the JavaScript interpreter.\n\n#### Properties\n\n* `version` – Version of the runtime to install. If a partial version is given,\n use the latest available version matching that prefix. *(name property)*\n\n#### Provider Options\n\nThe `poise-javascript` library offers an additional way to pass configuration\ninformation to the final provider called \"options\". Options are key/value pairs\nthat are passed down to the `javascript_runtime` provider and can be used to control how it\ninstalls JavaScript. These can be set in the `javascript_runtime`\nresource using the `options` method, in node attributes or via the\n`javascript_runtime_options` resource. The options from all sources are merged\ntogether in to a single hash.\n\nWhen setting options in the resource you can either set them for all providers:\n\n```ruby\njavascript_runtime 'myapp' do\n version '0.10'\n options dev_package: false\nend\n```\n\nor for a single provider:\n\n```ruby\njavascript_runtime 'myapp' do\n version '0.10'\n options :system, dev_package: false\nend\n```\n\nSetting via node attributes is generally how an end-user or application cookbook\nwill set options to customize installations in the library cookbooks they are using.\nYou can set options for all installations or for a single runtime:\n\n```ruby\n# Global, for all installations.\noverride['poise-javascript']['options']['version'] = '0.10'\n# Single installation.\noverride['poise-javascript']['myapp']['version'] = 'iojs'\n```\n\nThe `javascript_runtime_options` resource is also available to set node attributes\nfor a specific installation in a DSL-friendly way:\n\n```ruby\njavascript_runtime_options 'myapp' do\n version 'iojs'\nend\n```\n\nUnlike resource attributes, provider options can be different for each provider.\nNot all providers support the same options so make sure to the check the\ndocumentation for each provider to see what options the use.\n\n### `javascript_runtime_options`\n\nThe `javascript_runtime_options` resource allows setting provider options in a\nDSL-friendly way. See [the Provider Options](#provider-options) section for more\ninformation about provider options overall.\n\n```ruby\njavascript_runtime_options 'myapp' do\n version 'iojs'\nend\n```\n\n#### Actions\n\n* `:run` – Apply the provider options. *(default)*\n\n#### Properties\n\n* `resource` – Name of the `javascript_runtime` resource. *(name property)*\n* `for_provider` – Provider to set options for.\n\nAll other attribute keys will be used as options data.\n\n### `javascript_execute`\n\nThe `javascript_execute` resource executes a JavaScript script using the configured runtime.\n\n```ruby\njavascript_execute 'myapp.js' do\n user 'myuser'\nend\n```\n\nThis uses the built-in `execute` resource and supports all the same properties.\n\n#### Actions\n\n* `:run` – Execute the script. *(default)*\n\n#### Properties\n\n* `command` – Script and arguments to run. Must not include the `node`. *(name attribute)*\n* `javascript` – Name of the `javascript_runtime` resource to use. If not specified, the\n most recently declared `javascript_runtime` will be used. Can also be set to the\n full path to a `node` binary.\n\nFor other properties see the [Chef documentation](https://docs.chef.io/resource_execute.html#attributes).\n\n### `node_package`\n\nThe `node_package` resource installs Node.js packages using\n[NPM](https://www.npmjs.com/).\n\n```ruby\nnode_package 'express' do\n version '4.13.3'\nend\n```\n\nThis uses the built-in `package` resource and supports the same actions and\nproperties. Multi-package installs are supported using the standard syntax.\n\n#### Actions\n\n* `:install` – Install the package. *(default)*\n* `:upgrade` – Upgrade the package.\n* `:remove` – Uninstall the package.\n\nThe `:purge` and `:reconfigure` actions are not supported.\n\n#### Properties\n\n* `group` – System group to install the package.\n* `package_name` – Package or packages to install. *(name property)*\n* `path` – Path to install the package in to. If unset install using `--global`.\n *(default: nil)*\n* `version` – Version or versions to install.\n* `javascript` – Name of the `javascript_runtime` resource to use. If not specified, the\n most recently declared `javascript_runtime` will be used. Can also be set to the\n full path to a `node` binary.\n* `unsafe_perm` – Enable `--unsafe-perm`. *(default: true)*\n* `user` – System user to install the package.\n\nFor other properties see the [Chef documentation](https://docs.chef.io/resource_package.html#attributes).\nThe `response_file`, `response_file_variables`, and `source` properties are not\nsupported.\n\n### `npm_install`\n\nThe `npm_install` resource runs `npm install` for a package.\n\n```ruby\nnpm_install '/opt/myapp'\n```\n\nThe underlying `npm install` command will run on every converge, but notifications\nwill only be triggered if a package is actually installed.\n\n#### Actions\n\n* `:install` – Run `npm install`. *(default)*\n\n#### Properties\n\n* `path` – Path to the package folder containing a `package.json`. *(name attribute)*\n* `group` – System group to install the packages.\n* `javascript` – Name of the `javascript_runtime` resource to use. If not specified, the\n most recently declared `javascript_runtime` will be used. Can also be set to the\n full path to a `node` binary.\n* `production` – Enable production install mode. *(default: true)*\n* `unsafe_perm` – Enable `--unsafe-perm`. *(default: true)*\n* `user` – System user to install the packages.\n\n## Javascript Providers\n\n### Common Options\n\nThese provider options are supported by all providers.\n\n* `version` – Override the runtime version.\n\n### `system`\n\nThe `system` provider installs Node.js using system packages. This is currently\nonly tested on platforms using `apt-get` and `yum` (Debian, Ubuntu, RHEL, CentOS\nAmazon Linux, and Fedora). It may work on other platforms but is untested.\n\n```ruby\njavascript_runtime 'myapp' do\n provider :system\n version '0.10'\nend\n```\n\n#### Options\n\n* `dev_package` – Install the package with the headers and other development\n files. Can be set to a string to select the dev package specifically.\n *(default: true)*\n* `package_name` – Override auto-detection of the package name.\n* `package_upgrade` – Install using action `:upgrade`. *(default: false)*\n* `package_version` – Override auto-detection of the package version.\n\n### `scl`\n\nThe `scl` provider installs Node.js using the [Software Collections](https://www.softwarecollections.org/)\npackages. This is only available on RHEL and CentOS. SCL offers more\nrecent versions of Node.js than the system packages for the most part. If an SCL\npackage exists for the requests version, it will be used in preference to the\n`system` provider.\n\n```ruby\njavascript_runtime 'myapp' do\n provider :scl\n version '0.10'\nend\n```\n\n### `nodejs`\n\nThe `nodejs` provider installs Node.js from the static binaries on nodejs.org.\nSupport is included for Linux and OS X.\n\n```ruby\njavascript_runtime 'myapp' do\n provider :nodejs\n version '0.12'\nend\n```\n\n#### Options\n\n* `path` – Folder to install Node.js to. *(default: /opt/nodejs-)*\n* `static_version` – Specific version number to use for computing the URL and\n path. *(default: automatic from `version`)*\n* `strip_components` – Value to pass to tar --strip-components. *(automatic)*\n* `url` – URL template to download the archive from. *(default: automatic)*\n\n### `iojs`\n\nThe `iojs` provider installs io.js from the static binaries on iojs.org.\nSupport is included for Linux and OS X.\n\n```ruby\njavascript_runtime 'myapp' do\n provider :iojs\n version '3'\nend\n```\n\n#### Options\n\n* `path` – Folder to install io.js to. *(default: /opt/iojs-)*\n* `static_version` – Specific version number to use for computing the URL and\n path. *(default: automatic from `version`)*\n* `strip_components` – Value to pass to tar --strip-components. *(automatic)*\n* `url` – URL template to download the archive from. *(default: automatic)*\n\n## Sponsors\n\nThe Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/).\n\n## License\n\nCopyright 2015-2017, Noah Kantrowitz\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n" +maintainer "Noah Kantrowitz" +maintainer_email "noah@coderanger.net" +source_url "https://github.com/poise/poise-javascript" if defined?(source_url) +issues_url "https://github.com/poise/poise-javascript/issues" if defined?(issues_url) +license "Apache-2.0" +depends "poise", "~> 2.0" +depends "poise-languages", "~> 2.0" +chef_version ">= 12.14" if defined?(chef_version) +supports "amazon" +supports "arch" +supports "centos" +supports "debian" +supports "fedora" +supports "gentoo" +supports "mac_os_x" +supports "opensuse" +supports "oracle" +supports "raspbian" +supports "redhat" +supports "slackware" +supports "suse" +supports "ubuntu" diff --git a/cookbooks/poise-javascript/recipes/default.rb b/cookbooks/poise-javascript/recipes/default.rb new file mode 100644 index 0000000..0c9ab14 --- /dev/null +++ b/cookbooks/poise-javascript/recipes/default.rb @@ -0,0 +1,19 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +# Default runtimes, last one will be the default. +javascript_runtime 'iojs' if node['poise-javascript']['install_iojs'] +javascript_runtime 'nodejs' if node['poise-javascript']['install_nodejs'] diff --git a/cookbooks/poise-languages/CHANGELOG.md b/cookbooks/poise-languages/CHANGELOG.md new file mode 100644 index 0000000..3ebbbe0 --- /dev/null +++ b/cookbooks/poise-languages/CHANGELOG.md @@ -0,0 +1,89 @@ +# Changelog + +## v2.1.2 + +* Drop support for Chef that uses Ruby 2.1 (<= 12.13). +* Fix handling of RPM epoch prefixes in the system package resource. + +## v2.1.1 + +* Fix the SCL repository enable command for RHEL. +* Internal refactoring of the system package installer. + +## v2.1.0 + +* Allow customizing properties on the system package install resource via a block + +## v2.0.5 + +* Fixes to work with the latest Chef (again). + +## v2.0.4 + +* Fixes to work with the latest Chef. + +## v2.0.3 + +* Correct the subscription repository name used for SCLs on RedHat. + +## v2.0.2 + +* Don't try to use SCL providers on Amazon Linux. + +## v2.0.1 + +* Don't error on `Chef::Decorator::Lazy` proxy objects for `candidate_version`. +* Retry system and SCL package installs because transient network failures. + +## v2.0.0 + +* Backwards-incompatible change to SCL management to comply with their new repo + packages and layout. Uses `centos-release-scl-rh` repo package or the + `rhel-variant-rhscl` RedHat subscription. + +## v1.4.0 + +* Use `poise-archive` to unpack static binary archives. This should work better + on AIX and Solaris, as well as making it easier to add more archive formats in + the future. + +## v1.3.3 + +* [#3](https://github.com/poise/poise-languages/pull/3) Fix `static` binary + installation on AIX and Solaris. +* Only run the candidate version check for `system` installs when we aren't + passing in package_version. + +## v1.3.2 + +* Handle static archive unpacking correctly when a single download is shared + between two paths. + +## v1.3.1 + +* Fix system package installs on OS X. + +## v1.3.0 + +* `%{machine_label}` is available in URL template for static download. +* Automatically retry `remote_file` downloads to handle transient HTTP failures. +* All `*_shell_out` language command helpers use `poise_shell_out` to set `$HOME` + and other environment variables by default. + +## v1.2.0 + +* Support for installing development headers with SCL providers. +* Add `PoiseLanguages::Utils.shelljoin` for encoding command arrays with some + bash metadata characters allowed. +* [#1](https://github.com/poise/poise-languages/pull/1) Fix typo in gemspec. + +## v1.1.0 + +* Add helpers for installing from static archives. +* Improve auto-selection rules for system and SCL providers. +* Support SCL packages that depend on other SCL packages. +* Support Ruby 2.0 again. + +## v1.0.0 + +* Initial release! diff --git a/cookbooks/poise-languages/README.md b/cookbooks/poise-languages/README.md new file mode 100644 index 0000000..30bc6da --- /dev/null +++ b/cookbooks/poise-languages/README.md @@ -0,0 +1,27 @@ +# Poise-Languages Cookbook + +[![Build Status](https://img.shields.io/travis/poise/poise-languages.svg)](https://travis-ci.org/poise/poise-languages) +[![Gem Version](https://img.shields.io/gem/v/poise-languages.svg)](https://rubygems.org/gems/poise-languages) +[![Cookbook Version](https://img.shields.io/cookbook/v/poise-languages.svg)](https://supermarket.chef.io/cookbooks/poise-languages) +[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-languages.svg)](https://codecov.io/github/poise/poise-languages) +[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-languages.svg)](https://gemnasium.com/poise/poise-languages) +[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) + +Shared support code for Poise's language cookbooks like poise-ruby and +poise-python. + +## License + +Copyright 2015-2017, Noah Kantrowitz + +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/cookbooks/poise-languages/files/halite_gem/poise_languages.rb b/cookbooks/poise-languages/files/halite_gem/poise_languages.rb new file mode 100644 index 0000000..9952907 --- /dev/null +++ b/cookbooks/poise-languages/files/halite_gem/poise_languages.rb @@ -0,0 +1,26 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseLanguages + autoload :Command, 'poise_languages/command' + autoload :Error, 'poise_languages/error' + autoload :Scl, 'poise_languages/scl' + autoload :Static, 'poise_languages/static' + autoload :System, 'poise_languages/system' + autoload :Utils, 'poise_languages/utils' + autoload :VERSION, 'poise_languages/version' +end diff --git a/cookbooks/poise-languages/files/halite_gem/poise_languages/command.rb b/cookbooks/poise-languages/files/halite_gem/poise_languages/command.rb new file mode 100644 index 0000000..bd46621 --- /dev/null +++ b/cookbooks/poise-languages/files/halite_gem/poise_languages/command.rb @@ -0,0 +1,25 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseLanguages + # A namespace for language-command-related stuff. + # + # @since 1.0.0 + module Command + autoload :Mixin, 'poise_languages/command/mixin' + end +end diff --git a/cookbooks/poise-languages/files/halite_gem/poise_languages/command/mixin.rb b/cookbooks/poise-languages/files/halite_gem/poise_languages/command/mixin.rb new file mode 100644 index 0000000..15e2c7d --- /dev/null +++ b/cookbooks/poise-languages/files/halite_gem/poise_languages/command/mixin.rb @@ -0,0 +1,241 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'shellwords' + +require 'poise' + +require 'poise_languages/error' +require 'poise_languages/utils' + + +module PoiseLanguages + module Command + # A mixin for resources and providers that run language commands. + # + # @since 1.0.0 + module Mixin + include Poise::Utils::ResourceProviderMixin + + # A mixin for resources that run language commands. Also available as a + # parameterized mixin via `include PoiseLanguages::Command::Mixin::Resource(name)`. + # + # @example + # class MyLangThing + # include PoiseLanguages::Command::Mixin::Resource(:mylang) + # # ... + # end + module Resource + include Poise::Resource + poise_subresource(true) + + private + + # Implementation of the $name accessor. + # + # @api private + # @param name [Symbol] Language name. + # @param runtime [Symbol] Language runtime resource name. + # @param val [String, Chef::Resource, Poise::NOT_PASSED, nil] Accessor value. + # @return [String] + def language_command_runtime(name, runtime, default_binary, val=Poise::NOT_PASSED) + unless val == Poise::NOT_PASSED + path_arg = parent_arg = nil + # Figure out which property we are setting. + if val.is_a?(String) + # Check if it is a runtime resource. + begin + parent_arg = run_context.resource_collection.find("#{runtime}[#{val}]") + rescue Chef::Exceptions::ResourceNotFound + # Check if something looks like a path, defined as containing + # either / or \. While a single word could be a path, I think the + # UX win of better error messages should take priority. + might_be_path = val =~ %r{/|\\} + if might_be_path + Chef::Log.debug("[#{self}] #{runtime}[#{val}] not found, treating it as a path") + path_arg = val + else + # Surface the error up to the user. + raise + end + end + else + parent_arg = val + end + # Set both attributes. + send(:"parent_#{name}", parent_arg) + set_or_return(name, path_arg, kind_of: [String, NilClass]) + else + # Getter behavior. Using the ivar directly is kind of gross but oh well. + instance_variable_get(:"@#{name}") || default_language_command_runtime(name, default_binary) + end + end + + # Compute the path to the default runtime binary. + # + # @api private + # @param name [Symbol] Language name. + # @return [String] + def default_language_command_runtime(name, default_binary) + parent = send(:"parent_#{name}") + if parent + parent.send(:"#{name}_binary") + else + PoiseLanguages::Utils.which(default_binary || name.to_s) + end + end + + # Inherit language parent from another resource. + # + # @api private + # @param name [Symbol] Language name. + # @param resource [Chef::Resource] Resource to inherit from. + # @return [void] + def language_command_runtime_from_parent(name, resource) + parent = resource.send(:"parent_#{name}") + if parent + send(:"parent_#{name}", parent) + else + path = resource.send(name) + if path + send(name, path) + end + end + end + + module ClassMethods + # Configure this module or class for a specific language. + # + # @param name [Symbol] Language name. + # @param runtime [Symbol] Language runtime resource name. + # @param timeout [Boolean] Enable the timeout attribute. + # @param default_binary [String] Name of the default language binary. + # @return [void] + def language_command_mixin(name, runtime: :"#{name}_runtime", timeout: true, default_binary: nil) + # Create the parent attribute. + parent_attribute(name, type: runtime, optional: true) + + # Timeout attribute for the shell_out wrappers in the provider. + attribute(:timeout, kind_of: Integer, default: 900) if timeout + + # Create the main accessor for the parent/path. + define_method(name) do |val=Poise::NOT_PASSED| + language_command_runtime(name, runtime, default_binary, val) + end + + # Create the method to inherit settings from another resource. + define_method(:"#{name}_from_parent") do |resource| + language_command_runtime_from_parent(name, resource) + end + private :"#{name}_from_parent" + end + + def language_command_default_binary(val=Poise::NOT_PASSED) + @language_command_default_binary = val if val != Poise::NOT_PASSED + @language_command_default_binary + end + + # @api private + def included(klass) + super + klass.extend(ClassMethods) + end + end + + extend ClassMethods + Poise::Utils.parameterized_module(self) {|*args| language_command_mixin(*args) } + end # /module Resource + + # A mixin for providers that run language commands. + module Provider + include Poise::Utils::ShellOut + + private + + # Run a command using the configured language via `shell_out`. + # + # @api private + # @param name [Symbol] Language name. + # @param command_args [Array] Arguments to `shell_out`. + # @return [Mixlib::ShellOut] + def language_command_shell_out(name, *command_args, **options) + # Inject our environment variables if needed. + options[:environment] ||= {} + parent = new_resource.send(:"parent_#{name}") + if parent + options[:environment].update(parent.send(:"#{name}_environment")) + end + # Inject other options. + options[:timeout] ||= new_resource.timeout + # Find the actual binary to use. Raise an exception if we see false + # which happens if no parent resource is found, no explicit default + # binary was given, and which() fails to find a thing. + binary = new_resource.send(name) + raise Error.new("Unable to find a #{name} binary for command: #{command_args.is_a?(Array) ? Shellwords.shelljoin(command_args) : command_args}") unless binary + command = if command_args.length == 1 && command_args.first.is_a?(String) + # String mode, sigh. + "#{Shellwords.escape(binary)} #{command_args.first}" + else + # Array mode. Handle both ('one', 'two') and (['one', 'two']). + [binary] + command_args.flatten + end + Chef::Log.debug("[#{new_resource}] Running #{name} command: #{command.is_a?(Array) ? Shellwords.shelljoin(command) : command}") + # Run the command + poise_shell_out(command, options) + end + + # Run a command using the configured language via `shell_out!`. + # + # @api private + # @param name [Symbol] Language name. + # @param command_args [Array] Arguments to `shell_out!`. + # @return [Mixlib::ShellOut] + def language_command_shell_out!(name, *command_args) + send(:"#{name}_shell_out", *command_args).tap(&:error!) + end + + module ClassMethods + # Configure this module or class for a specific language. + # + # @param name [Symbol] Language name. + # @return [void] + def language_command_mixin(name) + define_method(:"#{name}_shell_out") do |*command_args| + language_command_shell_out(name, *command_args) + end + private :"#{name}_shell_out" + + define_method(:"#{name}_shell_out!") do |*command_args| + language_command_shell_out!(name, *command_args) + end + private :"#{name}_shell_out!" + end + + # @api private + def included(klass) + super + klass.extend(ClassMethods) + end + end + + extend ClassMethods + Poise::Utils.parameterized_module(self) {|*args| language_command_mixin(*args) } + end # /module Provider + + Poise::Utils.parameterized_module(self) {|*args| language_command_mixin(*args) } + end # /module Mixin + end +end diff --git a/cookbooks/poise-languages/files/halite_gem/poise_languages/error.rb b/cookbooks/poise-languages/files/halite_gem/poise_languages/error.rb new file mode 100644 index 0000000..ddfadee --- /dev/null +++ b/cookbooks/poise-languages/files/halite_gem/poise_languages/error.rb @@ -0,0 +1,21 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseLanguages + class Error < ::Exception + end +end diff --git a/cookbooks/poise-languages/files/halite_gem/poise_languages/scl.rb b/cookbooks/poise-languages/files/halite_gem/poise_languages/scl.rb new file mode 100644 index 0000000..b0b5771 --- /dev/null +++ b/cookbooks/poise-languages/files/halite_gem/poise_languages/scl.rb @@ -0,0 +1,24 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseLanguages + module Scl + autoload :Mixin, 'poise_languages/scl/mixin' + autoload :Resource, 'poise_languages/scl/resource' + autoload :Provider, 'poise_languages/scl/resource' + end +end diff --git a/cookbooks/poise-languages/files/halite_gem/poise_languages/scl/mixin.rb b/cookbooks/poise-languages/files/halite_gem/poise_languages/scl/mixin.rb new file mode 100644 index 0000000..63f6cd0 --- /dev/null +++ b/cookbooks/poise-languages/files/halite_gem/poise_languages/scl/mixin.rb @@ -0,0 +1,134 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_languages/scl/resource' + + +module PoiseLanguages + module Scl + module Mixin + private + + def install_scl_package + pkg = scl_package + poise_languages_scl options[:package_name] || pkg[:name] do + action :upgrade if options[:package_upgrade] + dev_package options[:dev_package] == true ? pkg[:devel_name] : options[:dev_package] + parent new_resource + version options[:package_version] + end + end + + def uninstall_scl_package + install_scl_package.tap do |r| + r.action(:uninstall) + end + end + + def scl_package + @scl_package ||= self.class.find_scl_package(node, options['version']).tap do |p| + raise PoiseLanguages::Error.new("No SCL repoistory package for #{node['platform']} #{node['platform_version']}") unless p + end + end + + def scl_folder + ::File.join('', 'opt', 'rh', scl_package[:name]) + end + + def scl_environment + parse_enable_file(::File.join(scl_folder, 'enable')) + end + + # Parse an SCL enable file to extract the environment variables set in it. + # + # @param path [String] Path to the enable file. + # @return [Hash] + def parse_enable_file(path, env={}) + # Doesn't exist yet, so running Python will fail anyway. Just make sure + # it fails in the expected way. + return {} unless File.exist?(path) + # Yes, this is a bash parser in regex. Feel free to be mad at me. + IO.readlines(path).inject(env) do |memo, line| + if match = line.match(/^export (\w+)=(.*)$/) + memo[match[1]] = match[2].gsub(/\$(?:\{(\w+)(:\+:\$\{\w+\})?\}|(\w+))/) do + key = $1 || $3 + value = (memo[key] || ENV[key]).to_s + value = ":#{value}" if $2 && !value.empty? + value + end + elsif match = line.match(/^\. scl_source enable (\w+)$/) + # Parse another file. + memo.update(parse_enable_file(::File.join('', 'opt', 'rh', match[1], 'enable'), memo)) + end + memo + end + end + + module ClassMethods + def provides_auto?(node, resource) + # They don't build 32-bit versions for these and only for RHEL/CentOS. + # TODO: What do I do about Fedora and/or Amazon? + return false unless node['kernel']['machine'] == 'x86_64' && node.platform?('redhat', 'centos') + version = inversion_options(node, resource)['version'] + !!find_scl_package(node, version) + end + + # Set some default inversion provider options. Package name can't get + # a default value here because that would complicate the handling of + # {system_package_candidates}. + # + # @api private + def default_inversion_options(node, resource) + super.merge({ + # Install dev headers? + dev_package: true, + # Manual overrides for package name and/or version. + package_name: nil, + package_version: nil, + # Set to true to use action :upgrade on system packages. + package_upgrade: false, + }) + end + + def find_scl_package(node, version) + platform_version = ::Gem::Version.create(node['platform_version']) + # Filter out anything that doesn't match this EL version. + candidate_packages = scl_packages.select {|p| p[:platform_version].satisfied_by?(platform_version) } + # Find something with a prefix match on the Python version. + candidate_packages.find {|p| p[:version].start_with?(version) } + end + + private + + def scl_packages + @scl_packages ||= [] + end + + def scl_package(version, name, devel_name=nil, platform_version='>= 6.0') + scl_packages << {version: version, name: name, devel_name: devel_name, platform_version: ::Gem::Requirement.create(platform_version)} + end + + def included(klass) + super + klass.extend(ClassMethods) + end + end + + extend ClassMethods + + end + end +end diff --git a/cookbooks/poise-languages/files/halite_gem/poise_languages/scl/resource.rb b/cookbooks/poise-languages/files/halite_gem/poise_languages/scl/resource.rb new file mode 100644 index 0000000..9ecf14a --- /dev/null +++ b/cookbooks/poise-languages/files/halite_gem/poise_languages/scl/resource.rb @@ -0,0 +1,159 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/resource' +require 'chef/provider' +require 'poise' + + +module PoiseLanguages + module Scl + # A `poise_language_scl` resource to manage installing a language from + # SCL packages. This is an internal implementation detail of + # poise-languages. + # + # @api private + # @since 1.0 + # @provides poise_languages_scl + # @action install + # @action uninstall + class Resource < Chef::Resource + include Poise + provides(:poise_languages_scl) + actions(:install, :upgrade, :uninstall) + + # @!attribute package_name + # Name of the SCL package for the language. + # @return [String] + attribute(:package_name, kind_of: String, name_attribute: true) + # @!attribute dev_package + # Name of the -devel package with headers and whatnot. + # @return [String, nil] + attribute(:dev_package, kind_of: [String, NilClass]) + # @!attribute version + # Version of the SCL package(s) to install. If unset, follows the same + # semantics as the core `package` resource. + # @return [String, nil] + attribute(:version, kind_of: [String, NilClass]) + # @!attribute parent + # Resource for the language runtime. Used only for messages. + # @return [Chef::Resource] + attribute(:parent, kind_of: Chef::Resource, required: true) + end + + # The default provider for `poise_languages_scl`. + # + # @api private + # @since 1.0 + # @see Resource + # @provides poise_languages_scl + class Provider < Chef::Provider + include Poise + provides(:poise_languages_scl) + + # The `install` action for the `poise_languages_scl` resource. + # + # @return [void] + def action_install + notifying_block do + install_scl_repo + flush_yum_cache + install_scl_package(:install) + install_scl_devel_package(:install) if new_resource.dev_package + end + end + + # The `upgrade` action for the `poise_languages_scl` resource. + # + # @return [void] + def action_upgrade + notifying_block do + install_scl_repo + flush_yum_cache + install_scl_package(:upgrade) + install_scl_devel_package(:upgrade) if new_resource.dev_package + end + end + + # The `uninstall` action for the `poise_languages_scl` resource. + # + # @return [void] + def action_uninstall + notifying_block do + uninstall_scl_devel_package if new_resource.dev_package + uninstall_scl_package + end + end + + private + + def install_scl_repo + if node.platform?('redhat') + # Set up the real RHSCL subscription. + # NOTE: THIS IS NOT TESTED BECAUSE REDHAT DOESN'T OFFER ANY WAY TO DO + # AUTOMATED TESTING. IF YOU USE REDHAT AND THIS BREAKS, PLEASE LET ME + # KNOW BY FILING A GITHUB ISSUE AT http://github.com/poise/poise-languages/issues/new. + repo_name = "rhel-server-rhscl-#{node['platform_version'][0]}-rpms" + execute "subscription-manager repos --enable #{repo_name}" do + not_if { shell_out!('subscription-manager repos --list-enabled').stdout.include?(repo_name) } + end + else + package 'centos-release-scl-rh' do + # Using upgrade here because changes very very rare and always + # important when they happen. If this breaks your prod infra, I'm + # sorry :-( + action :upgrade + retries 5 + end + end + end + + def flush_yum_cache + ruby_block 'flush_yum_cache' do + block do + # Equivalent to flush_cache after: true + Chef::Provider::Package::Yum::YumCache.instance.reload + end + end + end + + def install_scl_package(action) + package new_resource.package_name do + action action + retries 5 + version new_resource.version + end + end + + def install_scl_devel_package(action) + package new_resource.dev_package do + action action + retries 5 + version new_resource.version + end + end + + def uninstall_scl_package + install_scl_package(:remove) + end + + def uninstall_scl_devel_package + install_scl_devel_package(:remove) + end + + end + end +end diff --git a/cookbooks/poise-languages/files/halite_gem/poise_languages/static.rb b/cookbooks/poise-languages/files/halite_gem/poise_languages/static.rb new file mode 100644 index 0000000..efdbe10 --- /dev/null +++ b/cookbooks/poise-languages/files/halite_gem/poise_languages/static.rb @@ -0,0 +1,34 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'poise/utils' + + +module PoiseLanguages + # Helpers for installing languages from static archives. + # + # @since 1.1.0 + module Static + autoload :Mixin, 'poise_languages/static/mixin' + autoload :Resource, 'poise_languages/static/resource' + autoload :Provider, 'poise_languages/static/resource' + + Poise::Utils.parameterized_module(self) do |opts| + require 'poise_languages/static/mixin' + include PoiseLanguages::Static::Mixin(opts) + end + end +end diff --git a/cookbooks/poise-languages/files/halite_gem/poise_languages/static/mixin.rb b/cookbooks/poise-languages/files/halite_gem/poise_languages/static/mixin.rb new file mode 100644 index 0000000..d189331 --- /dev/null +++ b/cookbooks/poise-languages/files/halite_gem/poise_languages/static/mixin.rb @@ -0,0 +1,144 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_languages/static/resource' + + +module PoiseLanguages + module Static + # Mixin for language providers to install from static archives. + # + # @since 1.1.0 + module Mixin + private + + def install_static + url = static_url + poise_languages_static static_folder do + source url + strip_components options['strip_components'] + end + end + + def uninstall_static + install_static.tap do |r| + r.action(:uninstall) + end + end + + def static_folder + options['path'] || ::File.join('', 'opt', "#{self.class.static_name}-#{options['static_version']}") + end + + def static_url + options['url'] % static_url_variables + end + + def static_url_variables + { + version: options['static_version'], + kernel: node['kernel']['name'].downcase, + machine: node['kernel']['machine'], + machine_label: self.class.static_machine_label_wrapper(node, new_resource), + } + end + + module ClassMethods + attr_accessor :static_name + attr_accessor :static_versions + attr_accessor :static_machines + attr_accessor :static_url + attr_accessor :static_strip_components + attr_accessor :static_retries + + def provides_auto?(node, resource) + # Check that the version starts with our project name and the machine + # we are on is supported. + resource.version.to_s =~ /^#{static_name}(-|$)/ && static_machines.include?(static_machine_label_wrapper(node, resource)) + end + + # Set some default inversion provider options. Package name can't get + # a default value here because that would complicate the handling of + # {system_package_candidates}. + # + # @api private + def default_inversion_options(node, resource) + super.merge({ + # Path to install the package. Defaults to /opt/name-version. + path: nil, + # Number of times to retry failed downloads. + retries: static_retries, + # Full version number for use in interpolation. + static_version: static_version(node, resource), + # Value to pass to tar --strip-components. + strip_components: static_strip_components, + # URL template to download from. + url: static_url, + }) + end + + def static_options(name: nil, versions: [], machines: %w{linux-i686 linux-x86_64}, url: nil, strip_components: 1, retries: 5) + raise PoiseLanguages::Error.new("Static archive URL is required, on #{self}") unless url + self.static_name = name || provides.to_s + self.static_versions = versions + self.static_machines = Set.new(machines) + self.static_url = url + self.static_strip_components = strip_components + self.static_retries = retries + end + + def static_version(node, resource) + raw_version = resource.version.to_s.gsub(/^#{static_name}(-|$)/, '') + if static_versions.include?(raw_version) + raw_version + else + # Prefix match or just use the given version number if not found. + # This allow mild future proofing in some cases. + static_versions.find {|v| v.start_with?(raw_version) } || raw_version + end + end + + def static_machine_label(node, _resource=nil) + "#{node['kernel']['name'].downcase}-#{node['kernel']['machine']}" + end + + # Wrapper for {#static_machine_label} because I need to add an argument. + # This preserves backwards compat. + # + # @api private + def static_machine_label_wrapper(node, resource) + args = [node] + arity = method(:static_machine_label).arity + args << resource if arity > 1 || arity < 0 + static_machine_label(*args) + end + + def included(klass) + super + klass.extend ClassMethods + end + + end + + extend ClassMethods + + Poise::Utils.parameterized_module(self) do |opts| + static_options(opts) + end + + end + end +end diff --git a/cookbooks/poise-languages/files/halite_gem/poise_languages/static/resource.rb b/cookbooks/poise-languages/files/halite_gem/poise_languages/static/resource.rb new file mode 100644 index 0000000..150eb44 --- /dev/null +++ b/cookbooks/poise-languages/files/halite_gem/poise_languages/static/resource.rb @@ -0,0 +1,139 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/resource' +require 'chef/provider' +require 'poise' + + +module PoiseLanguages + module Static + # A `poise_languages_static` resource to manage installing a language from + # static binary archives. This is an internal implementation detail of + # poise-languages. + # + # @api private + # @since 1.1.0 + # @provides poise_languages_static + # @action install + # @action uninstall + class Resource < Chef::Resource + include Poise + provides(:poise_languages_static) + actions(:install, :uninstall) + + # @!attribute path + # Directory to install to. + # @return [String] + attribute(:path, kind_of: String, name_attribute: true) + # @!attribute download_retries + # Number of times to retry failed downloads. Defaults to 5. + # @return [Integer] + attribute(:download_retries, kind_of: Integer, default: 5) + # @!attribute source + # URL to download from. + # @return [String] + attribute(:source, kind_of: String, required: true) + # @!attribute strip_components + # Value to pass to tar --strip-components. + # @return [String, Integer, nil] + attribute(:strip_components, kind_of: [String, Integer, NilClass], default: 1) + + def cache_path + @cache_path ||= ::File.join(Chef::Config[:file_cache_path], source.split(/\//).last) + end + end + + # The default provider for `poise_languages_static`. + # + # @api private + # @since 1.0 + # @see Resource + # @provides poise_languages_static + class Provider < Chef::Provider + include Poise + provides(:poise_languages_static) + + # The `install` action for the `poise_languages_static` resource. + # + # @return [void] + def action_install + notifying_block do + download_archive + create_directory + # Unpack is handled as a notification from download_archive. + end + end + + # The `uninstall` action for the `poise_languages_static` resource. + # + # @return [void] + def action_uninstall + notifying_block do + delete_archive + delete_directory + end + end + + private + + def create_directory + unpack_resource = unpack_archive + directory new_resource.path do + user 0 + group 0 + mode '755' + notifies :unpack, unpack_resource, :immediately + end + end + + def download_archive + unpack_resource = unpack_archive + remote_file new_resource.cache_path do + source new_resource.source + owner 0 + group 0 + mode '644' + notifies :unpack, unpack_resource, :immediately if ::File.exist?(new_resource.path) + retries new_resource.download_retries + end + end + + def unpack_archive + @unpack_archive ||= poise_archive new_resource.cache_path do + # Run via notification from #download_archive and #create_directory. + action :nothing + destination new_resource.path + strip_components new_resource.strip_components + end + end + + def delete_archive + file new_resource.cache_path do + action :delete + end + end + + def delete_directory + directory new_resource.path do + action :delete + recursive true + end + end + + end + end +end diff --git a/cookbooks/poise-languages/files/halite_gem/poise_languages/system.rb b/cookbooks/poise-languages/files/halite_gem/poise_languages/system.rb new file mode 100644 index 0000000..5ece43c --- /dev/null +++ b/cookbooks/poise-languages/files/halite_gem/poise_languages/system.rb @@ -0,0 +1,24 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseLanguages + module System + autoload :Mixin, 'poise_languages/system/mixin' + autoload :Resource, 'poise_languages/system/resource' + autoload :Provider, 'poise_languages/system/resource' + end +end diff --git a/cookbooks/poise-languages/files/halite_gem/poise_languages/system/mixin.rb b/cookbooks/poise-languages/files/halite_gem/poise_languages/system/mixin.rb new file mode 100644 index 0000000..8b1764e --- /dev/null +++ b/cookbooks/poise-languages/files/halite_gem/poise_languages/system/mixin.rb @@ -0,0 +1,170 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_languages/system/resource' + + +module PoiseLanguages + module System + module Mixin + + private + + # Install a language using system packages. + # + # @api public + # @return [PoiseLanguages::System::Resource] + def install_system_packages(&block) + dev_package_overrides = system_dev_package_overrides + poise_languages_system system_package_name do + # Otherwise use the default install action. + action(:upgrade) if options['package_upgrade'] + parent new_resource + # Don't pass true because we want the default computed behavior for that. + dev_package options['dev_package'] unless options['dev_package'] == true + dev_package_overrides dev_package_overrides + package_version options['package_version'] if options['package_version'] + version options['version'] + instance_exec(&block) if block + end + end + + # Uninstall a language using system packages. + # + # @api public + # @return [PoiseLanguages::System::Resource] + def uninstall_system_packages(&block) + install_system_packages.tap do |r| + r.action(:uninstall) + r.instance_exec(&block) if block + end + end + + # Compute all possible package names for a given language version. Must be + # implemented by mixin users. Versions are expressed as prefixes so '' + # matches all versions, '2' matches 2.x. + # + # @abstract + # @api public + # @param version [String] Language version prefix. + # @return [Array] + def system_package_candidates(version) + raise NotImplementedError + end + + # Compute the default package name for the base package for this language. + # + # @api public + # @return [String] + def system_package_name + # If we have an override, just use that. + return options['package_name'] if options['package_name'] + # Look up all packages for this language on this platform. + system_packages = self.class.packages && node.value_for_platform(self.class.packages) + if !system_packages && self.class.default_package + Chef::Log.debug("[#{new_resource}] No known packages for #{node['platform']} #{node['platform_version']}, defaulting to '#{self.class.default_package}'.") if self.class.packages + system_packages = Array(self.class.default_package) + end + + # Find the first value on system_package_candidates that is in system_packages. + system_package_candidates(options['version'].to_s).each do |name| + return name if system_packages.include?(name) + end + # No valid candidate. Sad trombone. + raise PoiseLanguages::Error.new("Unable to find a candidate package for version #{options['version'].to_s.inspect}. Please set package_name provider option for #{new_resource}.") + end + + # A hash mapping package names to their override dev package name. + # + # @api public + # @return [Hash] + def system_dev_package_overrides + {} + end + + module ClassMethods + # Install this as a default provider if nothing else matched. Might not + # work, but worth a try at least for unknown platforms. Windows is a + # whole different story, and OS X might work sometimes so at least try. + # + # @api private + def provides_auto?(node, resource) + !node.platform_family?('windows') + end + + # Set some default inversion provider options. Package name can't get + # a default value here because that would complicate the handling of + # {system_package_candidates}. + # + # @api private + def default_inversion_options(node, resource) + super.merge({ + # Install dev headers? + dev_package: true, + # Manual overrides for package name and/or version. + package_name: nil, + package_version: nil, + # Set to true to use action :upgrade on system packages. + package_upgrade: false, + }) + end + + # @overload packages() + # Return a hash formatted for value_for_platform returning an Array + # of package names. + # @return [Hash] + # @overload packages(default_package, packages) + # Define what system packages are available for this language on each + # platform. + # @param default_package [String] Default package name for platforms + # not otherwise defined. + # @param [Hash] Hash formatted for value_for_platform returning an + # Array of package names. + # @return [Hash] + def packages(default_package=nil, packages=nil) + self.default_package(default_package) if default_package + if packages + @packages = packages + end + @packages + end + + # @overload default_package() + # Return the default package name for platforms not otherwise defined. + # @return [String] + # @overload default_package(name) + # Set the default package name for platforms not defined in {packages}. + # @param name [String] Package name. + # @return [String] + def default_package(name=nil) + if name + @default_package = name + end + @default_package + end + + # @api private + def included(klass) + super + klass.extend(ClassMethods) + end + end + + extend ClassMethods + + end + end +end diff --git a/cookbooks/poise-languages/files/halite_gem/poise_languages/system/resource.rb b/cookbooks/poise-languages/files/halite_gem/poise_languages/system/resource.rb new file mode 100644 index 0000000..90d18bd --- /dev/null +++ b/cookbooks/poise-languages/files/halite_gem/poise_languages/system/resource.rb @@ -0,0 +1,254 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/resource' +require 'chef/provider' +require 'poise' + + +module PoiseLanguages + module System + # A `poise_language_system` resource to manage installing a language from + # system packages. This is an internal implementation detail of + # poise-languages. + # + # @api private + # @since 1.0 + # @provides poise_languages_system + # @action install + # @action upgrade + # @action uninstall + class Resource < Chef::Resource + include Poise + provides(:poise_languages_system) + actions(:install, :upgrade, :uninstall) + + # @!attribute package_name + # Name of the main package for the language. + # @return [String] + attribute(:package_name, kind_of: String, name_attribute: true) + # @!attribute dev_package + # Name of the development headers package, or false to disable + # installing headers. By default computed from {package_name}. + # @return [String, false] + attribute(:dev_package, kind_of: [String, FalseClass], default: lazy { default_dev_package }) + # @!attribute dev_package_overrides + # A hash of override names for dev packages that don't match the normal + # naming scheme. + # @return [Hash] + attribute(:dev_package_overrides, kind_of: Hash, default: lazy { {} }) + # @!attribute package_version + # Version of the package(s) to install. This is distinct from {version}, + # and is the specific version package version, not the language version. + # By default this is unset meaning the latest version will be used. + # @return [String, nil] + attribute(:package_version, kind_of: [String, NilClass]) + # @!attribute parent + # Resource for the language runtime. Used only for messages. + # @return [Chef::Resource] + attribute(:parent, kind_of: Chef::Resource, required: true) + # @!attributes version + # Language version prefix. This prefix determines which version of the + # language to install, following prefix matching rules. + # @return [String] + attribute(:version, kind_of: String, default: '') + + # Compute the default package name for the development headers. + # + # @return [String] + def default_dev_package + # Check for an override. + return dev_package_overrides[package_name] if dev_package_overrides.include?(package_name) + suffix = node.value_for_platform_family(debian: '-dev', rhel: '-devel', fedora: '-devel') + # Platforms like Arch and Gentoo don't need this anyway. I've got no + # clue how Amazon Linux does this. + if suffix + package_name + suffix + else + nil + end + end + end + + # The default provider for `poise_languages_system`. + # + # @api private + # @since 1.0 + # @see Resource + # @provides poise_languages_system + class Provider < Chef::Provider + include Poise + provides(:poise_languages_system) + + # The `install` action for the `poise_languages_system` resource. + # + # @return [void] + def action_install + notifying_block do + install_packages + run_action_hack + end + end + + # The `upgrade` action for the `poise_languages_system` resource. + # + # @return [void] + def action_upgrade + notifying_block do + upgrade_packages + run_action_hack + end + end + + # The `uninstall` action for the `poise_languages_system` resource. + # + # @return [void] + def action_uninstall + notifying_block do + uninstall_packages + end + end + + private + + # Install the needed language packages. + # + # @api private + # @return [Array] + def install_packages + packages = {new_resource.package_name => new_resource.package_version} + # If we are supposed to install the dev package, grab it using the same + # version as the main package. + if new_resource.dev_package + packages[new_resource.dev_package] = new_resource.package_version + end + Chef::Log.debug("[#{new_resource.parent}] Building package resource using #{packages.inspect}.") + + # Check for multi-package support. + package_resource_class = Chef::Resource.resource_for_node(:package, node) + package_provider_class = package_resource_class.new('multipackage_check', run_context).provider_for_action(:install) + package_resources = if package_provider_class.respond_to?(:use_multipackage_api?) && package_provider_class.use_multipackage_api? + package packages.keys do + version packages.values + end + else + # Fallback for non-multipackage. + packages.map do |pkg_name, pkg_version| + package pkg_name do + version pkg_version + end + end + end + + # Apply some settings to all of the resources. + Array(package_resources).each do |res| + res.retries(5) + res.define_singleton_method(:apply_action_hack?) { true } + end + end + + # Upgrade the needed language packages. + # + # @api private + # @return [Array] + def upgrade_packages + install_packages.each do |res| + res.action(:upgrade) + end + end + + # Uninstall the needed language packages. + # + # @api private + # @return [Array] + def uninstall_packages + install_packages.each do |res| + res.action(node.platform_family?('debian') ? :purge : :remove) + end + end + + # Run the requested action for all package resources. This exists because + # we inject our version check in to the provider directly and I want to + # only run the provider action once for performance. It is otherwise + # mostly a stripped down version of Chef::Resource#run_action. + # + # @param action [Symbol] Action to run on all package resources. + # @return [void] + def run_action_hack + # If new_resource.package_version is set, skip this madness. + return if new_resource.package_version + + # Process every resource in the current collection, which is bounded + # by notifying_block. + run_context.resource_collection.each do |resource| + # Only apply to things we tagged above. + next unless resource.respond_to?(:apply_action_hack?) && resource.apply_action_hack? + + Array(resource.action).each do |action| + # Reset it so we have a clean baseline. + resource.updated_by_last_action(false) + # Grab the provider. + provider = resource.provider_for_action(action) + provider.action = action + # Inject our check for the candidate version. This will actually + # get run during run_action below. + patch_load_current_resource!(provider, new_resource.version) + # Run our action. + Chef::Log.debug("[#{new_resource.parent}] Running #{provider} with #{action}") + provider.run_action(action) + # Check updated flag. + new_resource.updated_by_last_action(true) if resource.updated_by_last_action? + end + + # Make sure the resource doesn't run again when notifying_block ends. + resource.action(:nothing) + end + end + + # Hack a provider object to run our verification code. + # + # @param provider [Chef::Provider] Provider object to patch. + # @param version [String] Language version prefix to check for. + # @return [void] + def patch_load_current_resource!(provider, version) + # Create a closure module and inject it. + provider.extend Module.new { + # Patch load_current_resource to run our verification logic after + # the normal code. + define_method(:load_current_resource) do + super().tap do |_| + each_package do |package_name, new_version, current_version, candidate_version| + # In Chef 12.14+, candidate_version is a Chef::Decorator::Lazy object + # so we need the nil? check to see if the object being proxied is + # nil (i.e. there is no version). The `\d+:` is for RPM epoch prefixes. + unless candidate_version && (!candidate_version.nil?) && (!candidate_version.empty?) && candidate_version =~ /^(\d+:)?#{Regexp.escape(version)}/ + # Don't display a wonky error message if there is no candidate. + candidate_label = if candidate_version && (!candidate_version.nil?) && (!candidate_version.empty?) + candidate_version + else + candidate_version.inspect + end + raise PoiseLanguages::Error.new("Package #{package_name} would install #{candidate_label}, which does not match #{version.empty? ? version.inspect : version}. Please set the package_name or package_version provider options.") + end + end + end + end + } + end + + end + end +end diff --git a/cookbooks/poise-languages/files/halite_gem/poise_languages/utils.rb b/cookbooks/poise-languages/files/halite_gem/poise_languages/utils.rb new file mode 100644 index 0000000..84ff73d --- /dev/null +++ b/cookbooks/poise-languages/files/halite_gem/poise_languages/utils.rb @@ -0,0 +1,68 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'shellwords' + +require 'poise_languages/utils/which' + + +module PoiseLanguages + module Utils + include Which + extend self + + # Default whitelist for {#shelljoin}. + SHELLJOIN_WHITELIST = [/^2?[><]/] + + # An improved version of Shellwords.shelljoin that doesn't escape a few + # things. + # + # @param cmd [Array] Command array to join. + # @param whitelist [Array] Array of patterns to whitelist. + # @return [String] + def shelljoin(cmd, whitelist: SHELLJOIN_WHITELIST) + cmd.map do |str| + if whitelist.any? {|pat| str =~ pat } + str + else + Shellwords.shellescape(str) + end + end.join(' ') + end + + # Convert the executable in a string or array command to an absolute path. + # + # @param cmd [String, Array] Command to fix up. + # @param path [String, nil] Replacement $PATH for executable lookup. + # @return [String, Array] + def absolute_command(cmd, path: nil) + was_array = cmd.is_a?(Array) + cmd = if was_array + cmd.dup + else + Shellwords.split(cmd) + end + # Don't try to touch anything if the first value looks like a flag or a path. + if cmd.first && !cmd.first.start_with?('-') && !cmd.first.include?(::File::SEPARATOR) + # If which returns false, just leave it I guess. + cmd[0] = which(cmd.first, path: path) || cmd.first + end + cmd = shelljoin(cmd) unless was_array + cmd + end + + end +end diff --git a/cookbooks/poise-languages/files/halite_gem/poise_languages/utils/which.rb b/cookbooks/poise-languages/files/halite_gem/poise_languages/utils/which.rb new file mode 100644 index 0000000..8661c57 --- /dev/null +++ b/cookbooks/poise-languages/files/halite_gem/poise_languages/utils/which.rb @@ -0,0 +1,51 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseLanguages + module Utils + # Replacement module for Chef::Mixin::Which with a slight improvement. + # + # @since 1.0.0 + # @see Which#which + module Which + extend self + + # A replacement for Chef::Mixin::Which#which that allows using something + # other than an environment variable if needed. + # + # @param cmd [String] Executable to search for. + # @param extra_path [Array] Extra directories to always search. + # @param path [String, nil] Replacement $PATH value. + # @return [String, false] + def which(cmd, extra_path: %w{/bin /usr/bin /sbin /usr/sbin}, path: nil) + # If it was already absolute, just return that. + return cmd if cmd =~ /^(\/|([a-z]:)?\\)/i + # Allow passing something other than the real env var. + path ||= ENV['PATH'] + # Based on Chef::Mixin::Which#which + # Copyright 2010-2017, Chef Softare, Inc. + paths = path.split(File::PATH_SEPARATOR) + extra_path + paths.each do |candidate_path| + filename = ::File.join(candidate_path, cmd) + return filename if ::File.executable?(filename) + end + false + end + + end + end +end diff --git a/cookbooks/poise-languages/files/halite_gem/poise_languages/version.rb b/cookbooks/poise-languages/files/halite_gem/poise_languages/version.rb new file mode 100644 index 0000000..61bcdb7 --- /dev/null +++ b/cookbooks/poise-languages/files/halite_gem/poise_languages/version.rb @@ -0,0 +1,20 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseLanguages + VERSION = '2.1.2' +end diff --git a/cookbooks/poise-languages/libraries/default.rb b/cookbooks/poise-languages/libraries/default.rb new file mode 100644 index 0000000..8b2a908 --- /dev/null +++ b/cookbooks/poise-languages/libraries/default.rb @@ -0,0 +1,18 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +raise 'Halite is not compatible with no_lazy_load false, please set no_lazy_load true in your Chef configuration file.' unless Chef::Config[:no_lazy_load] +$LOAD_PATH << File.expand_path('../../files/halite_gem', __FILE__) diff --git a/cookbooks/poise-languages/metadata.json b/cookbooks/poise-languages/metadata.json new file mode 100644 index 0000000..9cf3ac6 --- /dev/null +++ b/cookbooks/poise-languages/metadata.json @@ -0,0 +1 @@ +{"name":"poise-languages","version":"2.1.2","description":"A Chef cookbook to help writing language cookbooks.","long_description":"# Poise-Languages Cookbook\n\n[![Build Status](https://img.shields.io/travis/poise/poise-languages.svg)](https://travis-ci.org/poise/poise-languages)\n[![Gem Version](https://img.shields.io/gem/v/poise-languages.svg)](https://rubygems.org/gems/poise-languages)\n[![Cookbook Version](https://img.shields.io/cookbook/v/poise-languages.svg)](https://supermarket.chef.io/cookbooks/poise-languages)\n[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-languages.svg)](https://codecov.io/github/poise/poise-languages)\n[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-languages.svg)](https://gemnasium.com/poise/poise-languages)\n[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)\n\nShared support code for Poise's language cookbooks like poise-ruby and\npoise-python.\n\n## License\n\nCopyright 2015-2017, Noah Kantrowitz\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","maintainer":"Noah Kantrowitz","maintainer_email":"noah@coderanger.net","license":"Apache-2.0","platforms":{"aix":">= 0.0.0","amazon":">= 0.0.0","arch":">= 0.0.0","centos":">= 0.0.0","chefspec":">= 0.0.0","debian":">= 0.0.0","dragonfly4":">= 0.0.0","fedora":">= 0.0.0","freebsd":">= 0.0.0","gentoo":">= 0.0.0","ios_xr":">= 0.0.0","mac_os_x":">= 0.0.0","nexus":">= 0.0.0","omnios":">= 0.0.0","openbsd":">= 0.0.0","opensuse":">= 0.0.0","oracle":">= 0.0.0","raspbian":">= 0.0.0","redhat":">= 0.0.0","slackware":">= 0.0.0","smartos":">= 0.0.0","solaris2":">= 0.0.0","suse":">= 0.0.0","ubuntu":">= 0.0.0","windows":">= 0.0.0"},"dependencies":{"poise":"~> 2.5","poise-archive":"~> 1.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/poise/poise-languages","issues_url":"https://github.com/poise/poise-languages/issues","chef_version":[["< 15",">= 12.14"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/poise-ruby-build/CHANGELOG.md b/cookbooks/poise-ruby-build/CHANGELOG.md new file mode 100644 index 0000000..e4fbf98 --- /dev/null +++ b/cookbooks/poise-ruby-build/CHANGELOG.md @@ -0,0 +1,22 @@ +# Poise-Ruby-Build Changelog + +## v1.1.0 + +* Chef 13 support. +* Switch to `poise-git` and `poise-build-essential` rather than the traditional + cookbooks to ensure support for older Chef and clean up lingering bugs. + +## v1.0.2 + +* Fix a typo that prevented uninstalling `ruby_build` runtimes. +* Ensure bzip2 is installed as some minimal Linux images do not include it. + +## v1.0.1 + +* Install bundler in the same way as other `ruby_runtime` providers. +* New integration test harness. + +## v1.0.0 + +* Initial release! + diff --git a/cookbooks/poise-ruby-build/README.md b/cookbooks/poise-ruby-build/README.md new file mode 100644 index 0000000..05d13a1 --- /dev/null +++ b/cookbooks/poise-ruby-build/README.md @@ -0,0 +1,53 @@ +# Poise-Ruby-Build Cookbook + +[![Build Status](https://img.shields.io/travis/poise/poise-ruby-build.svg)](https://travis-ci.org/poise/poise-ruby-build) +[![Gem Version](https://img.shields.io/gem/v/poise-ruby-build.svg)](https://rubygems.org/gems/poise-ruby-build) +[![Cookbook Version](https://img.shields.io/cookbook/v/poise-ruby-build.svg)](https://supermarket.chef.io/cookbooks/poise-ruby-build) +[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-ruby-build.svg)](https://codecov.io/github/poise/poise-ruby-build) +[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-ruby-build.svg)](https://gemnasium.com/poise/poise-ruby-build) +[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) + +A [ruby-build](https://github.com/sstephenson/ruby-build) provider for the +[poise-ruby cookbook](https://github.com/poise/poise-ruby). + +## Provider + +The `ruby_build` provider uses [ruby-build](https://github.com/sstephenson/ruby-build) +to compile and install Ruby. + +```ruby +ruby_runtime 'myapp' do + provider :ruby_build + version '2.1' +end +``` + +### Options + +* `install_doc` – Install documentation with Ruby. *(default: false)* +* `install_repo` – Git URI to clone to install ruby-build. *(default: https://github.com/sstephenson/ruby-build.git)* +* `install_rev` – Git revision to clone to install ruby-build. *(default: master)* +* `prefix` – Base path for install ruby-build and rubies. *(default: /opt/ruby_build)* +* `version` – Override the Ruby version. + +## Sponsors + +Development sponsored by [Bloomberg](http://www.bloomberg.com/company/technology/). + +The Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/). + +## License + +Copyright 2015-2017, Noah Kantrowitz + +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/cookbooks/poise-ruby-build/attributes/default.rb b/cookbooks/poise-ruby-build/attributes/default.rb new file mode 100644 index 0000000..1bf8521 --- /dev/null +++ b/cookbooks/poise-ruby-build/attributes/default.rb @@ -0,0 +1,17 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +default['poise-ruby']['provider'] = 'ruby_build' diff --git a/cookbooks/poise-ruby-build/files/halite_gem/poise_ruby/ruby_build.rb b/cookbooks/poise-ruby-build/files/halite_gem/poise_ruby/ruby_build.rb new file mode 100644 index 0000000..342d461 --- /dev/null +++ b/cookbooks/poise-ruby-build/files/halite_gem/poise_ruby/ruby_build.rb @@ -0,0 +1,26 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseRuby + # A plugin for poise-ruby to compile Ruby using ruby-build. + # + # @since 1.0.0 + module RubyBuild + autoload :Provider, 'poise_ruby/ruby_build/provider' + autoload :VERSION, 'poise_ruby/ruby_build/version' + end +end diff --git a/cookbooks/poise-ruby-build/files/halite_gem/poise_ruby/ruby_build/cheftie.rb b/cookbooks/poise-ruby-build/files/halite_gem/poise_ruby/ruby_build/cheftie.rb new file mode 100644 index 0000000..32fd6ca --- /dev/null +++ b/cookbooks/poise-ruby-build/files/halite_gem/poise_ruby/ruby_build/cheftie.rb @@ -0,0 +1,17 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_ruby/ruby_build/provider' diff --git a/cookbooks/poise-ruby-build/files/halite_gem/poise_ruby/ruby_build/provider.rb b/cookbooks/poise-ruby-build/files/halite_gem/poise_ruby/ruby_build/provider.rb new file mode 100644 index 0000000..9cf45d6 --- /dev/null +++ b/cookbooks/poise-ruby-build/files/halite_gem/poise_ruby/ruby_build/provider.rb @@ -0,0 +1,219 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/mixin/shell_out' + +require 'poise_ruby/ruby_providers/base' + + +module PoiseRuby + module RubyBuild + # Inversion provider for `ruby_runtime` to install via ruby-build. + # + # @since 1.0.0 + # @provides ruby_build + class Provider < PoiseRuby::RubyProviders::Base + include Chef::Mixin::ShellOut + provides(:ruby_build) + + # Add default options for ruby-build. + # + # @param node [Chef::Node] Node to load from. + # @param resource [Chef::Resource] Resource to load from. + # @return [Hash] + def self.default_inversion_options(node, resource) + super.merge({ + install_doc: false, + install_repo: 'https://github.com/sstephenson/ruby-build.git', + install_rev: 'master', + prefix: '/opt/ruby_build', + }) + end + + # Path to the compiled Ruby binary. + # + # @return [String] + def ruby_binary + ::File.join(options['prefix'], 'builds', new_resource.name, 'bin', 'ruby') + end + + # Find the full definition name to use with ruby-build. This is based on + # prefix matching from the `ruby-build --definitions` output. Only + # public because sigh scoping. + # + # @!visibility private + # @return [String] + def ruby_definition + @ruby_definition ||= begin + cmd = shell_out!([::File.join(options['prefix'], 'install', options['install_rev'], 'bin', 'ruby-build'), '--definitions']) + version_prefix = options['version'] + # Default for '', look for MRI 2.x. + version_prefix = '2' if version_prefix == '' + # Find the last line that starts with the target version. + cmd.stdout.split(/\n/).reverse.find {|line| line.start_with?(version_prefix) } || options['version'] + end + end + + private + + # Path to the version record file. Should contain the actual version of + # Ruby installed in this folder. + # + # @return [String] + def version_file + ::File.join(options['prefix'], 'builds', new_resource.name, 'VERSION') + end + + # Installs ruby-build and then uses that to install Ruby. + # + # @return [void] + def install_ruby + # We assume that if the version_file exists, ruby-build is already + # installed. Calling #ruby_definition will shell out to ruby-build. + if ::File.exists?(version_file) && IO.read(version_file) == ruby_definition + # All set, bail out. + return + end + + converge_by("Installing Ruby #{options['version'].empty? ? new_resource.name : options['version']} via ruby-build") do + notifying_block do + create_prefix_directory + create_install_directory + create_builds_directory + install_ruby_build + install_dependencies + # Possible failed install or a version change. Wipe the existing build. + # If we weren't going to rebuild, we would have bailed out already. + uninstall_ruby + end + # Second converge has ruby-build installed so using #ruby_definition + # is safe. + notifying_block do + build_ruby + create_version_file + end + end + end + + # Create the base prefix directory. + # + # @return [Chef::Resource::Directory] + def create_prefix_directory + directory options['prefix'] do + owner 'root' + group 'root' + mode '755' + end + end + + # Create the directory to hold ruby-build installations. + # + # @return [Chef::Resource::Directory] + def create_install_directory + directory ::File.join(options['prefix'], 'install') do + owner 'root' + group 'root' + mode '755' + end + end + + # Create the directory to hold compiled rubies. + # + # @return [Chef::Resource::Directory] + def create_builds_directory + directory ::File.join(options['prefix'], 'builds') do + owner 'root' + group 'root' + mode '755' + end + end + + # Clone ruby-build from GitHub or a similar git server. Will also install + # git via the `git` cookbook unless `no_dependencies` is set. + # + # @return [Chef::Resource::Git] + def install_ruby_build + poise_git ::File.join(options['prefix'], 'install', options['install_rev']) do + repository options['install_repo'] + revision options['install_rev'] + user 'root' + end + end + + # Install dependency packages needed to compile Ruby. A no-op if + # `no_dependencies` is set. + # + # @return [Chef::Resource::Package] + def install_dependencies + return if options['no_dependencies'] + poise_build_essential 'build_essential' + unless options['version'].start_with?('jruby') + pkgs = node.value_for_platform_family( + debian: %w{libreadline6-dev zlib1g-dev libssl-dev libyaml-dev libsqlite3-dev libxml2-dev libxslt1-dev}, + rhel: %w{tar bzip2 readline-devel zlib-devel libffi-devel openssl-devel libxml2-devel libxslt-devel}, + suse: %w{zlib-devel libffi-devel sqlite3-devel libxml2-devel libxslt-devel}, + ) + package pkgs if pkgs + end + end + + + # Compile Ruby using ruby-build. + # + # @return [Chef::Resource::Execute] + def build_ruby + # Figure out the argument to disable docs + disable_docs = if options['install_doc'] + nil + elsif options['version'].start_with?('rbx') + nil # Doesn't support? + elsif options['version'].start_with?('ree') + '--no-dev-docs' + else + '--disable-install-doc' + end + + execute 'ruby-build install' do + command [::File.join(options['prefix'], 'install', options['install_rev'], 'bin', 'ruby-build'), ruby_definition, ::File.join(options['prefix'], 'builds', new_resource.name)] + user 'root' + environment 'RUBY_CONFIGURE_OPTS' => disable_docs if disable_docs + end + end + + # Write out the concrete version to the VERSION file. + # + # @return [Chef::Resource::File] + def create_version_file + file version_file do + owner 'root' + group 'root' + mode '644' + content ruby_definition + end + end + + # Delete the compiled Ruby, but leave ruby-build installed as it may be + # shared by other resources. + # + # @return [Chef::Resource::Directory] + def uninstall_ruby + directory ::File.join(options['prefix'], 'builds', new_resource.name) do + action :delete + end + end + end + end +end diff --git a/cookbooks/poise-ruby-build/files/halite_gem/poise_ruby/ruby_build/version.rb b/cookbooks/poise-ruby-build/files/halite_gem/poise_ruby/ruby_build/version.rb new file mode 100644 index 0000000..2b51c09 --- /dev/null +++ b/cookbooks/poise-ruby-build/files/halite_gem/poise_ruby/ruby_build/version.rb @@ -0,0 +1,22 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseRuby + module RubyBuild + VERSION = '1.1.0' + end +end diff --git a/cookbooks/poise-ruby-build/libraries/default.rb b/cookbooks/poise-ruby-build/libraries/default.rb new file mode 100644 index 0000000..2788808 --- /dev/null +++ b/cookbooks/poise-ruby-build/libraries/default.rb @@ -0,0 +1,19 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +raise 'Halite is not compatible with no_lazy_load false, please set no_lazy_load true in your Chef configuration file.' unless Chef::Config[:no_lazy_load] +$LOAD_PATH << File.expand_path('../../files/halite_gem', __FILE__) +require "poise_ruby/ruby_build/cheftie" diff --git a/cookbooks/poise-ruby-build/metadata.json b/cookbooks/poise-ruby-build/metadata.json new file mode 100644 index 0000000..49d9350 --- /dev/null +++ b/cookbooks/poise-ruby-build/metadata.json @@ -0,0 +1 @@ +{"name":"poise-ruby-build","version":"1.1.0","description":"A Chef cookbook for managing Ruby installations using ruby-build.","long_description":"# Poise-Ruby-Build Cookbook\n\n[![Build Status](https://img.shields.io/travis/poise/poise-ruby-build.svg)](https://travis-ci.org/poise/poise-ruby-build)\n[![Gem Version](https://img.shields.io/gem/v/poise-ruby-build.svg)](https://rubygems.org/gems/poise-ruby-build)\n[![Cookbook Version](https://img.shields.io/cookbook/v/poise-ruby-build.svg)](https://supermarket.chef.io/cookbooks/poise-ruby-build)\n[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-ruby-build.svg)](https://codecov.io/github/poise/poise-ruby-build)\n[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-ruby-build.svg)](https://gemnasium.com/poise/poise-ruby-build)\n[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)\n\nA [ruby-build](https://github.com/sstephenson/ruby-build) provider for the\n[poise-ruby cookbook](https://github.com/poise/poise-ruby).\n\n## Provider\n\nThe `ruby_build` provider uses [ruby-build](https://github.com/sstephenson/ruby-build)\nto compile and install Ruby.\n\n```ruby\nruby_runtime 'myapp' do\n provider :ruby_build\n version '2.1'\nend\n```\n\n### Options\n\n* `install_doc` – Install documentation with Ruby. *(default: false)*\n* `install_repo` – Git URI to clone to install ruby-build. *(default: https://github.com/sstephenson/ruby-build.git)*\n* `install_rev` – Git revision to clone to install ruby-build. *(default: master)*\n* `prefix` – Base path for install ruby-build and rubies. *(default: /opt/ruby_build)*\n* `version` – Override the Ruby version.\n\n## Sponsors\n\nDevelopment sponsored by [Bloomberg](http://www.bloomberg.com/company/technology/).\n\nThe Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/).\n\n## License\n\nCopyright 2015-2017, Noah Kantrowitz\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","maintainer":"Noah Kantrowitz","maintainer_email":"noah@coderanger.net","license":"Apache 2.0","platforms":{},"dependencies":{"poise":"~> 2.0","poise-build-essential":"~> 1.0","poise-git":"~> 1.0","poise-ruby":"~> 2.1"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/poise/poise-ruby-build","issues_url":"https://github.com/poise/poise-ruby-build/issues","chef_version":[["< 14",">= 12.1"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/poise-ruby/CHANGELOG.md b/cookbooks/poise-ruby/CHANGELOG.md new file mode 100644 index 0000000..22d7ccb --- /dev/null +++ b/cookbooks/poise-ruby/CHANGELOG.md @@ -0,0 +1,33 @@ +# Changelog + +## v2.4.0 + +* Add support for the rh-ruby24 SCL package. + +## v2.3.0 + +* Chef 13 support. + +## v2.2.0 + +* Add support for Ubuntu 16.04 system packages. +* Support new SCL structure and packages. + +## v2.1.1 + +* Create ChefSpec matchers for the `ruby_gem` resource. + +## v2.1.0 + +* Fix version field for default Ruby runtime. +* Add a `:dummy` provider for `ruby_runtime` for unit testing or complex overrides. +* Improved handling for `bundle exec` in `ruby_execute`. +* New integration test harness. + +## v2.0.0 + +* Initial release (again)! + +## v1.0.0 + +* Pre-history, we do not speak of these times. diff --git a/cookbooks/poise-ruby/README.md b/cookbooks/poise-ruby/README.md new file mode 100644 index 0000000..764aa20 --- /dev/null +++ b/cookbooks/poise-ruby/README.md @@ -0,0 +1,305 @@ +# Poise-Ruby Cookbook + +[![Build Status](https://img.shields.io/travis/poise/poise-ruby.svg)](https://travis-ci.org/poise/poise-ruby) +[![Gem Version](https://img.shields.io/gem/v/poise-ruby.svg)](https://rubygems.org/gems/poise-ruby) +[![Cookbook Version](https://img.shields.io/cookbook/v/poise-ruby.svg)](https://supermarket.chef.io/cookbooks/poise-ruby) +[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-ruby.svg)](https://codecov.io/github/poise/poise-ruby) +[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-ruby.svg)](https://gemnasium.com/poise/poise-ruby) +[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) + +A [Chef](https://www.chef.io/) cookbook to provide a unified interface for +installing Ruby and running things with it. This README covers the 2.x version +of the cookbook, the 1.x version is very different and no longer supported. + +## Quick Start + +To install the latest available version of Ruby 2.x and then use it to install +some gems: + +```ruby +ruby_runtime '2' + +ruby_gem 'rake' + +bundle_install '/path/to/Gemfile' do + without 'development' + deployment true +end +``` + +## Requirements + +Chef 12.1 or newer is required. + +## Attributes + +Attributes are used to configure the default recipe. + +* `node['poise-ruby']['install_ruby']` – Install a Ruby runtime. *(default: true)* +* `node['poise-ruby']['install_chef_ruby']` – Create a `ruby_runtime` using + the `:chef` provider. Doesn't actually install anything. *(default: true)* + +## Recipes + +### `default` + +The default recipe installs Ruby based on the node attributes. It is entirely +optional and can be ignored in favor of direct use of the `ruby_runtime` +resource. + +## Resources + +### `ruby_runtime` + +The `ruby_runtime` resource installs a Ruby interpreter. + +```ruby +ruby_runtime 'any' do + version '' +end +``` + +#### Actions + +* `:install` – Install the Ruby interpreter. *(default)* +* `:uninstall` – Uninstall the Ruby interpreter. + +#### Properties + +* `version` – Version of Ruby to install. If a partial version is given, use the + latest available version matching that prefix. *(name properties)* + +#### Provider Options + +The `poise-ruby` library offers an additional way to pass configuration +information to the final provider called "options". Options are key/value pairs +that are passed down to the ruby_runtime provider and can be used to control how it +installs Ruby. These can be set in the `ruby_runtime` +resource using the `options` method, in node attributes or via the +`ruby_runtime_options` resource. The options from all sources are merged +together in to a single hash. + +When setting options in the resource you can either set them for all providers: + +```ruby +ruby_runtime 'myapp' do + version '2.1' + options dev_package: false +end +``` + +or for a single provider: + +```ruby +ruby_runtime 'myapp' do + version '2.1' + options :system, dev_package: false +end +``` + +Setting via node attributes is generally how an end-user or application cookbook +will set options to customize installations in the library cookbooks they are using. +You can set options for all installations or for a single runtime: + +```ruby +# Global, for all installations. +override['poise-ruby']['options']['dev_package'] = false +# Single installation. +override['poise-ruby']['myapp']['version'] = '2.2' +``` + +The `ruby_runtime_options` resource is also available to set node attributes +for a specific installation in a DSL-friendly way: + +```ruby +ruby_runtime_options 'myapp' do + version '2.2' +end +``` + +Unlike resource attributes, provider options can be different for each provider. +Not all providers support the same options so make sure to the check the +documentation for each provider to see what options the use. + +### `ruby_runtime_options` + +The `ruby_runtime_options` resource allows setting provider options in a +DSL-friendly way. See [the Provider Options](#provider-options) section for more +information about provider options overall. + +```ruby +ruby_runtime_options 'myapp' do + version '2.2' +end +``` + +#### Actions + +* `:run` – Apply the provider options. *(default)* + +#### Properties + +* `resource` – Name of the `ruby_runtime` resource. *(name property)* +* `for_provider` – Provider to set options for. + +All other property keys will be used as options data. + +### `ruby_execute` + +The `ruby_execute` resource executes a Ruby script using the configured runtime. + +```ruby +ruby_execute 'myapp.rb' do + user 'myuser' +end +``` + +This uses the built-in `execute` resource and supports all the same properties. + +#### Actions + +* `:run` – Execute the script. *(default)* + +#### Properties + +* `command` – Script and arguments to run. Must not include the `ruby`. *(name property)* +* `ruby` – Name of the `ruby_runtime` resource to use. If not specified, the + most recently declared `ruby_runtime` will be used. + +For other properties see the [Chef documentation](https://docs.chef.io/resource_execute.html#attributes). + +### `ruby_gem` + +The `ruby_gem` resource is a subclass of the standard `gem_package` resource to +install the gem with the configured runtime. + +```ruby +ruby_gem 'rake' do + version ' 10.4.2' +end +``` + +All actions and attributes match the standard `gem_package` resource with the +addition of a `ruby` attribute matching `ruby_execute`. + +### `bundle_install` + +The `bundle_install` resource installs gems based on a Gemfile using +[bundler](http://bundler.io/). + +```ruby +bundle_install '/path/to/Gemfile' do + deployment true + jobs 3 +end +``` + +The underlying `bundle` command will run on every converge, but notifications +will only be triggered if a gem is actually installed. + +#### Actions + +* `:install` – Run `bundle install`. *(default)* +* `:update` – Run `bundle update`. + +#### Properties + +* `path` – Path to a Gemfile or a directory containing a Gemfile. *(name property)* +* `binstubs` – Enable binstubs. If set to a string it is the path to generate + stubs in. +* `bundler_version` – Version of bundler to install. If unset the latest version is used. +* `deployment` – Enable deployment mode. +* `gem_binary` – Path to the gem binary. If unset this uses the `ruby_runtime` parent. +* `jobs` – Number of parallel installations to run. +* `retry` – Number of times to retry failed installations. +* `ruby` – Name of the `ruby_runtime` resource to execute against. +* `user` – User to run bundler as. +* `vendor` – Enable local vendoring. This maps to the `--path` option in bundler, + but that attribute name is already used. +* `without` – Group or groups to not install. + +## Ruby Providers + +### `system` + +The `system` provider installs Ruby using system packages. This is currently +only tested on platforms using `apt-get` and `yum` (Debian, Ubuntu, RHEL, CentOS +Amazon Linux, and Fedora) and is the default provider on those platforms. It +may work on other platforms but is untested. + +```ruby +ruby_runtime 'myapp' do + provider :system + version '2.1' +end +``` + +#### Options + +* `dev_package` – Install the package with the headers and other development + files. *(default: true)* +* `rubygems_package` – Install rubygems from a package. This is only needed for + Ruby 1.8. *(default: true on RHEL 6)* +* `package_name` – Override auto-detection of the package name. +* `package_upgrade` – Install using action `:upgrade`. *(default: false)* +* `package_version` – Override auto-detection of the package version. +* `version` – Override the Ruby version. + +### `scl` + +The `scl` provider installs Ruby using the [Software Collections](https://www.softwarecollections.org/) +packages. This is only available on RHEL and CentOS. SCL offers more +recent versions of Ruby than the system packages for the most part. If an SCL +package exists for the requested version, it will be used in preference to the +`system` provider. + +```ruby +ruby_runtime 'myapp' do + provider :scl + version '2.2' +end +``` + +### `chef` + +The `chef` provider uses the Ruby environment included in the Omnibus packages. +Great care should be taken when using this provider. + +```ruby +ruby_runtime 'myapp' do + provider :chef + version '2.1' +end +``` + +#### Options + +* `version` – Override the Ruby version. + +### `ruby_build` + +The `ruby_build` provider uses [ruby-build](https://github.com/sstephenson/ruby-build) +to compile and install Ruby. It can be found in the +[poise-ruby-build cookbook](https://github.com/poise/poise-ruby-build). + +## Sponsors + +Development sponsored by [Bloomberg](http://www.bloomberg.com/company/technology/). + +The Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/). + +## License + +Copyright 2015-2017, Noah Kantrowitz + +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/cookbooks/poise-ruby/attributes/default.rb b/cookbooks/poise-ruby/attributes/default.rb new file mode 100644 index 0000000..48f1155 --- /dev/null +++ b/cookbooks/poise-ruby/attributes/default.rb @@ -0,0 +1,23 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +# Default inversion options. +default['poise-ruby']['provider'] = 'auto' +default['poise-ruby']['options'] = {} + +# Used for the default recipe. +default['poise-ruby']['install_ruby'] = true +default['poise-ruby']['install_chef_ruby'] = true diff --git a/cookbooks/poise-ruby/files/halite_gem/poise_ruby.rb b/cookbooks/poise-ruby/files/halite_gem/poise_ruby.rb new file mode 100644 index 0000000..d068a6f --- /dev/null +++ b/cookbooks/poise-ruby/files/halite_gem/poise_ruby.rb @@ -0,0 +1,25 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseRuby + autoload :BundlerMixin, 'poise_ruby/bundler_mixin' + autoload :Error, 'poise_ruby/error' + autoload :Resources, 'poise_ruby/resources' + autoload :RubyCommandMixin, 'poise_ruby/ruby_command_mixin' + autoload :RubyProviders, 'poise_ruby/ruby_providers' + autoload :VERSION, 'poise_ruby/version' +end diff --git a/cookbooks/poise-ruby/files/halite_gem/poise_ruby/bundler_mixin.rb b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/bundler_mixin.rb new file mode 100644 index 0000000..c393576 --- /dev/null +++ b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/bundler_mixin.rb @@ -0,0 +1,84 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_ruby/error' + + +module PoiseRuby + # Mixin for creating bundle exec commands. + # + # @since 2.1.0 + module BundlerMixin + # Transform a command to run under `bundle exec` with the same semantics as + # Ruby execution elsewhere in this system. That means you should end up with + # something like `/bin/ruby /bin/bundle exec /bin/ruby /bin/cmd args`. + # + # @param cmd [String, Array] Command to transform. + # @param path [String] Optional input path for command resolution. + # @return [String, Array] + def bundle_exec_command(cmd, path: nil) + bundle = new_resource.parent_bundle + return cmd unless bundle + is_array = cmd.is_a?(Array) + cmd = Shellwords.split(cmd) unless is_array + root_path = ::File.expand_path('..', bundle.gemfile_path) + # Grab this once in case I need it for the extra path. + bundler_binary = bundle.bundler_binary + # This doesn't account for the potential of a .bundle/config created with + # settings that Chef doesn't know about. (╯°□°)╯︵ ┻━┻ + extra_path = if bundle.binstubs + bundle.binstubs == true ? 'bin' : bundle.binstubs + elsif bundle.vendor || bundle.deployment + # Find the relative path to start searching from. + vendor_base_path = if bundle.vendor && bundle.vendor != true + bundle.vendor + else + 'vendor/bundle' + end + # Add the ruby/. + vendor_base_path = ::File.join(File.expand_path(vendor_base_path, root_path), 'ruby') + # Find the version number folder inside that. + candidates = Dir.entries(vendor_base_path) + ruby_abi_folder = candidates.find {|name| name =~ /^\d\./ } + vendor_sub_path = if ruby_abi_folder + ::File.join(ruby_abi_folder, 'bin') + elsif candidates.include?('bin') + 'bin' + else + raise PoiseRuby::Error.new("Unable to find the vendor bin folder for #{vendor_base_path}: #{candidates.join(', ')}") + end + # Make the final path. + ::File.join(vendor_base_path, vendor_sub_path) + else + # The folder the bundler binary is in was the global gem executable dir. + ::File.dirname(bundler_binary) + end + # Resolve relative paths against Bundler.root. + extra_path = ::File.expand_path(extra_path, root_path) + # Create the full $PATH. + path ||= ENV['PATH'] + bundle_exec_path = extra_path + ::File::PATH_SEPARATOR + path + # Resolve the command + abs_cmd = PoiseLanguages::Utils.absolute_command(cmd, path: bundle_exec_path) + bundle_exec = [new_resource.ruby, bundler_binary, 'exec', new_resource.ruby] + abs_cmd + if is_array + bundle_exec + else + PoiseLanguages::Utils.shelljoin(bundle_exec) + end + end + end +end diff --git a/cookbooks/poise-ruby/files/halite_gem/poise_ruby/cheftie.rb b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/cheftie.rb new file mode 100644 index 0000000..aef9f39 --- /dev/null +++ b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/cheftie.rb @@ -0,0 +1,18 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_ruby/resources' +require 'poise_ruby/ruby_providers' diff --git a/cookbooks/poise-ruby/files/halite_gem/poise_ruby/error.rb b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/error.rb new file mode 100644 index 0000000..813221f --- /dev/null +++ b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/error.rb @@ -0,0 +1,21 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseRuby + class Error < ::Exception + end +end diff --git a/cookbooks/poise-ruby/files/halite_gem/poise_ruby/resources.rb b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/resources.rb new file mode 100644 index 0000000..6a46c8e --- /dev/null +++ b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/resources.rb @@ -0,0 +1,29 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_ruby/resources/bundle_install' +require 'poise_ruby/resources/ruby_execute' +require 'poise_ruby/resources/ruby_gem' +require 'poise_ruby/resources/ruby_runtime' + + +module PoiseRuby + # Chef resources and providers for poise-ruby. + # + # @since 2.0.0 + module Resources + end +end diff --git a/cookbooks/poise-ruby/files/halite_gem/poise_ruby/resources/bundle_install.rb b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/resources/bundle_install.rb new file mode 100644 index 0000000..d2b4ec1 --- /dev/null +++ b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/resources/bundle_install.rb @@ -0,0 +1,225 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/mixin/shell_out' +require 'chef/mixin/which' +require 'chef/provider' +require 'chef/resource' +require 'poise' + +require 'poise_ruby/error' +require 'poise_ruby/ruby_command_mixin' + + +module PoiseRuby + module Resources + # (see BundleInstall::Resource) + # @since 2.0.0 + module BundleInstall + # A `bundle_install` resource to install a [Bundler](http://bundler.io/) + # Gemfile. + # + # @provides bundle_install + # @action install + # @action update + # @note + # This resource is not idempotent itself, it will always run `bundle + # install`. + # @example + # bundle_install '/opt/my_app' do + # gem_path '/usr/local/bin/gem' + # end + class Resource < Chef::Resource + include Poise + provides(:bundle_install) + actions(:install, :update) + include PoiseRuby::RubyCommandMixin + + # @!attribute path + # Path to the Gemfile or to a directory that contains a Gemfile. + # @return [String] + attribute(:path, kind_of: String, name_attribute: true) + # @!attribute binstubs + # Enable binstubs. If set to a string it is the path to generate + # stubs in. + # @return [Boolean, String] + attribute(:binstubs, kind_of: [TrueClass, String]) + # @!attribute deployment + # Enable deployment mode. + # @return [Boolean] + attribute(:deployment, equal_to: [true, false], default: false) + # @!attribute jobs + # Number of parallel installations to run. + # @return [String, Integer] + attribute(:jobs, kind_of: [String, Integer]) + # @!attribute retry + # Number of times to retry failed installations. + # @return [String, Integer] + attribute(:retry, kind_of: [String, Integer]) + # @!attribute user + # User to run bundler as. + # @return [String, Integery, nil] + attribute(:user, kind_of: [String, Integer, NilClass]) + # @!attribute vendor + # Enable local vendoring. This maps to the `--path` option in bundler, + # but that attribute name is already used. + # @return [Boolean, String] + attribute(:vendor, kind_of: [TrueClass, String]) + # @!attribute without + # Group or groups to not install. + # @return [String, Array] + attribute(:without, kind_of: [Array, String]) + + # The path to the `bundle` binary for this installation. This is an + # output property. + # + # @return [String] + # @example + # execute "#{resources('bundle_install[/opt/myapp]').bundler_binary} vendor" + def bundler_binary + @bundler_binary ||= provider_for_action(:bundler_binary).bundler_binary + end + + # The path to the Gemfile for this installation. This is an output + # property. + # + # @return [String] + # @example + # file resources('bundle_install[/opt/myapp]').gemfile_path do + # owner 'root' + # end + def gemfile_path + @gemfile_path ||= provider_for_action(:gemfile_path).gemfile_path + end + end + + # The default provider for the `bundle_install` resource. + # + # @see Resource + class Provider < Chef::Provider + include Poise + provides(:bundle_install) + include PoiseRuby::RubyCommandMixin + + # Install bundler and the gems in the Gemfile. + def action_install + run_bundler('install') + end + + # Install bundler and update the gems in the Gemfile. + def action_update + run_bundler('update') + end + + # Return the absolute path to the correct bundle binary to run. + # + # @return [String] + def bundler_binary + @bundler_binary ||= ::File.join(poise_gem_bindir, 'bundle') + end + + # Find the absolute path to the Gemfile. This mirrors bundler's internal + # search logic by scanning up to parent folder as needed. + # + # @return [String] + def gemfile_path + @gemfile_path ||= begin + path = ::File.expand_path(new_resource.path) + if ::File.file?(path) + # We got a path to a real file, use that. + path + else + # Walk back until path==dirname(path) meaning we are at the root + while path != (next_path = ::File.dirname(path)) + possible_path = ::File.join(path, 'Gemfile') + return possible_path if ::File.file?(possible_path) + path = next_path + end + end + end + end + + private + + # Install the gems in the Gemfile. + def run_bundler(command) + return converge_by "Run bundle #{command}" if whyrun_mode? + cmd = ruby_shell_out!(bundler_command(command), environment: {'BUNDLE_GEMFILE' => gemfile_path}, user: new_resource.user) + # Look for a line like 'Installing $gemname $version' to know if we did anything. + if cmd.stdout.include?('Installing') + new_resource.updated_by_last_action(true) + end + end + + # Parse out the value for Gem.bindir. This is so complicated to minimize + # the required configuration on the resource combined with gem having + # terrible output formats. + # + # Renamed from #gem_bindir in 2.3.0 because of a conflict with a method + # of the same name in Chef::Mixin::PathSanity (which is pulled in via + # ShellOut) added in 13.0. + # + # @return [String] + def poise_gem_bindir + cmd = ruby_shell_out!(new_resource.gem_binary, 'environment') + # Parse a line like: + # - EXECUTABLE DIRECTORY: /usr/local/bin + matches = cmd.stdout.scan(/EXECUTABLE DIRECTORY: (.*)$/).first + if matches + matches.first + else + raise PoiseRuby::Error.new("Cannot find EXECUTABLE DIRECTORY: #{cmd.stdout}") + end + end + + # Command line options for the bundle install. + # + # @return [Array] + def bundler_options + [].tap do |opts| + if new_resource.binstubs + opts << "--binstubs" + (new_resource.binstubs.is_a?(String) ? "=#{new_resource.binstubs}" : '') + end + if new_resource.vendor + opts << "--path=" + (new_resource.vendor.is_a?(String) ? new_resource.vendor : 'vendor/bundle') + end + if new_resource.deployment + opts << '--deployment' + end + if new_resource.jobs + opts << "--jobs=#{new_resource.jobs}" + end + if new_resource.retry + opts << "--retry=#{new_resource.retry}" + end + if new_resource.without + opts << '--without' + opts.insert(-1, *new_resource.without) + end + end + end + + # Command array to run when installing the Gemfile. + # + # @return [Array] + def bundler_command(command) + [bundler_binary, command] + bundler_options + end + + end + end + end +end diff --git a/cookbooks/poise-ruby/files/halite_gem/poise_ruby/resources/ruby_execute.rb b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/resources/ruby_execute.rb new file mode 100644 index 0000000..e1ea4f9 --- /dev/null +++ b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/resources/ruby_execute.rb @@ -0,0 +1,90 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/mash' +require 'chef/provider/execute' +require 'chef/resource/execute' +require 'poise' + +require 'poise_ruby/bundler_mixin' +require 'poise_ruby/ruby_command_mixin' + + +module PoiseRuby + module Resources + # (see RubyExecute::Resource) + # @since 2.0.0 + module RubyExecute + # A `ruby_execute` resource to run Ruby scripts and commands. + # + # @provides ruby_execute + # @action run + # @example + # ruby_execute 'myapp.rb' do + # user 'myuser' + # end + class Resource < Chef::Resource::Execute + include Poise + provides(:ruby_execute) + actions(:run) + include PoiseRuby::RubyCommandMixin + + # @!attribute parent_bundle + # Optional bundle_install resource to run `bundle exec` against. + # @return [PoiseRuby::Resources::BundleInstall::Resource] + parent_attribute(:bundle, type: :bundle_install, optional: true, auto: false) + end + + # The default provider for `ruby_execute`. + # + # @see Resource + # @provides ruby_execute + class Provider < Chef::Provider::Execute + include PoiseRuby::BundlerMixin + provides(:ruby_execute) + + private + + # Command to pass to shell_out. + # + # @return [String, Array] + def command + if new_resource.parent_bundle + bundle_exec_command(new_resource.command, path: environment['PATH']) + else + if new_resource.command.is_a?(Array) + [new_resource.ruby] + new_resource.command + else + "#{new_resource.ruby} #{new_resource.command}" + end + end + end + + # Environment variables to pass to shell_out. + # + # @return [Hash] + def environment + Mash.new.tap do |environment| + environment.update(new_resource.parent_ruby.ruby_environment) if new_resource.parent_ruby + environment['BUNDLE_GEMFILE'] = new_resource.parent_bundle.gemfile_path if new_resource.parent_bundle + environment.update(new_resource.environment) if new_resource.environment + end + end + + end + end + end +end diff --git a/cookbooks/poise-ruby/files/halite_gem/poise_ruby/resources/ruby_gem.rb b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/resources/ruby_gem.rb new file mode 100644 index 0000000..17d10c3 --- /dev/null +++ b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/resources/ruby_gem.rb @@ -0,0 +1,125 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/provider/package/rubygems' +require 'chef/resource/gem_package' +require 'poise' + +require 'poise_ruby/ruby_command_mixin' + + +module PoiseRuby + module Resources + # (see RubyGem::Resource) + # @since 2.0.0 + module RubyGem + # A `ruby_gem` resource to install Ruby gems. + # + # @provides ruby_gem + # @action install + # @action upgrade + # @action remove + # @action purge + # @action reconfig + # @example + # ruby_gem 'rack' + class Resource < Chef::Resource::GemPackage + include Poise + provides(:ruby_gem) + actions(:install, :upgrade, :remove, :purge, :reconfig) + include PoiseRuby::RubyCommandMixin + + # @api private + def initialize(name, run_context=nil) + super + @resource_name = :ruby_gem if @resource_name + # Remove when all useful versions are using provider resolver. + @provider = PoiseRuby::Resources::RubyGem::Provider if @provider + end + end + + # The default provider for `ruby_gem`. + # + # @see Resource + # @provides ruby_gem + class Provider < Chef::Provider::Package::Rubygems + include Poise + provides(:ruby_gem) + + def load_current_resource + patch_environment { super } + end + + def define_resource_requirements + patch_environment { super } + end + + def action_install + patch_environment { super } + end + + def action_upgrade + patch_environment { super } + end + + def action_remove + patch_environment { super } + end + + def action_purge + patch_environment { super } + end + + def action_reconfig + patch_environment { super } + end + + private + + def patch_environment(&block) + environment_to_add = if new_resource.parent_ruby + new_resource.parent_ruby.ruby_environment + else + {} + end + + begin + if ENV['GEM_HOME'] && !ENV['GEM_HOME'].empty? + Chef::Log.warn("[#{new_resource}] $GEM_HOME is set in Chef's environment, this will likely interfere with gem installation") + end + if ENV['GEM_PATH'] && !ENV['GEM_PATH'].empty? + Chef::Log.warn("[#{new_resource}] $GEM_PATH is set in Chef's environment, this will likely interfere with gem installation") + end + old_vars = environment_to_add.inject({}) do |memo, (key, value)| + memo[key] = ENV[key] + ENV[key] = value + memo + end + block.call + ensure + old_vars.each do |key, value| + if value.nil? + ENV.delete(key) + else + ENV[key] = value + end + end + end + end + end + end + end +end diff --git a/cookbooks/poise-ruby/files/halite_gem/poise_ruby/resources/ruby_runtime.rb b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/resources/ruby_runtime.rb new file mode 100644 index 0000000..695f601 --- /dev/null +++ b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/resources/ruby_runtime.rb @@ -0,0 +1,87 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/resource' +require 'poise' + + +module PoiseRuby + module Resources + # (see RubyRuntime::Resource) + # @since 2.0.0 + module RubyRuntime + # A `ruby_runtime` resource to manage Ruby installations. + # + # @provides ruby_runtime + # @action install + # @action uninstall + # @example + # ruby_runtime '2.1.2' + class Resource < Chef::Resource + include Poise(inversion: true, container: true) + provides(:ruby_runtime) + actions(:install, :uninstall) + + # @!attribute version + # Version of Ruby to install. + # @return [String] + attribute(:version, kind_of: String, name_attribute: true) + # @!attribute bundler_version + # Version of Bundler to install. It set to `true`, the latest + # available version will be used. If set to `false`, Bundler will + # not be installed. + # @note Disabling the Bundler install may result in other resources + # being non-functional. + # @return [String, Boolean] + attribute(:bundler_version, kind_of: [String, TrueClass, FalseClass], default: true) + + # The path to the `ruby` binary for this Ruby installation. This is an + # output property. + # + # @return [String] + # @example + # execute "#{resources('ruby_runtime[2.2.2]').ruby_binary} myapp.rb" + def ruby_binary + @ruby_binary ||= provider_for_action(:ruby_binary).ruby_binary + end + + # The environment variables for this Ruby installation. This is an + # output property. + # + # @return [Hash] + # @example + # execute '/opt/myapp.py' do + # environment resources('ruby_runtime[2.2.2]').ruby_environment + # end + def ruby_environment + @ruby_environment ||= provider_for_action(:ruby_environment).ruby_environment + end + + # The path to the `gem` binary for this Ruby installation. This is an + # output property. + # + # @return [String] + # @example + # execute "#{resources('ruby_runtime[2.2.2]').gem_binary} install myapp" + def gem_binary + @gem_binary ||= provider_for_action(:gem_binary).gem_binary + end + end + + # Providers can be found under lib/poise_ruby/ruby_providers/ + end + end +end diff --git a/cookbooks/poise-ruby/files/halite_gem/poise_ruby/resources/ruby_runtime_test.rb b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/resources/ruby_runtime_test.rb new file mode 100644 index 0000000..956394d --- /dev/null +++ b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/resources/ruby_runtime_test.rb @@ -0,0 +1,213 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/mixin/convert_to_class_name' +require 'chef/provider' +require 'chef/resource' +require 'poise' + + +module PoiseRuby + module Resources + # (see RubyRuntimeTest::Resource) + # @since 2.1.0 + # @api private + module RubyRuntimeTest + # A `ruby_runtime_test` resource for integration testing of this + # cookbook. This is an internal API and can change at any time. + # + # @provides ruby_runtime_test + # @action run + class Resource < Chef::Resource + include Poise + provides(:ruby_runtime_test) + actions(:run) + + attribute(:version, kind_of: String, name_attribute: true) + attribute(:runtime_provider, kind_of: Symbol) + attribute(:path, kind_of: String, default: lazy { default_path }) + + def default_path + ::File.join('', 'root', "ruby_test_#{name}") + end + end + + # The default provider for `ruby_runtime_test`. + # + # @see Resource + # @provides ruby_runtime_test + class Provider < Chef::Provider + include Poise + provides(:ruby_runtime_test) + + # The `run` action for the `ruby_runtime_test` resource. + # + # @return [void] + def action_run + notifying_block do + # Top level directory for this test. + directory new_resource.path + + # Install and log the version. + ruby_runtime new_resource.name do + provider new_resource.runtime_provider if new_resource.runtime_provider + version new_resource.version + end + test_version + + # Test ruby_gem. + ruby_gem 'thor remove before' do + action :remove + package_name 'thor' + ruby new_resource.name + end + test_require('thor', 'thor_before') + ruby_gem 'thor' do + ruby new_resource.name + notifies :create, sentinel_file('thor'), :immediately + end + test_require('thor', 'thor_mid') + ruby_gem 'thor again' do + package_name 'thor' + ruby new_resource.name + notifies :create, sentinel_file('thor2'), :immediately + end + ruby_gem 'thor remove after' do + action :remove + package_name 'thor' + ruby new_resource.name + end + test_require('thor', 'thor_after') + + # Use bundler to test something that should always be installed. + ruby_gem 'bundler' do + ruby new_resource.name + notifies :create, sentinel_file('bundler'), :immediately + end + + # Create and install a Gemfile. + bundle1_path = ::File.join(new_resource.path, 'bundle1') + directory bundle1_path + file ::File.join(bundle1_path, 'Gemfile') do + content <<-EOH +source 'https://rubygems.org/' +gem 'hashie' +gem 'tomlrb', '1.1.0' +EOH + end + bundle1 = bundle_install bundle1_path do + ruby new_resource.name + end + test_require('hashie', bundle: bundle1) + test_require('tomlrb', bundle: bundle1) + test_require('thor', 'thor_bundle', bundle: bundle1) + + # Test for bundle exec shebang issues. + bundle2_path = ::File.join(new_resource.path, 'bundle2') + directory bundle2_path + file ::File.join(bundle2_path, 'Gemfile') do + content <<-EOH +source 'https://rubygems.org/' +gem 'unicorn' +EOH + end + file ::File.join(bundle2_path, 'Gemfile.lock') do + content <<-EOH +GEM + remote: https://rubygems.org/ + specs: + kgio (2.10.0) + rack (1.6.4) + raindrops (0.15.0) + unicorn (4.9.0) + kgio (~> 2.6) + rack + raindrops (~> 0.7) + +PLATFORMS + ruby + +DEPENDENCIES + unicorn + +BUNDLED WITH + 1.10.6 +EOH + end + bundle2 = bundle_install bundle2_path do + ruby new_resource.name + deployment true + end + # test_require('unicorn', bundle: bundle2) + ruby_execute "unicorn --version > #{::File.join(new_resource.path, "unicorn_version")}" do + ruby new_resource.name + parent_bundle bundle2 + end + end + end + + def sentinel_file(name) + file ::File.join(new_resource.path, "sentinel_#{name}") do + action :nothing + end + end + + private + + def test_version(ruby: new_resource.name) + # Only queue up this resource once, the ivar is just for tracking. + @ruby_version_test ||= file ::File.join(new_resource.path, 'ruby_version.rb') do + user 'root' + group 'root' + mode '644' + content <<-EOH +File.new(ARGV[0], 'w').write(RUBY_VERSION) +EOH + end + + ruby_execute "#{@ruby_version_test.path} #{::File.join(new_resource.path, 'version')}" do + ruby ruby if ruby + end + end + + def test_require(name, path=name, ruby: new_resource.name, bundle: nil, class_name: nil) + # Only queue up this resource once, the ivar is just for tracking. + @ruby_require_test ||= file ::File.join(new_resource.path, 'require_version.rb') do + user 'root' + group 'root' + mode '644' + content <<-EOH +require 'rubygems' +begin + require "\#{ARGV[0]}/version" + klass = ARGV[1].split('::').inject(Object) {|memo, name| memo.const_get(name) } + File.new(ARGV[2], 'w').write(klass::VERSION) +rescue LoadError +end +EOH + end + + class_name ||= Chef::Mixin::ConvertToClassName.convert_to_class_name(name) + ruby_execute "#{@ruby_require_test.path} #{name} #{class_name} #{::File.join(new_resource.path, "require_#{path}")}" do + ruby ruby if ruby + parent_bundle bundle if bundle + end + end + + end + end + end +end diff --git a/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_command_mixin.rb b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_command_mixin.rb new file mode 100644 index 0000000..10bc0c6 --- /dev/null +++ b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_command_mixin.rb @@ -0,0 +1,59 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'poise/utils' +require 'poise_languages' + + +module PoiseRuby + # Mixin for resources and providers which run Ruby commands. + # + # @since 2.0.0 + module RubyCommandMixin + include Poise::Utils::ResourceProviderMixin + + module Resource + include PoiseLanguages::Command::Mixin::Resource(:ruby) + + # @!attribute gem_binary + # Path to the gem binary. + # @return [String] + attribute(:gem_binary, kind_of: String, default: lazy { default_gem_binary }) + + private + + # Find the default gem binary. If there is a parent use that, otherwise + # use the same logic as {PoiseRuby::RubyProviders::Base#gem_binary}. + # + # @return [String] + def default_gem_binary + if parent_ruby + parent_ruby.gem_binary + else + dir, base = ::File.split(ruby) + # If this ruby is called something weird, bail out. + raise NotImplementedError unless base.start_with?('ruby') + # Allow for names like "ruby2.0" -> "gem2.0". + ::File.join(dir, base.sub(/^ruby/, 'gem')) + end + end + end + + module Provider + include PoiseLanguages::Command::Mixin::Provider(:ruby) + end + end +end diff --git a/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_providers.rb b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_providers.rb new file mode 100644 index 0000000..621ee56 --- /dev/null +++ b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_providers.rb @@ -0,0 +1,35 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/platform/provider_priority_map' + +require 'poise_ruby/ruby_providers/chef' +require 'poise_ruby/ruby_providers/dummy' +require 'poise_ruby/ruby_providers/scl' +require 'poise_ruby/ruby_providers/system' + + +module PoiseRuby + # Inversion providers for the ruby_runtime resource. + # + # @since 2.0.0 + module RubyProviders + Chef::Platform::ProviderPriorityMap.instance.priority(:ruby_runtime, [ + PoiseRuby::RubyProviders::Scl, + PoiseRuby::RubyProviders::System, + ]) + end +end diff --git a/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_providers/base.rb b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_providers/base.rb new file mode 100644 index 0000000..4813c73 --- /dev/null +++ b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_providers/base.rb @@ -0,0 +1,117 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/provider' +require 'poise' + +require 'poise_ruby/resources/ruby_gem' +require 'poise_ruby/resources/ruby_runtime' + + +module PoiseRuby + module RubyProviders + class Base < Chef::Provider + include Poise(inversion: :ruby_runtime) + + # Set default inversion options. + # + # @api private + def self.default_inversion_options(node, new_resource) + super.merge({ + bundler_version: new_resource.bundler_version, + version: new_resource.version, + }) + end + + # The `install` action for the `ruby_runtime` resource. + # + # @return [void] + def action_install + notifying_block do + install_ruby + install_bundler + end + end + + # The `uninstall` action for the `ruby_runtime` resource. + # + # @return [void] + def action_uninstall + notifying_block do + uninstall_ruby + end + end + + # The path to the `ruby` binary. + # + # @abstract + # @return [String] + def ruby_binary + raise NotImplementedError + end + + # Output property for environment variables. + # + # @return [Hash] + def ruby_environment + # No environment variables needed. Rejoice. + {} + end + + # The path to the `gem` binary. Look relative to the + # `ruby` binary for a default implementation. + # + # @return [String] + def gem_binary + dir, base = ::File.split(ruby_binary) + # If this ruby is called something weird, bail out. + raise NotImplementedError unless base.start_with?('ruby') + # Allow for names like "ruby2.0" -> "gem2.0". + ::File.join(dir, base.sub(/^ruby/, 'gem')) + end + + private + + # Install the Ruby runtime. Must be implemented by subclass. + # + # @abstract + # @return [void] + def install_ruby + end + + # Uninstall the Ruby runtime. Must be implemented by subclass. + # + # @abstract + # @return [void] + def uninstall_ruby + end + + # Install Bundler in to the Ruby runtime. + # + # @return [void] + def install_bundler + # Captured because #options conflicts with Chef::Resource::Package#options. + bundler_version = options[:bundler_version] + return unless bundler_version + ruby_gem 'bundler' do + action :upgrade if bundler_version == true + parent_ruby new_resource + version bundler_version if bundler_version.is_a?(String) + end + end + end + end +end diff --git a/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_providers/chef.rb b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_providers/chef.rb new file mode 100644 index 0000000..be7ecc4 --- /dev/null +++ b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_providers/chef.rb @@ -0,0 +1,53 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_ruby/error' +require 'poise_ruby/ruby_providers/base' + + +module PoiseRuby + module RubyProviders + # Inversion provider for the `ruby_runtime` resource to use whatever Ruby is + # currently running, generally Chef's omnibus-d Ruby. + # + # @since 2.0.0 + # @provides chef + class ChefRuby < Base + provides(:chef) + + # The `install` action for the `ruby_runtime` resource. + # + # @return [void] + def action_install + # No-op, already installed! + end + + # The `uninstall` action for the `ruby_runtime` resource. + # + # @return [void] + def action_uninstall + raise PoiseRuby::Error.new("You cannot uninstall Chef's Ruby.") + end + + # The path to the running Ruby binary as determined via RbConfig. + # + # @return [String] + def ruby_binary + Gem.ruby + end + end + end +end diff --git a/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_providers/dummy.rb b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_providers/dummy.rb new file mode 100644 index 0000000..0996831 --- /dev/null +++ b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_providers/dummy.rb @@ -0,0 +1,77 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'poise_ruby/ruby_providers/base' + + +module PoiseRuby + module RubyProviders + # Inversion provider for the `ruby_runtime` resource to use a fake Ruby, + # for use in unit tests. + # + # @since 2.1.0 + # @provides dummy + class Dummy < Base + provides(:dummy) + + def self.default_inversion_options(node, resource) + super.merge({ + # Manual overrides for dummy data. + ruby_binary: ::File.join('', 'ruby'), + ruby_environment: nil, + gem_binary: nil, + }) + end + + # The `install` action for the `ruby_runtime` resource. + # + # @return [void] + def action_install + # This space left intentionally blank. + end + + # The `uninstall` action for the `ruby_runtime` resource. + # + # @return [void] + def action_uninstall + # This space left intentionally blank. + end + + # Path to the non-existent ruby. + # + # @return [String] + def ruby_binary + options['ruby_binary'] + end + + # Environment for the non-existent Ruby. + # + # @return [String] + def ruby_environment + options['ruby_environment'] || super + end + + # Path to the non-existent gem. + # + # @return [String] + def gem_binary + options['gem_binary'] || super + end + + end + end +end + diff --git a/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_providers/scl.rb b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_providers/scl.rb new file mode 100644 index 0000000..795a9a1 --- /dev/null +++ b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_providers/scl.rb @@ -0,0 +1,56 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/resource' +require 'poise_languages' + +require 'poise_ruby/ruby_providers/base' + + +module PoiseRuby + module RubyProviders + class Scl < Base + include PoiseLanguages::Scl::Mixin + provides(:scl) + scl_package('2.4.0', 'rh-ruby24', 'rh-ruby24-ruby-devel') + scl_package('2.3.1', 'rh-ruby23', 'rh-ruby23-ruby-devel') + scl_package('2.2.2', 'rh-ruby22', 'rh-ruby22-ruby-devel') + # On EL7, the system package is Ruby 2.0.0 and is newer than the SCL build. + scl_package('2.0.0', 'ruby200', 'ruby200-ruby-devel', '~> 6.0') + scl_package('1.9.3', 'ruby193', 'ruby193-ruby-devel') + + def ruby_binary + ::File.join(scl_folder, 'root', 'usr', 'bin', 'ruby') + end + + def ruby_environment + scl_environment + end + + private + + def install_ruby + install_scl_package + end + + def uninstall_ruby + uninstall_scl_package + end + + end + end +end + diff --git a/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_providers/system.rb b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_providers/system.rb new file mode 100644 index 0000000..fb4267c --- /dev/null +++ b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/ruby_providers/system.rb @@ -0,0 +1,116 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +require 'chef/resource' +require 'poise_languages' + +require 'poise_ruby/error' +require 'poise_ruby/ruby_providers/base' + + +module PoiseRuby + module RubyProviders + class System < Base + include PoiseLanguages::System::Mixin + provides(:system) + packages('ruby', { + debian: { + '8' => %w{ruby2.1}, + '7' => %w{ruby1.9.3 ruby1.9.1 ruby1.8}, + # Debian 6 has a ruby1.9.1 package that installs 1.9.2, ignoring it for now. + '6' => %w{ruby1.8}, + }, + ubuntu: { + '16.04' => %w{ruby2.3}, + '14.04' => %w{ruby2.0 ruby1.9.3}, + '12.04' => %w{ruby1.9.3 ruby1.8}, + '10.04' => %w{ruby1.9.1 ruby1.8}, + }, + rhel: {default: %w{ruby}}, + centos: {default: %w{ruby}}, + fedora: {default: %w{ruby}}, + # Amazon Linux does actually have packages ruby18, ruby19, ruby20, ruby21. + # Ignoring for now because wooooo non-standard formatting. + amazon: {default: %w{ruby}}, + }) + + def self.default_inversion_options(node, resource) + super.merge({ + # Install a separate rubygems package? Only needed for 1.8. + rubygems_package: node['platform_family'] == 'rhel' && node['platform_version'].start_with?('6'), + }) + end + + # Output value for the Python binary we are installing. Seems to match + # package name on all platforms I've checked. + def ruby_binary + ::File.join('', 'usr', 'bin', system_package_name) + end + + private + + def install_ruby + install_system_packages + install_rubygems_package if options['rubygems_package'] + end + + def uninstall_ruby + uninstall_system_packages + end + + # Ubuntu has no ruby1.9.3-dev package. + def system_dev_package_overrides + super.tap do |overrides| + # WTF Ubuntu, seriously. + overrides['ruby1.9.3'] = 'ruby1.9.1-dev' if node.platform_family?('debian') + end + end + + # Install the configured rubygems package. + def install_rubygems_package + package (options['rubygems_package'].is_a?(String) ? options['rubygems_package'] : 'rubygems') + end + + def system_package_candidates(version) + [].tap do |names| + # Might as well try it. + names << "ruby#{version}" if version && !['', '1', '2'].include?(version) + # On debian, 1.9.1 and 1.9.3 have special packages. + if match = version.match(/^(\d+\.\d+\.\d+)/) + names << "ruby#{match[1]}" + end + # Normal debian package like ruby2.0. + if match = version.match(/^(\d+\.\d+)/) + names << "ruby#{match[1]}" + end + # Aliases for ruby1 and ruby2 + if version == '2' || version == '' + # 2.3 is on there for future proofing. Well, at least giving me a + # buffer zone. + names.concat(%w{ruby2.3 ruby2.2 ruby2.1 ruby2.0}) + end + if version == '1' || version == '' + names.concat(%w{ruby1.9.3 ruby1.9 ruby1.8}) + end + # For RHEL and friends. + names << 'ruby' + names.uniq! + end + end + + end + end +end diff --git a/cookbooks/poise-ruby/files/halite_gem/poise_ruby/version.rb b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/version.rb new file mode 100644 index 0000000..6101a09 --- /dev/null +++ b/cookbooks/poise-ruby/files/halite_gem/poise_ruby/version.rb @@ -0,0 +1,20 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + + +module PoiseRuby + VERSION = '2.4.0' +end diff --git a/cookbooks/poise-ruby/libraries/default.rb b/cookbooks/poise-ruby/libraries/default.rb new file mode 100644 index 0000000..e31c91f --- /dev/null +++ b/cookbooks/poise-ruby/libraries/default.rb @@ -0,0 +1,19 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +raise 'Halite is not compatible with no_lazy_load false, please set no_lazy_load true in your Chef configuration file.' unless Chef::Config[:no_lazy_load] +$LOAD_PATH << File.expand_path('../../files/halite_gem', __FILE__) +require "poise_ruby/cheftie" diff --git a/cookbooks/poise-ruby/metadata.json b/cookbooks/poise-ruby/metadata.json new file mode 100644 index 0000000..10a7467 --- /dev/null +++ b/cookbooks/poise-ruby/metadata.json @@ -0,0 +1 @@ +{"name":"poise-ruby","version":"2.4.0","description":"A Chef cookbook for managing Ruby installations.","long_description":"# Poise-Ruby Cookbook\n\n[![Build Status](https://img.shields.io/travis/poise/poise-ruby.svg)](https://travis-ci.org/poise/poise-ruby)\n[![Gem Version](https://img.shields.io/gem/v/poise-ruby.svg)](https://rubygems.org/gems/poise-ruby)\n[![Cookbook Version](https://img.shields.io/cookbook/v/poise-ruby.svg)](https://supermarket.chef.io/cookbooks/poise-ruby)\n[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-ruby.svg)](https://codecov.io/github/poise/poise-ruby)\n[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-ruby.svg)](https://gemnasium.com/poise/poise-ruby)\n[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)\n\nA [Chef](https://www.chef.io/) cookbook to provide a unified interface for\ninstalling Ruby and running things with it. This README covers the 2.x version\nof the cookbook, the 1.x version is very different and no longer supported.\n\n## Quick Start\n\nTo install the latest available version of Ruby 2.x and then use it to install\nsome gems:\n\n```ruby\nruby_runtime '2'\n\nruby_gem 'rake'\n\nbundle_install '/path/to/Gemfile' do\n without 'development'\n deployment true\nend\n```\n\n## Requirements\n\nChef 12.1 or newer is required.\n\n## Attributes\n\nAttributes are used to configure the default recipe.\n\n* `node['poise-ruby']['install_ruby']` – Install a Ruby runtime. *(default: true)*\n* `node['poise-ruby']['install_chef_ruby']` – Create a `ruby_runtime` using\n the `:chef` provider. Doesn't actually install anything. *(default: true)*\n\n## Recipes\n\n### `default`\n\nThe default recipe installs Ruby based on the node attributes. It is entirely\noptional and can be ignored in favor of direct use of the `ruby_runtime`\nresource.\n\n## Resources\n\n### `ruby_runtime`\n\nThe `ruby_runtime` resource installs a Ruby interpreter.\n\n```ruby\nruby_runtime 'any' do\n version ''\nend\n```\n\n#### Actions\n\n* `:install` – Install the Ruby interpreter. *(default)*\n* `:uninstall` – Uninstall the Ruby interpreter.\n\n#### Properties\n\n* `version` – Version of Ruby to install. If a partial version is given, use the\n latest available version matching that prefix. *(name properties)*\n\n#### Provider Options\n\nThe `poise-ruby` library offers an additional way to pass configuration\ninformation to the final provider called \"options\". Options are key/value pairs\nthat are passed down to the ruby_runtime provider and can be used to control how it\ninstalls Ruby. These can be set in the `ruby_runtime`\nresource using the `options` method, in node attributes or via the\n`ruby_runtime_options` resource. The options from all sources are merged\ntogether in to a single hash.\n\nWhen setting options in the resource you can either set them for all providers:\n\n```ruby\nruby_runtime 'myapp' do\n version '2.1'\n options dev_package: false\nend\n```\n\nor for a single provider:\n\n```ruby\nruby_runtime 'myapp' do\n version '2.1'\n options :system, dev_package: false\nend\n```\n\nSetting via node attributes is generally how an end-user or application cookbook\nwill set options to customize installations in the library cookbooks they are using.\nYou can set options for all installations or for a single runtime:\n\n```ruby\n# Global, for all installations.\noverride['poise-ruby']['options']['dev_package'] = false\n# Single installation.\noverride['poise-ruby']['myapp']['version'] = '2.2'\n```\n\nThe `ruby_runtime_options` resource is also available to set node attributes\nfor a specific installation in a DSL-friendly way:\n\n```ruby\nruby_runtime_options 'myapp' do\n version '2.2'\nend\n```\n\nUnlike resource attributes, provider options can be different for each provider.\nNot all providers support the same options so make sure to the check the\ndocumentation for each provider to see what options the use.\n\n### `ruby_runtime_options`\n\nThe `ruby_runtime_options` resource allows setting provider options in a\nDSL-friendly way. See [the Provider Options](#provider-options) section for more\ninformation about provider options overall.\n\n```ruby\nruby_runtime_options 'myapp' do\n version '2.2'\nend\n```\n\n#### Actions\n\n* `:run` – Apply the provider options. *(default)*\n\n#### Properties\n\n* `resource` – Name of the `ruby_runtime` resource. *(name property)*\n* `for_provider` – Provider to set options for.\n\nAll other property keys will be used as options data.\n\n### `ruby_execute`\n\nThe `ruby_execute` resource executes a Ruby script using the configured runtime.\n\n```ruby\nruby_execute 'myapp.rb' do\n user 'myuser'\nend\n```\n\nThis uses the built-in `execute` resource and supports all the same properties.\n\n#### Actions\n\n* `:run` – Execute the script. *(default)*\n\n#### Properties\n\n* `command` – Script and arguments to run. Must not include the `ruby`. *(name property)*\n* `ruby` – Name of the `ruby_runtime` resource to use. If not specified, the\n most recently declared `ruby_runtime` will be used.\n\nFor other properties see the [Chef documentation](https://docs.chef.io/resource_execute.html#attributes).\n\n### `ruby_gem`\n\nThe `ruby_gem` resource is a subclass of the standard `gem_package` resource to\ninstall the gem with the configured runtime.\n\n```ruby\nruby_gem 'rake' do\n version ' 10.4.2'\nend\n```\n\nAll actions and attributes match the standard `gem_package` resource with the\naddition of a `ruby` attribute matching `ruby_execute`.\n\n### `bundle_install`\n\nThe `bundle_install` resource installs gems based on a Gemfile using\n[bundler](http://bundler.io/).\n\n```ruby\nbundle_install '/path/to/Gemfile' do\n deployment true\n jobs 3\nend\n```\n\nThe underlying `bundle` command will run on every converge, but notifications\nwill only be triggered if a gem is actually installed.\n\n#### Actions\n\n* `:install` – Run `bundle install`. *(default)*\n* `:update` – Run `bundle update`.\n\n#### Properties\n\n* `path` – Path to a Gemfile or a directory containing a Gemfile. *(name property)*\n* `binstubs` – Enable binstubs. If set to a string it is the path to generate\n stubs in.\n* `bundler_version` – Version of bundler to install. If unset the latest version is used.\n* `deployment` – Enable deployment mode.\n* `gem_binary` – Path to the gem binary. If unset this uses the `ruby_runtime` parent.\n* `jobs` – Number of parallel installations to run.\n* `retry` – Number of times to retry failed installations.\n* `ruby` – Name of the `ruby_runtime` resource to execute against.\n* `user` – User to run bundler as.\n* `vendor` – Enable local vendoring. This maps to the `--path` option in bundler,\n but that attribute name is already used.\n* `without` – Group or groups to not install.\n\n## Ruby Providers\n\n### `system`\n\nThe `system` provider installs Ruby using system packages. This is currently\nonly tested on platforms using `apt-get` and `yum` (Debian, Ubuntu, RHEL, CentOS\nAmazon Linux, and Fedora) and is the default provider on those platforms. It\nmay work on other platforms but is untested.\n\n```ruby\nruby_runtime 'myapp' do\n provider :system\n version '2.1'\nend\n```\n\n#### Options\n\n* `dev_package` – Install the package with the headers and other development\n files. *(default: true)*\n* `rubygems_package` – Install rubygems from a package. This is only needed for\n Ruby 1.8. *(default: true on RHEL 6)*\n* `package_name` – Override auto-detection of the package name.\n* `package_upgrade` – Install using action `:upgrade`. *(default: false)*\n* `package_version` – Override auto-detection of the package version.\n* `version` – Override the Ruby version.\n\n### `scl`\n\nThe `scl` provider installs Ruby using the [Software Collections](https://www.softwarecollections.org/)\npackages. This is only available on RHEL and CentOS. SCL offers more\nrecent versions of Ruby than the system packages for the most part. If an SCL\npackage exists for the requested version, it will be used in preference to the\n`system` provider.\n\n```ruby\nruby_runtime 'myapp' do\n provider :scl\n version '2.2'\nend\n```\n\n### `chef`\n\nThe `chef` provider uses the Ruby environment included in the Omnibus packages.\nGreat care should be taken when using this provider.\n\n```ruby\nruby_runtime 'myapp' do\n provider :chef\n version '2.1'\nend\n```\n\n#### Options\n\n* `version` – Override the Ruby version.\n\n### `ruby_build`\n\nThe `ruby_build` provider uses [ruby-build](https://github.com/sstephenson/ruby-build)\nto compile and install Ruby. It can be found in the\n[poise-ruby-build cookbook](https://github.com/poise/poise-ruby-build).\n\n## Sponsors\n\nDevelopment sponsored by [Bloomberg](http://www.bloomberg.com/company/technology/).\n\nThe Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/).\n\n## License\n\nCopyright 2015-2017, Noah Kantrowitz\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","maintainer":"Noah Kantrowitz","maintainer_email":"noah@coderanger.net","license":"Apache-2.0","platforms":{"ubuntu":">= 0.0.0","debian":">= 0.0.0","centos":">= 0.0.0","redhat":">= 0.0.0","fedora":">= 0.0.0","amazon":">= 0.0.0"},"dependencies":{"poise":"~> 2.0","poise-languages":"~> 2.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/poise/poise-ruby","issues_url":"https://github.com/poise/poise-ruby/issues","chef_version":[["< 15",">= 12.1"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/poise-ruby/recipes/default.rb b/cookbooks/poise-ruby/recipes/default.rb new file mode 100644 index 0000000..c01a91f --- /dev/null +++ b/cookbooks/poise-ruby/recipes/default.rb @@ -0,0 +1,19 @@ +# +# Copyright 2015-2017, Noah Kantrowitz +# +# 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. +# + +# Default runtimes, last one will be the default. +ruby_runtime('chef') { provider :chef } if node['poise-ruby']['install_chef_ruby'] +ruby_runtime('ruby') { version '' } if node['poise-ruby']['install_ruby'] diff --git a/cookbooks/poise-service/CHANGELOG.md b/cookbooks/poise-service/CHANGELOG.md new file mode 100644 index 0000000..8f0fa43 --- /dev/null +++ b/cookbooks/poise-service/CHANGELOG.md @@ -0,0 +1,92 @@ +# Poise-Service Changelog + +## v1.5.2 + +* Set `declared_type` on the mixin-created `poise_service` resource so it works + correctly with ChefSpec. + +## v1.5.1 + +* Fix the `sysvinit` provider on Amazon Linux under Chef 13. + +## v1.5.0 + +* Added `never_start` and `never_stop` provider options to prevent Chef from starting + or stopping a service. +* Automatically reload systemd when removing a service if auto_reload is enabled. +* Improved dummy provider, records process output to `/var/run/service_name.out` + and a `restart_delay` provider option to the dummy provider to wait between + stopping and starting. + +## v1.4.2 + +* Fix the `noterm` test service to work on Ruby 2.3. + +## v1.4.1 + +* Fix `poise_service_user` on Solaris and make it closer to being usable on Windows. + +## v1.4.0 + +* [#31](https://github.com/poise/poise-service/pull/31) Add `shell` property to + `poise_service_user` resource. + +## v1.3.1 + +* [#25](https://github.com/poise/poise-service/pull/25) Cope with a service user + with an invalid home directory. +* Use the correct default cookbook for `service_template` when used with additional plugins. + +## v1.3.0 + +* Allow setting `pid_file_external false` as a provider option for the `sysvinit` + provider to have non-standard path but keep the internal handling. +* Improved quoting for environment variables in the `inittab` provider. + +## v1.2.1 + +* [#23](https://github.com/poise/poise-service/pull/23) Fix service templates on AIX and FreeBSD to use the correct root group. + +## v1.2.0 + +* The `Restart` mode for systemd services can now be controlled via provider + option and defaults to `on-failure` to match other providers. + +## v1.1.2 + +* [#22](https://github.com/poise/poise-service/pull/22) Set all script commands + for the `sysvinit` provider. This should fix compatibility with EL5. + +## v1.1.1 + +* Fix an incorrect value in `poise_service_test`. This is not relevant to + end-users of `poise-service`. + +## v1.1.0 + +* Added `inittab` provider to manage services using old-fashioned `/etc/inittab`. + +## v1.0.4 + +* Set GID correctly in all service providers. +* Allow overriding the path to the generated sysvinit script. + +## v1.0.3 + +* [#10](https://github.com/poise/poise-service/pull/10) Fixes for ensuring services are restarted when their command or user changes. +* [#11](https://github.com/poise/poise-service/pull/11) Revamp the `sysvinit` provider for non-Debian platforms to be more stable. +* [#12](https://github.com/poise/poise-service/pull/12) Improve the `dummy` provider to handle dropping privs correctly. + +## v1.0.2 + +* Fix a potential infinite loop when starting a service with the dummy provider. +* [#2](https://github.com/poise/poise-service/pull/2) Remove usage of root + default files so uploading with Berkshelf works (for now). + +## v1.0.1 + +* Don't use a shared, mutable default value for `#environment`. + +## v1.0.0 + +* Initial release! diff --git a/cookbooks/poise-service/README.md b/cookbooks/poise-service/README.md new file mode 100644 index 0000000..a9e9947 --- /dev/null +++ b/cookbooks/poise-service/README.md @@ -0,0 +1,448 @@ +# Poise-Service Cookbook + +[![Build Status](https://img.shields.io/travis/poise/poise-service.svg)](https://travis-ci.org/poise/poise-service) +[![Gem Version](https://img.shields.io/gem/v/poise-service.svg)](https://rubygems.org/gems/poise-service) +[![Cookbook Version](https://img.shields.io/cookbook/v/poise-service.svg)](https://supermarket.chef.io/cookbooks/poise-service) +[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-service.svg)](https://codecov.io/github/poise/poise-service) +[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-service.svg)](https://gemnasium.com/poise/poise-service) +[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) + +A [Chef](https://www.chef.io/) cookbook to provide a unified interface for +services. + +### What is poise-service? + +Poise-service is a tool for developers of "library cookbooks" to define a +service without forcing the end-user of the library to adhere to their choice of +service management framework. The `poise_service` resource represents an +abstract service to be run, which can then be customized by node attributes and +the `poise_service_options` resource. This is a technique called [dependency +injection](https://en.wikipedia.org/wiki/Dependency_injection), and allows a +measure of decoupling between the library and application cookbooks. + +### Why would I use poise-service? + +Poise-service is most useful for authors of library-style cookbooks, for example +the `apache2`, `mysql`, or `application` cookbooks. When using other service +management options with Chef, the author of the library cookbook has to add +specific code for each service management framework they want to support, often +resulting in a cookbook only supporting the favorite framework of the author or +depending on distribution packages for their init scripts. The `poise_service` +resource allows library cookbook authors a way to write generic code for all +service management frameworks while still allowing users of that cookbook to +choose which service management framework best fits their needs. + +### How is this different from the built-in service resource? + +Chef includes a `service` resource which allows interacting with certain +service management frameworks such as SysV, Upstart, and systemd. +`poise-service` goes further in that it actually generates the configuration +files needed for the requested service management framework, as well as offering +a dependency injection system for application cookbooks to customize which +framework is used. + +### What service management frameworks are supported? + +* [SysV (aka /etc/init.d)](#sysvinit) +* [Upstart](#upstart) +* [systemd](#systemd) +* [Inittab](#inittab) +* [Runit](https://github.com/poise/poise-service-runit) +* [Monit](https://github.com/poise/poise-monit#service-provider) +* [Solaris](https://github.com/sh9189/poise-service-solaris) +* [AIX](https://github.com/johnbellone/poise-service-aix) +* *Supervisor (coming soon!)* + + +## Quick Start + +To create a service user and a service to run Apache2: + +```ruby +poise_service_user 'www-data' + +poise_service 'apache2' do + command '/usr/sbin/apache2 -f /etc/apache2/apache2.conf -DFOREGROUND' + stop_signal 'WINCH' + reload_signal 'USR1' +end +``` + +or for a hypothetical Rails web application: + +```ruby +poise_service_user 'myapp' + +poise_service 'myapp-web' do + command 'bundle exec unicorn -p 8080' + user 'myapp' + directory '/srv/myapp' + environment RAILS_ENV: 'production' +end +``` + +## Resources + +### `poise_service` + +The `poise_service` resource is the abstract definition of a service. + +```ruby +poise_service 'myapp' do + command 'myapp --serve' + environment RAILS_ENV: 'production' +end +``` + +#### Actions + +* `:enable` – Create, enable and start the service. *(default)* +* `:disable` – Stop, disable, and destroy the service. +* `:start` – Start the service. +* `:stop` – Stop the service. +* `:restart` – Stop and then start the service. +* `:reload` – Send the configured reload signal to the service. + +#### Attributes + +* `service_name` – Name of the service. *(name attribute)* +* `command` – Command to run for the service. This command must stay in the + foreground and not daemonize itself. *(required)* +* `user` – User to run the service as. See + [`poise_service_user`](#poise_service_user) for any easy way to create service + users. *(default: root)* +* `directory` – Working directory for the service. *(default: home directory for + user, or / if not found)* +* `environment` – Environment variables for the service. +* `stop_signal` – Signal to use to stop the service. Some systems will fall back + to SIGKILL if this signal fails to stop the process. *(default: TERM)* +* `reload_signal` – Signal to use to reload the service. *(default: HUP)* +* `restart_on_update` – If true, the service will be restarted if the service + definition or configuration changes. If `'immediately'`, the notification will + happen in immediate mode. *(default: true)* + +#### Service Options + +The `poise-service` library offers an additional way to pass configuration +information to the final service called "options". Options are key/value pairs +that are passed down to the service provider and can be used to control how it +creates and manages the service. These can be set in the `poise_service` +resource using the `options` method, in node attributes or via the +`poise_service_options` resource. The options from all sources are merged +together in to a single hash. + +When setting options in the resource you can either set them for all providers: + +```ruby +poise_service 'myapp' do + command 'myapp --serve' + options status_port: 8000 +end +``` + +or for a single provider: + +```ruby +poise_service 'myapp' do + command 'myapp --serve' + options :systemd, after_target: 'network' +end +``` + +Setting via node attributes is generally how an end-user or application cookbook +will set options to customize services in the library cookbooks they are using. +You can set options for all services or for a single service, by service name +or by resource name: + +```ruby +# Global, for all services. +override['poise-service']['options']['after_target'] = 'network' +# Single service. +override['poise-service']['myapp']['template'] = 'myapp.erb' +``` + +The `poise_service_options` resource is also available to set node attributes +for a specific service in a DSL-friendly way: + +```ruby +poise_service_options 'myapp' do + template 'myapp.erb' + restart_on_update false +end +``` + +Unlike resource attributes, service options can be different for each provider. +Not all providers support the same options so make sure to check the +documentation for each provider to see what options are available. + +### `poise_service_options` + +The `poise_service_options` resource allows setting per-service options in a +DSL-friendly way. See [the Service Options](#service-options) section for more +information about service options overall. + +```ruby +poise_service_options 'myapp' do + template 'myapp.erb' + restart_on_update false +end +``` + +#### Actions + +* `:run` – Apply the service options. *(default)* + +#### Attributes + +* `resource` – Name of the service. *(name attribute)* +* `for_provider` – Provider to set options for. + +All other attribute keys will be used as options data. + +### `poise_service_user` + +The `poise_service_user` resource is an easy way to create service users. It is +not required to use `poise_service`, it is only a helper. + +```ruby +poise_service_user 'myapp' do + home '/srv/myapp' +end +``` + +#### Actions + +* `:create` – Create the user and group. *(default)* +* `:remove` – Remove the user and group. + +#### Attributes + +* `user` – Name of the user. *(name attribute)* +* `group` – Name of the group. Set to `false` to disable group creation. *(name attribute)* +* `uid` – UID of the user. *(default: automatic)* +* `gid` – GID of the group. *(default: automatic)* +* `home` – Home directory of the user. +* `shell` – Shell of the user. *(default: /bin/nologin if present or /bin/false)* + +## Providers + +### `sysvinit` + +The `sysvinit` provider supports SystemV-style init systems on Debian-family and +RHEL-family platforms. It will create the `/etc/init.d/` script +and enable/disable the service using the platform-specific service resource. + +```ruby +poise_service 'myapp' do + provider :sysvinit + command 'myapp --serve' +end +``` + +By default a PID file will be created in `/var/run/service_name.pid`. You can +use the `pid_file` option detailed below to override this and rely on your +process creating a PID file in the given path. + +#### Options + +* `pid_file` – Path to PID file that the service command will create. +* `pid_file_external` – If true, assume the service will create the PID file + itself. *(default: true if `pid_file` option is set)* +* `template` – Override the default script template. If you want to use a + template in a different cookbook use `'cookbook:template'`. +* `command` – Override the service command. +* `directory` – Override the service directory. +* `environment` – Override the service environment variables. +* `reload_signal` – Override the service reload signal. +* `stop_signal` – Override the service stop signal. +* `user` – Override the service user. +* `never_start` – Never try to start the service. +* `never_stop` – Never try to stop the service. +* `never_restart` – Never try to restart the service. +* `never_reload` – Never try to reload the service. +* `script_path` – Override the path to the generated service script. + +### `upstart` + +The `upstart` provider supports [Upstart](http://upstart.ubuntu.com/). It will +create the `/etc/init/service_name.conf` configuration. + +```ruby +poise_service 'myapp' do + provider :upstart + command 'myapp --serve' +end +``` + +As a wide variety of versions of Upstart are in use in various Linux +distributions, the provider does its best to identify which features are +available and provide shims as appropriate. Most of these should be invisible +however Upstart older than 1.10 does not support setting a `reload signal` so +only SIGHUP can be used. You can set a `reload_shim` option to enable an +internal implementaion of reloading to be used for signals other than SIGHUP, +however as this is implemented inside Chef code, running `initctl reload` would +still result in SIGHUP being sent. For this reason, the feature is disabled by +default and will throw an error if a reload signal other than SIGHUP is used. + +#### Options + +* `reload_shim` – Enable the reload signal shim. See above for a warning about + this feature. +* `template` – Override the default configuration template. If you want to use a + template in a different cookbook use `'cookbook:template'`. +* `command` – Override the service command. +* `directory` – Override the service directory. +* `environment` – Override the service environment variables. +* `reload_signal` – Override the service reload signal. +* `stop_signal` – Override the service stop signal. +* `user` – Override the service user. +* `never_start` – Never try to start the service. +* `never_stop` – Never try to stop the service. +* `never_restart` – Never try to restart the service. +* `never_reload` – Never try to reload the service. + +### `systemd` + +The `systemd` provider supports [systemd](http://www.freedesktop.org/wiki/Software/systemd/). +It will create the `/etc/systemd/system/service_name.service` configuration. + + +```ruby +poise_service 'myapp' do + provider :systemd + command 'myapp --serve' +end +``` + +#### Options + +* `template` – Override the default configuration template. If you want to use a + template in a different cookbook use `'cookbook:template'`. +* `command` – Override the service command. +* `directory` – Override the service directory. +* `environment` – Override the service environment variables. +* `reload_signal` – Override the service reload signal. +* `stop_signal` – Override the service stop signal. +* `user` – Override the service user. +* `never_start` – Never try to start the service. +* `never_stop` – Never try to stop the service. +* `never_restart` – Never try to restart the service. +* `never_reload` – Never try to reload the service. +* `auto_reload` – Run `systemctl daemon-reload` after changes to the unit file. *(default: true)* +* `restart_mode` – Restart mode for the generated service unit. *(default: on-failure)* + +### `inittab` + +The `inittab` provider supports managing services via `/etc/inittab` using +[SystemV Init](http://www.nongnu.org/sysvinit/). This can provide basic +process supervision even on very old *nix machines. + +```ruby +poise_service 'myapp' do + provider :inittab + command 'myapp --serve' +end +``` + +**NOTE:** Inittab does not allow stopping services, and they are started as soon +as they are enabled. + +#### Options + +* `never_start` – Never try to start the service. +* `never_stop` – Never try to stop the service. +* `never_restart` – Never try to restart the service. +* `never_reload` – Never try to reload the service. +* `pid_file` – Path to PID file that the service command will create. +* `service_id` – Unique 1-4 character tag for the service. Defaults to an + auto-generated hash based on the service name. If these collide, bad things + happen. Don't do that. + +### `dummy` + +The `dummy` provider supports launching services directly from Chef itself. +This is for testing purposes only and is entirely unsuitable for use in +production. This is mostly useful when used alongside kitchen-docker. + +```ruby +poise_service 'myapp' do + provider :dummy + command 'myapp --serve' +end +``` + +The service information is written to `/var/run`. The PID file is `service_name.pid`, +the command output is `service_name.out`, and the service parameters are in +`service_name.json`. + +#### Options + +* `never_start` – Never try to start the service. +* `never_stop` – Never try to stop the service. +* `never_restart` – Never try to restart the service. +* `never_reload` – Never try to reload the service. +* `restart_delay` – Number of seconds to wait between stop and start when + restarting. *(default: 1)* + +## ServiceMixin + +For the common case of a resource (LWRP or plain Ruby) that roughly maps to +"some config files and a service" poise-service provides a mixin module, +`PoiseService::ServiceMixin`. This mixin adds the standard service actions +(`enable`, `disable`, `start`, `stop`, `restart`, and `reload`) with basic +implementations that call those actions on a `poise_service` resource for you. +You customize the service by defining a `service_options` method on your +provider class: + +```ruby +def service_options(service) + # service is the PoiseService::Resource object instance. + service.command "/usr/sbin/#{new_resource.name} -f /etc/#{new_resource.name}/conf/httpd.conf -DFOREGROUND" + service.stop_signal 'WINCH' + service.reload_signal 'USR1' +end +``` + +You will generally want to override the `enable` action to install things +related to the service like packages, users and configuration files: + +```ruby +def action_enable + notifying_block do + package 'apache2' + poise_service_user 'www-data' + template "/etc/#{new_resource.name}/conf/httpd.conf" do + # ... + end + end + # This super call will run the normal service enable, + # creating the service and starting it. + super +end +``` + +See [the poise_service_test_mixin resource](test/cookbooks/poise-service_test/resources/mixin.rb) +and [provider](test/cookbooks/poise-service_test/providers/mixin.rb) for +examples of using `ServiceMixin` in an LWRP. + +## Sponsors + +Development sponsored by [Bloomberg](http://www.bloomberg.com/company/technology/). + +The Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/). + +## License + +Copyright 2015-2016, Noah Kantrowitz + +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/cookbooks/poise-service/attributes/default.rb b/cookbooks/poise-service/attributes/default.rb new file mode 100644 index 0000000..2e8490d --- /dev/null +++ b/cookbooks/poise-service/attributes/default.rb @@ -0,0 +1,19 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +default['poise-service']['provider'] = 'auto' + +default['poise-service']['options'] = {} diff --git a/cookbooks/poise-service/files/halite_gem/poise_service.rb b/cookbooks/poise-service/files/halite_gem/poise_service.rb new file mode 100644 index 0000000..ad2ec60 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service.rb @@ -0,0 +1,25 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + + +module PoiseService + autoload :Error, 'poise_service/error' + autoload :Resources, 'poise_service/resources' + autoload :ServiceMixin, 'poise_service/service_mixin' + autoload :ServiceProviders, 'poise_service/service_providers' + autoload :Utils, 'poise_service/utils' + autoload :VERSION, 'poise_service/version' +end diff --git a/cookbooks/poise-service/files/halite_gem/poise_service/cheftie.rb b/cookbooks/poise-service/files/halite_gem/poise_service/cheftie.rb new file mode 100644 index 0000000..31d59db --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/cheftie.rb @@ -0,0 +1,18 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise_service/resources' +require 'poise_service/service_providers' diff --git a/cookbooks/poise-service/files/halite_gem/poise_service/error.rb b/cookbooks/poise-service/files/halite_gem/poise_service/error.rb new file mode 100644 index 0000000..5029795 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/error.rb @@ -0,0 +1,20 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +module PoiseService + class Error < ::Exception + end +end diff --git a/cookbooks/poise-service/files/halite_gem/poise_service/resources.rb b/cookbooks/poise-service/files/halite_gem/poise_service/resources.rb new file mode 100644 index 0000000..b0e1ddb --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/resources.rb @@ -0,0 +1,27 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise_service/resources/poise_service' +require 'poise_service/resources/poise_service_user' + + +module PoiseService + # Chef resources and providers for poise-service. + # + # @since 1.0.0 + module Resources + end +end diff --git a/cookbooks/poise-service/files/halite_gem/poise_service/resources/poise_service.rb b/cookbooks/poise-service/files/halite_gem/poise_service/resources/poise_service.rb new file mode 100644 index 0000000..157a584 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/resources/poise_service.rb @@ -0,0 +1,165 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'etc' + +require 'chef/mash' +require 'chef/resource' +require 'poise' + +require 'poise_service/error' + + +module PoiseService + module Resources + # (see PoiseService::Resource) + module PoiseService + # `poise_service` resource. Provides a unified service interface with a + # dependency injection framework. + # + # @since 1.0.0 + # @provides poise_service + # @action enable + # @action disable + # @action start + # @action stop + # @action restart + # @action reload + # @example + # poise_service 'myapp' do + # command 'myapp --serve' + # user 'myuser' + # directory '/home/myapp' + # end + class Resource < Chef::Resource + include Poise(inversion: true) + provides(:poise_service) + actions(:enable, :disable, :start, :stop, :restart, :reload) + + # @!attribute service_name + # Name of the service to the underlying init system. Defaults to the name + # of the resource. + # @return [String] + attribute(:service_name, kind_of: String, name_attribute: true) + # @!attribute command + # Command to run inside the service. This command must remain in the + # foreground and not daemoinize itself. + # @return [String] + attribute(:command, kind_of: String, required: true) + # @!attribute user + # User to run the service as. See {UserResource} for an easy way to + # create service users. Defaults to root. + # @return [String] + attribute(:user, kind_of: String, default: 'root') + # @!attribute directory + # Working directory for the service. Defaults to the home directory of + # the configured user or / if not found. + # @return [String] + attribute(:directory, kind_of: String, default: lazy { default_directory }) + # @!attribute environment + # Environment variables for the service. + # @return [Hash] + attribute(:environment, kind_of: Hash, default: lazy { Mash.new }) + # @!attribute stop_signal + # Signal to use to stop the service. Some systems will fall back to + # KILL if this signal fails to stop the process. Defaults to TERM. + # @return [String, Symbol, Integer] + attribute(:stop_signal, kind_of: [String, Symbol, Integer], default: 'TERM') + # @!attribute reload_signal + # Signal to use to reload the service. Defaults to HUP. + # @return [String, Symbol, Integer] + attribute(:reload_signal, kind_of: [String, Symbol, Integer], default: 'HUP') + # @!attribute restart_on_update + # If true, the service will be restarted if the service definition or + # configuration changes. If 'immediately', the notification will happen + # in immediate mode. + # @return [Boolean, String] + attribute(:restart_on_update, equal_to: [true, false, 'immediately', :immediately], default: true) + + # Resource DSL callback. + # + # @api private + def after_created + # Set signals to clean values. + stop_signal(clean_signal(stop_signal)) + reload_signal(clean_signal(reload_signal)) + end + + # Return the PID of the main process for this service or nil if the service + # isn't running or the PID cannot be found. + # + # @return [Integer, nil] + # @example + # execute "kill -WINCH #{resources('poise_test[myapp]').pid}" + def pid + # :pid isn't a real action, but this should still work. + provider_for_action(:pid).pid + end + + private + + # Try to find the home diretory for the configured user. This will fail if + # nsswitch.conf was changed during this run such as with LDAP. Defaults to + # the system root directory. + # + # @see #directory + # @return [String] + def default_directory + # Default fallback. + sysroot = case node['platform_family'] + when 'windows' + ENV.fetch('SystemRoot', 'C:\\') + else + '/' + end + # For root we always want the system root path. + return sysroot if user == 'root' + # Force a reload in case any users were created earlier in the run. + Etc.endpwent + # ArgumentError means we can't find the user, possibly nsswitch caching? + home = begin + Dir.home(user) + rescue ArgumentError + sysroot + end + # If the home doesn't exist or is empty, use sysroot. + home = sysroot if home.empty? || !::File.directory?(home) + home + end + + # Clean up a signal string/integer. Ints are mapped to the signal name, + # and strings are reformatted to upper case and without the SIG. + # + # @see #stop_signal + # @param signal [String, Symbol, Integer] Signal value to clean. + # @return [String] + def clean_signal(signal) + if signal.is_a?(Integer) + raise Error.new("Unknown signal #{signal}") unless (0..31).include?(signal) + Signal.signame(signal) + else + short_sig = signal.to_s.upcase + short_sig = short_sig[3..-1] if short_sig.start_with?('SIG') + raise Error.new("Unknown signal #{signal}") unless Signal.list.include?(short_sig) + short_sig + end + end + + # Providers can be found under service_providers/. + end + end + end +end diff --git a/cookbooks/poise-service/files/halite_gem/poise_service/resources/poise_service_test.rb b/cookbooks/poise-service/files/halite_gem/poise_service/resources/poise_service_test.rb new file mode 100644 index 0000000..393ae21 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/resources/poise_service_test.rb @@ -0,0 +1,240 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/resource' +require 'chef/provider' +require 'poise' + + +module PoiseService + module Resources + # (see PoiseServiceTest::Resource) + module PoiseServiceTest + # A `poise_service_test` resource for integration testing service providers. + # This is used in Test-Kitchen tests to ensure all providers behave + # similarly. + # + # @since 1.0.0 + # @provides poise_service_test + # @action run + # @example + # poise_service_test 'upstart' do + # service_provider :upstart + # base_port 5000 + # end + class Resource < Chef::Resource + include Poise + provides(:poise_service_test) + actions(:run) + + # @!attribute service_provider + # Service provider to set for the test group. + # @return [Symbol] + attribute(:service_provider, kind_of: Symbol) + # @!attribute service_options + # Service options to set for the test group. + # @return [Hash, nil] + attribute(:service_options, kind_of: [Hash, NilClass]) + # @!attribute base_port + # Port number to start from for the test group. + # @return [Integer] + attribute(:base_port, kind_of: Integer) + end + + # Provider for `poise_service_test`. + # + # @see Resource + # @provides poise_service_test + class Provider < Chef::Provider + include Poise + provides(:poise_service_test) + + SERVICE_SCRIPT = <<-EOH +require 'webrick' +require 'json' +require 'etc' +FILE_DATA = '' +server = WEBrick::HTTPServer.new(Port: ARGV[0].to_i) +server.mount_proc '/' do |req, res| + res.body = { + directory: Dir.getwd, + user: Etc.getpwuid(Process.uid).name, + euser: Etc.getpwuid(Process.euid).name, + group: Etc.getgrgid(Process.gid).name, + egroup: Etc.getgrgid(Process.egid).name, + environment: ENV.to_hash, + file_data: FILE_DATA, + pid: Process.pid, + }.to_json +end +EOH + + # `run` action for `poise_service_test`. Create all test services. + # + # @return [void] + def action_run + notifying_block do + create_script + create_noterm_script + create_user + create_tests + end + end + + private + + def create_script + file '/usr/bin/poise_test' do + owner 'root' + group 'root' + mode '755' + content <<-EOH +#!/opt/chef/embedded/bin/ruby +#{SERVICE_SCRIPT} +def load_file + FILE_DATA.replace(IO.read(ARGV[1])) +end +if ARGV[1] + load_file + trap('HUP') do + load_file + end +end +server.start +EOH + end + end + + def create_noterm_script + file '/usr/bin/poise_test_noterm' do + owner 'root' + group 'root' + mode '755' + content <<-EOH +#!/opt/chef/embedded/bin/ruby +trap('HUP', 'IGNORE') +trap('TERM', 'IGNORE') +#{SERVICE_SCRIPT} +while true + begin + server.start + rescue Exception + rescue StandardError + end +end +EOH + end + end + + def create_user + poise_service_user 'poise' do + home '/tmp' + end + end + + def create_tests + poise_service "poise_test_#{new_resource.name}" do + if new_resource.service_provider + provider new_resource.service_provider + options new_resource.service_provider, new_resource.service_options if new_resource.service_options + end + command "/usr/bin/poise_test #{new_resource.base_port}" + end + + poise_service "poise_test_#{new_resource.name}_params" do + if new_resource.service_provider + provider new_resource.service_provider + options new_resource.service_provider, new_resource.service_options if new_resource.service_options + end + command "/usr/bin/poise_test #{new_resource.base_port + 1}" + environment POISE_ENV: new_resource.name + user 'poise' + end + + poise_service "poise_test_#{new_resource.name}_noterm" do + if new_resource.service_provider + provider new_resource.service_provider + options new_resource.service_provider, new_resource.service_options if new_resource.service_options + end + action [:enable, :disable] + command "/usr/bin/poise_test_noterm #{new_resource.base_port + 2}" + stop_signal 'kill' + end + + {'restart' => 3, 'reload' => 4}.each do |action, port| + # Stop it before writing the file so we always start with first. + poise_service "poise_test_#{new_resource.name}_#{action} stop" do + if new_resource.service_provider + provider new_resource.service_provider + options new_resource.service_provider, new_resource.service_options if new_resource.service_options + end + action(:disable) + service_name "poise_test_#{new_resource.name}_#{action}" + end + + # Write the content to the read on service launch. + file "/etc/poise_test_#{new_resource.name}_#{action}" do + content 'first' + end + + # Launch the service, reading in first. + poise_service "poise_test_#{new_resource.name}_#{action}" do + if new_resource.service_provider + provider new_resource.service_provider + options new_resource.service_provider, new_resource.service_options if new_resource.service_options + end + command "/usr/bin/poise_test #{new_resource.base_port + port} /etc/poise_test_#{new_resource.name}_#{action}" + end + + # Rewrite the file to second, restart/reload to trigger an update. + file "/etc/poise_test_#{new_resource.name}_#{action} again" do + path "/etc/poise_test_#{new_resource.name}_#{action}" + content 'second' + notifies action.to_sym, "poise_service[poise_test_#{new_resource.name}_#{action}]" + end + end + + # Test the #pid accessor. + ruby_block "/tmp/poise_test_#{new_resource.name}_pid" do + block do + pid = resources("poise_service[poise_test_#{new_resource.name}]").pid + IO.write("/tmp/poise_test_#{new_resource.name}_pid", pid.to_s) + end + end + + # Test changing the service definition itself. + poise_service "poise_test_#{new_resource.name}_change" do + if new_resource.service_provider + provider new_resource.service_provider + options new_resource.service_provider, new_resource.service_options if new_resource.service_options + end + command "/usr/bin/poise_test #{new_resource.base_port + 5}" + end + + poise_service "poise_test_#{new_resource.name}_change_second" do + service_name "poise_test_#{new_resource.name}_change" + if new_resource.service_provider + provider new_resource.service_provider + options new_resource.service_provider, new_resource.service_options if new_resource.service_options + end + command "/usr/bin/poise_test #{new_resource.base_port + 6}" + end + + end + end + end + end +end diff --git a/cookbooks/poise-service/files/halite_gem/poise_service/resources/poise_service_user.rb b/cookbooks/poise-service/files/halite_gem/poise_service/resources/poise_service_user.rb new file mode 100644 index 0000000..6d4eac4 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/resources/poise_service_user.rb @@ -0,0 +1,186 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/resource' +require 'chef/provider' +require 'poise' + + +module PoiseService + module Resources + # (see PoiseServiceUser::Resource) + # @since 1.0.0 + module PoiseServiceUser + # Shells to look for in order. + # @api private + DEFAULT_SHELLS = %w{/bin/nologin /usr/bin/nologin /bin/false} + + # A `poise_service_user` resource to create service users/groups. + # + # @since 1.0.0 + # @provides poise_service_user + # @action create + # @action remove + # @example + # poise_service_user 'myapp' do + # home '/var/tmp' + # group 'nogroup' + # end + class Resource < Chef::Resource + include Poise + provides(:poise_service_user) + actions(:create, :remove) + + # @!attribute user + # Name of the user to create. Defaults to the name of the resource. + # @return [String] + attribute(:user, kind_of: String, name_attribute: true) + # @!attribute group + # Name of the group to create. Defaults to the name of the user, + # except on Windows where it defaults to false. Set to false to + # disable group creation. + # @return [String, false] + attribute(:group, kind_of: [String, FalseClass], default: lazy { default_group }) + # @!attribute uid + # UID of the user to create. Optional, if not set the UID will be + # allocated automatically. + # @return [Integer] + attribute(:uid, kind_of: Integer) + # @!attribute gid + # GID of the group to create. Optional, if not set the GID will be + # allocated automatically. + # @return [Integer] + attribute(:gid, kind_of: Integer) + # @!attribute shell + # Login shell for the user. Optional, if not set the shell will be + # determined automatically. + # @return [String] + attribute(:shell, kind_of: String, default: lazy { default_shell }) + # @!attribute home + # Home directory of the user. This directory will not be created if it + # does not exist. Optional. + # @return [String] + attribute(:home, kind_of: String) + + private + + # Find a default shell for service users. Tries to use nologin, but fall + # back on false. + # + # @api private + # @return [String] + def default_shell + DEFAULT_SHELLS.find {|s| ::File.exist?(s) } || DEFAULT_SHELLS.last + end + + # Find the default group name. Returns false on Windows because service + # groups aren't needed there. Otherwise use the name of the service user. + # + # @api private + # @return [String, false] + def default_group + if node.platform_family?('windows') + false + else + user + end + end + end + + # Provider for `poise_service_user`. + # + # @since 1.0.0 + # @see Resource + # @provides poise_service_user + class Provider < Chef::Provider + include Poise + provides(:poise_service_user) + + # `create` action for `poise_service_user`. Ensure the user and group (if + # enabled) exist. + # + # @return [void] + def action_create + notifying_block do + create_group if new_resource.group + create_user + end + end + + # `remove` action for `poise_service_user`. Ensure the user and group (if + # enabled) are destroyed. + # + # @return [void] + def action_remove + notifying_block do + remove_user + remove_group if new_resource.group + end + end + + private + + # Create the system group. + # + # @api private + # @return [void] + def create_group + group new_resource.group do + gid new_resource.gid + # Solaris doesn't support the idea of system groups. + system true unless node.platform_family?('solaris2') + end + end + + # Create the system user. + # + # @api private + # @return [void] + def create_user + user new_resource.user do + comment "Service user for #{new_resource.name}" + gid new_resource.group if new_resource.group + home new_resource.home + shell new_resource.shell + # Solaris doesn't support the idea of system users. + system true unless node.platform_family?('solaris2') + uid new_resource.uid + end + end + + # Remove the system group. + # + # @api private + # @return [void] + def remove_group + create_group.tap do |r| + r.action(:remove) + end + end + + # Remove the system user. + # + # @api private + # @return [void] + def remove_user + create_user.tap do |r| + r.action(:remove) + end + end + end + end + end +end diff --git a/cookbooks/poise-service/files/halite_gem/poise_service/service_mixin.rb b/cookbooks/poise-service/files/halite_gem/poise_service/service_mixin.rb new file mode 100644 index 0000000..41c2472 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/service_mixin.rb @@ -0,0 +1,193 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise' + +require 'poise_service/resources/poise_service' + + +module PoiseService + # Mixin for application services. This is any resource that will be part of + # an application deployment and involves running a persistent service. + # + # @since 1.0.0 + # @example + # module MyApp + # class Resource < Chef::Resource + # include Poise + # provides(:my_app) + # include PoiseService::ServiceMixin + # end + # + # class Provider < Chef::Provider + # include Poise + # provides(:my_app) + # include PoiseService::ServiceMixin + # + # def action_enable + # notifying_block do + # template '/etc/myapp.conf' do + # # ... + # end + # end + # super + # end + # + # def service_options(r) + # r.command('myapp --serve') + # end + # end + # end + module ServiceMixin + include Poise::Utils::ResourceProviderMixin + + # Mixin for service wrapper resources. + # + # @see ServiceMixin + module Resource + include Poise::Resource + + module ClassMethods + # @api private + def included(klass) + super + klass.extend(ClassMethods) + klass.class_exec do + actions(:enable, :disable, :start, :stop, :restart, :reload) + attribute(:service_name, kind_of: String, name_attribute: true) + end + end + end + + extend ClassMethods + end + + # Mixin for service wrapper providers. + # + # @see ServiceMixin + module Provider + include Poise::Provider + + # Default enable action for service wrappers. + # + # @return [void] + def action_enable + notify_if_service do + service_resource.run_action(:enable) + end + end + + # Default disable action for service wrappers. + # + # @return [void] + def action_disable + notify_if_service do + service_resource.run_action(:disable) + end + end + + # Default start action for service wrappers. + # + # @return [void] + def action_start + notify_if_service do + service_resource.run_action(:start) + end + end + + # Default stop action for service wrappers. + # + # @return [void] + def action_stop + notify_if_service do + service_resource.run_action(:stop) + end + end + + # Default restart action for service wrappers. + # + # @return [void] + def action_restart + notify_if_service do + service_resource.run_action(:restart) + end + end + + # Default reload action for service wrappers. + # + # @return [void] + def action_reload + notify_if_service do + service_resource.run_action(:reload) + end + end + + # @todo Add reload once poise-service supports it. + + private + + # Set the current resource as notified if the provided block updates the + # service resource. + # + # @api public + # @param block [Proc] Block to run. + # @return [void] + # @example + # notify_if_service do + # service_resource.run_action(:enable) + # end + def notify_if_service(&block) + service_resource.updated_by_last_action(false) + block.call if block + new_resource.updated_by_last_action(true) if service_resource.updated_by_last_action? + end + + # Service resource for this service wrapper. This returns a + # poise_service resource that will not be added to the resource + # collection. Override {#service_options} to set service resource + # parameters. + # + # @api public + # @return [Chef::Resource] + # @example + # service_resource.run_action(:restart) + def service_resource + @service_resource ||= PoiseService::Resources::PoiseService::Resource.new(new_resource.name, run_context).tap do |r| + # Set some defaults. + r.declared_type = :poise_service + r.enclosing_provider = self + r.source_line = new_resource.source_line + r.service_name(new_resource.service_name) + # Call the subclass hook for more specific settings. + service_options(r) + end + end + + # Abstract hook to set parameters on {#service_resource} when it is + # created. This is required to set at least `resource.command`. + # + # @api public + # @param resource [Chef::Resource] Resource instance to set parameters on. + # @return [void] + # @example + # def service_options(resource) + # resource.command('myapp --serve') + # end + def service_options(resource) + end + end + end +end diff --git a/cookbooks/poise-service/files/halite_gem/poise_service/service_providers.rb b/cookbooks/poise-service/files/halite_gem/poise_service/service_providers.rb new file mode 100644 index 0000000..6cee1ae --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/service_providers.rb @@ -0,0 +1,38 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/platform/provider_priority_map' + +require 'poise_service/service_providers/dummy' +require 'poise_service/service_providers/inittab' +require 'poise_service/service_providers/systemd' +require 'poise_service/service_providers/sysvinit' +require 'poise_service/service_providers/upstart' + + +module PoiseService + # Inversion providers for the poise_service resource. + # + # @since 1.0.0 + module ServiceProviders + # Set up priority maps + Chef::Platform::ProviderPriorityMap.instance.priority(:poise_service, [ + PoiseService::ServiceProviders::Systemd, + PoiseService::ServiceProviders::Upstart, + PoiseService::ServiceProviders::Sysvinit, + ]) + end +end diff --git a/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/base.rb b/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/base.rb new file mode 100644 index 0000000..31263d4 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/base.rb @@ -0,0 +1,196 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/provider' +require 'poise' + + +module PoiseService + module ServiceProviders + class Base < Chef::Provider + include Poise(inversion: :poise_service) + + # Extend the default lookup behavior to check for service_name too. + # + # @api private + def self.resolve_inversion_provider(node, resource) + attrs = resolve_inversion_attribute(node) + (attrs[resource.service_name] && attrs[resource.service_name]['provider']) || super + end + + # Extend the default options to check for service_name too. + # + # @api private + def self.inversion_options(node, resource) + super.tap do |opts| + attrs = resolve_inversion_attribute(node) + opts.update(attrs[resource.service_name]) if attrs[resource.service_name] + run_state = Mash.new(node.run_state.fetch('poise_inversion', {}).fetch(inversion_resource, {}))[resource.service_name] || {} + opts.update(run_state['*']) if run_state['*'] + opts.update(run_state[provides]) if run_state[provides] + end + end + + # Cache the service hints to improve performance. This is called from the + # provides_auto? on most service providers and hits the filesystem a lot. + # + # @return [Array] + def self.service_resource_hints + @@service_resource_hints ||= Chef::Platform::ServiceHelpers.service_resource_providers + end + + def action_enable + include_recipe(*Array(recipes)) if recipes + notifying_block do + create_service + end + enable_service + action_start + end + + def action_disable + action_stop + disable_service + notifying_block do + destroy_service + end + end + + def action_start + return if options['never_start'] + notify_if_service do + service_resource.run_action(:start) + end + end + + def action_stop + return if options['never_stop'] + notify_if_service do + service_resource.run_action(:stop) + end + end + + def action_restart + return if options['never_restart'] + notify_if_service do + service_resource.run_action(:restart) + end + end + + def action_reload + return if options['never_reload'] + notify_if_service do + service_resource.run_action(:reload) + end + end + + def pid + raise NotImplementedError + end + + private + + # Recipes to include for this provider to work. Subclasses can override. + # + # @return [String, Array] + def recipes + end + + # Subclass hook to create the required files et al for the service. + def create_service + raise NotImplementedError + end + + # Subclass hook to remove the required files et al for the service. + def destroy_service + raise NotImplementedError + end + + def enable_service + notify_if_service do + service_resource.run_action(:enable) + end + end + + def disable_service + notify_if_service do + service_resource.run_action(:disable) + end + end + + def notify_if_service(&block) + service_resource.updated_by_last_action(false) + block.call + new_resource.updated_by_last_action(true) if service_resource.updated_by_last_action? + end + + # Subclass hook to create the resource used to delegate start, stop, and + # restart actions. + def service_resource + @service_resource ||= Chef::Resource::Service.new(new_resource.service_name, run_context).tap do |r| + r.declared_type = :service + r.enclosing_provider = self + r.source_line = new_resource.source_line + r.supports(status: true, restart: true, reload: true) + end + end + + def service_template(path, default_source, &block) + # Sigh scoping. + template path do + owner 'root' + group node['root_group'] + mode '644' + if options['template'] + # If we have a template override, allow specifying a cookbook via + # "cookbook:template". + parts = options['template'].split(/:/, 2) + if parts.length == 2 + source parts[1] + cookbook parts[0] + else + source parts.first + cookbook new_resource.cookbook_name.to_s + end + else + source default_source + cookbook self.poise_defined_in_cookbook + end + variables( + command: options['command'] || new_resource.command, + directory: options['directory'] || new_resource.directory, + environment: options['environment'] || new_resource.environment, + name: new_resource.service_name, + new_resource: new_resource, + options: options, + reload_signal: options['reload_signal'] || new_resource.reload_signal, + stop_signal: options['stop_signal'] || new_resource.stop_signal, + user: options['user'] || new_resource.user, + ) + # Don't trigger a restart if the template doesn't already exist, this + # prevents restarting on the run that first creates the service. + restart_on_update = options.fetch('restart_on_update', new_resource.restart_on_update) + if restart_on_update && ::File.exist?(path) + mode = restart_on_update.to_s == 'immediately' ? :immediately : :delayed + notifies :restart, new_resource, mode + end + instance_exec(&block) if block + end + end + + end + end +end diff --git a/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/dummy.rb b/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/dummy.rb new file mode 100644 index 0000000..0a84ec5 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/dummy.rb @@ -0,0 +1,195 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'etc' +require 'shellwords' + +require 'poise_service/service_providers/base' + + +module PoiseService + module ServiceProviders + class Dummy < Base + provides(:dummy) + + # @api private + def self.default_inversion_options(node, resource) + super.merge({ + # Time to wait between stop and start. + restart_delay: 1, + }) + end + + def action_start + return if options['never_start'] + return if pid + Chef::Log.debug("[#{new_resource}] Starting #{new_resource.command}") + # Clear the pid file if it exists. + ::File.unlink(pid_file) if ::File.exist?(pid_file) + if Process.fork + # Parent, wait for the final child to write the pid file. + now = Time.now + until ::File.exist?(pid_file) + sleep(1) + # After 30 seconds, show output at a higher level to avoid too much + # confusing on failed process launches. + if Time.now - now <= 30 + Chef::Log.debug("[#{new_resource}] Waiting for PID file") + else + Chef::Log.warning("[#{new_resource}] Waiting for PID file at #{pid_file} to be created") + end + end + else + # :nocov: + begin + Chef::Log.debug("[#{new_resource}] Forked") + # First child, daemonize and go to town. This handles multi-fork, + # setsid, and shutting down stdin/out/err. + Process.daemon(true) + Chef::Log.debug("[#{new_resource}] Daemonized") + # Daemonized, set up process environment. + Dir.chdir(new_resource.directory) + Chef::Log.debug("[#{new_resource}] Directory changed to #{new_resource.directory}") + ENV['HOME'] = Dir.home(new_resource.user) + new_resource.environment.each do |key, val| + ENV[key.to_s] = val.to_s + end + Chef::Log.debug("[#{new_resource}] Process environment configured") + # Make sure to open the output file and write the pid file before we + # drop privs. + output = ::File.open(output_file, 'ab') + IO.write(pid_file, Process.pid) + Chef::Log.debug("[#{new_resource}] PID #{Process.pid} written to #{pid_file}") + ent = Etc.getpwnam(new_resource.user) + if Process.euid != ent.uid || Process.egid != ent.gid + Process.initgroups(ent.name, ent.gid) + Process::GID.change_privilege(ent.gid) if Process.egid != ent.gid + Process::UID.change_privilege(ent.uid) if Process.euid != ent.uid + Chef::Log.debug("[#{new_resource}] Changed privs to #{new_resource.user} (#{ent.uid}:#{ent.gid})") + end + # Log the command. Happens before ouput redirect or this ends up in the file. + Chef::Log.debug("[#{new_resource}] Execing #{new_resource.command}") + # Set up output logging. + Chef::Log.debug("[#{new_resource}] Logging output to #{output_file}") + $stdout.reopen(output) + $stdout.sync = true + $stderr.reopen(output) + $stderr.sync = true + $stdout.write("#{Time.now} Starting #{new_resource.command}") + # Split the command so we don't get an extra sh -c. + Kernel.exec(*Shellwords.split(new_resource.command)) + # Just in case, bail out. + $stdout.reopen(STDOUT) + $stderr.reopen(STDERR) + Chef::Log.debug("[#{new_resource}] Exec failed, bailing out.") + exit! + rescue Exception => e + # Welp, we tried. + $stdout.reopen(STDOUT) + $stderr.reopen(STDERR) + Chef::Log.error("[#{new_resource}] Error during process spawn: #{e}") + exit! + end + # :nocov: + end + Chef::Log.debug("[#{new_resource}] Started.") + end + + def action_stop + return if options['never_stop'] + return unless pid + Chef::Log.debug("[#{new_resource}] Stopping with #{new_resource.stop_signal}. Current PID is #{pid.inspect}.") + Process.kill(new_resource.stop_signal, pid) + ::File.unlink(pid_file) + end + + def action_restart + return if options['never_restart'] + action_stop + # Give things a moment to stop before we try starting again. + sleep(options['restart_delay']) + action_start + end + + def action_reload + return if options['never_reload'] + return unless pid + Chef::Log.debug("[#{new_resource}] Reloading with #{new_resource.reload_signal}. Current PID is #{pid.inspect}.") + Process.kill(new_resource.reload_signal, pid) + end + + def pid + return nil unless ::File.exist?(pid_file) + pid = IO.read(pid_file).to_i + begin + # Check if the PID is running. + Process.kill(0, pid) + pid + rescue Errno::ESRCH + nil + end + end + + private + + def service_resource + # Intentionally not implemented. + raise NotImplementedError + end + + def enable_service + end + + # Write all major service parameters to a file so that if they change, we + # can restart the service. This also makes debuggin a bit easier so you + # can still see what it thinks it was starting without sifting through + # piles of debug output. + def create_service + service_template(run_file, 'dummy.json.erb') + end + + def disable_service + end + + # Delete the tracking file. + def destroy_service + file run_file do + action :delete + end + + file pid_file do + action :delete + end + end + + # Path to the run parameters tracking file. + def run_file + "/var/run/#{new_resource.service_name}.json" + end + + # Path to the PID file. + def pid_file + "/var/run/#{new_resource.service_name}.pid" + end + + # Path to the output file. + def output_file + "/var/run/#{new_resource.service_name}.out" + end + + end + end +end diff --git a/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/inittab.rb b/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/inittab.rb new file mode 100644 index 0000000..4758455 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/inittab.rb @@ -0,0 +1,150 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/util/file_edit' + +require 'poise_service/service_providers/base' + + +module PoiseService + module ServiceProviders + class Inittab < Base + provides(:inittab) + + def self.provides_auto?(node, resource) + ::File.exist?('/etc/inittab') + end + + def pid + IO.read(pid_file).to_i if ::File.exist?(pid_file) + end + + # Don't try to stop when disabling because we can't. + def action_disable + disable_service + notifying_block do + destroy_service + end + end + + def action_start + Chef::Log.debug("[#{new_resource}] Inittab services are always started.") + end + + def action_stop + raise NotImplementedError.new("[#{new_resource}] Inittab services cannot be stopped") + end + + def action_restart + return if options['never_restart'] + # Just kill it and let init restart it. + Process.kill(new_resource.stop_signal, pid) if pid + end + + def action_reload + return if options['never_reload'] + Process.kill(new_resource.reload_signal, pid) if pid + end + + private + + def service_resource + # Intentionally not implemented. + raise NotImplementedError + end + + def enable_service + end + + def disable_service + end + + def create_service + # Sigh scoping. + pid_file_ = pid_file + # Inittab only allows 127 characters for the command, so cram stuff in + # a file. Writing to a file is gross, but so is using inittab so ¯\_(ツ)_/¯. + service_template("/sbin/poise_service_#{new_resource.service_name}", 'inittab.sh.erb') do + mode '755' + variables.update( + pid_file: pid_file_, + ) + end + # Add to inittab. + edit_inittab do |content| + inittab_line = "#{service_id}:2345:respawn:/sbin/poise_service_#{new_resource.service_name}" + if content =~ /^# #{Regexp.escape(service_tag)}$/ + # Existing line, update in place. + content.gsub!(/^(# #{Regexp.escape(service_tag)}\n)(.*)$/, "\\1#{inittab_line}") + else + # Add to the end. + content << "# #{service_tag}\n#{inittab_line}\n" + end + end + end + + def destroy_service + # Remove from inittab. + edit_inittab do |content| + content.gsub!(/^# #{Regexp.escape(service_tag)}\n.*?\n$/, '') + end + + file "/sbin/poise_service_#{new_resource.service_name}" do + action :delete + end + + file pid_file do + action :delete + end + end + + # The shortened ID because sysvinit only allows 4 characters. + def service_id + # This is a terrible hash, but it should be good enough. + options['service_id'] || begin + sum = new_resource.service_name.sum(20).to_s(36) + if sum.length < 4 + 'p' + sum + else + sum + end + end + end + + # Tag to put in a comment in inittab for tracking. + def service_tag + "poise_service(#{new_resource.service_name})" + end + + def pid_file + options['pid_file'] || "/var/run/#{new_resource.service_name}.pid" + end + + def edit_inittab(&block) + inittab = IO.read('/etc/inittab') + original_inittab = inittab.dup + block.call(inittab) + if inittab != original_inittab + file '/etc/inittab' do + content inittab + end + + execute 'telinit q' + end + end + end + end +end diff --git a/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/systemd.rb b/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/systemd.rb new file mode 100644 index 0000000..35faf03 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/systemd.rb @@ -0,0 +1,85 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/mixin/shell_out' + +require 'poise_service/service_providers/base' + + +module PoiseService + module ServiceProviders + class Systemd < Base + include Chef::Mixin::ShellOut + provides(:systemd) + + # @api private + def self.provides_auto?(node, resource) + service_resource_hints.include?(:systemd) + end + + # @api private + def self.default_inversion_options(node, resource) + super.merge({ + # Automatically reload systemd on changes. + auto_reload: true, + # Service restart mode. + restart_mode: 'on-failure', + }) + end + + def pid + cmd = shell_out(%w{systemctl status} + [new_resource.service_name]) + if !cmd.error? && cmd.stdout.include?('Active: active (running)') && md = cmd.stdout.match(/Main PID: (\d+)/) + md[1].to_i + else + nil + end + end + + private + + def service_resource + super.tap do |r| + r.provider(Chef::Provider::Service::Systemd) + end + end + + def systemctl_daemon_reload + execute 'systemctl daemon-reload' do + action :nothing + user 'root' + end + end + + def create_service + reloader = systemctl_daemon_reload + service_template("/etc/systemd/system/#{new_resource.service_name}.service", 'systemd.service.erb') do + notifies :run, reloader, :immediately if options['auto_reload'] + variables.update(auto_reload: options['auto_reload'], restart_mode: options['restart_mode']) + end + end + + def destroy_service + reloader = systemctl_daemon_reload + file "/etc/systemd/system/#{new_resource.service_name}.service" do + action :delete + notifies :run, reloader, :immediately if options['auto_reload'] + end + end + + end + end +end diff --git a/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/sysvinit.rb b/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/sysvinit.rb new file mode 100644 index 0000000..c9fb0e5 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/sysvinit.rb @@ -0,0 +1,97 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise_service/service_providers/base' + + +module PoiseService + module ServiceProviders + class Sysvinit < Base + provides(:sysvinit) + + def self.provides_auto?(node, resource) + [:debian, :redhat, :invokercd].any? {|name| service_resource_hints.include?(name) } + end + + def pid + IO.read(pid_file).to_i if ::File.exist?(pid_file) + end + + private + + def service_resource + super.tap do |r| + r.provider(case node['platform_family'] + when 'debian' + Chef::Provider::Service::Debian + when 'rhel', 'amazon' + Chef::Provider::Service::Redhat + else + # Better than nothing I guess? Will fail on enable I think. + Chef::Provider::Service::Init + end) + r.init_command(script_path) + # Pending https://github.com/chef/chef/pull/4709. + r.start_command("#{script_path} start") + r.stop_command("#{script_path} stop") + r.status_command("#{script_path} status") + r.restart_command("#{script_path} restart") + r.reload_command("#{script_path} reload") + end + end + + def create_service + # Split the command into the binary and its arguments. This is for + # start-stop-daemon since it treats those differently. + parts = new_resource.command.split(/ /, 2) + daemon = ENV['PATH'].split(/:/) + .map {|path| ::File.absolute_path(parts[0], path) } + .find {|path| ::File.exist?(path) } || parts[0] + # Sigh scoping. + pid_file_ = pid_file + # Render the service template + service_template(script_path, 'sysvinit.sh.erb') do + mode '755' + variables.update( + daemon: daemon, + daemon_options: parts[1].to_s, + pid_file: pid_file_, + pid_file_external: options['pid_file_external'].nil? ? !!options['pid_file'] : options['pid_file_external'], + platform_family: node['platform_family'], + ) + end + end + + def destroy_service + file script_path do + action :delete + end + + file pid_file do + action :delete + end + end + + def script_path + options['script_path'] || "/etc/init.d/#{new_resource.service_name}" + end + + def pid_file + options['pid_file'] || "/var/run/#{new_resource.service_name}.pid" + end + end + end +end diff --git a/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/upstart.rb b/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/upstart.rb new file mode 100644 index 0000000..cb4db46 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/upstart.rb @@ -0,0 +1,136 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +# Used in the template. +require 'shellwords' + +require 'chef/mixin/shell_out' + +require 'poise_service/error' +require 'poise_service/service_providers/base' + + +module PoiseService + module ServiceProviders + class Upstart < Base + include Chef::Mixin::ShellOut + provides(:upstart) + + def self.provides_auto?(node, resource) + service_resource_hints.include?(:upstart) + end + + # @api private + def self.default_inversion_options(node, resource) + super.merge({ + # Time to wait between stop and start. + restart_delay: 1, + }) + end + + # True restart in Upstart preserves the original config data, we want the + # more obvious behavior like everything else in the world that restart + # would re-read the updated config file. Use stop+start to get this + # behavior. http://manpages.ubuntu.com/manpages/raring/man8/initctl.8.html + def action_restart + return if options['never_restart'] + action_stop + # Give things a moment to stop before we try starting again. + sleep(options['restart_delay']) + action_start + end + + # Shim out reload if we have a version that predates reload support. + def action_reload + return if options['never_reload'] + if !upstart_features[:reload_signal] && new_resource.reload_signal != 'HUP' + if options[:reload_shim] + Process.kill(new_resource.reload_signal, pid) + else + check_reload_signal! + end + else + super + end + end + + def pid + cmd = shell_out(%w{initctl status} + [new_resource.service_name]) + if !cmd.error? && md = cmd.stdout.match(/process (\d+)/) + md[1].to_i + else + nil + end + end + + private + + def service_resource + super.tap do |r| + r.provider(Chef::Provider::Service::Upstart) + end + end + + def create_service + check_reload_signal! + # Set features so it will be a closure below. + features = upstart_features + service_template("/etc/init/#{new_resource.service_name}.conf", 'upstart.conf.erb') do + variables.update( + upstart_features: features, + ) + end + end + + def destroy_service + file "/etc/init/#{new_resource.service_name}.conf" do + action :delete + end + end + + def upstart_version + cmd = shell_out(%w{initctl --version}) + if !cmd.error? && md = cmd.stdout.match(/upstart ([^)]+)\)/) + md[1] + else + '0' + end + end + + def upstart_features + @upstart_features ||= begin + upstart_ver = Gem::Version.new(upstart_version) + versions_added = { + kill_signal: '1.3', + reload_signal: '1.10', + setuid: '1.4', + } + versions_added.inject({}) do |memo, (feature, version)| + memo[feature] = Gem::Requirement.create(">= #{version}").satisfied_by?(upstart_ver) + memo + end + end + end + + def check_reload_signal! + if !options['reload_shim'] && !upstart_features[:reload_signal] && new_resource.reload_signal != 'HUP' + raise Error.new("Upstart #{upstart_version} only supports HUP for reload, to use the shim please set the 'reload_shim' options for #{new_resource.to_s}") + end + end + + end + end +end diff --git a/cookbooks/poise-service/files/halite_gem/poise_service/utils.rb b/cookbooks/poise-service/files/halite_gem/poise_service/utils.rb new file mode 100644 index 0000000..bbf7896 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/utils.rb @@ -0,0 +1,45 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'pathname' + + +module PoiseService + # Utility methods for PoiseService. + # + # @api public + # @since 1.0.0 + module Utils + # Methods are also available as module-level methods as well as a mixin. + extend self + + # Common segments to ignore + COMMON_SEGMENTS = %w{var www current etc}.inject({}) {|memo, seg| memo[seg] = true; memo } + + # Parse the service name from a path. Look at the last component of the + # path, ignoring some common names. + # + # @param path [String] Path to parse. + # @return [String] + # @example + # attribute(:service_name, kind_of: String, default: lazy { PoiseService::Utils.parse_service_name(path) }) + def parse_service_name(path) + parts = Pathname.new(path).each_filename.to_a.reverse! + # Find the last segment not in common segments, fall back to the last segment. + parts.find {|seg| !COMMON_SEGMENTS[seg] } || parts.first + end + end +end diff --git a/cookbooks/poise-service/files/halite_gem/poise_service/version.rb b/cookbooks/poise-service/files/halite_gem/poise_service/version.rb new file mode 100644 index 0000000..f4c6463 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/version.rb @@ -0,0 +1,20 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + + +module PoiseService + VERSION = '1.5.2' +end diff --git a/cookbooks/poise-service/libraries/default.rb b/cookbooks/poise-service/libraries/default.rb new file mode 100644 index 0000000..dd4c6ca --- /dev/null +++ b/cookbooks/poise-service/libraries/default.rb @@ -0,0 +1,19 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +raise 'Halite is not compatible with no_lazy_load false, please set no_lazy_load true in your Chef configuration file.' unless Chef::Config[:no_lazy_load] +$LOAD_PATH << File.expand_path('../../files/halite_gem', __FILE__) +require "poise_service/cheftie" diff --git a/cookbooks/poise-service/metadata.json b/cookbooks/poise-service/metadata.json new file mode 100644 index 0000000..e71ef57 --- /dev/null +++ b/cookbooks/poise-service/metadata.json @@ -0,0 +1 @@ +{"name":"poise-service","version":"1.5.2","description":"A Chef cookbook for managing system services.","long_description":"# Poise-Service Cookbook\n\n[![Build Status](https://img.shields.io/travis/poise/poise-service.svg)](https://travis-ci.org/poise/poise-service)\n[![Gem Version](https://img.shields.io/gem/v/poise-service.svg)](https://rubygems.org/gems/poise-service)\n[![Cookbook Version](https://img.shields.io/cookbook/v/poise-service.svg)](https://supermarket.chef.io/cookbooks/poise-service)\n[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-service.svg)](https://codecov.io/github/poise/poise-service)\n[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-service.svg)](https://gemnasium.com/poise/poise-service)\n[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)\n\nA [Chef](https://www.chef.io/) cookbook to provide a unified interface for\nservices.\n\n### What is poise-service?\n\nPoise-service is a tool for developers of \"library cookbooks\" to define a\nservice without forcing the end-user of the library to adhere to their choice of\nservice management framework. The `poise_service` resource represents an\nabstract service to be run, which can then be customized by node attributes and\nthe `poise_service_options` resource. This is a technique called [dependency\ninjection](https://en.wikipedia.org/wiki/Dependency_injection), and allows a\nmeasure of decoupling between the library and application cookbooks.\n\n### Why would I use poise-service?\n\nPoise-service is most useful for authors of library-style cookbooks, for example\nthe `apache2`, `mysql`, or `application` cookbooks. When using other service\nmanagement options with Chef, the author of the library cookbook has to add\nspecific code for each service management framework they want to support, often\nresulting in a cookbook only supporting the favorite framework of the author or\ndepending on distribution packages for their init scripts. The `poise_service`\nresource allows library cookbook authors a way to write generic code for all\nservice management frameworks while still allowing users of that cookbook to\nchoose which service management framework best fits their needs.\n\n### How is this different from the built-in service resource?\n\nChef includes a `service` resource which allows interacting with certain\nservice management frameworks such as SysV, Upstart, and systemd.\n`poise-service` goes further in that it actually generates the configuration\nfiles needed for the requested service management framework, as well as offering\na dependency injection system for application cookbooks to customize which\nframework is used.\n\n### What service management frameworks are supported?\n\n* [SysV (aka /etc/init.d)](#sysvinit)\n* [Upstart](#upstart)\n* [systemd](#systemd)\n* [Inittab](#inittab)\n* [Runit](https://github.com/poise/poise-service-runit)\n* [Monit](https://github.com/poise/poise-monit#service-provider)\n* [Solaris](https://github.com/sh9189/poise-service-solaris)\n* [AIX](https://github.com/johnbellone/poise-service-aix)\n* *Supervisor (coming soon!)*\n\n\n## Quick Start\n\nTo create a service user and a service to run Apache2:\n\n```ruby\npoise_service_user 'www-data'\n\npoise_service 'apache2' do\n command '/usr/sbin/apache2 -f /etc/apache2/apache2.conf -DFOREGROUND'\n stop_signal 'WINCH'\n reload_signal 'USR1'\nend\n```\n\nor for a hypothetical Rails web application:\n\n```ruby\npoise_service_user 'myapp'\n\npoise_service 'myapp-web' do\n command 'bundle exec unicorn -p 8080'\n user 'myapp'\n directory '/srv/myapp'\n environment RAILS_ENV: 'production'\nend\n```\n\n## Resources\n\n### `poise_service`\n\nThe `poise_service` resource is the abstract definition of a service.\n\n```ruby\npoise_service 'myapp' do\n command 'myapp --serve'\n environment RAILS_ENV: 'production'\nend\n```\n\n#### Actions\n\n* `:enable` – Create, enable and start the service. *(default)*\n* `:disable` – Stop, disable, and destroy the service.\n* `:start` – Start the service.\n* `:stop` – Stop the service.\n* `:restart` – Stop and then start the service.\n* `:reload` – Send the configured reload signal to the service.\n\n#### Attributes\n\n* `service_name` – Name of the service. *(name attribute)*\n* `command` – Command to run for the service. This command must stay in the\n foreground and not daemonize itself. *(required)*\n* `user` – User to run the service as. See\n [`poise_service_user`](#poise_service_user) for any easy way to create service\n users. *(default: root)*\n* `directory` – Working directory for the service. *(default: home directory for\n user, or / if not found)*\n* `environment` – Environment variables for the service.\n* `stop_signal` – Signal to use to stop the service. Some systems will fall back\n to SIGKILL if this signal fails to stop the process. *(default: TERM)*\n* `reload_signal` – Signal to use to reload the service. *(default: HUP)*\n* `restart_on_update` – If true, the service will be restarted if the service\n definition or configuration changes. If `'immediately'`, the notification will\n happen in immediate mode. *(default: true)*\n\n#### Service Options\n\nThe `poise-service` library offers an additional way to pass configuration\ninformation to the final service called \"options\". Options are key/value pairs\nthat are passed down to the service provider and can be used to control how it\ncreates and manages the service. These can be set in the `poise_service`\nresource using the `options` method, in node attributes or via the\n`poise_service_options` resource. The options from all sources are merged\ntogether in to a single hash.\n\nWhen setting options in the resource you can either set them for all providers:\n\n```ruby\npoise_service 'myapp' do\n command 'myapp --serve'\n options status_port: 8000\nend\n```\n\nor for a single provider:\n\n```ruby\npoise_service 'myapp' do\n command 'myapp --serve'\n options :systemd, after_target: 'network'\nend\n```\n\nSetting via node attributes is generally how an end-user or application cookbook\nwill set options to customize services in the library cookbooks they are using.\nYou can set options for all services or for a single service, by service name\nor by resource name:\n\n```ruby\n# Global, for all services.\noverride['poise-service']['options']['after_target'] = 'network'\n# Single service.\noverride['poise-service']['myapp']['template'] = 'myapp.erb'\n```\n\nThe `poise_service_options` resource is also available to set node attributes\nfor a specific service in a DSL-friendly way:\n\n```ruby\npoise_service_options 'myapp' do\n template 'myapp.erb'\n restart_on_update false\nend\n```\n\nUnlike resource attributes, service options can be different for each provider.\nNot all providers support the same options so make sure to check the\ndocumentation for each provider to see what options are available.\n\n### `poise_service_options`\n\nThe `poise_service_options` resource allows setting per-service options in a\nDSL-friendly way. See [the Service Options](#service-options) section for more\ninformation about service options overall.\n\n```ruby\npoise_service_options 'myapp' do\n template 'myapp.erb'\n restart_on_update false\nend\n```\n\n#### Actions\n\n* `:run` – Apply the service options. *(default)*\n\n#### Attributes\n\n* `resource` – Name of the service. *(name attribute)*\n* `for_provider` – Provider to set options for.\n\nAll other attribute keys will be used as options data.\n\n### `poise_service_user`\n\nThe `poise_service_user` resource is an easy way to create service users. It is\nnot required to use `poise_service`, it is only a helper.\n\n```ruby\npoise_service_user 'myapp' do\n home '/srv/myapp'\nend\n```\n\n#### Actions\n\n* `:create` – Create the user and group. *(default)*\n* `:remove` – Remove the user and group.\n\n#### Attributes\n\n* `user` – Name of the user. *(name attribute)*\n* `group` – Name of the group. Set to `false` to disable group creation. *(name attribute)*\n* `uid` – UID of the user. *(default: automatic)*\n* `gid` – GID of the group. *(default: automatic)*\n* `home` – Home directory of the user.\n* `shell` – Shell of the user. *(default: /bin/nologin if present or /bin/false)*\n\n## Providers\n\n### `sysvinit`\n\nThe `sysvinit` provider supports SystemV-style init systems on Debian-family and\nRHEL-family platforms. It will create the `/etc/init.d/` script\nand enable/disable the service using the platform-specific service resource.\n\n```ruby\npoise_service 'myapp' do\n provider :sysvinit\n command 'myapp --serve'\nend\n```\n\nBy default a PID file will be created in `/var/run/service_name.pid`. You can\nuse the `pid_file` option detailed below to override this and rely on your\nprocess creating a PID file in the given path.\n\n#### Options\n\n* `pid_file` – Path to PID file that the service command will create.\n* `pid_file_external` – If true, assume the service will create the PID file\n itself. *(default: true if `pid_file` option is set)*\n* `template` – Override the default script template. If you want to use a\n template in a different cookbook use `'cookbook:template'`.\n* `command` – Override the service command.\n* `directory` – Override the service directory.\n* `environment` – Override the service environment variables.\n* `reload_signal` – Override the service reload signal.\n* `stop_signal` – Override the service stop signal.\n* `user` – Override the service user.\n* `never_start` – Never try to start the service.\n* `never_stop` – Never try to stop the service.\n* `never_restart` – Never try to restart the service.\n* `never_reload` – Never try to reload the service.\n* `script_path` – Override the path to the generated service script.\n\n### `upstart`\n\nThe `upstart` provider supports [Upstart](http://upstart.ubuntu.com/). It will\ncreate the `/etc/init/service_name.conf` configuration.\n\n```ruby\npoise_service 'myapp' do\n provider :upstart\n command 'myapp --serve'\nend\n```\n\nAs a wide variety of versions of Upstart are in use in various Linux\ndistributions, the provider does its best to identify which features are\navailable and provide shims as appropriate. Most of these should be invisible\nhowever Upstart older than 1.10 does not support setting a `reload signal` so\nonly SIGHUP can be used. You can set a `reload_shim` option to enable an\ninternal implementaion of reloading to be used for signals other than SIGHUP,\nhowever as this is implemented inside Chef code, running `initctl reload` would\nstill result in SIGHUP being sent. For this reason, the feature is disabled by\ndefault and will throw an error if a reload signal other than SIGHUP is used.\n\n#### Options\n\n* `reload_shim` – Enable the reload signal shim. See above for a warning about\n this feature.\n* `template` – Override the default configuration template. If you want to use a\n template in a different cookbook use `'cookbook:template'`.\n* `command` – Override the service command.\n* `directory` – Override the service directory.\n* `environment` – Override the service environment variables.\n* `reload_signal` – Override the service reload signal.\n* `stop_signal` – Override the service stop signal.\n* `user` – Override the service user.\n* `never_start` – Never try to start the service.\n* `never_stop` – Never try to stop the service.\n* `never_restart` – Never try to restart the service.\n* `never_reload` – Never try to reload the service.\n\n### `systemd`\n\nThe `systemd` provider supports [systemd](http://www.freedesktop.org/wiki/Software/systemd/).\nIt will create the `/etc/systemd/system/service_name.service` configuration.\n\n\n```ruby\npoise_service 'myapp' do\n provider :systemd\n command 'myapp --serve'\nend\n```\n\n#### Options\n\n* `template` – Override the default configuration template. If you want to use a\n template in a different cookbook use `'cookbook:template'`.\n* `command` – Override the service command.\n* `directory` – Override the service directory.\n* `environment` – Override the service environment variables.\n* `reload_signal` – Override the service reload signal.\n* `stop_signal` – Override the service stop signal.\n* `user` – Override the service user.\n* `never_start` – Never try to start the service.\n* `never_stop` – Never try to stop the service.\n* `never_restart` – Never try to restart the service.\n* `never_reload` – Never try to reload the service.\n* `auto_reload` – Run `systemctl daemon-reload` after changes to the unit file. *(default: true)*\n* `restart_mode` – Restart mode for the generated service unit. *(default: on-failure)*\n\n### `inittab`\n\nThe `inittab` provider supports managing services via `/etc/inittab` using\n[SystemV Init](http://www.nongnu.org/sysvinit/). This can provide basic\nprocess supervision even on very old *nix machines.\n\n```ruby\npoise_service 'myapp' do\n provider :inittab\n command 'myapp --serve'\nend\n```\n\n**NOTE:** Inittab does not allow stopping services, and they are started as soon\nas they are enabled.\n\n#### Options\n\n* `never_start` – Never try to start the service.\n* `never_stop` – Never try to stop the service.\n* `never_restart` – Never try to restart the service.\n* `never_reload` – Never try to reload the service.\n* `pid_file` – Path to PID file that the service command will create.\n* `service_id` – Unique 1-4 character tag for the service. Defaults to an\n auto-generated hash based on the service name. If these collide, bad things\n happen. Don't do that.\n\n### `dummy`\n\nThe `dummy` provider supports launching services directly from Chef itself.\nThis is for testing purposes only and is entirely unsuitable for use in\nproduction. This is mostly useful when used alongside kitchen-docker.\n\n```ruby\npoise_service 'myapp' do\n provider :dummy\n command 'myapp --serve'\nend\n```\n\nThe service information is written to `/var/run`. The PID file is `service_name.pid`,\nthe command output is `service_name.out`, and the service parameters are in\n`service_name.json`.\n\n#### Options\n\n* `never_start` – Never try to start the service.\n* `never_stop` – Never try to stop the service.\n* `never_restart` – Never try to restart the service.\n* `never_reload` – Never try to reload the service.\n* `restart_delay` – Number of seconds to wait between stop and start when\n restarting. *(default: 1)*\n\n## ServiceMixin\n\nFor the common case of a resource (LWRP or plain Ruby) that roughly maps to\n\"some config files and a service\" poise-service provides a mixin module,\n`PoiseService::ServiceMixin`. This mixin adds the standard service actions\n(`enable`, `disable`, `start`, `stop`, `restart`, and `reload`) with basic\nimplementations that call those actions on a `poise_service` resource for you.\nYou customize the service by defining a `service_options` method on your\nprovider class:\n\n```ruby\ndef service_options(service)\n # service is the PoiseService::Resource object instance.\n service.command \"/usr/sbin/#{new_resource.name} -f /etc/#{new_resource.name}/conf/httpd.conf -DFOREGROUND\"\n service.stop_signal 'WINCH'\n service.reload_signal 'USR1'\nend\n```\n\nYou will generally want to override the `enable` action to install things\nrelated to the service like packages, users and configuration files:\n\n```ruby\ndef action_enable\n notifying_block do\n package 'apache2'\n poise_service_user 'www-data'\n template \"/etc/#{new_resource.name}/conf/httpd.conf\" do\n # ...\n end\n end\n # This super call will run the normal service enable,\n # creating the service and starting it.\n super\nend\n```\n\nSee [the poise_service_test_mixin resource](test/cookbooks/poise-service_test/resources/mixin.rb)\nand [provider](test/cookbooks/poise-service_test/providers/mixin.rb) for\nexamples of using `ServiceMixin` in an LWRP.\n\n## Sponsors\n\nDevelopment sponsored by [Bloomberg](http://www.bloomberg.com/company/technology/).\n\nThe Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/).\n\n## License\n\nCopyright 2015-2016, Noah Kantrowitz\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","maintainer":"Noah Kantrowitz","maintainer_email":"noah@coderanger.net","license":"Apache-2.0","platforms":{"ubuntu":">= 0.0.0","debian":">= 0.0.0","centos":">= 0.0.0","redhat":">= 0.0.0","fedora":">= 0.0.0","amazon":">= 0.0.0","suse":">= 0.0.0","opensuse":">= 0.0.0"},"dependencies":{"poise":"~> 2.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/poise/poise-service","issues_url":"https://github.com/poise/poise-service/issues","chef_version":[["< 14",">= 12"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/poise-service/templates/default/dummy.json.erb b/cookbooks/poise-service/templates/default/dummy.json.erb new file mode 100644 index 0000000..ad62f40 --- /dev/null +++ b/cookbooks/poise-service/templates/default/dummy.json.erb @@ -0,0 +1,7 @@ +<%= {command: @command, + directory: @directory, + environment: @environment, + name: @name, + reload_signal: @reload_signal, + stop_signal: @stop_signal, + user: @user}.to_json %> diff --git a/cookbooks/poise-service/templates/default/inittab.sh.erb b/cookbooks/poise-service/templates/default/inittab.sh.erb new file mode 100644 index 0000000..7e19bf7 --- /dev/null +++ b/cookbooks/poise-service/templates/default/inittab.sh.erb @@ -0,0 +1,15 @@ +#!/bin/sh +exec /opt/chef/embedded/bin/ruby <", Process.pid) +Dir.chdir("<%= @directory %>") +ent = Etc.getpwnam("<%= @user %>") +if Process.euid != ent.uid || Process.egid != ent.gid + Process.initgroups(ent.name, ent.gid) + Process::GID.change_privilege(ent.gid) if Process.egid != ent.gid + Process::UID.change_privilege(ent.uid) if Process.euid != ent.uid +end +(ENV["HOME"] = Dir.home("<%= @user %>")) rescue nil +<%= @environment.map {|key, value| "ENV[#{key.to_s.inspect}] = #{value.to_s.inspect}" }.join("; ") %> +exec(*<%= Shellwords.split(@command).inspect %>) +EOH diff --git a/cookbooks/poise-service/templates/default/systemd.service.erb b/cookbooks/poise-service/templates/default/systemd.service.erb new file mode 100644 index 0000000..ebdf871 --- /dev/null +++ b/cookbooks/poise-service/templates/default/systemd.service.erb @@ -0,0 +1,14 @@ +[Unit] +Description=<%= @name %> + +[Service] +Environment=<%= @environment.map {|key, val| %Q{"#{key}=#{val}"} }.join(' ') %> +ExecStart=<%= @command %> +ExecReload=/bin/kill -<%= @reload_signal %> $MAINPID +KillSignal=<%= @stop_signal %> +User=<%= @user %> +WorkingDirectory=<%= @directory %> +Restart=<%= @restart_mode %> + +[Install] +WantedBy=multi-user.target diff --git a/cookbooks/poise-service/templates/default/sysvinit.sh.erb b/cookbooks/poise-service/templates/default/sysvinit.sh.erb new file mode 100644 index 0000000..f13d811 --- /dev/null +++ b/cookbooks/poise-service/templates/default/sysvinit.sh.erb @@ -0,0 +1,190 @@ +#!/bin/sh +# Init script for <%= @name %> generated by poise-service +# +### BEGIN INIT INFO +# Provides: <%= @name %> +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Init script for <%= @name %> +# Description: Init script for <%= @name %> +### END INIT INFO + +<%- if @platform_family == 'debian' -%> +. /lib/lsb/init-functions + +_start() { + start-stop-daemon --start --quiet --background \ + --pidfile "<%= @pid_file %>"<% unless @pid_file_external %> --make-pidfile<% end %> \ + --chuid "<%= @user %>" --chdir "<%= @directory %>" \ + --exec "<%= @daemon %>" -- <%= @daemon_options %> +} + +_stop() { + start-stop-daemon --stop --quiet --pidfile "<%= @pid_file %>" --user "<%= @user %>" --signal "<%= @stop_signal %>" +} + +_status() { + status_of_proc -p "<%= @pid_file %>" "<%= @daemon %>" "<%= @name %>" +} + +_reload() { + start-stop-daemon --stop --quiet --pidfile "<%= @pid_file %>" --user "<%= @user %>" --signal "<%= @reload_signal %>" +} + +<%- else -%> +_start() { + <%# Implementing this using RedHat's bash helpers is too painful. Sorry. %> + <%# See dummy.rb for a more commented version of this code. %> + /opt/chef/embedded/bin/ruby < +File.unlink(pid_file) if File.exist?(pid_file) +if Process.fork + sleep(1) until File.exist?(pid_file) +else + Process.daemon(true) + Dir.chdir(<%= @directory.inspect %>) + <%- unless @pid_file_external -%> + IO.write(pid_file, Process.pid) + <%- end -%> + ent = Etc.getpwnam(<%= @user.inspect %>) + if Process.euid != ent.uid || Process.egid != ent.gid + Process.initgroups(ent.name, ent.gid) + Process::GID.change_privilege(ent.gid) if Process.egid != ent.gid + Process::UID.change_privilege(ent.uid) if Process.euid != ent.uid + end + Kernel.exec(*<%= Shellwords.split(@command).inspect %>) + exit! +end +EOH +} + +_stop() { + if [ -r "<%= @pid_file %>" ]; then + kill -<%= @stop_signal%> "$(cat "<%= @pid_file %>")" + else + return 0 + fi +} + +_status() { + if [ -r "<%= @pid_file %>" ]; then + kill -0 "$(cat "<%= @pid_file %>")" + else + return 1 + fi +} + +_reload() { + if [ -r "<%= @pid_file %>" ]; then + kill -<%= @reload_signal%> "$(cat "<%= @pid_file %>")" + else + return 1 + fi +} + +<%# Some functions to match LSB %> + +log_daemon_msg() { + echo -n "$1" +} + +log_progress_msg() { + echo -n "$1" +} + +log_warning_msg() { + echo -n "$1" +} + +log_failure_msg() { + echo -n "$1" +} + +log_end_msg() { + if [ "$1" = 0 ]; then + echo " [ OK ]" + else + echo " [FAILED]" + fi +} +<%- end -%> + +set -e + +start() { + if _start + then + rc=0 + sleep 1 + if ! kill -0 "$(cat "<%= @pid_file %>")" >/dev/null 2>&1; then + log_failure_msg "<%= @name %> failed to start" + rc=1 + fi + else + rc=1 + fi + if [ "$rc" -eq 0 ]; then + log_end_msg 0 + else + log_end_msg 1 + rm -f "<%= @pid_file %>" + fi +} + +<%- @environment.each do |key, val| -%> +export <%= key %>="<%= val %>" +<%- end -%> +export PATH="${PATH:+$PATH:}/usr/sbin:/sbin" + +case "$1" in + start) + log_daemon_msg "Starting <%= @name %>" + if [ -s "<%= @pid_file %>" ] && kill -0 "$(cat "<%= @pid_file %>")" >/dev/null 2>&1; then + log_progress_msg "apparently already running" + log_end_msg 0 + exit 0 + fi + start + ;; + + stop) + log_daemon_msg "Stopping <%= @name %>" + _stop + log_end_msg "$?" + rm -f "<%= @pid_file %>" + ;; + + reload|force-reload) + log_daemon_msg "Reloading <%= @name %>" + _reload + log_end_msg "$?" + ;; + + restart) + set +e + log_daemon_msg "Restarting <%= @name %>" + if [ -s "<%= @pid_file %>" ] && kill -0 "$(cat "<%= @pid_file %>")" >/dev/null 2>&1; then + _stop || true + sleep 1 + else + log_warning_msg "<%= @name %> not running, attempting to start." + rm -f "<%= @pid_file %>" + fi + start + ;; + + status) + set +e + _status + exit $? + ;; + + *) + echo "Usage: /etc/init.d/<%= @name %> {start|stop|reload|force-reload|restart|status}" + exit 1 +esac + +exit 0 diff --git a/cookbooks/poise-service/templates/default/upstart.conf.erb b/cookbooks/poise-service/templates/default/upstart.conf.erb new file mode 100644 index 0000000..cd60ea1 --- /dev/null +++ b/cookbooks/poise-service/templates/default/upstart.conf.erb @@ -0,0 +1,49 @@ +# <%= @name %> generated by poise-service for <%= @new_resource.to_s %> + +description "<%= @name %>" + +start on runlevel [2345] +stop on runlevel [!2345] + +respawn +respawn limit 10 5 +umask 022 +chdir <%= @directory %> +<%- @environment.each do |key, val| -%> +env <%= key %>="<%= val %>" +<%- end -%> +<%- if @upstart_features[:setuid] -%> +setuid <%= @user %> +<%- end -%> +<%- if @upstart_features[:kill_signal] -%> +kill signal <%= @stop_signal %> +<%- end -%> +<%- if @upstart_features[:reload_signal] -%> +reload signal <%= @reload_signal %> +<%- end -%> + +<%- if @upstart_features[:setuid] -%> +exec <%= @command %> +<%- else -%> +script +exec /opt/chef/embedded/bin/ruby <) +if Process.euid != ent.uid || Process.egid != ent.gid + Process.initgroups(ent.name, ent.gid) + Process::GID.change_privilege(ent.gid) if Process.egid != ent.gid + Process::UID.change_privilege(ent.uid) if Process.euid != ent.uid +end +ENV["HOME"] = Dir.home(<%= @user.inspect %>) rescue nil +exec(*<%= Shellwords.split(@command).inspect %>) +EOH +end script +<%- end -%> +<%- if !@upstart_features[:kill_signal] && @stop_signal != 'TERM' -%> +pre-stop script + PID=`initctl status <%= @name %> | sed 's/^.*process \([0-9]*\)$/\1/'` + if [ -n "$PID" ]; then + kill -<%= @stop_signal %> "$PID" + fi +end script +<%- end -%> diff --git a/cookbooks/poise/CHANGELOG.md b/cookbooks/poise/CHANGELOG.md new file mode 100644 index 0000000..13b4f9c --- /dev/null +++ b/cookbooks/poise/CHANGELOG.md @@ -0,0 +1,203 @@ +# Changelog + +## v2.8.2 + +* Remove support for Chef before 12.14. +* Fixed compatibility with Chef 14.3. + +## v2.8.1 + +* Fix a missing `require` when using `subclass_providers!` on Chef 12.3. + +## v2.8.0 + +* Chef 13 compatibility. +* Passing a symbol for the parent now works with the `include Poise(:name)` + shortcut. +* Fixed `subclass_providers!` on older versions of Chef. + +## v2.7.2 + +* Test harness fixes for Chef. + +## v2.7.1 + +* Minor tweak for compatability with Chef master. + +## v2.7.0 + +* More compatibility improvements for Chef 12.9. +* New helper: `Poise::Helpers::Win32User` to automatically convert `'root'` + defaults for user and group properties to more platform-appropriate values. +* Enhanced `poise_shell_out` to better cope with Windows command parsing. Use + Bash-style commands and it will automatically convert. +* Overall compatibility fixes for Windows. + +## v2.6.1 + +* Compatibility with Chef master to fix issues with `defined_in!` not ignoring + stack frames from Chef code. +* Setting a provider in a inversion options resource now works as (probably) + expected. + +## v2.6.0 + +* New backwards-compatibility helper: `Poise::Backports::VERIFY_PATH`. Use it + like `verify "myapp -t #{Poise::Backports::VERIFY_PATH}" if defined?(verify)` + for backwards-compatible usage of file verifications. +* Fixed Poise's implementation of lazy defaults to more closely match Chef's + even when both are used in conjunction. Lazy defaults will no longer be + evaluated when setting a value or getting an existing non-default value. + +## v2.5.0 + +* New property for inversion resources: `provider_no_auto`. Set one or more + provider names that will be ignored for automatic resolution for that instance. +* Support `variables` as an alias for `options` in template content properties + to match the `template` resource. +* Template content properties are no longer validated after creation for + non-default actions. +* Formalize the extra-verbose logging mode for Poise and expose it via helpers. +* Extra-verbose logging mode can now be enabled by creating a `/poise_debug` file. +* New helper: `poise_shell_out`. Like normal `shell_out` but sets group and + environment variables automatically to better defaults. + +## v2.4.0 + +* Added return value to `Container#register_subresource` to track if the resource + was already added. +* Improve inspect output for subresources and containers. +* Ensure notifications work with subresources. +* Inversion providers process name equivalences. + +## v2.3.2 + +* Improve handling of deeply nested subresources. + +## v2.3.1 + +* Ensure a container with a parent link to its own type doesn't use self as the + default parent. +* Improve handling of `load_current_resource` in providers that call it via + `super`. + +## v2.3.0 + +* New helper: `ResourceSubclass`, a helper for subclassing a resource while + still using the providers as the base class. +* New feature: Non-default containers. Use `container_default: false` to mark + a container class as ineligible for default lookup. +* New feature: parent attribute defaults. You can set a `parent_default` to + provide a default value for the parent of a resource. This supports the + `lazy { }` helper as with normal default values. +* New feature: use `forced_keys: [:name]` on an option collector property to + force keys that would otherwise be clobbered by resource methods. +* Can enable verbose logging mode via a node attribute in addition to an + environment variable. + +## v2.2.3 + +* Add `ancestor_send` utility method for use in other helpers. +* Improve subresource support for use in mixins. + +## v2.2.2 + +* Fix 2.2.1 for older versions of Chef. + +## v2.2.1 + +* Fixed delayed notifications inside `notifying_block`. +* Default actions as expected within LWRPs. + +## v2.2.0 + +* Compatibility with Chef 12.4.1 and Chefspec 4.3.0. +* New helper `ResourceCloning`: Disables resource cloning between Poise-based + resources. This is enabled by default. +* Subresource parent references can be set to nil. + +## v2.1.0 + +* Compatibility with Chef 12.4. +* Add `#property` as an alias for `#attribute` in resources. This provides + forward compatibility with future versions of Chef. +* Freeze default resource attribute values. **This may break your code**, + however this is not a major release because any code broken by this change + was itself already a bug. + +## v2.0.1 + +* Make the ChefspecHelpers helper a no-op if chefspec is not already loaded. +* Fix for finding the correct cookbook for a file when using vendored gems. +* New flag for the OptionCollector helper, `parser`: + +```ruby +class Resource < Chef::Resource + include Poise + attribute(:options, option_collector: true, parser: proc {|val| parse(val) }) + + def parse(val) + {name: val} + end +end +``` + +* Fix for a possible infinite loop when using `ResourceProviderMixin` in a nested + module structure. + +## v2.0.0 + +Major overhaul! Poise is now a Halite gem/cookbook. New helpers: + +* ChefspecMatchers – Automatically create Chefspec matchers for Poise resources. +* DefinedIn – Track which file (and cookbook) a resource or provider is defined in. +* Fused – Experimental support for defining provider actions in the resource class. +* Inversion – Support for end-user dependency inversion with providers. + +All helpers are compatible with Chef >= 12.0. Chef 11 is now deprecated, if you +need to support Chef 11 please continue to use Poise 1. + +## v1.0.12 + +* Correctly propagate errors from inside notifying_block. + +## v1.0.10 + +* Fixes an issue with the LWRPPolyfill helper and false values. + + +## v1.0.8 + +* Delayed notifications from nested converges will still only run at the end of + the main converge. + +## v1.0.6 + +* The include_recipe helper now works correctly when used at compile time. + +## v1.0.4 + +* Redeclaring a template attribute with the same name as a parent class will + inherit its options. + +## v1.0.2 + +* New template attribute pattern. + +```ruby +attribute(:config, template: true) + +... + +resource 'name' do + config_source 'template.erb' +end + +... + +new_resource.config_content +``` + +## v1.0.0 + +* Initial release! diff --git a/cookbooks/poise/README.md b/cookbooks/poise/README.md new file mode 100644 index 0000000..881b5cf --- /dev/null +++ b/cookbooks/poise/README.md @@ -0,0 +1,233 @@ +# Poise + +[![Build Status](https://img.shields.io/travis/poise/poise.svg)](https://travis-ci.org/poise/poise) +[![Gem Version](https://img.shields.io/gem/v/poise.svg)](https://rubygems.org/gems/poise) +[![Cookbook Version](https://img.shields.io/cookbook/v/poise.svg)](https://supermarket.chef.io/cookbooks/poise) +[![Coverage](https://img.shields.io/codecov/c/github/poise/poise.svg)](https://codecov.io/github/poise/poise) +[![Gemnasium](https://img.shields.io/gemnasium/poise/poise.svg)](https://gemnasium.com/poise/poise) +[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) + +## What is Poise? + +The poise cookbook is a set of libraries for writing reusable cookbooks. It +provides helpers for common patterns and a standard structure to make it easier to create flexible cookbooks. + +## Writing your first resource + +Rather than LWRPs, Poise promotes the idea of using normal, or "heavy weight" +resources, while including helpers to reduce much of boilerplate needed for this. Each resource goes in its own file under `libraries/` named to match +the resource, which is in turn based on the class name. This means that the file `libraries/my_app.rb` would contain `Chef::Resource::MyApp` which maps to the resource `my_app`. + +An example of a simple shell to start from: + +```ruby +require 'poise' +require 'chef/resource' +require 'chef/provider' + +module MyApp + class Resource < Chef::Resource + include Poise + provides(:my_app) + actions(:enable) + + attribute(:path, kind_of: String) + # Other attribute definitions. + end + + class Provider < Chef::Provider + include Poise + provides(:my_app) + + def action_enable + notifying_block do + ... # Normal Chef recipe code goes here + end + end + end +end +``` + +Starting from the top, first we require the libraries we will be using. Then we +create a module to hold our resource and provider. If your cookbook declares +multiple resources and/or providers, you might want additional nesting here. +Then we declare the resource class, which inherits from `Chef::Resource`. This +is similar to the `resources/` file in an LWRP, and a similar DSL can be used. +We then include the `Poise` mixin to load our helpers, and then call +`provides(:my_app)` to tell Chef this class will implement the `my_app` +resource. Then we use the familiar DSL, though with a few additions we'll cover +later. + +Then we declare the provider class, again similar to the `providers/` file in an +LWRP. We include the `Poise` mixin again to get access to all the helpers and +call `provides()` to tell Chef what provider this is. Rather than use the +`action :enable do ... end` DSL from LWRPs, we just define the action method +directly. The implementation of action comes from a block of recipe code +wrapped with `notifying_block` to capture changes in much the same way as +`use_inline_resources`, see below for more information about all the features of +`notifying_block`. + +We can then use this resource like any other Chef resource: + +```ruby +my_app 'one' do + path '/tmp' +end +``` + +## Helpers + +While not exposed as a specific method, Poise will automatically set the +`resource_name` based on the class name. + +### Notifying Block + +As mentioned above, `notifying_block` is similar to `use_inline_resources` in LWRPs. Any Chef resource created inside the block will be converged in a sub-context and if any have updated it will trigger notifications on the current resource. Unlike `use_inline_resources`, resources inside the sub-context can still see resources outside of it, with lookups propagating up sub-contexts until a match is found. Also any delayed notifications are scheduled to run at the end of the main converge cycle, instead of the end of this inner converge. + +This can be used to write action methods using the normal Chef recipe DSL, while still offering more flexibility through subclassing and other forms of code reuse. + +### Include Recipe + +In keeping with `notifying_block` to implement action methods using the Chef DSL, Poise adds an `include_recipe` helper to match the method of the same name in recipes. This will load and converge the requested recipe. + +### Resource DSL + +To make writing resource classes easier, Poise exposes a DSL similar to LWRPs for defining actions and attributes. Both `actions` and +`default_action` are just like in LWRPs, though `default_action` is rarely needed as the first action becomes the default. `attribute` is also available just like in LWRPs, but with some enhancements noted below. + +One notable difference over the standard DSL method is that Poise attributes +can take a block argument. + +#### Template Content + +A common pattern with resources is to allow passing either a template filename or raw file content to be used in a configuration file. Poise exposes a new attribute flag to help with this behavior: + +```ruby +attribute(:name, template: true) +``` + +This creates four methods on the class, `name_source`, `name_cookbook`, +`name_content`, and `name_options`. If the name is set to `''`, no prefix is applied to the function names. The content method can be set directly, but if not set and source is set, then it will render the template and return it as a string. Default values can also be set for any of these: + +```ruby +attribute(:name, template: true, default_source: 'app.cfg.erb', + default_options: {host: 'localhost'}) +``` + +As an example, you can replace this: + +```ruby +if new_resource.source + template new_resource.path do + source new_resource.source + owner 'app' + group 'app' + variables new_resource.options + end +else + file new_resource.path do + content new_resource.content + owner 'app' + group 'app' + end +end +``` + +with simply: + +```ruby +file new_resource.path do + content new_resource.content + owner 'app' + group 'app' +end +``` + +As the content method returns the rendered template as a string, this can also +be useful within other templates to build from partials. + +#### Lazy Initializers + +One issue with Poise-style resources is that when the class definition is executed, Chef hasn't loaded very far so things like the node object are not +yet available. This means setting defaults based on node attributes does not work directly: + +```ruby +attribute(:path, default: node['myapp']['path']) +... +NameError: undefined local variable or method 'node' +``` + +To work around this, Poise extends the idea of lazy initializers from Chef recipes to work with resource definitions as well: + +```ruby +attribute(:path, default: lazy { node['myapp']['path'] }) +``` + +These initializers are run in the context of the resource object, allowing +complex default logic to be moved to a method if desired: + +```ruby +attribute(:path, default: lazy { my_default_path }) + +def my_default_path + ... +end +``` + +#### Option Collector + +Another common pattern with resources is to need a set of key/value pairs for +configuration data or options. This can done with a simple Hash, but an option collector attribute can offer a nicer syntax: + +```ruby +attribute(:mydata, option_collector: true) +... + +my_app 'name' do + mydata do + key1 'value1' + key2 'value2' + end +end +``` + +This will be converted to `{key1: 'value1', key2: 'value2'}`. You can also pass a Hash to an option collector attribute just as you would with a normal attribute. + +## Debugging Poise + +Poise has its own extra-verbose level of debug logging that can be enabled in +three different ways. You can either set the environment variable `$POISE_DEBUG`, +set a node attribute `node['POISE_DEBUG']`, or touch the file `/POISE_DEBUG`. +You will see a log message `Extra verbose logging enabled` at the start of the +run to confirm Poise debugging has been enabled. Make sure you also set Chef's +log level to `debug`, usually via `-l debug` on the command line. + +## Upgrading from Poise 1.x + +The biggest change when upgrading from Poise 1.0 is that the mixin is no longer +loaded automatically. You must add `require 'poise'` to your code is you want to +load it, as you would with normal Ruby code outside of Chef. It is also highly +recommended to add `provides(:name)` calls to your resources and providers, this +will be required in Chef 13 and will display a deprecation warning if you do +not. This also means you can move your code out of the `Chef` module namespace +and instead declare it in your own namespace. An example of this is shown above. + +## Sponsors + +The Poise test server infrastructure is generously sponsored by [Rackspace](https://rackspace.com/). Thanks Rackspace! + +## License + +Copyright 2013-2016, Noah Kantrowitz + +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/cookbooks/poise/files/halite_gem/poise.rb b/cookbooks/poise/files/halite_gem/poise.rb new file mode 100644 index 0000000..cdacd57 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise.rb @@ -0,0 +1,108 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/provider' +require 'chef/resource' +require 'chef/run_context' + +require 'poise/utils/resource_provider_mixin' + + +module Poise + include Poise::Utils::ResourceProviderMixin + autoload :Backports, 'poise/backports' + autoload :Helpers, 'poise/helpers' + autoload :NOT_PASSED, 'poise/backports/not_passed' + autoload :Provider, 'poise/provider' + autoload :Resource, 'poise/resource' + autoload :Subcontext, 'poise/subcontext' + autoload :Utils, 'poise/utils' + autoload :VERSION, 'poise/version' + + # Check if Poise's extra debugging output is enabled. This produces a *lot* + # of logging. + # + # @param node [Chef::Node, Chef::RunContext] Optional node to check for + # attributes. If not given, Chef.node is used instead. + # @return [Boolean] + def self.debug?(node=nil) + node = node.node if node.is_a?(Chef::RunContext) + node ||= Chef.node if defined?(Chef.node) + @debug_file_upper = ::File.exist?('/POISE_DEBUG') unless defined?(@debug_file_upper) + @debug_file_lower = ::File.exist?('/poise_debug') unless defined?(@debug_file_lower) + !!( + (ENV['POISE_DEBUG'] && ENV['POISE_DEBUG'] != 'false') || + (ENV['poise_debug'] && ENV['poise_debug'] != 'false') || + (node && node['POISE_DEBUG']) || + (node && node['poise_debug']) || + @debug_file_upper || + @debug_file_lower + ) + end + + # Log a message only if Poise's extra debugging output is enabled. + # + # @see #debug? + # @param msg [String] Log message. + # @return [void] + def self.debug(msg) + Chef::Log.debug(msg) if debug? + end +end + +# Callable form to allow passing in options: +# include Poise(ParentResource) +# include Poise(parent: ParentResource) +# include Poise(container: true) +def Poise(options={}) + # Allow passing a class as a shortcut + if options.is_a?(Class) || options.is_a?(Symbol) + options = {parent: options} + end + + # Create a new anonymous module + mod = Module.new + + # Fake the name. + mod.define_singleton_method(:name) do + super() || 'Poise' + end + + mod.define_singleton_method(:included) do |klass| + super(klass) + # Pull in the main helper to cover most of the needed logic. + klass.class_exec { include Poise } + # Set the defined_in values as needed. + klass.poise_defined!(caller) + # Resource-specific options. + if klass < Chef::Resource + klass.poise_subresource(options[:parent], options[:parent_optional], options[:parent_auto]) if options[:parent] + klass.poise_subresource_container(options[:container_namespace], options[:container_default]) if options[:container] + klass.poise_fused if options[:fused] + klass.poise_inversion(options[:inversion_options_resource]) if options[:inversion] + end + # Provider-specific options. + if klass < Chef::Provider + klass.poise_inversion(options[:inversion], options[:inversion_attribute]) if options[:inversion] + end + end + + mod +end + +# Display a message if poise_debug is enabled. Off in ChefSpec so I don't get +# extra logging stuff that I don't care about. +Poise.debug('[Poise] Extra verbose logging enabled') unless defined?(ChefSpec) diff --git a/cookbooks/poise/files/halite_gem/poise/backports.rb b/cookbooks/poise/files/halite_gem/poise/backports.rb new file mode 100644 index 0000000..84ceed8 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/backports.rb @@ -0,0 +1,28 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + + +module Poise + # Backported features from Chef to be able to use them with older versions. + # + # @since 2.3.0 + module Backports + autoload :NOT_PASSED, 'poise/backports/not_passed' + autoload :VERIFY_PATH, 'poise/backports/verify_path' + end + + autoload :NOT_PASSED, 'poise/backports/not_passed' +end diff --git a/cookbooks/poise/files/halite_gem/poise/backports/not_passed.rb b/cookbooks/poise/files/halite_gem/poise/backports/not_passed.rb new file mode 100644 index 0000000..c5b3ce0 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/backports/not_passed.rb @@ -0,0 +1,52 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +begin + require 'chef/constants' +rescue LoadError + # This space left intentionally blank. +end + + +module Poise + module Backports + # A sentinel value for optional arguments where nil is a valid value. + # @since 2.3.0 + # @!parse NOT_PASSED = Object.new + NOT_PASSED = if defined?(Chef::NOT_PASSED) + Chef::NOT_PASSED + else + # Copyright 2015-2016, Chef Software Inc. + # Used under Apache License, Version 2.0. + Object.new.tap do |not_passed| + def not_passed.to_s + "NOT_PASSED" + end + def not_passed.inspect + to_s + end + not_passed.freeze + end + end + + end + + # An alias to {Backports::NOT_PASSED} to avoid typing so much. + # + # @since 2.3.0 + # @see Backports::NOT_PASSED + NOT_PASSED = Backports::NOT_PASSED +end diff --git a/cookbooks/poise/files/halite_gem/poise/backports/verify_path.rb b/cookbooks/poise/files/halite_gem/poise/backports/verify_path.rb new file mode 100644 index 0000000..8bd4c06 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/backports/verify_path.rb @@ -0,0 +1,33 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + + +module Poise + module Backports + # The correct interpolation key for any version of Chef. + # @since 2.6.0 + # @example + # file '/path' do + # content my_content + # verify "myapp -t #{Poise::Backports::VERIFY_PATH}" + # end + VERIFY_PATH = if Gem::Version.create(Chef::VERSION) < Gem::Version.create('12.5.0') + '%{file}' + else + '%{path}' + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/error.rb b/cookbooks/poise/files/halite_gem/poise/error.rb new file mode 100644 index 0000000..9a6a948 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/error.rb @@ -0,0 +1,24 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + + +module Poise + # Base exception class for Poise errors. + # + # @since 2.0.0 + class Error < Exception + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers.rb b/cookbooks/poise/files/halite_gem/poise/helpers.rb new file mode 100644 index 0000000..ab2fc33 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers.rb @@ -0,0 +1,36 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + + +module Poise + module Helpers + autoload :ChefspecMatchers, 'poise/helpers/chefspec_matchers' + autoload :DefinedIn, 'poise/helpers/defined_in' + autoload :Fused, 'poise/helpers/fused' + autoload :IncludeRecipe, 'poise/helpers/include_recipe' + autoload :Inversion, 'poise/helpers/inversion' + autoload :LazyDefault, 'poise/helpers/lazy_default' + autoload :LWRPPolyfill, 'poise/helpers/lwrp_polyfill' + autoload :NotifyingBlock, 'poise/helpers/notifying_block' + autoload :OptionCollector, 'poise/helpers/option_collector' + autoload :ResourceCloning, 'poise/helpers/resource_cloning' + autoload :ResourceName, 'poise/helpers/resource_name' + autoload :ResourceSubclass, 'poise/helpers/resource_subclass' + autoload :Subresources, 'poise/helpers/subresources' + autoload :TemplateContent, 'poise/helpers/template_content' + autoload :Win32User, 'poise/helpers/win32_user' + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/chefspec_matchers.rb b/cookbooks/poise/files/halite_gem/poise/helpers/chefspec_matchers.rb new file mode 100644 index 0000000..7417628 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/chefspec_matchers.rb @@ -0,0 +1,92 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + +# Not requiring chefspec or rspec/expectations since this code should only +# activate if they are already loaded. + +require 'poise/helpers/lwrp_polyfill' +require 'poise/helpers/resource_name' + + +module Poise + module Helpers + # A resource mixin to register ChefSpec matchers for a resource + # automatically. + # + # If you are using the provides() form for naming resources, ensure that is + # set before declaring actions. + # + # @since 2.0.0 + # @example Define a class + # class Chef::Resource::MyResource < Chef::Resource + # include Poise::Helpers::ChefspecMatchers + # actions(:run) + # end + # @example Use a matcher + # expect(chef_run).to run_my_resource('...') + module ChefspecMatchers + include Poise::Helpers::LWRPPolyfill::Resource + include Poise::Helpers::ResourceName + + # Create a matcher for a given resource type and action. This is + # idempotent so if a matcher already exists, it will not be recreated. + # + # @api private + def self.create_matcher(resource, action) + # Check that we have everything we need. + return unless defined?(ChefSpec) && defined?(RSpec::Matchers) && resource + method = :"#{action}_#{resource}" + return if RSpec::Matchers.method_defined?(method) + RSpec::Matchers.send(:define_method, method) do |resource_name| + ChefSpec::Matchers::ResourceMatcher.new(resource, action, resource_name) + end + end + + # @!classmethods + module ClassMethods + # Create a resource-level matcher for this resource. + # + # @see Resource::ResourceName.provides + def provides(name, *args, &block) + super(name, *args, &block) + ChefSpec.define_matcher(name) if defined?(ChefSpec) + # Call #actions here to grab any actions from a parent class. + actions.each do |action| + ChefspecMatchers.create_matcher(name, action) + end + end + + # Create matchers for all declared actions. + # + # @see Resource::LWRPPolyfill.actions + def actions(*names) + super.tap do |actions| + actions.each do |action| + ChefspecMatchers.create_matcher(resource_name, action) + end if resource_name && resource_name != :resource && !names.empty? + end + end + + def included(klass) + super + klass.extend ClassMethods + end + end + + extend ClassMethods + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/defined_in.rb b/cookbooks/poise/files/halite_gem/poise/helpers/defined_in.rb new file mode 100644 index 0000000..81ce8c4 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/defined_in.rb @@ -0,0 +1,129 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise' +require 'poise/error' +require 'poise/utils' + + +module Poise + module Helpers + # A mixin to track where a resource or provider was defined. This can + # provide either the filename of the class or the cookbook it was defined in. + # + # @since 2.0.0 + # @example + # class MyProvider < Chef::provider + # include Poise::Helpers::DefinedIn + # + # def action_create + # template '...' do + # # ... + # cookbook new_resource.poise_defined_in + # end + # end + # end + module DefinedIn + # Path to the root of Poise's code. + # @see #poise_defined! + # @api private + POISE_LIB_ROOT = ::File.expand_path('../..', __FILE__) + + # Path to the root of Chef's code. + # @see #poise_defined! + # @api private + CHEF_LIB_ROOT = ::File.join(::Gem::Specification.find_by_name('chef').gem_dir, 'lib') + + # A regex used to parse Ruby's `caller` string syntax. + # @see #poise_defined! + # @api private + CALLER_REGEXP = /^(.+):\d+:in `.+'/ + + # Wrapper for {.poise_defined_in_cookbook} to pass the run context for you. + # + # @see .poise_defined_in_cookbook + # @param file [String, nil] Optional file path to check instead of the path + # this class was defined in. + # @return [String] + def poise_defined_in_cookbook(file=nil) + self.class.poise_defined_in_cookbook(run_context, file) + end + + # @!classmethods + module ClassMethods + # The file this class or module was defined in, or nil if it isn't found. + # + # @return [String] + def poise_defined_in + raise Poise::Error.new("Unable to determine location of #{self.name}") unless @poise_defined_in + @poise_defined_in + end + + # The cookbook this class or module was defined in. Can pass a file to + # check that instead. + # + # @param run_context [Chef::RunContext] Run context to check cookbooks in. + # @param file [String, nil] Optional file path to check instead of the + # path this class was defined in. + # @return [String] + def poise_defined_in_cookbook(run_context, file=nil) + file ||= poise_defined_in + Poise.debug("[#{self.name}] Checking cookbook name for #{file}") + Poise::Utils.find_cookbook_name(run_context, file).tap do |cookbook| + Poise.debug("[#{self.name}] found cookbook #{cookbook.inspect}") + end + end + + # Record that the class/module was defined. Called automatically by Ruby + # for all normal cases. + # + # @param caller_array [Array] A strack trace returned by #caller. + # @return [void] + def poise_defined!(caller_array) + # Only try to set this once. + return if @poise_defined_in + # Parse out just the filenames. + caller_paths = caller_array.map {|line| line[CALLER_REGEXP, 1] } + # Find the first non-poise, non-chef line. This assumes Halite + # transformation which I'm not thrilled about. + caller_path = caller_paths.find do |line| + line && !line.start_with?(POISE_LIB_ROOT) && !line.start_with?(CHEF_LIB_ROOT) + end + raise Poise::Error.new("Unable to find a caller path for: #{caller_array.inspect}") unless caller_path + if ::File::ALT_SEPARATOR + caller_path.gsub!(::File::ALT_SEPARATOR, ::File::SEPARATOR) + end + Chef::Log.debug("[#{self.name}] Recording poise_defined_in as #{caller_path}") + @poise_defined_in = caller_path + end + + # @api private + def inherited(klass) + super + klass.poise_defined!(caller) + end + + def included(klass) + super + klass.extend(ClassMethods) + klass.poise_defined!(caller) + end + end + + extend ClassMethods + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/fused.rb b/cookbooks/poise/files/halite_gem/poise/helpers/fused.rb new file mode 100644 index 0000000..8b67bea --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/fused.rb @@ -0,0 +1,127 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/provider' + + +module Poise + module Helpers + # Resource mixin to create "fused" resources where the resource and provider + # are implemented in the same class. + # + # @since 2.0.0 + # @example + # class Chef::Resource::MyResource < Chef::Resource + # include Poise(fused: true) + # attribute(:path, kind_of: String) + # attribute(:message, kind_of: String) + # action(:run) do + # file new_resource.path do + # content new_resource.message + # end + # end + # end + module Fused + # Hack is_a? so that the DSL will consider this a Provider for the + # purposes of attaching enclosing_provider. + # + # @api private + # @param klass [Class] + # @return [Boolean] + def is_a?(klass) + if klass == Chef::Provider + # Lies, damn lies, and Ruby code. + true + else + super + end + end + + # Hack provider_for_action so that the resource is also the provider. + # + # @api private + # @param action [Symbol] + # @return [Chef::Provider] + def provider_for_action(action) + provider(self.class.fused_provider_class) unless provider + super + end + + # @!classmethods + module ClassMethods + # Define a provider action. The block should contain the usual provider + # code. + # + # @param name [Symbol] Name of the action. + # @param block [Proc] Action implementation. + # @example + # action(:run) do + # file '/temp' do + # user 'root' + # content 'temp' + # end + # end + def action(name, &block) + fused_actions[name.to_sym] = block + # Make sure this action is allowed, also sets the default if first. + if respond_to?(:actions) + actions(name.to_sym) + end + end + + # Storage accessor for fused action blocks. Maps action name to proc. + # + # @api private + # @return [Hash] + def fused_actions + (@fused_actions ||= {}) + end + + # Create a provider class for the fused actions in this resource. + # Inherits from the fused provider class of the resource's superclass if + # present. + # + # @api private + # @return [Class] + def fused_provider_class + @fused_provider_class ||= begin + provider_superclass = begin + self.superclass.fused_provider_class + rescue NoMethodError + Chef::Provider + end + actions = fused_actions + class_name = self.name + Class.new(provider_superclass) do + include Poise + define_singleton_method(:name) { class_name + ' (fused)' } + actions.each do |action, block| + define_method(:"action_#{action}", &block) + end + end + end + end + + def included(klass) + super + klass.extend(ClassMethods) + end + end + + extend ClassMethods + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/include_recipe.rb b/cookbooks/poise/files/halite_gem/poise/helpers/include_recipe.rb new file mode 100644 index 0000000..2b84e30 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/include_recipe.rb @@ -0,0 +1,62 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise/helpers/subcontext_block' +require 'poise/subcontext/runner' + + +module Poise + module Helpers + # A provider mixin to add #include_recipe that can be called from action + # methods. + # + # @since 2.0.0 + module IncludeRecipe + include Poise::Helpers::SubcontextBlock + + def include_recipe(*recipes) + loaded_recipes = [] + subcontext = subcontext_block do + recipes.flatten.each do |recipe| + case recipe + when String + # Process normally + Chef::Log.debug("Loading recipe #{recipe} via include_recipe (poise)") + loaded_recipes += run_context.include_recipe(recipe) + when Proc + # Pretend its a block of recipe code + fake_recipe = Chef::Recipe.new(cookbook_name, new_resource.recipe_name, run_context) + fake_recipe.instance_eval(&recipe) + loaded_recipes << fake_recipe + end + end + end + # Converge the new context. + Poise::Subcontext::Runner.new(new_resource, subcontext).converge + collection = global_resource_collection + subcontext.resource_collection.each do |r| + Chef::Log.debug("Poise::IncludeRecipe: Adding #{r} to global collection #{collection.object_id}") + # Insert the local resource into the global context + collection.insert(r) + # Skip the iterator forward so we don't double-execute the inserted resource + # If running at compile time, the iterator is nil + collection.iterator.skip_forward if collection.iterator + end + loaded_recipes + end + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/inversion.rb b/cookbooks/poise/files/halite_gem/poise/helpers/inversion.rb new file mode 100644 index 0000000..76b64ba --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/inversion.rb @@ -0,0 +1,414 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/node' +require 'chef/node_map' +require 'chef/provider' +require 'chef/resource' + +require 'poise/backports' +require 'poise/helpers/defined_in' +require 'poise/error' +require 'poise/helpers/inversion/options_resource' +require 'poise/utils/resource_provider_mixin' + + +module Poise + module Helpers + # A mixin for dependency inversion in Chef. + # + # @since 2.0.0 + module Inversion + autoload :OptionsResource, 'poise/helpers/inversion/options_resource' + autoload :OptionsProvider, 'poise/helpers/inversion/options_provider' + + include Poise::Utils::ResourceProviderMixin + + # Resource implementation for {Poise::Helpers::Inversion}. + # @see Poise::Helpers::Inversion + module Resource + # @overload options(val=nil) + # Set or return provider options for all providers. + # @param val [Hash] Provider options to set. + # @return [Hash] + # @example + # my_resource 'thing_one' do + # options depends: 'thing_two' + # end + # @overload options(provider, val=nil) + # Set or return provider options for a specific provider. + # @param provider [Symbol] Provider to set for. + # @param val [Hash] Provider options to set. + # @return [Hash] + # @example + # my_resource 'thing_one' do + # options :my_provider, depends: 'thing_two' + # end + def options(provider=nil, val=nil) + key = :options + if !val && provider.is_a?(Hash) + val = provider + elsif provider + key = :"options_#{provider}" + end + set_or_return(key, val ? Mash.new(val) : val, kind_of: Hash, default: lazy { Mash.new }) + end + + # Allow setting the provider directly using the same names as the attribute + # settings. + # + # @param val [String, Symbol, Class, nil] Value to set the provider to. + # @return [Class] + # @example + # my_resource 'thing_one' do + # provider :my_provider + # end + def provider(val=nil) + if val && !val.is_a?(Class) + resource_names = [resource_name] + # If subclass_providers! might be in play, check for those names too. + resource_names.concat(self.class.subclass_resource_equivalents) if self.class.respond_to?(:subclass_resource_equivalents) + # Silly ruby tricks to find the first provider that exists and no more. + provider_class = resource_names.lazy.map {|name| Poise::Helpers::Inversion.provider_for(name, node, val) }.select {|x| x }.first + Poise.debug("[#{self}] Checking for an inversion provider for #{val}: #{provider_class && provider_class.name}") + val = provider_class if provider_class + end + super + end + + # Set or return the array of provider names to be blocked from + # auto-resolution. + # + # @param val [String, Array] Value to set. + # @return [Array] + def provider_no_auto(val=nil) + # Coerce to an array. + val = Array(val).map(&:to_s) if val + set_or_return(:provider_no_auto, val, kind_of: Array, default: []) + end + + # @!classmethods + module ClassMethods + # Options resource class. + attr_reader :inversion_options_resource_class + # Options provider class. + attr_reader :inversion_options_provider_class + + # @overload inversion_options_resource() + # Return the options resource mode for this class. + # @return [Boolean] + # @overload inversion_options_resource(val) + # Set the options resource mode for this class. Set to true to + # automatically create an options resource. Defaults to true. + # @param val [Boolean] Enable/disable setting. + # @return [Boolean] + def inversion_options_resource(val=nil) + @poise_inversion_options_resource = val unless val.nil? + @poise_inversion_options_resource + end + + # Create resource and provider classes for an options resource. + # + # @param name [String, Symbol] DSL name for the base resource. + # @return [void] + def create_inversion_options_resource!(name) + enclosing_class = self + options_resource_name = :"#{name}_options" + # Create the resource class. + @inversion_options_resource_class = Class.new(Chef::Resource) do + include Poise::Helpers::Inversion::OptionsResource + define_singleton_method(:name) do + "#{enclosing_class}::OptionsResource" + end + define_singleton_method(:inversion_resource_class) do + enclosing_class + end + provides(options_resource_name) + inversion_resource(name) + end + # Create the provider class. + @inversion_options_provider_class = Class.new(Chef::Provider) do + include Poise::Helpers::Inversion::OptionsProvider + define_singleton_method(:name) do + "#{enclosing_class}::OptionsProvider" + end + define_singleton_method(:inversion_resource_class) do + enclosing_class + end + provides(options_resource_name) + end + end + + # Wrap #provides() to create an options resource if desired. + # + # @param name [Symbol] Resource name + # return [void] + def provides(name, *args, &block) + create_inversion_options_resource!(name) if inversion_options_resource + super(name, *args, &block) if defined?(super) + end + + def included(klass) + super + klass.extend(ClassMethods) + end + end + + extend ClassMethods + end + + # Provider implementation for {Poise::Helpers::Inversion}. + # @see Poise::Helpers::Inversion + module Provider + include DefinedIn + + # Compile all the different levels of inversion options together. + # + # @return [Hash] + # @example + # def action_run + # if options['depends'] + # # ... + # end + # end + def options + @options ||= self.class.inversion_options(node, new_resource) + end + + # @!classmethods + module ClassMethods + # @overload inversion_resource() + # Return the inversion resource name for this class. + # @return [Symbo, nill] + # @overload inversion_resource(val) + # Set the inversion resource name for this class. You can pass either + # a symbol in DSL format or a resource class that uses Poise. This + # name is used to determine which resources the inversion provider is + # a candidate for. + # @param val [Symbol, Class] Name to set. + # @return [Symbol, nil] + def inversion_resource(val=Poise::NOT_PASSED) + if val != Poise::NOT_PASSED + val = val.resource_name if val.is_a?(Class) + Chef::Log.debug("[#{self.name}] Setting inversion resource to #{val}") + @poise_inversion_resource = val.to_sym + end + if defined?(@poise_inversion_resource) + @poise_inversion_resource + else + Poise::Utils.ancestor_send(self, :inversion_resource, default: nil) + end + end + + # @overload inversion_attribute() + # Return the inversion attribute name(s) for this class. + # @return [Array, nil] + # @overload inversion_attribute(val) + # Set the inversion attribute name(s) for this class. This is + # used by {.resolve_inversion_attribute} to load configuration data + # from node attributes. To specify a nested attribute pass an array + # of strings corresponding to the keys. + # @param val [String, Array] Attribute path. + # @return [Array, nil] + def inversion_attribute(val=Poise::NOT_PASSED) + if val != Poise::NOT_PASSED + # Coerce to an array of strings. + val = Array(val).map {|name| name.to_s } + @poise_inversion_attribute = val + end + if defined?(@poise_inversion_attribute) + @poise_inversion_attribute + else + Poise::Utils.ancestor_send(self, :inversion_attribute, default: nil) + end + end + + # Default attribute paths to check for inversion options. Based on + # the cookbook this class and its superclasses are defined in. + # + # @param node [Chef::Node] Node to load from. + # @return [Array>] + def default_inversion_attributes(node) + klass = self + tried = [] + while klass.respond_to?(:poise_defined_in_cookbook) + cookbook = klass.poise_defined_in_cookbook(node.run_context) + if node[cookbook] + return [cookbook] + end + tried << cookbook + klass = klass.superclass + end + raise Poise::Error.new("Unable to find inversion attributes, tried: #{tried.join(', ')}") + end + + # Resolve the node attribute used as the base for inversion options + # for this class. This can be set explicitly with {.inversion_attribute} + # or the default is to use the name of the cookbook the provider is + # defined in. + # + # @param node [Chef::Node] Node to load from. + # @return [Chef::Node::Attribute] + def resolve_inversion_attribute(node) + # Default to using just the name of the cookbook. + attribute_names = inversion_attribute || default_inversion_attributes(node) + return {} if attribute_names.empty? + attribute_names.inject(node) do |memo, key| + memo[key] || begin + raise Poise::Error.new("Attribute #{key} not set when expanding inversion attribute for #{self.name}: #{memo}") + end + end + end + + # Compile all the different levels of inversion options together. + # + # @param node [Chef::Node] Node to load from. + # @param resource [Chef::Resource] Resource to load from. + # @return [Hash] + def inversion_options(node, resource) + Mash.new.tap do |opts| + attrs = resolve_inversion_attribute(node) + # Cast the run state to a Mash because string vs. symbol keys. I can + # at least promise poise_inversion will be a str so cut down on the + # amount of data to convert. + run_state = Mash.new(node.run_state.fetch('poise_inversion', {}).fetch(inversion_resource, {}))[resource.name] || {} + # Class-level defaults. + opts.update(default_inversion_options(node, resource)) + # Resource options for all providers. + opts.update(resource.options) if resource.respond_to?(:options) + # Global provider from node attributes. + opts.update(provider: attrs['provider']) if attrs['provider'] + # Attribute options for all providers. + opts.update(attrs['options']) if attrs['options'] + # Resource options for this provider. + opts.update(resource.options(provides)) if resource.respond_to?(:options) + # Attribute options for this resource name. + opts.update(attrs[resource.name]) if attrs[resource.name] + # Options resource options for all providers. + opts.update(run_state['*']) if run_state['*'] + # Options resource options for this provider. + opts.update(run_state[provides]) if run_state[provides] + # Vomitdebug output for tracking down weirdness. + Poise.debug("[#{resource}] Resolved inversion options: #{opts.inspect}") + end + end + + # Default options data for this provider class. + # + # @param node [Chef::Node] Node to load from. + # @param resource [Chef::Resource] Resource to load from. + # @return [Hash] + def default_inversion_options(node, resource) + {} + end + + # Resolve which provider name should be used for a resource. + # + # @param node [Chef::Node] Node to load from. + # @param resource [Chef::Resource] Resource to query. + # @return [String] + def resolve_inversion_provider(node, resource) + inversion_options(node, resource)['provider'] || 'auto' + end + + # Override the normal #provides to set the inversion provider name + # instead of adding to the normal provider map. + # + # @overload provides() + # Return the inversion provider name for the class. + # @return [Symbol] + # @overload provides(name, opts={}, &block) + # Set the inversion provider name for the class. + # @param name [Symbol] Provider name. + # @param opts [Hash] NodeMap filter options. + # @param block [Proc] NodeMap filter proc. + # @return [Symbol] + def provides(name=nil, opts={}, &block) + if name + raise Poise::Error.new("Inversion resource name not set for #{self.name}") unless inversion_resource + @poise_inversion_provider = name + Chef::Log.debug("[#{self.name}] Setting inversion provider name to #{name}") + Poise::Helpers::Inversion.provider_map(inversion_resource).set(name.to_sym, self, opts, &block) + # Set the actual Chef-level provides name for DSL dispatch. + super(inversion_resource) + end + @poise_inversion_provider + end + + # Override the default #provides? to check for our inverted providers. + # + # @api private + # @param node [Chef::Node] Node to use for attribute checks. + # @param resource [Chef::Resource] Resource instance to match. + # @return [Boolean] + def provides?(node, resource) + raise Poise::Error.new("Inversion resource name not set for #{self.name}") unless inversion_resource + resource_name_equivalents = {resource.resource_name => true} + # If subclass_providers! might be in play, check for those names too. + if resource.class.respond_to?(:subclass_resource_equivalents) + resource.class.subclass_resource_equivalents.each do |name| + resource_name_equivalents[name] = true + end + end + return false unless resource_name_equivalents[inversion_resource] + provider_name = resolve_inversion_provider(node, resource).to_s + Poise.debug("[#{resource}] Checking provides? on #{self.name}. Got provider_name #{provider_name.inspect}") + provider_name == provides.to_s || ( provider_name == 'auto' && !resource.provider_no_auto.include?(provides.to_s) && provides_auto?(node, resource) ) + end + + # Subclass hook to provide auto-detection for providers. + # + # @param node [Chef::Node] Node to check against. + # @param resource [Chef::Resource] Resource to check against. + # @return [Boolean] + def provides_auto?(node, resource) + false + end + + def included(klass) + super + klass.extend(ClassMethods) + end + end + + extend ClassMethods + end + + # The provider map for a given resource type. + # + # @param resource_type [Symbol] Resource type in DSL format. + # @return [Chef::NodeMap] + # @example + # Poise::Helpers::Inversion.provider_map(:my_resource) + def self.provider_map(resource_type) + @provider_maps ||= {} + @provider_maps[resource_type.to_sym] ||= Chef::NodeMap.new + end + + # Find a specific provider class for a resource. + # + # @param resource_type [Symbol] Resource type in DSL format. + # @param node [Chef::Node] Node to use for the lookup. + # @param provider_type [Symbol] Provider type in DSL format. + # @return [Class] + # @example + # Poise::Helpers::Inversion.provider_for(:my_resource, node, :my_provider) + def self.provider_for(resource_type, node, provider_type) + provider_map(resource_type).get(node, provider_type.to_sym) + end + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/inversion/options_provider.rb b/cookbooks/poise/files/halite_gem/poise/helpers/inversion/options_provider.rb new file mode 100644 index 0000000..9ea5f94 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/inversion/options_provider.rb @@ -0,0 +1,41 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + + +module Poise + module Helpers + module Inversion + # A mixin for inversion options providers. + # + # @api private + # @since 2.0.0 + # @see Poise::Helper::Inversion + module OptionsProvider + # @api private + def self.included(klass) + klass.class_exec { include Poise } + end + + # A blank run action. + # + # @return [void] + def action_run + # This space left intentionally blank. + end + end + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/inversion/options_resource.rb b/cookbooks/poise/files/halite_gem/poise/helpers/inversion/options_resource.rb new file mode 100644 index 0000000..9ff47a7 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/inversion/options_resource.rb @@ -0,0 +1,115 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/mash' + +require 'poise/backports' +require 'poise/error' + + +module Poise + module Helpers + module Inversion + # A mixin for inversion options resources. + # + # @api private + # @since 2.0.0 + # @see Poise::Helpers::Inversion + module OptionsResource + include Poise + + # Method missing delegation to allow DSL-style options. + # + # @example + # my_app_options 'app' do + # key1 'value1' + # key2 'value2' + # end + def method_missing(method_sym, *args, &block) + super(method_sym, *args, &block) + rescue NoMethodError + # First time we've seen this key and using it as an rvalue, NOPE.GIF. + raise unless !args.empty? || block || _options[method_sym] + if !args.empty? || block + _options[method_sym] = block || args.first + end + _options[method_sym] + end + + # Capture setting the provider and make it Do What I Mean. This does + # mean you can't set the actual provider for the options resource, which + # is fine because the provider is a no-op. + # + # @api private + def provider(val=Poise::NOT_PASSED) + if val == Poise::NOT_PASSED + super() + else + _options[:provider] = val + end + end + + # Insert the options data in to the run state. This has to match the + # layout used in {Poise::Helpers::Inversion::Provider.inversion_options}. + # + # @api private + def after_created + raise Poise::Error.new("Inversion resource name not set for #{self.class.name}") unless self.class.inversion_resource + node.run_state['poise_inversion'] ||= {} + node.run_state['poise_inversion'][self.class.inversion_resource] ||= {} + node.run_state['poise_inversion'][self.class.inversion_resource][resource] ||= {} + node.run_state['poise_inversion'][self.class.inversion_resource][resource][for_provider] ||= {} + node.run_state['poise_inversion'][self.class.inversion_resource][resource][for_provider].update(_options) + end + + module ClassMethods + # @overload inversion_resource() + # Return the inversion resource name for this class. + # @return [Symbol] + # @overload inversion_resource(val) + # Set the inversion resource name for this class. You can pass either + # a symbol in DSL format or a resource class that uses Poise. This + # name is used to determine which resources the inversion provider is + # a candidate for. + # @param val [Symbol, Class] Name to set. + # @return [Symbol] + def inversion_resource(val=nil) + if val + val = val.resource_name if val.is_a?(Class) + Chef::Log.debug("[#{self.name}] Setting inversion resource to #{val}") + @poise_inversion_resource = val.to_sym + end + @poise_inversion_resource || (superclass.respond_to?(:inversion_resource) ? superclass.inversion_resource : nil) + end + + # @api private + def included(klass) + super + klass.extend(ClassMethods) + klass.class_exec do + actions(:run) + attribute(:resource, kind_of: String, name_attribute: true) + attribute(:for_provider, kind_of: [String, Symbol], default: '*') + attribute(:_options, kind_of: Hash, default: lazy { Mash.new }) + end + end + end + + extend ClassMethods + end + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/lazy_default.rb b/cookbooks/poise/files/halite_gem/poise/helpers/lazy_default.rb new file mode 100644 index 0000000..59a04c9 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/lazy_default.rb @@ -0,0 +1,79 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/version' + + +module Poise + module Helpers + # Resource mixin to allow lazyily-evaluated defaults in resource attributes. + # This is designed to be used with {LWRPPolyfill} or a similar #attributes + # method. + # + # @since 1.0.0 + # @example + # class MyResource < Chef::Resource + # include Poise::Helpers::LWRPPolyfill + # include Poise::Helpers::LazyDefault + # attribute(:path, default: lazy { name + '_temp' }) + # end + module LazyDefault + # Check if this version of Chef already supports lazy defaults. This is + # true for Chef 12.5+. + # + # @since 2.0.3 + # @api private + # @return [Boolean] + def self.needs_polyfill? + @needs_polyfill ||= Gem::Requirement.new('< 12.5.pre').satisfied_by?(Gem::Version.new(Chef::VERSION)) + end + + # Override the default set_or_return to support lazy evaluation of the + # default value. This only actually matters when it is called from a class + # level context via #attributes. + def set_or_return(symbol, arg, validation) + if LazyDefault.needs_polyfill? && validation && validation[:default].is_a?(Chef::DelayedEvaluator) + validation = validation.dup + if (arg.nil? || arg == Poise::NOT_PASSED) && (!instance_variable_defined?(:"@#{symbol}") || instance_variable_get(:"@#{symbol}").nil?) + validation[:default] = instance_eval(&validation[:default]) + else + # Clear the default. + validation.delete(:default) + end + end + super(symbol, arg, validation) + end + + # @!classmethods + module ClassMethods + # Create a lazyily-evaluated block. + # + # @param block [Proc] Callable to return the default value. + # @return [Chef::DelayedEvaluator] + def lazy(&block) + Chef::DelayedEvaluator.new(&block) + end + + def included(klass) + super + klass.extend(ClassMethods) + end + end + + extend ClassMethods + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/lwrp_polyfill.rb b/cookbooks/poise/files/halite_gem/poise/helpers/lwrp_polyfill.rb new file mode 100644 index 0000000..a8c2541 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/lwrp_polyfill.rb @@ -0,0 +1,163 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/resource' + +require 'poise/utils/resource_provider_mixin' + + +module Poise + module Helpers + # A resource and provider mixin to add back some compatability with Chef's + # LWRPBase classes. + # + # @since 1.0.0 + module LWRPPolyfill + include Poise::Utils::ResourceProviderMixin + + # Provide default_action and actions like LWRPBase but better equipped for subclassing. + module Resource + def initialize(*args) + super + # Try to not stomp on stuff if already set in a parent. Coerce @action + # to an array because this behavior may change in the future in Chef. + @action = self.class.default_action if Array(@action) == [:nothing] + (@allowed_actions << self.class.actions).flatten!.uniq! + end + + module ClassMethods + # @overload default_action() + # Get the default action for this resource class. If no explicit + # default is set, the first action in the list will be used. + # @see #actions + # @return [Array] + # @overload default_action(name) + # Set the default action for this resource class. If this action is + # not already allowed, it will be added. + # @note It is idiomatic to use {#actions} instead, with the first + # action specified being the default. + # @param name [Symbol, Array] Name of the action(s). + # @return [Array] + # @example + # class MyApp < Chef::Resource + # include Poise + # default_action(:install) + # end + def default_action(name=nil) + if name + name = Array(name).flatten.map(&:to_sym) + @default_action = name + actions(*name) + end + if @default_action + @default_action + elsif respond_to?(:superclass) && superclass != Chef::Resource && superclass.respond_to?(:default_action) && superclass.default_action && Array(superclass.default_action) != %i{nothing} + superclass.default_action + elsif first_non_nothing = actions.find {|action| action != :nothing } + [first_non_nothing] + else + %i{nothing} + end + end + + # @overload actions() + # Get all actions allowed for this resource class. This includes + # any actions allowed on parent classes. + # @return [Array] + # @overload actions(*names) + # Set actions as allowed for this resource class. These must + # correspond with action methods in the provider class(es). + # @param names [Array] One or more actions to set. + # @return [Array] + # @example + # class MyApp < Chef::Resource + # include Poise + # actions(:install, :uninstall) + # end + def actions(*names) + @actions ||= ( respond_to?(:superclass) && superclass.respond_to?(:actions) && superclass.actions.dup ) || ( respond_to?(:superclass) && superclass != Chef::Resource && superclass.respond_to?(:allowed_actions) && superclass.allowed_actions.dup ) || [] + (@actions << names).tap {|actions| actions.flatten!; actions.uniq! } + end + + # Create a resource property (née attribute) on this resource class. + # This follows the same usage as the helper of the same name in Chef + # LWRPs. + # + # @param name [Symbol] Name of the property. + # @param opts [Hash] Validation options and flags. + # @return [void] + # @example + # class MyApp < Chef::Resource + # include Poise + # attribute(:path, name_attribute: true) + # attribute(:port, kind_of: Integer, default: 8080) + # end + def attribute(name, opts={}) + # Freeze the default value. This is done upstream too in Chef 12.5+. + opts[:default].freeze if opts && opts[:default] + # Ruby 1.8 can go to hell. + define_method(name) do |arg=nil, &block| + arg = block if arg.nil? # Try to allow passing either. + set_or_return(name, arg, opts) + end + end + + # For forward compat with Chef 12.5+. + alias_method :property, :attribute + + def included(klass) + super + klass.extend(ClassMethods) + end + end + + extend ClassMethods + end + + # Helper to handle load_current_resource for direct subclasses of Provider + module Provider + module LoadCurrentResource + def load_current_resource + @current_resource = if new_resource + new_resource.class.new(new_resource.name, run_context) + else + # Better than nothing, subclass can overwrite anyway. + Chef::Resource.new(nil, run_context) + end + end + end + + # @!classmethods + module ClassMethods + def included(klass) + super + klass.extend(ClassMethods) + + # Mask Chef::Provider#load_current_resource because it throws NotImplementedError. + if klass.is_a?(Class) && klass.superclass == Chef::Provider + klass.send(:include, LoadCurrentResource) + end + + # Reinstate the Chef DSL, removed in Chef 12. + klass.send(:include, Chef::DSL::Recipe) + end + end + + extend ClassMethods + end + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/notifying_block.rb b/cookbooks/poise/files/halite_gem/poise/helpers/notifying_block.rb new file mode 100644 index 0000000..72708c9 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/notifying_block.rb @@ -0,0 +1,78 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise/helpers/subcontext_block' +require 'poise/subcontext/runner' + + +module Poise + module Helpers + # A provider mixin to provide #notifying_block, a scoped form of Chef's + # use_inline_resources. + # + # @since 1.0.0 + # @example + # class MyProvider < Chef::Provider + # include Chef::Helpers::NotifyingBlock + # + # def action_run + # notifying_block do + # template '/etc/myapp.conf' do + # # ... + # end + # end + # end + # end + module NotifyingBlock + include Poise::Helpers::SubcontextBlock + + private + + # Create and converge a subcontext for the recipe DSL. This is similar to + # Chef's use_inline_resources but is scoped to a block. All DSL resources + # declared inside the block will be converged when the block returns, and + # the updated_by_last_action flag will be set if any of the inner + # resources are updated. + # + # @api public + # @param block [Proc] Block to run in the subcontext. + # @return [void] + # @example + # def action_run + # notifying_block do + # template '/etc/myapp.conf' do + # # ... + # end + # end + # end + def notifying_block(&block) + # Make sure to mark the resource as updated-by-last-action if + # any sub-run-context resources were updated (any actual + # actions taken against the system) during the + # sub-run-context convergence. + begin + subcontext = subcontext_block(&block) + # Converge the new context. + Poise::Subcontext::Runner.new(new_resource, subcontext).converge + ensure + new_resource.updated_by_last_action( + subcontext && subcontext.resource_collection.any?(&:updated?) + ) + end + end + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/option_collector.rb b/cookbooks/poise/files/halite_gem/poise/helpers/option_collector.rb new file mode 100644 index 0000000..dfc5522 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/option_collector.rb @@ -0,0 +1,144 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/mash' + +require 'poise/error' + + +module Poise + module Helpers + # A resource mixin to add a new kind of attribute, an option collector. + # These attributes can act as mini-DSLs for things which would otherwise be + # key/value pairs. + # + # @since 1.0.0 + # @example Defining an option collector + # class MyResource < Chef::Resource + # include Poise::Helpers::OptionCollector + # attribute(:my_options, option_collector: true) + # end + # @example Using an option collector + # my_resource 'name' do + # my_options do + # key1 'value1' + # key2 'value2' + # end + # end + module OptionCollector + # Instance context used to eval option blocks. + # @api private + class OptionEvalContext + attr_reader :_options + + def initialize(parent, forced_keys) + @parent = parent + @forced_keys = forced_keys + @_options = {} + end + + def method_missing(method_sym, *args, &block) + # Deal with forced keys. + if @forced_keys.include?(method_sym) + @_options[method_sym] = args.first || block if !args.empty? || block + return @_options[method_sym] + end + # Try the resource context. + @parent.send(method_sym, *args, &block) + rescue NameError + # Even though method= in the block will set a variable instead of + # calling method_missing, still try to cope in case of self.method=. + method_sym = method_sym.to_s.chomp('=').to_sym + if !args.empty? || block + @_options[method_sym] = args.first || block + elsif !@_options.include?(method_sym) + # We haven't seen this name before, re-raise the NameError. + raise + end + @_options[method_sym] + end + end + + # @!classmethods + module ClassMethods + # Override the normal #attribute() method to support defining option + # collectors too. + def attribute(name, options={}) + # If present but false-y, make sure it is removed anyway so it + # doesn't confuse ParamsValidate. + if options.delete(:option_collector) + option_collector_attribute(name, options) + else + super + end + end + + # Define an option collector attribute. Normally used via {.attribute}. + # + # @param name [String, Symbol] Name of the attribute to define. + # @param default [Hash] Default value for the options. + # @param parser [Proc, Symbol] Optional parser method. If a symbol it is + # called as a method on self. Takes a non-hash value and returns a + # hash of its parsed representation. + # @param forced_keys [Array, Set] Method names that will be forced + # to be options rather than calls to the parent resource. + def option_collector_attribute(name, default: {}, parser: nil, forced_keys: Set.new) + raise Poise::Error.new("Parser must be a Proc or Symbol: #{parser.inspect}") if parser && !(parser.is_a?(Proc) || parser.is_a?(Symbol)) + # Cast to a set at definition time. + forced_keys = Set.new(forced_keys) unless forced_keys.is_a?(Set) + # Never allow name to be called accidentally since it does really wonky things. + forced_keys.add(:name) + # Unlike LWRPBase.attribute, I don't care about Ruby 1.8. Worlds tiniest violin. + define_method(name.to_sym) do |arg=nil, &block| + iv_sym = :"@#{name}" + + value = instance_variable_get(iv_sym) || begin + default = instance_eval(&default) if default.is_a?(Chef::DelayedEvaluator) # Handle lazy{} + Mash.new(default) # Wrap in a mash because fuck str vs sym. + end + if arg + if !arg.is_a?(Hash) && parser + arg = case parser + when Proc + instance_exec(arg, &parser) + when Symbol + send(parser, arg) + end + end + raise Exceptions::ValidationFailed, "Option #{name} must be a Hash" if !arg.is_a?(Hash) + # Should this and the update below be a deep merge? + value.update(arg) + end + if block + ctx = OptionEvalContext.new(self, forced_keys) + ctx.instance_exec(&block) + value.update(ctx._options) + end + instance_variable_set(iv_sym, value) + value + end + end + + def included(klass) + super + klass.extend(ClassMethods) + end + end + + extend ClassMethods + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/resource_cloning.rb b/cookbooks/poise/files/halite_gem/poise/helpers/resource_cloning.rb new file mode 100644 index 0000000..54c259c --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/resource_cloning.rb @@ -0,0 +1,72 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + + +module Poise + module Helpers + # A resource mixin to disable resource cloning. + # + # @since 2.2.0 + # @example + # class MyResource < Chef::Resource + # include Poise::Helpers::ResourceCloning + # end + module ResourceCloning + # Override to disable resource cloning on Chef 12.0. + # + # @api private + def load_prior_resource(*args) + # Do nothing. + end + + # Override to disable resource cloning on Chef 12.1+. + # + # @api private + def load_from(*args) + # Do nothing. + end + + # Monkeypatch for Chef::ResourceBuilder to silence the warning if needed. + # + # @api private + module ResourceBuilderPatch + # @api private + def self.install! + begin + require 'chef/resource_builder' + Chef::ResourceBuilder.send(:prepend, ResourceBuilderPatch) + rescue LoadError + # For 12.0, this is already taken care of. + end + end + + # @api private + def emit_cloned_resource_warning + super unless resource.is_a?(ResourceCloning) + end + + # @api private + def emit_harmless_cloning_debug + super unless resource.is_a?(ResourceCloning) + end + end + + # Install the patch. + ResourceBuilderPatch.install! + + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/resource_name.rb b/cookbooks/poise/files/halite_gem/poise/helpers/resource_name.rb new file mode 100644 index 0000000..c5d40e0 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/resource_name.rb @@ -0,0 +1,107 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/mixin/convert_to_class_name' + + +module Poise + module Helpers + # A resource mixin to automatically set @resource_name. + # + # @since 1.0.0 + # @example + # class MyResource < Chef::Resource + # include Poise::Helpers::ResourceName + # provides(:my_resource) + # end + module ResourceName + def initialize(*args) + super + # If provides() was explicitly set, unconditionally set @resource_name. + # This helps when subclassing core Chef resources which set it + # themselves in #initialize. + if self.class.resource_name(false) + @resource_name = self.class.resource_name + else + @resource_name ||= self.class.resource_name + end + end + + # @!classmethods + module ClassMethods + # Set the DSL name for the the resource class. + # + # @param name [Symbol] Name of the resource. + # @return [void] + # @example + # class MyResource < Chef::Resource + # include Poise::Resource::ResourceName + # provides(:my_resource) + # end + def provides(name, *args, &block) + # Patch self.constantize so this can cope with anonymous classes. + # This does require that the anonymous class define self.name though. + if self.name && respond_to?(:constantize) + old_constantize = instance_method(:constantize) + define_singleton_method(:constantize) do |const_name| + ( const_name == self.name ) ? self : old_constantize.bind(self).call(const_name) + end + end + # Store the name for later. + @provides_name ||= name + # Call the original if present. The defined? is for old Chef. + super(name, *args, &block) if defined?(super) + end + + # Retreive the DSL name for the resource class. If not set explicitly + # via {provides} this will try to auto-detect based on the class name. + # + # @param auto [Boolean] Try to auto-detect based on class name. + # @return [Symbol] + def resource_name(auto=true) + # In 12.4+ we need to proxy through the super class for setting. + return super(auto) if defined?(super) && (auto.is_a?(Symbol) || auto.is_a?(String)) + return @provides_name unless auto + @provides_name || if name + mode = if name.start_with?('Chef::Resource') + [name, 'Chef::Resource'] + else + [name.split('::').last] + end + Chef::Mixin::ConvertToClassName.convert_to_snake_case(*mode).to_sym + elsif defined?(super) + # No name on 12.4+ probably means this is an LWRP, use super(). + super() + end + end + + # Used by Resource#to_text to find the human name for the resource. + # + # @api private + def dsl_name + resource_name.to_s + end + + def included(klass) + super + klass.extend(ClassMethods) + end + end + + extend ClassMethods + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/resource_subclass.rb b/cookbooks/poise/files/halite_gem/poise/helpers/resource_subclass.rb new file mode 100644 index 0000000..69c4ff7 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/resource_subclass.rb @@ -0,0 +1,93 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +begin + require 'chef/chef_class' +rescue LoadError + # This space left intentionally blank, fallback is below. +end + +require 'poise/error' +require 'poise/helpers/resource_name' + + +module Poise + module Helpers + # A resource mixin to help subclass existing resources. + # + # @since 2.3.0 + module ResourceSubclass + include ResourceName + + module ClassMethods + def subclass_providers!(superclass_resource_name=nil, resource_name: nil) + resource_name ||= self.resource_name + superclass_resource_name ||= if superclass.respond_to?(:resource_name) + superclass.resource_name + elsif superclass.respond_to?(:dsl_name) + superclass.dsl_name + else + raise Poise::Error.new("Unable to determine superclass resource name for #{superclass}. Please specify name manually via subclass_providers!('name').") + end.to_sym + # Deal with the node maps. + node_maps = {} + node_maps['handler map'] = Chef.provider_handler_map if defined?(Chef.provider_handler_map) + node_maps['priority map'] = if defined?(Chef.provider_priority_map) + Chef.provider_priority_map + else + require 'chef/platform/provider_priority_map' + Chef::Platform::ProviderPriorityMap.instance.send(:priority_map) + end + # Patch anything in the descendants tracker. + Chef::Provider.descendants.each do |provider| + node_maps["#{provider} node map"] = provider.node_map if defined?(provider.node_map) + end if defined?(Chef::Provider.descendants) + node_maps.each do |map_name, node_map| + map = node_map.respond_to?(:map, true) ? node_map.send(:map) : node_map.instance_variable_get(:@map) + if map.include?(superclass_resource_name) + Chef::Log.debug("[#{self}] Copying provider mapping in #{map_name} from #{superclass_resource_name} to #{resource_name}") + map[resource_name] = map[superclass_resource_name].dup + end + end + # Add any needed equivalent names. + if superclass.respond_to?(:subclass_resource_equivalents) + subclass_resource_equivalents.concat(superclass.subclass_resource_equivalents) + else + subclass_resource_equivalents << superclass_resource_name + end + subclass_resource_equivalents.uniq! + end + + # An array of names for the resources this class is equivalent to for + # the purposes of provider resolution. + # + # @return [Array] + def subclass_resource_equivalents + @subclass_resource_names ||= [resource_name.to_sym] + end + + # @api private + def included(klass) + super + klass.extend(ClassMethods) + end + end + + extend ClassMethods + end + + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/subcontext_block.rb b/cookbooks/poise/files/halite_gem/poise/helpers/subcontext_block.rb new file mode 100644 index 0000000..facdda9 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/subcontext_block.rb @@ -0,0 +1,72 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise/subcontext/resource_collection' + + +module Poise + module Helpers + # A provider mixin to help with creating subcontexts. Mostly for internal + # use within Poise. + # + # @since 1.0.0 + module SubcontextBlock + private + + def subcontext_block(parent_context=nil, &block) + # Setup a subcontext. + parent_context ||= @run_context + sub_run_context = parent_context.dup + # Reset state for the subcontext. In 12.4+ this uses the built-in + # support, otherwise do it manually. + if defined?(sub_run_context.initialize_child_state) + sub_run_context.initialize_child_state + else + # Audits was added in 12.1 I think. + sub_run_context.audits = {} if defined?(sub_run_context.audits) + # Dup and clear to preserve the default behavior without copy-pasta. + sub_run_context.immediate_notification_collection = parent_context.immediate_notification_collection.dup.clear + sub_run_context.delayed_notification_collection = parent_context.delayed_notification_collection.dup.clear + end + # Create the subcollection. + sub_run_context.resource_collection = Poise::Subcontext::ResourceCollection.new(parent_context.resource_collection) + # Create an accessor for the parent run context. + sub_run_context.define_singleton_method(:parent_run_context) { parent_context } + + # Declare sub-resources within the sub-run-context. Since they + # are declared here, they do not pollute the parent run-context. + begin + outer_run_context = @run_context + @run_context = sub_run_context + instance_eval(&block) + ensure + @run_context = outer_run_context + end + + # Return the inner context to do other things with + sub_run_context + end + + def global_resource_collection + collection = @run_context.resource_collection + while collection.respond_to?(:parent) && collection.parent + collection = collection.parent + end + collection + end + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/subresources.rb b/cookbooks/poise/files/halite_gem/poise/helpers/subresources.rb new file mode 100644 index 0000000..ce0f199 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/subresources.rb @@ -0,0 +1,29 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + + +module Poise + module Helpers + # Mixins and helpers for managing subresources, resources with a + # parent/child relationship. + # + # @since 2.0.0 + module Subresources + autoload :Child, 'poise/helpers/subresources/child' + autoload :Container, 'poise/helpers/subresources/container' + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/subresources/child.rb b/cookbooks/poise/files/halite_gem/poise/helpers/subresources/child.rb new file mode 100644 index 0000000..ef6a24a --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/subresources/child.rb @@ -0,0 +1,276 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/resource' + +require 'poise/error' +require 'poise/helpers/subresources/default_containers' + + +module Poise + module Helpers + module Subresources + # A resource mixin for child subresources. + # + # @since 1.0.0 + module Child + # Little class used to fix up the display of subresources in #to_text. + # Without this you get the full parent resource shown for @parent et al. + # @api private + class ParentRef + attr_accessor :resource + + def initialize(resource) + @resource = resource + end + + def inspect + to_text + end + + def to_text + if @resource.nil? + 'nil' + else + @resource.to_s + end + end + end + + # @overload parent() + # Get the parent resource for this child. This may be nil if the + # resource is set to parent_optional = true. + # @return [Chef::Resource, nil] + # @overload parent(val) + # Set the parent resource. The parent can be set as resource + # object, a string (either a bare resource name or a type[name] + # string), or a type:name hash. + # @param val [String, Hash, Chef::Resource] Parent resource to set. + # @return [Chef::Resource, nil] + def parent(*args) + # Lie about this method if the parent type is true. + if self.class.parent_type == true + raise NoMethodError.new("undefined method `parent' for #{self}") + end + _parent(:parent, self.class.parent_type, self.class.parent_optional, self.class.parent_auto, self.class.parent_default, *args) + end + + # Register ourself with parents in case this is not a nested resource. + # + # @api private + def after_created + super + self.class.parent_attributes.each_key do |name| + parent = self.send(name) + parent.register_subresource(self) if parent && parent.respond_to?(:register_subresource) + end + end + + private + + # Generic form of the parent getter/setter. + # + # @since 2.0.0 + # @see #parent + def _parent(name, parent_type, parent_optional, parent_auto, parent_default, *args) + # Allow using a DSL symbol as the parent type. + if parent_type.is_a?(Symbol) + parent_type = Chef::Resource.resource_for_node(parent_type, node) + end + # Grab the ivar for local use. + parent_ref = instance_variable_get(:"@#{name}") + if !args.empty? + val = args.first + if val.nil? + # Unsetting the parent. + parent = parent_ref = nil + else + if val.is_a?(String) && !val.include?('[') + raise Poise::Error.new("Cannot use a string #{name} without defining a parent type") if parent_type == Chef::Resource + # Try to find the most recent instance of parent_type with a + # matching name. This takes subclassing parent_type into account. + found_val = nil + iterator = run_context.resource_collection.respond_to?(:recursive_each) ? :recursive_each : :each + # This will find the last matching value due to overwriting + # found_val as it goes. Will be the nearest match. + run_context.resource_collection.public_send(iterator) do |res| + found_val = res if res.is_a?(parent_type) && res.name == val + end + # If found_val is nil, fall back to using lookup even though + # it won't work with subclassing, better than nothing? + val = found_val || "#{parent_type.resource_name}[#{val}]" + end + if val.is_a?(String) || val.is_a?(Hash) + parent = @run_context.resource_collection.find(val) + else + parent = val + end + if !parent.is_a?(parent_type) + raise Poise::Error.new("Parent resource is not an instance of #{parent_type.name}: #{val.inspect}") + end + parent_ref = ParentRef.new(parent) + end + elsif !parent_ref || !parent_ref.resource + if parent_default + parent = if parent_default.is_a?(Chef::DelayedEvaluator) + instance_eval(&parent_default) + else + parent_default + end + end + # The @parent_ref means we won't run this if we previously set + # ParentRef.new(nil). This means auto-lookup only happens during + # after_created. + if !parent && !parent_ref && parent_auto + # Automatic sibling lookup for sequential composition. + # Find the last instance of the parent class as the default parent. + # This is super flaky and should only be a last resort. + parent = Poise::Helpers::Subresources::DefaultContainers.find(parent_type, run_context, self_resource: self) + end + # Can't find a valid parent, if it wasn't optional raise an error. + raise Poise::Error.new("No #{name} found for #{self}") unless parent || parent_optional + parent_ref = ParentRef.new(parent) + else + parent = parent_ref.resource + end + raise Poise::Error.new("Cannot set the #{name} of #{self} to itself") if parent.equal?(self) + # Store the ivar back. + instance_variable_set(:"@#{name}", parent_ref) + # Return the actual resource. + parent + end + + module ClassMethods + # @overload parent_type() + # Get the class of the default parent link on this resource. + # @return [Class, Symbol] + # @overload parent_type(type) + # Set the class of the default parent link on this resource. + # @param type [Class, Symbol] Class to set. + # @return [Class, Symbol] + def parent_type(type=nil) + if type + raise Poise::Error.new("Parent type must be a class, symbol, or true, got #{type.inspect}") unless type.is_a?(Class) || type.is_a?(Symbol) || type == true + # Setting to true shouldn't actually do anything if a type was already set. + @parent_type = type unless type == true && !@parent_type.nil? + end + # First ancestor_send looks for a non-true && non-default value, + # second one is to check for default vs true if no real value is found. + @parent_type || Poise::Utils.ancestor_send(self, :parent_type, ignore: [Chef::Resource, true]) || Poise::Utils.ancestor_send(self, :parent_type, default: Chef::Resource) + end + + # @overload parent_optional() + # Get the optional mode for the default parent link on this resource. + # @return [Boolean] + # @overload parent_optional(val) + # Set the optional mode for the default parent link on this resource. + # @param val [Boolean] Mode to set. + # @return [Boolean] + def parent_optional(val=nil) + unless val.nil? + @parent_optional = val + end + if @parent_optional.nil? + Poise::Utils.ancestor_send(self, :parent_optional, default: false) + else + @parent_optional + end + end + + # @overload parent_auto() + # Get the auto-detect mode for the default parent link on this resource. + # @return [Boolean] + # @overload parent_auto(val) + # Set the auto-detect mode for the default parent link on this resource. + # @param val [Boolean] Mode to set. + # @return [Boolean] + def parent_auto(val=nil) + unless val.nil? + @parent_auto = val + end + if @parent_auto.nil? + Poise::Utils.ancestor_send(self, :parent_auto, default: true) + else + @parent_auto + end + end + + # @overload parent_default() + # Get the default value for the default parent link on this resource. + # @since 2.3.0 + # @return [Object, Chef::DelayedEvaluator] + # @overload parent_default(val) + # Set the default value for the default parent link on this resource. + # @since 2.3.0 + # @param val [Object, Chef::DelayedEvaluator] Default value to set. + # @return [Object, Chef::DelayedEvaluator] + def parent_default(*args) + unless args.empty? + @parent_default = args.first + end + if defined?(@parent_default) + @parent_default + else + Poise::Utils.ancestor_send(self, :parent_default) + end + end + + # Create a new kind of parent link. + # + # @since 2.0.0 + # @param name [Symbol] Name of the relationship. This becomes a method + # name on the resource instance. + # @param type [Class] Class of the parent. + # @param optional [Boolean] If the parent is optional. + # @param auto [Boolean] If the parent is auto-detected. + # @return [void] + def parent_attribute(name, type: Chef::Resource, optional: false, auto: true, default: nil) + name = :"parent_#{name}" + (@parent_attributes ||= {})[name] = type + define_method(name) do |*args| + _parent(name, type, optional, auto, default, *args) + end + end + + # Return the name of all parent relationships on this class. + # + # @since 2.0.0 + # @return [Hash] + def parent_attributes + {}.tap do |attrs| + # Grab superclass's attributes if possible. + attrs.update(Poise::Utils.ancestor_send(self, :parent_attributes, default: {})) + # Local default parent. + attrs[:parent] = parent_type + # Extra locally defined parents. + attrs.update(@parent_attributes) if @parent_attributes + # Remove anything with the type set to true. + attrs.reject! {|name, type| type == true } + end + end + + # @api private + def included(klass) + super + klass.extend(ClassMethods) + end + end + + extend ClassMethods + end + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/subresources/container.rb b/cookbooks/poise/files/halite_gem/poise/helpers/subresources/container.rb new file mode 100644 index 0000000..f218e86 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/subresources/container.rb @@ -0,0 +1,229 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/dsl/recipe' + +require 'poise/helpers/subcontext_block' +require 'poise/helpers/subresources/default_containers' + + +module Poise + module Helpers + module Subresources + # A resource mixin for subresource containers. + # + # @since 1.0.0 + module Container + # A resource collection that has much more condensed text output. This + # is used to show the value of @subresources during Chef's error formatting. + # @api private + class NoPrintingResourceCollection < Chef::ResourceCollection + def inspect + to_text + end + + def to_text + "[#{all_resources.map(&:to_s).join(', ')}]" + end + end + + include SubcontextBlock + include Chef::DSL::Recipe + + attr_reader :subresources + attr_reader :subcontexts + + def initialize(*args) + super + @subresources = NoPrintingResourceCollection.new + @subcontexts = [] + end + + def after_created + super + # Register as a default container if needed. + Poise::Helpers::Subresources::DefaultContainers.register!(self, run_context) if self.class.container_default + # Add all internal subresources to the resource collection. + unless @subresources.empty? + Chef::Log.debug("[#{self}] Adding subresources to collection:") + # Because after_create is run before adding the container to the resource collection + # we need to jump through some hoops to get it swapped into place. + self_ = self + order_fixer = Chef::Resource::RubyBlock.new('subresource_order_fixer', @run_context) + # respond_to? is for <= 12.0.2, remove some day when I stop caring. + order_fixer.declared_type = 'ruby_block' if order_fixer.respond_to?(:declared_type=) + order_fixer.block do + Chef::Log.debug("[#{self_}] Running order fixer") + collection = self_.run_context.resource_collection + # Delete the current container resource from its current position. + collection.all_resources.delete(self_) + # Replace the order fixer with the container so it runs before all + # subresources. + collection.all_resources[collection.iterator.position] = self_ + # Hack for Chef 11 to reset the resources_by_name position too. + # @todo Remove this when I drop support for Chef 11. + if resources_by_name = collection.instance_variable_get(:@resources_by_name) + resources_by_name[self_.to_s] = collection.iterator.position + end + # Step back so we re-run the "current" resource, which is now the + # container. + collection.iterator.skip_back + Chef::Log.debug("Collection: #{@run_context.resource_collection.map(&:to_s).join(', ')}") + end + @run_context.resource_collection.insert(order_fixer) + @subcontexts.each do |ctx| + # Copy all resources to the outer context. + ctx.resource_collection.each do |r| + Chef::Log.debug(" * #{r}") + # Fix the subresource to use the outer run context. + r.run_context = @run_context + @run_context.resource_collection.insert(r) + end + # Copy all notifications to the outer context. + %w{immediate delayed}.each do |notification_type| + ctx.send(:"#{notification_type}_notification_collection").each do |key, notifications| + notifications.each do |notification| + parent_notifications = @run_context.send(:"#{notification_type}_notification_collection")[key] + unless parent_notifications.any? { |existing_notification| existing_notification.duplicates?(notification) } + parent_notifications << notification + end + end + end + end + end + Chef::Log.debug("Collection: #{@run_context.resource_collection.map(&:to_s).join(', ')}") + end + end + + def declare_resource(type, name, created_at=nil, &block) + Chef::Log.debug("[#{self}] Creating subresource from #{type}(#{name})") + self_ = self + # Used to break block context, non-local return from subcontext_block. + resource = [] + # Grab the caller so we can make the subresource look like it comes from + # correct place. + created_at ||= caller[0] + # Run this inside a subcontext to avoid adding to the current resource collection. + # It will end up added later, indirected via @subresources to ensure ordering. + @subcontexts << subcontext_block do + namespace = if self.class.container_namespace == true + # If the value is true, use the name of the container resource. + self.name + elsif self.class.container_namespace.is_a?(Proc) + instance_eval(&self.class.container_namespace) + else + self.class.container_namespace + end + sub_name = if name && !name.empty? + if namespace + "#{namespace}::#{name}" + else + name + end + else + # If you pass in nil or '', you just get the namespace or parent name. + namespace || self.name + end + resource << super(type, sub_name, created_at) do + # Apply the correct parent before anything else so it is available + # in after_created for the subresource. It might raise + # NoMethodError is there isn't a real parent. + begin + parent(self_) if respond_to?(:parent) + rescue NoMethodError + # This space left intentionally blank. + end + # Run the resource block. + instance_exec(&block) if block + end + end + # Try and add to subresources. For normal subresources this is handled + # in the after_created. + register_subresource(resource.first) if resource.first + # Return whatever we have + resource.first + end + + # Register a resource as part of this container. Returns true if the + # resource was added to the collection and false if it was already + # known. + # + # @note Return value added in 2.4.0. + # @return [Boolean] + def register_subresource(resource) + subresources.lookup(resource) + false + rescue Chef::Exceptions::ResourceNotFound + Chef::Log.debug("[#{self}] Adding #{resource} to subresources") + subresources.insert(resource) + true + end + + private + + # Thanks Array.flatten, big help you are. Specifically the + # method_missing in the recipe DSL will make a flatten on an array of + # resources fail, so make this safe. + def to_ary + nil + end + + # @!classmethods + module ClassMethods + def container_namespace(val=nil) + @container_namespace = val unless val.nil? + if @container_namespace.nil? + # Not set here, look at the superclass or true by default for backwards compat. + Poise::Utils.ancestor_send(self, :container_namespace, default: true) + else + @container_namespace + end + end + + # @overload container_default() + # Get the default mode for this resource. If false, this resource + # class will not be used for default container lookups. Defaults to + # true. + # @since 2.3.0 + # @return [Boolean] + # @overload container_default(val) + # Set the default mode for this resource. + # @since 2.3.0 + # @param val [Boolean] Default mode to set. + # @return [Boolean] + def container_default(val=nil) + @container_default = val unless val.nil? + if @container_default.nil? + # Not set here, look at the superclass or true by default for backwards compat. + Poise::Utils.ancestor_send(self, :container_default, default: true) + else + @container_default + end + end + + def included(klass) + super + klass.extend(ClassMethods) + klass.const_set(:HIDDEN_VARS, klass.const_get(:HIDDEN_IVARS) + [:@subcontexts]) + klass.const_set(:FORBIDDEN_IVARS, klass.const_get(:FORBIDDEN_IVARS) + [:@subcontexts]) + end + end + + extend ClassMethods + end + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/subresources/default_containers.rb b/cookbooks/poise/files/halite_gem/poise/helpers/subresources/default_containers.rb new file mode 100644 index 0000000..2ef26e5 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/subresources/default_containers.rb @@ -0,0 +1,75 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + + +module Poise + module Helpers + module Subresources + # Helpers to track default container resources. This is used to find a + # default parent for a child with no parent set. It flat out violates + # encapsulation to allow for the use of default parents to act as + # system-level defaults even when created in a nested scope. + # + # @api private + # @since 2.0.0 + module DefaultContainers + # Mutex to sync access to the containers array. + # + # @see .containers + CONTAINER_MUTEX = Mutex.new + + # Add a resource to the array of default containers. + # + # @param resource [Chef::Resource] Resource to add. + # @param run_context [Chef::RunContext] Context of the current run. + # @return [void] + def self.register!(resource, run_context) + CONTAINER_MUTEX.synchronize do + containers(run_context) << resource + end + end + + # Find a default container for a resource class. + # + # @param klass [Class] Resource class to search for. + # @param run_context [Chef::RunContext] Context of the current run. + # @return [Chef::Resource] + def self.find(klass, run_context, self_resource: nil) + CONTAINER_MUTEX.synchronize do + containers(run_context).reverse_each do |resource| + return resource if resource.is_a?(klass) && (!self_resource || self_resource != resource) + end + # Nothing found. + nil + end + end + + private + + # Get the array of all default container resources. + # + # @note MUST BE CALLED FROM A LOCKED CONTEXT! + # @param run_context [Chef::RunContext] Context of the current run. + # @return [Array] + def self.containers(run_context) + # For test cases where nil gets used sometimes. + return [] unless run_context && run_context.node && run_context.node.run_state + run_context.node.run_state[:poise_default_containers] ||= [] + end + end + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/template_content.rb b/cookbooks/poise/files/halite_gem/poise/helpers/template_content.rb new file mode 100644 index 0000000..48d8ec9 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/template_content.rb @@ -0,0 +1,168 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/provider/template_finder' +require 'chef/mixin/template' + +require 'poise/helpers/lazy_default' +require 'poise/helpers/lwrp_polyfill' +require 'poise/helpers/option_collector' +require 'poise/utils' + + +module Poise + module Helpers + # A resource mixin to add a new kind of attribute, template content. TODO + # + # @since 1.0.0 + module TemplateContent + include LazyDefault + include LWRPPolyfill + include OptionCollector + + # @!classmethods + module ClassMethods + def attribute(name, options={}) + if options.delete(:template) + name_prefix = name.empty? ? '' : "#{name}_" + + # If you are reading this, I'm so sorry + # This is used for computing the default cookbook below + parent_filename = caller.first.reverse.split(':', 4).last.reverse + + # If our parent class also declared a template_content attribute on the same name, inherit its options + if superclass.respond_to?("_#{name_prefix}_template_content_options") + options = superclass.send("_#{name_prefix}_template_content_options").merge(options) + end + + # Template source path if using a template + attribute("#{name_prefix}source", kind_of: String) + define_method("_#{name_prefix}source") do + send("#{name_prefix}source") || maybe_eval(options[:default_source]) + end + + # Template cookbook name if using a template + attribute("#{name_prefix}cookbook", kind_of: [String, Symbol], default: lazy do + if send("#{name_prefix}source") + cookbook_name + elsif options[:default_cookbook] + maybe_eval(options[:default_cookbook]) + else + Poise::Utils.find_cookbook_name(run_context, parent_filename) + end + end) + + # Template variables if using a template + attribute("#{name_prefix}options", option_collector: true) + + # Make an alias for #variables to match the template resource. + alias_method("#{name_prefix}variables", "#{name_prefix}options") + + # The big one, get/set content, but if you are getting and no + # explicit content was given, try to render the template + define_method("#{name_prefix}content") do |arg=nil, no_compute=false| + ret = set_or_return("#{name_prefix}content", arg, kind_of: String) + if !ret && !arg && !no_compute + ret = send("_#{name_prefix}content") + # Cache the results for next time + set_or_return("#{name_prefix}content", ret, {}) if ret + end + ret + end + + # Validate that arguments work + define_method("_#{name_prefix}validate") do + if options[:required] && !send("_#{name_prefix}source") && !send("#{name_prefix}content", nil, true) + raise Chef::Exceptions::ValidationFailed, "#{self}: One of #{name_prefix}source or #{name_prefix}content is required" + end + if send("#{name_prefix}source") && send("#{name_prefix}content", nil, true) + raise Chef::Exceptions::ValidationFailed, "#{self}: Only one of #{name_prefix}source or #{name_prefix}content can be specified" + end + end + + # Monkey patch #after_create to run best-effort validation. Arguments + # could be changed after creation, but this gives nicer errors for + # most cases. + unless options[:no_validate_on_create] + old_after_created = instance_method(:after_created) + define_method(:after_created) do + old_after_created.bind(self).call + send("_#{name_prefix}validate") if Array(action) == Array(self.class.default_action) + end + end + + # Compile the needed content + define_method("_#{name_prefix}content") do + # Run validation again + send("_#{name_prefix}validate") + # Get all the relevant parameters + content = send("#{name_prefix}content", nil, true) + source = send("_#{name_prefix}source") + if content + content # I don't think it can ever hit this branch + elsif source + cookbook = send("#{name_prefix}cookbook") + template_options = send("#{name_prefix}options") + send("_#{name_prefix}render_template", source, cookbook, template_options) + else + maybe_eval(options[:default]) + end + end + + # Actually render a template + define_method("_#{name_prefix}render_template") do |source, cookbook, template_options| + all_template_options = {} + all_template_options.update(maybe_eval(options[:default_options])) if options[:default_options] + all_template_options.update(template_options) + all_template_options[:new_resource] = self + finder = Chef::Provider::TemplateFinder.new(run_context, cookbook, node) + context = Chef::Mixin::Template::TemplateContext.new(all_template_options) + context[:node] = node + context[:template_finder] = finder + context.render_template(finder.find(source)) + end + + # Used to check if a parent class already defined a template_content thing here + define_singleton_method("_#{name_prefix}_template_content_options") do + options + end + else + super if defined?(super) + end + end + + def included(klass) + super + klass.extend(ClassMethods) + end + end + + extend ClassMethods + + private + + # Evaluate lazy blocks if needed + def maybe_eval(val) + if val.is_a?(Chef::DelayedEvaluator) + instance_eval(&val) + else + val + end + end + + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/win32_user.rb b/cookbooks/poise/files/halite_gem/poise/helpers/win32_user.rb new file mode 100644 index 0000000..4588df4 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/win32_user.rb @@ -0,0 +1,64 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise/utils/win32' + + +module Poise + module Helpers + # A resource mixin to intercept properties named `user`, `group`, or `owner`, + # if their default value is `'root'` and make it work on Windows (and + # FreeBSD, AIX). + # + # @since 2.7.0 + # @example + # class MyResource < Chef::Resource + # include Poise::Helpers::Win32User + # attribute(:user, default: 'root') + # attribute(:group, default: 'root') + # end + # @example Avoiding automatic translation + # class MyResource < Chef::Resource + # include Poise::Helpers::Win32User + # attribute(:user, default: lazy { 'root' }) + # attribute(:group, default: lazy { 'root' }) + # end + module Win32User + # User-ish property names. + # @api private + USER_PROPERTIES = ['user', :user, 'owner', :owner] + + # Group-ish property names. + # @api private + GROUP_PROPERTIES = ['group', :group] + + # Intercept property access to swap out the default value. + # @api private + def set_or_return(symbol, arg, options={}) + if options && options[:default] == 'root' + if USER_PROPERTIES.include?(symbol) && node.platform_family?('windows') + options = options.dup + options[:default] = Poise::Utils::Win32.admin_user + elsif GROUP_PROPERTIES.include?(symbol) + options = options.dup + options[:default] = node['root_group'] + end + end + super(symbol, arg, options) + end + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/provider.rb b/cookbooks/poise/files/halite_gem/poise/provider.rb new file mode 100644 index 0000000..953e31c --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/provider.rb @@ -0,0 +1,59 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise/helpers' +require 'poise/utils' + + +module Poise + # Master provider mixin for Poise-based providers. + # + # @since 1.0.0 + # @example Default helpers. + # class MyProvider < Chef::Provider + # include Poise::Provider + # end + # @example With optional helpers. + # class MyProvider < Chef::Provider + # include Poise::Provider + # poise_inversion(MyResource) + # end + module Provider + include Poise::Helpers::DefinedIn + include Poise::Helpers::LWRPPolyfill + # IncludeRecipe must come after LWRPPolyfill because that pulls in the + # recipe DSL which has its own #include_recipe. + include Poise::Helpers::IncludeRecipe + include Poise::Helpers::NotifyingBlock + include Poise::Utils::ShellOut + + # @!classmethods + module ClassMethods + def poise_inversion(resource, attribute=nil) + include Poise::Helpers::Inversion + inversion_resource(resource) + inversion_attribute(attribute) if attribute + end + + def included(klass) + super + klass.extend(ClassMethods) + end + end + + extend ClassMethods + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/resource.rb b/cookbooks/poise/files/halite_gem/poise/resource.rb new file mode 100644 index 0000000..ff8ad05 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/resource.rb @@ -0,0 +1,81 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise/helpers' +require 'poise/utils' + + +module Poise + # Master resource mixin for Poise-based resources. + # + # @since 1.0.0 + # @example Default helpers. + # class MyResource < Chef::Resource + # include Poise::Resource + # end + # @example With optional helpers. + # class MyResource < Chef::Resource + # include Poise::Resource + # poise_subresource(MyParent) + # poise_fused + # end + module Resource + include Poise::Helpers::ChefspecMatchers + include Poise::Helpers::DefinedIn + include Poise::Helpers::LazyDefault if Poise::Helpers::LazyDefault.needs_polyfill? + include Poise::Helpers::LWRPPolyfill + include Poise::Helpers::OptionCollector + include Poise::Helpers::ResourceCloning + include Poise::Helpers::ResourceName + include Poise::Helpers::ResourceSubclass + include Poise::Helpers::TemplateContent + include Poise::Helpers::Win32User # Must be after LazyDefault. + include Poise::Utils::ShellOut + + # @!classmethods + module ClassMethods + def poise_subresource_container(namespace=nil, default=nil) + include Poise::Helpers::Subresources::Container + # false is a valid value. + container_namespace(namespace) unless namespace.nil? + container_default(default) unless default.nil? + end + + def poise_subresource(parent_type=nil, parent_optional=nil, parent_auto=nil) + include Poise::Helpers::Subresources::Child + parent_type(parent_type) if parent_type + parent_optional(parent_optional) unless parent_optional.nil? + parent_auto(parent_auto) unless parent_auto.nil? + end + + def poise_fused + include Poise::Helpers::Fused + end + + def poise_inversion(options_resource=nil) + include Poise::Helpers::Inversion + inversion_options_resource(true) unless options_resource == false + end + + def included(klass) + super + klass.extend(ClassMethods) + end + end + + extend ClassMethods + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/subcontext.rb b/cookbooks/poise/files/halite_gem/poise/subcontext.rb new file mode 100644 index 0000000..278d973 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/subcontext.rb @@ -0,0 +1,27 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + + +module Poise + # Helpers and whatnot for dealing with subcontexts. + # + # @api private + # @since 2.0.0 + module Subcontext + autoload :ResourceCollection, 'poise/subcontext/resource_collection' + autoload :Runner, 'poise/subcontext/runner' + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/subcontext/resource_collection.rb b/cookbooks/poise/files/halite_gem/poise/subcontext/resource_collection.rb new file mode 100644 index 0000000..cacd32c --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/subcontext/resource_collection.rb @@ -0,0 +1,75 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/resource_collection' + + +module Poise + module Subcontext + # A subclass of the normal Chef ResourceCollection that creates a partially + # isolated set of resources. Notifications and other resources lookups can + # propagate out to parent contexts but not back in. This is used to allow + # black-box resources that are still aware of things in upper contexts. + # + # @api private + # @since 1.0.0 + class ResourceCollection < Chef::ResourceCollection + attr_accessor :parent + + def initialize(parent) + @parent = parent + super() + end + + def lookup(resource) + super + rescue Chef::Exceptions::ResourceNotFound + @parent.lookup(resource) + end + + # Iterate over all resources, expanding parent context in order. + # + # @param block [Proc] Iteration block + # @return [void] + def recursive_each(&block) + if @parent + if @parent.respond_to?(:recursive_each) + @parent.recursive_each(&block) + else + @parent.each(&block) + end + end + each(&block) + end + + # Iterate over all resources in reverse order. + # + # @since 2.3.0 + # @param block [Proc] Iteration block + # @return [void] + def reverse_recursive_each(&block) + reverse_each(&block) + if @parent + if @parent.respond_to?(:recursive_each) + @parent.reverse_recursive_each(&block) + else + @parent.reverse_each(&block) + end + end + end + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/subcontext/runner.rb b/cookbooks/poise/files/halite_gem/poise/subcontext/runner.rb new file mode 100644 index 0000000..aaa5e44 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/subcontext/runner.rb @@ -0,0 +1,55 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + +require 'chef/runner' + + +module Poise + module Subcontext + # A subclass of the normal Chef Runner that migrates delayed notifications + # to the enclosing run_context instead of running them at the end of the + # subcontext convergence. + # + # @api private + # @since 1.0.0 + class Runner < Chef::Runner + def initialize(resource, *args) + super(*args) + @resource = resource + end + + def run_delayed_notifications(error=nil) + # If there is an error, just do the normal thing. The return shouldn't + # ever fire because the superclass re-raises if there is an error. + return super if error + delayed_actions.each do |notification| + if @resource.run_context.respond_to?(:add_delayed_action) + @resource.run_context.add_delayed_action(notification) + else + notifications = run_context.parent_run_context.delayed_notifications(@resource) + if notifications.any? { |existing_notification| existing_notification.duplicates?(notification) } + Chef::Log.info( "#{@resource} not queuing delayed action #{notification.action} on #{notification.resource}"\ + " (delayed), as it's already been queued") + else + notifications << notification + end + end + end + end + + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/utils.rb b/cookbooks/poise/files/halite_gem/poise/utils.rb new file mode 100644 index 0000000..9e05270 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/utils.rb @@ -0,0 +1,181 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'poise/error' + + +module Poise + module Utils + autoload :ResourceProviderMixin, 'poise/utils/resource_provider_mixin' + autoload :ShellOut, 'poise/utils/shell_out' + autoload :Win32, 'poise/utils/win32' + + extend self + + # Find the cookbook name for a given filename. The can used to find the + # cookbook that corresponds to a caller of a file. + # + # @param run_context [Chef::RunContext] Context to check. + # @param filename [String] Absolute filename to check for. + # @return [String] + # @example + # def my_thing + # caller_filename = caller.first.split(':').first + # cookbook = Poise::Utils.find_cookbook_name(run_context, caller_filename) + # # ... + # end + def find_cookbook_name(run_context, filename) + possibles = {} + Poise.debug("[Poise] Checking cookbook for #{filename.inspect}") + run_context.cookbook_collection.each do |name, ver| + # This special method is added by Halite::Gem#as_cookbook_version. + if ver.respond_to?(:halite_root) + # The join is there because ../poise-ruby/lib starts with ../poise so + # we want a trailing /. + if filename.start_with?(File.join(ver.halite_root, '')) + Poise.debug("[Poise] Found matching halite_root in #{name}: #{ver.halite_root.inspect}") + possibles[ver.halite_root] = name + end + else + Chef::CookbookVersion::COOKBOOK_SEGMENTS.each do |seg| + ver.segment_filenames(seg).each do |file| + if ::File::ALT_SEPARATOR + file = file.gsub(::File::ALT_SEPARATOR, ::File::SEPARATOR) + end + # Put this behind an environment variable because it is verbose + # even for normal debugging-level output. + Poise.debug("[Poise] Checking #{seg} in #{name}: #{file.inspect}") + if file == filename + Poise.debug("[Poise] Found matching #{seg} in #{name}: #{file.inspect}") + possibles[file] = name + end + end + end + end + end + raise Poise::Error.new("Unable to find cookbook for file #{filename.inspect}") if possibles.empty? + # Sort the items by matching path length, pick the name attached to the longest. + possibles.sort_by{|key, value| key.length }.last[1] + end + + # Try to find an ancestor to call a method on. + # + # @since 2.2.3 + # @since 2.3.0 + # Added ignore parameter. + # @param obj [Object] Self from the caller. + # @param msg [Symbol] Method to try to call. + # @param args [Array] Method arguments. + # @param default [Object] Default return value if no valid ancestor exists. + # @param ignore [Array] Return value to ignore when scanning ancesors. + # @return [Object] + # @example + # val = @val || Poise::Utils.ancestor_send(self, :val) + def ancestor_send(obj, msg, *args, default: nil, ignore: [default]) + # Class is a subclass of Module, if we get something else use its class. + obj = obj.class unless obj.is_a?(Module) + ancestors = [] + if obj.respond_to?(:superclass) + # Check the superclass first if present. + ancestors << obj.superclass + end + # Make sure we don't check obj itself. + ancestors.concat(obj.ancestors.drop(1)) + ancestors.each do |mod| + if mod.respond_to?(msg) + val = mod.send(msg, *args) + # If we get the default back, assume we should keep trying. + return val unless ignore.include?(val) + end + end + # Nothing valid found, use the default. + default + end + + # Create a helper to invoke a module with some parameters. + # + # @since 2.3.0 + # @param mod [Module] The module to wrap. + # @param block [Proc] The module to implement to parameterization. + # @return [void] + # @example + # module MyMixin + # def self.my_mixin_name(name) + # # ... + # end + # end + # + # Poise::Utils.parameterized_module(MyMixin) do |name| + # my_mixin_name(name) + # end + def parameterized_module(mod, &block) + raise Poise::Error.new("Cannot parameterize an anonymous module") unless mod.name && !mod.name.empty? + parent_name_parts = mod.name.split(/::/) + # Grab the last piece which will be the method name. + mod_name = parent_name_parts.pop + # Find the enclosing module or class object. + parent = parent_name_parts.inject(Object) {|memo, name| memo.const_get(name) } + # Object is a special case since we need #define_method instead. + method_type = if parent == Object + :define_method + else + :define_singleton_method + end + # Scoping hack. + self_ = self + # Construct the method. + parent.send(method_type, mod_name) do |*args| + self_.send(:check_block_arity!, block, args) + # Create a new anonymous module to be returned from the method. + Module.new do + # Fake the name. + define_singleton_method(:name) do + super() || mod.name + end + + # When the stub module gets included, activate our behaviors. + define_singleton_method(:included) do |klass| + super(klass) + klass.send(:include, mod) + klass.instance_exec(*args, &block) + end + end + end + end + + private + + # Check that the given arguments match the given block. This is needed + # because Ruby will nil-pad mismatched argspecs on blocks rather than error. + # + # @since 2.3.0 + # @param block [Proc] Block to check. + # @param args [Array] Arguments to check. + # @return [void] + def check_block_arity!(block, args) + # Convert the block to a lambda-style proc. You can't make this shit up. + obj = Object.new + obj.define_singleton_method(:block, &block) + block = obj.method(:block).to_proc + # Check + required_args = block.arity < 0 ? ~block.arity : block.arity + if args.length < required_args || (block.arity >= 0 && args.length > block.arity) + raise ArgumentError.new("wrong number of arguments (#{args.length} for #{required_args}#{block.arity < 0 ? '+' : ''})") + end + end + + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/utils/resource_provider_mixin.rb b/cookbooks/poise/files/halite_gem/poise/utils/resource_provider_mixin.rb new file mode 100644 index 0000000..fba69d4 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/utils/resource_provider_mixin.rb @@ -0,0 +1,65 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + + +module Poise + module Utils + # A mixin to dispatch other mixins with resource and provider + # implementations. The module this is included in must have Resource and + # Provider sub-modules. + # + # @since 2.0.0 + # @example + # module MyHelper + # include Poise::Utils::ResourceProviderMixin + # module Resource + # # ... + # end + # + # module Provider + # # ... + # end + # end + module ResourceProviderMixin + def self.included(klass) + # Warning here be dragons. + # Create a new anonymous module, klass will be the module that + # actually included ResourceProviderMixin. We want to keep a reference + # to that locked down so that we can close over it and use it in the + # "real" .included defined below to find the original relative consts. + mod = Module.new do + # Use define_method instead of def so we can close over klass and mod. + define_method(:included) do |inner_klass| + # Has to be explicit because super inside define_method. + super(inner_klass) + # Cargo this .included to things which include us. + inner_klass.extend(mod) + # Dispatch to submodules, inner_klass is the most recent includer. + if inner_klass < Chef::Resource || inner_klass.name.to_s.end_with?('::Resource') + # Use klass::Resource to look up relative to the original module. + inner_klass.class_exec { include klass::Resource } + elsif inner_klass < Chef::Provider || inner_klass.name.to_s.end_with?('::Provider') + # As above, klass::Provider. + inner_klass.class_exec { include klass::Provider } + end + end + end + # Add our .included to the original includer. + klass.extend(mod) + end + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/utils/shell_out.rb b/cookbooks/poise/files/halite_gem/poise/utils/shell_out.rb new file mode 100644 index 0000000..0231e14 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/utils/shell_out.rb @@ -0,0 +1,90 @@ +# +# Copyright 2015-2016, Noah Kantrowitz +# +# 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. +# + +require 'etc' + +require 'chef/mixin/shell_out' + + +module Poise + module Utils + # A mixin to provider a better shell_out. + # + # @since 2.5.0 + # @example + # Poise::Utils::ShellOut.poise_shell_out('ruby myapp.rb', user: 'myuser') + module ShellOut + extend self + include Chef::Mixin::ShellOut + + # An enhanced version of Chef's `shell_out` which sets some default + # parameters. If possible it will set $HOME, $USER, $LOGNAME, and the + # group to run as. + # + # @param command_args [Array] Command arguments to be passed to `shell_out`. + # @param options [Hash] Options to be passed to `shell_out`, + # with modifications. + # @return [Mixlib::ShellOut] + def poise_shell_out(*command_args, **options) + # Allow the env option shorthand. + options[:environment] ||= {} + if options[:env] + options[:environment].update(options[:env]) + options.delete(:env) + end + # Convert environment keys to strings to be safe. + options[:environment] = options[:environment].inject({}) do |memo, (key, value)| + memo[key.to_s] = value.to_s + memo + end + # Populate some standard environment variables. + ent = begin + if options[:user].is_a?(Integer) + Etc.getpwuid(options[:user]) + elsif options[:user] + Etc.getpwnam(options[:user]) + end + rescue ArgumentError + nil + end + username = ent ? ent.name : options[:name] + if username + options[:environment]['HOME'] ||= Dir.home(username) + options[:environment]['USER'] ||= username + # On the off chance they set one manually but not the other. + options[:environment]['LOGNAME'] ||= options[:environment]['USER'] + end + # Set the default group on Unix. + options[:group] ||= ent.gid if ent + # Mixlib-ShellOut doesn't support array commands on Windows and has + # super wonky escaping for cmd.exe. + if respond_to?(:node) && node.platform_family?('windows') + command_args = [Poise::Utils::Win32.reparse_command(*command_args)] + end + # Call Chef's shell_out wrapper. + shell_out(*command_args, **options) + end + + # The `error!` version of {#poise_shell_out}. + # + # @see #poise_shell_out + # @return [Mixlib::ShellOut] + def poise_shell_out!(*command_args) + poise_shell_out(*command_args).tap(&:error!) + end + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/utils/win32.rb b/cookbooks/poise/files/halite_gem/poise/utils/win32.rb new file mode 100644 index 0000000..0cc6f9d --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/utils/win32.rb @@ -0,0 +1,127 @@ +# +# Copyright 2016, Noah Kantrowitz +# +# 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. +# + +require 'shellwords' + + +module Poise + module Utils + # Utilities for working with Windows. + # + # @since 2.7.0 + module Win32 + extend self + + # Code borrowed from https://github.com/chef-cookbooks/chef-client/blob/master/libraries/helpers.rb + # Used under the terms of the Apache v2 license. + # Copyright 2012-2016, John Dewey + + # Run a WMI query and extracts a property. This assumes Chef has already + # loaded the win32 libraries. + # + # @api private + # @param wmi_property [Symbol] Property to extract. + # @param wmi_query [String] Query to run. + # @return [String] + def wmi_property_from_query(wmi_property, wmi_query) + @wmi = ::WIN32OLE.connect('winmgmts://') + result = @wmi.ExecQuery(wmi_query) + return nil unless result.each.count > 0 + result.each.next.send(wmi_property) + end + + # Find the name of the Administrator user, give or take localization. + # + # @return [String] + def admin_user + if defined?(::WIN32OLE) + wmi_property_from_query(:name, "select * from Win32_UserAccount where sid like 'S-1-5-21-%-500' and LocalAccount=True") + else + # Warn except under ChefSpec because it will just annoy people. + Chef::Log.warn('[Poise::Utils::Win32] Unable to query admin user, WIN32OLE not available') unless defined?(ChefSpec) + 'Administrator' + end + end + + # Escaping that is compatible with CommandLineToArgvW. Based on + # https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/ + # + # @api private + # @param string [String] String to escape. + # @return [String] + def argv_quote(string, force_quote: false) + if !force_quote && !string.empty? && string !~ /[ \t\n\v"]/ + # Nothing fancy, no escaping needed. + string + else + command_line = '"' + i = 0 + while true + number_backslashes = 0 + + while i != string.size && string[i] == '\\' + i += 1 + number_backslashes += 1 + end + + if i == string.size + # Escape all backslashes, but let the terminating + # double quotation mark we add below be interpreted + # as a metacharacter. + command_line << '\\' * (number_backslashes * 2) + break + elsif string[i] == '"' + # Escape all backslashes and the following + # double quotation mark. + command_line << '\\' * ((number_backslashes * 2) + 1) + command_line << '"' + else + # Backslashes aren't special here. + command_line << '\\' * number_backslashes + command_line << string[i] + end + i += 1 + end + command_line << '"' + command_line + end + end + + # Take a string or array command in the format used by shell_out et al and + # create something we can use on Windows. + # + # @ + def reparse_command(*args) + array_mode = !(args.length == 1 && args.first.is_a?(String)) + # At some point when mixlib-shellout groks array commands on Windows, + # we should support that here. + parsed_args = array_mode ? args.flatten : Shellwords.split(args.first) + cmd = parsed_args.map {|s| argv_quote(s) }.join(' ') + if array_mode + # This fails on non-Windows because of win32/process. + require 'mixlib/shellout/windows' + if Mixlib::ShellOut::Windows::Utils.should_run_under_cmd?(cmd) + # If we are in array mode, try to make cmd.exe keep its grubby paws + # off our metacharacters. + cmd = cmd.each_char.map {|c| '^'+c }.join('') + end + end + cmd + end + + end + end +end diff --git a/cookbooks/poise/files/halite_gem/poise/version.rb b/cookbooks/poise/files/halite_gem/poise/version.rb new file mode 100644 index 0000000..ba30d42 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/version.rb @@ -0,0 +1,20 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + + +module Poise + VERSION = '2.8.2' +end diff --git a/cookbooks/poise/libraries/default.rb b/cookbooks/poise/libraries/default.rb new file mode 100644 index 0000000..9731909 --- /dev/null +++ b/cookbooks/poise/libraries/default.rb @@ -0,0 +1,18 @@ +# +# Copyright 2013-2016, Noah Kantrowitz +# +# 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. +# + +raise 'Halite is not compatible with no_lazy_load false, please set no_lazy_load true in your Chef configuration file.' unless Chef::Config[:no_lazy_load] +$LOAD_PATH << File.expand_path('../../files/halite_gem', __FILE__) diff --git a/cookbooks/poise/metadata.json b/cookbooks/poise/metadata.json new file mode 100644 index 0000000..38a322c --- /dev/null +++ b/cookbooks/poise/metadata.json @@ -0,0 +1 @@ +{"name":"poise","version":"2.8.2","description":"Helpers for writing extensible Chef cookbooks.","long_description":"# Poise\n\n[![Build Status](https://img.shields.io/travis/poise/poise.svg)](https://travis-ci.org/poise/poise)\n[![Gem Version](https://img.shields.io/gem/v/poise.svg)](https://rubygems.org/gems/poise)\n[![Cookbook Version](https://img.shields.io/cookbook/v/poise.svg)](https://supermarket.chef.io/cookbooks/poise)\n[![Coverage](https://img.shields.io/codecov/c/github/poise/poise.svg)](https://codecov.io/github/poise/poise)\n[![Gemnasium](https://img.shields.io/gemnasium/poise/poise.svg)](https://gemnasium.com/poise/poise)\n[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)\n\n## What is Poise?\n\nThe poise cookbook is a set of libraries for writing reusable cookbooks. It\nprovides helpers for common patterns and a standard structure to make it easier to create flexible cookbooks.\n\n## Writing your first resource\n\nRather than LWRPs, Poise promotes the idea of using normal, or \"heavy weight\"\nresources, while including helpers to reduce much of boilerplate needed for this. Each resource goes in its own file under `libraries/` named to match\nthe resource, which is in turn based on the class name. This means that the file `libraries/my_app.rb` would contain `Chef::Resource::MyApp` which maps to the resource `my_app`.\n\nAn example of a simple shell to start from:\n\n```ruby\nrequire 'poise'\nrequire 'chef/resource'\nrequire 'chef/provider'\n\nmodule MyApp\n class Resource < Chef::Resource\n include Poise\n provides(:my_app)\n actions(:enable)\n\n attribute(:path, kind_of: String)\n # Other attribute definitions.\n end\n\n class Provider < Chef::Provider\n include Poise\n provides(:my_app)\n\n def action_enable\n notifying_block do\n ... # Normal Chef recipe code goes here\n end\n end\n end\nend\n```\n\nStarting from the top, first we require the libraries we will be using. Then we\ncreate a module to hold our resource and provider. If your cookbook declares\nmultiple resources and/or providers, you might want additional nesting here.\nThen we declare the resource class, which inherits from `Chef::Resource`. This\nis similar to the `resources/` file in an LWRP, and a similar DSL can be used.\nWe then include the `Poise` mixin to load our helpers, and then call\n`provides(:my_app)` to tell Chef this class will implement the `my_app`\nresource. Then we use the familiar DSL, though with a few additions we'll cover\nlater.\n\nThen we declare the provider class, again similar to the `providers/` file in an\nLWRP. We include the `Poise` mixin again to get access to all the helpers and\ncall `provides()` to tell Chef what provider this is. Rather than use the\n`action :enable do ... end` DSL from LWRPs, we just define the action method\ndirectly. The implementation of action comes from a block of recipe code\nwrapped with `notifying_block` to capture changes in much the same way as\n`use_inline_resources`, see below for more information about all the features of\n`notifying_block`.\n\nWe can then use this resource like any other Chef resource:\n\n```ruby\nmy_app 'one' do\n path '/tmp'\nend\n```\n\n## Helpers\n\nWhile not exposed as a specific method, Poise will automatically set the\n`resource_name` based on the class name.\n\n### Notifying Block\n\nAs mentioned above, `notifying_block` is similar to `use_inline_resources` in LWRPs. Any Chef resource created inside the block will be converged in a sub-context and if any have updated it will trigger notifications on the current resource. Unlike `use_inline_resources`, resources inside the sub-context can still see resources outside of it, with lookups propagating up sub-contexts until a match is found. Also any delayed notifications are scheduled to run at the end of the main converge cycle, instead of the end of this inner converge.\n\nThis can be used to write action methods using the normal Chef recipe DSL, while still offering more flexibility through subclassing and other forms of code reuse.\n\n### Include Recipe\n\nIn keeping with `notifying_block` to implement action methods using the Chef DSL, Poise adds an `include_recipe` helper to match the method of the same name in recipes. This will load and converge the requested recipe.\n\n### Resource DSL\n\nTo make writing resource classes easier, Poise exposes a DSL similar to LWRPs for defining actions and attributes. Both `actions` and\n`default_action` are just like in LWRPs, though `default_action` is rarely needed as the first action becomes the default. `attribute` is also available just like in LWRPs, but with some enhancements noted below.\n\nOne notable difference over the standard DSL method is that Poise attributes\ncan take a block argument.\n\n#### Template Content\n\nA common pattern with resources is to allow passing either a template filename or raw file content to be used in a configuration file. Poise exposes a new attribute flag to help with this behavior:\n\n```ruby\nattribute(:name, template: true)\n```\n\nThis creates four methods on the class, `name_source`, `name_cookbook`,\n`name_content`, and `name_options`. If the name is set to `''`, no prefix is applied to the function names. The content method can be set directly, but if not set and source is set, then it will render the template and return it as a string. Default values can also be set for any of these:\n\n```ruby\nattribute(:name, template: true, default_source: 'app.cfg.erb',\n default_options: {host: 'localhost'})\n```\n\nAs an example, you can replace this:\n\n```ruby\nif new_resource.source\n template new_resource.path do\n source new_resource.source\n owner 'app'\n group 'app'\n variables new_resource.options\n end\nelse\n file new_resource.path do\n content new_resource.content\n owner 'app'\n group 'app'\n end\nend\n```\n\nwith simply:\n\n```ruby\nfile new_resource.path do\n content new_resource.content\n owner 'app'\n group 'app'\nend\n```\n\nAs the content method returns the rendered template as a string, this can also\nbe useful within other templates to build from partials.\n\n#### Lazy Initializers\n\nOne issue with Poise-style resources is that when the class definition is executed, Chef hasn't loaded very far so things like the node object are not\nyet available. This means setting defaults based on node attributes does not work directly:\n\n```ruby\nattribute(:path, default: node['myapp']['path'])\n...\nNameError: undefined local variable or method 'node'\n```\n\nTo work around this, Poise extends the idea of lazy initializers from Chef recipes to work with resource definitions as well:\n\n```ruby\nattribute(:path, default: lazy { node['myapp']['path'] })\n```\n\nThese initializers are run in the context of the resource object, allowing\ncomplex default logic to be moved to a method if desired:\n\n```ruby\nattribute(:path, default: lazy { my_default_path })\n\ndef my_default_path\n ...\nend\n```\n\n#### Option Collector\n\nAnother common pattern with resources is to need a set of key/value pairs for\nconfiguration data or options. This can done with a simple Hash, but an option collector attribute can offer a nicer syntax:\n\n```ruby\nattribute(:mydata, option_collector: true)\n...\n\nmy_app 'name' do\n mydata do\n key1 'value1'\n key2 'value2'\n end\nend\n```\n\nThis will be converted to `{key1: 'value1', key2: 'value2'}`. You can also pass a Hash to an option collector attribute just as you would with a normal attribute.\n\n## Debugging Poise\n\nPoise has its own extra-verbose level of debug logging that can be enabled in\nthree different ways. You can either set the environment variable `$POISE_DEBUG`,\nset a node attribute `node['POISE_DEBUG']`, or touch the file `/POISE_DEBUG`.\nYou will see a log message `Extra verbose logging enabled` at the start of the\nrun to confirm Poise debugging has been enabled. Make sure you also set Chef's\nlog level to `debug`, usually via `-l debug` on the command line.\n\n## Upgrading from Poise 1.x\n\nThe biggest change when upgrading from Poise 1.0 is that the mixin is no longer\nloaded automatically. You must add `require 'poise'` to your code is you want to\nload it, as you would with normal Ruby code outside of Chef. It is also highly\nrecommended to add `provides(:name)` calls to your resources and providers, this\nwill be required in Chef 13 and will display a deprecation warning if you do\nnot. This also means you can move your code out of the `Chef` module namespace\nand instead declare it in your own namespace. An example of this is shown above.\n\n## Sponsors\n\nThe Poise test server infrastructure is generously sponsored by [Rackspace](https://rackspace.com/). Thanks Rackspace!\n\n## License\n\nCopyright 2013-2016, Noah Kantrowitz\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","maintainer":"Noah Kantrowitz","maintainer_email":"noah@coderanger.net","license":"Apache-2.0","platforms":{"aix":">= 0.0.0","amazon":">= 0.0.0","arch":">= 0.0.0","centos":">= 0.0.0","chefspec":">= 0.0.0","debian":">= 0.0.0","dragonfly4":">= 0.0.0","fedora":">= 0.0.0","freebsd":">= 0.0.0","gentoo":">= 0.0.0","ios_xr":">= 0.0.0","mac_os_x":">= 0.0.0","nexus":">= 0.0.0","omnios":">= 0.0.0","openbsd":">= 0.0.0","opensuse":">= 0.0.0","oracle":">= 0.0.0","raspbian":">= 0.0.0","redhat":">= 0.0.0","slackware":">= 0.0.0","smartos":">= 0.0.0","solaris2":">= 0.0.0","suse":">= 0.0.0","ubuntu":">= 0.0.0","windows":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/poise/poise","issues_url":"https://github.com/poise/poise/issues","chef_version":[["< 15",">= 12.14"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/postfix/CHANGELOG.md b/cookbooks/postfix/CHANGELOG.md new file mode 100644 index 0000000..415b74c --- /dev/null +++ b/cookbooks/postfix/CHANGELOG.md @@ -0,0 +1,219 @@ +# postfix Cookbook CHANGELOG + +This file is used to list changes made in each version of the postfix cookbook. + +## 5.0.2 (2017-05-17) + +- Fix use_relay_restrictions_maps attribute misspelling in attributes file + +## 5.0.1 (2017-03-03) + +- Fix documentation error on inet-interfaces +- Test with Local Delivery instead of Rake +- Fix master.cf attributes types on README + +## 5.0.0 (2017-01-17) + +- Manage any hash: tables for postfix with hash_maps recipe +- Fully customizable master.cf file +- Support for any kind of postfix lookup tables +- Remove old minitest files +- Update chef requirement in the readme +- Update tests for new config comment blocks +- fixing /etc/aliases syntax for full-mailaddresses + +## 4.0.0 (2016-09-07) + +- Update supported platforms in metadata +- Remove node name from config file +- Testing updates +- Use node.normal vs. node.set to avoid deprecation warnings +- Require Chef 12+ + +## v3.8.0 (2016-04-01) + +- Updated attributes to use node.default_unless instead of node.default to be more wrapper friendly +- Added integration and unit testing in Travis CI +- Added rubocop config and resolved rubocop warnings +- Added Gemfile with all necessary test deps +- Added standard gitignore and chefignore files +- Added updated contributing and testing docs +- Removed the Kitchen Digital Ocean files and dependencies +- Added additional platforms to the Test Kitchen config +- Added a Rakefile for simplified testing +- Fixed a typo in the use_relay_restrictions_maps attribute that prevented the default from being set +- Added fedora and oracle as supported platforms in the metadata +- Removed the attributes from the metadata. +- Added long_description to the metadata +- Added Chef 11 compatibility checks to issues_url and source_url in metadata.rb +- Added maintainers.md and maintainers.toml files + +## v3.7.0 (2015-04-30) + +- Adding support for relay restrictions +- Update chefspec and serverspec tests + +## v3.6.2 (2014-10-31) + +- Fix FreeBSDisms + +## v3.6.1 (2014-10-28) + +- Fix documentation around node['postfix']['main']['relayhost'] attribute +- Fix logic around include_recipe 'postfix::virtual_aliases_domains' + +## v3.6.0 (2014-08-25) + +- restart postfix after updating virtual alias templates #86 +- fixing typo for alias_db location in omnios +- moving conditional attributes to a recipe so they can be modified +- via other cookbook attributes + +## v3.5.0 (2014-08-25) + +Adding virtual_domains functionality + +## v3.4.1 (2014-08-20) + +Removing unused parameters from main.cf + +## v3.4.0 (2014-07-25) + +Refactoring to fix some logic issues + +## v3.3.1 (2014-06-11) + +Reverting #37 - [COOK-3418] Virtual Domain Support PR - duplicate of #55 + +## v3.3.0 (2014-06-11) + +- 37 - [COOK-3418] - Virtual Domain Support +- 44 - Fix minor formatting issue in attributes +- 55 - Add support for virtual aliases +- 57 - Fixing attributes bug in README +- 64 - add smtp_generic maps configuration option +- 66 - [COOK-3652] Add support for transport mappings +- 67 - [COOK-4662] Added support for access control +- 68 - Properly handle binding to loopback on mixed IPV4/IPV6 systems + +## v3.2.0 (2014-05-09) + +- [COOK-4619] - no way to unset recipient_delimiter + +## v3.1.8 (2014-03-27) + +- [COOK-4410] - Fix sender_canonical configuration by adding template +- and postmap execution + +## v3.1.6 (2014-03-19) + +- [COOK-4423] - use platform_family, find cert.pem on rhel + +## v3.1.4 (2014-02-27) + +[COOK-4329] Migrate minitest PITs to latest test-kitchen + serverspec + +## v3.1.2 (2014-02-19) + +### Bug + +- **[COOK-4357](https://tickets.chef.io/browse/COOK-4357)** - postfix::sasl_auth recipe fails to converge + +## v3.1.0 (2014-02-19) + +### Bug + +- **[COOK-4322](https://tickets.chef.io/browse/COOK-4322)** - Postfix cookbook has incorrect default path for sasl_passwd + +### New Feature + +- **[COOK-4086](https://tickets.chef.io/browse/COOK-4086)** - use conf_dir attribute for sasl recipe, and add omnios support +- **[COOK-2551](https://tickets.chef.io/browse/COOK-2551)** - Support creating the sender_canonical map file + +## v3.0.4 + +### Bug + +- **[COOK-3824](https://tickets.chef.io/browse/COOK-3824)** - main.cf.erb mishandles lists + +### Improvement + +- **[COOK-3822](https://tickets.chef.io/browse/COOK-3822)** - postfix cookbook readme has an incorrect example +- Got rubocop errors down to 32 + +### New Feature + +- **[COOK-2551](https://tickets.chef.io/browse/COOK-2551)** - Support creating the sender_canonical map file + +## v3.0.2 + +### Bug + +- **[COOK-3617](https://tickets.chef.io/browse/COOK-3617)** - Fix error when no there is no FQDN +- **[COOK-3530](https://tickets.chef.io/browse/COOK-3530)** - Update `client.rb` after 3.0.0 refactor +- **[COOK-2499](https://tickets.chef.io/browse/COOK-2499)** - Do not use resource cloning + +### Improvement + +- **[COOK-3116](https://tickets.chef.io/browse/COOK-3116)** - Add SmartOS support + +## v3.0.0 + +### Improvement + +- **[COOK-3328](https://tickets.chef.io/browse/COOK-3328)** - Postfix main/master and attributes refactor + +**Breaking changes**: + +- Attributes are namespaced as `node['postfix']`, `node['postfix']['main']`, and `node['postfix']['master']`. + +## v2.1.6 + +### Bug + +- [COOK-2501]: Reference to `['postfix']['domain']` should be `['postfix']['mydomain']` +- [COOK-2715]: master.cf uses old name for `smtp_fallback_relay` (`fallback_relay`) parameter in master.cf + +## v2.1.4 + +- [COOK-2281] - postfix aliases uses require_recipe statement + +## v2.1.2 + +- [COOK-2010] - postfix sasl_auth does not include the sasl plain package + +## v2.1.0 + +- [COOK-1233] - optional configuration for canonical maps +- [COOK-1660] - allow comma separated arrays in aliases +- [COOK-1662] - allow inet_interfaces configuration via attribute + +## v2.0.0 + +This version uses platform_family attribute, making the cookbook incompatible with older versions of Chef/Ohai, hence the major version bump. + +- [COOK-1535] - `smtpd_cache` should be in `data_directory`, not `queue_directory` +- [COOK-1790] - /etc/aliases template is only in ubuntu directory +- [COOK-1792] - add minitest-chef tests to postfix cookbook + +## v1.2.2 + +- [COOK-1442] - Missing ['postfix']['domain'] Attribute causes initial installation failure +- [COOK-1520] - Add support for procmail delivery +- [COOK-1528] - Make aliasses template less specific +- [COOK-1538] - Add iptables_rule template +- [COOK-1540] - Add smtpd_milters and non_smtpd_milters parameters to main.cf + +## v1.2.0 + +- [COOK-880] - add client/server roles for search-based discovery of relayhost + +## v1.0.0 + +- [COOK-668] - RHEL/CentOS/Scientific/Amazon platform support +- [COOK-733] - postfix::aliases recipe to manage /etc/aliases +- [COOK-821] - add README.md :) + +## v0.8.4 + +- Current public release. diff --git a/cookbooks/postfix/CONTRIBUTING.md b/cookbooks/postfix/CONTRIBUTING.md new file mode 100644 index 0000000..cd21578 --- /dev/null +++ b/cookbooks/postfix/CONTRIBUTING.md @@ -0,0 +1 @@ +Please refer to diff --git a/cookbooks/postfix/MAINTAINERS.md b/cookbooks/postfix/MAINTAINERS.md new file mode 100644 index 0000000..645ed14 --- /dev/null +++ b/cookbooks/postfix/MAINTAINERS.md @@ -0,0 +1,15 @@ + + +# Maintainers + +This file lists how this cookbook project is maintained. When making changes to the system, this file tells you who needs to review your patch - you need a review from an existing maintainer for the cookbook to provide a :+1: on your pull request. Additionally, you need to not receive a veto from a Lieutenant or the Project Lead. + +Check out [How Cookbooks are Maintained](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD) for details on the process and how to become a maintainer or the project lead. + +# Project Maintainer +* [Tim Smith](https://github.com/tas50) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) diff --git a/cookbooks/postfix/README.md b/cookbooks/postfix/README.md new file mode 100644 index 0000000..3531da4 --- /dev/null +++ b/cookbooks/postfix/README.md @@ -0,0 +1,446 @@ +# postfix Cookbook + +[![Build Status](https://travis-ci.org/chef-cookbooks/postfix.svg?branch=master)](https://travis-ci.org/chef-cookbooks/postfix) [![Cookbook Version](https://img.shields.io/cookbook/v/postfix.svg)](https://supermarket.chef.io/cookbooks/postfix) + +Installs and configures postfix for client or outbound relayhost, or to do SASL authentication. + +On RHEL-family systems, sendmail will be replaced with postfix. + +## Requirements + +### Platforms + +- Ubuntu 12.04+ +- Debian 7.0+ +- RHEL/CentOS/Scientific 5.7+, 6.2+ +- Amazon Linux (as of AMIs created after 4/9/2012) + +May work on other platforms with or without modification. + +### Chef + +- Chef 12.1+ + +### Cookbooks + +- none + +## Attributes + +See `attributes/default.rb` for default values. + +### Generic cookbook attributes + +- `node['postfix']['mail_type']` - Sets the kind of mail configuration. `master` will set up a server (relayhost). +- `node['postfix']['relayhost_role']` - name of a role used for search in the client recipe. +- `node['postfix']['multi_environment_relay']` - set to true if nodes should not constrain search for the relayhost in their own environment. +- `node['postfix']['use_procmail']` - set to true if nodes should use procmail as the delivery agent. +- `node['postfix']['use_alias_maps']` - set to true if you want the cookbook to use/configure alias maps +- `node['postfix']['use_transport_maps']` - set to true if you want the cookbook to use/configure transport maps +- `node['postfix']['use_access_maps']` - set to true if you want the cookbook to use/configure access maps +- `node['postfix']['use_virtual_aliases']` - set to true if you want the cookbook to use/configure virtual alias maps +- `node['postfix']['use_relay_restrictions_maps']` - set to true if you want the cookbook to use/configure a list of domains to which postfix will allow relay +- `node['postfix']['aliases']` - hash of aliases to create with `recipe[postfix::aliases]`, see below under **Recipes** for more information. +- `node['postfix']['transports']` - hash of transports to create with `recipe[postfix::transports]`, see below under **Recipes** for more information. +- `node['postfix']['access']` - hash of access to create with `recipe[postfix::access]`, see below under **Recipes** for more information. +- `node['postfix']['virtual_aliases']` - hash of virtual_aliases to create with `recipe[postfix::virtual_aliases]`, see below under __Recipes__ for more information. +- `node['postfix']['main_template_source']` - Cookbook source for main.cf template. Default 'postfix' +- `node['postfix']['master_template_source']` - Cookbook source for master.cf template. Default 'postfix' + +### main.cf and sasl_passwd template attributes + +The main.cf template has been simplified to include any attributes in the `node['postfix']['main']` data structure. The following attributes are still included with this cookbook to maintain some semblance of backwards compatibility. + +This change in namespace to `node['postfix']['main']` should allow for greater flexibility, given the large number of configuration variables for the postfix daemon. All of these cookbook attributes correspond to the option of the same name in `/etc/postfix/main.cf`. + +- `node['postfix']['main']['biff']` - (yes/no); default no +- `node['postfix']['main']['append_dot_mydomain']` - (yes/no); default no +- `node['postfix']['main']['myhostname']` - defaults to fqdn from Ohai +- `node['postfix']['main']['mydomain']` - defaults to domain from Ohai +- `node['postfix']['main']['myorigin']` - defaults to $myhostname +- `node['postfix']['main']['mynetworks']` - default is nil, which forces Postfix to default to loopback addresses. +- `node['postfix']['main']['inet_interfaces']` - set to `loopback-only`, or `all` for server recipe +- `node['postfix']['main']['alias_maps']` - set to `hash:/etc/aliases` +- `node['postfix']['main']['mailbox_size_limit']` - set to `0` (disabled) +- `node['postfix']['main']['mydestination']` - default fqdn, hostname, localhost.localdomain, localhost +- `node['postfix']['main']['smtpd_use_tls']` - (yes/no); default yes. See conditional cert/key attributes. +- `node['postfix']['main']['smtpd_tls_cert_file']` - conditional attribute, set to full path of server's x509 certificate. +- `node['postfix']['main']['smtpd_tls_key_file']` - conditional attribute, set to full path of server's private key +- `node['postfix']['main']['smtpd_tls_CAfile']` - set to platform specific CA bundle +- `node['postfix']['main']['smtpd_tls_session_cache_database']` - set to `btree:${data_directory}/smtpd_scache` +- `node['postfix']['main']['smtp_use_tls']` - (yes/no); default yes. See following conditional attributes. +- `node['postfix']['main']['smtp_tls_CAfile']` - set to platform specific CA bundle +- `node['postfix']['main']['smtp_tls_session_cache_database']` - set to `btree:${data_directory}/smtpd_scache` +- `node['postfix']['main']['smtp_sasl_auth_enable']` - (yes/no); default no. If enabled, see following conditional attributes. +- `node['postfix']['main']['smtp_sasl_password_maps']` - Set to `hash:/etc/postfix/sasl_passwd` template file +- `node['postfix']['main']['smtp_sasl_security_options']` - Set to noanonymous +- `node['postfix']['main']['relayhost']` - Set to empty string +- `node['postfix']['sasl']['smtp_sasl_user_name']` - SASL user to authenticate as. Default empty +- `node['postfix']['sasl']['smtp_sasl_passwd']` - SASL password to use. Default empty. +- `node['postfix']['sender_canonical_map_entries']` - (hash with key value pairs); default not configured. Setup generic canonical maps. See `man 5 canonical`. If has at least one value, then will be enabled in config. +- `node['postfix']['smtp_generic_map_entries']` - (hash with key value pairs); default not configured. Setup generic postfix maps. See `man 5 generic`. If has at least one value, then will be enabled in config. + +Example of json role config, for setup *_map_entries: + +`postfix : {` + +`...` + +`"smtp_generic_map_entries" : { "root@youinternaldomain.local" : "admin@example.com", "admin@youinternaldomain.local" : "admin@example.com" }` + +`}` + +### master.cf template attributes + +The master.cf template has been changed to allow full customization of the file content. For purpose of backwards compatibility default attributes generate the same master.cf. But via `node['postfix']['master']` data structure in your role for instance it can be completelly rewritten. + +Examples of json role config, for customize master.cf: + +`postfix : {` + +`...` + +turn some services off or on: + +```json + "master" : { + "smtps": { + "active": true + }, + "old-cyrus": { + "active": false + }, + "cyrus": { + "active": false + }, + "uucp": { + "active": false + }, + "ifmail": { + "active": false + }, +``` + +`...` define you own service: + +```json + "spamfilter": { + "comment": "My own spamfilter", + "active": true, + "order": 590, + "type": "unix", + "unpriv": false, + "chroot": false, + "command": "pipe", + "args": ["flags=Rq user=spamd argv=/usr/bin/spamfilter.sh -oi -f ${sender} ${recipient}"] + } +``` + +`...` + +`}` `}` + +The possible service hash fields and their meanings: hash key - have to be unique, unless you wish to override default definition. + +Field | Mandatory | Description +------- | --------- | -------------------------------------------------------------------- +active | Yes | Boolean. Defines whether or not the service needs to be in master.cf +comment | No | String. If you would like to add a comment line before service line +order | Yes | Integer. Number to define the order of lines in the file +type | Yes | String. Type of the service (inet, unix, fifo) +private | No | Boolean. If present replaced by `y` or `n`, otherwise by `-` +unpriv | No | Boolean. If present replaced by `y` or `n`, otherwise by `-` +chroot | No | Boolean. If present replaced by `y` or `n`, otherwise by `-` +wakeup | No | String. If present value placed in file, otherwise replaced by `-` +maxproc | No | String. If present value placed in file, otherwise replaced by `-` +command | Yes | String. The command to be executed. +args | Yes | Array of Strings. Arguments passed to command. + +For more information about meaning of the fields consult `master (5)` manual: + +## Recipes + +### default + +Installs the postfix package and manages the service and the main configuration files (`/etc/postfix/main.cf` and `/etc/postfix/master.cf`). See **Usage** and **Examples** to see how to affect behavior of this recipe through configuration. Depending on the `node['postfix']['use_alias_maps']`, `node['postfix']['use_transport_maps']`, `node['postfix']['use_access_maps']` and `node['postfix']['use_virtual_aliases']` attributes the default recipe can call additional recipes to manage additional postfix configuration files + +For a more dynamic approach to discovery for the relayhost, see the `client` and `server` recipes below. + +### client + +Use this recipe to have nodes automatically search for the mail relay based which node has the `node['postfix']['relayhost_role']` role. Sets the `node['postfix']['main']['relayhost']` attribute to the first result from the search. + +Includes the default recipe to install, configure and start postfix. + +Does not work with `chef-solo`. + +### sasl_auth + +Sets up the system to authenticate with a remote mail relay using SASL authentication. + +### server + +To use Chef Server search to automatically detect a node that is the relayhost, use this recipe in a role that will be relayhost. By default, the role should be "relayhost" but you can change the attribute `node['postfix']['relayhost_role']` to modify this. + +**Note** This recipe will set the `node['postfix']['mail_type']` to "master" with an override attribute. + +### maps + +General recipe to manage any number of any type postfix lookup tables. You can replace with it recipes like `transport` or `virtual_aliases`, but what is more important - you can create any kinds of maps, which has no own recipe, including database lookup maps configuration. `maps` is a hash keys of which is a lookup table type and value is another hash with filenames as the keys and hash with file content as the value. File content is an any number of key/value pairs which meaning depends on lookup table type. Examlle: + +```json + "override_attributes": { + "postfix": { + "maps": { + "hash": { + "/etc/postfix/vmailbox": { + "john@example.com": "ok", + "john@example.net": "ok", + }, + "/etc/postfix/virtual": { + "postmaster@example.com": "john@example.com", + "postmaster@example.net": "john@example.net", + "root@mail.example.net": "john@example.net" + }, + "/etc/postfix/envelope_senders": { + "@example.com": "john@example.com", + "@example.net": "john@example.net" + }, + "/etc/postfix/relay_recipients": { + "john@example.net": "ok", + "john@example.com": "ok", + "admin@example.com": "ok", + } + }, + "pgsql": { + "/etc/postfix/pgtest": { + "hosts": "db.local:2345", + "user": "postfix", + "password": "test", + "dbname": "postdb", + "query": "SELECT replacement FROM aliases WHERE mailbox = '%s'" + } + } + } + } +``` + +To use these files in your configuration reference them in `node['postfix']['main']`, for instance: + +```json + "postfix": { + "main": { + "smtpd_sender_login_maps": "hash:/etc/postfix/envelope_senders", + "relay_recipient_maps": "hash:/etc/postfix/relay_recipients", + "virtual_mailbox_maps": "hash:/etc/postfix/vmailbox", + "virtual_alias_maps": "hash:/etc/postfix/virtual", + } + } +``` + +### aliases + +Manage `/etc/aliases` with this recipe. Currently only Ubuntu 10.04 platform has a template for the aliases file. Add your aliases template to the `templates/default` or to the appropriate platform+version directory per the File Specificity rules for templates. Then specify a hash of aliases for the `node['postfix']['aliases']` attribute. + +Arrays are supported as alias values, since postfix supports comma separated values per alias, simply specify your alias as an array to use this handy feature. + +### aliases + +Manage `/etc/aliases` with this recipe. + +### transports + +Manage `/etc/postfix/transport` with this recipe. + +### access + +Manage `/etc/postfix/access` with this recipe. + +### virtual_aliases + +Manage `/etc/postfix/virtual` with this recipe. + +### relay_restrictions + +Manage `/etc/postfix/relay_restriction` with this recipe The postfix option smtpd_relay_restrictions in main.cf will point to this hash map db. + + + +## Usage + +On systems that should simply send mail directly to a relay, or out to the internet, use `recipe[postfix]` and modify the `node['postfix']['main']['relayhost']` attribute via a role. + +On systems that should be the MX for a domain, set the attributes accordingly and make sure the `node['postfix']['mail_type']` attribute is `master`. See **Examples** for information on how to use `recipe[postfix::server]` to do this automatically. + +If you need to use SASL authentication to send mail through your ISP (such as on a home network), use `postfix::sasl_auth` and set the appropriate attributes. + +For each of these implementations, see **Examples** for role usage. + +### Examples + +The example roles below only have the relevant postfix usage. You may have other contents depending on what you're configuring on your systems. + +The `base` role is applied to all nodes in the environment. + +```ruby +name "base" +run_list("recipe[postfix]") +override_attributes( + "postfix" => { + "mail_type" => "client", + "main" => { + "mydomain" => "example.com", + "myorigin" => "example.com", + "relayhost" => "[smtp.example.com]", + "smtp_use_tls" => "no" + } + } +) +``` + +The `relayhost` role is applied to the nodes that are relayhosts. Often this is 2 systems using a CNAME of `smtp.example.com`. + +```ruby +name "relayhost" +run_list("recipe[postfix::server]") +override_attributes( + "postfix" => { + "mail_type" => "master", + "main" => { + "mynetworks" => [ "10.3.3.0/24", "127.0.0.0/8" ], + "inet_interfaces" => "all", + "mydomain" => "example.com", + "myorigin" => "example.com" + } +) +``` + +The `sasl_relayhost` role is applied to the nodes that are relayhosts and require authenticating with SASL. For example this might be on a household network with an ISP that otherwise blocks direct internet access to SMTP. + +```ruby +name "sasl_relayhost" +run_list("recipe[postfix], recipe[postfix::sasl_auth]") +override_attributes( + "postfix" => { + "mail_type" => "master", + "main" => { + "mynetworks" => "10.3.3.0/24", + "mydomain" => "example.com", + "myorigin" => "example.com", + "relayhost" => "[smtp.comcast.net]:587", + "smtp_sasl_auth_enable" => "yes" + }, + "sasl" => { + "smtp_sasl_passwd" => "your_password", + "smtp_sasl_user_name" => "your_username" + } + } +) +``` + +For an example of using encrypted data bags to encrypt the SASL password, see the following blog post: + +- + +#### Examples using the client & server recipes + +If you'd like to use the more dynamic search based approach for discovery, use the server and client recipes. First, create a relayhost role. + +```ruby +name "relayhost" +run_list("recipe[postfix::server]") +override_attributes( + "postfix" => { + "main" => { + "mynetworks" => "10.3.3.0/24", + "mydomain" => "example.com", + "myorigin" => "example.com" + } + } +) +``` + +Then, add the `postfix::client` recipe to the run list of your `base` role or equivalent role for postfix clients. + +```ruby +name "base" +run_list("recipe[postfix::client]") +override_attributes( + "postfix" => { + "mail_type" => "client", + "main" => { + "mydomain" => "example.com", + "myorigin" => "example.com" + } + } +) +``` + +If you wish to use a different role name for the relayhost, then also set the attribute in the `base` role. For example, `postfix_master` as the role name: + +```ruby +name "postfix_master" +description "a role for postfix master that isn't relayhost" +run_list("recipe[postfix::server]") +override_attributes( + "postfix" => { + "main" => { + "mynetworks" => "10.3.3.0/24", + "mydomain" => "example.com", + "myorigin" => "example.com" + } + } +) +``` + +The base role would look something like this: + +```ruby +name "base" +run_list("recipe[postfix::client]") +override_attributes( + "postfix" => { + "relayhost_role" => "postfix_master", + "mail_type" => "client", + "main" => { + "mydomain" => "example.com", + "myorigin" => "example.com" + } + } +) +``` + +To use relay restrictions override the relay restrictions attribute in this format: + +```ruby +override_attributes( + "postfix" => { + "use_relay_restrictions_maps" => true, + "relay_restrictions" => { + "chef.io" => "OK", + ".chef.io" => "OK", + "example.com" => "OK" + } + } +) +``` + +## License & Authors + +**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io)) + +**Copyright:** 2009-2016, Chef Software, Inc. + +``` +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/cookbooks/postfix/attributes/default.rb b/cookbooks/postfix/attributes/default.rb new file mode 100644 index 0000000..d467072 --- /dev/null +++ b/cookbooks/postfix/attributes/default.rb @@ -0,0 +1,400 @@ +# Author:: Joshua Timberman +# Copyright:: 2009-2017, Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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. + +# Generic cookbook attributes +default['postfix']['mail_type'] = 'client' +default['postfix']['relayhost_role'] = 'relayhost' +default['postfix']['multi_environment_relay'] = false +default['postfix']['use_procmail'] = false +default['postfix']['use_alias_maps'] = (node['platform'] == 'freebsd') +default['postfix']['use_transport_maps'] = false +default['postfix']['use_access_maps'] = false +default['postfix']['use_virtual_aliases'] = false +default['postfix']['use_virtual_aliases_domains'] = false +default['postfix']['use_relay_restrictions_maps'] = false +default['postfix']['transports'] = {} +default['postfix']['access'] = {} +default['postfix']['virtual_aliases'] = {} +default['postfix']['virtual_aliases_domains'] = {} +default['postfix']['main_template_source'] = 'postfix' +default['postfix']['master_template_source'] = 'postfix' +default['postfix']['sender_canonical_map_entries'] = {} +default['postfix']['smtp_generic_map_entries'] = {} +default['postfix']['access_db_type'] = 'hash' +default['postfix']['aliases_db_type'] = 'hash' +default['postfix']['transport_db_type'] = 'hash' +default['postfix']['virtual_alias_db_type'] = 'hash' +default['postfix']['virtual_alias_domains_db_type'] = 'hash' + +case node['platform'] +when 'smartos' + default['postfix']['conf_dir'] = '/opt/local/etc/postfix' + default['postfix']['aliases_db'] = '/opt/local/etc/postfix/aliases' + default['postfix']['transport_db'] = '/opt/local/etc/postfix/transport' + default['postfix']['access_db'] = '/opt/local/etc/postfix/access' + default['postfix']['virtual_alias_db'] = '/opt/local/etc/postfix/virtual' + default['postfix']['virtual_alias_domains_db'] = '/opt/local/etc/postfix/virtual_domains' + default['postfix']['relay_restrictions_db'] = '/opt/local/etc/postfix/relay_restrictions' +when 'freebsd' + default['postfix']['conf_dir'] = '/usr/local/etc/postfix' + default['postfix']['aliases_db'] = '/etc/aliases' + default['postfix']['transport_db'] = '/usr/local/etc/postfix/transport' + default['postfix']['access_db'] = '/usr/local/etc/postfix/access' + default['postfix']['virtual_alias_db'] = '/usr/local/etc/postfix/virtual' + default['postfix']['virtual_alias_domains_db'] = '/usr/local/etc/postfix/virtual_domains' + default['postfix']['relay_restrictions_db'] = '/etc/postfix/relay_restrictions' +when 'omnios' + default['postfix']['conf_dir'] = '/opt/omni/etc/postfix' + default['postfix']['aliases_db'] = '/opt/omni/etc/postfix/aliases' + default['postfix']['transport_db'] = '/opt/omni/etc/postfix/transport' + default['postfix']['access_db'] = '/opt/omni/etc/postfix/access' + default['postfix']['virtual_alias_db'] = '/etc/omni/etc/postfix/virtual' + default['postfix']['virtual_alias_domains_db'] = '/etc/omni/etc/postfix/virtual_domains' + default['postfix']['relay_restrictions_db'] = '/opt/omni/etc/postfix/relay_restrictions' + default['postfix']['uid'] = 11 +else + default['postfix']['conf_dir'] = '/etc/postfix' + default['postfix']['aliases_db'] = '/etc/aliases' + default['postfix']['transport_db'] = '/etc/postfix/transport' + default['postfix']['access_db'] = '/etc/postfix/access' + default['postfix']['virtual_alias_db'] = '/etc/postfix/virtual' + default['postfix']['virtual_alias_domains_db'] = '/etc/postfix/virtual_domains' + default['postfix']['relay_restrictions_db'] = '/etc/postfix/relay_restrictions' +end + +# Non-default main.cf attributes +default['postfix']['main']['biff'] = 'no' +default['postfix']['main']['append_dot_mydomain'] = 'no' +default['postfix']['main']['myhostname'] = (node['fqdn'] || node['hostname']).to_s.chomp('.') +default['postfix']['main']['mydomain'] = (node['domain'] || node['hostname']).to_s.chomp('.') +default['postfix']['main']['myorigin'] = '$myhostname' +default['postfix']['main']['mydestination'] = [node['postfix']['main']['myhostname'], node['hostname'], 'localhost.localdomain', 'localhost'].compact +default['postfix']['main']['smtpd_use_tls'] = 'yes' +default['postfix']['main']['smtp_use_tls'] = 'yes' +default['postfix']['main']['smtp_sasl_auth_enable'] = 'no' +default['postfix']['main']['mailbox_size_limit'] = 0 +default['postfix']['main']['mynetworks'] = nil +default['postfix']['main']['inet_interfaces'] = 'loopback-only' + +# Conditional attributes, also reference _attributes recipe +case node['platform_family'] +when 'debian' + default['postfix']['cafile'] = '/etc/ssl/certs/ca-certificates.crt' +when 'smartos' + default['postfix']['main']['smtpd_use_tls'] = 'no' + default['postfix']['main']['smtp_use_tls'] = 'no' + default['postfix']['cafile'] = '/opt/local/etc/postfix/cacert.pem' +when 'rhel' + default['postfix']['cafile'] = '/etc/pki/tls/cert.pem' +else + default['postfix']['cafile'] = "#{node['postfix']['conf_dir']}/cacert.pem" +end + +# # Default main.cf attributes according to `postconf -d` +# default['postfix']['main']['relayhost'] = '' +# default['postfix']['main']['milter_default_action'] = 'tempfail' +# default['postfix']['main']['milter_protocol'] = '6' +# default['postfix']['main']['smtpd_milters'] = '' +# default['postfix']['main']['non_smtpd_milters'] = '' +# default['postfix']['main']['sender_canonical_classes'] = nil +# default['postfix']['main']['recipient_canonical_classes'] = nil +# default['postfix']['main']['canonical_classes'] = nil +# default['postfix']['main']['sender_canonical_maps'] = nil +# default['postfix']['main']['recipient_canonical_maps'] = nil +# default['postfix']['main']['canonical_maps'] = nil + +# Master.cf attributes +default['postfix']['master']['smtp']['active'] = true +default['postfix']['master']['smtp']['order'] = 10 +default['postfix']['master']['smtp']['type'] = 'inet' +default['postfix']['master']['smtp']['private'] = false +default['postfix']['master']['smtp']['chroot'] = false +default['postfix']['master']['smtp']['command'] = 'smtpd' +default['postfix']['master']['smtp']['args'] = [] + +default['postfix']['master']['submission']['active'] = false +default['postfix']['master']['submission']['order'] = 20 +default['postfix']['master']['submission']['type'] = 'inet' +default['postfix']['master']['submission']['private'] = false +default['postfix']['master']['submission']['chroot'] = false +default['postfix']['master']['submission']['command'] = 'smtpd' +default['postfix']['master']['submission']['args'] = ['-o smtpd_enforce_tls=yes', ' -o smtpd_sasl_auth_enable=yes', '-o smtpd_client_restrictions=permit_sasl_authenticated,reject'] + +default['postfix']['master']['smtps']['active'] = false +default['postfix']['master']['smtps']['order'] = 30 +default['postfix']['master']['smtps']['type'] = 'inet' +default['postfix']['master']['smtps']['private'] = false +default['postfix']['master']['smtps']['chroot'] = false +default['postfix']['master']['smtps']['command'] = 'smtpd' +default['postfix']['master']['smtps']['args'] = ['-o smtpd_tls_wrappermode=yes', '-o smtpd_sasl_auth_enable=yes', '-o smtpd_client_restrictions=permit_sasl_authenticated,reject'] + +default['postfix']['master']['628']['active'] = false +default['postfix']['master']['628']['order'] = 40 +default['postfix']['master']['628']['type'] = 'inet' +default['postfix']['master']['628']['private'] = false +default['postfix']['master']['628']['chroot'] = false +default['postfix']['master']['628']['command'] = 'qmqpdd' +default['postfix']['master']['628']['args'] = [] + +default['postfix']['master']['pickup']['active'] = true +default['postfix']['master']['pickup']['order'] = 50 +default['postfix']['master']['pickup']['type'] = 'fifo' +default['postfix']['master']['pickup']['private'] = false +default['postfix']['master']['pickup']['chroot'] = false +default['postfix']['master']['pickup']['wakeup'] = '60' +default['postfix']['master']['pickup']['maxproc'] = '1' +default['postfix']['master']['pickup']['command'] = 'pickup' +default['postfix']['master']['pickup']['args'] = [] + +default['postfix']['master']['cleanup']['active'] = true +default['postfix']['master']['cleanup']['order'] = 60 +default['postfix']['master']['cleanup']['type'] = 'unix' +default['postfix']['master']['cleanup']['private'] = false +default['postfix']['master']['cleanup']['chroot'] = false +default['postfix']['master']['cleanup']['maxproc'] = '0' +default['postfix']['master']['cleanup']['command'] = 'cleanup' +default['postfix']['master']['cleanup']['args'] = [] + +default['postfix']['master']['qmgr']['active'] = true +default['postfix']['master']['qmgr']['order'] = 70 +default['postfix']['master']['qmgr']['type'] = 'fifo' +default['postfix']['master']['qmgr']['private'] = false +default['postfix']['master']['qmgr']['chroot'] = false +default['postfix']['master']['qmgr']['wakeup'] = '300' +default['postfix']['master']['qmgr']['maxproc'] = '1' +default['postfix']['master']['qmgr']['command'] = 'qmgr' +default['postfix']['master']['qmgr']['args'] = [] + +default['postfix']['master']['tlsmgr']['active'] = true +default['postfix']['master']['tlsmgr']['order'] = 80 +default['postfix']['master']['tlsmgr']['type'] = 'unix' +default['postfix']['master']['tlsmgr']['chroot'] = false +default['postfix']['master']['tlsmgr']['wakeup'] = '1000?' +default['postfix']['master']['tlsmgr']['maxproc'] = '1' +default['postfix']['master']['tlsmgr']['command'] = 'tlsmgr' +default['postfix']['master']['tlsmgr']['args'] = [] + +default['postfix']['master']['rewrite']['active'] = true +default['postfix']['master']['rewrite']['order'] = 90 +default['postfix']['master']['rewrite']['type'] = 'unix' +default['postfix']['master']['rewrite']['chroot'] = false +default['postfix']['master']['rewrite']['command'] = 'trivial-rewrite' +default['postfix']['master']['rewrite']['args'] = [] + +default['postfix']['master']['bounce']['active'] = true +default['postfix']['master']['bounce']['order'] = 100 +default['postfix']['master']['bounce']['type'] = 'unix' +default['postfix']['master']['bounce']['chroot'] = false +default['postfix']['master']['bounce']['maxproc'] = '0' +default['postfix']['master']['bounce']['command'] = 'bounce' +default['postfix']['master']['bounce']['args'] = [] + +default['postfix']['master']['defer']['active'] = true +default['postfix']['master']['defer']['order'] = 110 +default['postfix']['master']['defer']['type'] = 'unix' +default['postfix']['master']['defer']['chroot'] = false +default['postfix']['master']['defer']['maxproc'] = '0' +default['postfix']['master']['defer']['command'] = 'bounce' +default['postfix']['master']['defer']['args'] = [] + +default['postfix']['master']['trace']['active'] = true +default['postfix']['master']['trace']['order'] = 120 +default['postfix']['master']['trace']['type'] = 'unix' +default['postfix']['master']['trace']['chroot'] = false +default['postfix']['master']['trace']['maxproc'] = '0' +default['postfix']['master']['trace']['command'] = 'bounce' +default['postfix']['master']['trace']['args'] = [] + +default['postfix']['master']['verify']['active'] = true +default['postfix']['master']['verify']['order'] = 130 +default['postfix']['master']['verify']['type'] = 'unix' +default['postfix']['master']['verify']['chroot'] = false +default['postfix']['master']['verify']['maxproc'] = '1' +default['postfix']['master']['verify']['command'] = 'verify' +default['postfix']['master']['verify']['args'] = [] + +default['postfix']['master']['flush']['active'] = true +default['postfix']['master']['flush']['order'] = 140 +default['postfix']['master']['flush']['type'] = 'unix' +default['postfix']['master']['flush']['private'] = false +default['postfix']['master']['flush']['chroot'] = false +default['postfix']['master']['flush']['wakeup'] = '1000?' +default['postfix']['master']['flush']['maxproc'] = '0' +default['postfix']['master']['flush']['command'] = 'flush' +default['postfix']['master']['flush']['args'] = [] + +default['postfix']['master']['proxymap']['active'] = true +default['postfix']['master']['proxymap']['order'] = 150 +default['postfix']['master']['proxymap']['type'] = 'unix' +default['postfix']['master']['proxymap']['chroot'] = false +default['postfix']['master']['proxymap']['command'] = 'proxymap' +default['postfix']['master']['proxymap']['args'] = [] + +default['postfix']['master']['smtpunix']['service'] = 'smtp' +default['postfix']['master']['smtpunix']['active'] = true +default['postfix']['master']['smtpunix']['order'] = 160 +default['postfix']['master']['smtpunix']['type'] = 'unix' +default['postfix']['master']['smtpunix']['chroot'] = false +default['postfix']['master']['smtpunix']['maxproc'] = '500' +default['postfix']['master']['smtpunix']['command'] = 'smtp' +default['postfix']['master']['smtpunix']['args'] = [] + +default['postfix']['master']['relay']['active'] = true +default['postfix']['master']['relay']['comment'] = 'When relaying mail as backup MX, disable fallback_relay to avoid MX loops' +default['postfix']['master']['relay']['order'] = 170 +default['postfix']['master']['relay']['type'] = 'unix' +default['postfix']['master']['relay']['chroot'] = false +default['postfix']['master']['relay']['command'] = 'smtp' +default['postfix']['master']['relay']['args'] = ['-o smtp_fallback_relay='] + +default['postfix']['master']['showq']['active'] = true +default['postfix']['master']['showq']['order'] = 180 +default['postfix']['master']['showq']['type'] = 'unix' +default['postfix']['master']['showq']['private'] = false +default['postfix']['master']['showq']['chroot'] = false +default['postfix']['master']['showq']['command'] = 'showq' +default['postfix']['master']['showq']['args'] = [] + +default['postfix']['master']['error']['active'] = true +default['postfix']['master']['error']['order'] = 190 +default['postfix']['master']['error']['type'] = 'unix' +default['postfix']['master']['error']['chroot'] = false +default['postfix']['master']['error']['command'] = 'error' +default['postfix']['master']['error']['args'] = [] + +default['postfix']['master']['discard']['active'] = true +default['postfix']['master']['discard']['order'] = 200 +default['postfix']['master']['discard']['type'] = 'unix' +default['postfix']['master']['discard']['chroot'] = false +default['postfix']['master']['discard']['command'] = 'discard' +default['postfix']['master']['discard']['args'] = [] + +default['postfix']['master']['local']['active'] = true +default['postfix']['master']['local']['order'] = 210 +default['postfix']['master']['local']['type'] = 'unix' +default['postfix']['master']['local']['unpriv'] = false +default['postfix']['master']['local']['chroot'] = false +default['postfix']['master']['local']['command'] = 'local' +default['postfix']['master']['local']['args'] = [] + +default['postfix']['master']['virtual']['active'] = true +default['postfix']['master']['virtual']['order'] = 220 +default['postfix']['master']['virtual']['type'] = 'unix' +default['postfix']['master']['virtual']['unpriv'] = false +default['postfix']['master']['virtual']['chroot'] = false +default['postfix']['master']['virtual']['command'] = 'virtual' +default['postfix']['master']['virtual']['args'] = [] + +default['postfix']['master']['lmtp']['active'] = true +default['postfix']['master']['lmtp']['order'] = 230 +default['postfix']['master']['lmtp']['type'] = 'unix' +default['postfix']['master']['lmtp']['chroot'] = false +default['postfix']['master']['lmtp']['command'] = 'lmtp' +default['postfix']['master']['lmtp']['args'] = [] + +default['postfix']['master']['anvil']['active'] = true +default['postfix']['master']['anvil']['order'] = 240 +default['postfix']['master']['anvil']['type'] = 'unix' +default['postfix']['master']['anvil']['chroot'] = false +default['postfix']['master']['anvil']['maxproc'] = '1' +default['postfix']['master']['anvil']['command'] = 'anvil' +default['postfix']['master']['anvil']['args'] = [] + +default['postfix']['master']['scache']['active'] = true +default['postfix']['master']['scache']['order'] = 250 +default['postfix']['master']['scache']['type'] = 'unix' +default['postfix']['master']['scache']['chroot'] = false +default['postfix']['master']['scache']['maxproc'] = '1' +default['postfix']['master']['scache']['command'] = 'scache' +default['postfix']['master']['scache']['args'] = [] + +default['postfix']['master']['maildrop']['active'] = true +default['postfix']['master']['maildrop']['comment'] = 'See the Postfix MAILDROP_README file for details. To main.cf will be added: maildrop_destination_recipient_limit=1' +default['postfix']['master']['maildrop']['order'] = 510 +default['postfix']['master']['maildrop']['type'] = 'unix' +default['postfix']['master']['maildrop']['unpriv'] = false +default['postfix']['master']['maildrop']['chroot'] = false +default['postfix']['master']['maildrop']['command'] = 'pipe' +default['postfix']['master']['maildrop']['args'] = ['flags=DRhu user=vmail argv=/usr/local/bin/maildrop -d ${recipient}'] + +default['postfix']['master']['old-cyrus']['active'] = false +default['postfix']['master']['old-cyrus']['comment'] = 'The Cyrus deliver program has changed incompatibly, multiple times.' +default['postfix']['master']['old-cyrus']['order'] = 520 +default['postfix']['master']['old-cyrus']['type'] = 'unix' +default['postfix']['master']['old-cyrus']['unpriv'] = false +default['postfix']['master']['old-cyrus']['chroot'] = false +default['postfix']['master']['old-cyrus']['command'] = 'pipe' +default['postfix']['master']['old-cyrus']['args'] = ['flags=R user=cyrus argv=/usr/lib/cyrus-imapd/deliver -e -m ${extension} ${user}'] + +default['postfix']['master']['cyrus']['active'] = true +default['postfix']['master']['cyrus']['comment'] = 'Cyrus 2.1.5 (Amos Gouaux). To main.cf will be added: cyrus_destination_recipient_limit=1' +default['postfix']['master']['cyrus']['order'] = 530 +default['postfix']['master']['cyrus']['type'] = 'unix' +default['postfix']['master']['cyrus']['unpriv'] = false +default['postfix']['master']['cyrus']['chroot'] = false +default['postfix']['master']['cyrus']['command'] = 'pipe' +default['postfix']['master']['cyrus']['args'] = ['user=cyrus argv=/usr/lib/cyrus-imapd/deliver -e -r ${sender} -m ${extension} ${user}'] + +default['postfix']['master']['uucp']['active'] = true +default['postfix']['master']['uucp']['comment'] = 'See the Postfix UUCP_README file for configuration details.' +default['postfix']['master']['uucp']['order'] = 540 +default['postfix']['master']['uucp']['type'] = 'unix' +default['postfix']['master']['uucp']['unpriv'] = false +default['postfix']['master']['uucp']['chroot'] = false +default['postfix']['master']['uucp']['command'] = 'pipe' +default['postfix']['master']['uucp']['args'] = ['flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)'] + +default['postfix']['master']['ifmail']['active'] = false +default['postfix']['master']['ifmail']['order'] = 550 +default['postfix']['master']['ifmail']['type'] = 'unix' +default['postfix']['master']['ifmail']['unpriv'] = false +default['postfix']['master']['ifmail']['chroot'] = false +default['postfix']['master']['ifmail']['command'] = 'pipe' +default['postfix']['master']['ifmail']['args'] = ['flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)'] + +default['postfix']['master']['bsmtp']['active'] = true +default['postfix']['master']['bsmtp']['order'] = 560 +default['postfix']['master']['bsmtp']['type'] = 'unix' +default['postfix']['master']['bsmtp']['unpriv'] = false +default['postfix']['master']['bsmtp']['chroot'] = false +default['postfix']['master']['bsmtp']['command'] = 'pipe' +default['postfix']['master']['bsmtp']['args'] = ['flags=Fq. user=foo argv=/usr/local/sbin/bsmtp -f $sender $nexthop $recipient'] + +# OS Aliases +default['postfix']['aliases'] = case node['platform'] + when 'freebsd' + { + 'MAILER-DAEMON' => 'postmaster', + 'bin' => 'root', + 'daemon' => 'root', + 'named' => 'root', + 'nobody' => 'root', + 'uucp' => 'root', + 'www' => 'root', + 'ftp-bugs' => 'root', + 'postfix' => 'root', + 'manager' => 'root', + 'dumper' => 'root', + 'operator' => 'root', + 'abuse' => 'postmaster', + } + else + {} + end + +if node['postfix']['use_relay_restrictions_maps'] + default['postfix']['main']['smtpd_relay_restrictions'] = "hash:#{node['postfix']['relay_restrictions_db']}, reject" +end diff --git a/cookbooks/postfix/metadata.json b/cookbooks/postfix/metadata.json new file mode 100644 index 0000000..e535f33 --- /dev/null +++ b/cookbooks/postfix/metadata.json @@ -0,0 +1 @@ +{"name":"postfix","version":"5.0.2","description":"Installs and configures postfix for client or outbound relayhost, or to do SASL auth","long_description":"# postfix Cookbook\n\n[![Build Status](https://travis-ci.org/chef-cookbooks/postfix.svg?branch=master)](https://travis-ci.org/chef-cookbooks/postfix) [![Cookbook Version](https://img.shields.io/cookbook/v/postfix.svg)](https://supermarket.chef.io/cookbooks/postfix)\n\nInstalls and configures postfix for client or outbound relayhost, or to do SASL authentication.\n\nOn RHEL-family systems, sendmail will be replaced with postfix.\n\n## Requirements\n\n### Platforms\n\n- Ubuntu 12.04+\n- Debian 7.0+\n- RHEL/CentOS/Scientific 5.7+, 6.2+\n- Amazon Linux (as of AMIs created after 4/9/2012)\n\nMay work on other platforms with or without modification.\n\n### Chef\n\n- Chef 12.1+\n\n### Cookbooks\n\n- none\n\n## Attributes\n\nSee `attributes/default.rb` for default values.\n\n### Generic cookbook attributes\n\n- `node['postfix']['mail_type']` - Sets the kind of mail configuration. `master` will set up a server (relayhost).\n- `node['postfix']['relayhost_role']` - name of a role used for search in the client recipe.\n- `node['postfix']['multi_environment_relay']` - set to true if nodes should not constrain search for the relayhost in their own environment.\n- `node['postfix']['use_procmail']` - set to true if nodes should use procmail as the delivery agent.\n- `node['postfix']['use_alias_maps']` - set to true if you want the cookbook to use/configure alias maps\n- `node['postfix']['use_transport_maps']` - set to true if you want the cookbook to use/configure transport maps\n- `node['postfix']['use_access_maps']` - set to true if you want the cookbook to use/configure access maps\n- `node['postfix']['use_virtual_aliases']` - set to true if you want the cookbook to use/configure virtual alias maps\n- `node['postfix']['use_relay_restrictions_maps']` - set to true if you want the cookbook to use/configure a list of domains to which postfix will allow relay\n- `node['postfix']['aliases']` - hash of aliases to create with `recipe[postfix::aliases]`, see below under **Recipes** for more information.\n- `node['postfix']['transports']` - hash of transports to create with `recipe[postfix::transports]`, see below under **Recipes** for more information.\n- `node['postfix']['access']` - hash of access to create with `recipe[postfix::access]`, see below under **Recipes** for more information.\n- `node['postfix']['virtual_aliases']` - hash of virtual_aliases to create with `recipe[postfix::virtual_aliases]`, see below under __Recipes__ for more information.\n- `node['postfix']['main_template_source']` - Cookbook source for main.cf template. Default 'postfix'\n- `node['postfix']['master_template_source']` - Cookbook source for master.cf template. Default 'postfix'\n\n### main.cf and sasl_passwd template attributes\n\nThe main.cf template has been simplified to include any attributes in the `node['postfix']['main']` data structure. The following attributes are still included with this cookbook to maintain some semblance of backwards compatibility.\n\nThis change in namespace to `node['postfix']['main']` should allow for greater flexibility, given the large number of configuration variables for the postfix daemon. All of these cookbook attributes correspond to the option of the same name in `/etc/postfix/main.cf`.\n\n- `node['postfix']['main']['biff']` - (yes/no); default no\n- `node['postfix']['main']['append_dot_mydomain']` - (yes/no); default no\n- `node['postfix']['main']['myhostname']` - defaults to fqdn from Ohai\n- `node['postfix']['main']['mydomain']` - defaults to domain from Ohai\n- `node['postfix']['main']['myorigin']` - defaults to $myhostname\n- `node['postfix']['main']['mynetworks']` - default is nil, which forces Postfix to default to loopback addresses.\n- `node['postfix']['main']['inet_interfaces']` - set to `loopback-only`, or `all` for server recipe\n- `node['postfix']['main']['alias_maps']` - set to `hash:/etc/aliases`\n- `node['postfix']['main']['mailbox_size_limit']` - set to `0` (disabled)\n- `node['postfix']['main']['mydestination']` - default fqdn, hostname, localhost.localdomain, localhost\n- `node['postfix']['main']['smtpd_use_tls']` - (yes/no); default yes. See conditional cert/key attributes.\n- `node['postfix']['main']['smtpd_tls_cert_file']` - conditional attribute, set to full path of server's x509 certificate.\n- `node['postfix']['main']['smtpd_tls_key_file']` - conditional attribute, set to full path of server's private key\n- `node['postfix']['main']['smtpd_tls_CAfile']` - set to platform specific CA bundle\n- `node['postfix']['main']['smtpd_tls_session_cache_database']` - set to `btree:${data_directory}/smtpd_scache`\n- `node['postfix']['main']['smtp_use_tls']` - (yes/no); default yes. See following conditional attributes.\n- `node['postfix']['main']['smtp_tls_CAfile']` - set to platform specific CA bundle\n- `node['postfix']['main']['smtp_tls_session_cache_database']` - set to `btree:${data_directory}/smtpd_scache`\n- `node['postfix']['main']['smtp_sasl_auth_enable']` - (yes/no); default no. If enabled, see following conditional attributes.\n- `node['postfix']['main']['smtp_sasl_password_maps']` - Set to `hash:/etc/postfix/sasl_passwd` template file\n- `node['postfix']['main']['smtp_sasl_security_options']` - Set to noanonymous\n- `node['postfix']['main']['relayhost']` - Set to empty string\n- `node['postfix']['sasl']['smtp_sasl_user_name']` - SASL user to authenticate as. Default empty\n- `node['postfix']['sasl']['smtp_sasl_passwd']` - SASL password to use. Default empty.\n- `node['postfix']['sender_canonical_map_entries']` - (hash with key value pairs); default not configured. Setup generic canonical maps. See `man 5 canonical`. If has at least one value, then will be enabled in config.\n- `node['postfix']['smtp_generic_map_entries']` - (hash with key value pairs); default not configured. Setup generic postfix maps. See `man 5 generic`. If has at least one value, then will be enabled in config.\n\nExample of json role config, for setup *_map_entries:\n\n`postfix : {`\n\n`...`\n\n`\"smtp_generic_map_entries\" : { \"root@youinternaldomain.local\" : \"admin@example.com\", \"admin@youinternaldomain.local\" : \"admin@example.com\" }`\n\n`}`\n\n### master.cf template attributes\n\nThe master.cf template has been changed to allow full customization of the file content. For purpose of backwards compatibility default attributes generate the same master.cf. But via `node['postfix']['master']` data structure in your role for instance it can be completelly rewritten.\n\nExamples of json role config, for customize master.cf:\n\n`postfix : {`\n\n`...`\n\nturn some services off or on:\n\n```json\n \"master\" : {\n \"smtps\": {\n \"active\": true\n },\n \"old-cyrus\": {\n \"active\": false\n },\n \"cyrus\": {\n \"active\": false\n },\n \"uucp\": {\n \"active\": false\n },\n \"ifmail\": {\n \"active\": false\n },\n```\n\n`...` define you own service:\n\n```json\n \"spamfilter\": {\n \"comment\": \"My own spamfilter\",\n \"active\": true,\n \"order\": 590,\n \"type\": \"unix\",\n \"unpriv\": false,\n \"chroot\": false,\n \"command\": \"pipe\",\n \"args\": [\"flags=Rq user=spamd argv=/usr/bin/spamfilter.sh -oi -f ${sender} ${recipient}\"]\n }\n```\n\n`...`\n\n`}` `}`\n\nThe possible service hash fields and their meanings: hash key - have to be unique, unless you wish to override default definition.\n\nField | Mandatory | Description\n------- | --------- | --------------------------------------------------------------------\nactive | Yes | Boolean. Defines whether or not the service needs to be in master.cf\ncomment | No | String. If you would like to add a comment line before service line\norder | Yes | Integer. Number to define the order of lines in the file\ntype | Yes | String. Type of the service (inet, unix, fifo)\nprivate | No | Boolean. If present replaced by `y` or `n`, otherwise by `-`\nunpriv | No | Boolean. If present replaced by `y` or `n`, otherwise by `-`\nchroot | No | Boolean. If present replaced by `y` or `n`, otherwise by `-`\nwakeup | No | String. If present value placed in file, otherwise replaced by `-`\nmaxproc | No | String. If present value placed in file, otherwise replaced by `-`\ncommand | Yes | String. The command to be executed.\nargs | Yes | Array of Strings. Arguments passed to command.\n\nFor more information about meaning of the fields consult `master (5)` manual: \n\n## Recipes\n\n### default\n\nInstalls the postfix package and manages the service and the main configuration files (`/etc/postfix/main.cf` and `/etc/postfix/master.cf`). See **Usage** and **Examples** to see how to affect behavior of this recipe through configuration. Depending on the `node['postfix']['use_alias_maps']`, `node['postfix']['use_transport_maps']`, `node['postfix']['use_access_maps']` and `node['postfix']['use_virtual_aliases']` attributes the default recipe can call additional recipes to manage additional postfix configuration files\n\nFor a more dynamic approach to discovery for the relayhost, see the `client` and `server` recipes below.\n\n### client\n\nUse this recipe to have nodes automatically search for the mail relay based which node has the `node['postfix']['relayhost_role']` role. Sets the `node['postfix']['main']['relayhost']` attribute to the first result from the search.\n\nIncludes the default recipe to install, configure and start postfix.\n\nDoes not work with `chef-solo`.\n\n### sasl_auth\n\nSets up the system to authenticate with a remote mail relay using SASL authentication.\n\n### server\n\nTo use Chef Server search to automatically detect a node that is the relayhost, use this recipe in a role that will be relayhost. By default, the role should be \"relayhost\" but you can change the attribute `node['postfix']['relayhost_role']` to modify this.\n\n**Note** This recipe will set the `node['postfix']['mail_type']` to \"master\" with an override attribute.\n\n### maps\n\nGeneral recipe to manage any number of any type postfix lookup tables. You can replace with it recipes like `transport` or `virtual_aliases`, but what is more important - you can create any kinds of maps, which has no own recipe, including database lookup maps configuration. `maps` is a hash keys of which is a lookup table type and value is another hash with filenames as the keys and hash with file content as the value. File content is an any number of key/value pairs which meaning depends on lookup table type. Examlle:\n\n```json\n \"override_attributes\": {\n \"postfix\": {\n \"maps\": {\n \"hash\": {\n \"/etc/postfix/vmailbox\": {\n \"john@example.com\": \"ok\",\n \"john@example.net\": \"ok\",\n },\n \"/etc/postfix/virtual\": {\n \"postmaster@example.com\": \"john@example.com\",\n \"postmaster@example.net\": \"john@example.net\",\n \"root@mail.example.net\": \"john@example.net\"\n },\n \"/etc/postfix/envelope_senders\": {\n \"@example.com\": \"john@example.com\",\n \"@example.net\": \"john@example.net\"\n },\n \"/etc/postfix/relay_recipients\": {\n \"john@example.net\": \"ok\",\n \"john@example.com\": \"ok\",\n \"admin@example.com\": \"ok\",\n }\n },\n \"pgsql\": {\n \"/etc/postfix/pgtest\": {\n \"hosts\": \"db.local:2345\",\n \"user\": \"postfix\",\n \"password\": \"test\",\n \"dbname\": \"postdb\",\n \"query\": \"SELECT replacement FROM aliases WHERE mailbox = '%s'\"\n }\n }\n }\n }\n```\n\nTo use these files in your configuration reference them in `node['postfix']['main']`, for instance:\n\n```json\n \"postfix\": {\n \"main\": {\n \"smtpd_sender_login_maps\": \"hash:/etc/postfix/envelope_senders\",\n \"relay_recipient_maps\": \"hash:/etc/postfix/relay_recipients\",\n \"virtual_mailbox_maps\": \"hash:/etc/postfix/vmailbox\",\n \"virtual_alias_maps\": \"hash:/etc/postfix/virtual\",\n }\n }\n```\n\n### aliases\n\nManage `/etc/aliases` with this recipe. Currently only Ubuntu 10.04 platform has a template for the aliases file. Add your aliases template to the `templates/default` or to the appropriate platform+version directory per the File Specificity rules for templates. Then specify a hash of aliases for the `node['postfix']['aliases']` attribute.\n\nArrays are supported as alias values, since postfix supports comma separated values per alias, simply specify your alias as an array to use this handy feature.\n\n### aliases\n\nManage `/etc/aliases` with this recipe.\n\n### transports\n\nManage `/etc/postfix/transport` with this recipe.\n\n### access\n\nManage `/etc/postfix/access` with this recipe.\n\n### virtual_aliases\n\nManage `/etc/postfix/virtual` with this recipe.\n\n### relay_restrictions\n\nManage `/etc/postfix/relay_restriction` with this recipe The postfix option smtpd_relay_restrictions in main.cf will point to this hash map db.\n\n\n\n## Usage\n\nOn systems that should simply send mail directly to a relay, or out to the internet, use `recipe[postfix]` and modify the `node['postfix']['main']['relayhost']` attribute via a role.\n\nOn systems that should be the MX for a domain, set the attributes accordingly and make sure the `node['postfix']['mail_type']` attribute is `master`. See **Examples** for information on how to use `recipe[postfix::server]` to do this automatically.\n\nIf you need to use SASL authentication to send mail through your ISP (such as on a home network), use `postfix::sasl_auth` and set the appropriate attributes.\n\nFor each of these implementations, see **Examples** for role usage.\n\n### Examples\n\nThe example roles below only have the relevant postfix usage. You may have other contents depending on what you're configuring on your systems.\n\nThe `base` role is applied to all nodes in the environment.\n\n```ruby\nname \"base\"\nrun_list(\"recipe[postfix]\")\noverride_attributes(\n \"postfix\" => {\n \"mail_type\" => \"client\",\n \"main\" => {\n \"mydomain\" => \"example.com\",\n \"myorigin\" => \"example.com\",\n \"relayhost\" => \"[smtp.example.com]\",\n \"smtp_use_tls\" => \"no\"\n }\n }\n)\n```\n\nThe `relayhost` role is applied to the nodes that are relayhosts. Often this is 2 systems using a CNAME of `smtp.example.com`.\n\n```ruby\nname \"relayhost\"\nrun_list(\"recipe[postfix::server]\")\noverride_attributes(\n \"postfix\" => {\n \"mail_type\" => \"master\",\n \"main\" => {\n \"mynetworks\" => [ \"10.3.3.0/24\", \"127.0.0.0/8\" ],\n \"inet_interfaces\" => \"all\",\n \"mydomain\" => \"example.com\",\n \"myorigin\" => \"example.com\"\n }\n)\n```\n\nThe `sasl_relayhost` role is applied to the nodes that are relayhosts and require authenticating with SASL. For example this might be on a household network with an ISP that otherwise blocks direct internet access to SMTP.\n\n```ruby\nname \"sasl_relayhost\"\nrun_list(\"recipe[postfix], recipe[postfix::sasl_auth]\")\noverride_attributes(\n \"postfix\" => {\n \"mail_type\" => \"master\",\n \"main\" => {\n \"mynetworks\" => \"10.3.3.0/24\",\n \"mydomain\" => \"example.com\",\n \"myorigin\" => \"example.com\",\n \"relayhost\" => \"[smtp.comcast.net]:587\",\n \"smtp_sasl_auth_enable\" => \"yes\"\n },\n \"sasl\" => {\n \"smtp_sasl_passwd\" => \"your_password\",\n \"smtp_sasl_user_name\" => \"your_username\"\n }\n }\n)\n```\n\nFor an example of using encrypted data bags to encrypt the SASL password, see the following blog post:\n\n- \n\n#### Examples using the client & server recipes\n\nIf you'd like to use the more dynamic search based approach for discovery, use the server and client recipes. First, create a relayhost role.\n\n```ruby\nname \"relayhost\"\nrun_list(\"recipe[postfix::server]\")\noverride_attributes(\n \"postfix\" => {\n \"main\" => {\n \"mynetworks\" => \"10.3.3.0/24\",\n \"mydomain\" => \"example.com\",\n \"myorigin\" => \"example.com\"\n }\n }\n)\n```\n\nThen, add the `postfix::client` recipe to the run list of your `base` role or equivalent role for postfix clients.\n\n```ruby\nname \"base\"\nrun_list(\"recipe[postfix::client]\")\noverride_attributes(\n \"postfix\" => {\n \"mail_type\" => \"client\",\n \"main\" => {\n \"mydomain\" => \"example.com\",\n \"myorigin\" => \"example.com\"\n }\n }\n)\n```\n\nIf you wish to use a different role name for the relayhost, then also set the attribute in the `base` role. For example, `postfix_master` as the role name:\n\n```ruby\nname \"postfix_master\"\ndescription \"a role for postfix master that isn't relayhost\"\nrun_list(\"recipe[postfix::server]\")\noverride_attributes(\n \"postfix\" => {\n \"main\" => {\n \"mynetworks\" => \"10.3.3.0/24\",\n \"mydomain\" => \"example.com\",\n \"myorigin\" => \"example.com\"\n }\n }\n)\n```\n\nThe base role would look something like this:\n\n```ruby\nname \"base\"\nrun_list(\"recipe[postfix::client]\")\noverride_attributes(\n \"postfix\" => {\n \"relayhost_role\" => \"postfix_master\",\n \"mail_type\" => \"client\",\n \"main\" => {\n \"mydomain\" => \"example.com\",\n \"myorigin\" => \"example.com\"\n }\n }\n)\n```\n\nTo use relay restrictions override the relay restrictions attribute in this format:\n\n```ruby\noverride_attributes(\n \"postfix\" => {\n \"use_relay_restrictions_maps\" => true,\n \"relay_restrictions\" => {\n \"chef.io\" => \"OK\",\n \".chef.io\" => \"OK\",\n \"example.com\" => \"OK\"\n }\n }\n)\n```\n\n## License & Authors\n\n**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io))\n\n**Copyright:** 2009-2016, Chef Software, Inc.\n\n```\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"ubuntu":">= 0.0.0","debian":">= 0.0.0","redhat":">= 0.0.0","centos":">= 0.0.0","amazon":">= 0.0.0","oracle":">= 0.0.0","scientific":">= 0.0.0","smartos":">= 0.0.0","fedora":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{"postfix":"Installs and configures postfix","postfix::sasl_auth":"Set up postfix to auth to a server with sasl","postfix::aliases":"Manages /etc/aliases","postfix::transports":"Manages /etc/postfix/transport","postfix::access":"Manages /etc/postfix/access","postfix::virtual_aliases":"Manages /etc/postfix/virtual","postfix::client":"Searches for the relayhost based on an attribute","postfix::server":"Sets the mail_type attribute to master","postfix::maps":"Manages any number of any type postfix lookup tables"},"source_url":"https://github.com/chef-cookbooks/postfix","issues_url":"https://github.com/chef-cookbooks/postfix/issues","chef_version":[[">= 12.1"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/postfix/recipes/_attributes.rb b/cookbooks/postfix/recipes/_attributes.rb new file mode 100644 index 0000000..f3ffe6e --- /dev/null +++ b/cookbooks/postfix/recipes/_attributes.rb @@ -0,0 +1,71 @@ +# Copyright:: 2012-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if node['postfix']['use_procmail'] + node.default_unless['postfix']['main']['mailbox_command'] = '/usr/bin/procmail -a "$EXTENSION"' +end + +if node['postfix']['main']['smtpd_use_tls'] == 'yes' + node.default_unless['postfix']['main']['smtpd_tls_cert_file'] = '/etc/ssl/certs/ssl-cert-snakeoil.pem' + node.default_unless['postfix']['main']['smtpd_tls_key_file'] = '/etc/ssl/private/ssl-cert-snakeoil.key' + node.default_unless['postfix']['main']['smtpd_tls_CAfile'] = node['postfix']['cafile'] + node.default_unless['postfix']['main']['smtpd_tls_session_cache_database'] = 'btree:${data_directory}/smtpd_scache' +end + +if node['postfix']['main']['smtp_use_tls'] == 'yes' + node.default_unless['postfix']['main']['smtp_tls_CAfile'] = node['postfix']['cafile'] + node.default_unless['postfix']['main']['smtp_tls_session_cache_database'] = 'btree:${data_directory}/smtp_scache' +end + +if node['postfix']['main']['smtp_sasl_auth_enable'] == 'yes' + node.default_unless['postfix']['sasl_password_file'] = "#{node['postfix']['conf_dir']}/sasl_passwd" + node.default_unless['postfix']['main']['smtp_sasl_password_maps'] = "hash:#{node['postfix']['sasl_password_file']}" + node.default_unless['postfix']['main']['smtp_sasl_security_options'] = 'noanonymous' + node.default_unless['postfix']['sasl']['smtp_sasl_user_name'] = '' + node.default_unless['postfix']['sasl']['smtp_sasl_passwd'] = '' + node.default_unless['postfix']['main']['relayhost'] = '' +end + +if node['postfix']['use_alias_maps'] + node.default_unless['postfix']['main']['alias_maps'] = ["hash:#{node['postfix']['aliases_db']}"] +end + +if node['postfix']['use_transport_maps'] + node.default_unless['postfix']['main']['transport_maps'] = ["hash:#{node['postfix']['transport_db']}"] +end + +if node['postfix']['use_access_maps'] + node.default_unless['postfix']['main']['access_maps'] = ["hash:#{node['postfix']['access_db']}"] +end + +if node['postfix']['use_virtual_aliases'] + node.default_unless['postfix']['main']['virtual_alias_maps'] = ["#{node['postfix']['virtual_alias_db_type']}:#{node['postfix']['virtual_alias_db']}"] +end + +if node['postfix']['use_virtual_aliases_domains'] + node.default_unless['postfix']['main']['virtual_alias_domains'] = ["#{node['postfix']['virtual_alias_domains_db_type']}:#{node['postfix']['virtual_alias_domains_db']}"] +end + +if node['postfix']['use_relay_restrictions_maps'] + default['postfix']['main']['smtpd_relay_restrictions'] = "hash:#{node['postfix']['relay_restrictions_db']}, reject" +end + +if node['postfix']['master']['maildrop']['active'] + node.default_unless['postfix']['main']['maildrop_destination_recipient_limit'] = 1 +end + +if node['postfix']['master']['cyrus']['active'] + node.default_unless['postfix']['main']['cyrus_destination_recipient_limit'] = 1 +end diff --git a/cookbooks/postfix/recipes/_common.rb b/cookbooks/postfix/recipes/_common.rb new file mode 100644 index 0000000..17d5e0e --- /dev/null +++ b/cookbooks/postfix/recipes/_common.rb @@ -0,0 +1,127 @@ +# Author:: Joshua Timberman() +# Cookbook:: common +# Recipe:: default +# +# Copyright:: 2009-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'postfix::_attributes' + +package 'postfix' + +package 'procmail' if node['postfix']['use_procmail'] + +case node['platform_family'] +when 'rhel', 'fedora' + service 'sendmail' do + action :nothing + end + + execute 'switch_mailer_to_postfix' do + command '/usr/sbin/alternatives --set mta /usr/sbin/sendmail.postfix' + notifies :stop, 'service[sendmail]' + notifies :start, 'service[postfix]' + not_if '/usr/bin/test /etc/alternatives/mta -ef /usr/sbin/sendmail.postfix' + end +when 'omnios' + manifest_path = ::File.join(Chef::Config[:file_cache_path], 'manifest-postfix.xml') + + # we need to manage the postfix group and user + # and then subscribe to the package install because it creates a + # postdrop group and adds postfix user to it. + group 'postfix' do + append true + end + + user 'postfix' do + uid node['postfix']['uid'] + gid 'postfix' + home '/var/spool/postfix' + subscribes :manage, 'package[postfix]' + notifies :run, 'execute[/opt/omni/sbin/postfix set-permissions]', :immediately + end + + # we don't guard this because if the user creation was successful (or happened out of band), then this won't get executed when the action is :nothing. + execute '/opt/omni/sbin/postfix set-permissions' + + template manifest_path do + source 'manifest-postfix.xml.erb' + owner 'root' + group node['root_group'] + mode '0644' + notifies :run, 'execute[load postfix manifest]', :immediately + end + + execute 'load postfix manifest' do + action :nothing + command "svccfg import #{manifest_path}" + notifies :restart, 'service[postfix]' + end +end + +execute 'update-postfix-sender_canonical' do + command "postmap #{node['postfix']['conf_dir']}/sender_canonical" + action :nothing +end + +unless node['postfix']['sender_canonical_map_entries'].empty? + template "#{node['postfix']['conf_dir']}/sender_canonical" do + owner 'root' + group node['root_group'] + mode '0644' + notifies :run, 'execute[update-postfix-sender_canonical]' + notifies :reload, 'service[postfix]' + end + + unless node['postfix']['main'].key?('sender_canonical_maps') + node.normal['postfix']['main']['sender_canonical_maps'] = "hash:#{node['postfix']['conf_dir']}/sender_canonical" + end +end + +execute 'update-postfix-smtp_generic' do + command "postmap #{node['postfix']['conf_dir']}/smtp_generic" + action :nothing +end + +unless node['postfix']['smtp_generic_map_entries'].empty? + template "#{node['postfix']['conf_dir']}/smtp_generic" do + owner 'root' + group node['root_group'] + mode '0644' + notifies :run, 'execute[update-postfix-smtp_generic]' + notifies :reload, 'service[postfix]' + end + + unless node['postfix']['main'].key?('smtp_generic_maps') + node.normal['postfix']['main']['smtp_generic_maps'] = "hash:#{node['postfix']['conf_dir']}/smtp_generic" + end +end + +%w( main master ).each do |cfg| + template "#{node['postfix']['conf_dir']}/#{cfg}.cf" do + source "#{cfg}.cf.erb" + owner 'root' + group node['root_group'] + mode '0644' + notifies :restart, 'service[postfix]' + variables(settings: node['postfix'][cfg]) + cookbook node['postfix']["#{cfg}_template_source"] + end +end + +service 'postfix' do + supports status: true, restart: true, reload: true + action :enable +end diff --git a/cookbooks/postfix/recipes/access.rb b/cookbooks/postfix/recipes/access.rb new file mode 100644 index 0000000..62e3025 --- /dev/null +++ b/cookbooks/postfix/recipes/access.rb @@ -0,0 +1,27 @@ +# Copyright:: 2012-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'postfix::_common' + +execute 'update-postfix-access' do + command "postmap #{node['postfix']['access_db']}" + environment PATH: "#{ENV['PATH']}:/opt/omni/bin:/opt/omni/sbin" if platform_family?('omnios') + action :nothing +end + +template node['postfix']['access_db'] do + source 'access.erb' + notifies :run, 'execute[update-postfix-access]' +end diff --git a/cookbooks/postfix/recipes/aliases.rb b/cookbooks/postfix/recipes/aliases.rb new file mode 100644 index 0000000..67d6db7 --- /dev/null +++ b/cookbooks/postfix/recipes/aliases.rb @@ -0,0 +1,29 @@ +# Copyright:: 2012-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'postfix::_common' + +execute 'update-postfix-aliases' do + command 'newaliases' + environment PATH: "#{ENV['PATH']}:/opt/omni/bin:/opt/omni/sbin" if platform_family?('omnios') + # On FreeBSD, /usr/sbin/newaliases is the sendmail command, and it's in the path before postfix's /usr/local/bin/newaliases + environment('PATH' => "/usr/local/bin:#{ENV['PATH']}") if platform_family?('freebsd') + action :nothing +end + +template node['postfix']['aliases_db'] do + source 'aliases.erb' + notifies :run, 'execute[update-postfix-aliases]' +end diff --git a/cookbooks/postfix/recipes/client.rb b/cookbooks/postfix/recipes/client.rb new file mode 100644 index 0000000..2231ce2 --- /dev/null +++ b/cookbooks/postfix/recipes/client.rb @@ -0,0 +1,41 @@ +# Author:: Joshua Timberman() +# Cookbook:: postfix +# Recipe:: client +# +# Copyright:: 2009-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if Chef::Config[:solo] + Chef::Log.info("#{cookbook_name}::#{recipe_name} is intended for use with Chef Server, use #{cookbook_name}::default with Chef Solo.") + return +end + +query = "role:#{node['postfix']['relayhost_role']}" +relayhost = '' +# results = [] + +if node.run_list.roles.include?(node['postfix']['relayhost_role']) + relayhost << node['ipaddress'] +elsif node['postfix']['multi_environment_relay'] + results = search(:node, query) + relayhost = results.map { |n| n['ipaddress'] }.first +else + results = search(:node, "#{query} AND chef_environment:#{node.chef_environment}") + relayhost = results.map { |n| n['ipaddress'] }.first +end + +node.normal['postfix']['main']['relayhost'] = "[#{relayhost}]" + +include_recipe 'postfix' diff --git a/cookbooks/postfix/recipes/default.rb b/cookbooks/postfix/recipes/default.rb new file mode 100644 index 0000000..07026e4 --- /dev/null +++ b/cookbooks/postfix/recipes/default.rb @@ -0,0 +1,36 @@ +# Author:: Joshua Timberman() +# Cookbook:: postfix +# Recipe:: default +# +# Copyright:: 2009-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'postfix::_common' + +include_recipe 'postfix::sasl_auth' if node['postfix']['main']['smtp_sasl_auth_enable'] == 'yes' + +include_recipe 'postfix::aliases' if node['postfix']['use_alias_maps'] + +include_recipe 'postfix::transports' if node['postfix']['use_transport_maps'] + +include_recipe 'postfix::access' if node['postfix']['use_access_maps'] + +include_recipe 'postfix::virtual_aliases' if node['postfix']['use_virtual_aliases'] + +include_recipe 'postfix::virtual_aliases_domains' if node['postfix']['use_virtual_aliases_domains'] + +include_recipe 'postfix::relay_restrictions' if node['postfix']['use_relay_restrictions_maps'] + +include_recipe 'postfix::maps' if node['postfix']['maps'] diff --git a/cookbooks/postfix/recipes/maps.rb b/cookbooks/postfix/recipes/maps.rb new file mode 100644 index 0000000..9c47486 --- /dev/null +++ b/cookbooks/postfix/recipes/maps.rb @@ -0,0 +1,47 @@ +# encoding: utf-8 +# Copyright:: 2012-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +node['postfix']['maps'].each do |type, maps| + if node['platform_family'] == 'debian' + package "postfix-#{type}" if %w(pgsql mysql ldap cdb).include?(type) + end + + separator = if %w(pgsql mysql ldap memcache sqlite).include?(type) + ' = ' + else + ' ' + end + maps.each do |file, content| + execute "update-postmap-#{file}" do + command "postmap #{file}" + environment PATH: "#{ENV['PATH']}:/opt/omni/bin:/opt/omni/sbin" if platform_family?('omnios') + action :nothing + end if %w(btree cdb dbm hash sdbm).include?(type) + template "#{file}-#{type}" do + path file + source 'maps.erb' + only_if "postconf -m | grep -q #{type}" + variables( + map: content, + separator: separator + ) + if %w(btree cdb dbm hash sdbm).include?(type) + notifies :run, "execute[update-postmap-#{file}]" + end + notifies :restart, 'service[postfix]' + end + end +end diff --git a/cookbooks/postfix/recipes/relay_restrictions.rb b/cookbooks/postfix/recipes/relay_restrictions.rb new file mode 100644 index 0000000..c5548e4 --- /dev/null +++ b/cookbooks/postfix/recipes/relay_restrictions.rb @@ -0,0 +1,27 @@ +# Copyright:: 2012-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'postfix::_common' + +execute 'update-postfix-relay-restrictions' do + command "postmap #{node['postfix']['relay_restrictions_db']}" + environment PATH: "#{ENV['PATH']}:/opt/omni/bin:/opt/omni/sbin" if platform_family?('omnios') + action :nothing +end + +template node['postfix']['relay_restrictions_db'] do + source 'relay_restrictions.erb' + notifies :run, 'execute[update-postfix-relay-restrictions]' +end diff --git a/cookbooks/postfix/recipes/sasl_auth.rb b/cookbooks/postfix/recipes/sasl_auth.rb new file mode 100644 index 0000000..38f040e --- /dev/null +++ b/cookbooks/postfix/recipes/sasl_auth.rb @@ -0,0 +1,59 @@ +# +# Author:: Joshua Timberman() +# Cookbook:: postfix +# Recipe:: sasl_auth +# +# Copyright:: 2009-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'postfix::_common' + +sasl_pkgs = [] + +# We use case instead of value_for_platform_family because we need +# version specifics for RHEL. +case node['platform_family'] +when 'debian' + sasl_pkgs = %w(libsasl2-2 libsasl2-modules ca-certificates) +when 'rhel' + sasl_pkgs = if node['platform_version'].to_i < 6 + %w(cyrus-sasl cyrus-sasl-plain openssl) + else + %w(cyrus-sasl cyrus-sasl-plain ca-certificates) + end +when 'fedora' + sasl_pkgs = %w(cyrus-sasl cyrus-sasl-plain ca-certificates) +end + +sasl_pkgs.each do |pkg| + package pkg +end + +execute 'postmap-sasl_passwd' do + command "postmap #{node['postfix']['sasl_password_file']}" + environment 'PATH' => "#{ENV['PATH']}:/opt/omni/bin:/opt/omni/sbin" if platform_family?('omnios') + action :nothing +end + +template node['postfix']['sasl_password_file'] do + sensitive true + source 'sasl_passwd.erb' + owner 'root' + group node['root_group'] + mode '400' + notifies :run, 'execute[postmap-sasl_passwd]', :immediately + notifies :restart, 'service[postfix]' + variables(settings: node['postfix']['sasl']) +end diff --git a/cookbooks/postfix/recipes/server.rb b/cookbooks/postfix/recipes/server.rb new file mode 100644 index 0000000..2166777 --- /dev/null +++ b/cookbooks/postfix/recipes/server.rb @@ -0,0 +1,24 @@ +# +# Author:: Joshua Timberman() +# Cookbook:: postfix +# Recipe:: server +# +# Copyright:: 2009-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +node.override['postfix']['mail_type'] = 'master' +node.override['postfix']['main']['inet_interfaces'] = 'all' + +include_recipe 'postfix' diff --git a/cookbooks/postfix/recipes/transports.rb b/cookbooks/postfix/recipes/transports.rb new file mode 100644 index 0000000..7386caa --- /dev/null +++ b/cookbooks/postfix/recipes/transports.rb @@ -0,0 +1,27 @@ +# Copyright:: 2012-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'postfix::_common' + +execute 'update-postfix-transport' do + command "postmap #{node['postfix']['transport_db']}" + environment PATH: "#{ENV['PATH']}:/opt/omni/bin:/opt/omni/sbin" if platform_family?('omnios') + action :nothing +end + +template node['postfix']['transport_db'] do + source 'transport.erb' + notifies :run, 'execute[update-postfix-transport]' +end diff --git a/cookbooks/postfix/recipes/virtual_aliases.rb b/cookbooks/postfix/recipes/virtual_aliases.rb new file mode 100644 index 0000000..f8e9eda --- /dev/null +++ b/cookbooks/postfix/recipes/virtual_aliases.rb @@ -0,0 +1,28 @@ +# Copyright:: 2012-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'postfix::_common' + +execute 'update-postfix-virtual-alias' do + command "postmap #{node['postfix']['virtual_alias_db']}" + environment PATH: "#{ENV['PATH']}:/opt/omni/bin:/opt/omni/sbin" if platform_family?('omnios') + action :nothing +end + +template node['postfix']['virtual_alias_db'] do + source 'virtual_aliases.erb' + notifies :run, 'execute[update-postfix-virtual-alias]' + notifies :restart, 'service[postfix]' +end diff --git a/cookbooks/postfix/recipes/virtual_aliases_domains.rb b/cookbooks/postfix/recipes/virtual_aliases_domains.rb new file mode 100644 index 0000000..067b697 --- /dev/null +++ b/cookbooks/postfix/recipes/virtual_aliases_domains.rb @@ -0,0 +1,28 @@ +# Copyright:: 2012-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include_recipe 'postfix::_common' + +execute 'update-postfix-virtual-alias-domains' do + command "postmap #{node['postfix']['virtual_alias_domains_db']}" + environment PATH: "#{ENV['PATH']}:/opt/omni/bin:/opt/omni/sbin" if platform_family?('omnios') + action :nothing +end + +template node['postfix']['virtual_alias_domains_db'] do + source 'virtual_aliases_domains.erb' + notifies :run, 'execute[update-postfix-virtual-alias-domains]' + notifies :restart, 'service[postfix]' +end diff --git a/cookbooks/postfix/templates/default/access.erb b/cookbooks/postfix/templates/default/access.erb new file mode 100644 index 0000000..d054fa9 --- /dev/null +++ b/cookbooks/postfix/templates/default/access.erb @@ -0,0 +1,9 @@ +# +# Auto-generated by Chef. Do not hand edit! +# Local modifications will be overwritten. +# +# See man 5 access for format + +<% node['postfix']['access'].each do |name, value| %> +<%= name %> <%= value %> +<% end unless node['postfix']['access'].nil? %> diff --git a/cookbooks/postfix/templates/default/aliases.erb b/cookbooks/postfix/templates/default/aliases.erb new file mode 100644 index 0000000..3093154 --- /dev/null +++ b/cookbooks/postfix/templates/default/aliases.erb @@ -0,0 +1,10 @@ +# +# Auto-generated by Chef. +# Local modifications will be overwritten. +# +# See man 5 aliases for format +postmaster: root + +<% node['postfix']['aliases'].each do |name, value| %> +<%= name %>: <%= [value].flatten.map{|x| if (x.include?("@")) then x else %Q("#{x}") end}.join(', ') %> +<% end unless node['postfix']['aliases'].nil? %> diff --git a/cookbooks/postfix/templates/default/main.cf.erb b/cookbooks/postfix/templates/default/main.cf.erb new file mode 100644 index 0000000..57067d2 --- /dev/null +++ b/cookbooks/postfix/templates/default/main.cf.erb @@ -0,0 +1,14 @@ +### +# Auto-generated by Chef. +# Local modifications will be overwritten. +# Configured as <%= node['postfix']['mail_type'] %> +### + +<% @settings.sort.map do |key, value| -%> +<% next if value.nil? -%> +<% if value.kind_of? Array -%> +<%= "#{key} = #{value.join(', ')}"%> +<% else -%> +<%= "#{key} = #{value}"%> +<% end -%> +<% end -%> diff --git a/cookbooks/postfix/templates/default/manifest-postfix.xml.erb b/cookbooks/postfix/templates/default/manifest-postfix.xml.erb new file mode 100644 index 0000000..8a1a77a --- /dev/null +++ b/cookbooks/postfix/templates/default/manifest-postfix.xml.erb @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cookbooks/postfix/templates/default/maps.erb b/cookbooks/postfix/templates/default/maps.erb new file mode 100644 index 0000000..a351e82 --- /dev/null +++ b/cookbooks/postfix/templates/default/maps.erb @@ -0,0 +1,8 @@ +# +# This file is generated by Chef. +# Local changes will be overwritten +# + +<% @map.each do |key, value| -%> +<%= key %><%= @separator %><%= value %> +<% end unless @map.nil? -%> diff --git a/cookbooks/postfix/templates/default/master.cf.erb b/cookbooks/postfix/templates/default/master.cf.erb new file mode 100644 index 0000000..fb37a6b --- /dev/null +++ b/cookbooks/postfix/templates/default/master.cf.erb @@ -0,0 +1,67 @@ +# This file is generated by Chef. +# Local changes will be overwritten +# +# Postfix master process configuration file. For details on the format +# of the file, see the master(5) manual page (command: "man 5 master"). +# +# ========================================================================== +# service type private unpriv chroot wakeup maxproc command + args +# (yes) (yes) (yes) (never) (100) +# ========================================================================== +<% @settings.sort_by{|k,v| v['order']}.map do |service, properties| -%> +<% next if !properties['active'] -%> +<% if properties.has_key?('comment') -%> +# +#<%= properties['comment'] %> +<% end -%> +<% if properties.has_key?('service') -%> +<%= properties['service'].ljust(10) -%> +<% else -%> +<%= service.ljust(10) -%> +<% end -%> + <%= properties['type'].ljust(6) -%> +<% if properties.has_key?('private') -%> +<% if properties['private'] -%> +<% priv='y' -%> +<% else -%> +<% priv='n' -%> +<% end -%> +<% else -%> +<% priv='-' -%> +<% end -%> +<%= priv.ljust(8) -%> +<% if properties.has_key?('unpriv') -%> +<% if properties['unpriv'] -%> +<% unpriv='y' -%> +<% else -%> +<% unpriv='n' -%> +<% end -%> +<% else -%> +<% unpriv='-' -%> +<% end -%> +<%= unpriv.ljust(8) -%> +<% if properties.has_key?('chroot') -%> +<% if properties['chroot'] -%> +<% chroot='y' -%> +<% else -%> +<% chroot='n' -%> +<% end -%> +<% else -%> +<% chroot='-' -%> +<% end -%> +<%= chroot.ljust(7) -%> +<% if properties.has_key?('wakeup') -%> + <%= properties['wakeup'].ljust(7) -%> +<% else -%> + <%= '-'.ljust(7) -%> +<% end -%> +<% if properties.has_key?('maxproc') -%> + <%= properties['maxproc'].ljust(7) -%> +<% else -%> + <%= '-'.ljust(7) -%> +<% end -%> + <%= properties['command'] %> +<% properties['args'].each do |arg| -%> + <%= arg %> +<% end -%> +<% end -%> diff --git a/cookbooks/postfix/templates/default/port_smtp.erb b/cookbooks/postfix/templates/default/port_smtp.erb new file mode 100644 index 0000000..eb6aa80 --- /dev/null +++ b/cookbooks/postfix/templates/default/port_smtp.erb @@ -0,0 +1,2 @@ +# SMTP +-A FWR -p tcp -m tcp --dport 25 -j ACCEPT diff --git a/cookbooks/postfix/templates/default/relay_restrictions.erb b/cookbooks/postfix/templates/default/relay_restrictions.erb new file mode 100644 index 0000000..85a9eda --- /dev/null +++ b/cookbooks/postfix/templates/default/relay_restrictions.erb @@ -0,0 +1,10 @@ +# +# Auto-generated by Chef. +# Local modifications will be overwritten. +# +# Attribute name is the domain name, Attribute value is either OK or REJECT + +<% node['postfix']['relay_restrictions'].each do |name, value| %> +<%= name %> <%= value %> +<% end unless node['postfix']['relay_restrictions'].nil? %> +* REJECT diff --git a/cookbooks/postfix/templates/default/sasl_passwd.erb b/cookbooks/postfix/templates/default/sasl_passwd.erb new file mode 100644 index 0000000..18f16b3 --- /dev/null +++ b/cookbooks/postfix/templates/default/sasl_passwd.erb @@ -0,0 +1,4 @@ +# Auto-generated by Chef. +# Local modifications will be overwritten. +# +<%= node['postfix']['main']['relayhost'] %> <%= @settings['smtp_sasl_user_name'] %>:<%= @settings['smtp_sasl_passwd'] %> diff --git a/cookbooks/postfix/templates/default/sender_canonical.erb b/cookbooks/postfix/templates/default/sender_canonical.erb new file mode 100644 index 0000000..3eb25ef --- /dev/null +++ b/cookbooks/postfix/templates/default/sender_canonical.erb @@ -0,0 +1,9 @@ +# +# Auto-generated by Chef. +# Local modifications will be overwritten. +# +# See man 5 canonical for format + +<% node['postfix']['sender_canonical_map_entries'].each do |name, value| %> +<%= name %> <%= value %> +<% end unless node['postfix']['sender_canonical_map_entries'].nil? %> diff --git a/cookbooks/postfix/templates/default/smtp_generic.erb b/cookbooks/postfix/templates/default/smtp_generic.erb new file mode 100644 index 0000000..47b36d2 --- /dev/null +++ b/cookbooks/postfix/templates/default/smtp_generic.erb @@ -0,0 +1,9 @@ +# +# Auto-generated by Chef. +# Local modifications will be overwritten. +# +# See man 5 generic for format + +<% node['postfix']['smtp_generic_map_entries'].each do |name, value| %> +<%= name %> <%= value %> +<% end unless node['postfix']['smtp_generic_map_entries'].nil? %> diff --git a/cookbooks/postfix/templates/default/transport.erb b/cookbooks/postfix/templates/default/transport.erb new file mode 100644 index 0000000..df31153 --- /dev/null +++ b/cookbooks/postfix/templates/default/transport.erb @@ -0,0 +1,9 @@ +# +# Auto-generated by Chef. +# Local modifications will be overwritten. +# +# See man 5 transport for format + +<% node['postfix']['transports'].each do |name, value| %> +<%= name %> <%= value %> +<% end unless node['postfix']['transports'].nil? %> diff --git a/cookbooks/postfix/templates/default/virtual_aliases.erb b/cookbooks/postfix/templates/default/virtual_aliases.erb new file mode 100644 index 0000000..d1bfadf --- /dev/null +++ b/cookbooks/postfix/templates/default/virtual_aliases.erb @@ -0,0 +1,9 @@ +# +# Auto-generated by Chef. +# Local modifications will be overwritten. +# +# See man 5 virtual for format + +<% node['postfix']['virtual_aliases'].each do |key, value| %> +<%= key %> <%= value %> +<% end unless node['postfix']['virtual_aliases'].nil? %> diff --git a/cookbooks/postfix/templates/default/virtual_aliases_domains.erb b/cookbooks/postfix/templates/default/virtual_aliases_domains.erb new file mode 100644 index 0000000..d4334b2 --- /dev/null +++ b/cookbooks/postfix/templates/default/virtual_aliases_domains.erb @@ -0,0 +1,9 @@ +# +# Auto-generated by Chef. +# Local modifications will be overwritten. +# +# See man 5 virtual for format + +<% node['postfix']['virtual_aliases_domains'].each do |key, value| %> +<%= key %> <%= value %> +<% end unless node['postfix']['virtual_aliases_domains'].nil? %> diff --git a/cookbooks/postgresql/CHANGELOG.md b/cookbooks/postgresql/CHANGELOG.md new file mode 100644 index 0000000..95af871 --- /dev/null +++ b/cookbooks/postgresql/CHANGELOG.md @@ -0,0 +1,153 @@ +# postgresql Cookbook CHANGELOG + +This file is used to list changes made in the last 3 major versions of the postgresql cookbook. + +## Unreleased + +## v7.1.4 (28-03-2019) + +- Fix installation of extensions. + +## v7.1.3 (15-01-2019) + +- Added support for dash in database role name. + +## v7.1.2 (06-01-2019) + +- Cleanup and update the user resource documentation and code. Removed extraneous 'sensitive' property which is a common property in all Chef resources. +- Change default permissions on the postgres.conf to be world readable so that psql can work. + +## v7.1.1 (26-09-2018) + +- Rename slave to follower +- Use CircleCI for testing +- Simplyfy extension resource + +## v7.1.0 (22-06-2018) + +- Update the `initdb` script to use initdb rather than a service. #542 +- Refactor database commands to use the common connect method. #535 +- Increase the unit test coverage. + +## v7.0.0 (25-05-2018) + +_Breaking Change_ Please see UPGRADING.md and the README.md for information how to use. + +- Add custom resources for: + + - `postgresql_client_install` + - `postgresql_server_install` + - `postgresql_repository` + - `postgresql_pg_gem` + +- Deprecate recipes: + + - `apt_pgdg_postgresql` + - `config_initdb` + - `config_pgtune` + - `contrib` + - `ruby` + - `yum_pgdg_postgresql` + +- Remove deprecated tests + +## v6.1.3 (2018-04-18) + +- Fix recipes referencing the old helpers + +## v6.1.2 (2018-04-16) + +**this will be the last release of the 6.0 series before all recipes are removed from the cookbook** + +- Deprecate all recipes + +## v6.1.1 (2017-03-08) + +- Fix pg gem installation on non-omnibus chef runs +- Resolve resource cloning deprecation warnings in the ruby recipe +- Fix issues resolving the timezone on CentOS 7 and probably other distros +- Test with Delivery local instead of Rake + +## v6.1.0 (2017-02-18) + +- Fix a method name conflict that caused errors if Chef Sugar was also being used on the run list +- Revert a previous PR that added support for Postgresql 9.6 as it introduced incorrect configuration values +- Added Fedora 25 support for pgdg packages +- Added RHEL 5 support for Postgresql 9.4 pgdg packages +- Removed testing for RHEL 5 and Ubuntu 12.04 as they are scheduled for EoL in the near future +- Improvements to Test Kitchen testing to allow more extensive testing in Travis CI +- Fixed the client recipe on Fedora +- Added Inspec tests for client installs + +## v6.0.1 (2017-01-04 + +- Fix systemd unit file template + +## v6.0.0 (2017-01-03) + +- This cookbook now requires Chef 12.1 or later +- Removed the dependency on the apt cookbook as this functionality is built into modern chef client releases +- Added a new custom resource for installing extensions. This acts as a replacement for the contrib recipe with minimal backwards compatibility. You can now install / remove extensions into any database. This adds the compat_resource cookbook dependency so we can continue to support Chef 12.1-12.4, which lack custom resource support. +- The unused get_result_orig helper has been removed. If you utilized this you'll want to move it to your own wrapper cookbook +- Updates for compatibility with Postgresql 9.5 and 9.6 +- Fixed client package installation on openSUSE Leap 42.2 +- ca-certificates recipe has been deprecated. If ca-certificates package needs to be upgraded the user should do so prior to including this recipe. Package upgrades in community cookbooks are generally a bad idea as this bring in updated packages to production systems. The recipe currently warns if used and will be removed with the next major cookbook release. +- Fixed RHEL platform detection in the Ruby recipe +- systemd fixes for RHEL systems +- Fix systemd service file include when using pgdg packages +- Package installation now uses multi-package installs to speed up converge times +- Added integration testing in Travis of the client recipe using a new test cookbook. This will be expanded in the future to cover server installation as well +- Expanded the specs to test converges on multiple platforms + +## v5.2.0 (2016-12-30) + +- Updated contacts and links to point to Sous Chefs now +- Added a Code of Conduct (the Chef CoC) +- Removed duplicate platforms in the metadata +- Fix Chef runs with local mode in the server recipe +- Fix the ruby recipe to not fail when you specify enabling both the apt and yum repos for mixed distro environments +- Set the postgresql data directory to 700 permissions +- Added node['postgresql']['pg_gem']['version'] to specify the version of the pg gem to install +- Cookstyle fixes for the latest cookstyle release +- Removed test deps from the Gemfile. Rely on ChefDK for base testing deps instead + +## v5.1.0 (2016-11-01) + +- Maintenance of this cookbook has been migrated from Heavy Water to Sous Chefs - +- Add support for Chef-Zero (local mode) +- Don't hardcode the UID / GID on RHEL/Amazon/Suse platforms +- Add PGDG yum RPMs for 9.5 / 9.6 + +## v5.0.0 (2016-10-25) + +### Breaking changes + +- Switched from Librarian to Berkshelf +- Remove support for the following platforms + + - SLES < 12 + - openSUSE < 13 + - Debian < 7 + - Ubuntu < 12.04 + - RHEL < 6 + - Amazon < 2013 + - Unsupported (EOL) Fedora releases + +### Other changes + +- Added support for Ubuntu 16.04 +- Loosened cookbook dependencies to not prevent pulling in the latest community cookbooks +- Added chef_version metadata +- Switched from rubocop to cookstyle and fix all warnings +- Removed minitests and the minitest handler +- Added support for opensuse / opensuseleap +- Added support for Fedora 23/24 +- Added a chefignore file to limit the files uploaded to the chef server +- Updated Test Kitchen config to test on modern platform releases +- Added a Rakefile and updated Travis to test with ChefDK and that rakefile +- Avoid installing packages included in build-essential twice in the ruby recipe +- Require at least build-essential 2.0 +- Don't cleanup the old PPA files in the apt_pgdg_postgresql recipe anymore. These should be long gone everywhere +- Remove logic in the apt_pgdg_postgresql recipe that made Chef fail when new distro releases came out +- Avoid node.set deprecation warnings +- Avoid managed_home deprecation warnings in server_redhat recipe diff --git a/cookbooks/postgresql/CONTRIBUTING.md b/cookbooks/postgresql/CONTRIBUTING.md new file mode 100644 index 0000000..e28e2a6 --- /dev/null +++ b/cookbooks/postgresql/CONTRIBUTING.md @@ -0,0 +1,21 @@ +# Contributing + +## Branches + +### `master` branch + +The master branch is the current committed changes. These changes may not yet be released although we try to release often. + +## Tags + +All releases are tagged in git. To see the releases available to you see the changelog or the tags directly. + +## Pull requests + +- + +## Issues + +Need to report an issue? Use the github issues: + +- diff --git a/cookbooks/postgresql/README.md b/cookbooks/postgresql/README.md new file mode 100644 index 0000000..d25d75e --- /dev/null +++ b/cookbooks/postgresql/README.md @@ -0,0 +1,433 @@ +# PostgreSQL cookbook + +[![Cookbook Version](https://img.shields.io/cookbook/v/postgresql.svg)](https://supermarket.chef.io/cookbooks/postgresql) +[![Build Status](https://img.shields.io/circleci/project/github/sous-chefs/postgresql/master.svg)](https://circleci.com/gh/sous-chefs/postgresql) +[![pullreminders](https://pullreminders.com/badge.svg)](https://pullreminders.com?ref=badge) + +Installs and configures PostgreSQL as a client or a server. + +## Upgrading + +If you are wondering where all the recipes went in v7.0+, or how on earth I use this new cookbook please see upgrading.md for a full description. + +## Requirements + +### Platforms + +- Amazon Linux +- Debian 7+ +- Ubuntu 14.04+ +- Red Hat/CentOS/Scientific 6+ +- Fedora + +### PostgreSQL version + +We follow the currently supported versions listed on + +### Chef + +- Chef 13.8+ + +### Cookbook Dependencies + +None. + +## Resources + +### postgresql_client_install + +This resource installs PostgreSQL client packages. + +#### Actions + +- `install` - (default) Install client packages + +#### Properties + +Name | Types | Description | Default | Required? +------------------- | ----------------- | ------------------------------------------------------------- | ----------------------------------------- | --------- +`version` | String | Version of PostgreSQL to install | '9.6' | no +`setup_repo` | Boolean | Define if you want to add the PostgreSQL repo | true | no +`hba_file` | String | | `#{conf_dir}/main/pg_hba.conf` | no +`ident_file` | String | | `#{conf_dir}/main/pg_ident.conf` | no +`external_pid_file` | String | | `/var/run/postgresql/#{version}-main.pid` | no +`password` | String, nil | Pass in a password, or have the cookbook generate one for you | | no + +#### Examples + +To install version 9.5: + +```ruby +postgresql_client_install 'My PostgreSQL Client install' do + version '9.5' +end +``` + +### postgresql_server_install + +This resource installs PostgreSQL client and server packages. + +#### Actions + +- `install` - (default) Install client and server packages +- `create` - Initialize the database + +#### Properties + +Name | Types | Description | Default | Required? +------------------- | --------------- | --------------------------------------------- | -------------------------------------------------- | --------- +`version` | String | Version of PostgreSQL to install | '9.6' | no +`setup_repo` | Boolean | Define if you want to add the PostgreSQL repo | true | no +`hba_file` | String | Path of pg_hba.conf file | `/pg_hba.conf'` | no +`ident_file` | String | Path of pg_ident.conf file | `/pg_ident.conf` | no +`external_pid_file` | String | Path of PID file | `/var/run/postgresql/-main.pid` | no +`password` | String, nil | Set PostgreSQL user password | 'generate' | no +`port` | Integer | Set listen port of PostgreSQL service | 5432 | no +`initdb_locale` | String | Locale to initialise the database with | 'C' | no + +#### Examples + +To install PostgreSQL server, set your own postgres password using non-default service port. + +```ruby +postgresql_server_install 'My PostgreSQL Server install' do + action :install +end + +postgresql_server_install 'Setup my PostgreSQL 9.6 server' do + password 'MyP4ssw0rd' + port 5433 + action :create +end +``` + +#### Known issues + +On some platforms (e.g. Ubuntu 18.04), your `initdb_locale` should be set to the +same as the template database [GH-555](https://github.com/sous-chefs/postgresql/issues/555). + +### postgresql_server_conf + +This resource manages postgresql.conf configuration file. + +#### Actions + +- `modify` - (default) Manager PostgreSQL configuration file (postgresql.conf) + +#### Properties + +Name | Types | Description | Default | Required? +---------------------- | ------- | --------------------------------------- | --------------------------------------------------- | --------- +`version` | String | Version of PostgreSQL to install | '9.6' | no +`data_directory` | String | Path of PostgreSQL data directory | `` | no +`hba_file` | String | Path of pg_hba.conf file | `/pg_hba.conf` | no +`ident_file` | String | Path of pg_ident.conf file | `/pg_ident.conf` | no +`external_pid_file` | String | Path of PID file | `/var/run/postgresql/-main.pid` | no +`stats_temp_directory` | String | Path of stats file | `/var/run/postgresql/version>-main.pg_stat_tmp` | no +`port` | Integer | Set listen port of PostgreSQL service | 5432 | no +`additional_config` | Hash | Extra configuration for the config file | {} | no + +#### Examples + +To setup your PostgreSQL configuration with a specific data directory. If you have installed a specific version of PostgreSQL (different from 9.6), you must specify version in this resource too. + +```ruby +postgresql_server_conf 'My PostgreSQL Config' do + version '9.5' + data_directory '/data/postgresql/9.5/main' + notifies :reload, 'service[postgresql]' +end +``` + +### postgresql_extension + +This resource manages PostgreSQL extensions for a given database. + +#### Actions + +- `create` - (default) Creates an extension in a given database +- `drop` - Drops an extension from the database + +#### Properties + +Name | Types | Description | Default | Required? +------------- | ------ | -------------------------------------------------------------------------------- | ---------------- | --------- +`database` | String | Name of the database to install the extension into | | yes +`extension` | String | Name of the extension to install the database | Name of resource | yes +`version` | String | Version of the extension to install | | no +`old_version` | String | Older module name for new extension replacement. Appends FROM to extension query | | no + +#### Examples + +To install the `adminpack` extension: + +```ruby +# Add the contrib package in Ubuntu/Debian +package 'postgresql-contrib-9.6' + +# Install adminpack extension +postgresql_extension 'postgres adminpack' do + database 'postgres' + extension 'adminpack' +end +``` + +### postgresql_access + +This resource uses the accumulator pattern to build up the `pg_hba.conf` file via chef resources instead of piling on a mountain of chef attributes to make this cookbook more reusable. It directly mirrors the configuration options of the postgres hba file in the resource and by default notifies the server with a reload to avoid a full restart, causing a potential outage of service. To revoke access, simply remove the resource and the access change won't be computed into the final `pg_hba.conf` + +#### Actions + +- `grant` - (default) Creates an access line inside of `pg_hba.conf` + +#### Properties + +Name | Types | Description | Default | Required? +--------------- | ------ | ----------------------------------------------------------------------------------------- | ----------------- | --------- +`name` | String | Name of the access resource, this is left as a comment inside the `pg_hba` config | Resource name | yes +`source` | String | The cookbook template filename if you want to use your own custom template | 'pg_hba.conf.erb' | yes +`cookbook` | String | The cookbook to look in for the template source | 'postgresql' | yes +`comment` | String | A comment to leave above the entry in `pg_hba` | nil | no +`access_type` | String | The type of access, e.g. local or host | 'local' | yes +`access_db` | String | The database to access. Can use 'all' for all databases | 'all' | yes +`access_user` | String | The user accessing the database. Can use 'all' for any user | 'all' | yes +`access_addr` | String | The address(es) allowed access. Can be nil if method ident is used since it is local then | nil | no +`access_method` | String | Authentication method to use | 'ident' | yes + +#### Examples + +To grant access to the PostgreSQL user with ident authentication: + +```ruby +postgresql_access 'local_postgres_superuser' do + comment 'Local postgres superuser access' + access_type 'local' + access_db 'all' + access_user 'postgres' + access_addr nil + access_method 'ident' +end +``` + +This generates the following line in the `pg_hba.conf`: + +``` +# Local postgres superuser access +local all postgres ident +``` + +**Note**: The template by default generates a local access for Unix domain sockets only to support running the SQL execute resources. In Postgres version 9.1 and higher, the method is 'peer' instead of 'ident' which is identical. It looks like this: + +``` +# "local" is for Unix domain socket connections only +local all all peer +``` + +### postgresql_ident + +This resource generate `pg_ident.conf` configuration file to manage user mapping between system and PostgreSQL users. + +#### Actions + +- `create` - (default) Creates an mapping line inside of `pg_ident.conf` + +#### Properties + +Name | Types | Description | Default | Required? +-------------- | ----------- | -------------------------------------------------------------------------- | ------------------- | --------- +`mapname` | String | Name of the user mapping | Resource name | yes +`source` | String | The cookbook template filename if you want to use your own custom template | 'pg_ident.conf.erb' | no +`cookbook` | String | The cookbook to look in for the template source | 'postgresql' | no +`comment` | String, nil | A comment to leave above the entry in `pg_ident` | nil | no +`system_user` | String | System user or regexp used for the mapping | None | yes +`pg_user` | String | Pg user or regexp used for the mapping | None | yes + +#### Examples + +Creates a `mymapping` mapping that map `john` system user to `user1` PostgreSQL user: + +```ruby +postgresql_ident 'Map john to user1' do + comment 'John Mapping' + mapname 'mymapping' + system_user 'john' + pg_user 'user1' +end +``` + +This generates the following line in the `pg_ident.conf`: + +``` +# MAPNAME SYSTEM-USERNAME PG-USERNAME + +# John Mapping +mymapping john user1 +``` + +To grant access to the foo user with password authentication: + +```ruby +postgresql_access 'local_foo_user' do + comment 'Foo user access' + access_type 'host' + access_db 'all' + access_user 'foo' + access_addr '127.0.0.1/32' + access_method 'md5' +end +``` + +This generates the following line in the `pg_hba.conf`: + +``` +# Local postgres superuser access +host all foo 127.0.0.1/32 ident +``` + +### postgresql_database + +This resource manages PostgreSQL databases. + +#### Actions + +- `create` - (default) Creates the given database. +- `drop` - Drops the given database. + +#### Properties + +Name | Types | Description | Default | Required? +---------- | ------- | ------------------------------------------------------------------- | ------------------- | --------- +`database` | String | Name of the database to create | Resource name | yes +`user` | String | User which run psql command | 'postgres' | no +`template` | String | Template used to create the new database | 'template1' | no +`host` | String | Define the host server where the database creation will be executed | Not set (localhost) | no +`port` | Integer | Define the port of PostgreSQL server | 5432 | no +`encoding` | String | Define database encoding | 'UTF-8' | no +`locale` | String | Define database locale | 'en_US.UTF-8' | no +`owner` | String | Define the owner of the database | Not set | no + +#### Examples + +To create database named 'my_app' with owner 'user1': + +```ruby +postgresql_database 'my_app' do + owner 'user1' +end +``` + +#### Known issues + +On some platforms (e.g. Ubuntu 18.04), your `initdb_locale` should be set to the +same as the template database [GH-555](https://github.com/sous-chefs/postgresql/issues/555). + +### postgresql_user + +This resource manage PostgreSQL users. + +#### Actions + +- `create` - (default) Creates the given user with default or given privileges. +- `update` - Update user privilieges. +- `drop` - Deletes the given user. + +#### Properties + +Name | Types | Description | Default | Required? +-------------------- | ------- | ----------------------------------------------- | -------- | --------- +`create_user` | String | User to create (defaults to the resource name) | | Yes +`superuser` | Boolean | Define if user needs superuser role | false | no +`createdb` | Boolean | Define if user needs createdb role | false | no +`createrole` | Boolean | Define if user needs createrole role | false | no +`inherit` | Boolean | Define if user inherits the privileges of roles | true | no +`replication` | Boolean | Define if user needs replication role | false | no +`login` | Boolean | Define if user can login | true | no +`password` | String | Set user's password | | no +`encrypted_password` | String | Set user's password with an hashed password | | no +`valid_until` | String | Define an account expiration date | | no +`attributes` | Hash | Additional attributes for :update action | {} | no +`user` | String | User for command | postgres | no +`database` | String | Database for command | | no +`host` | String | Hostname for command | | no +`port` | Integer | Port number to connect to postgres | 5432 | no + +#### Examples + +Create a user `user1` with a password, with `createdb` role and set an expiration date to 2018, Dec 21. + +```ruby +postgresql_user 'user1' do + password 'UserP4ssword' + createdb true + valid_until '2018-12-31' +end +``` + +Create a user `user1` with a password, with `createdb` role and set an expiration date to 2018, Dec 21. + +```ruby +postgresql_user 'user1' do + password 'UserP4ssword' + createdb true + valid_until '2018-12-31' +end +``` + +## Usage + +To install and configure your PostgreSQL instance you need to create your own cookbook and call needed resources with your own parameters. + +More examples can be found in `test/cookbooks/test/recipes` + +## Example Usage + +```ruby +# cookbooks/my_postgresql/recipes/default.rb + +postgresql_client_install 'PostgreSQL Client' do + setup_repo false + version '10.6' +end + +postgresql_server_install 'PostgreSQL Server' do + version '10.6' + setup_repo false + password 'P0stgresP4ssword' +end + +postgresql_server_conf 'PostgreSQL Config' do + notifies :reload, 'service[postgresql]' +end +``` + +## Contributing + +Please refer to each project's style guidelines and guidelines for submitting patches and additions. In general, we follow the "fork-and-pull" Git workflow. + +1. **Fork** the repo on GitHub +2. **Clone** the project to your own machine +3. **Commit** changes to your own branch +4. **Push** your work back up to your fork +5. Submit a **Pull request** so that we can review your changes + +NOTE: Be sure to merge the latest from "upstream" before making a pull request! + +[Contribution informations for this project](CONTRIBUTING.md) + +## License + +Copyright 2010-2017, Chef Software, Inc. + +```text +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/cookbooks/postgresql/libraries/helpers.rb b/cookbooks/postgresql/libraries/helpers.rb new file mode 100644 index 0000000..431d5dd --- /dev/null +++ b/cookbooks/postgresql/libraries/helpers.rb @@ -0,0 +1,247 @@ +# +# Cookbook:: postgresql +# Library:: helpers +# +# 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. +# + +module PostgresqlCookbook + module Helpers + include Chef::Mixin::ShellOut + + require 'securerandom' + + def psql_command_string(new_resource, query, grep_for: nil, value_only: false) + cmd = "/usr/bin/psql -c \"#{query}\"" + cmd << " -d #{new_resource.database}" if new_resource.database + cmd << " -U #{new_resource.user}" if new_resource.user + cmd << " --host #{new_resource.host}" if new_resource.host + cmd << " --port #{new_resource.port}" if new_resource.port + cmd << ' --tuples-only' if value_only + cmd << " | grep #{grep_for}" if grep_for + cmd + end + + def execute_sql(new_resource, query) + # If we don't pass in a user to the resource + # default to the postgres user + user = new_resource.user ? new_resource.user : 'postgres' + + # Query could be a String or an Array of Strings + statement = query.is_a?(String) ? query : query.join("\n") + + cmd = shell_out(statement, user: user) + + # Pass back cmd so we can decide what to do with it in the calling method. + cmd + end + + def database_exists?(new_resource) + sql = %(SELECT datname from pg_database WHERE datname='#{new_resource.database}') + + exists = psql_command_string(new_resource, sql, grep_for: new_resource.database) + + cmd = execute_sql(new_resource, exists) + cmd.exitstatus == 0 + end + + def user_exists?(new_resource) + sql = %(SELECT rolname FROM pg_roles WHERE rolname='#{new_resource.create_user}';) + + exists = psql_command_string(new_resource, sql, grep_for: new_resource.create_user) + + cmd = execute_sql(new_resource, exists) + cmd.exitstatus == 0 + end + + def extension_installed?(new_resource) + query = %(SELECT extversion FROM pg_extension WHERE extname='#{new_resource.extension}';) + check_extension_version = psql_command_string(new_resource, query, value_only: true) + version_result = execute_sql(new_resource, check_extension_version) + if new_resource.version + version_result.stdout == new_resource.version + else + !version_result.stdout.chomp.empty? + end + end + + def alter_role_sql(new_resource) + sql = %(ALTER ROLE postgres ENCRYPTED PASSWORD '#{postgres_password(new_resource)}';) + psql_command_string(new_resource, sql) + end + + def create_extension_sql(new_resource) + sql = "CREATE EXTENSION IF NOT EXISTS #{new_resource.extension}" + sql << " FROM \"#{new_resource.old_version}\"" if new_resource.old_version + + psql_command_string(new_resource, sql) + end + + def user_has_password?(new_resource) + sql = %(SELECT rolpassword from pg_authid WHERE rolname='postgres' AND rolpassword IS NOT NULL;) + cmd = psql_command_string(new_resource, sql) + + res = execute_sql(new_resource, cmd) + res.stdout =~ /1 row/ ? true : false + end + + def role_sql(new_resource) + sql = %(\\"#{new_resource.create_user}\\" WITH ) + + %w(superuser createdb createrole inherit replication login).each do |perm| + sql << "#{'NO' unless new_resource.send(perm)}#{perm.upcase} " + end + + sql << if new_resource.encrypted_password + "ENCRYPTED PASSWORD '#{new_resource.encrypted_password}'" + elsif new_resource.password + "PASSWORD '#{new_resource.password}'" + else + '' + end + + sql << if new_resource.valid_until + " VALID UNTIL '#{new_resource.valid_until}'" + else + '' + end + end + + def create_user_sql(new_resource) + sql = %(CREATE ROLE #{role_sql(new_resource)}) + psql_command_string(new_resource, sql) + end + + def update_user_sql(new_resource) + sql = %(ALTER ROLE #{role_sql(new_resource)}) + psql_command_string(new_resource, sql) + end + + def update_user_with_attributes_sql(new_resource, value) + sql = %(ALTER ROLE '#{new_resource.create_user}' SET #{attr} = #{value}) + psql_command_string(new_resource, sql) + end + + def drop_user_sql(new_resource) + sql = %(DROP ROLE IF EXISTS '#{new_resource.create_user}') + psql_command_string(new_resource, sql) + end + + def data_dir(version = node.run_state['postgresql']['version']) + case node['platform_family'] + when 'rhel', 'fedora' + "/var/lib/pgsql/#{version}/data" + when 'amazon' + if node['virtualization']['system'] == 'docker' + "/var/lib/pgsql#{version.delete('.')}/data" + else + "/var/lib/pgsql/#{version}/data" + end + when 'debian' + "/var/lib/postgresql/#{version}/main" + end + end + + def conf_dir(version = node.run_state['postgresql']['version']) + case node['platform_family'] + when 'rhel', 'fedora' + "/var/lib/pgsql/#{version}/data" + when 'amazon' + if node['virtualization']['system'] == 'docker' + "/var/lib/pgsql#{version.delete('.')}/data" + else + "/var/lib/pgsql/#{version}/data" + end + when 'debian' + "/etc/postgresql/#{version}/main" + end + end + + # determine the platform specific service name + def platform_service_name(version = node.run_state['postgresql']['version']) + case node['platform_family'] + when 'rhel', 'fedora' + "postgresql-#{version}" + when 'amazon' + if node['virtualization']['system'] == 'docker' + "postgresql#{version.delete('.')}" + else + "postgresql-#{version}" + end + else + 'postgresql' + end + end + + def follower? + ::File.exist? "#{data_dir}/recovery.conf" + end + + def initialized? + return true if ::File.exist?("#{conf_dir}/PG_VERSION") + false + end + + def secure_random + r = SecureRandom.hex + Chef::Log.debug "Generated password: #{r}" + r + end + + # determine the platform specific server package name + def server_pkg_name + platform_family?('debian') ? "postgresql-#{new_resource.version}" : "postgresql#{new_resource.version.delete('.')}-server" + end + + # determine the appropriate DB init command to run based on RHEL/Fedora/Amazon release + # initdb defaults to the execution environment. + # https://www.postgresql.org/docs/9.5/static/locale.html + def rhel_init_db_command(new_resource) + cmd = if platform_family?('amazon') + '/usr/bin/initdb' + else + "/usr/pgsql-#{new_resource.version}/bin/initdb" + end + cmd << " --locale '#{new_resource.initdb_locale}'" if new_resource.initdb_locale + cmd << " -D '#{data_dir(new_resource.version)}'" + end + + # Given the base URL build the complete URL string for a yum repo + def yum_repo_url(base_url) + "#{base_url}/#{new_resource.version}/#{yum_repo_platform_family_string}/#{yum_repo_platform_string}" + end + + # The postgresql yum repos URLs are organized into redhat and fedora directories.s + # route things to the right place based on platform_family + def yum_repo_platform_family_string + platform_family?('fedora') ? 'fedora' : 'redhat' + end + + # Build the platform string that makes up the final component of the yum repo URL + def yum_repo_platform_string + platform = platform?('fedora') ? 'fedora' : 'rhel' + release = platform?('amazon') ? '6' : '$releasever' + "#{platform}-#{release}-$basearch" + end + + # On Amazon use the RHEL 6 packages. Otherwise use the releasever yum variable + def yum_releasever + platform?('amazon') ? '6' : '$releasever' + end + + # Generate a password if the value is set to generate. + def postgres_password(new_resource) + new_resource.password == 'generate' ? secure_random : new_resource.password + end + end +end diff --git a/cookbooks/postgresql/metadata.json b/cookbooks/postgresql/metadata.json new file mode 100644 index 0000000..52a549a --- /dev/null +++ b/cookbooks/postgresql/metadata.json @@ -0,0 +1 @@ +{"name":"postgresql","version":"7.1.4","description":"Installs and configures postgresql for clients or servers","long_description":"# PostgreSQL cookbook\n\n[![Cookbook Version](https://img.shields.io/cookbook/v/postgresql.svg)](https://supermarket.chef.io/cookbooks/postgresql)\n[![Build Status](https://img.shields.io/circleci/project/github/sous-chefs/postgresql/master.svg)](https://circleci.com/gh/sous-chefs/postgresql)\n[![pullreminders](https://pullreminders.com/badge.svg)](https://pullreminders.com?ref=badge)\n\nInstalls and configures PostgreSQL as a client or a server.\n\n## Upgrading\n\nIf you are wondering where all the recipes went in v7.0+, or how on earth I use this new cookbook please see upgrading.md for a full description.\n\n## Requirements\n\n### Platforms\n\n- Amazon Linux\n- Debian 7+\n- Ubuntu 14.04+\n- Red Hat/CentOS/Scientific 6+\n- Fedora\n\n### PostgreSQL version\n\nWe follow the currently supported versions listed on \n\n### Chef\n\n- Chef 13.8+\n\n### Cookbook Dependencies\n\nNone.\n\n## Resources\n\n### postgresql_client_install\n\nThis resource installs PostgreSQL client packages.\n\n#### Actions\n\n- `install` - (default) Install client packages\n\n#### Properties\n\nName | Types | Description | Default | Required?\n------------------- | ----------------- | ------------------------------------------------------------- | ----------------------------------------- | ---------\n`version` | String | Version of PostgreSQL to install | '9.6' | no\n`setup_repo` | Boolean | Define if you want to add the PostgreSQL repo | true | no\n`hba_file` | String | | `#{conf_dir}/main/pg_hba.conf` | no\n`ident_file` | String | | `#{conf_dir}/main/pg_ident.conf` | no\n`external_pid_file` | String | | `/var/run/postgresql/#{version}-main.pid` | no\n`password` | String, nil | Pass in a password, or have the cookbook generate one for you | | no\n\n#### Examples\n\nTo install version 9.5:\n\n```ruby\npostgresql_client_install 'My PostgreSQL Client install' do\n version '9.5'\nend\n```\n\n### postgresql_server_install\n\nThis resource installs PostgreSQL client and server packages.\n\n#### Actions\n\n- `install` - (default) Install client and server packages\n- `create` - Initialize the database\n\n#### Properties\n\nName | Types | Description | Default | Required?\n------------------- | --------------- | --------------------------------------------- | -------------------------------------------------- | ---------\n`version` | String | Version of PostgreSQL to install | '9.6' | no\n`setup_repo` | Boolean | Define if you want to add the PostgreSQL repo | true | no\n`hba_file` | String | Path of pg_hba.conf file | `/pg_hba.conf'` | no\n`ident_file` | String | Path of pg_ident.conf file | `/pg_ident.conf` | no\n`external_pid_file` | String | Path of PID file | `/var/run/postgresql/-main.pid` | no\n`password` | String, nil | Set PostgreSQL user password | 'generate' | no\n`port` | Integer | Set listen port of PostgreSQL service | 5432 | no\n`initdb_locale` | String | Locale to initialise the database with | 'C' | no\n\n#### Examples\n\nTo install PostgreSQL server, set your own postgres password using non-default service port.\n\n```ruby\npostgresql_server_install 'My PostgreSQL Server install' do\n action :install\nend\n\npostgresql_server_install 'Setup my PostgreSQL 9.6 server' do\n password 'MyP4ssw0rd'\n port 5433\n action :create\nend\n```\n\n#### Known issues\n\nOn some platforms (e.g. Ubuntu 18.04), your `initdb_locale` should be set to the\nsame as the template database [GH-555](https://github.com/sous-chefs/postgresql/issues/555).\n\n### postgresql_server_conf\n\nThis resource manages postgresql.conf configuration file.\n\n#### Actions\n\n- `modify` - (default) Manager PostgreSQL configuration file (postgresql.conf)\n\n#### Properties\n\nName | Types | Description | Default | Required?\n---------------------- | ------- | --------------------------------------- | --------------------------------------------------- | ---------\n`version` | String | Version of PostgreSQL to install | '9.6' | no\n`data_directory` | String | Path of PostgreSQL data directory | `` | no\n`hba_file` | String | Path of pg_hba.conf file | `/pg_hba.conf` | no\n`ident_file` | String | Path of pg_ident.conf file | `/pg_ident.conf` | no\n`external_pid_file` | String | Path of PID file | `/var/run/postgresql/-main.pid` | no\n`stats_temp_directory` | String | Path of stats file | `/var/run/postgresql/version>-main.pg_stat_tmp` | no\n`port` | Integer | Set listen port of PostgreSQL service | 5432 | no\n`additional_config` | Hash | Extra configuration for the config file | {} | no\n\n#### Examples\n\nTo setup your PostgreSQL configuration with a specific data directory. If you have installed a specific version of PostgreSQL (different from 9.6), you must specify version in this resource too.\n\n```ruby\npostgresql_server_conf 'My PostgreSQL Config' do\n version '9.5'\n data_directory '/data/postgresql/9.5/main'\n notifies :reload, 'service[postgresql]'\nend\n```\n\n### postgresql_extension\n\nThis resource manages PostgreSQL extensions for a given database.\n\n#### Actions\n\n- `create` - (default) Creates an extension in a given database\n- `drop` - Drops an extension from the database\n\n#### Properties\n\nName | Types | Description | Default | Required?\n------------- | ------ | -------------------------------------------------------------------------------- | ---------------- | ---------\n`database` | String | Name of the database to install the extension into | | yes\n`extension` | String | Name of the extension to install the database | Name of resource | yes\n`version` | String | Version of the extension to install | | no\n`old_version` | String | Older module name for new extension replacement. Appends FROM to extension query | | no\n\n#### Examples\n\nTo install the `adminpack` extension:\n\n```ruby\n# Add the contrib package in Ubuntu/Debian\npackage 'postgresql-contrib-9.6'\n\n# Install adminpack extension\npostgresql_extension 'postgres adminpack' do\n database 'postgres'\n extension 'adminpack'\nend\n```\n\n### postgresql_access\n\nThis resource uses the accumulator pattern to build up the `pg_hba.conf` file via chef resources instead of piling on a mountain of chef attributes to make this cookbook more reusable. It directly mirrors the configuration options of the postgres hba file in the resource and by default notifies the server with a reload to avoid a full restart, causing a potential outage of service. To revoke access, simply remove the resource and the access change won't be computed into the final `pg_hba.conf`\n\n#### Actions\n\n- `grant` - (default) Creates an access line inside of `pg_hba.conf`\n\n#### Properties\n\nName | Types | Description | Default | Required?\n--------------- | ------ | ----------------------------------------------------------------------------------------- | ----------------- | ---------\n`name` | String | Name of the access resource, this is left as a comment inside the `pg_hba` config | Resource name | yes\n`source` | String | The cookbook template filename if you want to use your own custom template | 'pg_hba.conf.erb' | yes\n`cookbook` | String | The cookbook to look in for the template source | 'postgresql' | yes\n`comment` | String | A comment to leave above the entry in `pg_hba` | nil | no\n`access_type` | String | The type of access, e.g. local or host | 'local' | yes\n`access_db` | String | The database to access. Can use 'all' for all databases | 'all' | yes\n`access_user` | String | The user accessing the database. Can use 'all' for any user | 'all' | yes\n`access_addr` | String | The address(es) allowed access. Can be nil if method ident is used since it is local then | nil | no\n`access_method` | String | Authentication method to use | 'ident' | yes\n\n#### Examples\n\nTo grant access to the PostgreSQL user with ident authentication:\n\n```ruby\npostgresql_access 'local_postgres_superuser' do\n comment 'Local postgres superuser access'\n access_type 'local'\n access_db 'all'\n access_user 'postgres'\n access_addr nil\n access_method 'ident'\nend\n```\n\nThis generates the following line in the `pg_hba.conf`:\n\n```\n# Local postgres superuser access\nlocal all postgres ident\n```\n\n**Note**: The template by default generates a local access for Unix domain sockets only to support running the SQL execute resources. In Postgres version 9.1 and higher, the method is 'peer' instead of 'ident' which is identical. It looks like this:\n\n```\n# \"local\" is for Unix domain socket connections only\nlocal all all peer\n```\n\n### postgresql_ident\n\nThis resource generate `pg_ident.conf` configuration file to manage user mapping between system and PostgreSQL users.\n\n#### Actions\n\n- `create` - (default) Creates an mapping line inside of `pg_ident.conf`\n\n#### Properties\n\nName | Types | Description | Default | Required?\n-------------- | ----------- | -------------------------------------------------------------------------- | ------------------- | ---------\n`mapname` | String | Name of the user mapping | Resource name | yes\n`source` | String | The cookbook template filename if you want to use your own custom template | 'pg_ident.conf.erb' | no\n`cookbook` | String | The cookbook to look in for the template source | 'postgresql' | no\n`comment` | String, nil | A comment to leave above the entry in `pg_ident` | nil | no\n`system_user` | String | System user or regexp used for the mapping | None | yes\n`pg_user` | String | Pg user or regexp used for the mapping | None | yes\n\n#### Examples\n\nCreates a `mymapping` mapping that map `john` system user to `user1` PostgreSQL user:\n\n```ruby\npostgresql_ident 'Map john to user1' do\n comment 'John Mapping'\n mapname 'mymapping'\n system_user 'john'\n pg_user 'user1'\nend\n```\n\nThis generates the following line in the `pg_ident.conf`:\n\n```\n# MAPNAME SYSTEM-USERNAME PG-USERNAME\n\n# John Mapping\nmymapping john user1\n```\n\nTo grant access to the foo user with password authentication:\n\n```ruby\npostgresql_access 'local_foo_user' do\n comment 'Foo user access'\n access_type 'host'\n access_db 'all'\n access_user 'foo'\n access_addr '127.0.0.1/32'\n access_method 'md5'\nend\n```\n\nThis generates the following line in the `pg_hba.conf`:\n\n```\n# Local postgres superuser access\nhost all foo 127.0.0.1/32 ident\n```\n\n### postgresql_database\n\nThis resource manages PostgreSQL databases.\n\n#### Actions\n\n- `create` - (default) Creates the given database.\n- `drop` - Drops the given database.\n\n#### Properties\n\nName | Types | Description | Default | Required?\n---------- | ------- | ------------------------------------------------------------------- | ------------------- | ---------\n`database` | String | Name of the database to create | Resource name | yes\n`user` | String | User which run psql command | 'postgres' | no\n`template` | String | Template used to create the new database | 'template1' | no\n`host` | String | Define the host server where the database creation will be executed | Not set (localhost) | no\n`port` | Integer | Define the port of PostgreSQL server | 5432 | no\n`encoding` | String | Define database encoding | 'UTF-8' | no\n`locale` | String | Define database locale | 'en_US.UTF-8' | no\n`owner` | String | Define the owner of the database | Not set | no\n\n#### Examples\n\nTo create database named 'my_app' with owner 'user1':\n\n```ruby\npostgresql_database 'my_app' do\n owner 'user1'\nend\n```\n\n#### Known issues\n\nOn some platforms (e.g. Ubuntu 18.04), your `initdb_locale` should be set to the\nsame as the template database [GH-555](https://github.com/sous-chefs/postgresql/issues/555).\n\n### postgresql_user\n\nThis resource manage PostgreSQL users.\n\n#### Actions\n\n- `create` - (default) Creates the given user with default or given privileges.\n- `update` - Update user privilieges.\n- `drop` - Deletes the given user.\n\n#### Properties\n\nName | Types | Description | Default | Required?\n-------------------- | ------- | ----------------------------------------------- | -------- | ---------\n`create_user` | String | User to create (defaults to the resource name) | | Yes\n`superuser` | Boolean | Define if user needs superuser role | false | no\n`createdb` | Boolean | Define if user needs createdb role | false | no\n`createrole` | Boolean | Define if user needs createrole role | false | no\n`inherit` | Boolean | Define if user inherits the privileges of roles | true | no\n`replication` | Boolean | Define if user needs replication role | false | no\n`login` | Boolean | Define if user can login | true | no\n`password` | String | Set user's password | | no\n`encrypted_password` | String | Set user's password with an hashed password | | no\n`valid_until` | String | Define an account expiration date | | no\n`attributes` | Hash | Additional attributes for :update action | {} | no\n`user` | String | User for command | postgres | no\n`database` | String | Database for command | | no\n`host` | String | Hostname for command | | no\n`port` | Integer | Port number to connect to postgres | 5432 | no\n\n#### Examples\n\nCreate a user `user1` with a password, with `createdb` role and set an expiration date to 2018, Dec 21.\n\n```ruby\npostgresql_user 'user1' do\n password 'UserP4ssword'\n createdb true\n valid_until '2018-12-31'\nend\n```\n\nCreate a user `user1` with a password, with `createdb` role and set an expiration date to 2018, Dec 21.\n\n```ruby\npostgresql_user 'user1' do\n password 'UserP4ssword'\n createdb true\n valid_until '2018-12-31'\nend\n```\n\n## Usage\n\nTo install and configure your PostgreSQL instance you need to create your own cookbook and call needed resources with your own parameters.\n\nMore examples can be found in `test/cookbooks/test/recipes`\n\n## Example Usage\n\n```ruby\n# cookbooks/my_postgresql/recipes/default.rb\n\npostgresql_client_install 'PostgreSQL Client' do\n setup_repo false\n version '10.6'\nend\n\npostgresql_server_install 'PostgreSQL Server' do\n version '10.6'\n setup_repo false\n password 'P0stgresP4ssword'\nend\n\npostgresql_server_conf 'PostgreSQL Config' do\n notifies :reload, 'service[postgresql]'\nend\n```\n\n## Contributing\n\nPlease refer to each project's style guidelines and guidelines for submitting patches and additions. In general, we follow the \"fork-and-pull\" Git workflow.\n\n1. **Fork** the repo on GitHub\n2. **Clone** the project to your own machine\n3. **Commit** changes to your own branch\n4. **Push** your work back up to your fork\n5. Submit a **Pull request** so that we can review your changes\n\nNOTE: Be sure to merge the latest from \"upstream\" before making a pull request!\n\n[Contribution informations for this project](CONTRIBUTING.md)\n\n## License\n\nCopyright 2010-2017, Chef Software, Inc.\n\n```text\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","maintainer":"Sous Chefs","maintainer_email":"help@sous-chefs.org","license":"Apache-2.0","platforms":{"ubuntu":">= 0.0.0","debian":">= 0.0.0","fedora":">= 0.0.0","amazon":">= 0.0.0","redhat":">= 0.0.0","centos":">= 0.0.0","scientific":">= 0.0.0","oracle":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/sous-chefs/postgresql","issues_url":"https://github.com/sous-chefs/postgresql/issues","chef_version":[[">= 13.8"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/postgresql/metadata.rb b/cookbooks/postgresql/metadata.rb new file mode 100644 index 0000000..9fb54ac --- /dev/null +++ b/cookbooks/postgresql/metadata.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true +name 'postgresql' +maintainer 'Sous Chefs' +maintainer_email 'help@sous-chefs.org' +license 'Apache-2.0' +description 'Installs and configures postgresql for clients or servers' +long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) +version '7.1.4' +source_url 'https://github.com/sous-chefs/postgresql' +issues_url 'https://github.com/sous-chefs/postgresql/issues' +chef_version '>= 13.8' + +%w(ubuntu debian fedora amazon redhat centos scientific oracle).each do |os| + supports os +end diff --git a/cookbooks/postgresql/resources/access.rb b/cookbooks/postgresql/resources/access.rb new file mode 100644 index 0000000..56d69cc --- /dev/null +++ b/cookbooks/postgresql/resources/access.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true +# +# Cookbook:: postgresql +# Resource:: access +# +# 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. +# + +property :access_type, String, required: true, default: 'local' +property :access_db, String, required: true, default: 'all' +property :access_user, String, required: true, default: 'postgres' +property :access_method, String, required: true, default: 'ident' +property :cookbook, String, default: 'postgresql' +property :source, String, default: 'pg_hba.conf.erb' +property :access_addr, String +property :comment, String + +action :grant do + config_resource = new_resource + with_run_context :root do # ~FC037 + edit_resource(:template, "#{conf_dir}/pg_hba.conf") do |new_resource| + source new_resource.source + cookbook new_resource.cookbook + owner 'postgres' + group 'postgres' + mode '0600' + variables[:pg_hba] ||= {} + variables[:pg_hba][new_resource.name] = { + comment: new_resource.comment, + type: new_resource.access_type, + db: new_resource.access_db, + user: new_resource.access_user, + addr: new_resource.access_addr, + method: new_resource.access_method, + } + action :nothing + delayed_action :create + notifies :trigger, config_resource, :immediately + end + end +end + +action :trigger do + new_resource.updated_by_last_action(true) # ~FC085 +end + +action_class do + include PostgresqlCookbook::Helpers +end diff --git a/cookbooks/postgresql/resources/client_install.rb b/cookbooks/postgresql/resources/client_install.rb new file mode 100644 index 0000000..2698d00 --- /dev/null +++ b/cookbooks/postgresql/resources/client_install.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true +# +# Cookbook:: postgresql +# Resource:: client_install +# +# 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. +# + +property :version, String, default: '9.6' +property :setup_repo, [true, false], default: true + +action :install do + postgresql_repository 'Add downloads.postgresql.org repository' do + version new_resource.version + only_if { new_resource.setup_repo } + end + + case node['platform_family'] + when 'debian' + package "postgresql-client-#{new_resource.version}" + when 'rhel', 'fedora', 'amazon' + ver = new_resource.version.delete('.') + package "postgresql#{ver}" + end +end diff --git a/cookbooks/postgresql/resources/database.rb b/cookbooks/postgresql/resources/database.rb new file mode 100644 index 0000000..be2a813 --- /dev/null +++ b/cookbooks/postgresql/resources/database.rb @@ -0,0 +1,67 @@ +# +# Cookbook:: postgresql +# Resource:: database +# +# 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. +# + +property :template, String, default: 'template1' +property :encoding, String, default: 'UTF-8' +property :locale, String, default: 'en_US.UTF-8' +property :owner, String + +# Connection prefernces +property :user, String, default: 'postgres' +property :database, String, name_property: true +property :host, [String, nil], default: nil +property :port, Integer, default: 5432 + +action :create do + createdb = 'createdb' + createdb << " -E #{new_resource.encoding}" if new_resource.encoding + createdb << " -l #{new_resource.locale}" if new_resource.locale + createdb << " -T #{new_resource.template}" unless new_resource.template.empty? + createdb << " -O #{new_resource.owner}" if new_resource.owner + createdb << " -U #{new_resource.user}" if new_resource.user + createdb << " -h #{new_resource.host}" if new_resource.host + createdb << " -p #{new_resource.port}" if new_resource.port + createdb << " #{new_resource.database}" + + bash "Create Database #{new_resource.database}" do + code createdb + user new_resource.user + not_if { follower? } + not_if { database_exists?(new_resource) } + end +end + +action :drop do + converge_by "Drop PostgreSQL Database #{new_resource.database}" do + dropdb = 'dropdb' + dropdb << " -U #{new_resource.user}" if new_resource.user + dropdb << " --host #{new_resource.host}" if new_resource.host + dropdb << " --port #{new_resource.port}" if new_resource.port + dropdb << " #{new_resource.database}" + + bash "drop postgresql database #{new_resource.database})" do + user 'postgres' + code dropdb + not_if { follower? } + only_if { database_exists?(new_resource) } + end + end +end + +action_class do + include PostgresqlCookbook::Helpers +end diff --git a/cookbooks/postgresql/resources/extension.rb b/cookbooks/postgresql/resources/extension.rb new file mode 100644 index 0000000..fb104dd --- /dev/null +++ b/cookbooks/postgresql/resources/extension.rb @@ -0,0 +1,49 @@ +# +# Cookbook:: postgresql +# Resource:: extension +# +# 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. +# + +property :extension, String, name_property: true +property :old_version, String +property :version, String + +# Connection prefernces +property :user, String, default: 'postgres' +property :database, String, required: true +property :host, [String, nil] +property :port, Integer, default: 5432 + +action :create do + bash "CREATE EXTENSION #{new_resource.name}" do + code create_extension_sql(new_resource) + user 'postgres' + action :run + not_if { follower? || extension_installed?(new_resource) } + end +end + +action :drop do + bash "DROP EXTENSION #{new_resource.name}" do + code psql_command_string(new_resource, "DROP EXTENSION IF EXISTS \"#{new_resource.extension}\"") + user 'postgres' + action :run + not_if { follower? } + only_if { extension_installed?(new_resource) } + end +end + +action_class do + include PostgresqlCookbook::Helpers +end diff --git a/cookbooks/postgresql/resources/ident.rb b/cookbooks/postgresql/resources/ident.rb new file mode 100644 index 0000000..ba677f0 --- /dev/null +++ b/cookbooks/postgresql/resources/ident.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true +# +# Cookbook:: postgresql +# Resource:: access +# +# 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. +# + +property :mapname, String, required: true +property :source, String, default: 'pg_ident.conf.erb' +property :cookbook, String, default: 'postgresql' +property :system_user, String, required: true +property :pg_user, String, required: true +property :comment, [String, nil], default: nil + +action :create do + ident_resource = new_resource + with_run_context :root do # ~FC037 + edit_resource(:template, "#{conf_dir}/pg_ident.conf") do |new_resource| + source new_resource.source + cookbook new_resource.cookbook + owner 'postgres' + group 'postgres' + mode '0640' + variables[:pg_ident] ||= {} + variables[:pg_ident][new_resource.name] = { + comment: new_resource.comment, + mapname: new_resource.mapname, + system_user: new_resource.system_user, + pg_user: new_resource.pg_user, + } + action :nothing + delayed_action :create + notifies :trigger, ident_resource, :immediately + end + end +end + +action :trigger do + new_resource.updated_by_last_action(true) # ~FC085 +end + +action_class do + include PostgresqlCookbook::Helpers +end diff --git a/cookbooks/postgresql/resources/repository.rb b/cookbooks/postgresql/resources/repository.rb new file mode 100644 index 0000000..7040c6b --- /dev/null +++ b/cookbooks/postgresql/resources/repository.rb @@ -0,0 +1,90 @@ +# frozen_string_literal: true +# +# Cookbook:: postgresql +# Resource:: repository +# +# 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. +# + +property :version, String, default: '9.6' +property :enable_pgdg, [true, false], default: true +property :enable_pgdg_source, [true, false], default: false +property :enable_pgdg_updates_testing, [true, false], default: false +property :enable_pgdg_source_updates_testing, [true, false], default: false +property :yum_gpg_key_uri, String, default: 'https://download.postgresql.org/pub/repos/yum/RPM-GPG-KEY-PGDG' +property :apt_gpg_key_uri, String, default: 'https://download.postgresql.org/pub/repos/apt/ACCC4CF8.asc' + +action :add do + case node['platform_family'] + + when 'rhel', 'fedora', 'amazon' + remote_file "/etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG-#{new_resource.version}" do + source new_resource.yum_gpg_key_uri + end + + yum_repository "PostgreSQL #{new_resource.version}" do # ~FC005 + repositoryid "pgdg#{new_resource.version}" + description "PostgreSQL.org #{new_resource.version}" + baseurl yum_repo_url('https://download.postgresql.org/pub/repos/yum') + enabled new_resource.enable_pgdg + gpgcheck true + gpgkey "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG-#{new_resource.version}" + end + + yum_repository "PostgreSQL #{new_resource.version} - source " do + repositoryid "pgdg#{new_resource.version}-source" + description "PostgreSQL.org #{new_resource.version} Source" + baseurl yum_repo_url('https://download.postgresql.org/pub/repos/yum/srpms') + enabled new_resource.enable_pgdg_source + gpgcheck true + gpgkey "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG-#{new_resource.version}" + end + + yum_repository "PostgreSQL #{new_resource.version} - updates testing" do + repositoryid "pgdg#{new_resource.version}-updates-testing" + description "PostgreSQL.org #{new_resource.version} Updates Testing" + baseurl yum_repo_url('https://download.postgresql.org/pub/repos/yum/testing') + enabled new_resource.enable_pgdg_updates_testing + gpgcheck true + gpgkey "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG-#{new_resource.version}" + end + + yum_repository "PostgreSQL #{new_resource.version} - source - updates testing" do + repositoryid "pgdg#{new_resource.version}-source-updates-testing" + description "PostgreSQL.org #{new_resource.version} Source Updates Testing" + baseurl yum_repo_url('https://download.postgresql.org/pub/repos/yum/srpms/testing') + enabled new_resource.enable_pgdg_source_updates_testing + gpgcheck true + gpgkey "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG-#{new_resource.version}" + end + + when 'debian' + apt_update + + package 'apt-transport-https' + + apt_repository 'postgresql_org_repository' do + uri 'https://download.postgresql.org/pub/repos/apt/' + components ['main', new_resource.version.to_s] + distribution "#{node['lsb']['codename']}-pgdg" + key new_resource.apt_gpg_key_uri + cache_rebuild true + end + else + raise "The platform_family '#{node['platform_family']}' or platform '#{node['platform']}' is not supported by the postgresql_repository resource. If you believe this platform can/should be supported by this resource please file and issue or open a pull request at https://github.com/sous-chefs/postgresql" + end +end + +action_class do + include PostgresqlCookbook::Helpers +end diff --git a/cookbooks/postgresql/resources/server_conf.rb b/cookbooks/postgresql/resources/server_conf.rb new file mode 100644 index 0000000..3c44c22 --- /dev/null +++ b/cookbooks/postgresql/resources/server_conf.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true +# +# Cookbook:: postgresql +# Resource:: server_conf +# +# 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. +# + +include PostgresqlCookbook::Helpers + +property :version, String, default: '9.6' +property :data_directory, String, default: lazy { data_dir } +property :hba_file, String, default: lazy { "#{conf_dir}/pg_hba.conf" } +property :ident_file, String, default: lazy { "#{conf_dir}/pg_ident.conf" } +property :external_pid_file, String, default: lazy { "/var/run/postgresql/#{version}-main.pid" } +property :stats_temp_directory, String, default: lazy { "/var/run/postgresql/#{version}-main.pg_stat_tmp" } +property :port, Integer, default: 5432 +property :additional_config, Hash, default: {} +property :cookbook, String, default: 'postgresql' + +action :modify do + template "#{conf_dir}/postgresql.conf" do + cookbook new_resource.cookbook + source 'postgresql.conf.erb' + owner 'postgres' + group 'postgres' + mode '0644' + variables( + data_dir: new_resource.data_directory, + hba_file: new_resource.hba_file, + ident_file: new_resource.ident_file, + external_pid_file: new_resource.external_pid_file, + stats_temp_directory: new_resource.stats_temp_directory, + port: new_resource.port, + additional_config: new_resource.additional_config + ) + end +end + +action_class do + include PostgresqlCookbook::Helpers +end diff --git a/cookbooks/postgresql/resources/server_install.rb b/cookbooks/postgresql/resources/server_install.rb new file mode 100644 index 0000000..3c66c67 --- /dev/null +++ b/cookbooks/postgresql/resources/server_install.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true +# +# Cookbook:: postgresql +# Resource:: server_install +# +# 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. +# + +include PostgresqlCookbook::Helpers + +property :version, String, default: '9.6' +property :setup_repo, [true, false], default: true +property :hba_file, String, default: lazy { "#{conf_dir}/main/pg_hba.conf" } +property :ident_file, String, default: lazy { "#{conf_dir}/main/pg_ident.conf" } +property :external_pid_file, String, default: lazy { "/var/run/postgresql/#{version}-main.pid" } +property :password, [String, nil], default: 'generate' # Set to nil if we do not want to set a password +property :port, Integer, default: 5432 +property :initdb_locale, String + +# Connection preferences +property :user, String, default: 'postgres' +property :database, String +property :host, [String, nil] + +action :install do + node.run_state['postgresql'] ||= {} + node.run_state['postgresql']['version'] = new_resource.version + + postgresql_client_install 'Install PostgreSQL Client' do + version new_resource.version + setup_repo new_resource.setup_repo + end + + package server_pkg_name +end + +action :create do + execute 'init_db' do + command rhel_init_db_command(new_resource) + user new_resource.user + not_if { initialized? } + only_if { platform_family?('rhel', 'fedora', 'amazon') } + end + + # We use to use find_resource here. + # But that required the user to do the same in their recipe. + # This also seemed to never trigger notifications, therefore requiring a log resource + # to notify the enable/start on the service, which always fires (Check v7.0 tag for more) + service 'postgresql' do + service_name platform_service_name + supports restart: true, status: true, reload: true + action [:enable, :start] + end + + # Generate a random password or set it as per new_resource.password. + bash 'generate-postgres-password' do + user 'postgres' + code alter_role_sql(new_resource) + not_if { user_has_password?(new_resource) } + not_if { new_resource.password.nil? } + end +end + +action_class do + include PostgresqlCookbook::Helpers +end diff --git a/cookbooks/postgresql/resources/user.rb b/cookbooks/postgresql/resources/user.rb new file mode 100644 index 0000000..05da73b --- /dev/null +++ b/cookbooks/postgresql/resources/user.rb @@ -0,0 +1,87 @@ +# +# Cookbook:: postgresql +# Resource:: user +# +# 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. +# + +property :create_user, String, name_property: true +property :superuser, [true, false], default: false +property :createdb, [true, false], default: false +property :createrole, [true, false], default: false +property :inherit, [true, false], default: true +property :replication, [true, false], default: false +property :login, [true, false], default: true +property :password, String +property :encrypted_password, String +property :valid_until, String +property :attributes, Hash, default: {} + +# Connection prefernces +property :user, String, default: 'postgres' +property :database, String +property :host, String +property :port, Integer, default: 5432 + +action :create do + Chef::Log.warn('You cannot use "attributes" property with create action.') unless new_resource.attributes.empty? + + execute "create postgresql user #{new_resource.create_user}" do # ~FC009 + user 'postgres' + command create_user_sql(new_resource) + sensitive new_resource.sensitive + not_if { follower? || user_exists?(new_resource) } + end +end + +action :update do + if new_resource.attributes.empty? + execute "update postgresql user #{new_resource.create_user}" do + user 'postgres' + command update_user_sql(new_resource) + sensitive true + not_if { follower? } + only_if { user_exists?(new_resource) } + end + else + new_resource.attributes.each do |attr, value| + v = if value.is_a?(TrueClass) || value.is_a?(FalseClass) + value.to_s + else + "'#{value}'" + end + + execute "Update postgresql user #{new_resource.create_user} to set #{attr}" do + user 'postgres' + command update_user_with_attributes_sql(new_resource, v) + sensitive true + not_if { follower? } + only_if { user_exists?(new_resource) } + end + end + end +end + +action :drop do + execute "drop postgresql user #{new_resource.create_user}" do + user 'postgres' + command drop_user_sql(new_resource) + sensitive true + not_if { follower? } + only_if { user_exists?(new_resource) } + end +end + +action_class do + include PostgresqlCookbook::Helpers +end diff --git a/cookbooks/postgresql/templates/pg_hba.conf.erb b/cookbooks/postgresql/templates/pg_hba.conf.erb new file mode 100644 index 0000000..9eab8a9 --- /dev/null +++ b/cookbooks/postgresql/templates/pg_hba.conf.erb @@ -0,0 +1,33 @@ +# This file was automatically generated and dropped off by Chef! + +# PostgreSQL Client Authentication Configuration File +# =================================================== +# +# Refer to the "Client Authentication" section in the PostgreSQL +# documentation for a complete description of this file. + +local all postgres peer + +# TYPE DATABASE USER ADDRESS METHOD + +# "local" is for Unix domain socket connections only +local all all peer +# IPv4 local connections: +host all all 127.0.0.1/32 md5 +# IPv6 local connections: +host all all ::1/128 md5 + +########### +# From the postgresql_access resources +########### +<% @pg_hba.each do |k,v| -%> +# <%= k %> +<% if v[:comment] -%> +# <%= v[:comment] %> +<% end -%> +<% if v[:addr] %> +<%= v[:type].ljust(7) %> <%= v[:db].ljust(15) %> <%= v[:user].ljust(15) %> <%= v[:addr].ljust(23) %> <%= v[:method] %> +<% else %> +<%= v[:type].ljust(7) %> <%= v[:db].ljust(15) %> <%= v[:user].ljust(15) %> <%= v[:method] %> +<% end %> +<% end %> diff --git a/cookbooks/postgresql/templates/pg_ident.conf.erb b/cookbooks/postgresql/templates/pg_ident.conf.erb new file mode 100644 index 0000000..f3ba499 --- /dev/null +++ b/cookbooks/postgresql/templates/pg_ident.conf.erb @@ -0,0 +1,49 @@ +# PostgreSQL User Name Maps +# ========================= +# +# Refer to the PostgreSQL documentation, chapter "Client +# Authentication" for a complete description. A short synopsis +# follows. +# +# This file controls PostgreSQL user name mapping. It maps external +# user names to their corresponding PostgreSQL user names. Records +# are of the form: +# +# MAPNAME SYSTEM-USERNAME PG-USERNAME +# +# (The uppercase quantities must be replaced by actual values.) +# +# MAPNAME is the (otherwise freely chosen) map name that was used in +# pg_hba.conf. SYSTEM-USERNAME is the detected user name of the +# client. PG-USERNAME is the requested PostgreSQL user name. The +# existence of a record specifies that SYSTEM-USERNAME may connect as +# PG-USERNAME. +# +# If SYSTEM-USERNAME starts with a slash (/), it will be treated as a +# regular expression. Optionally this can contain a capture (a +# parenthesized subexpression). The substring matching the capture +# will be substituted for \1 (backslash-one) if present in +# PG-USERNAME. +# +# Multiple maps may be specified in this file and used by pg_hba.conf. +# +# No map names are defined in the default configuration. If all +# system user names and PostgreSQL user names are the same, you don't +# need anything in this file. +# +# This file is read on server startup and when the postmaster receives +# a SIGHUP signal. If you edit the file on a running system, you have +# to SIGHUP the postmaster for the changes to take effect. You can +# use "pg_ctl reload" to do that. + +# Put your actual configuration here +# ---------------------------------- + +# MAPNAME SYSTEM-USERNAME PG-USERNAME +<% @pg_ident.each do |k,v| -%> + <% if v[:comment] -%> + +# <%= v[:comment] %> + <% end -%> +<%= v[:mapname].ljust(15) %> <%= v[:system_user].ljust(23) %> <%= v[:pg_user].ljust(15) %> +<% end %> diff --git a/cookbooks/postgresql/templates/pgsql.sysconfig.erb b/cookbooks/postgresql/templates/pgsql.sysconfig.erb new file mode 100644 index 0000000..2740356 --- /dev/null +++ b/cookbooks/postgresql/templates/pgsql.sysconfig.erb @@ -0,0 +1,2 @@ +PGDATA=<%= @postgresql_dir %> +PGPORT=<%= @port %> diff --git a/cookbooks/postgresql/templates/postgresql.conf.erb b/cookbooks/postgresql/templates/postgresql.conf.erb new file mode 100644 index 0000000..7656770 --- /dev/null +++ b/cookbooks/postgresql/templates/postgresql.conf.erb @@ -0,0 +1,26 @@ +# PostgreSQL configuration file +# This file was automatically generated and dropped off by chef! +# Please refer to the PostgreSQL documentation for details on +# configuration settings. + +data_directory = '<%= @data_dir %>' +hba_file = '<%= @hba_file %>' +ident_file = '<%= @ident_file %>' +external_pid_file = '<%= @external_pid_file %>' +stats_temp_directory = '<%= @stats_temp_directory %>' +port = <%= @port %> +<% @additional_config.sort.each do |key, value| %> +<% next if value.nil? -%> +<%= key %> = <%= + case value + when String + "'#{value}'" + when TrueClass + 'on' + when FalseClass + 'off' + else + value + end +%> +<% end %> diff --git a/cookbooks/postgresql/templates/postgresql.service.erb b/cookbooks/postgresql/templates/postgresql.service.erb new file mode 100644 index 0000000..688e7d5 --- /dev/null +++ b/cookbooks/postgresql/templates/postgresql.service.erb @@ -0,0 +1,6 @@ +[Service] +.include /usr/lib/systemd/system/<%= @svc_name %>.service + +Environment= +Environment=PGPORT=<%= @port %> +Environment=PGDATA=<%= @data_dir %> diff --git a/cookbooks/redis/.gitignore b/cookbooks/redis/.gitignore new file mode 100644 index 0000000..bf6420b --- /dev/null +++ b/cookbooks/redis/.gitignore @@ -0,0 +1,9 @@ +*.tgz +*.tar.gz +vendor/bundle +.bundle +.DS_Store +build/* +tmp/ +*.lock +.kitchen/* diff --git a/cookbooks/redis/.kitchen.yml b/cookbooks/redis/.kitchen.yml new file mode 100644 index 0000000..c69ece7 --- /dev/null +++ b/cookbooks/redis/.kitchen.yml @@ -0,0 +1,20 @@ +driver: + require_chef_omnibus: <%= ENV.fetch("CHEF_VERSION", "latest") %> + ssh_key: <%= File.expand_path("./test/support/keys/vagrant") %> + name: vagrant + +provisioner: + name: chef_solo + +platforms: + - name: debian-6.0.8 + - name: debian-7.2.0 + - name: ubuntu-12.04 + - name: ubuntu-14.04 + +suites: + - name: default + run_list: + - recipe[redis::server] + - recipe[redis::client] + # - recipe[minitest-handler] diff --git a/cookbooks/redis/.rubocop.yml b/cookbooks/redis/.rubocop.yml new file mode 100644 index 0000000..9e26e49 --- /dev/null +++ b/cookbooks/redis/.rubocop.yml @@ -0,0 +1,18 @@ +LineLength: + Max: 80 + Exclude: + - "**/attributes/*.rb" + - "**/metadata.rb" + +StringLiterals: + EnforcedStyle: double_quotes + +PercentLiteralDelimiters: + PreferredDelimiters: + "%w": "[]" # Arrays use brackets + +SingleSpaceBeforeFirstArg: + Enabled: false # too strict about metadata and certain formatting + +inherit_from: test/support/rubocop/enabled.yml +inherit_from: test/support/rubocop/disabled.yml diff --git a/cookbooks/redis/.ruby-gemset b/cookbooks/redis/.ruby-gemset new file mode 100644 index 0000000..515fa5d --- /dev/null +++ b/cookbooks/redis/.ruby-gemset @@ -0,0 +1 @@ +chef-redis diff --git a/cookbooks/redis/.ruby-version b/cookbooks/redis/.ruby-version new file mode 100644 index 0000000..cd57a8b --- /dev/null +++ b/cookbooks/redis/.ruby-version @@ -0,0 +1 @@ +2.1.5 diff --git a/cookbooks/redis/.travis.yml b/cookbooks/redis/.travis.yml new file mode 100644 index 0000000..852f917 --- /dev/null +++ b/cookbooks/redis/.travis.yml @@ -0,0 +1,19 @@ +language: ruby +bundler_args: --jobs 3 --without integration +rvm: +- 1.9.3 +- 2.0.0 +- 2.1.5 +before_script: +- "gem install bundler-audit --no-rdoc --no-ri && bundle-audit update" +script: +- bundle-audit +- bundle exec rake rubocop +- bundle exec rake foodcritic +- bundle exec rake chefspec +- bundle exec rake kitchen:all +- bundle exec license_finder --quiet +env: + matrix: + - CHEF_VERSION: "10.30" + - CHEF_VERSION: "11.16" diff --git a/cookbooks/redis/Berksfile b/cookbooks/redis/Berksfile new file mode 100644 index 0000000..06f8e4f --- /dev/null +++ b/cookbooks/redis/Berksfile @@ -0,0 +1,7 @@ +source "http://api.berkshelf.com" + +metadata + +group :integration do + cookbook "minitest-handler" +end diff --git a/cookbooks/redis/Gemfile b/cookbooks/redis/Gemfile new file mode 100644 index 0000000..88b54de --- /dev/null +++ b/cookbooks/redis/Gemfile @@ -0,0 +1,20 @@ +source "https://rubygems.org" + +chef_version = ENV.fetch("CHEF_VERSION", "11.16") + +gem "chef", "~> #{chef_version}" +gem "chefspec", "~> 4.1.1" if chef_version =~ /^11/ + +gem "berkshelf", "~> 3.2.1" +gem "foodcritic", "~> 4.0.0" +gem "license_finder", "~> 1.2.0" +gem "rake" +gem "rubocop", "~> 0.27.1" +gem "serverspec", "~> 2.3.1" + +group :integration do + gem "busser-serverspec", "~> 0.5.3" + gem "guard-rspec", "~> 4.3.1" + gem "kitchen-vagrant", "~> 0.15.0" + gem "test-kitchen", "~> 1.2.1" +end diff --git a/cookbooks/redis/Guardfile b/cookbooks/redis/Guardfile new file mode 100644 index 0000000..e40e264 --- /dev/null +++ b/cookbooks/redis/Guardfile @@ -0,0 +1,5 @@ +guard :rspec, cmd: "rspec --color", all_on_start: false do + watch(/^spec\/(.+)_spec\.rb$/) + watch(/^recipes\/(.+)\.rb$/) { |m| "spec/#{m[1]}_spec.rb" } + watch("spec/spec_helper.rb") { "spec" } +end diff --git a/cookbooks/redis/LICENSE.txt b/cookbooks/redis/LICENSE.txt new file mode 100644 index 0000000..20dac68 --- /dev/null +++ b/cookbooks/redis/LICENSE.txt @@ -0,0 +1,20 @@ +The MIT License (MIT) +Copyright © 2012-2014 Phil Cohen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the “Software”), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/cookbooks/redis/README.md b/cookbooks/redis/README.md new file mode 100644 index 0000000..30954ef --- /dev/null +++ b/cookbooks/redis/README.md @@ -0,0 +1,155 @@ +# chef-redis [![Build Status](https://travis-ci.org/phlipper/chef-redis.svg?branch=master)](https://travis-ci.org/phlipper/chef-redis) + +## Description + +This cookbook installs [Redis](http://redis.io) from Chris Lea's [ppa archive](https://launchpad.net/~chris-lea/+archive/redis-server). + +Redis is an open source, advanced key-value store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets and sorted sets. + + +## Requirements + +### Supported Platforms + +The following platforms are supported by this cookbook, meaning that the recipes run on these platforms without error: + +* Ubuntu 12.04+ +* Debian 6+ + +### Cookbooks + +* [apt](http://community.opscode.com/cookbooks/apt) +* [minitest-handler](http://community.opscode.com/cookbooks/minitest-handler) _(suggested, not required)_ + + +## Recipes + +* `redis` - The default recipe. Setup apt with ppa details. +* `redis::server` - Install the Redis server. +* `redis::client` - Install the Redis client. + +# Usage + +This cookbook installs the Redis components if not present, and pulls updates if they are installed on the system. + + +## Attributes + +```ruby +case node["platform"] +when "debian" + default["redis"]["apt_distribution"] = node["lsb"]["codename"] + default["redis"]["apt_repository"] = "dotdeb" + default["redis"]["apt_uri"] = "http://packages.dotdeb.org" + default["redis"]["apt_components"] = ["all"] + default["redis"]["apt_key"] = "http://www.dotdeb.org/dotdeb.gpg" +when "ubuntu" + default["redis"]["apt_distribution"] = node["lsb"]["codename"] + default["redis"]["apt_repository"] = "chris-lea-redis-server" + default["redis"]["apt_uri"] = "http://ppa.launchpad.net/chris-lea/redis-server/ubuntu" + default["redis"]["apt_components"] = ["main"] + default["redis"]["apt_keyserver"] = "keyserver.ubuntu.com" + default["redis"]["apt_key"] = "C7917B12" +end +default["redis"]["pidfile"] = "/var/run/redis/redis-server.pid" +default["redis"]["daemonize"] = "yes" +default["redis"]["port"] = 6379 +default["redis"]["bind"] = "127.0.0.1" +default["redis"]["unixsocket"] = "/var/run/redis/redis.sock" +default["redis"]["unixsocketperm"] = 755 +default["redis"]["timeout"] = 300 +default["redis"]["loglevel"] = "notice" +default["redis"]["logfile"] = "/var/log/redis/redis-server.log" +default["redis"]["syslog_enabled"] = "no" +default["redis"]["syslog_ident"] = "redis" +default["redis"]["syslog_facility"] = "local0" +default["redis"]["databases"] = 16 +default["redis"]["snapshots"] = { + 900 => 1, + 300 => 10, + 60 => 10000 +} +default["redis"]["stop_writes_on_bgsave_error"] = "yes" +default["redis"]["rdbcompression"] = "yes" +default["redis"]["rdbchecksum"] = "yes" +default["redis"]["dbfilename"] = "dump.rdb" +default["redis"]["dir"] = "/var/lib/redis" +default["redis"]["slaveof"] = "" +default["redis"]["masterauth"] = "" +default["redis"]["slave_serve_stale_data"] = "yes" +default["redis"]["slave_read_only"] = "yes" +default["redis"]["repl_ping_slave_period"] = 10 +default["redis"]["repl_timeout"] = 60 +default["redis"]["slave_priority"] = 100 +default["redis"]["requirepass"] = "" +default["redis"]["rename_commands"] = [] +default["redis"]["maxclients"] = 128 +default["redis"]["maxmemory"] = "64mb" +default["redis"]["maxmemory_policy"] = "volatile-lru" +default["redis"]["maxmemory_samples"] = 3 +default["redis"]["appendonly"] = "no" +default["redis"]["appendfilename"] = "appendonly.aof" +default["redis"]["appendfsync"] = "everysec" +default["redis"]["no_appendfsync_on_rewrite"] = "no" +default["redis"]["auto_aof_rewrite_percentage"] = 100 +default["redis"]["auto_aof_rewrite_min_size"] = "64mb" +default["redis"]["lua_time_limit"] = 5000 +default["redis"]["slowlog_log_slower_than"] = 10000 +default["redis"]["slowlog_max_len"] = 1024 +default["redis"]["hash_max_ziplist_entries"] = 512 +default["redis"]["hash_max_ziplist_value"] = 64 +default["redis"]["list_max_ziplist_entries"] = 512 +default["redis"]["list_max_ziplist_value"] = 64 +default["redis"]["set_max_intset_entries"] = 512 +default["redis"]["zset_max_ziplist_entries"] = 128 +default["redis"]["zset_max_ziplist_value"] = 64 +default["redis"]["activerehashing"] = "yes" +default["redis"]["client_output_buffer_limit"] = { + "normal" => "0 0 0", + "slave" => "256mb 64mb 60", + "pubsub" => "32mb 8mb 60" +} +default["redis"]["include_config_files"] = [] +default["redis"]["ulimit"] = "" +default["redis"]["auto_upgrade"] = false +``` + + +## Basic Settings + +* `node["redis"]["ulimit"]` - Sets the maximum number of file descriptors for the Redis process. If this is unset or empty, the limit is the system default. The default may not be high enough to handle a large number of concurrent connections. See [Redis Clients Handling](http://redis.io/topics/clients). + + +## Contributors + +Many thanks go to the following [contributors](https://github.com/phlipper/chef-redis/graphs/contributors) who have helped to make this cookbook even better: + +* **[@smoil](https://github.com/smoil)** + * `redis.conf` updates for Redis 2.6 +* **[@svend](https://github.com/svend)** + * add attribute to set ulimit +* **[@maciej](https://github.com/maciej)** + * ensure `node["redis"]["dir"]` exists +* **[@dwradcliffe](https://github.com/dwradcliffe)** + * allow bind to all interfaces +* **[@duggan](https://github.com/duggan)** + * allow customizable apt sources + +## Contributing + +This cookbook could have way more personality... Help make it so! + +1. Fork it +2. Create your feature branch (`git checkout -b my-new-feature`) +3. Commit your changes (`git commit -am 'Added some feature'`) +4. Push to the branch (`git push origin my-new-feature`) +5. Create new Pull Request + + +## License + +**chef-redis** + +* Freely distributable and licensed under the [MIT license](http://phlipper.mit-license.org/2012-2014/license.html). +* Copyright (c) 2012-2014 Phil Cohen (github@phlippers.net) [![endorse](http://api.coderwall.com/phlipper/endorsecount.png)](http://coderwall.com/phlipper) [![Gittip](http://img.shields.io/gittip/phlipper.png)](https://www.gittip.com/phlipper/) +* http://phlippers.net/ diff --git a/cookbooks/redis/Rakefile b/cookbooks/redis/Rakefile new file mode 100644 index 0000000..52903cd --- /dev/null +++ b/cookbooks/redis/Rakefile @@ -0,0 +1,31 @@ +task default: "test" + +desc "Run all tests except `kitchen`" +task test: [:rubocop, :foodcritic, :chefspec] + +desc "Run all tests" +task all_tests: [:rubocop, :foodcritic, :chefspec, "kitchen:all"] + +# rubocop style checker +require "rubocop/rake_task" +RuboCop::RakeTask.new + +# foodcritic chef lint +require "foodcritic" +FoodCritic::Rake::LintTask.new do |t| + t.options = { fail_tags: ["any"] } +end + +# chefspec unit tests +require "rspec/core/rake_task" +RSpec::Core::RakeTask.new(:chefspec) do |t| + t.rspec_opts = "--color --format progress" +end + +# test-kitchen integration tests +begin + require "kitchen/rake_tasks" + Kitchen::RakeTasks.new +rescue LoadError + task("kitchen:all") { puts "Unable to run `test-kitchen`" } +end diff --git a/cookbooks/redis/attributes/default.rb b/cookbooks/redis/attributes/default.rb new file mode 100644 index 0000000..692fe4e --- /dev/null +++ b/cookbooks/redis/attributes/default.rb @@ -0,0 +1,77 @@ +case node["platform"] +when "debian" + default["redis"]["apt_distribution"] = node["lsb"]["codename"] + default["redis"]["apt_repository"] = "dotdeb" + default["redis"]["apt_uri"] = "http://packages.dotdeb.org" + default["redis"]["apt_components"] = ["all"] + default["redis"]["apt_key"] = "http://www.dotdeb.org/dotdeb.gpg" +when "ubuntu" + default["redis"]["apt_distribution"] = node["lsb"]["codename"] + default["redis"]["apt_repository"] = "chris-lea-redis-server" + default["redis"]["apt_uri"] = "http://ppa.launchpad.net/chris-lea/redis-server/ubuntu" + default["redis"]["apt_components"] = ["main"] + default["redis"]["apt_keyserver"] = "keyserver.ubuntu.com" + default["redis"]["apt_key"] = "C7917B12" +end + +default["redis"]["pidfile"] = "/var/run/redis/redis-server.pid" +default["redis"]["daemonize"] = "yes" +default["redis"]["port"] = 6379 +default["redis"]["bind"] = "127.0.0.1" +default["redis"]["unixsocket"] = "/var/run/redis/redis.sock" +default["redis"]["unixsocketperm"] = 755 +default["redis"]["timeout"] = 300 +default["redis"]["loglevel"] = "notice" +default["redis"]["logfile"] = "/var/log/redis/redis-server.log" +default["redis"]["syslog_enabled"] = "no" +default["redis"]["syslog_ident"] = "redis" +default["redis"]["syslog_facility"] = "local0" +default["redis"]["databases"] = 16 +default["redis"]["snapshots"] = { + 900 => 1, + 300 => 10, + 60 => 10_000 +} +default["redis"]["stop_writes_on_bgsave_error"] = "yes" +default["redis"]["rdbcompression"] = "yes" +default["redis"]["rdbchecksum"] = "yes" +default["redis"]["dbfilename"] = "dump.rdb" +default["redis"]["dir"] = "/var/lib/redis" +default["redis"]["slaveof"] = "" +default["redis"]["masterauth"] = "" +default["redis"]["slave_serve_stale_data"] = "yes" +default["redis"]["slave_read_only"] = "yes" +default["redis"]["repl_ping_slave_period"] = 10 +default["redis"]["repl_timeout"] = 60 +default["redis"]["slave_priority"] = 100 +default["redis"]["requirepass"] = "" +default["redis"]["rename_commands"] = [] +default["redis"]["maxclients"] = 128 +default["redis"]["maxmemory"] = "64mb" +default["redis"]["maxmemory_policy"] = "volatile-lru" +default["redis"]["maxmemory_samples"] = 3 +default["redis"]["appendonly"] = "no" +default["redis"]["appendfilename"] = "appendonly.aof" +default["redis"]["appendfsync"] = "everysec" +default["redis"]["no_appendfsync_on_rewrite"] = "no" +default["redis"]["auto_aof_rewrite_percentage"] = 100 +default["redis"]["auto_aof_rewrite_min_size"] = "64mb" +default["redis"]["lua_time_limit"] = 5000 +default["redis"]["slowlog_log_slower_than"] = 10_000 +default["redis"]["slowlog_max_len"] = 1024 +default["redis"]["hash_max_ziplist_entries"] = 512 +default["redis"]["hash_max_ziplist_value"] = 64 +default["redis"]["list_max_ziplist_entries"] = 512 +default["redis"]["list_max_ziplist_value"] = 64 +default["redis"]["set_max_intset_entries"] = 512 +default["redis"]["zset_max_ziplist_entries"] = 128 +default["redis"]["zset_max_ziplist_value"] = 64 +default["redis"]["activerehashing"] = "yes" +default["redis"]["client_output_buffer_limit"] = { + "normal" => "0 0 0", + "slave" => "256mb 64mb 60", + "pubsub" => "32mb 8mb 60" +} +default["redis"]["include_config_files"] = [] +default["redis"]["ulimit"] = "" +default["redis"]["auto_upgrade"] = false diff --git a/cookbooks/redis/config/license_finder.yml b/cookbooks/redis/config/license_finder.yml new file mode 100644 index 0000000..45173be --- /dev/null +++ b/cookbooks/redis/config/license_finder.yml @@ -0,0 +1,11 @@ +--- +whitelist: +- Apache 2.0 +- Apache v2 +- BSD +- BSD-3 +- ISC +- MIT +- Ruby +dependencies_file_dir: doc/license_finder +project_name: chef-redis diff --git a/cookbooks/redis/doc/license_finder/dependencies.csv b/cookbooks/redis/doc/license_finder/dependencies.csv new file mode 100644 index 0000000..91da360 --- /dev/null +++ b/cookbooks/redis/doc/license_finder/dependencies.csv @@ -0,0 +1,105 @@ +addressable, 2.3.6, Apache 2.0 +ast, 2.0.0, MIT +astrolabe, 1.3.0, MIT +berkshelf, 3.2.1, Apache 2.0 +berkshelf-api-client, 1.2.0, Apache 2.0 +buff-config, 1.0.1, Apache 2.0 +buff-extensions, 1.0.0, Apache 2.0 +buff-ignore, 1.1.1, Apache 2.0 +buff-ruby_engine, 0.1.0, Apache 2.0 +buff-shell_out, 0.2.0, Apache 2.0 +bundler, 1.7.6, MIT +busser, 0.6.0, Apache 2.0 +busser-serverspec, 0.5.3, Apache 2.0 +celluloid, 0.16.0, MIT +celluloid-io, 0.16.1, MIT +chef, 11.16.4, Apache 2.0 +chef-zero, 2.2.1, Apache 2.0 +chefspec, 4.1.1, MIT +cleanroom, 1.0.0, Apache 2.0 +coderay, 1.1.0, MIT +dep-selector-libgecode, 1.0.2, MIT, Apache 2.0 +dep_selector, 1.0.3, Apache v2 +diff-lcs, 1.2.5, MIT, Perl Artistic v2, GNU GPL v2 +erubis, 2.7.0, MIT +faraday, 0.9.0, MIT +fauxhai, 2.2.0, MIT +ffi, 1.9.6, BSD +ffi-yajl, 1.3.0, Apache 2.0 +foodcritic, 4.0.0, MIT +formatador, 0.2.5, MIT +gherkin, 2.12.2, MIT +guard, 2.8.2, MIT +guard-rspec, 4.3.1, MIT +hashie, 2.1.2, MIT +highline, 1.6.21, ruby +hitimes, 1.2.2, ISC +httparty, 0.13.3, MIT +ipaddress, 0.8.0, MIT +json, 1.8.1, ruby +kitchen-vagrant, 0.15.0, Apache 2.0 +libyajl2, 1.2.0, Apache 2.0 +license_finder, 1.2, MIT +listen, 2.8.0, MIT +lumberjack, 1.0.9, MIT +method_source, 0.8.2, MIT +mime-types, 1.25.1, MIT, Artistic 2.0, GPL-2 +mini_portile, 0.6.1, MIT +minitar, 0.5.4, ruby +mixlib-authentication, 1.3.0, Apache 2.0 +mixlib-cli, 1.5.0, Apache 2.0 +mixlib-config, 2.1.0, Apache 2.0 +mixlib-log, 1.6.0, Apache 2.0 +mixlib-shellout, 1.6.0, Apache 2.0 +multi_json, 1.10.1, MIT +multi_xml, 0.5.5, MIT +multipart-post, 2.0.0, MIT +net-http-persistent, 2.9.4, MIT +net-scp, 1.2.1, MIT +net-ssh, 2.9.1, MIT +net-ssh-gateway, 1.2.0, MIT +net-ssh-multi, 1.2.0, MIT +nio4r, 1.0.1, MIT +nokogiri, 1.6.4.1, MIT +octokit, 3.5.2, MIT +ohai, 7.4.0, Apache 2.0 +parser, 2.2.0.pre.8, MIT +plist, 3.1.0, MIT +polyglot, 0.3.5, MIT +powerpack, 0.0.9, MIT +pry, 0.10.1, MIT +rack, 1.5.2, MIT +rainbow, 2.0.0, MIT +rake, 10.3.2, MIT +rb-fsevent, 0.9.4, MIT +rb-inotify, 0.9.5, MIT +rest-client, 1.6.7, MIT +retryable, 1.3.6, MIT +ridley, 4.1.0, Apache 2.0 +rspec, 3.1.0, MIT +rspec-core, 3.1.7, MIT +rspec-expectations, 3.1.2, MIT +rspec-its, 1.1.0, MIT +rspec-mocks, 3.1.3, MIT +rspec-support, 3.1.2, MIT +rubocop, 0.27.1, MIT +ruby-progressbar, 1.7.0, MIT +rufus-lru, 1.0.5, MIT +safe_yaml, 1.0.4, MIT +sawyer, 0.5.5, MIT +semverse, 1.2.1, Apache 2.0 +sequel, 4.16.0, MIT +serverspec, 2.3.1, MIT +slop, 3.6.0, MIT +solve, 1.2.1, Apache 2.0 +specinfra, 2.5.0, MIT +sqlite3, 1.3.10, New BSD +systemu, 2.6.4, ruby +test-kitchen, 1.2.1, Apache 2.0 +thor, 0.19.1, MIT +timers, 4.0.1, MIT +treetop, 1.5.3, MIT +varia_model, 0.4.0, Apache 2.0 +wmi-lite, 1.0.0, Apache 2.0 +xml-simple, 1.1.4, ruby +yajl-ruby, 1.2.1, MIT diff --git a/cookbooks/redis/doc/license_finder/dependencies.db b/cookbooks/redis/doc/license_finder/dependencies.db new file mode 100644 index 0000000..1e1e87a Binary files /dev/null and b/cookbooks/redis/doc/license_finder/dependencies.db differ diff --git a/cookbooks/redis/doc/license_finder/dependencies.html b/cookbooks/redis/doc/license_finder/dependencies.html new file mode 100644 index 0000000..5df7d0d --- /dev/null +++ b/cookbooks/redis/doc/license_finder/dependencies.html @@ -0,0 +1,2509 @@ + + + + + + + +
+

chef-redis

+
+
+
+

Dependencies

+ +

As of November 22, 2014 9:37pm

+ +

105 total

+ +
    +
  • 65 MIT
  • +
  • 28 Apache 2.0
  • +
  • 5 ruby
  • +
  • 1 Apache 2.0, MIT
  • +
  • 1 BSD
  • +
  • 1 Apache v2
  • +
  • 1 ISC
  • +
  • 1 Artistic 2.0, GPL-2, MIT
  • +
  • 1 GNU GPL v2, MIT, Perl Artistic v2
  • +
  • 1 New BSD
  • +
+
+
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ addressable + v2.3.6 +

+

URI Implementation

+

Addressable is a replacement for the URI implementation that is part of +Ruby's standard library. It more closely conforms to the relevant RFCs and +adds support for IRIs and URI templates. +

+
+
addressable is required by:
+
sawyer, ridley, berkshelf
+
+
+
addressable relies on:
+
rake, rspec
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ ast + v2.0.0 +

+

A library for working with Abstract Syntax Trees.

+

A library for working with Abstract Syntax Trees.

+
+
ast is required by:
+
parser
+
+
+
ast relies on:
+
rake, mime-types
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ astrolabe + v1.3.0 +

+

An object-oriented AST extension for Parser

+

An object-oriented AST extension for Parser

+
+
astrolabe is required by:
+
rubocop
+
+
+
astrolabe relies on:
+
parser, bundler, rake, rspec, rubocop, guard-rspec
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ berkshelf + v3.2.1 (default) +

+

Manages a Cookbook's, or an Application's, Cookbook dependencies

+

Manages a Cookbook's, or an Application's, Cookbook dependencies

+
+
berkshelf relies on:
+
addressable, berkshelf-api-client, buff-config, buff-extensions, buff-shell_out, cleanroom, faraday, minitar, retryable, ridley, solve, thor, octokit, celluloid, celluloid-io, chef-zero, rake, rspec, test-kitchen
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ berkshelf-api-client + v1.2.0 +

+

API Client for communicating with a Berkshelf API server

+

API Client for communicating with a Berkshelf API server

+
+
berkshelf-api-client is required by:
+
berkshelf
+
+
+
berkshelf-api-client relies on:
+
faraday, bundler, rake, rspec
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ buff-config + v1.0.1 +

+

A simple configuration class

+

A simple configuration class

+
+
buff-config is required by:
+
ridley, berkshelf
+
+
+
buff-config relies on:
+
varia_model, buff-extensions, buff-ruby_engine, thor, bundler, rake, rspec, guard, guard-rspec
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ buff-extensions + v1.0.0 +

+

Extensions to Core Ruby classes

+

Extensions to Core Ruby classes

+
+
buff-extensions is required by:
+
varia_model, buff-config, ridley, berkshelf
+
+
+
buff-extensions relies on:
+
buff-ruby_engine, thor, bundler, rake, rspec, guard, guard-rspec
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ buff-ignore + v1.1.1 +

+

A Ruby library for parsing lists of files and applying pattern matching exclusion (such as .gitignore)

+

Parse ignore files with Ruby

+
+
buff-ignore is required by:
+
ridley
+
+
+
buff-ignore relies on:
+
bundler, rake, rspec
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ buff-ruby_engine + v0.1.0 +

+

Buff up your code with a mixin for querying the platform running Ruby

+

A mixin for querying the platform running Ruby

+
+
buff-ruby_engine is required by:
+
buff-extensions, varia_model, buff-config, buff-shell_out, ridley
+
+
+
buff-ruby_engine relies on:
+
thor, bundler, rake, rspec, guard, guard-rspec
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ buff-shell_out + v0.2.0 +

+

Buff up your code with a mixin for issuing shell commands and collecting the output

+

A mixin for issuing shell commands and collecting the output

+
+
buff-shell_out is required by:
+
ridley, berkshelf
+
+
+
buff-shell_out relies on:
+
buff-ruby_engine, thor, bundler, rake, rspec, guard, guard-rspec
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ bundler + v1.7.6 +

+

+

+
+
bundler is required by:
+
parser, astrolabe, faraday, berkshelf-api-client, buff-extensions, varia_model, buff-config, buff-ruby_engine, buff-shell_out, cleanroom, octokit, retryable, buff-ignore, semverse, dep-selector-libgecode, thor, busser, busser-serverspec, libyajl2, wmi-lite, pry, rspec-support, multi_json, gherkin, rb-fsevent, listen, guard-rspec, multi_xml, test-kitchen, license_finder, powerpack, rainbow, rspec-its, rubocop, specinfra, serverspec
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ busser + v0.6.0 +

+

Kitchen Busser - Runs tests for projects in test-kitchen

+

Kitchen Busser - Runs tests for projects in test-kitchen

+
+
busser is required by:
+
busser-serverspec
+
+
+
busser relies on:
+
thor, chef, bundler, rake
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ busser-serverspec + v0.5.3 (integration) +

+

A Busser runner plugin for Serverspec

+

A Busser runner plugin for Serverspec

+
+
busser-serverspec relies on:
+
busser, serverspec, bundler, rake
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ celluloid + v0.16.0 +

+

Actor-based concurrent object framework for Ruby

+

Celluloid enables people to build concurrent programs out of concurrent objects just as easily as they build sequential programs out of sequential objects

+
+
celluloid is required by:
+
celluloid-io, ridley, berkshelf, listen
+
+
+
celluloid relies on:
+
timers, rake, rspec, guard-rspec, rubocop
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ celluloid-io + v0.16.1 +

+

Celluloid::IO allows you to monitor multiple IO objects within a Celluloid actor

+

Evented IO for Celluloid actors

+
+
celluloid-io is required by:
+
ridley, berkshelf, listen
+
+
+
celluloid-io relies on:
+
celluloid, nio4r, rake, rspec, guard-rspec, rb-fsevent
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ chef + v11.16.4 (default) +

+

A systems integration framework, built to bring the benefits of configuration management to your entire infrastructure.

+

A systems integration framework, built to bring the benefits of configuration management to your entire infrastructure.

+
+
chef is required by:
+
busser, ohai, chefspec
+
+
+
chef relies on:
+
mixlib-config, mixlib-cli, mixlib-log, mixlib-authentication, mixlib-shellout, ohai, rest-client, mime-types, ffi-yajl, net-ssh, net-ssh-multi, highline, erubis, diff-lcs, chef-zero, pry, plist, rack, rake, rspec-core, rspec-expectations, rspec-mocks
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ chef-zero + v2.2.1 +

+

Self-contained, easy-setup, fast-start in-memory Chef server for testing and solo setup purposes

+

Self-contained, easy-setup, fast-start in-memory Chef server for testing and solo setup purposes

+
+
chef-zero is required by:
+
berkshelf, chef
+
+
+
chef-zero relies on:
+
mixlib-log, hashie, ffi-yajl, rack, rake, rspec
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ chefspec + v4.1.1 (default) +

+

Write RSpec examples and generate coverage reports for Chef recipes!

+

ChefSpec is a unit testing and resource coverage (code coverage) framework for testing Chef cookbooks ChefSpec makes it easy to write examples and get fast feedback on cookbook changes without the need for virtual machines or cloud servers.

+
+
chefspec relies on:
+
chef, fauxhai, rspec, rake
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ cleanroom + v1.0.0 +

+

(More) safely evaluate Ruby DSLs with cleanroom

+

Ruby is an excellent programming language for creating and managing custom DSLs, but how can you securely evaluate a DSL while explicitly controlling the methods exposed to the user? Our good friends instance_eval and instance_exec are great, but they expose all methods - public, protected, and private - to the user. Even worse, they expose the ability to accidentally or intentionally alter the behavior of the system! The cleanroom pattern is a safer, more convenient, Ruby-like approach for limiting the information exposed by a DSL while giving users the ability to write awesome code!

+
+
cleanroom is required by:
+
berkshelf
+
+
+
cleanroom relies on:
+
rspec, bundler, rake
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ coderay + v1.1.0 +

+

Fast syntax highlighting for selected languages.

+

Fast and easy syntax highlighting for selected languages, written in Ruby. Comes with RedCloth integration and LOC counter.

+
+
coderay is required by:
+
pry, rspec-core
+
+
+
+
+

+ MIT, Apache 2.0 + whitelisted + +

+
+

+ dep-selector-libgecode + v1.0.2 +

+

Installs a vendored copy of Gecode suitable for use with dep-selector

+

Installs a vendored copy of Gecode suitable for use with dep-selector

+
+
dep-selector-libgecode is required by:
+
dep_selector
+
+
+
dep-selector-libgecode relies on:
+
bundler, rake
+
+
+
+
+

+ Apache v2 + whitelisted + +

+
+

+ dep_selector + v1.0.3 +

+

Given packages, versions, and a dependency graph, find a valid assignment of package versions

+

Given packages, versions, and a dependency graph, find a valid assignment of package versions

+
+
dep_selector is required by:
+
solve
+
+
+
dep_selector relies on:
+
ffi, dep-selector-libgecode, rake, rspec, solve
+
+
+
+
+

+ MIT, Perl Artistic v2, GNU GPL v2 + whitelisted + +

+
+

+ diff-lcs + v1.2.5 +

+

Diff::LCS computes the difference between two Enumerable sequences using the McIlroy-Hunt longest common subsequence (LCS) algorithm

+

Diff::LCS computes the difference between two Enumerable sequences using the +McIlroy-Hunt longest common subsequence (LCS) algorithm. It includes utilities +to create a simple HTML diff output format and a standard diff-like tool. + +This is release 1.2.4, fixing a bug introduced after diff-lcs 1.1.3 that did +not properly prune common sequences at the beginning of a comparison set. +Thanks to Paul Kunysch for fixing this issue. + +Coincident with the release of diff-lcs 1.2.3, we reported an issue with +Rubinius in 1.9 mode +({rubinius/rubinius#2268}[https://github.com/rubinius/rubinius/issues/2268]). +We are happy to report that this issue has been resolved.

+
+
diff-lcs is required by:
+
chef, rspec-expectations
+
+
+
diff-lcs relies on:
+
rake, rspec
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ erubis + v2.7.0 +

+

a fast and extensible eRuby implementation which supports multi-language

+

Erubis is an implementation of eRuby and has the following features: + + * Very fast, almost three times faster than ERB and about 10% faster than eruby. + * Multi-language support (Ruby/PHP/C/Java/Scheme/Perl/Javascript) + * Auto escaping support + * Auto trimming spaces around '<% %>' + * Embedded pattern changeable (default '<% %>') + * Enable to handle Processing Instructions (PI) as embedded pattern (ex. '') + * Context object available and easy to combine eRuby template with YAML datafile + * Print statement available + * Easy to extend and customize in subclass + * Ruby on Rails support +

+
+
erubis is required by:
+
ridley, chef, foodcritic
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ faraday + v0.9.0 +

+

HTTP/REST API client library.

+

+
+
faraday is required by:
+
berkshelf-api-client, sawyer, ridley, berkshelf
+
+
+
faraday relies on:
+
multipart-post, bundler
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ fauxhai + v2.2.0 +

+

Fauxhai provides an easy way to mock out your ohai data for testing with chefspec!

+

Easily mock out ohai data

+
+
fauxhai is required by:
+
chefspec
+
+
+
fauxhai relies on:
+
net-ssh, ohai, rake
+
+
+
+
+

+ BSD + whitelisted + +

+
+

+ ffi + v1.9.6 +

+

Ruby FFI

+

Ruby FFI library

+
+
ffi is required by:
+
dep_selector, libyajl2, ffi-yajl, ohai, rb-inotify
+
+
+
ffi relies on:
+
rake, rspec
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ ffi-yajl + v1.3.0 +

+

Ruby FFI wrapper around YAJL 2.x

+

Ruby FFI wrapper around YAJL 2.x

+
+
ffi-yajl is required by:
+
chef-zero, ohai, chef
+
+
+
ffi-yajl relies on:
+
rake, rspec, pry, mime-types, ffi, libyajl2
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ foodcritic + v4.0.0 (default) +

+

foodcritic-4.0.0

+

Lint tool for Opscode Chef cookbooks.

+
+
foodcritic relies on:
+
gherkin, nokogiri, rake, treetop, yajl-ruby, erubis, rufus-lru
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ formatador + v0.2.5 +

+

Ruby STDOUT text formatting

+

STDOUT text formatting

+
+
formatador is required by:
+
guard
+
+
+
formatador relies on:
+
rake
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ gherkin + v2.12.2 +

+

gherkin-2.12.2

+

A fast Gherkin lexer/parser based on the Ragel State Machine Compiler.

+
+
gherkin is required by:
+
foodcritic
+
+
+
gherkin relies on:
+
multi_json, rake, bundler, rspec
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ guard + v2.8.2 +

+

Guard keeps an eye on your file modifications

+

Guard is a command line tool to easily handle events on file system modifications.

+
+
guard is required by:
+
buff-extensions, varia_model, buff-config, buff-ruby_engine, buff-shell_out, guard-rspec
+
+
+
guard relies on:
+
thor, listen, pry, lumberjack, formatador
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ guard-rspec + v4.3.1 (integration) +

+

Guard gem for RSpec

+

Guard::RSpec automatically run your specs (much like autotest).

+
+
guard-rspec is required by:
+
astrolabe, buff-extensions, varia_model, buff-config, buff-ruby_engine, buff-shell_out, celluloid, celluloid-io, rb-fsevent
+
+
+
guard-rspec relies on:
+
guard, rspec, bundler, rake
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ hashie + v2.1.2 +

+

Your friendly neighborhood hash library.

+

Hashie is a collection of classes and mixins that make hashes more powerful.

+
+
hashie is required by:
+
varia_model, ridley, chef-zero
+
+
+
hashie relies on:
+
rake, rspec
+
+
+
+
+

+ ruby + whitelisted + +

+
+

+ highline + v1.6.21 +

+

HighLine is a high-level command-line IO library.

+

A high-level IO library that provides validation, type conversion, and more for +command-line interfaces. HighLine also includes a complete menu system that can +crank out anything from simple list selection to complete shells with just +minutes of work. +

+
+
highline is required by:
+
chef
+
+
+
+
+

+ ISC + whitelisted + +

+
+

+ hitimes + v1.2.2 +

+

Hitimes is a fast, high resolution timer library for recording performance metrics. It uses the appropriate low method calls for each system to get the highest granularity time increments possible.

+

Hitimes is a fast, high resolution timer library for recording performance metrics. It uses the appropriate low method calls for each system to get the highest granularity time increments possible. It currently supports any of the following systems: * any system with the POSIX call `clock_gettime()` * Mac OS X * Windows * JRuby Using Hitimes can be faster than using a series of `Time.new` calls, and it will have a much higher granularity. It is definitely faster than using `Process.times`.

+
+
hitimes is required by:
+
timers
+
+
+
hitimes relies on:
+
rake, json
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ httparty + v0.13.3 +

+

Makes http fun! Also, makes consuming restful web services dead easy.

+

Makes http fun! Also, makes consuming restful web services dead easy.

+
+
httparty is required by:
+
license_finder
+
+
+
httparty relies on:
+
json, multi_xml
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ ipaddress + v0.8.0 +

+

IPv4/IPv6 addresses manipulation library

+

IPAddress is a Ruby library designed to make manipulation + of IPv4 and IPv6 addresses both powerful and simple. It mantains + a layer of compatibility with Ruby's own IPAddr, while + addressing many of its issues. +

+
+
ipaddress is required by:
+
ohai
+
+
+
+
+

+ ruby + whitelisted + +

+
+

+ json + v1.8.1 +

+

This json is bundled with Ruby

+

+
+
json is required by:
+
hitimes, ridley, yajl-ruby, httparty
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ kitchen-vagrant + v0.15.0 (integration) +

+

Kitchen::Driver::Vagrant - A Vagrant Driver for Test Kitchen.

+

Kitchen::Driver::Vagrant - A Vagrant Driver for Test Kitchen.

+
+
kitchen-vagrant relies on:
+
test-kitchen
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ libyajl2 + v1.2.0 +

+

Installs a vendored copy of libyajl2 for distributions which lack it

+

Installs a vendored copy of libyajl2 for distributions which lack it

+
+
libyajl2 is required by:
+
ffi-yajl
+
+
+
libyajl2 relies on:
+
bundler, rake, mime-types, rspec, ffi
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ license_finder + v1.2 (default) +

+

Audit the OSS licenses of your application's dependencies.

+

LicenseFinder works with your package managers to find + dependencies, detect the licenses of the packages in them, compare + those licenses against a user-defined whitelist, and give you an + actionable exception report. +

+
+
license_finder relies on:
+
bundler, sequel, thor, httparty, xml-simple, sqlite3, rake, rspec-its, pry, rspec
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ listen + v2.8.0 +

+

Listen to file modifications

+

The Listen gem listens to file modifications and notifies you about the changes. Works everywhere!

+
+
listen is required by:
+
guard
+
+
+
listen relies on:
+
celluloid, rb-fsevent, rb-inotify, bundler, celluloid-io, rake, rspec
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ lumberjack + v1.0.9 +

+

A simple, powerful, and very fast logging utility that can be a drop in replacement for Logger or ActiveSupport::BufferedLogger.

+

A simple, powerful, and very fast logging utility that can be a drop in replacement for Logger or ActiveSupport::BufferedLogger. Provides support for automatically rolling log files even with multiple processes writing the same log file.

+
+
lumberjack is required by:
+
guard
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ method_source + v0.8.2 +

+

retrieve the sourcecode for a method

+

retrieve the sourcecode for a method

+
+
method_source is required by:
+
pry
+
+
+
method_source relies on:
+
rake
+
+
+
+
+

+ MIT, Artistic 2.0, GPL-2 + whitelisted + +

+
+

+ mime-types + v1.25.1 +

+

This library allows for the identification of a file's likely MIME content type

+

This library allows for the identification of a file's likely MIME content +type. This is release 1.25.1, fixing an issue with priority comparison for +mime-types 1.x. The current release is 2.0, which only supports Ruby 1.9 or +later. + +Release 1.25.1 contains all features of 1.25, including the experimental +caching and lazy loading functionality. The caching and lazy loading features +were initially implemented by Greg Brockman (gdb). As these features are +experimental, they are disabled by default and must be enabled through the use +of environment variables. The cache is invalidated on a per-version basis; the +cache for version 1.25 will not be reused for any later version. + +To use lazy loading, set the environment variable +RUBY_MIME_TYPES_LAZY_LOAD+ +to any value other than 'false'. When using lazy loading, the initial startup +of MIME::Types is around 12–25× faster than normal startup (on my system, +normal startup is about 90 ms; lazy startup is about 4 ms). This isn't +generally useful, however, as the MIME::Types database has not been loaded. +Lazy startup and load is just *slightly* faster—around 1 ms. The real advantage +comes from using the cache. + +To enable the cache, set the environment variable +RUBY_MIME_TYPES_CACHE+ to a +filename where MIME::Types will have read-write access. The first time a new +version of MIME::Types is run using this file, it will be created, taking a +little longer than normal. Subsequent loads using the same cache file will be +approximately 3½× faster (25 ms) than normal loads. This can be combined with ++RUBY_MIME_TYPES_LAZY_LOAD+, but this is *not* recommended in a multithreaded +or multiprocess environment where all threads or processes will be using the +same cache file. + +As the caching interface is still experimental, the only values cached are the +default MIME::Types database, not any custom MIME::Types added by users. + +MIME types are used in MIME-compliant communications, as in e-mail or HTTP +traffic, to indicate the type of content which is transmitted. MIME::Types +provides the ability for detailed information about MIME entities (provided as +a set of MIME::Type objects) to be determined and used programmatically. There +are many types defined by RFCs and vendors, so the list is long but not +complete; don't hesitate to ask to add additional information. This library +follows the IANA collection of MIME types (see below for reference). + +MIME::Types for Ruby was originally based on MIME::Types for Perl by Mark +Overmeer, copyright 2001 - 2009. + +MIME::Types is built to conform to the MIME types of RFCs 2045 and 2231. It +tracks the {IANA registry}[http://www.iana.org/assignments/media-types/] +({ftp}[ftp://ftp.iana.org/assignments/media-types]) with some unofficial types +added from the {LTSW collection}[http://www.ltsw.se/knbase/internet/mime.htp] +and added by the users of MIME::Types.

+
+
mime-types is required by:
+
ast, parser, libyajl2, ffi-yajl, ohai, rest-client, chef
+
+
+
mime-types relies on:
+
rake
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ mini_portile + v0.6.1 +

+

Simplistic port-like solution for developers

+

Simplistic port-like solution for developers. It provides a standard and simplified way to compile against dependency libraries without messing up your system.

+
+
mini_portile is required by:
+
nokogiri, sqlite3
+
+
+
+
+

+ ruby + whitelisted + +

+
+

+ minitar + v0.5.4 +

+

Provides POSIX tarchive management from Ruby programs.

+

Archive::Tar::Minitar is a pure-Ruby library and command-line utility that provides the ability to deal with POSIX tar(1) archive files. The implementation is based heavily on Mauricio Ferna'ndez's implementation in rpa-base, but has been reorganised to promote reuse in other projects. Antoine Toulme forked the original project on rubyforge to place it on github, under http://www.github.com/atoulme/minitar

+
+
minitar is required by:
+
berkshelf
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ mixlib-authentication + v1.3.0 +

+

Mixes in simple per-request authentication

+

Mixes in simple per-request authentication

+
+
mixlib-authentication is required by:
+
ridley, chef
+
+
+
mixlib-authentication relies on:
+
mixlib-log
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ mixlib-cli + v1.5.0 +

+

A simple mixin for CLI interfaces, including option parsing

+

A simple mixin for CLI interfaces, including option parsing

+
+
mixlib-cli is required by:
+
ohai, chef
+
+
+
mixlib-cli relies on:
+
rake, rspec
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ mixlib-config + v2.1.0 +

+

A class based configuration library

+

A class based configuration library

+
+
mixlib-config is required by:
+
ohai, chef
+
+
+
mixlib-config relies on:
+
rake, rspec
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ mixlib-log + v1.6.0 +

+

A gem that provides a simple mixin for log functionality

+

+
+
mixlib-log is required by:
+
mixlib-authentication, chef-zero, ohai, chef
+
+
+
mixlib-log relies on:
+
rake, rspec
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ mixlib-shellout + v1.6.0 +

+

Run external commands on Unix or Windows

+

Run external commands on Unix or Windows

+
+
mixlib-shellout is required by:
+
ohai, chef, test-kitchen
+
+
+
mixlib-shellout relies on:
+
rspec
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ multi_json + v1.10.1 +

+

A common interface to multiple JSON libraries.

+

A common interface to multiple JSON libraries, including Oj, Yajl, the JSON gem (with C-extensions), the pure-Ruby JSON gem, NSJSONSerialization, gson.rb, JrJackson, and OkJson.

+
+
multi_json is required by:
+
gherkin, serverspec
+
+
+
multi_json relies on:
+
bundler
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ multi_xml + v0.5.5 +

+

A generic swappable back-end for XML parsing

+

Provides swappable XML backends utilizing LibXML, Nokogiri, Ox, or REXML.

+
+
multi_xml is required by:
+
httparty
+
+
+
multi_xml relies on:
+
bundler
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ multipart-post + v2.0.0 +

+

A multipart form post accessory for Net::HTTP.

+

Use with Net::HTTP to do multipart form posts. IO values that have #content_type, #original_filename, and #local_path will be posted as a binary file.

+
+
multipart-post is required by:
+
faraday
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ net-http-persistent + v2.9.4 +

+

Manages persistent connections using Net::HTTP plus a speed fix for Ruby 1.8

+

Manages persistent connections using Net::HTTP plus a speed fix for Ruby 1.8. +It's thread-safe too! + +Using persistent HTTP connections can dramatically increase the speed of HTTP. +Creating a new HTTP connection for every request involves an extra TCP +round-trip and causes TCP congestion avoidance negotiation to start over. + +Net::HTTP supports persistent connections with some API methods but does not +handle reconnection gracefully. Net::HTTP::Persistent supports reconnection +and retry according to RFC 2616.

+
+
net-http-persistent is required by:
+
ridley
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ net-scp + v1.2.1 +

+

A pure Ruby implementation of the SCP client protocol

+

A pure Ruby implementation of the SCP client protocol

+
+
net-scp is required by:
+
test-kitchen, specinfra
+
+
+
net-scp relies on:
+
net-ssh
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ net-ssh + v2.9.1 +

+

Net::SSH: a pure-Ruby implementation of the SSH2 client protocol.

+

Net::SSH: a pure-Ruby implementation of the SSH2 client protocol. It allows you to write programs that invoke and interact with processes on remote servers, via SSH2.

+
+
net-ssh is required by:
+
net-ssh-gateway, net-ssh-multi, chef, fauxhai, net-scp, test-kitchen, specinfra
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ net-ssh-gateway + v1.2.0 +

+

A simple library to assist in establishing tunneled Net::SSH connections

+

A simple library to assist in establishing tunneled Net::SSH connections

+
+
net-ssh-gateway is required by:
+
net-ssh-multi
+
+
+
net-ssh-gateway relies on:
+
net-ssh
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ net-ssh-multi + v1.2.0 +

+

Control multiple Net::SSH connections via a single interface.

+

Control multiple Net::SSH connections via a single interface.

+
+
net-ssh-multi is required by:
+
chef
+
+
+
net-ssh-multi relies on:
+
net-ssh, net-ssh-gateway
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ nio4r + v1.0.1 +

+

NIO provides a high performance selector API for monitoring IO objects

+

New IO for Ruby

+
+
nio4r is required by:
+
celluloid-io
+
+
+
nio4r relies on:
+
rake, rspec
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ nokogiri + v1.6.4.1 +

+

Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser

+

Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser. Among Nokogiri's +many features is the ability to search documents via XPath or CSS3 selectors. + +XML is like violence - if it doesn’t solve your problems, you are not using +enough of it.

+
+
nokogiri is required by:
+
rspec-core, foodcritic
+
+
+
nokogiri relies on:
+
mini_portile, rake
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ octokit + v3.5.2 +

+

Ruby toolkit for working with the GitHub API

+

Simple wrapper for the GitHub API

+
+
octokit is required by:
+
berkshelf
+
+
+
octokit relies on:
+
bundler, sawyer
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ ohai + v7.4.0 +

+

Ohai profiles your system and emits JSON

+

Ohai profiles your system and emits JSON

+
+
ohai is required by:
+
chef, fauxhai
+
+
+
ohai relies on:
+
mime-types, systemu, ffi-yajl, mixlib-cli, mixlib-config, mixlib-log, mixlib-shellout, ipaddress, wmi-lite, ffi, rake, rspec-core, rspec-expectations, rspec-mocks, chef
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ parser + v2.2.0.pre.8 +

+

A Ruby parser written in pure Ruby.

+

A Ruby parser written in pure Ruby.

+
+
parser is required by:
+
astrolabe, rubocop
+
+
+
parser relies on:
+
ast, slop, bundler, rake, mime-types, rest-client
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ plist + v3.1.0 +

+

All-purpose Property List manipulation library.

+

Plist is a library to manipulate Property List files, also known as plists. It can parse plist files into native Ruby data structures as well as generating new plist files from your Ruby objects. +

+
+
plist is required by:
+
chef
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ polyglot + v0.3.5 +

+

Augment 'require' to load non-Ruby file types

+

+The Polyglot library allows a Ruby module to register a loader +for the file type associated with a filename extension, and it +augments 'require' to find and load matching files.

+
+
polyglot is required by:
+
treetop
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ powerpack + v0.0.9 +

+

A few useful extensions to core Ruby classes.

+

A few useful extensions to core Ruby classes.

+
+
powerpack is required by:
+
rubocop
+
+
+
powerpack relies on:
+
bundler, rake, rspec
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ pry + v0.10.1 +

+

An IRB alternative and runtime developer console

+

An IRB alternative and runtime developer console

+
+
pry is required by:
+
ffi-yajl, wmi-lite, chef, guard, license_finder
+
+
+
pry relies on:
+
coderay, slop, method_source, bundler
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ rack + v1.5.2 +

+

a modular Ruby webserver interface

+

Rack provides a minimal, modular and adaptable interface for developing +web applications in Ruby. By wrapping HTTP requests and responses in +the simplest way possible, it unifies and distills the API for web +servers, web frameworks, and software in between (the so-called +middleware) into a single method call. + +Also see http://rack.github.com/. +

+
+
rack is required by:
+
chef-zero, chef
+
+
+
rack relies on:
+
rake
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ rainbow + v2.0.0 +

+

Colorize printed text on ANSI terminals

+

Colorize printed text on ANSI terminals

+
+
rainbow is required by:
+
rubocop
+
+
+
rainbow relies on:
+
bundler, rake, rspec
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ rake + v10.3.2 (default) +

+

Rake is a Make-like program implemented in Ruby

+

Rake is a Make-like program implemented in Ruby. Tasks and dependencies are +specified in standard Ruby syntax. + +Rake has the following features: + +* Rakefiles (rake's version of Makefiles) are completely defined in + standard Ruby syntax. No XML files to edit. No quirky Makefile + syntax to worry about (is that a tab or a space?) + +* Users can specify tasks with prerequisites. + +* Rake supports rule patterns to synthesize implicit tasks. + +* Flexible FileLists that act like arrays but know about manipulating + file names and paths. + +* A library of prepackaged tasks to make building rakefiles easier. For example, + tasks for building tarballs and publishing to FTP or SSH sites. (Formerly + tasks for building RDoc and Gems were included in rake but they're now + available in RDoc and RubyGems respectively.) + +* Supports parallel execution of tasks.

+
+
rake is required by:
+
addressable, ast, slop, parser, astrolabe, berkshelf-api-client, buff-extensions, hashie, varia_model, buff-config, buff-ruby_engine, buff-shell_out, hitimes, timers, celluloid, nio4r, celluloid-io, cleanroom, buff-ignore, mixlib-log, semverse, dep-selector-libgecode, ffi, dep_selector, berkshelf, busser, busser-serverspec, libyajl2, ffi-yajl, rack, chef-zero, diff-lcs, mime-types, mixlib-cli, mixlib-config, wmi-lite, ohai, method_source, chef, fauxhai, rspec-support, rspec-core, rspec-expectations, rspec-mocks, chefspec, gherkin, nokogiri, rufus-lru, treetop, foodcritic, formatador, listen, guard-rspec, test-kitchen, license_finder, powerpack, rainbow, rspec-its, rubocop, specinfra, serverspec
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ rb-fsevent + v0.9.4 +

+

Very simple & usable FSEvents API

+

FSEvents API with Signals catching (without RubyCocoa)

+
+
rb-fsevent is required by:
+
celluloid-io, listen
+
+
+
rb-fsevent relies on:
+
bundler, rspec, guard-rspec
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ rb-inotify + v0.9.5 +

+

A Ruby wrapper for Linux's inotify, using FFI

+

A Ruby wrapper for Linux's inotify, using FFI

+
+
rb-inotify is required by:
+
listen
+
+
+
rb-inotify relies on:
+
ffi
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ rest-client + v1.6.7 +

+

Simple HTTP and REST client for Ruby, inspired by microframework syntax for specifying actions.

+

A simple HTTP and REST client for Ruby, inspired by the Sinatra microframework style of specifying actions: get, put, post, delete.

+
+
rest-client is required by:
+
parser, chef
+
+
+
rest-client relies on:
+
mime-types, rspec
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ retryable + v1.3.6 +

+

Kernel#retryable, allow for retrying of code blocks.

+

Kernel#retryable, allow for retrying of code blocks.

+
+
retryable is required by:
+
ridley, berkshelf
+
+
+
retryable relies on:
+
bundler
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ ridley + v4.1.0 +

+

A reliable Chef API client with a clean syntax

+

A reliable Chef API client with a clean syntax

+
+
ridley is required by:
+
berkshelf
+
+
+
ridley relies on:
+
addressable, varia_model, buff-config, buff-extensions, buff-ignore, buff-shell_out, celluloid, celluloid-io, erubis, faraday, hashie, json, mixlib-authentication, net-http-persistent, retryable, semverse, buff-ruby_engine
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ rspec + v3.1.0 +

+

rspec-3.1.0

+

BDD for Ruby

+
+
rspec is required by:
+
addressable, astrolabe, berkshelf-api-client, buff-extensions, hashie, varia_model, buff-config, buff-ruby_engine, buff-shell_out, timers, celluloid, nio4r, celluloid-io, cleanroom, buff-ignore, mixlib-log, ffi, dep_selector, berkshelf, libyajl2, ffi-yajl, chef-zero, diff-lcs, mixlib-cli, mixlib-config, mixlib-shellout, wmi-lite, rest-client, chefspec, gherkin, rufus-lru, treetop, yajl-ruby, rb-fsevent, listen, guard-rspec, license_finder, powerpack, rainbow, ruby-progressbar, rubocop, specinfra, serverspec
+
+
+
rspec relies on:
+
rspec-core, rspec-expectations, rspec-mocks
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ rspec-core + v3.1.7 +

+

rspec-core-3.1.7

+

BDD for Ruby. RSpec runner and example groups.

+
+
rspec-core is required by:
+
ohai, chef, rspec, rspec-its
+
+
+
rspec-core relies on:
+
rspec-support, rake, nokogiri, coderay
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ rspec-expectations + v3.1.2 +

+

rspec-expectations-3.1.2

+

rspec-expectations provides a simple, readable API to express expected outcomes of a code example.

+
+
rspec-expectations is required by:
+
ohai, chef, rspec, rspec-its
+
+
+
rspec-expectations relies on:
+
rspec-support, diff-lcs, rake
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ rspec-its + v1.1.0 +

+

Provides "its" method formally part of rspec-core

+

RSpec extension gem for attribute matching

+
+
rspec-its is required by:
+
license_finder, specinfra, serverspec
+
+
+
rspec-its relies on:
+
rspec-core, rspec-expectations, bundler, rake
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ rspec-mocks + v3.1.3 +

+

rspec-mocks-3.1.3

+

RSpec's 'test double' framework, with support for stubbing and mocking

+
+
rspec-mocks is required by:
+
ohai, chef, rspec
+
+
+
rspec-mocks relies on:
+
rspec-support, rake
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ rspec-support + v3.1.2 +

+

rspec-support-3.1.2

+

Support utilities for RSpec gems

+
+
rspec-support is required by:
+
rspec-core, rspec-expectations, rspec-mocks
+
+
+
rspec-support relies on:
+
bundler, rake
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ rubocop + v0.27.1 (default) +

+

Automatic Ruby code style checking tool.

+

Automatic Ruby code style checking tool. + Aims to enforce the community-driven Ruby Style Guide. +

+
+
rubocop is required by:
+
astrolabe, celluloid
+
+
+
rubocop relies on:
+
rainbow, parser, powerpack, astrolabe, ruby-progressbar, rake, rspec, bundler
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ ruby-progressbar + v1.7.0 +

+

Ruby/ProgressBar is a flexible text progress bar library for Ruby.

+

Ruby/ProgressBar is an extremely flexible text progress bar library for Ruby. +The output can be customized with a flexible formatting system including: +percentage, bars of various formats, elapsed time and estimated time remaining. +

+
+
ruby-progressbar is required by:
+
rubocop
+
+
+
ruby-progressbar relies on:
+
rspec
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ rufus-lru + v1.0.5 +

+

A Hash with a max size, controlled by a LRU mechanism

+

LruHash class, a Hash with a max size, controlled by a LRU mechanism

+
+
rufus-lru is required by:
+
foodcritic
+
+
+
rufus-lru relies on:
+
rake, rspec
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ safe_yaml + v1.0.4 +

+

SameYAML provides an alternative implementation of YAML.load suitable for accepting user input in Ruby applications.

+

Parse YAML safely

+
+
safe_yaml is required by:
+
test-kitchen
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ sawyer + v0.5.5 +

+

Secret User Agent of HTTP

+

+
+
sawyer is required by:
+
octokit
+
+
+
sawyer relies on:
+
faraday, addressable
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ semverse + v1.2.1 +

+

An elegant library for representing and comparing SemVer versions and constraints

+

An elegant library for representing and comparing SemVer versions and constraints

+
+
semverse is required by:
+
ridley, solve
+
+
+
semverse relies on:
+
bundler, rake
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ sequel + v4.16.0 +

+

The Database Toolkit for Ruby

+

The Database Toolkit for Ruby

+
+
sequel is required by:
+
license_finder
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ serverspec + v2.3.1 (default) +

+

RSpec tests for your servers configured by Puppet, Chef or anything else

+

RSpec tests for your servers configured by Puppet, Chef or anything else

+
+
serverspec is required by:
+
busser-serverspec
+
+
+
serverspec relies on:
+
rspec, rspec-its, multi_json, specinfra, bundler, rake
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ slop + v3.6.0 +

+

Simple Lightweight Option Parsing

+

A simple DSL for gathering options and parsing the command line

+
+
slop is required by:
+
parser, pry
+
+
+
slop relies on:
+
rake
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ solve + v1.2.1 +

+

A Ruby version constraint solver implementing Semantic Versioning 2.0.0-rc.1

+

A Ruby version constraint solver

+
+
solve is required by:
+
dep_selector, berkshelf
+
+
+
solve relies on:
+
semverse, dep_selector
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ specinfra + v2.5.0 +

+

Common layer for serverspec and itamae

+

Common layer for serverspec and itamae

+
+
specinfra is required by:
+
serverspec
+
+
+
specinfra relies on:
+
net-ssh, net-scp, bundler, rake, rspec, rspec-its
+
+
+
+
+

+ New BSD + whitelisted + +

+
+

+ sqlite3 + v1.3.10 +

+

This module allows Ruby programs to interface with the SQLite3 database engine (http://www.sqlite.org)

+

This module allows Ruby programs to interface with the SQLite3 +database engine (http://www.sqlite.org). You must have the +SQLite engine installed in order to build this module. + +Note that this module is only compatible with SQLite 3.6.16 or newer.

+
+
sqlite3 is required by:
+
license_finder
+
+
+
sqlite3 relies on:
+
mini_portile
+
+
+
+
+

+ ruby + whitelisted + +

+
+

+ systemu + v2.6.4 +

+

systemu

+

universal capture of stdout and stderr and handling of child process pid for windows, *nix, etc.

+
+
systemu is required by:
+
ohai
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ test-kitchen + v1.2.1 (integration) +

+

Test Kitchen is an integration tool for developing and testing infrastructure code and software on isolated target platforms.

+

Test Kitchen is an integration tool for developing and testing infrastructure code and software on isolated target platforms.

+
+
test-kitchen is required by:
+
berkshelf, kitchen-vagrant
+
+
+
test-kitchen relies on:
+
mixlib-shellout, net-scp, net-ssh, safe_yaml, thor, bundler, rake
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ thor + v0.19.1 +

+

Thor is a toolkit for building powerful command-line interfaces.

+

Thor is a toolkit for building powerful command-line interfaces.

+
+
thor is required by:
+
buff-extensions, varia_model, buff-config, buff-ruby_engine, buff-shell_out, berkshelf, busser, guard, test-kitchen, license_finder
+
+
+
thor relies on:
+
bundler
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ timers + v4.0.1 +

+

Schedule procs to run after a certain time, or at periodic intervals, using any API that accepts a timeout

+

Pure Ruby one-shot and periodic timers

+
+
timers is required by:
+
celluloid
+
+
+
timers relies on:
+
hitimes, rake, rspec
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ treetop + v1.5.3 +

+

A Ruby-based text parsing and interpretation DSL

+

+
+
treetop is required by:
+
foodcritic
+
+
+
treetop relies on:
+
polyglot, rspec, rake
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ varia_model + v0.4.0 +

+

A mixin to provide objects with magic attribute reading and writing

+

A mixin to provide objects with magic attribute reading and writing

+
+
varia_model is required by:
+
buff-config, ridley
+
+
+
varia_model relies on:
+
hashie, buff-extensions, buff-ruby_engine, thor, bundler, rake, rspec, guard, guard-rspec
+
+
+
+
+

+ Apache 2.0 + whitelisted + +

+
+

+ wmi-lite + v1.0.0 +

+

A lightweight utility library for accessing basic WMI (Windows Management Instrumentation) functionality on Windows

+

A lightweight utility over win32ole for accessing basic WMI (Windows Management Instrumentation) functionality in the Microsoft Windows operating system. It has no runtime dependencies other than Ruby, so it can be used without concerns around dependency issues.

+
+
wmi-lite is required by:
+
ohai
+
+
+
wmi-lite relies on:
+
bundler, rspec, rake, pry
+
+
+
+
+

+ ruby + whitelisted + +

+
+

+ xml-simple + v1.1.4 +

+

A simple API for XML processing.

+

+
+
xml-simple is required by:
+
license_finder
+
+
+
+
+

+ MIT + whitelisted + +

+
+

+ yajl-ruby + v1.2.1 +

+

Ruby C bindings to the excellent Yajl JSON stream-based parser library.

+

+
+
yajl-ruby is required by:
+
foodcritic
+
+
+
yajl-ruby relies on:
+
rspec, json
+
+
+
+
+ + diff --git a/cookbooks/redis/doc/license_finder/dependencies.md b/cookbooks/redis/doc/license_finder/dependencies.md new file mode 100644 index 0000000..581d441 --- /dev/null +++ b/cookbooks/redis/doc/license_finder/dependencies.md @@ -0,0 +1,991 @@ +# chef-redis + +As of November 22, 2014 9:37pm. 105 total + +## Summary +* 65 MIT +* 28 Apache 2.0 +* 5 ruby +* 1 Apache 2.0, MIT +* 1 BSD +* 1 Apache v2 +* 1 ISC +* 1 Artistic 2.0, GPL-2, MIT +* 1 GNU GPL v2, MIT, Perl Artistic v2 +* 1 New BSD + + + +## Items + + + +### addressable v2.3.6 +#### URI Implementation + +Apache 2.0 whitelisted + +Addressable is a replacement for the URI implementation that is part of +Ruby's standard library. It more closely conforms to the relevant RFCs and +adds support for IRIs and URI templates. + + + +### ast v2.0.0 +#### A library for working with Abstract Syntax Trees. + +MIT whitelisted + +A library for working with Abstract Syntax Trees. + + +### astrolabe v1.3.0 +#### An object-oriented AST extension for Parser + +MIT whitelisted + +An object-oriented AST extension for Parser + + +### berkshelf v3.2.1 (default) +#### Manages a Cookbook's, or an Application's, Cookbook dependencies + +Apache 2.0 whitelisted + +Manages a Cookbook's, or an Application's, Cookbook dependencies + + +### berkshelf-api-client v1.2.0 +#### API Client for communicating with a Berkshelf API server + +Apache 2.0 whitelisted + +API Client for communicating with a Berkshelf API server + + +### buff-config v1.0.1 +#### A simple configuration class + +Apache 2.0 whitelisted + +A simple configuration class + + +### buff-extensions v1.0.0 +#### Extensions to Core Ruby classes + +Apache 2.0 whitelisted + +Extensions to Core Ruby classes + + +### buff-ignore v1.1.1 +#### A Ruby library for parsing lists of files and applying pattern matching exclusion (such as .gitignore) + +Apache 2.0 whitelisted + +Parse ignore files with Ruby + + +### buff-ruby_engine v0.1.0 +#### Buff up your code with a mixin for querying the platform running Ruby + +Apache 2.0 whitelisted + +A mixin for querying the platform running Ruby + + +### buff-shell_out v0.2.0 +#### Buff up your code with a mixin for issuing shell commands and collecting the output + +Apache 2.0 whitelisted + +A mixin for issuing shell commands and collecting the output + + +### bundler v1.7.6 +#### + +MIT whitelisted + + + +### busser v0.6.0 +#### Kitchen Busser - Runs tests for projects in test-kitchen + +Apache 2.0 whitelisted + +Kitchen Busser - Runs tests for projects in test-kitchen + + +### busser-serverspec v0.5.3 (integration) +#### A Busser runner plugin for Serverspec + +Apache 2.0 whitelisted + +A Busser runner plugin for Serverspec + + +### celluloid v0.16.0 +#### Actor-based concurrent object framework for Ruby + +MIT whitelisted + +Celluloid enables people to build concurrent programs out of concurrent objects just as easily as they build sequential programs out of sequential objects + + +### celluloid-io v0.16.1 +#### Celluloid::IO allows you to monitor multiple IO objects within a Celluloid actor + +MIT whitelisted + +Evented IO for Celluloid actors + + +### chef v11.16.4 (default) +#### A systems integration framework, built to bring the benefits of configuration management to your entire infrastructure. + +Apache 2.0 whitelisted + +A systems integration framework, built to bring the benefits of configuration management to your entire infrastructure. + + +### chef-zero v2.2.1 +#### Self-contained, easy-setup, fast-start in-memory Chef server for testing and solo setup purposes + +Apache 2.0 whitelisted + +Self-contained, easy-setup, fast-start in-memory Chef server for testing and solo setup purposes + + +### chefspec v4.1.1 (default) +#### Write RSpec examples and generate coverage reports for Chef recipes! + +MIT whitelisted + +ChefSpec is a unit testing and resource coverage (code coverage) framework for testing Chef cookbooks ChefSpec makes it easy to write examples and get fast feedback on cookbook changes without the need for virtual machines or cloud servers. + + +### cleanroom v1.0.0 +#### (More) safely evaluate Ruby DSLs with cleanroom + +Apache 2.0 whitelisted + +Ruby is an excellent programming language for creating and managing custom DSLs, but how can you securely evaluate a DSL while explicitly controlling the methods exposed to the user? Our good friends instance_eval and instance_exec are great, but they expose all methods - public, protected, and private - to the user. Even worse, they expose the ability to accidentally or intentionally alter the behavior of the system! The cleanroom pattern is a safer, more convenient, Ruby-like approach for limiting the information exposed by a DSL while giving users the ability to write awesome code! + + +### coderay v1.1.0 +#### Fast syntax highlighting for selected languages. + +MIT whitelisted + +Fast and easy syntax highlighting for selected languages, written in Ruby. Comes with RedCloth integration and LOC counter. + + +### dep-selector-libgecode v1.0.2 +#### Installs a vendored copy of Gecode suitable for use with dep-selector + +MIT, Apache 2.0 whitelisted + +Installs a vendored copy of Gecode suitable for use with dep-selector + + +### dep_selector v1.0.3 +#### Given packages, versions, and a dependency graph, find a valid assignment of package versions + +Apache v2 whitelisted + +Given packages, versions, and a dependency graph, find a valid assignment of package versions + + +### diff-lcs v1.2.5 +#### Diff::LCS computes the difference between two Enumerable sequences using the McIlroy-Hunt longest common subsequence (LCS) algorithm + +MIT, Perl Artistic v2, GNU GPL v2 whitelisted + +Diff::LCS computes the difference between two Enumerable sequences using the +McIlroy-Hunt longest common subsequence (LCS) algorithm. It includes utilities +to create a simple HTML diff output format and a standard diff-like tool. + +This is release 1.2.4, fixing a bug introduced after diff-lcs 1.1.3 that did +not properly prune common sequences at the beginning of a comparison set. +Thanks to Paul Kunysch for fixing this issue. + +Coincident with the release of diff-lcs 1.2.3, we reported an issue with +Rubinius in 1.9 mode +({rubinius/rubinius#2268}[https://github.com/rubinius/rubinius/issues/2268]). +We are happy to report that this issue has been resolved. + + +### erubis v2.7.0 +#### a fast and extensible eRuby implementation which supports multi-language + +MIT whitelisted + + Erubis is an implementation of eRuby and has the following features: + + * Very fast, almost three times faster than ERB and about 10% faster than eruby. + * Multi-language support (Ruby/PHP/C/Java/Scheme/Perl/Javascript) + * Auto escaping support + * Auto trimming spaces around '<% %>' + * Embedded pattern changeable (default '<% %>') + * Enable to handle Processing Instructions (PI) as embedded pattern (ex. '') + * Context object available and easy to combine eRuby template with YAML datafile + * Print statement available + * Easy to extend and customize in subclass + * Ruby on Rails support + + + +### faraday v0.9.0 +#### HTTP/REST API client library. + +MIT whitelisted + + + +### fauxhai v2.2.0 +#### Fauxhai provides an easy way to mock out your ohai data for testing with chefspec! + +MIT whitelisted + +Easily mock out ohai data + + +### ffi v1.9.6 +#### Ruby FFI + +BSD whitelisted + +Ruby FFI library + + +### ffi-yajl v1.3.0 +#### Ruby FFI wrapper around YAJL 2.x + +Apache 2.0 whitelisted + +Ruby FFI wrapper around YAJL 2.x + + +### foodcritic v4.0.0 (default) +#### foodcritic-4.0.0 + +MIT whitelisted + +Lint tool for Opscode Chef cookbooks. + + +### formatador v0.2.5 +#### Ruby STDOUT text formatting + +MIT whitelisted + +STDOUT text formatting + + +### gherkin v2.12.2 +#### gherkin-2.12.2 + +MIT whitelisted + +A fast Gherkin lexer/parser based on the Ragel State Machine Compiler. + + +### guard v2.8.2 +#### Guard keeps an eye on your file modifications + +MIT whitelisted + +Guard is a command line tool to easily handle events on file system modifications. + + +### guard-rspec v4.3.1 (integration) +#### Guard gem for RSpec + +MIT whitelisted + +Guard::RSpec automatically run your specs (much like autotest). + + +### hashie v2.1.2 +#### Your friendly neighborhood hash library. + +MIT whitelisted + +Hashie is a collection of classes and mixins that make hashes more powerful. + + +### highline v1.6.21 +#### HighLine is a high-level command-line IO library. + +ruby whitelisted + +A high-level IO library that provides validation, type conversion, and more for +command-line interfaces. HighLine also includes a complete menu system that can +crank out anything from simple list selection to complete shells with just +minutes of work. + + + +### hitimes v1.2.2 +#### Hitimes is a fast, high resolution timer library for recording performance metrics. It uses the appropriate low method calls for each system to get the highest granularity time increments possible. + +ISC whitelisted + +Hitimes is a fast, high resolution timer library for recording performance metrics. It uses the appropriate low method calls for each system to get the highest granularity time increments possible. It currently supports any of the following systems: * any system with the POSIX call `clock_gettime()` * Mac OS X * Windows * JRuby Using Hitimes can be faster than using a series of `Time.new` calls, and it will have a much higher granularity. It is definitely faster than using `Process.times`. + + +### httparty v0.13.3 +#### Makes http fun! Also, makes consuming restful web services dead easy. + +MIT whitelisted + +Makes http fun! Also, makes consuming restful web services dead easy. + + +### ipaddress v0.8.0 +#### IPv4/IPv6 addresses manipulation library + +MIT whitelisted + + IPAddress is a Ruby library designed to make manipulation + of IPv4 and IPv6 addresses both powerful and simple. It mantains + a layer of compatibility with Ruby's own IPAddr, while + addressing many of its issues. + + + +### json v1.8.1 +#### This json is bundled with Ruby + +ruby whitelisted + + + +### kitchen-vagrant v0.15.0 (integration) +#### Kitchen::Driver::Vagrant - A Vagrant Driver for Test Kitchen. + +Apache 2.0 whitelisted + +Kitchen::Driver::Vagrant - A Vagrant Driver for Test Kitchen. + + +### libyajl2 v1.2.0 +#### Installs a vendored copy of libyajl2 for distributions which lack it + +Apache 2.0 whitelisted + +Installs a vendored copy of libyajl2 for distributions which lack it + + +### license_finder v1.2 (default) +#### Audit the OSS licenses of your application's dependencies. + +MIT whitelisted + + LicenseFinder works with your package managers to find + dependencies, detect the licenses of the packages in them, compare + those licenses against a user-defined whitelist, and give you an + actionable exception report. + + + +### listen v2.8.0 +#### Listen to file modifications + +MIT whitelisted + +The Listen gem listens to file modifications and notifies you about the changes. Works everywhere! + + +### lumberjack v1.0.9 +#### A simple, powerful, and very fast logging utility that can be a drop in replacement for Logger or ActiveSupport::BufferedLogger. + +MIT whitelisted + +A simple, powerful, and very fast logging utility that can be a drop in replacement for Logger or ActiveSupport::BufferedLogger. Provides support for automatically rolling log files even with multiple processes writing the same log file. + + +### method_source v0.8.2 +#### retrieve the sourcecode for a method + +MIT whitelisted + +retrieve the sourcecode for a method + + +### mime-types v1.25.1 +#### This library allows for the identification of a file's likely MIME content type + +MIT, Artistic 2.0, GPL-2 whitelisted + +This library allows for the identification of a file's likely MIME content +type. This is release 1.25.1, fixing an issue with priority comparison for +mime-types 1.x. The current release is 2.0, which only supports Ruby 1.9 or +later. + +Release 1.25.1 contains all features of 1.25, including the experimental +caching and lazy loading functionality. The caching and lazy loading features +were initially implemented by Greg Brockman (gdb). As these features are +experimental, they are disabled by default and must be enabled through the use +of environment variables. The cache is invalidated on a per-version basis; the +cache for version 1.25 will not be reused for any later version. + +To use lazy loading, set the environment variable +RUBY_MIME_TYPES_LAZY_LOAD+ +to any value other than 'false'. When using lazy loading, the initial startup +of MIME::Types is around 12–25× faster than normal startup (on my system, +normal startup is about 90 ms; lazy startup is about 4 ms). This isn't +generally useful, however, as the MIME::Types database has not been loaded. +Lazy startup and load is just *slightly* faster—around 1 ms. The real advantage +comes from using the cache. + +To enable the cache, set the environment variable +RUBY_MIME_TYPES_CACHE+ to a +filename where MIME::Types will have read-write access. The first time a new +version of MIME::Types is run using this file, it will be created, taking a +little longer than normal. Subsequent loads using the same cache file will be +approximately 3½× faster (25 ms) than normal loads. This can be combined with ++RUBY_MIME_TYPES_LAZY_LOAD+, but this is *not* recommended in a multithreaded +or multiprocess environment where all threads or processes will be using the +same cache file. + +As the caching interface is still experimental, the only values cached are the +default MIME::Types database, not any custom MIME::Types added by users. + +MIME types are used in MIME-compliant communications, as in e-mail or HTTP +traffic, to indicate the type of content which is transmitted. MIME::Types +provides the ability for detailed information about MIME entities (provided as +a set of MIME::Type objects) to be determined and used programmatically. There +are many types defined by RFCs and vendors, so the list is long but not +complete; don't hesitate to ask to add additional information. This library +follows the IANA collection of MIME types (see below for reference). + +MIME::Types for Ruby was originally based on MIME::Types for Perl by Mark +Overmeer, copyright 2001 - 2009. + +MIME::Types is built to conform to the MIME types of RFCs 2045 and 2231. It +tracks the {IANA registry}[http://www.iana.org/assignments/media-types/] +({ftp}[ftp://ftp.iana.org/assignments/media-types]) with some unofficial types +added from the {LTSW collection}[http://www.ltsw.se/knbase/internet/mime.htp] +and added by the users of MIME::Types. + + +### mini_portile v0.6.1 +#### Simplistic port-like solution for developers + +MIT whitelisted + +Simplistic port-like solution for developers. It provides a standard and simplified way to compile against dependency libraries without messing up your system. + + +### minitar v0.5.4 +#### Provides POSIX tarchive management from Ruby programs. + +ruby whitelisted + +Archive::Tar::Minitar is a pure-Ruby library and command-line utility that provides the ability to deal with POSIX tar(1) archive files. The implementation is based heavily on Mauricio Ferna'ndez's implementation in rpa-base, but has been reorganised to promote reuse in other projects. Antoine Toulme forked the original project on rubyforge to place it on github, under http://www.github.com/atoulme/minitar + + +### mixlib-authentication v1.3.0 +#### Mixes in simple per-request authentication + +Apache 2.0 whitelisted + +Mixes in simple per-request authentication + + +### mixlib-cli v1.5.0 +#### A simple mixin for CLI interfaces, including option parsing + +Apache 2.0 whitelisted + +A simple mixin for CLI interfaces, including option parsing + + +### mixlib-config v2.1.0 +#### A class based configuration library + +Apache 2.0 whitelisted + +A class based configuration library + + +### mixlib-log v1.6.0 +#### A gem that provides a simple mixin for log functionality + +Apache 2.0 whitelisted + + + +### mixlib-shellout v1.6.0 +#### Run external commands on Unix or Windows + +Apache 2.0 whitelisted + +Run external commands on Unix or Windows + + +### multi_json v1.10.1 +#### A common interface to multiple JSON libraries. + +MIT whitelisted + +A common interface to multiple JSON libraries, including Oj, Yajl, the JSON gem (with C-extensions), the pure-Ruby JSON gem, NSJSONSerialization, gson.rb, JrJackson, and OkJson. + + +### multi_xml v0.5.5 +#### A generic swappable back-end for XML parsing + +MIT whitelisted + +Provides swappable XML backends utilizing LibXML, Nokogiri, Ox, or REXML. + + +### multipart-post v2.0.0 +#### A multipart form post accessory for Net::HTTP. + +MIT whitelisted + +Use with Net::HTTP to do multipart form posts. IO values that have #content_type, #original_filename, and #local_path will be posted as a binary file. + + +### net-http-persistent v2.9.4 +#### Manages persistent connections using Net::HTTP plus a speed fix for Ruby 1.8 + +MIT whitelisted + +Manages persistent connections using Net::HTTP plus a speed fix for Ruby 1.8. +It's thread-safe too! + +Using persistent HTTP connections can dramatically increase the speed of HTTP. +Creating a new HTTP connection for every request involves an extra TCP +round-trip and causes TCP congestion avoidance negotiation to start over. + +Net::HTTP supports persistent connections with some API methods but does not +handle reconnection gracefully. Net::HTTP::Persistent supports reconnection +and retry according to RFC 2616. + + +### net-scp v1.2.1 +#### A pure Ruby implementation of the SCP client protocol + +MIT whitelisted + +A pure Ruby implementation of the SCP client protocol + + +### net-ssh v2.9.1 +#### Net::SSH: a pure-Ruby implementation of the SSH2 client protocol. + +MIT whitelisted + +Net::SSH: a pure-Ruby implementation of the SSH2 client protocol. It allows you to write programs that invoke and interact with processes on remote servers, via SSH2. + + +### net-ssh-gateway v1.2.0 +#### A simple library to assist in establishing tunneled Net::SSH connections + +MIT whitelisted + +A simple library to assist in establishing tunneled Net::SSH connections + + +### net-ssh-multi v1.2.0 +#### Control multiple Net::SSH connections via a single interface. + +MIT whitelisted + +Control multiple Net::SSH connections via a single interface. + + +### nio4r v1.0.1 +#### NIO provides a high performance selector API for monitoring IO objects + +MIT whitelisted + +New IO for Ruby + + +### nokogiri v1.6.4.1 +#### Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser + +MIT whitelisted + +Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser. Among Nokogiri's +many features is the ability to search documents via XPath or CSS3 selectors. + +XML is like violence - if it doesn’t solve your problems, you are not using +enough of it. + + +### octokit v3.5.2 +#### Ruby toolkit for working with the GitHub API + +MIT whitelisted + +Simple wrapper for the GitHub API + + +### ohai v7.4.0 +#### Ohai profiles your system and emits JSON + +Apache 2.0 whitelisted + +Ohai profiles your system and emits JSON + + +### parser v2.2.0.pre.8 +#### A Ruby parser written in pure Ruby. + +MIT whitelisted + +A Ruby parser written in pure Ruby. + + +### plist v3.1.0 +#### All-purpose Property List manipulation library. + +MIT whitelisted + +Plist is a library to manipulate Property List files, also known as plists. It can parse plist files into native Ruby data structures as well as generating new plist files from your Ruby objects. + + + +### polyglot v0.3.5 +#### Augment 'require' to load non-Ruby file types + +MIT whitelisted + + +The Polyglot library allows a Ruby module to register a loader +for the file type associated with a filename extension, and it +augments 'require' to find and load matching files. + + +### powerpack v0.0.9 +#### A few useful extensions to core Ruby classes. + +MIT whitelisted + +A few useful extensions to core Ruby classes. + + +### pry v0.10.1 +#### An IRB alternative and runtime developer console + +MIT whitelisted + +An IRB alternative and runtime developer console + + +### rack v1.5.2 +#### a modular Ruby webserver interface + +MIT whitelisted + +Rack provides a minimal, modular and adaptable interface for developing +web applications in Ruby. By wrapping HTTP requests and responses in +the simplest way possible, it unifies and distills the API for web +servers, web frameworks, and software in between (the so-called +middleware) into a single method call. + +Also see http://rack.github.com/. + + + +### rainbow v2.0.0 +#### Colorize printed text on ANSI terminals + +MIT whitelisted + +Colorize printed text on ANSI terminals + + +### rake v10.3.2 (default) +#### Rake is a Make-like program implemented in Ruby + +MIT whitelisted + +Rake is a Make-like program implemented in Ruby. Tasks and dependencies are +specified in standard Ruby syntax. + +Rake has the following features: + +* Rakefiles (rake's version of Makefiles) are completely defined in + standard Ruby syntax. No XML files to edit. No quirky Makefile + syntax to worry about (is that a tab or a space?) + +* Users can specify tasks with prerequisites. + +* Rake supports rule patterns to synthesize implicit tasks. + +* Flexible FileLists that act like arrays but know about manipulating + file names and paths. + +* A library of prepackaged tasks to make building rakefiles easier. For example, + tasks for building tarballs and publishing to FTP or SSH sites. (Formerly + tasks for building RDoc and Gems were included in rake but they're now + available in RDoc and RubyGems respectively.) + +* Supports parallel execution of tasks. + + +### rb-fsevent v0.9.4 +#### Very simple & usable FSEvents API + +MIT whitelisted + +FSEvents API with Signals catching (without RubyCocoa) + + +### rb-inotify v0.9.5 +#### A Ruby wrapper for Linux's inotify, using FFI + +MIT whitelisted + +A Ruby wrapper for Linux's inotify, using FFI + + +### rest-client v1.6.7 +#### Simple HTTP and REST client for Ruby, inspired by microframework syntax for specifying actions. + +MIT whitelisted + +A simple HTTP and REST client for Ruby, inspired by the Sinatra microframework style of specifying actions: get, put, post, delete. + + +### retryable v1.3.6 +#### Kernel#retryable, allow for retrying of code blocks. + +MIT whitelisted + +Kernel#retryable, allow for retrying of code blocks. + + +### ridley v4.1.0 +#### A reliable Chef API client with a clean syntax + +Apache 2.0 whitelisted + +A reliable Chef API client with a clean syntax + + +### rspec v3.1.0 +#### rspec-3.1.0 + +MIT whitelisted + +BDD for Ruby + + +### rspec-core v3.1.7 +#### rspec-core-3.1.7 + +MIT whitelisted + +BDD for Ruby. RSpec runner and example groups. + + +### rspec-expectations v3.1.2 +#### rspec-expectations-3.1.2 + +MIT whitelisted + +rspec-expectations provides a simple, readable API to express expected outcomes of a code example. + + +### rspec-its v1.1.0 +#### Provides "its" method formally part of rspec-core + +MIT whitelisted + +RSpec extension gem for attribute matching + + +### rspec-mocks v3.1.3 +#### rspec-mocks-3.1.3 + +MIT whitelisted + +RSpec's 'test double' framework, with support for stubbing and mocking + + +### rspec-support v3.1.2 +#### rspec-support-3.1.2 + +MIT whitelisted + +Support utilities for RSpec gems + + +### rubocop v0.27.1 (default) +#### Automatic Ruby code style checking tool. + +MIT whitelisted + + Automatic Ruby code style checking tool. + Aims to enforce the community-driven Ruby Style Guide. + + + +### ruby-progressbar v1.7.0 +#### Ruby/ProgressBar is a flexible text progress bar library for Ruby. + +MIT whitelisted + +Ruby/ProgressBar is an extremely flexible text progress bar library for Ruby. +The output can be customized with a flexible formatting system including: +percentage, bars of various formats, elapsed time and estimated time remaining. + + + +### rufus-lru v1.0.5 +#### A Hash with a max size, controlled by a LRU mechanism + +MIT whitelisted + +LruHash class, a Hash with a max size, controlled by a LRU mechanism + + +### safe_yaml v1.0.4 +#### SameYAML provides an alternative implementation of YAML.load suitable for accepting user input in Ruby applications. + +MIT whitelisted + +Parse YAML safely + + +### sawyer v0.5.5 +#### Secret User Agent of HTTP + +MIT whitelisted + + + +### semverse v1.2.1 +#### An elegant library for representing and comparing SemVer versions and constraints + +Apache 2.0 whitelisted + +An elegant library for representing and comparing SemVer versions and constraints + + +### sequel v4.16.0 +#### The Database Toolkit for Ruby + +MIT whitelisted + +The Database Toolkit for Ruby + + +### serverspec v2.3.1 (default) +#### RSpec tests for your servers configured by Puppet, Chef or anything else + +MIT whitelisted + +RSpec tests for your servers configured by Puppet, Chef or anything else + + +### slop v3.6.0 +#### Simple Lightweight Option Parsing + +MIT whitelisted + +A simple DSL for gathering options and parsing the command line + + +### solve v1.2.1 +#### A Ruby version constraint solver implementing Semantic Versioning 2.0.0-rc.1 + +Apache 2.0 whitelisted + +A Ruby version constraint solver + + +### specinfra v2.5.0 +#### Common layer for serverspec and itamae + +MIT whitelisted + +Common layer for serverspec and itamae + + +### sqlite3 v1.3.10 +#### This module allows Ruby programs to interface with the SQLite3 database engine (http://www.sqlite.org) + +New BSD whitelisted + +This module allows Ruby programs to interface with the SQLite3 +database engine (http://www.sqlite.org). You must have the +SQLite engine installed in order to build this module. + +Note that this module is only compatible with SQLite 3.6.16 or newer. + + +### systemu v2.6.4 +#### systemu + +ruby whitelisted + +universal capture of stdout and stderr and handling of child process pid for windows, *nix, etc. + + +### test-kitchen v1.2.1 (integration) +#### Test Kitchen is an integration tool for developing and testing infrastructure code and software on isolated target platforms. + +Apache 2.0 whitelisted + +Test Kitchen is an integration tool for developing and testing infrastructure code and software on isolated target platforms. + + +### thor v0.19.1 +#### Thor is a toolkit for building powerful command-line interfaces. + +MIT whitelisted + +Thor is a toolkit for building powerful command-line interfaces. + + +### timers v4.0.1 +#### Schedule procs to run after a certain time, or at periodic intervals, using any API that accepts a timeout + +MIT whitelisted + +Pure Ruby one-shot and periodic timers + + +### treetop v1.5.3 +#### A Ruby-based text parsing and interpretation DSL + +MIT whitelisted + + + +### varia_model v0.4.0 +#### A mixin to provide objects with magic attribute reading and writing + +Apache 2.0 whitelisted + +A mixin to provide objects with magic attribute reading and writing + + +### wmi-lite v1.0.0 +#### A lightweight utility library for accessing basic WMI (Windows Management Instrumentation) functionality on Windows + +Apache 2.0 whitelisted + +A lightweight utility over win32ole for accessing basic WMI (Windows Management Instrumentation) functionality in the Microsoft Windows operating system. It has no runtime dependencies other than Ruby, so it can be used without concerns around dependency issues. + + +### xml-simple v1.1.4 +#### A simple API for XML processing. + +ruby whitelisted + + + +### yajl-ruby v1.2.1 +#### Ruby C bindings to the excellent Yajl JSON stream-based parser library. + +MIT whitelisted + diff --git a/cookbooks/redis/doc/license_finder/dependencies_detailed.csv b/cookbooks/redis/doc/license_finder/dependencies_detailed.csv new file mode 100644 index 0000000..b529837 --- /dev/null +++ b/cookbooks/redis/doc/license_finder/dependencies_detailed.csv @@ -0,0 +1,234 @@ +addressable,2.3.6,Apache 2.0,URI Implementation,"Addressable is a replacement for the URI implementation that is part of +Ruby's standard library. It more closely conforms to the relevant RFCs and +adds support for IRIs and URI templates." +ast,2.0.0,MIT,A library for working with Abstract Syntax Trees.,A library for working with Abstract Syntax Trees. +astrolabe,1.3.0,MIT,An object-oriented AST extension for Parser,An object-oriented AST extension for Parser +berkshelf,3.2.1,Apache 2.0,"Manages a Cookbook's, or an Application's, Cookbook dependencies","Manages a Cookbook's, or an Application's, Cookbook dependencies" +berkshelf-api-client,1.2.0,Apache 2.0,API Client for communicating with a Berkshelf API server,API Client for communicating with a Berkshelf API server +buff-config,1.0.1,Apache 2.0,A simple configuration class,A simple configuration class +buff-extensions,1.0.0,Apache 2.0,Extensions to Core Ruby classes,Extensions to Core Ruby classes +buff-ignore,1.1.1,Apache 2.0,A Ruby library for parsing lists of files and applying pattern matching exclusion (such as .gitignore),Parse ignore files with Ruby +buff-ruby_engine,0.1.0,Apache 2.0,Buff up your code with a mixin for querying the platform running Ruby,A mixin for querying the platform running Ruby +buff-shell_out,0.2.0,Apache 2.0,Buff up your code with a mixin for issuing shell commands and collecting the output,A mixin for issuing shell commands and collecting the output +bundler,1.7.6,MIT,"","" +busser,0.6.0,Apache 2.0,Kitchen Busser - Runs tests for projects in test-kitchen,Kitchen Busser - Runs tests for projects in test-kitchen +busser-serverspec,0.5.3,Apache 2.0,A Busser runner plugin for Serverspec,A Busser runner plugin for Serverspec +celluloid,0.16.0,MIT,Actor-based concurrent object framework for Ruby,Celluloid enables people to build concurrent programs out of concurrent objects just as easily as they build sequential programs out of sequential objects +celluloid-io,0.16.1,MIT,Celluloid::IO allows you to monitor multiple IO objects within a Celluloid actor,Evented IO for Celluloid actors +chef,11.16.4,Apache 2.0,"A systems integration framework, built to bring the benefits of configuration management to your entire infrastructure.","A systems integration framework, built to bring the benefits of configuration management to your entire infrastructure." +chef-zero,2.2.1,Apache 2.0,"Self-contained, easy-setup, fast-start in-memory Chef server for testing and solo setup purposes","Self-contained, easy-setup, fast-start in-memory Chef server for testing and solo setup purposes" +chefspec,4.1.1,MIT,Write RSpec examples and generate coverage reports for Chef recipes!,ChefSpec is a unit testing and resource coverage (code coverage) framework for testing Chef cookbooks ChefSpec makes it easy to write examples and get fast feedback on cookbook changes without the need for virtual machines or cloud servers. +cleanroom,1.0.0,Apache 2.0,(More) safely evaluate Ruby DSLs with cleanroom,"Ruby is an excellent programming language for creating and managing custom DSLs, but how can you securely evaluate a DSL while explicitly controlling the methods exposed to the user? Our good friends instance_eval and instance_exec are great, but they expose all methods - public, protected, and private - to the user. Even worse, they expose the ability to accidentally or intentionally alter the behavior of the system! The cleanroom pattern is a safer, more convenient, Ruby-like approach for limiting the information exposed by a DSL while giving users the ability to write awesome code!" +coderay,1.1.0,MIT,Fast syntax highlighting for selected languages.,"Fast and easy syntax highlighting for selected languages, written in Ruby. Comes with RedCloth integration and LOC counter." +dep-selector-libgecode,1.0.2,"MIT,Apache 2.0",Installs a vendored copy of Gecode suitable for use with dep-selector,Installs a vendored copy of Gecode suitable for use with dep-selector +dep_selector,1.0.3,Apache v2,"Given packages, versions, and a dependency graph, find a valid assignment of package versions","Given packages, versions, and a dependency graph, find a valid assignment of package versions" +diff-lcs,1.2.5,"MIT,Perl Artistic v2,GNU GPL v2",Diff::LCS computes the difference between two Enumerable sequences using the McIlroy-Hunt longest common subsequence (LCS) algorithm,"Diff::LCS computes the difference between two Enumerable sequences using the +McIlroy-Hunt longest common subsequence (LCS) algorithm. It includes utilities +to create a simple HTML diff output format and a standard diff-like tool. + +This is release 1.2.4, fixing a bug introduced after diff-lcs 1.1.3 that did +not properly prune common sequences at the beginning of a comparison set. +Thanks to Paul Kunysch for fixing this issue. + +Coincident with the release of diff-lcs 1.2.3, we reported an issue with +Rubinius in 1.9 mode +({rubinius/rubinius#2268}[https://github.com/rubinius/rubinius/issues/2268]). +We are happy to report that this issue has been resolved." +erubis,2.7.0,MIT,a fast and extensible eRuby implementation which supports multi-language,"Erubis is an implementation of eRuby and has the following features: + + * Very fast, almost three times faster than ERB and about 10% faster than eruby. + * Multi-language support (Ruby/PHP/C/Java/Scheme/Perl/Javascript) + * Auto escaping support + * Auto trimming spaces around '<% %>' + * Embedded pattern changeable (default '<% %>') + * Enable to handle Processing Instructions (PI) as embedded pattern (ex. '') + * Context object available and easy to combine eRuby template with YAML datafile + * Print statement available + * Easy to extend and customize in subclass + * Ruby on Rails support" +faraday,0.9.0,MIT,HTTP/REST API client library.,"" +fauxhai,2.2.0,MIT,Fauxhai provides an easy way to mock out your ohai data for testing with chefspec!,Easily mock out ohai data +ffi,1.9.6,BSD,Ruby FFI,Ruby FFI library +ffi-yajl,1.3.0,Apache 2.0,Ruby FFI wrapper around YAJL 2.x,Ruby FFI wrapper around YAJL 2.x +foodcritic,4.0.0,MIT,foodcritic-4.0.0,Lint tool for Opscode Chef cookbooks. +formatador,0.2.5,MIT,Ruby STDOUT text formatting,STDOUT text formatting +gherkin,2.12.2,MIT,gherkin-2.12.2,A fast Gherkin lexer/parser based on the Ragel State Machine Compiler. +guard,2.8.2,MIT,Guard keeps an eye on your file modifications,Guard is a command line tool to easily handle events on file system modifications. +guard-rspec,4.3.1,MIT,Guard gem for RSpec,Guard::RSpec automatically run your specs (much like autotest). +hashie,2.1.2,MIT,Your friendly neighborhood hash library.,Hashie is a collection of classes and mixins that make hashes more powerful. +highline,1.6.21,ruby,HighLine is a high-level command-line IO library.,"A high-level IO library that provides validation, type conversion, and more for +command-line interfaces. HighLine also includes a complete menu system that can +crank out anything from simple list selection to complete shells with just +minutes of work." +hitimes,1.2.2,ISC,"Hitimes is a fast, high resolution timer library for recording performance metrics. It uses the appropriate low method calls for each system to get the highest granularity time increments possible.","Hitimes is a fast, high resolution timer library for recording performance metrics. It uses the appropriate low method calls for each system to get the highest granularity time increments possible. It currently supports any of the following systems: * any system with the POSIX call `clock_gettime()` * Mac OS X * Windows * JRuby Using Hitimes can be faster than using a series of `Time.new` calls, and it will have a much higher granularity. It is definitely faster than using `Process.times`." +httparty,0.13.3,MIT,"Makes http fun! Also, makes consuming restful web services dead easy.","Makes http fun! Also, makes consuming restful web services dead easy." +ipaddress,0.8.0,MIT,IPv4/IPv6 addresses manipulation library,"IPAddress is a Ruby library designed to make manipulation + of IPv4 and IPv6 addresses both powerful and simple. It mantains + a layer of compatibility with Ruby's own IPAddr, while + addressing many of its issues." +json,1.8.1,ruby,This json is bundled with Ruby,"" +kitchen-vagrant,0.15.0,Apache 2.0,Kitchen::Driver::Vagrant - A Vagrant Driver for Test Kitchen.,Kitchen::Driver::Vagrant - A Vagrant Driver for Test Kitchen. +libyajl2,1.2.0,Apache 2.0,Installs a vendored copy of libyajl2 for distributions which lack it,Installs a vendored copy of libyajl2 for distributions which lack it +license_finder,1.2,MIT,Audit the OSS licenses of your application's dependencies.,"LicenseFinder works with your package managers to find + dependencies, detect the licenses of the packages in them, compare + those licenses against a user-defined whitelist, and give you an + actionable exception report." +listen,2.8.0,MIT,Listen to file modifications,The Listen gem listens to file modifications and notifies you about the changes. Works everywhere! +lumberjack,1.0.9,MIT,"A simple, powerful, and very fast logging utility that can be a drop in replacement for Logger or ActiveSupport::BufferedLogger.","A simple, powerful, and very fast logging utility that can be a drop in replacement for Logger or ActiveSupport::BufferedLogger. Provides support for automatically rolling log files even with multiple processes writing the same log file." +method_source,0.8.2,MIT,retrieve the sourcecode for a method,retrieve the sourcecode for a method +mime-types,1.25.1,"MIT,Artistic 2.0,GPL-2",This library allows for the identification of a file's likely MIME content type,"This library allows for the identification of a file's likely MIME content +type. This is release 1.25.1, fixing an issue with priority comparison for +mime-types 1.x. The current release is 2.0, which only supports Ruby 1.9 or +later. + +Release 1.25.1 contains all features of 1.25, including the experimental +caching and lazy loading functionality. The caching and lazy loading features +were initially implemented by Greg Brockman (gdb). As these features are +experimental, they are disabled by default and must be enabled through the use +of environment variables. The cache is invalidated on a per-version basis; the +cache for version 1.25 will not be reused for any later version. + +To use lazy loading, set the environment variable +RUBY_MIME_TYPES_LAZY_LOAD+ +to any value other than 'false'. When using lazy loading, the initial startup +of MIME::Types is around 12–25× faster than normal startup (on my system, +normal startup is about 90 ms; lazy startup is about 4 ms). This isn't +generally useful, however, as the MIME::Types database has not been loaded. +Lazy startup and load is just *slightly* faster—around 1 ms. The real advantage +comes from using the cache. + +To enable the cache, set the environment variable +RUBY_MIME_TYPES_CACHE+ to a +filename where MIME::Types will have read-write access. The first time a new +version of MIME::Types is run using this file, it will be created, taking a +little longer than normal. Subsequent loads using the same cache file will be +approximately 3½× faster (25 ms) than normal loads. This can be combined with ++RUBY_MIME_TYPES_LAZY_LOAD+, but this is *not* recommended in a multithreaded +or multiprocess environment where all threads or processes will be using the +same cache file. + +As the caching interface is still experimental, the only values cached are the +default MIME::Types database, not any custom MIME::Types added by users. + +MIME types are used in MIME-compliant communications, as in e-mail or HTTP +traffic, to indicate the type of content which is transmitted. MIME::Types +provides the ability for detailed information about MIME entities (provided as +a set of MIME::Type objects) to be determined and used programmatically. There +are many types defined by RFCs and vendors, so the list is long but not +complete; don't hesitate to ask to add additional information. This library +follows the IANA collection of MIME types (see below for reference). + +MIME::Types for Ruby was originally based on MIME::Types for Perl by Mark +Overmeer, copyright 2001 - 2009. + +MIME::Types is built to conform to the MIME types of RFCs 2045 and 2231. It +tracks the {IANA registry}[http://www.iana.org/assignments/media-types/] +({ftp}[ftp://ftp.iana.org/assignments/media-types]) with some unofficial types +added from the {LTSW collection}[http://www.ltsw.se/knbase/internet/mime.htp] +and added by the users of MIME::Types." +mini_portile,0.6.1,MIT,Simplistic port-like solution for developers,Simplistic port-like solution for developers. It provides a standard and simplified way to compile against dependency libraries without messing up your system. +minitar,0.5.4,ruby,Provides POSIX tarchive management from Ruby programs.,"Archive::Tar::Minitar is a pure-Ruby library and command-line utility that provides the ability to deal with POSIX tar(1) archive files. The implementation is based heavily on Mauricio Ferna'ndez's implementation in rpa-base, but has been reorganised to promote reuse in other projects. Antoine Toulme forked the original project on rubyforge to place it on github, under http://www.github.com/atoulme/minitar" +mixlib-authentication,1.3.0,Apache 2.0,Mixes in simple per-request authentication,Mixes in simple per-request authentication +mixlib-cli,1.5.0,Apache 2.0,"A simple mixin for CLI interfaces, including option parsing","A simple mixin for CLI interfaces, including option parsing" +mixlib-config,2.1.0,Apache 2.0,A class based configuration library,A class based configuration library +mixlib-log,1.6.0,Apache 2.0,A gem that provides a simple mixin for log functionality,"" +mixlib-shellout,1.6.0,Apache 2.0,Run external commands on Unix or Windows,Run external commands on Unix or Windows +multi_json,1.10.1,MIT,A common interface to multiple JSON libraries.,"A common interface to multiple JSON libraries, including Oj, Yajl, the JSON gem (with C-extensions), the pure-Ruby JSON gem, NSJSONSerialization, gson.rb, JrJackson, and OkJson." +multi_xml,0.5.5,MIT,A generic swappable back-end for XML parsing,"Provides swappable XML backends utilizing LibXML, Nokogiri, Ox, or REXML." +multipart-post,2.0.0,MIT,A multipart form post accessory for Net::HTTP.,"Use with Net::HTTP to do multipart form posts. IO values that have #content_type, #original_filename, and #local_path will be posted as a binary file." +net-http-persistent,2.9.4,MIT,Manages persistent connections using Net::HTTP plus a speed fix for Ruby 1.8,"Manages persistent connections using Net::HTTP plus a speed fix for Ruby 1.8. +It's thread-safe too! + +Using persistent HTTP connections can dramatically increase the speed of HTTP. +Creating a new HTTP connection for every request involves an extra TCP +round-trip and causes TCP congestion avoidance negotiation to start over. + +Net::HTTP supports persistent connections with some API methods but does not +handle reconnection gracefully. Net::HTTP::Persistent supports reconnection +and retry according to RFC 2616." +net-scp,1.2.1,MIT,A pure Ruby implementation of the SCP client protocol,A pure Ruby implementation of the SCP client protocol +net-ssh,2.9.1,MIT,Net::SSH: a pure-Ruby implementation of the SSH2 client protocol.,"Net::SSH: a pure-Ruby implementation of the SSH2 client protocol. It allows you to write programs that invoke and interact with processes on remote servers, via SSH2." +net-ssh-gateway,1.2.0,MIT,A simple library to assist in establishing tunneled Net::SSH connections,A simple library to assist in establishing tunneled Net::SSH connections +net-ssh-multi,1.2.0,MIT,Control multiple Net::SSH connections via a single interface.,Control multiple Net::SSH connections via a single interface. +nio4r,1.0.1,MIT,NIO provides a high performance selector API for monitoring IO objects,New IO for Ruby +nokogiri,1.6.4.1,MIT,"Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser","Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser. Among Nokogiri's +many features is the ability to search documents via XPath or CSS3 selectors. + +XML is like violence - if it doesn’t solve your problems, you are not using +enough of it." +octokit,3.5.2,MIT,Ruby toolkit for working with the GitHub API,Simple wrapper for the GitHub API +ohai,7.4.0,Apache 2.0,Ohai profiles your system and emits JSON,Ohai profiles your system and emits JSON +parser,2.2.0.pre.8,MIT,A Ruby parser written in pure Ruby.,A Ruby parser written in pure Ruby. +plist,3.1.0,MIT,All-purpose Property List manipulation library.,"Plist is a library to manipulate Property List files, also known as plists. It can parse plist files into native Ruby data structures as well as generating new plist files from your Ruby objects." +polyglot,0.3.5,MIT,Augment 'require' to load non-Ruby file types,"The Polyglot library allows a Ruby module to register a loader +for the file type associated with a filename extension, and it +augments 'require' to find and load matching files." +powerpack,0.0.9,MIT,A few useful extensions to core Ruby classes.,A few useful extensions to core Ruby classes. +pry,0.10.1,MIT,An IRB alternative and runtime developer console,An IRB alternative and runtime developer console +rack,1.5.2,MIT,a modular Ruby webserver interface,"Rack provides a minimal, modular and adaptable interface for developing +web applications in Ruby. By wrapping HTTP requests and responses in +the simplest way possible, it unifies and distills the API for web +servers, web frameworks, and software in between (the so-called +middleware) into a single method call. + +Also see http://rack.github.com/." +rainbow,2.0.0,MIT,Colorize printed text on ANSI terminals,Colorize printed text on ANSI terminals +rake,10.3.2,MIT,Rake is a Make-like program implemented in Ruby,"Rake is a Make-like program implemented in Ruby. Tasks and dependencies are +specified in standard Ruby syntax. + +Rake has the following features: + +* Rakefiles (rake's version of Makefiles) are completely defined in + standard Ruby syntax. No XML files to edit. No quirky Makefile + syntax to worry about (is that a tab or a space?) + +* Users can specify tasks with prerequisites. + +* Rake supports rule patterns to synthesize implicit tasks. + +* Flexible FileLists that act like arrays but know about manipulating + file names and paths. + +* A library of prepackaged tasks to make building rakefiles easier. For example, + tasks for building tarballs and publishing to FTP or SSH sites. (Formerly + tasks for building RDoc and Gems were included in rake but they're now + available in RDoc and RubyGems respectively.) + +* Supports parallel execution of tasks." +rb-fsevent,0.9.4,MIT,Very simple & usable FSEvents API,FSEvents API with Signals catching (without RubyCocoa) +rb-inotify,0.9.5,MIT,"A Ruby wrapper for Linux's inotify, using FFI","A Ruby wrapper for Linux's inotify, using FFI" +rest-client,1.6.7,MIT,"Simple HTTP and REST client for Ruby, inspired by microframework syntax for specifying actions.","A simple HTTP and REST client for Ruby, inspired by the Sinatra microframework style of specifying actions: get, put, post, delete." +retryable,1.3.6,MIT,"Kernel#retryable, allow for retrying of code blocks.","Kernel#retryable, allow for retrying of code blocks." +ridley,4.1.0,Apache 2.0,A reliable Chef API client with a clean syntax,A reliable Chef API client with a clean syntax +rspec,3.1.0,MIT,rspec-3.1.0,BDD for Ruby +rspec-core,3.1.7,MIT,rspec-core-3.1.7,BDD for Ruby. RSpec runner and example groups. +rspec-expectations,3.1.2,MIT,rspec-expectations-3.1.2,"rspec-expectations provides a simple, readable API to express expected outcomes of a code example." +rspec-its,1.1.0,MIT,"Provides ""its"" method formally part of rspec-core",RSpec extension gem for attribute matching +rspec-mocks,3.1.3,MIT,rspec-mocks-3.1.3,"RSpec's 'test double' framework, with support for stubbing and mocking" +rspec-support,3.1.2,MIT,rspec-support-3.1.2,Support utilities for RSpec gems +rubocop,0.27.1,MIT,Automatic Ruby code style checking tool.,"Automatic Ruby code style checking tool. + Aims to enforce the community-driven Ruby Style Guide." +ruby-progressbar,1.7.0,MIT,Ruby/ProgressBar is a flexible text progress bar library for Ruby.,"Ruby/ProgressBar is an extremely flexible text progress bar library for Ruby. +The output can be customized with a flexible formatting system including: +percentage, bars of various formats, elapsed time and estimated time remaining." +rufus-lru,1.0.5,MIT,"A Hash with a max size, controlled by a LRU mechanism","LruHash class, a Hash with a max size, controlled by a LRU mechanism" +safe_yaml,1.0.4,MIT,SameYAML provides an alternative implementation of YAML.load suitable for accepting user input in Ruby applications.,Parse YAML safely +sawyer,0.5.5,MIT,Secret User Agent of HTTP,"" +semverse,1.2.1,Apache 2.0,An elegant library for representing and comparing SemVer versions and constraints,An elegant library for representing and comparing SemVer versions and constraints +sequel,4.16.0,MIT,The Database Toolkit for Ruby,The Database Toolkit for Ruby +serverspec,2.3.1,MIT,"RSpec tests for your servers configured by Puppet, Chef or anything else","RSpec tests for your servers configured by Puppet, Chef or anything else" +slop,3.6.0,MIT,Simple Lightweight Option Parsing,A simple DSL for gathering options and parsing the command line +solve,1.2.1,Apache 2.0,A Ruby version constraint solver implementing Semantic Versioning 2.0.0-rc.1,A Ruby version constraint solver +specinfra,2.5.0,MIT,Common layer for serverspec and itamae,Common layer for serverspec and itamae +sqlite3,1.3.10,New BSD,This module allows Ruby programs to interface with the SQLite3 database engine (http://www.sqlite.org),"This module allows Ruby programs to interface with the SQLite3 +database engine (http://www.sqlite.org). You must have the +SQLite engine installed in order to build this module. + +Note that this module is only compatible with SQLite 3.6.16 or newer." +systemu,2.6.4,ruby,systemu,"universal capture of stdout and stderr and handling of child process pid for windows, *nix, etc." +test-kitchen,1.2.1,Apache 2.0,Test Kitchen is an integration tool for developing and testing infrastructure code and software on isolated target platforms.,Test Kitchen is an integration tool for developing and testing infrastructure code and software on isolated target platforms. +thor,0.19.1,MIT,Thor is a toolkit for building powerful command-line interfaces.,Thor is a toolkit for building powerful command-line interfaces. +timers,4.0.1,MIT,"Schedule procs to run after a certain time, or at periodic intervals, using any API that accepts a timeout",Pure Ruby one-shot and periodic timers +treetop,1.5.3,MIT,A Ruby-based text parsing and interpretation DSL,"" +varia_model,0.4.0,Apache 2.0,A mixin to provide objects with magic attribute reading and writing,A mixin to provide objects with magic attribute reading and writing +wmi-lite,1.0.0,Apache 2.0,A lightweight utility library for accessing basic WMI (Windows Management Instrumentation) functionality on Windows,"A lightweight utility over win32ole for accessing basic WMI (Windows Management Instrumentation) functionality in the Microsoft Windows operating system. It has no runtime dependencies other than Ruby, so it can be used without concerns around dependency issues." +xml-simple,1.1.4,ruby,A simple API for XML processing.,"" +yajl-ruby,1.2.1,MIT,Ruby C bindings to the excellent Yajl JSON stream-based parser library.,"" diff --git a/cookbooks/redis/files/default/tests/minitest/client_test.rb b/cookbooks/redis/files/default/tests/minitest/client_test.rb new file mode 100644 index 0000000..8295e75 --- /dev/null +++ b/cookbooks/redis/files/default/tests/minitest/client_test.rb @@ -0,0 +1,7 @@ +require_relative "test_helper" + +describe_recipe "redis::client" do + it "installed the `redis-tools` package" do + package("redis-tools").must_be_installed + end +end diff --git a/cookbooks/redis/files/default/tests/minitest/default_test.rb b/cookbooks/redis/files/default/tests/minitest/default_test.rb new file mode 100644 index 0000000..7a8d743 --- /dev/null +++ b/cookbooks/redis/files/default/tests/minitest/default_test.rb @@ -0,0 +1,19 @@ +require_relative "test_helper" + +describe_recipe "redis::default" do + let(:apt_path) do + "/etc/apt/sources.list.d" + end + + it "set up an apt repository" do + repo = { + "debian" => { name: "dotdeb", content: "dotdeb" }, + "ubuntu" => { name: "chris-lea-redis-server", content: "chris-lea" } + }[node["platform"]] + + apt_file = "#{apt_path}/#{repo[:name]}.list" + + file(apt_file).must_exist + file(apt_file).must_include repo[:content] + end +end diff --git a/cookbooks/redis/files/default/tests/minitest/server_test.rb b/cookbooks/redis/files/default/tests/minitest/server_test.rb new file mode 100644 index 0000000..d6a085b --- /dev/null +++ b/cookbooks/redis/files/default/tests/minitest/server_test.rb @@ -0,0 +1,48 @@ +require_relative "test_helper" + +describe_recipe "redis::server" do + it "installed the `redis-server` package" do + package("redis-server").must_be_installed + end + + it "enabled the `redis-server` service" do + service("redis-server").must_be_enabled + end + + it "started the `redis-server` service" do + service("redis-server").must_be_running + end + + describe "data directory" do + let(:dir) do + directory node["redis"]["dir"] + end + + it { dir.must_exist } + it { dir.must_have :owner, "redis" } + it { dir.must_have :group, "redis" } + it { dir.must_have :mode, "750" } + end + + describe "redis.conf" do + let(:conf) do + file "/etc/redis/redis.conf" + end + + it { conf.must_exist } + it { conf.must_have :owner, "root" } + it { conf.must_have :group, "root" } + it { conf.must_have :mode, "644" } + end + + describe "`default` file" do + let(:default) do + file "/etc/default/redis-server" + end + + it { default.must_exist } + it { default.must_have :owner, "root" } + it { default.must_have :group, "root" } + it { default.must_have :mode, "644" } + end +end diff --git a/cookbooks/redis/files/default/tests/minitest/test_helper.rb b/cookbooks/redis/files/default/tests/minitest/test_helper.rb new file mode 100644 index 0000000..2b82ba7 --- /dev/null +++ b/cookbooks/redis/files/default/tests/minitest/test_helper.rb @@ -0,0 +1,5 @@ +require "minitest/spec" + +include MiniTest::Chef::Assertions +include MiniTest::Chef::Context +include MiniTest::Chef::Resources diff --git a/cookbooks/redis/metadata.json b/cookbooks/redis/metadata.json new file mode 100644 index 0000000..bf66c4d --- /dev/null +++ b/cookbooks/redis/metadata.json @@ -0,0 +1,36 @@ +{ + "name": "redis", + "description": "Installs and configures Redis", + "long_description": "", + "maintainer": "Phil Cohen", + "maintainer_email": "github@phlippers.net", + "license": "MIT", + "platforms": { + "debian": ">= 0.0.0", + "ubuntu": ">= 0.0.0" + }, + "dependencies": { + "apt": ">= 0.0.0" + }, + "providing": { + + }, + "recipes": { + "redis::default": "Sets up ppa apt repository", + "redis::server": "Installs redis server", + "redis::client": "Installs redis client" + }, + "version": "0.5.6", + "source_url": "", + "issues_url": "", + "privacy": false, + "chef_versions": [ + + ], + "ohai_versions": [ + + ], + "gems": [ + + ] +} diff --git a/cookbooks/redis/metadata.rb b/cookbooks/redis/metadata.rb new file mode 100644 index 0000000..d67a2c7 --- /dev/null +++ b/cookbooks/redis/metadata.rb @@ -0,0 +1,15 @@ +name "redis" +maintainer "Phil Cohen" +maintainer_email "github@phlippers.net" +license "MIT" +description "Installs and configures Redis" +version "0.5.6" + +recipe "redis::default", "Sets up ppa apt repository" +recipe "redis::server", "Installs redis server" +recipe "redis::client", "Installs redis client" + +supports "debian" +supports "ubuntu" + +depends "apt" diff --git a/cookbooks/redis/recipes/client.rb b/cookbooks/redis/recipes/client.rb new file mode 100644 index 0000000..f80ac1e --- /dev/null +++ b/cookbooks/redis/recipes/client.rb @@ -0,0 +1,10 @@ +# +# Cookbook Name:: redis +# Recipe:: client +# + +include_recipe "redis::default" + +package "redis-tools" do + action node["redis"]["auto_upgrade"] ? :upgrade : :install +end diff --git a/cookbooks/redis/recipes/default.rb b/cookbooks/redis/recipes/default.rb new file mode 100644 index 0000000..496ec29 --- /dev/null +++ b/cookbooks/redis/recipes/default.rb @@ -0,0 +1,11 @@ +# +# Cookbook Name:: redis +# Recipe:: default +# +apt_repository node["redis"]["apt_repository"] do + uri node["redis"]["apt_uri"] + distribution node["redis"]["apt_distribution"] + components node["redis"]["apt_components"] + keyserver node["redis"]["apt_keyserver"] + key node["redis"]["apt_key"] +end diff --git a/cookbooks/redis/recipes/server.rb b/cookbooks/redis/recipes/server.rb new file mode 100644 index 0000000..7d22d4b --- /dev/null +++ b/cookbooks/redis/recipes/server.rb @@ -0,0 +1,38 @@ +# +# Cookbook Name:: redis +# Recipe:: server +# + +include_recipe "redis::default" + +package "redis-server" do + action node["redis"]["auto_upgrade"] ? :upgrade : :install +end + +directory node["redis"]["dir"] do + owner "redis" + group "redis" + mode "0750" + recursive true +end + +service "redis-server" do + supports restart: true + action [:enable, :start] +end + +template "/etc/redis/redis.conf" do + source "redis.conf.erb" + owner "root" + group "root" + mode "0644" + notifies :restart, "service[redis-server]" +end + +template "/etc/default/redis-server" do + source "default_redis-server.erb" + owner "root" + group "root" + mode "0644" + notifies :restart, "service[redis-server]" +end diff --git a/cookbooks/redis/spec/client_spec.rb b/cookbooks/redis/spec/client_spec.rb new file mode 100644 index 0000000..fda98a4 --- /dev/null +++ b/cookbooks/redis/spec/client_spec.rb @@ -0,0 +1,27 @@ +require "spec_helper" + +describe "redis::client" do + let(:chef_run) do + ChefSpec::SoloRunner.new.converge(described_recipe) + end + + it { expect(chef_run).to include_recipe("redis::default") } + + describe "package installation" do + describe "default action" do + it { expect(chef_run).to install_package("redis-tools") } + it { expect(chef_run).to_not upgrade_package("redis-tools") } + end + + describe "when `auto_upgrade` is `true`" do + let(:chef_run) do + ChefSpec::SoloRunner.new do |node| + node.set["redis"]["auto_upgrade"] = true + end.converge(described_recipe) + end + + it { expect(chef_run).to_not install_package("redis-tools") } + it { expect(chef_run).to upgrade_package("redis-tools") } + end + end +end diff --git a/cookbooks/redis/spec/default_spec.rb b/cookbooks/redis/spec/default_spec.rb new file mode 100644 index 0000000..e228887 --- /dev/null +++ b/cookbooks/redis/spec/default_spec.rb @@ -0,0 +1,19 @@ +require "spec_helper" + +describe "redis::default" do + let(:chef_run) do + ChefSpec::SoloRunner.new.converge(described_recipe) + end + + it { expect(chef_run).to add_apt_repository("chris-lea-redis-server") } + + # debian family setup + context "using debian platform" do + let(:chef_run) do + env_options = { platform: "debian", version: "6.0.5" } + ChefSpec::SoloRunner.new(env_options).converge(described_recipe) + end + + it { expect(chef_run).to add_apt_repository("dotdeb") } + end +end diff --git a/cookbooks/redis/spec/server_spec.rb b/cookbooks/redis/spec/server_spec.rb new file mode 100644 index 0000000..7e0dfd3 --- /dev/null +++ b/cookbooks/redis/spec/server_spec.rb @@ -0,0 +1,69 @@ +require "spec_helper" + +describe "redis::server" do + let(:chef_run) do + ChefSpec::SoloRunner.new.converge(described_recipe) + end + + it { expect(chef_run).to include_recipe("redis::default") } + + describe "package installation" do + describe "default action" do + it { expect(chef_run).to install_package("redis-server") } + it { expect(chef_run).to_not upgrade_package("redis-server") } + end + + describe "when `auto_upgrade` is `true`" do + let(:chef_run) do + ChefSpec::SoloRunner.new do |node| + node.set["redis"]["auto_upgrade"] = true + end.converge(described_recipe) + end + + it { expect(chef_run).to_not install_package("redis-server") } + it { expect(chef_run).to upgrade_package("redis-server") } + end + end + + it "creates the data directory" do + expect(chef_run).to create_directory("/var/lib/redis").with( + owner: "redis", + group: "redis", + mode: "0750", + recursive: true + ) + end + + it { expect(chef_run).to enable_service("redis-server") } + it { expect(chef_run).to start_service("redis-server") } + + it "creates `/etc/redis/redis.conf`" do + path = "/etc/redis/redis.conf" + + expect(chef_run).to create_template(path).with( + source: "redis.conf.erb", + owner: "root", + group: "root", + mode: "0644" + ) + + expect(chef_run.template(path)).to( + notify("service[redis-server]").to(:restart) + ) + end + + it "creates `/etc/default/redis-server`" do + path = "/etc/default/redis-server" + + expect(chef_run).to create_template(path).with( + source: "default_redis-server.erb", + owner: "root", + group: "root", + mode: "0644" + ) + + expect(chef_run.template(path)).to( + notify("service[redis-server]").to(:restart) + ) + end +end diff --git a/cookbooks/redis/spec/spec_helper.rb b/cookbooks/redis/spec/spec_helper.rb new file mode 100644 index 0000000..75a73c8 --- /dev/null +++ b/cookbooks/redis/spec/spec_helper.rb @@ -0,0 +1,20 @@ +begin + require "chefspec" + require "chefspec/berkshelf" +rescue LoadError + puts "Unable to run `chefspec`" + exit +end + +RSpec.configure do |config| + config.platform = "ubuntu" + config.version = "12.04" + config.log_level = :error + config.raise_errors_for_deprecations! +end + +def add_apt_repository(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:apt_repository, :add, resource_name) +end + +at_exit { ChefSpec::Coverage.report! } diff --git a/cookbooks/redis/templates/default/default_redis-server.erb b/cookbooks/redis/templates/default/default_redis-server.erb new file mode 100644 index 0000000..9a24ec7 --- /dev/null +++ b/cookbooks/redis/templates/default/default_redis-server.erb @@ -0,0 +1,12 @@ +# redis-server configure options + +# ULIMIT: Call ulimit -n with this argument prior to invoking Redis itself. +# This may be required for high-concurrency environments. Redis itself cannot +# alter its limits as it is not being run as root. (default: do not call +# ulimit) +# +<% if node["redis"]["ulimit"] && !node["redis"]["ulimit"].empty? %> +ULIMIT=<%= node["redis"]["ulimit"] %> +<% else %> +# ULIMIT=65536 +<% end %> diff --git a/cookbooks/redis/templates/default/redis.conf.erb b/cookbooks/redis/templates/default/redis.conf.erb new file mode 100644 index 0000000..474e881 --- /dev/null +++ b/cookbooks/redis/templates/default/redis.conf.erb @@ -0,0 +1,556 @@ +# Redis configuration file example + +# Note on units: when memory size is needed, it is possible to specifiy +# it in the usual form of 1k 5GB 4M and so forth: +# +# 1k => 1000 bytes +# 1kb => 1024 bytes +# 1m => 1000000 bytes +# 1mb => 1024*1024 bytes +# 1g => 1000000000 bytes +# 1gb => 1024*1024*1024 bytes +# +# units are case insensitive so 1GB 1Gb 1gB are all the same. + +# By default Redis does not run as a daemon. Use 'yes' if you need it. +# Note that Redis will write a pid file in /var/run/redis.pid when daemonized. +daemonize <%= node["redis"]["daemonize"] %> + +# When running daemonized, Redis writes a pid file in /var/run/redis.pid by +# default. You can specify a custom pid file location here. +pidfile <%= node["redis"]["pidfile"] %> + +# Accept connections on the specified port, default is 6379. +# If port 0 is specified Redis will not listen on a TCP socket. +port <%= node["redis"]["port"] %> + +# If you want you can bind a single interface, if the bind option is not +# specified all the interfaces will listen for incoming connections. +# +<% unless node["redis"]["bind"].empty? %> +bind <%= node["redis"]["bind"] %> +<% end %> + +# Specify the path for the unix socket that will be used to listen for +# incoming connections. There is no default, so Redis will not listen +# on a unix socket when not specified. +# +<% unless node["redis"]["unixsocket"].empty? %> +unixsocket <%= node["redis"]["unixsocket"] %> +unixsocketperm <%= node["redis"]["unixsocketperm"] %> +<% end %> + +# Close the connection after a client is idle for N seconds (0 to disable) +timeout <%= node["redis"]["timeout"] %> + +# Set server verbosity to 'debug' +# it can be one of: +# debug (a lot of information, useful for development/testing) +# verbose (many rarely useful info, but not a mess like the debug level) +# notice (moderately verbose, what you want in production probably) +# warning (only very important / critical messages are logged) +loglevel <%= node["redis"]["loglevel"] %> + +# Specify the log file name. Also 'stdout' can be used to force +# Redis to log on the standard output. Note that if you use standard +# output for logging but daemonize, logs will be sent to /dev/null +logfile <%= node["redis"]["logfile"] %> + +# To enable logging to the system logger, just set 'syslog-enabled' to yes, +# and optionally update the other syslog parameters to suit your needs. +syslog-enabled <%= node["redis"]["syslog_enabled"] %> + +<% if node["redis"]["syslog_enabled"] == "yes" %> +# Specify the syslog identity. +syslog-ident <%= node["redis"]["syslog_ident"] %> + +# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7. +syslog-facility <%= node["redis"]["syslog_facility"] %> +<% end %> + +# Set the number of databases. The default database is DB 0, you can select +# a different one on a per-connection basis using SELECT where +# dbid is a number between 0 and 'databases'-1 +databases <%= node["redis"]["databases"] %> + +################################ SNAPSHOTTING ################################# +# +# Save the DB on disk: +# +# save +# +# Will save the DB if both the given number of seconds and the given +# number of write operations against the DB occurred. +# +# In the example below the behaviour will be to save: +# after 900 sec (15 min) if at least 1 key changed +# after 300 sec (5 min) if at least 10 keys changed +# after 60 sec if at least 10000 keys changed +# +# Note: you can disable saving at all commenting all the "save" lines. +# +# It is also possible to remove all the previously configured save +# points by adding a save directive with a single empty string argument +# like in the following example: +# +# save "" + +<% node["redis"]["snapshots"].each do |interval, keys| %> +save <%= "#{interval} #{keys}" %> +<% end %> + +# By default Redis will stop accepting writes if RDB snapshots are enabled +# (at least one save point) and the latest background save failed. +# This will make the user aware (in an hard way) that data is not persisting +# on disk properly, otherwise chances are that no one will notice and some +# distater will happen. +# +# If the background saving process will start working again Redis will +# automatically allow writes again. +# +# However if you have setup your proper monitoring of the Redis server +# and persistence, you may want to disable this feature so that Redis will +# continue to work as usually even if there are problems with disk, +# permissions, and so forth. +stop-writes-on-bgsave-error <%= node["redis"]["stop_writes_on_bgsave_error"] %> + +# Compress string objects using LZF when dump .rdb databases? +# For default that's set to 'yes' as it's almost always a win. +# If you want to save some CPU in the saving child set it to 'no' but +# the dataset will likely be bigger if you have compressible values or keys. +rdbcompression <%= node["redis"]["rdbcompression"] %> + +# Since verison 5 of RDB a CRC64 checksum is placed at the end of the file. +# This makes the format more resistant to corruption but there is a performance +# hit to pay (around 10%) when saving and loading RDB files, so you can disable it +# for maximum performances. +# +# RDB files created with checksum disabled have a checksum of zero that will +# tell the loading code to skip the check. +rdbchecksum <%= node["redis"]["rdbchecksum"] %> + +# The filename where to dump the DB +dbfilename <%= node["redis"]["dbfilename"] %> + +# The working directory. +# +# The DB will be written inside this directory, with the filename specified +# above using the 'dbfilename' configuration directive. +# +# Also the Append Only File will be created inside this directory. +# +# Note that you must specify a directory here, not a file name. +dir <%= node["redis"]["dir"] %> + +################################# REPLICATION ################################# + +# Master-Slave replication. Use slaveof to make a Redis instance a copy of +# another Redis server. Note that the configuration is local to the slave +# so for example it is possible to configure the slave to save the DB with a +# different interval, or to listen to another port, and so on. +# +# slaveof +<% if node["redis"]["slaveof"] && !node["redis"]["slaveof"].empty? %> +slaveof <%= node["redis"]["slaveof"] %> +<% end %> + +# If the master is password protected (using the "requirepass" configuration +# directive below) it is possible to tell the slave to authenticate before +# starting the replication synchronization process, otherwise the master will +# refuse the slave request. +# +# masterauth +<% if node["redis"]["masterauth"] && !node["redis"]["masterauth"].empty? %> +masterauth <%= node["redis"]["masterauth"] %> +<% end %> + +# When a slave lost the connection with the master, or when the replication +# is still in progress, the slave can act in two different ways: +# +# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will +# still reply to client requests, possibly with out of data data, or the +# data set may just be empty if this is the first synchronization. +# +# 2) if slave-serve-stale data is set to 'no' the slave will reply with +# an error "SYNC with master in progress" to all the kind of commands +# but to INFO and SLAVEOF. +# +slave-serve-stale-data <%= node["redis"]["slave_serve_stale_data"] %> + +# You can configure a slave instance to accept writes or not. Writing against +# a slave instance may be useful to store some ephemeral data (because data +# written on a slave will be easily deleted after resync with the master) but +# may also cause problems if clients are writing to it because of a +# misconfiguration. +# +# Since Redis 2.6 by default slaves are read-only. +# +# Note: read only slaves are not designed to be exposed to untrusted clients +# on the internet. It's just a protection layer against misuse of the instance. +# Still a read only slave exports by default all the administrative commands +# such as CONFIG, DEBUG, and so forth. To a limited extend you can improve +# security of read only slaves using 'rename-command' to shadow all the +# administrative / dangerous commands. +slave-read-only <%= node["redis"]["slave_read_only"] %> + +# Slaves send PINGs to server in a predefined interval. It's possible to change +# this interval with the repl_ping_slave_period option. The default value is 10 +# seconds. +# +repl-ping-slave-period <%= node["redis"]["repl_ping_slave_period"] %> + +# The following option sets a timeout for both Bulk transfer I/O timeout and +# master data or ping response timeout. The default value is 60 seconds. +# +# It is important to make sure that this value is greater than the value +# specified for repl-ping-slave-period otherwise a timeout will be detected +# every time there is low traffic between the master and the slave. +# +repl-timeout <%= node["redis"]["repl_timeout"] %> + +# The slave priority is an integer number published by Redis in the INFO output. +# It is used by Redis Sentinel in order to select a slave to promote into a +# master if the master is no longer working correctly. +# +# A slave with a low priority number is considered better for promotion, so +# for instance if there are three slaves with priority 10, 100, 25 Sentinel will +# pick the one wtih priority 10, that is the lowest. +# +# However a special priority of 0 marks the slave as not able to perform the +# role of master, so a slave with priority of 0 will never be selected by +# Redis Sentinel for promotion. +# +# By default the priority is 100. +slave-priority <%= node["redis"]["slave_priority"] %> + +################################## SECURITY ################################### + +# Require clients to issue AUTH before processing any other +# commands. This might be useful in environments in which you do not trust +# others with access to the host running redis-server. +# +# This should stay commented out for backward compatibility and because most +# people do not need auth (e.g. they run their own servers). +# +# Warning: since Redis is pretty fast an outside user can try up to +# 150k passwords per second against a good box. This means that you should +# use a very strong password otherwise it will be very easy to break. +# +# requirepass foobared +<% if node["redis"]["requirepass"] && !node["redis"]["requirepass"].empty? %> +requirepass <%= node["redis"]["requirepass"] %> +<% end %> + +# Command renaming. +# +# It is possilbe to change the name of dangerous commands in a shared +# environment. For instance the CONFIG command may be renamed into something +# of hard to guess so that it will be still available for internal-use +# tools but not available for general clients. +# +# Example: +# +# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52 +# +# It is also possilbe to completely kill a command renaming it into +# an empty string: +# +# rename-command CONFIG "" +<% node["redis"]["rename_commands"].each do |command| %> +rename-command <%= command %> +<% end %> + +################################### LIMITS #################################### + +# Set the max number of connected clients at the same time. By default there +# is no limit, and it's up to the number of file descriptors the Redis process +# is able to open. The special value '0' means no limits. +# Once the limit is reached Redis will close all the new connections sending +# an error 'max number of clients reached'. +# +maxclients <%= node["redis"]["maxclients"] %> + +# Don't use more memory than the specified amount of bytes. +# When the memory limit is reached Redis will try to remove keys +# accordingly to the eviction policy selected (see maxmemmory-policy). +# +# If Redis can't remove keys according to the policy, or if the policy is +# set to 'noeviction', Redis will start to reply with errors to commands +# that would use more memory, like SET, LPUSH, and so on, and will continue +# to reply to read-only commands like GET. +# +# This option is usually useful when using Redis as an LRU cache, or to set +# an hard memory limit for an instance (using the 'noeviction' policy). +# +# WARNING: If you have slaves attached to an instance with maxmemory on, +# the size of the output buffers needed to feed the slaves are subtracted +# from the used memory count, so that network problems / resyncs will +# not trigger a loop where keys are evicted, and in turn the output +# buffer of slaves is full with DELs of keys evicted triggering the deletion +# of more keys, and so forth until the database is completely emptied. +# +# In short... if you have slaves attached it is suggested that you set a lower +# limit for maxmemory so that there is some free RAM on the system for slave +# output buffers (but this is not needed if the policy is 'noeviction'). +# +maxmemory <%= node["redis"]["maxmemory"] %> + +# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory +# is reached? You can select among five behavior: +# +# volatile-lru -> remove the key with an expire set using an LRU algorithm +# allkeys-lru -> remove any key accordingly to the LRU algorithm +# volatile-random -> remove a random key with an expire set +# allkeys->random -> remove a random key, any key +# volatile-ttl -> remove the key with the nearest expire time (minor TTL) +# noeviction -> don't expire at all, just return an error on write operations +# +# Note: with all the kind of policies, Redis will return an error on write +# operations, when there are not suitable keys for eviction. +# +# At the date of writing this commands are: set setnx setex append +# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd +# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby +# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby +# getset mset msetnx exec sort +# +# The default is: +# +# maxmemory-policy volatile-lru +maxmemory-policy <%= node["redis"]["maxmemory_policy"] %> + +# LRU and minimal TTL algorithms are not precise algorithms but approximated +# algorithms (in order to save memory), so you can select as well the sample +# size to check. For instance for default Redis will check three keys and +# pick the one that was used less recently, you can change the sample size +# using the following configuration directive. +# +# maxmemory-samples 3 +maxmemory-samples <%= node["redis"]["maxmemory_samples"] %> + +############################## APPEND ONLY MODE ############################### + +# By default Redis asynchronously dumps the dataset on disk. If you can live +# with the idea that the latest records will be lost if something like a crash +# happens this is the preferred way to run Redis. If instead you care a lot +# about your data and don't want to that a single record can get lost you should +# enable the append only mode: when this mode is enabled Redis will append +# every write operation received in the file appendonly.aof. This file will +# be read on startup in order to rebuild the full dataset in memory. +# +# Note that you can have both the async dumps and the append only file if you +# like (you have to comment the "save" statements above to disable the dumps). +# Still if append only mode is enabled Redis will load the data from the +# log file at startup ignoring the dump.rdb file. +# +# IMPORTANT: Check the BGREWRITEAOF to check how to rewrite the append +# log file in background when it gets too big. + +appendonly <%= node["redis"]["appendonly"] %> + +# The name of the append only file (default: "appendonly.aof") +appendfilename <%= node["redis"]["appendfilename"] %> + +# The fsync() call tells the Operating System to actually write data on disk +# instead to wait for more data in the output buffer. Some OS will really flush +# data on disk, some other OS will just try to do it ASAP. +# +# Redis supports three different modes: +# +# no: don't fsync, just let the OS flush the data when it wants. Faster. +# always: fsync after every write to the append only log . Slow, Safest. +# everysec: fsync only if one second passed since the last fsync. Compromise. +# +# The default is "everysec" that's usually the right compromise between +# speed and data safety. It's up to you to understand if you can relax this to +# "no" that will will let the operating system flush the output buffer when +# it wants, for better performances (but if you can live with the idea of +# some data loss consider the default persistence mode that's snapshotting), +# or on the contrary, use "always" that's very slow but a bit safer than +# everysec. +# +# If unsure, use "everysec". + +# appendfsync always +appendfsync <%= node["redis"]["appendfsync"] %> +# appendfsync no + +# When the AOF fsync policy is set to always or everysec, and a background +# saving process (a background save or AOF log background rewriting) is +# performing a lot of I/O against the disk, in some Linux configurations +# Redis may block too long on the fsync() call. Note that there is no fix for +# this currently, as even performing fsync in a different thread will block +# our synchronous write(2) call. +# +# In order to mitigate this problem it's possible to use the following option +# that will prevent fsync() from being called in the main process while a +# BGSAVE or BGREWRITEAOF is in progress. +# +# This means that while another child is saving the durability of Redis is +# the same as "appendfsync none", that in pratical terms means that it is +# possible to lost up to 30 seconds of log in the worst scenario (with the +# default Linux settings). +# +# If you have latency problems turn this to "yes". Otherwise leave it as +# "no" that is the safest pick from the point of view of durability. +no-appendfsync-on-rewrite <%= node["redis"]["no_appendfsync_on_rewrite"] %> + +# Automatic rewrite of the append only file. +# Redis is able to automatically rewrite the log file implicitly calling +# BGREWRITEAOF when the AOF log size will growth by the specified percentage. +# +# This is how it works: Redis remembers the size of the AOF file after the +# latest rewrite (or if no rewrite happened since the restart, the size of +# the AOF at startup is used). +# +# This base size is compared to the current size. If the current size is +# bigger than the specified percentage, the rewrite is triggered. Also +# you need to specify a minimal size for the AOF file to be rewritten, this +# is useful to avoid rewriting the AOF file even if the percentage increase +# is reached but it is still pretty small. +# +# Specify a precentage of zero in order to disable the automatic AOF +# rewrite feature. + +auto-aof-rewrite-percentage <%= node["redis"]["auto_aof_rewrite_percentage"] %> +auto-aof-rewrite-min-size <%= node["redis"]["auto_aof_rewrite_min_size"] %> + +################################ LUA SCRIPTING ############################### + +# Max execution time of a Lua script in milliseconds. +# +# If the maximum execution time is reached Redis will log that a script is +# still in execution after the maximum allowed time and will start to +# reply to queries with an error. +# +# When a long running script exceed the maximum execution time only the +# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be +# used to stop a script that did not yet called write commands. The second +# is the only way to shut down the server in the case a write commands was +# already issue by the script but the user don't want to wait for the natural +# termination of the script. +# +# Set it to 0 or a negative value for unlimited execution without warnings. +lua-time-limit <%= node["redis"]["lua_time_limit"] %> + +################################## SLOW LOG ################################### + +# The Redis Slow Log is a system to log queries that exceeded a specified +# execution time. The execution time does not include the I/O operations +# like talking with the client, sending the reply and so forth, +# but just the time needed to actually execute the command (this is the only +# stage of command execution where the thread is blocked and can not serve +# other requests in the meantime). +# +# You can configure the slow log with two parameters: one tells Redis +# what is the execution time, in microseconds, to exceed in order for the +# command to get logged, and the other parameter is the length of the +# slow log. When a new command is logged the oldest one is removed from the +# queue of logged commands. + +# The following time is expressed in microseconds, so 1000000 is equivalent +# to one second. Note that a negative number disables the slow log, while +# a value of zero forces the logging of every command. +slowlog-log-slower-than <%= node["redis"]["slowlog_log_slower_than"] %> + +# There is no limit to this length. Just be aware that it will consume memory. +# You can reclaim memory used by the slow log with SLOWLOG RESET. +slowlog-max-len <%= node["redis"]["slowlog_max_len"] %> + + +############################### ADVANCED CONFIG ############################### + +# Hashes are encoded using a memory efficient data structure when they have a +# small number of entries, and the biggest entry does not exceed a given +# threshold. These thresholds can be configured using the following directives. +hash-max-ziplist-entries <%= node["redis"]["hash_max_ziplist_entries"] %> +hash-max-ziplist-value <%= node["redis"]["hash_max_ziplist_value"] %> + +# Similarly to hashes, small lists are also encoded in a special way in order +# to save a lot of space. The special representation is only used when +# you are under the following limits: +list-max-ziplist-entries <%= node["redis"]["list_max_ziplist_entries"] %> +list-max-ziplist-value <%= node["redis"]["list_max_ziplist_value"] %> + +# Sets have a special encoding in just one case: when a set is composed +# of just strings that happens to be integers in radix 10 in the range +# of 64 bit signed integers. +# The following configuration setting sets the limit in the size of the +# set in order to use this special memory saving encoding. +set-max-intset-entries <%= node["redis"]["set_max_intset_entries"] %> + +# Similarly to hashes and lists, sorted sets are also specially encoded in +# order to save a lot of space. This encoding is only used when the length and +# elements of a sorted set are below the following limits: +zset-max-ziplist-entries <%= node["redis"]["zset_max_ziplist_entries"] %> +zset-max-ziplist-value <%= node["redis"]["zset_max_ziplist_value"] %> + +# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in +# order to help rehashing the main Redis hash table (the one mapping top-level +# keys to values). The hash table implementation redis uses (see dict.c) +# performs a lazy rehashing: the more operation you run into an hash table +# that is rhashing, the more rehashing "steps" are performed, so if the +# server is idle the rehashing is never complete and some more memory is used +# by the hash table. +# +# The default is to use this millisecond 10 times every second in order to +# active rehashing the main dictionaries, freeing memory when possible. +# +# If unsure: +# use "activerehashing no" if you have hard latency requirements and it is +# not a good thing in your environment that Redis can reply form time to time +# to queries with 2 milliseconds delay. +# +# use "activerehashing yes" if you don't have such hard requirements but +# want to free memory asap when possible. +activerehashing <%= node["redis"]["activerehashing"] %> + +# The client output buffer limits can be used to force disconnection of clients +# that are not reading data from the server fast enough for some reason (a +# common reason is that a Pub/Sub client can't consume messages as fast as the +# publisher can produce them). +# +# The limit can be set differently for the three different classes of clients: +# +# normal -> normal clients +# slave -> slave clients and MONITOR clients +# pubsub -> clients subcribed to at least one pubsub channel or pattern +# +# The syntax of every client-output-buffer-limit directive is the following: +# +# client-output-buffer-limit +# +# A client is immediately disconnected once the hard limit is reached, or if +# the soft limit is reached and remains reached for the specified number of +# seconds (continuously). +# So for instance if the hard limit is 32 megabytes and the soft limit is +# 16 megabytes / 10 seconds, the client will get disconnected immediately +# if the size of the output buffers reach 32 megabytes, but will also get +# disconnected if the client reaches 16 megabytes and continuously overcomes +# the limit for 10 seconds. +# +# By default normal clients are not limited because they don't receive data +# without asking (in a push way), but just after a request, so only +# asynchronous clients may create a scenario where data is requested faster +# than it can read. +# +# Instead there is a default limit for pubsub and slave clients, since +# subscribers and slaves receive data in a push fashion. +# +# Both the hard or the soft limit can be disabled just setting it to zero. +client-output-buffer-limit normal <%= node["redis"]["client_output_buffer_limit"]["normal"] %> +client-output-buffer-limit slave <%= node["redis"]["client_output_buffer_limit"]["slave"] %> +client-output-buffer-limit pubsub <%= node["redis"]["client_output_buffer_limit"]["pubsub"] %> + +################################## INCLUDES ################################### + +# Include one or more other config files here. This is useful if you +# have a standard template that goes to all redis server but also need +# to customize a few per-server settings. Include files can include +# other files, so use this wisely. +# +# include /path/to/local.conf +# include /path/to/other.conf +<% node["redis"]["include_config_files"].each do |file| %> +include <%= file %> +<% end %> diff --git a/cookbooks/redis/test/.chef/knife.rb b/cookbooks/redis/test/.chef/knife.rb new file mode 100644 index 0000000..a0fd5a0 --- /dev/null +++ b/cookbooks/redis/test/.chef/knife.rb @@ -0,0 +1,2 @@ +cache_type "BasicFile" +cache_options(path: "#{ENV["HOME"]}/.chef/checksums") diff --git a/cookbooks/redis/test/integration/default/serverspec/default_spec.rb b/cookbooks/redis/test/integration/default/serverspec/default_spec.rb new file mode 100644 index 0000000..395eddf --- /dev/null +++ b/cookbooks/redis/test/integration/default/serverspec/default_spec.rb @@ -0,0 +1,41 @@ +require "serverspec" + +set :backend, :exec + +describe "Redis client installation" do + describe package("redis-tools") do + it { should be_installed } + end +end + +describe "Redis server installation" do + describe package("redis-server") do + it { should be_installed } + end + + describe file("/var/lib/redis") do + it { should be_a_directory } + it { should be_owned_by "redis" } + it { should be_grouped_into "redis" } + it { should be_mode 750 } + end + + describe service("redis-server") do + it { should be_enabled } + it { should be_running } + end + + describe file("/etc/redis/redis.conf") do + it { should be_a_file } + it { should be_owned_by "root" } + it { should be_grouped_into "root" } + it { should be_mode 644 } + end + + describe file("/etc/default/redis-server") do + it { should be_a_file } + it { should be_owned_by "root" } + it { should be_grouped_into "root" } + it { should be_mode 644 } + end +end diff --git a/cookbooks/redis/test/support/keys/README.md b/cookbooks/redis/test/support/keys/README.md new file mode 100644 index 0000000..47c0ccf --- /dev/null +++ b/cookbooks/redis/test/support/keys/README.md @@ -0,0 +1,17 @@ +# Insecure Keypair + +These keys are the "insecure" public/private keypair we offer to +[base box creators](http://docs.vagrantup.com/v1/docs/base_boxes.html) for use in their base boxes so that +vagrant installations can automatically SSH into the boxes. + +If you're working with a team or company or with a custom box and +you want more secure SSH, you should create your own keypair +and configure the private key in the Vagrantfile with +`config.ssh.private_key_path` + +# Putty + +If you are using Vagrant on windows, the .ppk file contained here, in the keys directory, +has been generated from the private key and should be used to connect Putty to any VMs that +are leveraging the default key pair. See [guide](http://docs.vagrantup.com/v1/docs/getting-started/ssh.html) +in the documentation for more details on using Putty with Vagrant. diff --git a/cookbooks/redis/test/support/keys/vagrant b/cookbooks/redis/test/support/keys/vagrant new file mode 100644 index 0000000..7d6a083 --- /dev/null +++ b/cookbooks/redis/test/support/keys/vagrant @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzI +w+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoP +kcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2 +hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NO +Td0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcW +yLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQIBIwKCAQEA4iqWPJXtzZA68mKd +ELs4jJsdyky+ewdZeNds5tjcnHU5zUYE25K+ffJED9qUWICcLZDc81TGWjHyAqD1 +Bw7XpgUwFgeUJwUlzQurAv+/ySnxiwuaGJfhFM1CaQHzfXphgVml+fZUvnJUTvzf +TK2Lg6EdbUE9TarUlBf/xPfuEhMSlIE5keb/Zz3/LUlRg8yDqz5w+QWVJ4utnKnK +iqwZN0mwpwU7YSyJhlT4YV1F3n4YjLswM5wJs2oqm0jssQu/BT0tyEXNDYBLEF4A +sClaWuSJ2kjq7KhrrYXzagqhnSei9ODYFShJu8UWVec3Ihb5ZXlzO6vdNQ1J9Xsf +4m+2ywKBgQD6qFxx/Rv9CNN96l/4rb14HKirC2o/orApiHmHDsURs5rUKDx0f9iP +cXN7S1uePXuJRK/5hsubaOCx3Owd2u9gD6Oq0CsMkE4CUSiJcYrMANtx54cGH7Rk +EjFZxK8xAv1ldELEyxrFqkbE4BKd8QOt414qjvTGyAK+OLD3M2QdCQKBgQDtx8pN +CAxR7yhHbIWT1AH66+XWN8bXq7l3RO/ukeaci98JfkbkxURZhtxV/HHuvUhnPLdX +3TwygPBYZFNo4pzVEhzWoTtnEtrFueKxyc3+LjZpuo+mBlQ6ORtfgkr9gBVphXZG +YEzkCD3lVdl8L4cw9BVpKrJCs1c5taGjDgdInQKBgHm/fVvv96bJxc9x1tffXAcj +3OVdUN0UgXNCSaf/3A/phbeBQe9xS+3mpc4r6qvx+iy69mNBeNZ0xOitIjpjBo2+ +dBEjSBwLk5q5tJqHmy/jKMJL4n9ROlx93XS+njxgibTvU6Fp9w+NOFD/HvxB3Tcz +6+jJF85D5BNAG3DBMKBjAoGBAOAxZvgsKN+JuENXsST7F89Tck2iTcQIT8g5rwWC +P9Vt74yboe2kDT531w8+egz7nAmRBKNM751U/95P9t88EDacDI/Z2OwnuFQHCPDF +llYOUI+SpLJ6/vURRbHSnnn8a/XG+nzedGH5JGqEJNQsz+xT2axM0/W/CRknmGaJ +kda/AoGANWrLCz708y7VYgAtW2Uf1DPOIYMdvo6fxIB5i9ZfISgcJ/bbCUkFrhoH ++vq/5CIWxCPp0f85R4qxxQ5ihxJ0YDQT9Jpx4TMss4PSavPaBH3RXow5Ohe+bYoQ +NE5OgEXk2wVfZczCZpigBKbKZHNYcelXtTt/nP3rsCuGcM4h53s= +-----END RSA PRIVATE KEY----- diff --git a/cookbooks/redis/test/support/keys/vagrant.pub b/cookbooks/redis/test/support/keys/vagrant.pub new file mode 100644 index 0000000..18a9c00 --- /dev/null +++ b/cookbooks/redis/test/support/keys/vagrant.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key diff --git a/cookbooks/redis/test/support/rubocop/disabled.yml b/cookbooks/redis/test/support/rubocop/disabled.yml new file mode 100644 index 0000000..b4fd70a --- /dev/null +++ b/cookbooks/redis/test/support/rubocop/disabled.yml @@ -0,0 +1,25 @@ +Encoding: + Description: 'Use UTF-8 as the source file encoding.' + Enabled: false + +SymbolArray: + Description: 'Use %i or %I for arrays of symbols.' + Enabled: false + +##################### Rails ################################## + +DefaultScope: + Description: 'Checks if the argument passed to default_scope is a block.' + Enabled: false + +HasAndBelongsToMany: + Description: 'Prefer has_many :through to has_and_belongs_to_many.' + Enabled: false + +Output: + Description: 'Checks for calls to puts, print, etc.' + Enabled: false + +Validation: + Description: 'Use sexy validations.' + Enabled: false diff --git a/cookbooks/redis/test/support/rubocop/enabled.yml b/cookbooks/redis/test/support/rubocop/enabled.yml new file mode 100644 index 0000000..df712be --- /dev/null +++ b/cookbooks/redis/test/support/rubocop/enabled.yml @@ -0,0 +1,652 @@ +# These are all the cops that are enabled in the default configuration. + +AccessModifierIndentation: + Description: Check indentation of private/protected visibility modifiers. + Enabled: true + +AccessorMethodName: + Description: Check the naming of accessor methods for get_/set_. + Enabled: true + +Alias: + Description: 'Use alias_method instead of alias.' + Enabled: true + +AlignArray: + Description: >- + Align the elements of an array literal if they span more than + one line. + Enabled: true + +AlignHash: + Description: >- + Align the elements of a hash literal if they span more than + one line. + Enabled: true + +AlignParameters: + Description: >- + Align the parameters of a method call if they span more + than one line. + Enabled: true + +AndOr: + Description: 'Use &&/|| instead of and/or.' + Enabled: true + +AsciiComments: + Description: 'Use only ascii symbols in comments.' + Enabled: true + +AsciiIdentifiers: + Description: 'Use only ascii symbols in identifiers.' + Enabled: true + +Attr: + Description: 'Checks for uses of Module#attr.' + Enabled: true + +BeginBlock: + Description: 'Avoid the use of BEGIN blocks.' + Enabled: true + +BlockComments: + Description: 'Do not use block comments.' + Enabled: true + +BlockNesting: + Description: 'Avoid excessive block nesting' + Enabled: true + +Blocks: + Description: >- + Avoid using {...} for multi-line blocks (multiline chaining is + always ugly). + Prefer {...} over do...end for single-line blocks. + Enabled: true + +BracesAroundHashParameters: + Description: 'Enforce braces style inside hash parameters.' + Enabled: true + +CaseEquality: + Description: 'Avoid explicit use of the case equality operator(===).' + Enabled: true + +CaseIndentation: + Description: 'Indentation of when in a case/when/[else/]end.' + Enabled: true + +CharacterLiteral: + Description: 'Checks for uses of character literals.' + Enabled: true + +ClassAndModuleCamelCase: + Description: 'Use CamelCase for classes and modules.' + Enabled: true + +ClassLength: + Description: 'Avoid classes longer than 100 lines of code.' + Enabled: true + +ClassMethods: + Description: 'Use self when defining module/class methods.' + Enabled: true + +ClassVars: + Description: 'Avoid the use of class variables.' + Enabled: true + +CollectionMethods: + Description: 'Preferred collection methods.' + Enabled: true + +ColonMethodCall: + Description: 'Do not use :: for method call.' + Enabled: true + +CommentAnnotation: + Description: >- + Checks formatting of special comments + (TODO, FIXME, OPTIMIZE, HACK, REVIEW). + Enabled: true + +ConstantName: + Description: 'Constants should use SCREAMING_SNAKE_CASE.' + Enabled: true + +CyclomaticComplexity: + Description: 'Avoid complex methods.' + Enabled: true + +DefWithParentheses: + Description: 'Use def with parentheses when there are arguments.' + Enabled: true + +Documentation: + Description: 'Document classes and non-namespace modules.' + Enabled: true + +DotPosition: + Description: 'Checks the position of the dot in multi-line method calls.' + Enabled: true + +EmptyLineBetweenDefs: + Description: 'Use empty lines between defs.' + Enabled: true + +EmptyLines: + Description: "Don't use several empty lines in a row." + Enabled: true + +EmptyLinesAroundAccessModifier: + Description: "Keep blank lines around access modifiers." + Enabled: true + +EmptyLinesAroundBody: + Description: "Keeps track of empty lines around expression bodies." + Enabled: true + +EmptyLiteral: + Description: 'Prefer literals to Array.new/Hash.new/String.new.' + Enabled: true + +EndBlock: + Description: 'Avoid the use of END blocks.' + Enabled: true + +EndOfLine: + Description: 'Use Unix-style line endings.' + Enabled: true + +EvenOdd: + Description: 'Favor the use of Fixnum#even? && Fixnum#odd?' + Enabled: true + +FavorJoin: + Description: 'Use Array#join instead of Array#*.' + Enabled: true + +FavorUnlessOverNegatedIf: + Description: >- + Favor unless over if for negative conditions + (or control flow or). + Enabled: true + +FavorUntilOverNegatedWhile: + Description: 'Favor until over while for negative conditions.' + Enabled: true + +FileName: + Description: 'Use snake_case for source file names.' + Enabled: true + +FinalNewline: + Description: 'Checks for a final newline in a source file.' + Enabled: true + +FlipFlop: + Description: 'Checks for flip flops' + Enabled: true + +For: + Description: 'Checks use of for or each in multiline loops.' + Enabled: true + +FormatString: + Description: 'Enforce the use of Kernel#sprintf, Kernel#format or String#%.' + Enabled: true + +GlobalVars: + Description: 'Do not introduce global variables.' + Enabled: true + +HashMethods: + Description: 'Checks for use of deprecated Hash methods.' + Enabled: true + +HashSyntax: + Description: >- + Prefer Ruby 1.9 hash syntax { a: 1, b: 2 } over 1.8 syntax + { :a => 1, :b => 2 }. + Enabled: true + +IfUnlessModifier: + Description: >- + Favor modifier if/unless usage when you have a + single-line body. + Enabled: true + +IfWithSemicolon: + Description: 'Never use if x; .... Use the ternary operator instead.' + Enabled: true + +IndentationConsistency: + Description: 'Keep indentation straight.' + Enabled: true + +IndentationWidth: + Description: 'Use 2 spaces for indentation.' + Enabled: true + +IndentArray: + Description: >- + Checks the indentation of the first element in an array + literal. + Enabled: true + +IndentHash: + Description: 'Checks the indentation of the first key in a hash literal.' + Enabled: true + +Lambda: + Description: 'Use the new lambda literal syntax for single-line blocks.' + Enabled: true + +LambdaCall: + Description: 'Use lambda.call(...) instead of lambda.(...).' + Enabled: true + +LeadingCommentSpace: + Description: 'Comments should start with a space.' + Enabled: true + +LineEndConcatenation: + Description: 'Use \\ instead of + to concatenate two string literals at line end.' + Enabled: true + +LineLength: + Description: 'Limit lines to 79 characters.' + Enabled: true + +MethodCalledOnDoEndBlock: + Description: 'Avoid chaining a method call on a do...end block.' + Enabled: true + +MethodCallParentheses: + Description: 'Do not use parentheses for method calls with no arguments.' + Enabled: true + +MethodDefParentheses: + Description: >- + Checks if the method definitions have or don't have + parentheses. + Enabled: true + +MethodLength: + Description: 'Avoid methods longer than 10 lines of code.' + Enabled: true + +MethodName: + Description: 'Use the configured style when naming methods.' + Enabled: true + +ModuleFunction: + Description: 'Checks for usage of `extend self` in modules.' + Enabled: true + +MultilineBlockChain: + Description: 'Avoid multi-line chains of blocks.' + Enabled: true + +MultilineIfThen: + Description: 'Never use then for multi-line if/unless.' + Enabled: true + +MultilineTernaryOperator: + Description: >- + Avoid multi-line ?: (the ternary operator); + use if/unless instead. + Enabled: true + +NestedTernaryOperator: + Description: 'Use one expression per branch in a ternary operator.' + Enabled: true + +NilComparison: + Description: 'Prefer x.nil? to x == nil.' + Enabled: true + +Not: + Description: 'Use ! instead of not.' + Enabled: true + +NumericLiterals: + Description: >- + Add underscores to large numeric literals to improve their + readability. + Enabled: true + +OneLineConditional: + Description: >- + Favor the ternary operator(?:) over + if/then/else/end constructs. + Enabled: true + +OpMethod: + Description: 'When defining binary operators, name the argument other.' + Enabled: true + +ParameterLists: + Description: 'Avoid parameter lists longer than three or four parameters.' + Enabled: true + +ParenthesesAroundCondition: + Description: >- + Don't use parentheses around the condition of an + if/unless/while. + Enabled: true + +PerlBackrefs: + Description: 'Avoid Perl-style regex back references.' + Enabled: true + +PredicateName: + Description: 'Check the names of predicate methods.' + Enabled: true + +Proc: + Description: 'Use proc instead of Proc.new.' + Enabled: true + +RaiseArgs: + Description: 'Checks the arguments passed to raise/fail.' + Enabled: true + +RedundantBegin: + Description: "Don't use begin blocks when they are not needed." + Enabled: true + +RedundantException: + Description: "Checks for an obsolete RuntimeException argument in raise/fail." + Enabled: true + +RedundantReturn: + Description: "Don't use return where it's not required." + Enabled: true + +RedundantSelf: + Description: "Don't use self where it's not needed." + Enabled: true + +RegexpLiteral: + Description: >- + Use %r for regular expressions matching more than + `MaxSlashes` '/' characters. + Use %r only for regular expressions matching more than + `MaxSlashes` '/' character. + Enabled: true + +RescueModifier: + Description: 'Avoid using rescue in its modifier form.' + Enabled: true + +Semicolon: + Description: "Don't use semicolons to terminate expressions." + Enabled: true + +SignalException: + Description: 'Checks for proper usage of fail and raise.' + Enabled: true + +SingleLineBlockParams: + Description: 'Enforces the names of some block params.' + Enabled: true + +SingleLineMethods: + Description: 'Avoid single-line methods.' + Enabled: true + +SpaceAfterColon: + Description: 'Use spaces after colons.' + Enabled: true + +SpaceAfterComma: + Description: 'Use spaces after commas.' + Enabled: true + +SpaceAfterControlKeyword: + Description: 'Use spaces after if/elsif/unless/while/until/case/when.' + Enabled: true + +SpaceAfterMethodName: + Description: >- + Never put a space between a method name and the opening + parenthesis. + Enabled: true + +SpaceAfterNot: + Description: Tracks redundant space after the ! operator. + Enabled: true + +SpaceAfterSemicolon: + Description: 'Use spaces after semicolons.' + Enabled: true + +SpaceAroundBlockBraces: + Description: >- + Checks that block braces have or don't have surrounding space. + For blocks taking parameters, checks that the left brace has + or doesn't have trailing space. + Enabled: true + +SpaceAroundEqualsInParameterDefault: + Description: >- + Use spaces around the = operator when assigning default + values in def params. + Enabled: true + +SpaceAroundOperators: + Description: 'Use spaces around operators.' + Enabled: true + +SpaceBeforeModifierKeyword: + Description: 'Put a space before the modifier keyword.' + Enabled: true + +SpaceInsideBrackets: + Description: 'No spaces after [ or before ].' + Enabled: true + +SpaceInsideHashLiteralBraces: + Description: "Use spaces inside hash literal braces - or don't." + Enabled: true + +SpaceInsideParens: + Description: 'No spaces after ( or before ).' + Enabled: true + +SpecialGlobalVars: + Description: 'Avoid Perl-style global variables.' + Enabled: true + +StringLiterals: + Description: 'Checks if uses of quotes match the configured preference.' + Enabled: true + +Tab: + Description: 'No hard tabs.' + Enabled: true + +TrailingBlankLines: + Description: 'Checks for superfluous trailing blank lines.' + Enabled: true + +TrailingComma: + Description: 'Checks for trailing comma in parameter lists and literals.' + Enabled: true + +TrailingWhitespace: + Description: 'Avoid trailing whitespace.' + Enabled: true + +TrivialAccessors: + Description: 'Prefer attr_* methods to trivial readers/writers.' + Enabled: true + +UnlessElse: + Description: >- + Never use unless with else. Rewrite these with the positive + case first. + Enabled: true + +VariableInterpolation: + Description: >- + Don't interpolate global, instance and class variables + directly in strings. + Enabled: true + +VariableName: + Description: 'Use the configured style when naming variables.' + Enabled: true + +WhenThen: + Description: 'Use when x then ... for one-line cases.' + Enabled: true + +WhileUntilDo: + Description: 'Checks for redundant do after while or until.' + Enabled: true + +WhileUntilModifier: + Description: >- + Favor modifier while/until usage when you have a + single-line body. + Enabled: true + +WordArray: + Description: 'Use %w or %W for arrays of words.' + Enabled: true + +#################### Lint ################################ +### Warnings + +AmbiguousOperator: + Description: >- + Checks for ambiguous operators in the first argument of a + method invocation without parentheses. + Enabled: true + +AmbiguousRegexpLiteral: + Description: >- + Checks for ambiguous regexp literals in the first argument of + a method invocation without parenthesis. + Enabled: true + +AssignmentInCondition: + Description: "Don't use assignment in conditions." + Enabled: true + +BlockAlignment: + Description: 'Align block ends correctly.' + Enabled: true + +ConditionPosition: + Description: 'Checks for condition placed in a confusing position relative to the keyword.' + Enabled: true + +Debugger: + Description: 'Check for debugger calls.' + Enabled: true + +DeprecatedClassMethods: + Description: 'Check for deprecated class method calls.' + Enabled: true + +ElseLayout: + Description: 'Check for odd code arrangement in an else block.' + Enabled: true + +EmptyEnsure: + Description: 'Checks for empty ensure block.' + Enabled: true + +EndAlignment: + Description: 'Align ends correctly.' + Enabled: true + +EndInMethod: + Description: 'END blocks should not be placed inside method definitions.' + Enabled: true + +EnsureReturn: + Description: 'Never use return in an ensure block.' + Enabled: true + +Eval: + Description: 'The use of eval represents a serious security risk.' + Enabled: true + +HandleExceptions: + Description: "Don't suppress exception." + Enabled: true + +InvalidCharacterLiteral: + Description: >- + Checks for invalid character literals with a non-escaped + whitespace character. + Enabled: true + +LiteralInCondition: + Description: 'Checks of literals used in conditions.' + Enabled: true + +LiteralInInterpolation: + Description: 'Checks for literals used in interpolation.' + Enabled: true + +Loop: + Description: >- + Use Kernel#loop with break rather than begin/end/until or + begin/end/while for post-loop tests. + Enabled: true + +ParenthesesAsGroupedExpression: + Description: >- + Checks for method calls with a space before the opening + parenthesis. + Enabled: true + +RequireParentheses: + Description: >- + Use parentheses in the method call to avoid confusion + about precedence. + Enabled: true + +RescueException: + Description: 'Avoid rescuing the Exception class.' + Enabled: true + +ShadowingOuterLocalVariable: + Description: >- + Do not use the same name as outer local variable + for block arguments or block local variables. + Enabled: true + +StringConversionInInterpolation: + Description: 'Checks for Object#to_s usage in string interpolation.' + Enabled: true + +UnreachableCode: + Description: 'Unreachable code.' + Enabled: true + +UselessAssignment: + Description: 'Checks for useless assignment to a local variable.' + Enabled: true + +UselessComparison: + Description: 'Checks for comparison of something with itself.' + Enabled: true + +UselessElseWithoutRescue: + Description: 'Checks for useless `else` in `begin..end` without `rescue`.' + Enabled: true + +UselessSetterCall: + Description: 'Checks for useless setter call to a local variable.' + Enabled: true + +Void: + Description: 'Possible use of operator/literal/variable in void context.' + Enabled: true diff --git a/cookbooks/seven_zip/Gemfile b/cookbooks/seven_zip/Gemfile new file mode 100644 index 0000000..b6ba658 --- /dev/null +++ b/cookbooks/seven_zip/Gemfile @@ -0,0 +1,8 @@ +source 'http://rubygems.org' + +gem 'cookstyle' +gem 'foodcritic' +gem 'rspec-expectations' +gem 'rspec-mocks' +gem 'rubocop' +gem 'stove' diff --git a/cookbooks/seven_zip/Gemfile.lock b/cookbooks/seven_zip/Gemfile.lock new file mode 100644 index 0000000..9a5c87f --- /dev/null +++ b/cookbooks/seven_zip/Gemfile.lock @@ -0,0 +1,79 @@ +GEM + remote: http://rubygems.org/ + specs: + ast (2.4.0) + backports (3.11.3) + chef-api (0.8.0) + logify (~> 0.1) + mime-types + cookstyle (3.0.0) + rubocop (= 0.55.0) + cucumber-core (3.1.0) + backports (>= 3.8.0) + cucumber-tag_expressions (~> 1.1.0) + gherkin (>= 5.0.0) + cucumber-tag_expressions (1.1.1) + diff-lcs (1.3) + erubis (2.7.0) + ffi-yajl (2.3.1) + libyajl2 (~> 1.2) + foodcritic (13.1.1) + cucumber-core (>= 1.3) + erubis + ffi-yajl (~> 2.0) + nokogiri (>= 1.5, < 2.0) + rake + rufus-lru (~> 1.0) + treetop (~> 1.4) + gherkin (5.0.0) + libyajl2 (1.2.0) + logify (0.2.0) + mime-types (3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2016.0521) + mini_portile2 (2.3.0) + nokogiri (1.8.2) + mini_portile2 (~> 2.3.0) + parallel (1.12.1) + parser (2.5.1.0) + ast (~> 2.4.0) + polyglot (0.3.5) + powerpack (0.1.1) + rainbow (3.0.0) + rake (12.3.1) + rspec-expectations (3.7.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.7.0) + rspec-mocks (3.7.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.7.0) + rspec-support (3.7.1) + rubocop (0.55.0) + parallel (~> 1.10) + parser (>= 2.5) + powerpack (~> 0.1) + rainbow (>= 2.2.2, < 4.0) + ruby-progressbar (~> 1.7) + unicode-display_width (~> 1.0, >= 1.0.1) + ruby-progressbar (1.9.0) + rufus-lru (1.1.0) + stove (6.0.0) + chef-api (~> 0.5) + logify (~> 0.2) + treetop (1.6.10) + polyglot (~> 0.3) + unicode-display_width (1.3.2) + +PLATFORMS + ruby + +DEPENDENCIES + cookstyle + foodcritic + rspec-expectations + rspec-mocks + rubocop + stove + +BUNDLED WITH + 1.16.1 diff --git a/cookbooks/seven_zip/LICENSE b/cookbooks/seven_zip/LICENSE new file mode 100644 index 0000000..11069ed --- /dev/null +++ b/cookbooks/seven_zip/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/cookbooks/seven_zip/README.md b/cookbooks/seven_zip/README.md new file mode 100644 index 0000000..7e04831 --- /dev/null +++ b/cookbooks/seven_zip/README.md @@ -0,0 +1,114 @@ +[![Cookbook Version](http://img.shields.io/cookbook/v/seven_zip.svg)](https://supermarket.chef.io/cookbooks/seven_zip) +[![Build status](https://ci.appveyor.com/api/projects/status/y1lsnlkd2b3q6gfd/branch/master?svg=true)](https://ci.appveyor.com/project/ChefWindowsCookbooks65871/seven-zip/branch/master) + +# seven_zip Cookbook +[7-Zip](http://www.7-zip.org/) is a file archiver with a high compression ratio. This cookbook installs the full 7-Zip suite of tools (GUI and CLI). This cookbook replaces the older [7-Zip cookbook](https://github.com/sneal/7-zip). + +# Requirements +## Platforms +- Windows XP +- Windows Vista +- Windows 7 +- Windows 8, 8.1 +- Windows 10 +- Windows Server 2003 R2 +- Windows Server 2008 (R1, R2) +- Windows Server 2012 (R1, R2) + +## Chef +- Chef >= 13.0 + +## Cookbooks +- windows + +# Attributes +## Optional + +| Key | Type | Description | Default | +|-----|------|-------------|---------| +| `['seven_zip']['home']` | String | 7-Zip installation directory. | | +| `['seven_zip']['syspath']` | Boolean | If true, adds 7-Zip directory to system PATH environment variable. | | +| `['seven_zip']['default_extract_timeout']` | Integer | The default timeout for an extract operation in seconds. This can be overridden by a resource attribute. | `600` | + +# Usage +## default + +Add `seven_zip::default` to your run\_list which will download and install 7-Zip for the current Windows platform. + +# Resource/Provider +## seven_zip_archive +Extracts a 7-Zip compatible archive (iso, zip, 7z, etc.) to the specified destination directory. + +#### Actions +- `:extract` - Extract a 7-Zip compatible archive. + +#### Attribute Parameters +- `path` - Name attribute. The destination to extract to. +- `source` - The file path to the archive to extract. +- `overwrite` - Defaults to false. If true, the destination files will be overwritten. +- `checksum` - The archive file checksum. +- `timeout` - The extract action timeout in seconds, defaults to `node['seven_zip']['default_extract_timeout']`. + +#### Examples +Extract 7-Zip source files to `C:\seven_zip_source`. + +```ruby +seven_zip_archive 'seven_zip_source' do + path 'C:\seven_zip_source' + source 'https://www.7-zip.org/a/7z1805-src.7z' + overwrite true + checksum 'd9acfcbbdcad078435586e00f73909358ed8d714d106e064dcba52fa73e75d83' + timeout 30 +end +``` + +## seven_zip_tool +Download and install 7-zip for the current Windows platform. + +#### Actions +- `:install` - Installs 7-zip +- `:add_to_path` - Add 7-zip to the PATH + +#### Attribute Parameters +- `package` - The name of the package. +- `path` - The install directory of 7-zip. +- `source` - The source URL of the 7-zip package. +- `checksum` - The 7-zip package checksum. + +#### Examples +Install 7-zip in `C:\7z` and add it to the path. + +```ruby +seven_zip_tool '7z 15.14 install' do + action [:install, :add_to_path] + package '7-Zip 15.14' + path 'C:\7z' + source 'http://www.7-zip.org/a/7z1514.msi' + checksum 'eaf58e29941d8ca95045946949d75d9b5455fac167df979a7f8e4a6bf2d39680' +end +``` + +# Recipes +## default + +Installs 7-Zip and adds it to your system PATH. + +# License & Authors +- Author:: Seth Chisamore () +- Author:: Shawn Neal () + +```text +Copyright:: 2011-2016, Chef Software, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/cookbooks/seven_zip/appveyor.yml b/cookbooks/seven_zip/appveyor.yml new file mode 100644 index 0000000..321b270 --- /dev/null +++ b/cookbooks/seven_zip/appveyor.yml @@ -0,0 +1,42 @@ +version: "3.1.1.{build}-{branch}" + +image: Visual Studio 2013 +platform: x64 + +environment: + machine_user: vagrant + machine_pass: vagrant + KITCHEN_YAML: .kitchen.appveyor.yml + +branches: + only: + - master + +# Do not build on tags (GitHub only) +skip_tags: true + +#faster cloning +clone_depth: 1 + +install: + - ps: (& cmd /c); iex (irm https://omnitruck.chef.io/install.ps1); Install-Project -Project chefdk -channel stable -version 3.10.1 + - ps: 'Get-CimInstance win32_operatingsystem -Property Caption, OSArchitecture, Version | fl Caption, OSArchitecture, Version' + - ps: $PSVersionTable + - c:\opscode\chefdk\bin\chef.bat exec ruby --version + - ps: secedit /export /cfg $env:temp/export.cfg + - ps: ((get-content $env:temp/export.cfg) -replace ('PasswordComplexity = 1', 'PasswordComplexity = 0')) | Out-File $env:temp/export.cfg + - ps: ((get-content $env:temp/export.cfg) -replace ('MinimumPasswordLength = 8', 'MinimumPasswordLength = 0')) | Out-File $env:temp/export.cfg + - ps: secedit /configure /db $env:windir/security/new.sdb /cfg $env:temp/export.cfg /areas SECURITYPOLICY + - ps: net user /add $env:machine_user $env:machine_pass + - ps: net localgroup administrators $env:machine_user /add + +build_script: + - ps: c:\opscode\chefdk\bin\chef.bat shell-init powershell | iex; cmd /c c:\opscode\chefdk\bin\chef.bat --version + +test_script: + - c:\opscode\chefdk\bin\cookstyle --version + - c:\opscode\chefdk\bin\chef.bat exec foodcritic --version + - c:\opscode\chefdk\bin\chef.bat exec rake + - c:\opscode\chefdk\bin\chef.bat exec kitchen verify + +deploy: off diff --git a/cookbooks/seven_zip/attributes/default.rb b/cookbooks/seven_zip/attributes/default.rb new file mode 100644 index 0000000..443a28b --- /dev/null +++ b/cookbooks/seven_zip/attributes/default.rb @@ -0,0 +1,31 @@ +# +# Author:: Seth Chisamore () +# Cookbook:: seven_zip +# Attribute:: default +# +# Copyright:: 2011-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if node['kernel']['machine'] == 'x86_64' + default['seven_zip']['url'] = 'https://www.7-zip.org/a/7z1805-x64.msi' + default['seven_zip']['checksum'] = '898c1ca0015183fe2ba7d55cacf0a1dea35e873bf3f8090f362a6288c6ef08d7' + default['seven_zip']['package_name'] = '7-Zip 18.05 (x64 edition)' +else + default['seven_zip']['url'] = 'https://www.7-zip.org/a/7z1805.msi' + default['seven_zip']['checksum'] = 'c554238bee18a03d736525e06d9258c9ecf7f64ead7c6b0d1eb04db2c0de30d0' + default['seven_zip']['package_name'] = '7-Zip 18.05' +end + +default['seven_zip']['default_extract_timeout'] = 600 diff --git a/cookbooks/seven_zip/chefignore b/cookbooks/seven_zip/chefignore new file mode 100644 index 0000000..9c2bd55 --- /dev/null +++ b/cookbooks/seven_zip/chefignore @@ -0,0 +1,98 @@ +# OS generated files # +###################### +.DS_Store +Icon? +nohup.out +ehthumbs.db +Thumbs.db + +# SASS # +######## +.sass-cache + +# EDITORS # +########### +\#* +.#* +*~ +*.sw[a-z] +*.bak +REVISION +TAGS* +tmtags +*_flymake.* +*_flymake +*.tmproj +.project +.settings +mkmf.log + +## COMPILED ## +############## +a.out +*.o +*.pyc +*.so +*.com +*.class +*.dll +*.exe +*/rdoc/ + +# Testing # +########### +.watchr +.rspec +spec/* +spec/fixtures/* +test/* +features/* +examples/* +Guardfile +Procfile +.kitchen* +.rubocop.yml +spec/* +Rakefile +.travis.yml +.foodcritic +.codeclimate.yml + +# SCM # +####### +.git +*/.git +.gitignore +.gitmodules +.gitconfig +.gitattributes +.svn +*/.bzr/* +*/.hg/* +*/.svn/* + +# Berkshelf # +############# +Berksfile +Berksfile.lock +cookbooks/* +tmp + +# Cookbooks # +############# +CONTRIBUTING* +CHANGELOG* +TESTING* +MAINTAINERS.toml + +# Strainer # +############ +Colanderfile +Strainerfile +.colander +.strainer + +# Vagrant # +########### +.vagrant +Vagrantfile diff --git a/cookbooks/seven_zip/libraries/matchers.rb b/cookbooks/seven_zip/libraries/matchers.rb new file mode 100644 index 0000000..6dd4dca --- /dev/null +++ b/cookbooks/seven_zip/libraries/matchers.rb @@ -0,0 +1,33 @@ +# +# Author:: Shawn Neal () +# Cookbook:: visualstudio +# +# Copyright:: 2015-2017, Shawn Neal +# +# 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. +# + +if defined?(ChefSpec) + chefspec_version = Gem.loaded_specs['chefspec'].version + define_method = if chefspec_version < Gem::Version.new('4.1.0') + ChefSpec::Runner.method(:define_runner_method) + else + ChefSpec.method(:define_matcher) + end + + define_method.call :seven_zip_archive + + def extract_seven_zip_archive(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:seven_zip_archive, :extract, resource_name) + end +end diff --git a/cookbooks/seven_zip/metadata.json b/cookbooks/seven_zip/metadata.json new file mode 100644 index 0000000..cf13785 --- /dev/null +++ b/cookbooks/seven_zip/metadata.json @@ -0,0 +1,38 @@ +{ + "name": "seven_zip", + "description": "Installs/Configures 7-Zip", + "long_description": "[![Cookbook Version](http://img.shields.io/cookbook/v/seven_zip.svg)](https://supermarket.chef.io/cookbooks/seven_zip)\n[![Build status](https://ci.appveyor.com/api/projects/status/y1lsnlkd2b3q6gfd/branch/master?svg=true)](https://ci.appveyor.com/project/ChefWindowsCookbooks65871/seven-zip/branch/master)\n\n# seven_zip Cookbook\n[7-Zip](http://www.7-zip.org/) is a file archiver with a high compression ratio. This cookbook installs the full 7-Zip suite of tools (GUI and CLI). This cookbook replaces the older [7-Zip cookbook](https://github.com/sneal/7-zip).\n\n# Requirements\n## Platforms\n- Windows XP\n- Windows Vista\n- Windows 7\n- Windows 8, 8.1\n- Windows 10\n- Windows Server 2003 R2\n- Windows Server 2008 (R1, R2)\n- Windows Server 2012 (R1, R2)\n\n## Chef\n- Chef >= 13.0\n\n## Cookbooks\n- windows\n\n# Attributes\n## Optional\n\n| Key | Type | Description | Default |\n|-----|------|-------------|---------|\n| `['seven_zip']['home']` | String | 7-Zip installation directory. | |\n| `['seven_zip']['syspath']` | Boolean | If true, adds 7-Zip directory to system PATH environment variable. | |\n| `['seven_zip']['default_extract_timeout']` | Integer | The default timeout for an extract operation in seconds. This can be overridden by a resource attribute. | `600` |\n\n# Usage\n## default\n\nAdd `seven_zip::default` to your run\\_list which will download and install 7-Zip for the current Windows platform.\n\n# Resource/Provider\n## seven_zip_archive\nExtracts a 7-Zip compatible archive (iso, zip, 7z, etc.) to the specified destination directory.\n\n#### Actions\n- `:extract` - Extract a 7-Zip compatible archive.\n\n#### Attribute Parameters\n- `path` - Name attribute. The destination to extract to.\n- `source` - The file path to the archive to extract.\n- `overwrite` - Defaults to false. If true, the destination files will be overwritten.\n- `checksum` - The archive file checksum.\n- `timeout` - The extract action timeout in seconds, defaults to `node['seven_zip']['default_extract_timeout']`.\n\n#### Examples\nExtract 7-Zip source files to `C:\\seven_zip_source`.\n\n```ruby\nseven_zip_archive 'seven_zip_source' do\n path 'C:\\seven_zip_source'\n source 'https://www.7-zip.org/a/7z1805-src.7z'\n overwrite true\n checksum 'd9acfcbbdcad078435586e00f73909358ed8d714d106e064dcba52fa73e75d83'\n timeout 30\nend\n```\n\n## seven_zip_tool\nDownload and install 7-zip for the current Windows platform.\n\n#### Actions\n- `:install` - Installs 7-zip\n- `:add_to_path` - Add 7-zip to the PATH\n\n#### Attribute Parameters\n- `package` - The name of the package.\n- `path` - The install directory of 7-zip.\n- `source` - The source URL of the 7-zip package.\n- `checksum` - The 7-zip package checksum.\n\n#### Examples\nInstall 7-zip in `C:\\7z` and add it to the path.\n\n```ruby\nseven_zip_tool '7z 15.14 install' do\n action [:install, :add_to_path]\n package '7-Zip 15.14'\n path 'C:\\7z'\n source 'http://www.7-zip.org/a/7z1514.msi'\n checksum 'eaf58e29941d8ca95045946949d75d9b5455fac167df979a7f8e4a6bf2d39680'\nend\n```\n\n# Recipes\n## default\n\nInstalls 7-Zip and adds it to your system PATH.\n\n# License & Authors\n- Author:: Seth Chisamore ()\n- Author:: Shawn Neal ()\n\n```text\nCopyright:: 2011-2016, Chef Software, Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n", + "maintainer": "Shawn Neal", + "maintainer_email": "sneal@sneal.net", + "license": "Apache-2.0", + "platforms": { + "windows": ">= 0.0.0" + }, + "dependencies": { + "windows": ">= 0.0.0" + }, + "providing": { + + }, + "attributes": { + + }, + "recipes": { + + }, + "version": "3.1.1", + "source_url": "https://github.com/windowschefcookbooks/seven_zip", + "issues_url": "https://github.com/windowschefcookbooks/seven_zip/issues", + "privacy": false, + "chef_versions": [ + [ + ">= 13.0" + ] + ], + "ohai_versions": [ + + ], + "gems": [ + + ] +} diff --git a/cookbooks/seven_zip/metadata.rb b/cookbooks/seven_zip/metadata.rb new file mode 100644 index 0000000..d840292 --- /dev/null +++ b/cookbooks/seven_zip/metadata.rb @@ -0,0 +1,12 @@ +name 'seven_zip' +maintainer 'Shawn Neal' +maintainer_email 'sneal@sneal.net' +source_url 'https://github.com/windowschefcookbooks/seven_zip' +issues_url 'https://github.com/windowschefcookbooks/seven_zip/issues' +chef_version '>= 13.0' if respond_to?(:chef_version) +license 'Apache-2.0' +description 'Installs/Configures 7-Zip' +long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) +version '3.1.1' +supports 'windows' +depends 'windows' diff --git a/cookbooks/seven_zip/providers/archive.rb b/cookbooks/seven_zip/providers/archive.rb new file mode 100644 index 0000000..c935569 --- /dev/null +++ b/cookbooks/seven_zip/providers/archive.rb @@ -0,0 +1,64 @@ +# +# Author:: Shawn Neal () +# Cookbook:: seven_zip +# Provider:: archive +# +# Copyright:: 2013-2017, Daptiv Solutions LLC +# +# 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. +# + +require 'fileutils' +require 'chef/mixin/shell_out' +require 'chef/util/path_helper' + +include Chef::Mixin::ShellOut +include Windows::Helper + +def whyrun_supported? + true +end + +action :extract do + converge_by("Extract #{@new_resource.source} => #{@new_resource.path} (overwrite=#{@new_resource.overwrite})") do + FileUtils.mkdir_p(@new_resource.path) unless Dir.exist?(@new_resource.path) + local_source = cached_file(@new_resource.source, @new_resource.checksum) + overwrite_file = @new_resource.overwrite ? ' -y' : ' -aos' + cmd = "\"#{seven_zip_exe}\" x" + cmd << overwrite_file + cmd << " -o\"#{Chef::Util::PathHelper.cleanpath(@new_resource.path)}\"" + cmd << " \"#{local_source}\"" + Chef::Log.debug(cmd) + shell_out!(cmd, timeout: extract_timeout) + end +end + +def seven_zip_exe + path = node['seven_zip']['home'] || seven_zip_exe_from_registry + Chef::Log.debug("Using 7-zip home: #{path}") + Chef::Util::PathHelper.cleanpath(::File.join(path, '7z.exe')) +end + +def seven_zip_exe_from_registry + require 'win32/registry' + # Read path from recommended Windows App Paths registry location + # docs: https://msdn.microsoft.com/en-us/library/windows/desktop/ee872121 + ::Win32::Registry::HKEY_LOCAL_MACHINE.open( + 'SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\7zFM.exe', + ::Win32::Registry::KEY_READ + ).read_s('Path') +end + +def extract_timeout + @new_resource.timeout || node['seven_zip']['default_extract_timeout'] +end diff --git a/cookbooks/seven_zip/rakefile.rb b/cookbooks/seven_zip/rakefile.rb new file mode 100644 index 0000000..6eab0cc --- /dev/null +++ b/cookbooks/seven_zip/rakefile.rb @@ -0,0 +1,27 @@ +require 'cookstyle' +require 'foodcritic' +require 'rspec/core/rake_task' +require 'rubocop/rake_task' + +task default: [:rubocop, :foodcritic, :spec] + +FoodCritic::Rake::LintTask.new do |t| + t.options = { + cookbook_paths: '.', + search_gems: true, + } +end + +RSpec::Core::RakeTask.new do |task| + task.pattern = 'spec/**/*_spec.rb' + task.rspec_opts = ['--color', '-f documentation', '-tunit'] +end + +RuboCop::RakeTask.new + +begin + require 'stove/rake_task' + Stove::RakeTask.new +rescue LoadError => e + puts ">>> Gem load error: #{e}, omitting #{task.name}" unless ENV['CI'] +end diff --git a/cookbooks/seven_zip/recipes/default.rb b/cookbooks/seven_zip/recipes/default.rb new file mode 100644 index 0000000..b013889 --- /dev/null +++ b/cookbooks/seven_zip/recipes/default.rb @@ -0,0 +1,24 @@ +# +# Author:: Seth Chisamore () +# Cookbook:: seven_zip +# Recipe:: default +# +# Copyright:: 2011-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Install 7z and optionally add it to path +seven_zip_tool 'install seven_zip' do + action [:install, :add_to_path] if node['seven_zip']['syspath'] +end diff --git a/cookbooks/seven_zip/resources/archive.rb b/cookbooks/seven_zip/resources/archive.rb new file mode 100644 index 0000000..5558f14 --- /dev/null +++ b/cookbooks/seven_zip/resources/archive.rb @@ -0,0 +1,29 @@ +# +# Author:: Shawn Neal () +# Cookbook:: seven_zip +# Resource:: archive +# +# Copyright:: 2013-2017, Daptiv Solutions LLC +# +# 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. +# + +default_action :extract + +actions :extract + +attribute :path, kind_of: String, name_attribute: true +attribute :source, kind_of: String +attribute :overwrite, kind_of: [TrueClass, FalseClass], default: false +attribute :checksum, kind_of: String +attribute :timeout, kind_of: Integer diff --git a/cookbooks/seven_zip/resources/tool.rb b/cookbooks/seven_zip/resources/tool.rb new file mode 100644 index 0000000..4e27965 --- /dev/null +++ b/cookbooks/seven_zip/resources/tool.rb @@ -0,0 +1,47 @@ +# +# Author:: Annih () +# Cookbook:: seven_zip +# Resource:: tool +# +# Copyright:: 2018, Baptiste Courtois +# +# 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. +# +property :package, ::String, default: lazy { node['seven_zip']['package_name'] } +property :source, ::String, default: lazy { node['seven_zip']['url'] } +property :checksum, [::NilClass, ::String], default: lazy { node['seven_zip']['checksum'] } +property :path, [::NilClass, ::String], default: lazy { node['seven_zip']['home'] } + +action :install do + windows_package new_resource.package do + action :install + source new_resource.source + checksum new_resource.checksum unless new_resource.checksum.nil? + options "INSTALLDIR=\"#{new_resource.path}\"" unless new_resource.path.nil? + end +end + +action :add_to_path do + windows_path 'seven_zip' do + action :add + path new_resource.path || registry_path + end +end + +action_class do + REG_PATH = 'SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\7zFM.exe'.freeze + + def registry_path + ::Win32::Registry::HKEY_LOCAL_MACHINE.open(REG_PATH, ::Win32::Registry::KEY_READ).read_s('Path') + end +end diff --git a/cookbooks/timezone_iii/LICENSE b/cookbooks/timezone_iii/LICENSE new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/cookbooks/timezone_iii/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/cookbooks/timezone_iii/README.md b/cookbooks/timezone_iii/README.md new file mode 100644 index 0000000..0b8788b --- /dev/null +++ b/cookbooks/timezone_iii/README.md @@ -0,0 +1,137 @@ +[![Chef cookbook](https://img.shields.io/cookbook/v/timezone_iii.svg)]() +[![Code Climate](https://codeclimate.com/github/Stromweld/timezone_iii/badges/gpa.svg)](https://codeclimate.com/github/Stromweld/timezone_iii) +[![Issue Count](https://codeclimate.com/github/Stromweld/timezone_iii/badges/issue_count.svg)](https://codeclimate.com/github/Stromweld/timezone_iii) + +# timezone_iii + +The Timezone III cookbook contains recipes for installing the latest tzdata (a.k.a. IANA or Olson) timezone database and setting the timezone on your system. It is a fork of the [timezone-ii cookbook by Lawrence Gilbert.](https://supermarket.chef.io/cookbooks/timezone-ii). + +## Requirements + +This cookbook is known to work with: + +* Amazon Linux +* CentOS and RHEL +* Debian +* Fedora +* Gentoo +* PLD Linux +* Ubuntu +* Windows + +It _should_ work with any OS that uses the IANA/Olson timezone database and stores local timezone data in /etc/localtime (the only OS I know of that does _not_ do this is MS Windows). However, some OSs not mentioned above have their own system utility for setting the timezone, and this may overwrite the changes made by this cookbook. + +## Attributes + +| Attribute | Default | Comment | +| ------------- | ------------- | ------------- | +| ['timezone_iii']['timezone'] | 'value_for_platform_family(debian: 'Etc/UTC', default: 'UTC')' | String, timezone to set OS to | +| ['timezone_iii']['tzdata_dir'] | '/usr/share/zoneinfo' | String, the path to the root of the tzdata files; the default value is for most known distributions of Linux | +| ['timezone_iii']['localtime_path'] | '/etc/localtime' | String, the path to the file used by the kernel to read the local timezone's settings; the default works for Linux and other *ix variants | +| ['timezone_iii']['use_symlink'] | false | Boolean, whether to use a symlink into the tzdata tree rather than make a copy of the appropriate timezone data file (amazon and linux_generic recipes only) | + +## Usage + +Set the ['timezone_iii']['timezone'] attribute to your desired timezone and include the "timezone_iii" recipe in your node's run list: + + { + "name": "my_node", + "timezone_iii" { + "timezone": "Africa/Timbuktu" + }, + "run_list": [ + "recipe[timezone_iii]" + ] + } + +### timezone_iii::default + +The default recipe will first install or upgrade the IANA/Olson timezone database package for your OS (`timezone-data` on Gentoo, `tzdata` on all other linux platforms). Then it will call one of the recipes below according to your node's platform. + +### timezone_iii::amazon + +This changes the timezone on Amazon Linux by: + +1. including the "timezone_iii::linux_generic" recipe then; +2. including the "timezone_iii::rhel" recipe. + +Refer to the sections for those recipes for details. + +### timezone_iii::debian + +This changes the timezone on Debian-family platforms by: + +1. writing the value of `['timezone_iii']['timezone']` to `/etc/timezone` then; +2. calling `dpkg-reconfigure -f noninteractive tzdata`; +3. if `dpkg-reconfigure` amends the timezone value (e.g. by changing "UTC" to "Etc/UTC" or "EET" to "Europe/Helsinki"), it logs a warning. + +Only the `['timezone_iii']['timezone']` attribute is used; all others are ignored. + +### timezone_iii::linux_generic + +This changes the time on all OSs without a more specific recipe. It assumes that the kernel gets data on the local timezone from `/etc/localtime`. (This is true for FreeBSD as well as Linux, so "linux_generic" is a bit of a misnomer.) + +What this recipe does: + +1. verifies that the value of `['timezone_iii']['timezone']` corresponds with a timezone data file under the directory specified in `timezone.tzdata_dir` (default:`/usr/share/zoneinfo`), then; +2. creates a copy of or symbolic link to that data file in the path specified in `timezone.localtime_path` (default: `/etc/localtime`). + +The truthiness of `timezone.use_symlink` (default: `false`) determines whether a symlink or a copy is made. + +### timezone_iii::pld + +This changes the timezone on PLD Linux. It writes the appropriate timezone configuration file, making use of the `['timezone_iii']['timezone']` and `['timezone_iii']['tzdata_dir']` attributes. Other attributes are ignored. + +### timezone_iii::rhel + +This changes the timezone on RedHat Enterprise Linux (RHEL) and RHEL-family platforms such as CentOS. It is intended only for versions prior to 7.0, but should the recipe be called on a system with version 7.0 or newer, it will automatically include the "timezone_iii::rhel7" recipe and do nothing else. + +This recipe updates the `/etc/sysconfig/clock` file with the value of the `['timezone_iii']['timezone']` attribute, then calls `tzdata-update` (if available) to change the timezone. All node attributes other than `['timezone_iii']['timezone']` are ignored. + +### timezone_iii::rhel7 + +This changes the timezone on EL 7 platforms by calling `timedatectl set-timezone` with the value of `['timezone_iii']['timezone']`. + +Only the `['timezone_iii']['timezone']` attribute is used; all others are ignored. + +### timezone_iii::windows + +This changes the timezone on windows platforms by calling `tzutil.exe` with the value of `['timezone_iii']['timezone']`. To get a list of timezones to use with windows you can run the command `tzutil.exe /l | more` on the command line and use the standard name under the offset info. + +Only the `['timezone_iii']['timezone']` attribute is used; all others are ignored. + +## Contributing + +1. Fork the [repository on GitHub](https://github.com/Stromweld/timezone_iii); +2. Write your change; +3. If at all possible, write tests for your change and ensure they all pass; +4. Submit a pull request using GitHub. + +## Acknowledgements + +Thanks to: + +* Larry Gilbert, for launching the timezone-ii cookbook +* James Harton, for launching the timezone cookbook +* Elan Ruusamäe, for PLD support +* Mike Conigliaro, for bringing testing up to date +* "fraD00r4", for RHEL/CentOS support + +## License and Authors + +* Copyright © 2010 James Harton +* Copyright © 2013-2015 Lawrence Leonard Gilbert +* Copyright © 2013 Elan Ruusamäe +* Copyright © 2013 fraD00r4 +* Copyright © 2017 Corey Hemminger + +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/cookbooks/timezone_iii/attributes/default.rb b/cookbooks/timezone_iii/attributes/default.rb new file mode 100644 index 0000000..ff0cc96 --- /dev/null +++ b/cookbooks/timezone_iii/attributes/default.rb @@ -0,0 +1,33 @@ +# +# Cookbook:: timezone_iii +# Attribute:: default +# +# Copyright:: 2017, Corey Hemminger +# +# 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. + +# Use universal time if no other timezone is specified +default['timezone_iii']['timezone'] = value_for_platform_family( + debian: 'Etc/UTC', + default: 'UTC' +) + +# Path to tzdata directory +default['timezone_iii']['tzdata_dir'] = '/usr/share/zoneinfo' + +# Path to file used by kernel for local timezone's data +default['timezone_iii']['localtime_path'] = '/etc/localtime' + +# Whether to use a symlink to tzdata (instead of copying). +# Used only in the linux-default recipe. +default['timezone_iii']['use_symlink'] = false diff --git a/cookbooks/timezone_iii/chefignore b/cookbooks/timezone_iii/chefignore new file mode 100644 index 0000000..38e7379 --- /dev/null +++ b/cookbooks/timezone_iii/chefignore @@ -0,0 +1,107 @@ +# Put files/directories that should be ignored in this file when uploading +# to a chef-server or supermarket. +# Lines that start with '# ' are comments. + +# OS generated files # +###################### +.DS_Store +Icon? +nohup.out +ehthumbs.db +Thumbs.db + +# SASS # +######## +.sass-cache + +# EDITORS # +########### +\#* +.#* +*~ +*.sw[a-z] +*.bak +REVISION +TAGS* +tmtags +*_flymake.* +*_flymake +*.tmproj +.project +.settings +mkmf.log + +## COMPILED ## +############## +a.out +*.o +*.pyc +*.so +*.com +*.class +*.dll +*.exe +*/rdoc/ + +# Testing # +########### +.watchr +.rspec +spec/* +spec/fixtures/* +test/* +features/* +examples/* +Guardfile +Procfile +.kitchen* +.rubocop.yml +spec/* +Rakefile +.travis.yml +.foodcritic +.codeclimate.yml + +# SCM # +####### +.git +*/.git +.gitignore +.gitmodules +.gitconfig +.gitattributes +.svn +*/.bzr/* +*/.hg/* +*/.svn/* + +# Berkshelf # +############# +Berksfile +Berksfile.lock +cookbooks/* +tmp + +# Policyfile # +############## +Policyfile.rb +Policyfile.lock.json + +# Cookbooks # +############# +CONTRIBUTING* +CHANGELOG* +TESTING* +MAINTAINERS.toml + +# Strainer # +############ +Colanderfile +Strainerfile +.colander +.strainer + +# Vagrant # +########### +.vagrant +Vagrantfile diff --git a/cookbooks/timezone_iii/metadata.json b/cookbooks/timezone_iii/metadata.json new file mode 100644 index 0000000..3bb096d --- /dev/null +++ b/cookbooks/timezone_iii/metadata.json @@ -0,0 +1,62 @@ +{ + "name": "timezone_iii", + "description": "Configures the timezone for node", + "long_description": "[![Chef cookbook](https://img.shields.io/cookbook/v/timezone_iii.svg)]()\n[![Code Climate](https://codeclimate.com/github/Stromweld/timezone_iii/badges/gpa.svg)](https://codeclimate.com/github/Stromweld/timezone_iii)\n[![Issue Count](https://codeclimate.com/github/Stromweld/timezone_iii/badges/issue_count.svg)](https://codeclimate.com/github/Stromweld/timezone_iii)\n\n# timezone_iii\n\nThe Timezone III cookbook contains recipes for installing the latest tzdata (a.k.a. IANA or Olson) timezone database and setting the timezone on your system. It is a fork of the [timezone-ii cookbook by Lawrence Gilbert.](https://supermarket.chef.io/cookbooks/timezone-ii).\n\n## Requirements\n\nThis cookbook is known to work with:\n\n* Amazon Linux\n* CentOS and RHEL\n* Debian\n* Fedora\n* Gentoo\n* PLD Linux\n* Ubuntu\n* Windows\n\nIt _should_ work with any OS that uses the IANA/Olson timezone database and stores local timezone data in /etc/localtime (the only OS I know of that does _not_ do this is MS Windows). However, some OSs not mentioned above have their own system utility for setting the timezone, and this may overwrite the changes made by this cookbook.\n\n## Attributes\n\n| Attribute | Default | Comment |\n| ------------- | ------------- | ------------- |\n| ['timezone_iii']['timezone'] | 'value_for_platform_family(debian: 'Etc/UTC', default: 'UTC')' | String, timezone to set OS to |\n| ['timezone_iii']['tzdata_dir'] | '/usr/share/zoneinfo' | String, the path to the root of the tzdata files; the default value is for most known distributions of Linux |\n| ['timezone_iii']['localtime_path'] | '/etc/localtime' | String, the path to the file used by the kernel to read the local timezone's settings; the default works for Linux and other *ix variants |\n| ['timezone_iii']['use_symlink'] | false | Boolean, whether to use a symlink into the tzdata tree rather than make a copy of the appropriate timezone data file (amazon and linux_generic recipes only) |\n\n## Usage\n\nSet the ['timezone_iii']['timezone'] attribute to your desired timezone and include the \"timezone_iii\" recipe in your node's run list:\n\n {\n \"name\": \"my_node\",\n \"timezone_iii\" {\n \"timezone\": \"Africa/Timbuktu\"\n },\n \"run_list\": [\n \"recipe[timezone_iii]\"\n ]\n }\n\n### timezone_iii::default\n\nThe default recipe will first install or upgrade the IANA/Olson timezone database package for your OS (`timezone-data` on Gentoo, `tzdata` on all other linux platforms). Then it will call one of the recipes below according to your node's platform.\n\n### timezone_iii::amazon\n\nThis changes the timezone on Amazon Linux by:\n\n1. including the \"timezone_iii::linux_generic\" recipe then;\n2. including the \"timezone_iii::rhel\" recipe.\n\nRefer to the sections for those recipes for details.\n\n### timezone_iii::debian\n\nThis changes the timezone on Debian-family platforms by:\n\n1. writing the value of `['timezone_iii']['timezone']` to `/etc/timezone` then;\n2. calling `dpkg-reconfigure -f noninteractive tzdata`;\n3. if `dpkg-reconfigure` amends the timezone value (e.g. by changing \"UTC\" to \"Etc/UTC\" or \"EET\" to \"Europe/Helsinki\"), it logs a warning.\n\nOnly the `['timezone_iii']['timezone']` attribute is used; all others are ignored.\n\n### timezone_iii::linux_generic\n\nThis changes the time on all OSs without a more specific recipe. It assumes that the kernel gets data on the local timezone from `/etc/localtime`. (This is true for FreeBSD as well as Linux, so \"linux_generic\" is a bit of a misnomer.)\n\nWhat this recipe does:\n\n1. verifies that the value of `['timezone_iii']['timezone']` corresponds with a timezone data file under the directory specified in `timezone.tzdata_dir` (default:`/usr/share/zoneinfo`), then;\n2. creates a copy of or symbolic link to that data file in the path specified in `timezone.localtime_path` (default: `/etc/localtime`).\n\nThe truthiness of `timezone.use_symlink` (default: `false`) determines whether a symlink or a copy is made.\n\n### timezone_iii::pld\n\nThis changes the timezone on PLD Linux. It writes the appropriate timezone configuration file, making use of the `['timezone_iii']['timezone']` and `['timezone_iii']['tzdata_dir']` attributes. Other attributes are ignored.\n\n### timezone_iii::rhel\n\nThis changes the timezone on RedHat Enterprise Linux (RHEL) and RHEL-family platforms such as CentOS. It is intended only for versions prior to 7.0, but should the recipe be called on a system with version 7.0 or newer, it will automatically include the \"timezone_iii::rhel7\" recipe and do nothing else.\n\nThis recipe updates the `/etc/sysconfig/clock` file with the value of the `['timezone_iii']['timezone']` attribute, then calls `tzdata-update` (if available) to change the timezone. All node attributes other than `['timezone_iii']['timezone']` are ignored.\n\n### timezone_iii::rhel7\n\nThis changes the timezone on EL 7 platforms by calling `timedatectl set-timezone` with the value of `['timezone_iii']['timezone']`.\n\nOnly the `['timezone_iii']['timezone']` attribute is used; all others are ignored.\n\n### timezone_iii::windows\n\nThis changes the timezone on windows platforms by calling `tzutil.exe` with the value of `['timezone_iii']['timezone']`. To get a list of timezones to use with windows you can run the command `tzutil.exe /l | more` on the command line and use the standard name under the offset info.\n\nOnly the `['timezone_iii']['timezone']` attribute is used; all others are ignored.\n\n## Contributing\n\n1. Fork the [repository on GitHub](https://github.com/Stromweld/timezone_iii);\n2. Write your change;\n3. If at all possible, write tests for your change and ensure they all pass;\n4. Submit a pull request using GitHub.\n\n## Acknowledgements\n\nThanks to:\n\n* Larry Gilbert, for launching the timezone-ii cookbook\n* James Harton, for launching the timezone cookbook\n* Elan Ruusamäe, for PLD support\n* Mike Conigliaro, for bringing testing up to date\n* \"fraD00r4\", for RHEL/CentOS support\n\n## License and Authors\n\n* Copyright © 2010 James Harton \n* Copyright © 2013-2015 Lawrence Leonard Gilbert \n* Copyright © 2013 Elan Ruusamäe \n* Copyright © 2013 fraD00r4 \n* Copyright © 2017 Corey Hemminger \n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\nthis file except in compliance with the License. You may obtain a copy of the\nLicense at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed\nunder the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\nCONDITIONS OF ANY KIND, either express or implied. See the License for the\nspecific language governing permissions and limitations under the License.\n", + "maintainer": "Corey Hemminger", + "maintainer_email": "hemminger@hotmail.com", + "license": "Apache-2.0", + "platforms": { + "amazon": ">= 0.0.0", + "centos": ">= 0.0.0", + "debian": ">= 0.0.0", + "fedora": ">= 0.0.0", + "gentoo": ">= 0.0.0", + "ubuntu": ">= 0.0.0", + "pld": ">= 0.0.0", + "redhat": ">= 0.0.0", + "windows": ">= 0.0.0" + }, + "dependencies": { + + }, + "recommendations": { + + }, + "suggestions": { + + }, + "conflicting": { + + }, + "providing": { + + }, + "replacing": { + "timezone": ">= 0.0.0", + "timezone-ii": ">= 0.0.0" + }, + "attributes": { + + }, + "groupings": { + + }, + "recipes": { + + }, + "version": "1.0.4", + "source_url": "https://github.com/Stromweld/timezone_iii", + "issues_url": "https://github.com/Stromweld/timezone_iii/issues", + "privacy": false, + "chef_versions": [ + [ + ">= 12.1" + ] + ], + "ohai_versions": [ + + ], + "gems": [ + + ] +} diff --git a/cookbooks/timezone_iii/metadata.rb b/cookbooks/timezone_iii/metadata.rb new file mode 100644 index 0000000..06c7ed6 --- /dev/null +++ b/cookbooks/timezone_iii/metadata.rb @@ -0,0 +1,27 @@ +name 'timezone_iii' +maintainer 'Corey Hemminger' +maintainer_email 'hemminger@hotmail.com' +license 'Apache-2.0' +description 'Configures the timezone for node' +long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) +version '1.0.4' +chef_version '>= 12.1' if respond_to?(:chef_version) + +# The `issues_url` points to the location where issues for this cookbook are +# tracked. A `View Issues` link will be displayed on this cookbook's page when +# uploaded to a Supermarket. +# +issues_url 'https://github.com/Stromweld/timezone_iii/issues' + +# The `source_url` points to the development reposiory for this cookbook. A +# `View Source` link will be displayed on this cookbook's page when uploaded to +# a Supermarket. +# +source_url 'https://github.com/Stromweld/timezone_iii' + +%w(amazon centos debian fedora gentoo ubuntu pld redhat windows).each do |os| + supports os +end + +replaces 'timezone' +replaces 'timezone-ii' diff --git a/cookbooks/timezone_iii/recipes/amazon.rb b/cookbooks/timezone_iii/recipes/amazon.rb new file mode 100644 index 0000000..51d32ed --- /dev/null +++ b/cookbooks/timezone_iii/recipes/amazon.rb @@ -0,0 +1,27 @@ +# +# Cookbook:: timezone_iii +# Recipe:: amazon +# +# Copyright:: 2017, Corey Hemminger +# +# 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. + +# Amazon recommends editing /etc/sysconfig/clock as in the rhel recipe, but then +# creating a link for /etc/localtime. It doesn't have a tzdata-update command +# like the other flavors of RHEL. +# +# Source: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/set-time.html +# (as of 2014-12-18) + +include_recipe 'timezone_iii::linux_generic' +include_recipe 'timezone_iii::rhel' diff --git a/cookbooks/timezone_iii/recipes/debian.rb b/cookbooks/timezone_iii/recipes/debian.rb new file mode 100644 index 0000000..c96431f --- /dev/null +++ b/cookbooks/timezone_iii/recipes/debian.rb @@ -0,0 +1,61 @@ +# +# Cookbook:: timezone_iii +# Recipe:: debian +# +# Copyright:: 2017, Corey Hemminger +# +# 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. + +# Set timezone for Debian family: Put the timezone string in plain text in +# /etc/timezone and then re-run the tzdata configuration to pick it up. + +TIMEZONE_FILE = '/etc/timezone'.freeze + +if File.file?('/etc/localtime') then + bash 'check-localtime' do + user 'root' + cwd '/tmp' + code <<-EOH + ls -la /etc/localtime >> /tmp/check.txt + if grep node['timezone_iii']['timezone'] /tmp/check.txt ; then + echo "Nothing to do!!!" + else + rm /etc/localtime + fi + rm /tmp/check.txt + EOH + end +end + +template TIMEZONE_FILE do + source 'timezone.conf.erb' + owner 'root' + group 'root' + mode '0644' + notifies :run, 'execute[dpkg-reconfigure-tzdata]' +end + +execute 'dpkg-reconfigure-tzdata' do + command '/usr/sbin/dpkg-reconfigure -f noninteractive tzdata' + action :nothing +end + +# Certain values get normalized by dpkg-reconfigure, causing this recipe to try +# to rewrite the file over and over. This raises a red flag in such a case. +log 'if-unexpected-timezone-change' do + message "dpkg-reconfigure is amending the value #{node['timezone_iii']['timezone'].inspect} in #{TIMEZONE_FILE}" + level :warn + not_if { ::File.read(TIMEZONE_FILE).chomp == node['timezone_iii']['timezone'] } + action :nothing + subscribes :write, 'execute[dpkg-reconfigure-tzdata]', :immediately +end diff --git a/cookbooks/timezone_iii/recipes/default.rb b/cookbooks/timezone_iii/recipes/default.rb new file mode 100644 index 0000000..0009d10 --- /dev/null +++ b/cookbooks/timezone_iii/recipes/default.rb @@ -0,0 +1,46 @@ +# +# Cookbook:: timezone_iii +# Recipe:: default +# +# Copyright:: 2017, Corey Hemminger +# +# 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. + +case node['os'] +when 'linux' + package value_for_platform_family( + gentoo: 'timezone-data', + default: 'tzdata' + ) + case node['platform_family'] + when 'rhel', 'fedora' + include_recipe node['platform_version'].split('.')[0].to_i >= 7 ? 'timezone_iii::rhel7' : 'timezone_iii::rhel' + when 'debian', 'pld', 'amazon' + include_recipe "timezone_iii::#{node['platform_family']}" + else + # Load the generic Linux recipe if there's no better known way to change the + # timezone. Log a warning (unless this is known to be the best way on a + # particular platform). + message = "Linux platform '#{node['platform']}' is unknown to this recipe; using generic Linux method" + log message do + level :warn + not_if { %w(centos gentoo rhel amazon).include? node['platform_family'] } + only_if { node['os'] == 'linux' } + end + include_recipe 'timezone_iii::linux_generic' + end +when 'windows' + include_recipe 'timezone_iii::windows' +else + raise 'OS Unsuported' +end diff --git a/cookbooks/timezone_iii/recipes/linux_generic.rb b/cookbooks/timezone_iii/recipes/linux_generic.rb new file mode 100644 index 0000000..f44f4e4 --- /dev/null +++ b/cookbooks/timezone_iii/recipes/linux_generic.rb @@ -0,0 +1,49 @@ +# +# Cookbook:: timezone_iii +# Recipe:: linux_generic +# +# Copyright:: 2017, Corey Hemminger +# +# 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. + +# Generic timezone-changing method for Linux that should work for any distro +# without a platform-specific method. + +timezone_data_file = File.join(node['timezone_iii']['tzdata_dir'], node['timezone_iii']['timezone']) +localtime_path = node['timezone_iii']['localtime_path'] + +ruby_block 'confirm timezone' do + block do + unless File.exist?(timezone_data_file) + raise "Can't find #{timezone_data_file}!" + end + end +end + +if node['timezone_iii']['use_symlink'] + link localtime_path do + to timezone_data_file + owner 'root' + group 'root' + mode '0644' + end + +else + file localtime_path do + content File.open(timezone_data_file, 'rb').read + owner 'root' + group 'root' + mode '0644' + not_if { File.symlink?(localtime_path) && Chef::Log.error("You must remove symbolic link at #{localtime_path} or set attribute ['timezone']['use_symlink'] = true") } + end +end diff --git a/cookbooks/timezone_iii/recipes/pld.rb b/cookbooks/timezone_iii/recipes/pld.rb new file mode 100644 index 0000000..8406efd --- /dev/null +++ b/cookbooks/timezone_iii/recipes/pld.rb @@ -0,0 +1,32 @@ +# +# Cookbook:: timezone_iii +# Recipe:: pld +# +# Copyright:: 2017, Corey Hemminger +# +# 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. + +# Set timezone for PLD family: Put the timezone string in plain text in +# /etc/sysconfig/timezone and then re-run the timezone service to pick it up. + +template '/etc/sysconfig/timezone' do + source 'pld/timezone.conf.erb' + owner 'root' + group 'root' + mode '0644' + notifies :reload, 'service[timezone]' +end + +service 'timezone' do + action :nothing +end diff --git a/cookbooks/timezone_iii/recipes/rhel.rb b/cookbooks/timezone_iii/recipes/rhel.rb new file mode 100644 index 0000000..e2ce208 --- /dev/null +++ b/cookbooks/timezone_iii/recipes/rhel.rb @@ -0,0 +1,38 @@ +# +# Cookbook:: timezone_iii +# Recipe:: rhel +# +# Copyright:: 2017, Corey Hemminger +# +# 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. + +# This recipe sets the timezone on EL 6 and older (RedHat Enterprise Linux, +# CentOS, etc.) +# +# If it is being run on EL 7 or newer, the recipe will be skipped and +# the "rhel7" recipe will be included instead. + +template '/etc/sysconfig/clock' do + source 'rhel/clock.erb' + owner 'root' + group 'root' + mode '0644' + notifies :run, 'execute[tzdata-update]' +end + +execute 'tzdata-update' do + command '/usr/sbin/tzdata-update' + action :nothing + # Amazon Linux doesn't have this command! + only_if { ::File.executable?('/usr/sbin/tzdata-update') } +end diff --git a/cookbooks/timezone_iii/recipes/rhel7.rb b/cookbooks/timezone_iii/recipes/rhel7.rb new file mode 100644 index 0000000..040d0fb --- /dev/null +++ b/cookbooks/timezone_iii/recipes/rhel7.rb @@ -0,0 +1,35 @@ +# +# Cookbook:: timezone_iii +# Recipe:: amazon +# +# Copyright:: 2017, Corey Hemminger +# +# 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. + +# This sets the timezone on EL 7 distributions (e.g. RedHat and CentOS) +execute "timedatectl --no-ask-password set-timezone #{node['timezone_iii']['timezone']}" + +template '/etc/sysconfig/clock' do + source 'rhel/clock.erb' + owner 'root' + group 'root' + mode '0644' + notifies :run, 'execute[tzdata-update]' +end + +execute 'tzdata-update' do + command '/usr/sbin/tzdata-update' + action :nothing + # Amazon Linux doesn't have this command! + only_if { ::File.executable?('/usr/sbin/tzdata-update') } +end diff --git a/cookbooks/timezone_iii/recipes/windows.rb b/cookbooks/timezone_iii/recipes/windows.rb new file mode 100644 index 0000000..ec9a428 --- /dev/null +++ b/cookbooks/timezone_iii/recipes/windows.rb @@ -0,0 +1,24 @@ +# +# Cookbook:: timezone_iii +# Recipe:: amazon +# +# Copyright:: 2017, Corey Hemminger +# +# 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. + +powershell_script 'set windows timezone' do + code <<-EOH + tzutil.exe /s "#{node['timezone_iii']['timezone']}" + EOH + not_if { shell_out('tzutil.exe /g').stdout.include?(node['timezone_iii']['timezone']) } +end diff --git a/cookbooks/timezone_iii/templates/default/pld/timezone.conf.erb b/cookbooks/timezone_iii/templates/default/pld/timezone.conf.erb new file mode 100644 index 0000000..b694bd7 --- /dev/null +++ b/cookbooks/timezone_iii/templates/default/pld/timezone.conf.erb @@ -0,0 +1,10 @@ +# Time zone information. + +# Directory containing zone information files. +ZONE_INFO_DIR="<%= node['timezone_iii']['tzdata_dir'] %>" + +# Scheme you would like to use in your system. +ZONE_INFO_SCHEME="posix" + +# Name of the time zone for your system. +TIMEZONE="<%= node['timezone_iii']['timezone'] %>" diff --git a/cookbooks/timezone_iii/templates/default/rhel/clock.erb b/cookbooks/timezone_iii/templates/default/rhel/clock.erb new file mode 100644 index 0000000..97a003c --- /dev/null +++ b/cookbooks/timezone_iii/templates/default/rhel/clock.erb @@ -0,0 +1 @@ +ZONE="<%= node['timezone_iii']['timezone'] %>" diff --git a/cookbooks/timezone_iii/templates/default/timezone.conf.erb b/cookbooks/timezone_iii/templates/default/timezone.conf.erb new file mode 100644 index 0000000..1182373 --- /dev/null +++ b/cookbooks/timezone_iii/templates/default/timezone.conf.erb @@ -0,0 +1 @@ +<%= node['timezone_iii']['timezone'] %> diff --git a/cookbooks/users/CHANGELOG.md b/cookbooks/users/CHANGELOG.md new file mode 100644 index 0000000..6659c3c --- /dev/null +++ b/cookbooks/users/CHANGELOG.md @@ -0,0 +1,174 @@ +# users Cookbook CHANGELOG + +This file is used to list changes made in each version of the users cookbook. + +## 5.3.1 (2017-12-15) + +- Remove special case for freebsd in favor of later shell validity check + +## 5.3.0 (2017-12-07) + +- Add check if user shell exists +- Verify the shell is allowed on AIX +- Add AIX as a supported platform + +## 5.2.2 (2017-11-29) + +- Add home directory base for solaris + +## 5.2.1 (2017-10-31) + +- Make sure ssh_keys can be an array or a string by converting strings to an array if they're passed + +## 5.2.0 (2017-10-31) + +- Require Chef 12.7+ as 12.5 and 12.6 had bugs in their custom resource implementation +- Allow fetching one or more ssh_keys from a url + +## 5.1.0 (2017-05-30) + +- Keep ssh keys out of the chef logs +- Improve docs and examples +- Remove class_eval and require Chef 12.7+ as class_eval causes issues with later Chef 12 releases + +## 5.0.0 (2017-04-17) + +### Breaking changes + +- The users_manage LWRP has been converted to a custom resource, which requires Chef 12.5 or later +- The sysadmins recipe contains no resources now and will do nothing + +### Other changes + +- Added integration tests with Inspec +- Fixed all deprecation warnings +- Fixed group creation on macOS when the group already exists +- Added suse platforms as supported in the metadata +- Switched to a SPDX apache-2.0 license string +- Moved all templates out of the default directory as we don't support Chef 11 anymore + +## 4.0.3 (2016-11-23) + +- Update manage provider to return true/false in guard block which avoids warnings during run on Chef 12.14+ + +## 4.0.2 (2016-11-18) + +- Deprecate the sysadmins recipe + +## 4.0.1 (2016-09-15) + +- Fix creation of user home directory + +## 4.0.0 (2016-09-15) + +- Add chef_version to the metadata +- Require Chef 12.1+ +- Testing updates +- Fixed compatibility with Chef 12.14 +- Properly define the Chefspec matcher +- Add a warning if someone includes users::default since that does nothing + +## v3.0.0 + +- @onlyhavecans - Fix FreeBSD support +- @stem - Fix user creation on Mac OS X on 10.7 and 10.8 +- Remove old style chef solo code to clean up rubocop issues, move to using cookstyle +- Adding zlinux support + +## v2.0.3 + +- @nkadel-skyhook - create .ssh directory only if keys are configured. +- @signe - allow force parameter to be specified for users configured to be removed. +- @FlorentFlament - adding the ability to manage groups for existing users. + +## v2.0.2 (2016-1-25) + +- @375gnu- validate uid/gid for strings versus numeric +- fix rubocop errors based on +- fix kitchen configurations for testing + +## v2.0.1 (2016-1-8) + +- Fixed provider to work on Mac OS X +- funzoneq - add correct default shell for FreeBSD if not provided +- Added kitchen.dokken to speed up platform testing + +## v2.0.0 (2015-12-11) + +- Removed Chef 10 compatibility code +- Removed the nodes fqdn from the authorized_keys file +- Removed a trailing comma in a readme example +- Added chef standard .gitignore and chefignore files +- Added chef standard .rubocop.yml file and resolved warnings +- Resolved foodcritic warnings + +## v1.8.2 (2015-03-18) + +- No changes, just republishing 1.8.1 + +## v1.8.1 (2015-03-12) + +- Add `source_url` and `issues_url` to the metadata.rb so Supermarket can display appropriate links + +## v1.8.0 (2015-03-09) + +- Expose LWRP state attributes +- [COOK-4401] - Add unit tests with ChefSpec +- [COOK-4404] - Determine file system and add manage_nfs_home_dirs attribute to disable managing NFS mounted home directories +- Remove `converge_by` when creating home directory, the directory resource already handles this +- Do not manage home directory if the path does not exist +- Add integration with TravisCI +- "Opscode" to "Chef" replacements +- Retire unsupported Ruby 1.9.3 and add Ruby 2.2 to the Travis integration tests +- Updates for RSpec 3 + +## v1.7.0 (2014-02-14) + +- [COOK-4139] - users_manage resource always notifies +- [COOK-4078] - users cookbook fails in why-run mode for .ssh directory +- [COOK-3959] - Add support for Mac OS X to users cookbook + +## v1.6.0 + +### Bug + +- **[COOK-3744](https://tickets.opscode.com/browse/COOK-3744)** - Allow passing an action option via the `data_bag` to the user resource + +## v1.5.2 + +### Bug + +- **[COOK-3215](https://tickets.opscode.com/browse/COOK-3215)** - Make `group_id` optional + +## v1.5.0 + +- [COOK-2427] - Mistakenly released instead of sudo :-). + +## v1.4.0 + +- [COOK-2479] - Permit users cookbook to work with chef-solo if edelight/chef-solo-search is installed +- [COOK-2486] - specify precedence when setting node attribute + +## v1.3.0 + +- [COOK-1842] - allow specifying private SSH keys +- [COOK-2021] - Empty default recipe for including users LWRPs + +## v1.2.0 + +- [COOK-1398] - Provider manage.rb ignores username attribute +- [COOK-1582] - ssh_keys should take an array in addition to a string separated by new lines + +## v1.1.4 + +- [COOK-1396] - removed users get recreated +- [COOK-1433] - resolve foodcritic warnings +- [COOK-1583] - set passwords for users + +## v1.1.2 + +- [COOK-1076] - authorized_keys template not found in another cookbook + +## v1.1.0 + +- [COOK-623] - LWRP conversion diff --git a/cookbooks/users/CONTRIBUTING.md b/cookbooks/users/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/users/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/cookbooks/users/README.md b/cookbooks/users/README.md new file mode 100644 index 0000000..ca1c606 --- /dev/null +++ b/cookbooks/users/README.md @@ -0,0 +1,338 @@ +# users Cookbook + +[![Build Status](https://travis-ci.org/chef-cookbooks/users.svg?branch=master)](http://travis-ci.org/chef-cookbooks/users) [![Cookbook Version](https://img.shields.io/cookbook/v/users.svg)](https://supermarket.chef.io/cookbooks/users) + +Manages OS users from databags. + +## Scope + +This cookbook is concerned with the management of OS users and groups from databags. It also manages the distribution of ssh keys to a user's home directory. + +## Requirements + +### Platforms + +The following platforms have been tested with Test Kitchen: + +- Debian / Ubuntu derivatives +- RHEL and derivatives +- Fedora +- openSUSE / SUSE Linux Enterprises +- FreeBSD / OpenBSD +- Mac OS X +- AIX + +### Chef + +- Chef 12.7+ + +### Cookbooks + +- none + +## Usage + +To use the resource `users_manage`, make sure to add the dependency on the users cookbook by the following line to your wrapper cookbook's [metadata.rb](https://docs.chef.io/config_rb_metadata.html): + +``` +depends 'users' +``` + +or to pin to a specific version of the users cookbook, in this case any version of 2.X: + +``` +depends 'users', '~> 2' +``` + +Then in a recipe use the `user_manage` resource to add all users in the defined group to the system: + +```ruby +users_manage 'GROUPNAME' do + group_id GROUPID + action [:create] + data_bag 'DATABAG_NAME' +end +``` + +Example: + +```ruby +users_manage 'testgroup' do + group_id 3000 + action [:create] + data_bag 'test_home_dir' +end +``` + +**Note**: If you do not specify the data_bag, the default will be to look for a databag called users. + +## Databag Definition + +A sample user object in a users databag would look like: + +```json +{ + "id": "test_user", + "password": "$1$5cE1rI/9$4p0fomh9U4kAI23qUlZVv/", + "ssh_keys": [ + "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU\nGPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3\nPbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA\nt3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En\nmZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx\nNrRFi9wrf+M7Q== chefuser@mylaptop.local", + "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU\nGPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3\nPbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA\nt3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En\nmZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx\nNQCPO0ZZEa1== chefuser@mylaptop.local" + ], + "groups": [ "testgroup", "nfsgroup" ], + "uid": 9001, + "shell": "\/bin\/bash", + "comment": "Test User" +} +``` + +A sample user to remove from a system would like like: + +```json +{ + "id": "mwaddams", + "action": "remove", + "groups": [ "testgroup", "nfsgroup" ] +} +``` + +### Databag Key Definitions + +- `id`: _String_ specifies the username, as well as the data bag object id. +- `password`: _String_ specifies the user's password. +- `ssh_keys`: _Array_ an array of authorized keys that will be managed by Chef to the user's home directory in `$HOME/.ssh/authorized_keys`. A key can include an `https` endpoint that returns a line seperated list of keys such as `https://github.com/$GITHUB_USERNAME.keys` this will retrieve all the keys and add it to the array and can be used with static keys as well as dynamic ones. +- `groups`: _Array_ an array of groups that the user will be added to +- `uid`: _Integer_ a unique identifier for the user +- `shell`: _String_ the user's shell +- `comment`:_String_ the [GECOS field](https://en.wikipedia.org/wiki/Gecos_field), generally the User's full name. + +Other potential fields: + +- `home`: _String_ User's home directory. If not assigned, will be set based on platform and username. +- `action`: _String_ Supported actions are one's supported by the [user](https://docs.chef.io/resource_user.html#actions) resource. If not specified, the default action is `create`. +- `ssh_private_key`: _String_ manages user's private key generally ~/.ssh/id_* +- `ssh_public_key`: _String_ manages user's public key generally ~/.ssh/id_*.pub + +## Resources Overview + +### users_manage + +The `users_manage` resource manages users and groups based off of a data bag search and specified action. + +#### Examples + +Creates the `sysadmin` group and users defined in the `users` databag. + +```ruby +users_manage 'sysadmin' do + group_id 2300 + action [:create] +end +``` + +Creates the `testgroup` group, and users defined in the `test_home_dir` databag. + +```ruby +users_manage 'testgroup' do + group_id 3000 + action [:create] + data_bag 'test_home_dir' +end +``` + +Creates the `nfsgroup` group, and users defined in the `test_home_dir` databag and does not manage nfs home directories. + +```ruby +users_manage 'nfsgroup' do + group_id 4000 + action [:create] + data_bag 'test_home_dir' + manage_nfs_home_dirs false +end +``` + +#### Parameters + +- `data_bag` _String_ is the data bag to search +- `search_group` _String_ groups name to search for, defaults to resource name +- `group_name` _String_ name of the group to create, defaults to resource name +- `group_id` _Integer_ numeric id of the group to create, default is to allow the OS to pick next +- `cookbook` _String_ name of the cookbook that the authorized_keys template should be found in +- `manage_nfs_home_dirs` _Boolean_ whether to manage nfs home directories. + +Otherwise, this cookbook is specific for setting up `sysadmin` group and users with the sysadmins recipe for now. + +## Recipe Overview + +### Deprecation Notice + +This recipe has been deprecated and the resource will be removed from the recipe in a new major release of this cookbook in April 2017\. The functionality can easily be recreated and changed to suit your organization by copying the single resource below into your own cookbook. + +`sysadmins.rb`: recipe that manages the group sysadmins with group id 2300, and adds users to this group. + +To use: + +```ruby +include_recipe "users::sysadmins" +``` + +The recipe is defined as follows: + +```ruby +users_manage "sysadmin" do + group_id 2300 + action [ :create ] +end +``` + +This `users_manage` resource searches the `users` data bag for the `sysadmin` group attribute, and adds those users to a Unix security group `sysadmin`. The only required attribute is group_id, which represents the numeric Unix gid and _must_ be unique. The default action for the resource is `:create`. + +The recipe, by default, will also create the sysadmin group. The sysadmin group will be created with GID 2300. + +## Data bag Overview + +**Reminder** Data bags generally should not be stored in cookbooks, but in a policy repo within your organization. Data bags are useful across cookbooks, not just for a single cookbook. + +Use knife to create a data bag for users. + +```bash +$ knife data bag create users +``` + +Create a user in the data_bag/users/ directory. + +An optional password hash can be specified that will be used as the user's password. + +The hash can be generated with the following command. + +```bash +$ openssl passwd -1 "plaintextpassword" +``` + +Note: The ssh_keys attribute below can be either a String or an Array. However, we are recommending the use of an Array. + +```json +{ + "id": "bofh", + "ssh_keys": "ssh-rsa AAAAB3Nz...yhCw== bofh" +} +``` + +```json +{ + "id": "bofh", + "password": "$1$d...HgH0", + "ssh_keys": [ + "ssh-rsa AAA123...xyz== foo", + "ssh-rsa AAA456...uvw== bar" + ], + "groups": [ "sysadmin", "dba", "devops" ], + "uid": 2001, + "shell": "\/bin\/bash", + "comment": "BOFH" +} +``` + +You can pass any action listed in the [user](http://docs.chef.io/chef/resources.html#user) resource for Chef via the "action" option. For Example: + +Lock a user, johndoe1. + +```bash +$ knife data bag edit users johndoe1 +``` + +And then change the action to "lock": + +```javascript +{ + "id": "johndoe1", + "groups": ["sysadmin", "dba", "devops"], + "uid": 2002, + "action": "lock", // <-- + "comment": "User violated access policy" +} +``` + +Remove a user, johndoe1. + +```bash +$ knife data bag edit users johndoe1 +``` + +And then change the action to "remove": + +```javascript +{ + "id": "johndoe1", + "groups": [ "sysadmin", "dba", "devops" ], + "uid": 2002, + "action": "remove", // <-- + "comment": "User quit, retired, or fired." +} +``` + +- Note only user bags with the "action : remove" and a search-able "group" attribute will be purged by the :remove action. +- As of v2.0.3 you can use the force parameter within the user data bag object for users with action remove. As per [user docs](https://docs.chef.io/resource_user.html) this may leave the system in an inconsistent state. For example, a user account will be removed even if the user is logged in. A user's home directory will be removed, even if that directory is shared by multiple users. + +If you have different requirements, for example: + +- You want to search a different data bag specific to a role such as +- mail. You may change the data_bag searched. + + - data_bag `mail` + +- You want to search for a different group attribute named + +- `postmaster`. You may change the search_group attribute. This + +- attribute defaults to the LWRP resource name. + + - search_group `postmaster` + +- You want to add the users to a security group other than the + +- lightweight resource name. You may change the group_name attribute. + +- This attribute also defaults to the LWRP resource name. + + - group_name `wheel` + +Putting these requirements together our recipe might look like this: + +```ruby +users_manage "postmaster" do + data_bag "mail" + group_name "wheel" + group_id 10 +end +``` + +Knife supports reading data bags from a file and automatically looks in a directory called +data_bags+ in the current directory. The "bag" should be a directory with JSON files of each item. For the above: + +```bash +$ mkdir data_bags/users +$EDITOR data_bags/users/bofh.json +``` + +Paste the user's public SSH key into the ssh_keys value. Also make sure the uid is unique, and if you're not using bash, that the shell is installed. + +The Apache cookbook can set up authentication using OpenIDs, which is set up using the openid key here. See the Chef Software 'apache2' cookbook for more information about this. + +## License & Authors + +**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io)) + +**Copyright:** 2009-2017, Chef Software, Inc. + +``` +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/cookbooks/users/libraries/helpers.rb b/cookbooks/users/libraries/helpers.rb new file mode 100644 index 0000000..c38576b --- /dev/null +++ b/cookbooks/users/libraries/helpers.rb @@ -0,0 +1,78 @@ +module Users + # Helpers for Users + module Helpers + # Checks fs type. + # + # @return [String] + def fs_type(mount) + # Doesn't support macosx + stat = Mixlib::ShellOut.new("stat -f -L -c %T #{mount} 2>&1").run_command + stat.stdout.chomp + rescue + 'none' + end + + # Determines if provided mount point is remote. + # + # @return [Boolean] + def fs_remote?(mount) + fs_type(mount) == 'nfs' ? true : false + end + + def keys_from_url(url) + host = url.split('/')[0..2].join('/') + path = url.split('/')[3..-1].join('/') + begin + response = Chef::HTTP.new(host).get(path) + response.split("\n") + rescue Net::HTTPServerException => e + p "request: #{host}#{path}, error: #{e}" + end + end + + # Determines if the user's shell is valid on the machine, otherwise + # returns the default of /bin/sh + # + # @return [String] + def shell_is_valid?(shell_path) + return false if shell_path.nil? || !File.exist?(shell_path) + # AIX is the only OS that has the concept of 'approved shells' + return true unless platform_family?('aix') + + begin + File.open('/etc/security/login.cfg') do |f| + f.each_line do |l| + l.match(/^\s*shells\s*=\s*(.*)/) do |m| + return true if m[1].split(/\s*,\s*/).any? { |entry| entry.eql? shell_path } + end + end + end + rescue + return false + end + + false + end + + # Validates passed id. + # + # @return [Numeric, String] + # handles checking whether uid was specified as a string + def validate_id(id) + id.to_i.to_s == id ? id.to_i : id + end + + # Returns the appropriate base user home directory per platform + # + # @return [ String] + def home_basedir + if platform_family?('mac_os_x') + '/Users' + elsif platform_family?('solaris2') + '/export/home' + else + '/home' + end + end + end +end diff --git a/cookbooks/users/libraries/matchers.rb b/cookbooks/users/libraries/matchers.rb new file mode 100644 index 0000000..9b3226e --- /dev/null +++ b/cookbooks/users/libraries/matchers.rb @@ -0,0 +1,15 @@ +if defined?(ChefSpec) + ChefSpec.define_matcher :users_manage + + def create_users_manage(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:users_manage, + :create, + resource_name) + end + + def remove_users_manage(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:users_manage, + :remove, + resource_name) + end +end diff --git a/cookbooks/users/libraries/osx_helper.rb b/cookbooks/users/libraries/osx_helper.rb new file mode 100644 index 0000000..d195e76 --- /dev/null +++ b/cookbooks/users/libraries/osx_helper.rb @@ -0,0 +1,29 @@ +module Users + # Helpers for Users + module OsxHelper + def dscl(*args) + host = '.' + stdout_result = '' + stderr_result = '' + cmd = "dscl #{host} -#{args.join(' ')}" + status = shell_out(cmd) + status.stdout.each_line { |line| stdout_result << line } + status.stderr.each_line { |line| stderr_result << line } + [cmd, status, stdout_result, stderr_result] + end + + def safe_dscl(*args) + result = dscl(*args) + return '' if (args.first =~ /^delete/) && (result[1].exitstatus != 0) + raise(Chef::Exceptions::Group, "dscl error: #{result.inspect}") unless result[1].exitstatus == 0 + raise(Chef::Exceptions::Group, "dscl error: #{result.inspect}") if result[2] =~ /No such key: / + result[2] + end + + def gid_used?(gid) + return false unless gid + groups_gids = safe_dscl('list /Groups gid') + !!(groups_gids =~ Regexp.new("#{Regexp.escape(gid.to_s)}\n")) + end + end +end diff --git a/cookbooks/users/metadata.json b/cookbooks/users/metadata.json new file mode 100644 index 0000000..aae1122 --- /dev/null +++ b/cookbooks/users/metadata.json @@ -0,0 +1 @@ +{"name":"users","version":"5.3.1","description":"Creates users from a databag search","long_description":"# users Cookbook\n\n[![Build Status](https://travis-ci.org/chef-cookbooks/users.svg?branch=master)](http://travis-ci.org/chef-cookbooks/users) [![Cookbook Version](https://img.shields.io/cookbook/v/users.svg)](https://supermarket.chef.io/cookbooks/users)\n\nManages OS users from databags.\n\n## Scope\n\nThis cookbook is concerned with the management of OS users and groups from databags. It also manages the distribution of ssh keys to a user's home directory.\n\n## Requirements\n\n### Platforms\n\nThe following platforms have been tested with Test Kitchen:\n\n- Debian / Ubuntu derivatives\n- RHEL and derivatives\n- Fedora\n- openSUSE / SUSE Linux Enterprises\n- FreeBSD / OpenBSD\n- Mac OS X\n- AIX\n\n### Chef\n\n- Chef 12.7+\n\n### Cookbooks\n\n- none\n\n## Usage\n\nTo use the resource `users_manage`, make sure to add the dependency on the users cookbook by the following line to your wrapper cookbook's [metadata.rb](https://docs.chef.io/config_rb_metadata.html):\n\n```\ndepends 'users'\n```\n\nor to pin to a specific version of the users cookbook, in this case any version of 2.X:\n\n```\ndepends 'users', '~> 2'\n```\n\nThen in a recipe use the `user_manage` resource to add all users in the defined group to the system:\n\n```ruby\nusers_manage 'GROUPNAME' do\n group_id GROUPID\n action [:create]\n data_bag 'DATABAG_NAME'\nend\n```\n\nExample:\n\n```ruby\nusers_manage 'testgroup' do\n group_id 3000\n action [:create]\n data_bag 'test_home_dir'\nend\n```\n\n**Note**: If you do not specify the data_bag, the default will be to look for a databag called users.\n\n## Databag Definition\n\nA sample user object in a users databag would look like:\n\n```json\n{\n \"id\": \"test_user\",\n \"password\": \"$1$5cE1rI/9$4p0fomh9U4kAI23qUlZVv/\",\n \"ssh_keys\": [\n \"ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU\\nGPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3\\nPbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA\\nt3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En\\nmZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx\\nNrRFi9wrf+M7Q== chefuser@mylaptop.local\",\n \"ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU\\nGPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3\\nPbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA\\nt3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En\\nmZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx\\nNQCPO0ZZEa1== chefuser@mylaptop.local\"\n ],\n \"groups\": [ \"testgroup\", \"nfsgroup\" ],\n \"uid\": 9001,\n \"shell\": \"\\/bin\\/bash\",\n \"comment\": \"Test User\"\n}\n```\n\nA sample user to remove from a system would like like:\n\n```json\n{\n \"id\": \"mwaddams\",\n \"action\": \"remove\",\n \"groups\": [ \"testgroup\", \"nfsgroup\" ]\n}\n```\n\n### Databag Key Definitions\n\n- `id`: _String_ specifies the username, as well as the data bag object id.\n- `password`: _String_ specifies the user's password.\n- `ssh_keys`: _Array_ an array of authorized keys that will be managed by Chef to the user's home directory in `$HOME/.ssh/authorized_keys`. A key can include an `https` endpoint that returns a line seperated list of keys such as `https://github.com/$GITHUB_USERNAME.keys` this will retrieve all the keys and add it to the array and can be used with static keys as well as dynamic ones.\n- `groups`: _Array_ an array of groups that the user will be added to\n- `uid`: _Integer_ a unique identifier for the user\n- `shell`: _String_ the user's shell\n- `comment`:_String_ the [GECOS field](https://en.wikipedia.org/wiki/Gecos_field), generally the User's full name.\n\nOther potential fields:\n\n- `home`: _String_ User's home directory. If not assigned, will be set based on platform and username.\n- `action`: _String_ Supported actions are one's supported by the [user](https://docs.chef.io/resource_user.html#actions) resource. If not specified, the default action is `create`.\n- `ssh_private_key`: _String_ manages user's private key generally ~/.ssh/id_*\n- `ssh_public_key`: _String_ manages user's public key generally ~/.ssh/id_*.pub\n\n## Resources Overview\n\n### users_manage\n\nThe `users_manage` resource manages users and groups based off of a data bag search and specified action.\n\n#### Examples\n\nCreates the `sysadmin` group and users defined in the `users` databag.\n\n```ruby\nusers_manage 'sysadmin' do\n group_id 2300\n action [:create]\nend\n```\n\nCreates the `testgroup` group, and users defined in the `test_home_dir` databag.\n\n```ruby\nusers_manage 'testgroup' do\n group_id 3000\n action [:create]\n data_bag 'test_home_dir'\nend\n```\n\nCreates the `nfsgroup` group, and users defined in the `test_home_dir` databag and does not manage nfs home directories.\n\n```ruby\nusers_manage 'nfsgroup' do\n group_id 4000\n action [:create]\n data_bag 'test_home_dir'\n manage_nfs_home_dirs false\nend\n```\n\n#### Parameters\n\n- `data_bag` _String_ is the data bag to search\n- `search_group` _String_ groups name to search for, defaults to resource name\n- `group_name` _String_ name of the group to create, defaults to resource name\n- `group_id` _Integer_ numeric id of the group to create, default is to allow the OS to pick next\n- `cookbook` _String_ name of the cookbook that the authorized_keys template should be found in\n- `manage_nfs_home_dirs` _Boolean_ whether to manage nfs home directories.\n\nOtherwise, this cookbook is specific for setting up `sysadmin` group and users with the sysadmins recipe for now.\n\n## Recipe Overview\n\n### Deprecation Notice\n\nThis recipe has been deprecated and the resource will be removed from the recipe in a new major release of this cookbook in April 2017\\. The functionality can easily be recreated and changed to suit your organization by copying the single resource below into your own cookbook.\n\n`sysadmins.rb`: recipe that manages the group sysadmins with group id 2300, and adds users to this group.\n\nTo use:\n\n```ruby\ninclude_recipe \"users::sysadmins\"\n```\n\nThe recipe is defined as follows:\n\n```ruby\nusers_manage \"sysadmin\" do\n group_id 2300\n action [ :create ]\nend\n```\n\nThis `users_manage` resource searches the `users` data bag for the `sysadmin` group attribute, and adds those users to a Unix security group `sysadmin`. The only required attribute is group_id, which represents the numeric Unix gid and _must_ be unique. The default action for the resource is `:create`.\n\nThe recipe, by default, will also create the sysadmin group. The sysadmin group will be created with GID 2300.\n\n## Data bag Overview\n\n**Reminder** Data bags generally should not be stored in cookbooks, but in a policy repo within your organization. Data bags are useful across cookbooks, not just for a single cookbook.\n\nUse knife to create a data bag for users.\n\n```bash\n$ knife data bag create users\n```\n\nCreate a user in the data_bag/users/ directory.\n\nAn optional password hash can be specified that will be used as the user's password.\n\nThe hash can be generated with the following command.\n\n```bash\n$ openssl passwd -1 \"plaintextpassword\"\n```\n\nNote: The ssh_keys attribute below can be either a String or an Array. However, we are recommending the use of an Array.\n\n```json\n{\n \"id\": \"bofh\",\n \"ssh_keys\": \"ssh-rsa AAAAB3Nz...yhCw== bofh\"\n}\n```\n\n```json\n{\n \"id\": \"bofh\",\n \"password\": \"$1$d...HgH0\",\n \"ssh_keys\": [\n \"ssh-rsa AAA123...xyz== foo\",\n \"ssh-rsa AAA456...uvw== bar\"\n ],\n \"groups\": [ \"sysadmin\", \"dba\", \"devops\" ],\n \"uid\": 2001,\n \"shell\": \"\\/bin\\/bash\",\n \"comment\": \"BOFH\"\n}\n```\n\nYou can pass any action listed in the [user](http://docs.chef.io/chef/resources.html#user) resource for Chef via the \"action\" option. For Example:\n\nLock a user, johndoe1.\n\n```bash\n$ knife data bag edit users johndoe1\n```\n\nAnd then change the action to \"lock\":\n\n```javascript\n{\n \"id\": \"johndoe1\",\n \"groups\": [\"sysadmin\", \"dba\", \"devops\"],\n \"uid\": 2002,\n \"action\": \"lock\", // <--\n \"comment\": \"User violated access policy\"\n}\n```\n\nRemove a user, johndoe1.\n\n```bash\n$ knife data bag edit users johndoe1\n```\n\nAnd then change the action to \"remove\":\n\n```javascript\n{\n \"id\": \"johndoe1\",\n \"groups\": [ \"sysadmin\", \"dba\", \"devops\" ],\n \"uid\": 2002,\n \"action\": \"remove\", // <--\n \"comment\": \"User quit, retired, or fired.\"\n}\n```\n\n- Note only user bags with the \"action : remove\" and a search-able \"group\" attribute will be purged by the :remove action.\n- As of v2.0.3 you can use the force parameter within the user data bag object for users with action remove. As per [user docs](https://docs.chef.io/resource_user.html) this may leave the system in an inconsistent state. For example, a user account will be removed even if the user is logged in. A user's home directory will be removed, even if that directory is shared by multiple users.\n\nIf you have different requirements, for example:\n\n- You want to search a different data bag specific to a role such as\n- mail. You may change the data_bag searched.\n\n - data_bag `mail`\n\n- You want to search for a different group attribute named\n\n- `postmaster`. You may change the search_group attribute. This\n\n- attribute defaults to the LWRP resource name.\n\n - search_group `postmaster`\n\n- You want to add the users to a security group other than the\n\n- lightweight resource name. You may change the group_name attribute.\n\n- This attribute also defaults to the LWRP resource name.\n\n - group_name `wheel`\n\nPutting these requirements together our recipe might look like this:\n\n```ruby\nusers_manage \"postmaster\" do\n data_bag \"mail\"\n group_name \"wheel\"\n group_id 10\nend\n```\n\nKnife supports reading data bags from a file and automatically looks in a directory called +data_bags+ in the current directory. The \"bag\" should be a directory with JSON files of each item. For the above:\n\n```bash\n$ mkdir data_bags/users\n$EDITOR data_bags/users/bofh.json\n```\n\nPaste the user's public SSH key into the ssh_keys value. Also make sure the uid is unique, and if you're not using bash, that the shell is installed.\n\nThe Apache cookbook can set up authentication using OpenIDs, which is set up using the openid key here. See the Chef Software 'apache2' cookbook for more information about this.\n\n## License & Authors\n\n**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io))\n\n**Copyright:** 2009-2017, Chef Software, Inc.\n\n```\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"ubuntu":">= 0.0.0","debian":">= 0.0.0","redhat":">= 0.0.0","centos":">= 0.0.0","fedora":">= 0.0.0","freebsd":">= 0.0.0","mac_os_x":">= 0.0.0","scientific":">= 0.0.0","oracle":">= 0.0.0","amazon":">= 0.0.0","zlinux":">= 0.0.0","suse":">= 0.0.0","opensuse":">= 0.0.0","opensuseleap":">= 0.0.0","aix":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/chef-cookbooks/users","issues_url":"https://github.com/chef-cookbooks/users/issues","chef_version":[[">= 12.7"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/users/recipes/default.rb b/cookbooks/users/recipes/default.rb new file mode 100644 index 0000000..317ccf7 --- /dev/null +++ b/cookbooks/users/recipes/default.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: users +# Recipe:: default +# +# Copyright:: 2009-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +Chef::Log.warn('The default users recipe does nothing. See the readme for information on using the users resources') diff --git a/cookbooks/users/recipes/sysadmins.rb b/cookbooks/users/recipes/sysadmins.rb new file mode 100644 index 0000000..85ba4e7 --- /dev/null +++ b/cookbooks/users/recipes/sysadmins.rb @@ -0,0 +1,21 @@ +# +# Cookbook:: users +# Recipe:: sysadmins +# +# Copyright:: 2011-2017, Eric G. Wolfe +# Copyright:: 2009-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +Chef::Log.warn('The sysadmins recipe has been deprecated. We suggest using the users_manage resource in your own cookbook if you need similar functionality.') diff --git a/cookbooks/users/resources/manage.rb b/cookbooks/users/resources/manage.rb new file mode 100644 index 0000000..170d156 --- /dev/null +++ b/cookbooks/users/resources/manage.rb @@ -0,0 +1,186 @@ +# +# Cookbook:: users +# Resources:: manage +# +# Copyright:: 2011-2017, Eric G. Wolfe +# +# 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. +# + +# :data_bag is the object to search +# :search_group is the groups name to search for, defaults to resource name +# :group_name is the string name of the group to create, defaults to resource name +# :group_id is the numeric id of the group to create, default is to allow the OS to pick next +# :cookbook is the name of the cookbook that the authorized_keys template should be found in +property :data_bag, String, default: 'users' +property :search_group, String, name_property: true +property :group_name, String, name_property: true +property :group_id, Integer +property :cookbook, String, default: 'users' +property :manage_nfs_home_dirs, [true, false], default: true + +action :create do + users_groups = {} + users_groups[new_resource.group_name] = [] + + search(new_resource.data_bag, "groups:#{new_resource.search_group} AND NOT action:remove") do |u| + u['username'] ||= u['id'] + u['groups'].each do |g| + users_groups[g] = [] unless users_groups.key?(g) + users_groups[g] << u['username'] + end + + # Set home to location in data bag, + # or a reasonable default ($home_basedir/$user). + home_dir = (u['home'] ? u['home'] : "#{home_basedir}/#{u['username']}") + + # check whether home dir is null + manage_home = (home_dir == '/dev/null' ? false : true) + + # The user block will fail if the group does not yet exist. + # See the -g option limitations in man 8 useradd for an explanation. + # This should correct that without breaking functionality. + group u['username'] do # ~FC022 + case node['platform_family'] + when 'mac_os_x' + gid validate_id(u['gid']) unless gid_used?(validate_id(u['gid'])) || new_resource.group_name == u['username'] + else + gid validate_id(u['gid']) + end + only_if { u['gid'] && u['gid'].is_a?(Numeric) } + end + + # Create user object. + # Do NOT try to manage null home directories. + user u['username'] do + uid validate_id(u['uid']) + gid validate_id(u['gid']) if u['gid'] + shell shell_is_valid?(u['shell']) ? u['shell'] : '/bin/sh' + comment u['comment'] + password u['password'] if u['password'] + salt u['salt'] if u['salt'] + iterations u['iterations'] if u['iterations'] + manage_home manage_home + home home_dir + action u['action'] if u['action'] + end + + if manage_home_files?(home_dir, u['username']) + Chef::Log.debug("Managing home files for #{u['username']}") + + directory "#{home_dir}/.ssh" do + recursive true + owner u['uid'] ? validate_id(u['uid']) : u['username'] + group validate_id(u['gid']) if u['gid'] + mode '0700' + only_if { !!(u['ssh_keys'] || u['ssh_private_key'] || u['ssh_public_key']) } + end + + # loop over the keys and if we have a URL we should add each key + # from the url response and append it to the list of keys + ssh_keys = [] + if u['ssh_keys'] + Array(u['ssh_keys']).each do |key| + if key.start_with?('https') + ssh_keys += keys_from_url(key) + else + ssh_keys << key + end + end + end + + template "#{home_dir}/.ssh/authorized_keys" do + source 'authorized_keys.erb' + cookbook new_resource.cookbook + owner u['uid'] ? validate_id(u['uid']) : u['username'] + group validate_id(u['gid']) if u['gid'] + mode '0600' + sensitive true + # ssh_keys should be a combination of u['ssh_keys'] and any keys + # returned from a specified URL + variables ssh_keys: ssh_keys + only_if { !!(u['ssh_keys']) } + end + + if u['ssh_private_key'] + key_type = u['ssh_private_key'].include?('BEGIN RSA PRIVATE KEY') ? 'rsa' : 'dsa' + template "#{home_dir}/.ssh/id_#{key_type}" do + source 'private_key.erb' + cookbook new_resource.cookbook + owner u['uid'] ? validate_id(u['uid']) : u['username'] + group validate_id(u['gid']) if u['gid'] + mode '0400' + variables private_key: u['ssh_private_key'] + end + end + + if u['ssh_public_key'] + key_type = u['ssh_public_key'].include?('ssh-rsa') ? 'rsa' : 'dsa' + template "#{home_dir}/.ssh/id_#{key_type}.pub" do + source 'public_key.pub.erb' + cookbook new_resource.cookbook + owner u['uid'] ? validate_id(u['uid']) : u['username'] + group validate_id(u['gid']) if u['gid'] + mode '0400' + variables public_key: u['ssh_public_key'] + end + end + else + Chef::Log.debug("Not managing home files for #{u['username']}") + end + end + # Populating users to appropriates groups + users_groups.each do |g, u| + group g do + members u + append true + action :manage # Do nothing if group doesn't exist + end unless g == new_resource.group_name # Dealing with managed group later + end + + group new_resource.group_name do + case node['platform_family'] + when 'mac_os_x' + gid new_resource.group_id unless gid_used?(new_resource.group_id) + else + gid new_resource.group_id + end + members users_groups[new_resource.group_name] + end +end + +action :remove do + search(new_resource.data_bag, "groups:#{new_resource.search_group} AND action:remove") do |rm_user| + user rm_user['username'] ||= rm_user['id'] do + action :remove + force rm_user['force'] ||= false + end + end +end + +action_class do + include ::Users::Helpers + include ::Users::OsxHelper + + def manage_home_files?(home_dir, _user) + # Don't manage home dir if it's NFS mount + # and manage_nfs_home_dirs is disabled + if home_dir == '/dev/null' + false + elsif fs_remote?(home_dir) + new_resource.manage_nfs_home_dirs ? true : false + else + true + end + end +end diff --git a/cookbooks/users/templates/authorized_keys.erb b/cookbooks/users/templates/authorized_keys.erb new file mode 100644 index 0000000..f656d5f --- /dev/null +++ b/cookbooks/users/templates/authorized_keys.erb @@ -0,0 +1,6 @@ +# Generated by Chef +# Local modifications will be overwritten. + +<% Array(@ssh_keys).each do |key| %> +<%= key %> +<% end -%> diff --git a/cookbooks/users/templates/private_key.erb b/cookbooks/users/templates/private_key.erb new file mode 100644 index 0000000..f931c04 --- /dev/null +++ b/cookbooks/users/templates/private_key.erb @@ -0,0 +1 @@ +<%= @private_key %> diff --git a/cookbooks/users/templates/public_key.pub.erb b/cookbooks/users/templates/public_key.pub.erb new file mode 100644 index 0000000..31a7285 --- /dev/null +++ b/cookbooks/users/templates/public_key.pub.erb @@ -0,0 +1 @@ +<%= @public_key %> diff --git a/cookbooks/windows/CHANGELOG.md b/cookbooks/windows/CHANGELOG.md new file mode 100644 index 0000000..d88694c --- /dev/null +++ b/cookbooks/windows/CHANGELOG.md @@ -0,0 +1,846 @@ +# windows Cookbook CHANGELOG + +This file is used to list changes made in each version of the windows cookbook. + +## 6.0.0 (2019-04-25) + +### Breaking Changes + +- This cookbook now requires Chef 14 or later. As of April 2019 Chef 13 is EOL. If you are still running Chef 13 we highly suggest you begin your migration. Chef 14 provides a greatly improved Windows experience with built in resources for Windows clients. +- Resources that are built into Chef 14 and later have been removed from this cookbook: + - windows_auto_run + - windows_feature + - windows_font + - windows_pagefile + - windows_printer_port + - windows_printer + - windows_shortcut + +## 5.3.1 (2019-04-25) + +- Resolved failures on Chef 14.11 or later +- Removed OS detectio support in the helpers for Windows 2003 + +## 5.3.0 (2019-03-06) + +- Expanded certificate testing to cover more scenarios - [@Xorima](https://github.com/Xorima) +- Updated windows_share to better compare the current and desired path in order to prevent converging on each Chef run - [@Xorima](https://github.com/Xorima) +- Backported all windows_certificate fixes from Chef 14.8 - 14.11 including improvements to importing the types of certificates that can be imported, suppport for nested certs, and support for importing private keys with certs. + +## 5.2.4 (2019-02-28) + +- Fix http_acl regex to properly capture SDDL - [@Annih](https://github.com/Annih) +- Updated windows_share to create share if the share is deleted, and to sanitize paths using Chef::Util::PathHelper.cleanpath (#607) - [@Xorima](https://github.com/Xorima) + +## 5.3.3 (2019-01-30) + +- Updated windows_certificate code to match that in Chef 14.10. This increases the requirement of the win32_certstore gem to the latest and resolves multiple issues with the previous implementation. + +## 5.2.2 (2018-11-20) + +- windows_share: Accounts to be revoked should be provided as an individually quoted string array + +## 5.2.1 (2018-11-19) + +- windows_share: Fix idempotency by not adding everyone by default + +## 5.2.0 (2018-11-14) + +- Support installing deleted features in windows_feature_dism + +## 5.1.6 (2018-11-13) + +- Add a warning to the readme regarding windows_share and windows_certificate now being included in Chef 14.7 +- Deprecated win_friendly_path helper in favor of built-in helpers + +## 5.1.5 (2018-11-07) + +- Avoid deprecation warnings in windows_share and windows_certificate on Chef 14.7+ as these are now included in the chef-client itself. + +## 5.1.4 (2018-10-30) + +- Note the :verify action for windows_certificate in the readme +- certificate resource: auto set sensitive is passing password + +## 5.1.3 (2018-10-11) + +- Remove docs and test suite for windows tasks +- Changed variable name in log message for retrieving SMB share access +- Don't load the windows helper in windows_certificate + +## 5.1.2 (2018-10-08) + +- Fix typo in windows_feature_dism resource name + +## 5.1.1 (2018-09-06) + +- Require the win32-certstore gem and upgrade the gem as the resource runs so we get the most up to date version +- Remove redundant helper methods from the windows_certificate resource + +## 5.1.0 (2018-08-29) + +- Add an action to windows_user_privilege to remove a privilege +- Fix failing appveyor tests +- Require win32-certstore 0.1.8 which resolves several issues with the windows_certificate resource +- Avoid deprecation warnings with Chef 14.3+ by not loading resources that are now built into Chef + +## 5.0.0 (2018-07-24) + +### Breaking Changes + +This release removes the windows_task and windows_path resources from this cookbook. This resources shipped in Chef 13.0 and 13.4 This raises the required version of chef-client for this cookbook to 13.4 or later. + +## 4.3.4 (2018-07-18) + +- Fix error message typo in windows_feature_powershell +- Use win32-certstore 0.1.7 for bugfixes + +## 4.3.3 (2018-07-05) + +- Fix failures on PS 3.0 in windows_feature_powershell + +## 4.3.2 (2018-06-13) + +- Don't error in windows_feature_dism when providing a source + +## 4.3.1 (2018-06-11) + +- Make sure to quote each individual user to grant share access to + +## 4.3.0 (2018-06-11) + +- Add the windows_user_privilege resource which can grant privileges like Logon As a Service +- Add windows_feature_powershell support for Windows 2008 R2 by not downcasing the feature names there and modifying the shell_out commands to make older output look like the 2012+ output +- windows_certificate resource has been reworked to use the new win32-certstore gem. This gem abstracts away much of the logic and will allow us to better support certificates on Windows, especially on non-english systems. +- Convert pester tests to InSpec for easier testing with ChefDK out of the box +- Added additional tests for better testing in AppVeyor +- Stop importing the servermanager module in windows_feature_powershell since we require PowerShell 3.0 and we don't need to do this there +- Improve the error messages in Windows feature to get the Windows versions right +- Increase readability in version logic with helpers in windows_feature resources + +## 4.2.5 (2018-05-28) + +- Add quoting to Path when creating new Share + +## 4.2.4 (2018-05-14) + +- Fix the platform version check in windows_share + +## 4.2.3 (2018-05-07) + +- Include the helper in the action class to prevent failures with the zipfile resource + +## 4.2.2 (2018-04-24) + +- Properly fail in windows_share on Windows 2008 R2 since we lack the cmdlets to manipulates shares on those systems. + +## 4.2.1 (2018-04-17) + +- Make sure shares can have spaces in the share name + +## 4.2.0 (2018-04-16) + +- Initial rewrite of windows_share to use PowerShell for share creation. This introduces multiple new properties and resolves a good number of longstanding issues. Please be sure to report any issues you see with this so we can stabilize this resource and include it in Chef 15! +- Resolve failures in windows_certificate + +## 4.1.4 (2018-03-29) + +- Raise in windows_feature_powershell if we're on PS < 3.0 + +## 4.1.3 (2018-03-28) + +- Restore support for Windows 2008 R2 in windows_feature_dism + +## 4.1.2 (2018-03-27) + +- Improve creation messaging for shares +- Allow feature names to be case insensitive in windows_feature + +## 4.1.1 (2018-03-23) + +- Simplify delete action slightly in windows_pagefile +- Don't use win_friendly_path helper in windows_pagefile since we already coerce the path value + +## 4.1.0 (2018-03-21) + +- Adds Caching for WIndows Feature Powershell resource using the same sort of logic we use on windows_feature_dism. This gives us a 3.5X speedup when no features need to be changed (subsequent runs after the change) +- Warn if we're on w2k12 and trying to use source/management properties in windows_feature_powershell since that doesn't work. +- Properly parse features into arrays so installing an array of features works in dism/powershell. This is the preferred way to install a number of features and will be faster than a large number of feature resources +- Fix description of properties for pagefile in the readme + +## 4.0.2 (2018-03-20) + +- Enable FC016 testing +- Enable FC059 testing +- Properly calculate available packages if source is passed in windows_feature_dism resource + +## 4.0.1 (2018-03-07) + +Fix the previous update to windows_feature_dism to use 'override' level of attributes not the normal level which persists to the node. Thanks to @Annih for pointing out the mistake here. + +## 4.0.0 (2018-03-05) + +### WARNING + +This release contains a complete rewrite to windows_feature_dism resource and includes several behavior changes to windows_feature resource. Make sure to read the complete list of changes below before deploying this to production systems. + +#### DISM feature caching Ohai plugin replacement + +In the 3.X cookbook we installed an Ohai plugin that cached the state of features on the node, and we reloaded that plugin anytime we installed/removed a feature from the system. This greatly sped up Chef runs where no features were actually installed/removed (2nd run and later). Without the caching each resource would take about 1 second longer while it queried current feature state. Using Ohai to cache this data was problematic though due to incompatibilities with Chef Solo, the reliance on the ohai cookbook, and the addition of extra node data which had to be stored on the Chef Server. + +In the 4.0 release instead of caching data via an Ohai plugin we just write directly to the node within the resource. This avoids the need to load in the ohai plugin and the various issues that come with that. In the end it's basically the exact same thing, but less impacting on end users and faster when the data needs to be updated. + +#### Fail when feature is missing in windows_feature_dism + +The windows_feature_dism resource had a rather un-Chef behavior in which it just warned you if a feature wasn't available on your platform and then continued on silently. This isn't how we handle missing packages in any of our package resource and because of that it's not going to be what anyone expects out of the box. If someone really wants SNMP installed and we can't install it we should fail instead of continuing on as if we did install it. So we'll now do the following things: + +- When installing a feature that doesn't exist: fail +- When removing a feature that doesn't exist: continue since it is technically removed +- When deleting a feature that doesn't exist: continue since it is technically deleted + +For some users, particularly those writing community cookbooks, this is going to be a breaking change. I'd highly recommend putting logic within your cookbooks to only install features on supported releases of Windows. If you'd just like it to continue even with a failure you can also use `ignore_failure true` on your resource although this produces a lot of failure messaging in logs. + +#### Properly support features as an array in windows_feature_dism + +We claimed to support installing features as an array in the windows_feature_dism resource previously, but it didn't actually work. The actual result was a warning that the array of features wasn't available on your platform since we compared the array to available features as if it was a string. We now properly support installation as a array and we do validation on each feature in the array to make sure the features are available on your Windows release. + +#### Install as the default action in windows_feature_powershell + +Due to some previous refactoring the :install action was not the default action for windows_feature_powershell. For all other package resources in Chef install is the default so this would likely lead to some unexpected behavior in cookbooks. This is technically a breaking change, but I suspect everyone assumed :install was always the default. + +#### servermanagercmd.exe Support Removal + +This cookbook previously supported servermanagercmd.exe, which was necessary for feature installation on Windows 2003 / 2008 (not R2) systems. Windows 2003 went full EOL in 2015 and 2008 went into extended support in 2015\. Neither releases are supported platforms for Chef or this cookbook so we've chosen to simplify the code and remove support entirely. + +#### Remove the undocumented node['windows']['rubyzipversion'] attribute + +This attribute was a workaround for a bug in the rubyzip gem YEARS ago that's just not necessary anymore. We also never documented this attribute and a resource shouldn't change behavior based on attributes. + +## 3.5.2 (2018-03-01) + +- Remove value_for_feature_provider helper which wasn't being used and was using deprecated methods +- Add all the Windows Core editions to the version helper +- Simplify / speedup how we find the font directory in windows_font +- Don't bother enabling why-run mode in the resources since it's enabled by default +- Don't include mixlib-shellout in the resources since it's included by default +- Fix installation messaging for windows_feature_powershell to properly show all features being installed +- Use powershell for the share creation / deletion in windows_share. This speeds up the runs and fixes some of the failures. + +## 3.5.1 (2018-02-23) + +- Add a new `shortcut_name` property to `windows_shortcut` +- Use Chef's built in registry_key_exists helper in `windows_printer_port` +- Fix the `source` coerce in `windows_font` + +## 3.5.0 (2018-02-23) + +- Add Windows 2016 to the supported releases in the readme +- Add Windows 10 detection to the version helper +- Remove the Chefspec matchers. These are auto generated by ChefSpec now. If this causes your specs to fail upgrade ChefDK +- In `certificate_binding` support `hostnameport` option if address is a hostname +- Convert several tests to InSpec tests and add additional test scenarios +- Remove `required: true` on the name_properties, which serves no purpose and will be a Foodcritic rule in the next Foodcritic release +- Fix `windows_feature` logging to work when the user provides an array of features +- Don't both coercing a symbol into a symbol in the `windows_auto_run` resource. +- Switch `windows_font` over to the built in path helper in Chef, which a much more robust +- Don't coerce forward slashes to backslashes in the `windows_font` `source` property if the source is a URI +- Add a new `path` property to `windows_pagefile` for properly overriding the resource name +- Coerce backslashes to forward slashes in `windows_pagefile`'s `path` property so we do the right thing even if a user gives bad input +- Add a new `program_name` property in windows_auto_run for overriding the resource name +- Rename `program` property to `path` in windows_auto_run. The legacy name will continue to work, but cookbooks should be updated +- Coerce the `path` property to use backslashes in `windows_auto_run` so it works no matter what format of path the user provides +- Avoid writing out an extra space in `windows_auto_run`'s registry entry when the user doesn't specify an arg +- Added yard comments to many of the helper methods + +## 3.4.4 (2018-01-19) + +- Fix undefined method for 'ipv4_address' in windows_printer_port + +## 3.4.3 (2018-01-04) + +- Added missing parentheses around PersistKeySet flag that was preventing PowerShell from creating X509Certificate2 object + +## 3.4.2 (2018-01-02) + +- Add deprecation warnings for windows_path and windows_task which are now included in Chef 13\. These will be removed from this cookbook in Sept 2018. + +## 3.4.1 (2017-12-06) + +- Fix long-running filtering by replace LIKE with equality sign in the share resource +- Use logical OR instead of AND when trying to detect share permissions changing in the share resource +- Remove extra new_resource.updated_by_last_action in the windows_task resource that resulted in a Foodcritic warning + +## 3.4.0 (2017-11-14) + +- Add a root key property for the auto_run resource +- Fix a resource typo where a name_property was still written name_attribute +- Resolve FC108 warnings + +## 3.3.0 (2017-11-06) + +- Add new dns resource. See readme for examples +- Add BUILTIN\Users to SYSTEM_USERS for windows_task + +## 3.2.0 (2017-10-17) + +- Add management_tools property to windows_feature powershell provider which installs the various management tools +- Fix deprecations_namespace_collisions +- Add additional certificate store names +- Add the ability to define a timeout on windows_feature +- Multiple improvements to the font resource + + - Improved logging, particularly debug logging + - Allow pulling the font from a remote location using remote_file + - Fix some failures in fetching local fonts + - Added a font_name property that allows you specify the local name of the font, which can be different from the name of the chef resource. This allows you to create more friendly resource names for your converge. + - Handle font resources with backslashes in their source + +- Remove source property from servermanagercmd provider as it does not support it. + +- Remove converge_by around inner powershell_script resource to stop it always reporting as changed + +- Change install feature guards to work on Windows 2008r2 + +- Allow dism feature installs to work on non-English systems + +## 3.1.3 (2017-09-18) + +### windows_task and windows_path deprecation + +s of chef-client 13.0+ and 13.4+ windows_task and windows_path are now included in the Chef client. windows_task underwent a full rewrite that greatly improved the functionality and idempotency of the resource. We highly recommend using these new resources by upgrading to Chef 13.4 or later. If you are running these more recent Chef releases the windows_task and windows_path resources within chef-client will take precedence over those in this cookbook. In September 2018 we will release a new major version of this cookbook that removes windows_task and windows_path. + +## 3.1.2 (2017-08-14) + +- Revert "Require path in the share resource instead of raising if it's missing" which was causing failures due to a bug in the chef-client + +## 3.1.1 (2017-06-13) + +- Replace Windows 7 testing with Windows 10 testing +- Expand debug logging in the pagefile resource +- Require path in the share resource instead of raising if it's missing +- Make pagefile properly fail the run if the command fails to run + +## 3.1.0 (2017-05-30) + +- Updated resource documentation for windows_pagefile +- Declare windows_feature as why-runnable +- Remove action_class.class_eval usage and require 12.7+ as class_eval is causing issues with later versions of Chef + +## 3.0.5 (2017-04-07) + +- Add support for windows_task resource to run on non-English editions of Windows +- Ensure chef-client 12.6 compatibility with action_class.class_eval + +## 3.0.4 (2017-03-29) + +- restoring the `cached_file` helper as downstream cookbooks use it. + +## 3.0.3 (2017-03-28) + +- Correct a typo in a Log message + +## 3.0.2 (2017-03-21) + +- Fix `windows_zipfile` resource to properly download and cache the zip archives + +## 3.0.1 (2017-03-17) + +- Fix `windows_share` to be fully idempotent. Fixes #447 + +## 3.0.0 (2017-03-15) + +**Warning** This release includes multiple breaking changes as we refactored all existing resources and resolved many longstanding bugs. We highly recommend exercising caution and fully testing this new version before rolling it out to a production environment. + +### Breaking changes + +- This cookbook now requires Chef 12.6 or later and we highly recommend even more recent Chef 12 releases as they resolve critical Windows bugs and include new Windows specific functionality. +- The windows_package resource has been removed as it is built into chef-client 12.6+ and the built in version is faster / more robust. +- The powershell out helper has been removed as it is now included in chef-client 12.6+ +- The default recipe no longer installs the various Windows rubygems required for non-omnibus chef-client installs. This was a leftover from Chef 10 and is no longer necessary, or desired, as we ship these gems in every Windows chef release. +- windows_feature has been heavily refactored and in doing so the method used to control the underlying providers has changed. You can no longer specify which windows_feature provider to use by setting `node['windows']['feature_provider']` or by setting the `provider` property on the resource itself. Instead you must set `install_method` to specify the correct underlying installation method. You can also now reference the resources directly by using `windows_feature_servermanagercmd`, `windows_feature_powershell` or `windows_feature_dism` instead of `windows_feature` + +- Windows_font's `file` property has been renamed to `name` to avoid collisions with the Chef file resource. + +### Other Changes + +- All LWRPs in this cookbook have been refactored to be custom resources +- windows_path, windows_shortcut, and windows_zipfile have been updated to be idempotent with support for why-run mode and proper notification when the resources actually update +- windows_pagefile now validates the name of the pagefile to avoid cryptic error messages +- A new `share` resource has been added for setting up Windows shares +- TrustedPeople certificate store has been added to the list of allowed store_names in the certificate resources +- version helper constant definitions has been improved +- A new `all` property has been added to the Windows feature resource to install all dependent features. See the windows feature test recipe for usage examples. +- Windows feature now accepts an array of features, which greatly speeds up feature installs and simplifies recipe code +- The path resource now accepts paths with either forward slashes or backslashes and correctly adds the path using Windows style backslash. +- The powershell provider for windows_feature resource has been fixed to properly import ServerManager in the :remove action +- Testing has been switched from a Rakefile to the new Delivery local mode +- Several issues with testing the resources on non-Windows hosts in ChefSpec have been resolved +- A new `source` property has been added to the windows_feature_powershell resource +- Additional test suites have been added to Test Kitchen to cover all resources and those test suites are now being executed in AppVeyer on every PR +- Travis CI testing has been removed and all testing is being performed in AppVeyer + +## 2.1.1 (2016-11-23) + +- Make sure the ohai plugin is available when installing features + +## 2.1.0 (2016-11-22) + +- Reduce expensive executions of dism in windows_feature by using a new Ohai plugin +- Add guard around chef_version metadata for Opsworks and older Chef 12 clients +- Update the rakefile to the latest +- Add deprecation dates for the windows_package and powershell functionality that has been moved to core Chef. These will be removed 4/17 when we release Chef 13 +- Provide helper method to get windows version info +- Allow defining http acl using SDDL + +## 2.0.2 (2016-09-07) + +- Added the powershell_out mixin back to allow for Chef 12.1-12.3 compatibility +- Set the dependency back to Chef 12.1 + +## 2.0.1 (2016-09-07) + +- Clarify the platforms we support in the readme +- Require Chef 12.4 which included powershell_out + +## 2.0.0 (2016-09-07) + +This cookbook now requires Chef 12.1+. Resources (lwrps) that have been moved into the chef-client have been removed from this cookbook. While the functionality in the chef-client is similar, and in many cases improved, the names and properties have changed in some cases. Make sure to check for full documentation on each of these resources, and as usual carefully test your cookbooks before upgrading to this new release. + +### Removed resources and helpers: + +- windows_reboot provider +- windows_batch provider +- windows_registry provider +- Powershell out for only_if / not_if statements +- Windows Architecture Helper +- Reboot handler and the dependency on the chef_handler cookbook + +#### Changes resource behavior + +- For Chef clients 12.6 and later the windows_package provider will no longer be used as windows_package logic is now included in Chef. Chef 12.1 - 12.5.1 clients will continue to default to the windows_package provider in this cookbook for full compatibility. + +#### Additional changes + +- Updated and expanded testing +- Fixed the windows_feature powershell provider to run on Windows 2008 / 2008 R2 +- Added TrustedPublisher as a valid cert store_name +- Updated the certificate_binding resource to respect the app_id property +- Added why-run support to the auto_run resource + +## 1.44.3 (2016-08-16) + +- Remove support for ChefSpec <4.1 in the matchers +- Add missing Chefspec matchers + +## 1.44.2 (2016-08-15) + +- Add missing windows_font matcher +- Add chef_version to the metadata +- Switch from Rubocop to Cookstyle and use our improved Rakefile +- Remove test deps from the Gemfile that are in ChefDK + +## v1.44.1 + +- [PR 375](https://github.com/chef-cookbooks/windows/pull/375) - Fix comparison of string to number in platform_version +- [PR 376](https://github.com/chef-cookbooks/windows/pull/376) - Switch to cookstyle, update gem deps and other minor stuff +- [PR 377](https://github.com/chef-cookbooks/windows/pull/377) - add test and check for feature installation through powershell + +## v1.44.0 + +- [PR 372](https://github.com/chef-cookbooks/windows/pull/372) - Support Server 2008 for feature installs via PowerShell + +## v1.43.0 + +- [PR 369](https://github.com/chef-cookbooks/windows/pull/369) - Add a enable_windows_task matcher + +## v1.42.0 + +- [PR 365](https://github.com/chef-cookbooks/windows/pull/365) - Escape command quotes when passing to schtasks + +## v1.41.0 + +- [PR 364](https://github.com/chef-cookbooks/windows/pull/364) - Configurable font source + +## v1.40.0 + +- [PR 357](https://github.com/chef-cookbooks/windows/pull/357) - Fixes for schtasks +- [PR 359](https://github.com/chef-cookbooks/windows/pull/359) - take bundler out of the appveyor build +- [PR 356](https://github.com/chef-cookbooks/windows/pull/356) - Misc fixes and updates +- [PR 355](https://github.com/chef-cookbooks/windows/pull/355) - bump and pin rubocop, fix broken cop +- [PR 348](https://github.com/chef-cookbooks/windows/pull/348) - Make notify work for `windows_task` + +## v1.39.2 + +- [PR 329](https://github.com/chef-cookbooks/windows/pull/329) - Silence `compile_time` warning for `chef_gem` +- [PR 338](https://github.com/chef-cookbooks/windows/pull/338) - ChefSpec matchers for `windows_certificate` +- [PR 341](https://github.com/chef-cookbooks/windows/pull/341) - Updated rubocop and FoodCritic compliance +- [PR 336](https://github.com/chef-cookbooks/windows/pull/336) - Fixed where clause compliance with PS v1/v2 + +## v1.39.1 + +- [PR 325](https://github.com/chef-cookbooks/windows/pull/325) - Raise an error if a bogus feature is given to the powershell `windows_feature` provider +- [PR 326](https://github.com/chef-cookbooks/windows/pull/326) - Fix `windows_font` and copy the font file before installation + +## v1.39.0 + +- [PR 305](https://github.com/chef-cookbooks/windows/pull/305) - Added `months` attribute to `windows_task` and allow `frequency_modifier` to accept values 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST', and 'LASTDAY' for monthly frequency +- [PR 310](https://github.com/chef-cookbooks/windows/pull/310) - Fix `windows_task` breaks when there is a space in the user name +- [PR 314](https://github.com/chef-cookbooks/windows/pull/314) - fixes reboot handling on some chef versions below 11.12 +- [PR 317](https://github.com/chef-cookbooks/windows/pull/317) - Adds a `disable_windows_task` matcher +- [PR 311](https://github.com/chef-cookbooks/windows/pull/311) - Implements the `cwd` attribute of `windows_task` +- [PR 318](https://github.com/chef-cookbooks/windows/pull/318) - Use dsl instead of manual resource instanciation +- [PR 303](https://github.com/chef-cookbooks/windows/pull/303) - Fix `http_acl` idempotency when user name contains a space +- [PR 257](https://github.com/chef-cookbooks/windows/pull/257) - Speed up windows_feature dism provider +- [PR 319](https://github.com/chef-cookbooks/windows/pull/319) - Add a `.kitchen.cloud.yml` for kitchen testing on Azure +- [PR 315](https://github.com/chef-cookbooks/windows/pull/315) - Deprecate `windows_package` and forward to `Chef::Provider::Package::Windows` when running 12.6 or higher + +## v1.38.4 + +- [PR 295](https://github.com/chef-cookbooks/windows/pull/295) - Escape `http_acl` username +- [PR 293](https://github.com/chef-cookbooks/windows/pull/293) - Separating assignments to `code_script` and `guard_script` as they should be different scripts and not hold the same reference +- [Issue 298](https://github.com/chef-cookbooks/windows/issues/298) - `windows_certificate_binding` is ignoring `store_name` attribute and always saving to `MY` +- [Issue 296](https://github.com/chef-cookbooks/windows/pull/302) - Fixes `windows_certificate` idempotentcy on chef 11 clients + +## v1.38.3 + +- Make `windows_task` resource idempotent (double quotes need to be single when comparing) +- [Issue 245](https://github.com/chef-cookbooks/windows/issues/256) - Fix `No resource, method, or local variable named`password' for `Chef::Provider::WindowsTask'` when `interactive_enabled` is `true` + +## v1.38.2 + +- Lazy-load windows-pr gem library files. Chef 12.5 no longer includes the windows-pr gem. Earlier versions of this cookbook will not compile on Chef 12.5. + +## v1.38.1 (2015-07-28) + +- Publishing without extended metadata + +## v1.38.0 (2015-07-27) + +- Do not set new_resource.password to nil, Fixes #219, Fixes #220 +- Add `windows_certificate` resource #212 +- Add `windows_http_acl` resource #214 + +## v1.37.0 (2015-05-14) + +- fix `windows_package` `Chef.set_resource_priority_array` warning +- update `windows_task` to support tasks in folders +- fix `windows_task` delete action +- replace `windows_task` name attribute with 'task_name' +- add :end action to 'windows_task' +- Tasks created with the `windows_task` resource default to the SYSTEM account +- The force attribute for `windows_task` makes the :create action update the definition. +- `windows_task` :create action will force an update of the task if the user or command differs from the currently configured setting. +- add default provider for `windows_feature` +- add a helper to make sure `WindowsRebootHandler` works in ChefSpec +- added a source and issues url to the metadata for Supermarket +- updated the Gemfile and .kitchen.yml to reflect the latest test-kitchen windows guest support +- started tests using the kitchen-pester verifier + +## v1.36.6 (2014-12-18) + +- reverting all chef_gem compile_time work + +## v1.36.5 (2014-12-18) + +- Fix zipfile provider + +## v1.36.4 (2014-12-18) + +- Fix Chef chef_gem with Chef::Resource::ChefGem.method_defined?(:compile_time) + +## v1.36.3 (2014-12-18) + +- Fix Chef chef_gem below 12.1.0 + +## v1.36.2 (2014-12-17) + +- Being explicit about usage of the chef_gem's compile_time property. +- Eliminating future deprecation warnings in Chef 12.1.0 + +## v1.36.1 (2014-12-17) + +- [PR 160](https://github.com/chef-cookbooks/windows/pull/160) - Fix Chef 11.10 / versions without windows_package in core + +## v1.36.0 (2014-12-16) + +- [PR 145](https://github.com/chef-cookbooks/windows/pull/145) - do not fail on non-existant task +- [PR 144](https://github.com/chef-cookbooks/windows/pull/144) - Add a zip example to the README +- [PR 110](https://github.com/chef-cookbooks/windows/pull/110) - More zip documentation +- [PR 148](https://github.com/chef-cookbooks/windows/pull/148) - Add an LWRP for font installation +- [PR 151](https://github.com/chef-cookbooks/windows/pull/151) - Fix windows_package on Chef 12, add integration tests +- [PR 129](https://github.com/chef-cookbooks/windows/pull/129) - Add enable/disable actions to task LWRP +- [PR 115](https://github.com/chef-cookbooks/windows/pull/115) - require Chef::Mixin::PowershellOut before using it +- [PR 88](https://github.com/chef-cookbooks/windows/pull/88) - Code 1003 from servermanagercmd.exe is valid + +## v1.34.8 (2014-10-31) + +- [Issue 137](https://github.com/chef-cookbooks/windows/issues/137) - windows_path resource breaks with ruby 2.x + +## v1.34.6 (2014-09-22) + +- [Chef-2009](https://github.com/chef/chef/issues/2009) - Patch to work around a regression in [Chef](https://github.com/chef/chef) + +## v1.34.2 (2014-08-12) + +- [Issue 99](https://github.com/chef-cookbooks/windows/issues/99) - Remove rubygems / Internet wmi-lite dependency (PR #108) + +## v1.34.0 (2014-08-04) + +- [Issue 99](https://github.com/chef-cookbooks/windows/issues/99) - Use wmi-lite to fix Chef 11.14.2 break in rdp-ruby-wmi dependency + +## v1.32.1 (2014-07-15) + +- Fixes broken cookbook release + +## v1.32.0 (2014-07-11) + +- Add ChefSpec resource methods to allow notification testing (@sneal) +- Add use_inline_resources to providers (@micgo) +- [COOK-4728] - Allow reboot handler to be used as an exception handler +- [COOK-4620] - Ensure win_friendly_path doesn't error out when ALT_SEPARATOR is nil + +## v1.31.0 (2014-05-07) + +- [COOK-2934] - Add windows_feature support for 2 new DISM attributes: all, source + +## v1.30.2 (2014-04-02) + +- [COOK-4414] - Adding ChefSpec matchers + +## v1.30.0 (2014-02-14) + +- [COOK-3715] - Unable to create a startup task with no login +- [COOK-4188] - Add powershell_version method to return Powershell version + +## v1.12.8 (2014-01-21) + +- [COOK-3988] Don't unescape URI before constructing it. + +## v1.12.6 (2014-01-03) + +- [COOK-4168] Circular dep on powershell - moving powershell libraries into windows. removing dependency on powershell + +## v1.12.4 + +Fixing depend/depends typo in metadata.rb + +## v1.12.2 + +### Bug + +- **[COOK-4110](https://tickets.chef.io/browse/COOK-4110)** - feature_servermanager installed? method regex bug + +## v1.12.0 + +### Bug + +- **[COOK-3793](https://tickets.chef.io/browse/COOK-3793)** - parens inside parens of README.md don't render + +### New Feature + +- **[COOK-3714](https://tickets.chef.io/browse/COOK-3714)** - Powershell features provider and delete support. + +## v1.11.0 + +### Improvement + +- **[COOK-3724](https://tickets.chef.io/browse/COOK-3724)** - Rrecommend built-in resources over cookbook resources +- **[COOK-3515](https://tickets.chef.io/browse/COOK-3515)** - Remove unprofessional comment from library +- **[COOK-3455](https://tickets.chef.io/browse/COOK-3455)** - Add Windows Server 2012R2 to windows cookbook version helper + +### Bug + +- **[COOK-3542](https://tickets.chef.io/browse/COOK-3542)** - Fix an issue where `windows_zipfile` fails with LoadError +- **[COOK-3447](https://tickets.chef.io/browse/COOK-3447)** - Allow Overriding Of The Default Reboot Timeout In windows_reboot_handler +- **[COOK-3382](https://tickets.chef.io/browse/COOK-3382)** - Allow windows_task to create `on_logon` tasks +- **[COOK-2098](https://tickets.chef.io/browse/COOK-2098)** - Fix and issue where the `windows_reboot` handler is ignoring the reboot time + +### New Feature + +- **[COOK-3458](https://tickets.chef.io/browse/COOK-3458)** - Add support for `start_date` and `start_time` in `windows_task` + +## v1.10.0 + +### Improvement + +- [COOK-3126]: `windows_task` should support the on start frequency +- [COOK-3127]: Support the force option on task create and delete + +## v1.9.0 + +### Bug + +- [COOK-2899]: windows_feature fails when a feature install requires a reboot +- [COOK-2914]: Foodcritic failures in Cookbooks +- [COOK-2983]: windows cookbook has foodcritic failures + +### Improvement + +- [COOK-2686]: Add Windows Server 2012 to version.rb so other depending chef scripts can detect Windows Server 2012 + +## v1.8.10 + +When using Windows qualified filepaths (C:/foo), the #absolute? method for URI returns true, because "C" is the scheme. + +This change checks that the URI is http or https scheme, so it can be passed off to remote_file appropriately. + +- [COOK-2729] - allow only http, https URI schemes + +## v1.8.8 + +- [COOK-2729] - helper should use URI rather than regex and bare string + +## v1.8.6 + +- [COOK-968] - `windows_package` provider should gracefully handle paths with spaces +- [COOK-222] - `windows_task` resource does not declare :change action +- [COOK-241] - Windows cookbook should check for redefined constants +- [COOK-248] - Windows package install type is case sensitive + +## v1.8.4 + +- [COOK-2336] - MSI That requires reboot returns with RC 3010 and causes chef run failure +- [COOK-2368] - `version` attribute of the `windows_package` provider should be documented + +## v1.8.2 + +**Important**: Use powershell in nodes expanded run lists to ensure powershell is downloaded, as powershell has a dependency on this cookbook; v1.8.0 created a circular dependency. + +- [COOK-2301] - windows 1.8.0 has circular dependency on powershell + +## v1.8.0 + +- [COOK-2126] - Add checksum attribute to `windows_zipfile` +- [COOK-2142] - Add printer and `printer_port` LWRPs +- [COOK-2149] - Chef::Log.debug Windows Package command line +- [COOK-2155] -`windows_package` does not send checksum to `cached_file` in `installer_type` + +## v1.7.0 + +- [COOK-1745] - allow for newer versions of rubyzip + +## v1.6.0 + +- [COOK-2048] - undefined method for Falseclass on task :change when action is :nothing (and task doesn't exist) +- [COOK-2049] - Add `windows_pagefile` resource + +## v1.5.0 + +- [COOK-1251] - Fix LWRP "NotImplementedError" +- [COOK-1921] - Task LWRP will return true for resource exists when no other scheduled tasks exist +- [COOK-1932] - Include :change functionality to windows task lwrp + +## v1.4.0: + +- [COOK-1571] - `windows_package` resource (with msi provider) does not accept spaces in filename +- [COOK-1581] - Windows cookbook needs a scheduled tasks LWRP +- [COOK-1584] - `windows_registry` should support all registry types + +## v1.3.4 + +- [COOK-1173] - `windows_registry` throws Win32::Registry::Error for action :remove on a nonexistent key +- [COOK-1182] - windows package sets start window title instead of quoting a path +- [COOK-1476] - zipfile lwrp should support :zip action +- [COOK-1485] - package resource fails to perform install correctly when "source" contains quote +- [COOK-1519] - add action :remove for path lwrp + +## v1.3.2 + +- [COOK-1033] - remove the `libraries/ruby_19_patches.rb` file which causes havoc on non-Windows systems. +- [COOK-811] - add a timeout parameter attribute for `windows_package` + +## v1.3.0 + +- [COOK-1323] - Update for changes in Chef 0.10.10. + + - Setting file mode doesn't make sense on Windows (package provider + - and `reboot_handler` recipe) + - Prefix ::Win32 to avoid namespace collision with Chef::Win32 + - (`registry_helper` library) + - Use chef_gem instead of gem_package so gems get installed correctly under the Ruby environment Chef runs in (reboot_handler recipe, zipfile provider) + +## v1.2.12 + +- [COOK-1037] - specify version for rubyzip gem +- [COOK-1007] - `windows_feature` does not work to remove features with dism +- [COOK-667] - shortcut resource + provider for Windows platforms + +## v1.2.10 + +- [COOK-939] - add `type` parameter to `windows_registry` to allow binary registry keys. +- [COOK-940] - refactor logic so multiple values get created. + +## v1.2.8 + +- FIX: Older Windows (Windows Server 2003) sometimes return 127 on successful forked commands +- FIX: `windows_package`, ensure we pass the WOW* registry redirection flags into reg.open + +## v1.2.6 + +- patch to fix [CHEF-2684], Open4 is named Open3 in Ruby 1.9 +- Ruby 1.9's Open3 returns 0 and 42 for successful commands +- retry keyword can only be used in a rescue block in Ruby 1.9 + +## v1.2.4 + +- `windows_package` - catch Win32::Registry::Error that pops up when searching certain keys + +## v1.2.2 + +- combined numerous helper libarires for easier sharing across libaries/LWRPs +- renamed Chef::Provider::WindowsFeature::Base file to the more descriptive `feature_base.rb` +- refactored `windows_path` LWRP + + - :add action should MODIFY the the underlying ENV variable (vs CREATE) + - deleted greedy :remove action until it could be made more idempotent + +- added a `windows_batch` resource/provider for running batch scripts remotely + +## v1.2.0 + +- [COOK-745] gracefully handle required server restarts on Windows platform + + - WindowsRebootHandler for requested and pending reboots + - `windows_reboot` LWRP for requesting (receiving notifies) reboots + - `reboot_handler` recipe for enabling WindowsRebootHandler as a report handler + +- [COOK-714] Correct initialize misspelling + +- RegistryHelper - new `get_values` method which returns all values for a particular key. + +## v1.0.8 + +- [COOK-719] resource/provider for managing windows features +- [COOK-717] remove `windows_env_vars` resource as env resource exists in core chef +- new `Windows::Version` helper class +- refactored `Windows::Helper` mixin + +## v1.0.6 + +- added `force_modify` action to `windows_registry` resource +- add `win_friendly_path` helper +- re-purpose default recipe to install useful supporting windows related gems + +## v1.0.4 + +- [COOK-700] new resources and improvements to the `windows_registry` provider (thanks Paul Morton!) + + - Open the registry in the bitednes of the OS + - Provide convenience methods to check if keys and values exit + - Provide convenience method for reading registry values + - NEW - `windows_auto_run` resource/provider + - NEW - `windows_env_vars` resource/provider + - NEW - `windows_path` resource/provider + +- re-write of the `windows_package` logic for determining current installed packages + +- new checksum attribute for `windows_package` resource...useful for remote packages + +## v1.0.2 + +- [COOK-647] account for Wow6432Node registry redirecter +- [COOK-656] begin/rescue on win32/registry + +## v1.0.0 + +- [COOK-612] initial release diff --git a/cookbooks/windows/CONTRIBUTING.md b/cookbooks/windows/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/windows/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/cookbooks/windows/README.md b/cookbooks/windows/README.md new file mode 100644 index 0000000..b849fbf --- /dev/null +++ b/cookbooks/windows/README.md @@ -0,0 +1,517 @@ +# Windows Cookbook + +[![Build status](https://ci.appveyor.com/api/projects/status/9x4uepmm1g4rktie/branch/master?svg=true)](https://ci.appveyor.com/project/ChefWindowsCookbooks/windows/branch/master) [![Cookbook Version](https://img.shields.io/cookbook/v/windows.svg)](https://supermarket.chef.io/cookbooks/windows) + +Provides a set of Windows-specific resources to aid in the creation of cookbooks/recipes targeting the Windows platform. + +## Requirements + +### Platforms + +- Windows 7 +- Windows Server 2008 R2 +- Windows 8, 8.1 +- Windows Server 2012 (R1, R2) +- Windows Server 2016 + +### Chef + +- Chef 14+ + +## Resources + +### Deprecated Resources Note + +As of Chef 14.7+ the windows_share and windows_certificate resources are now included in the Chef Client. If you are running Chef 14.7+ the resources in Chef client will take precedence over the resources in this cookbook. In November 2019 we will release a new major version of this cookbook that removes these resources. + +### windows_certificate + +`Note`: This resource is now included in Chef 14.7 and later. There is no need to depend on the Windows cookbook for this resource. + +Installs a certificate into the Windows certificate store from a file, and grants read-only access to the private key for designated accounts. Due to current limitations in WinRM, installing certificated remotely may not work if the operation requires a user profile. Operations on the local machine store should still work. + +#### Actions + +- `:create` - creates or updates a certificate. +- `:delete` - deletes a certificate. +- `:acl_add` - adds read-only entries to a certificate's private key ACL. +- `:verify` - logs whether or not a certificate is valid + +#### Properties + +- `source` - name attribute. The source file (for create and acl_add), thumbprint (for delete and acl_add) or subject (for delete). +- `pfx_password` - the password to access the source if it is a pfx file. +- `private_key_acl` - array of 'domain\account' entries to be granted read-only access to the certificate's private key. This is not idempotent. +- `store_name` - the certificate store to manipulate. One of: + - MY (Personal) + - CA (Intermediate Certification Authorities) + - ROOT (Trusted Root Certification Authorities) + - TRUSTEDPUBLISHER (Trusted Publishers) + - CLIENTAUTHISSUER (Client Authentication Issuers) + - REMOTE DESKTOP (Remote Desktop) + - TRUSTEDDEVICES (Trusted Devices) + - WEBHOSTING (Web Hosting) + - AUTHROOT (Third-Party Root Certification Authorities) + - TRUSTEDPEOPLE (Trusted People) + - SMARTCARDROOT (Smart Card Trusted Roots) + - TRUST (Enterprise Trust) + - DISALLOWED (Untrusted Certificates) +- `user_store` - if false (default) then use the local machine store; if true then use the current user's store. + +#### Examples + +```ruby +# Add PFX cert to local machine personal store and grant accounts read-only access to private key +windows_certificate "c:/test/mycert.pfx" do + pfx_password "password" + private_key_acl ["acme\fred", "pc\jane"] +end +``` + +```ruby +# Add cert to trusted intermediate store +windows_certificate "c:/test/mycert.cer" do + store_name "CA" +end +``` + +```ruby +# Remove all certificates matching the subject +windows_certificate "me.acme.com" do + action :delete +end +``` + +### windows_certificate_binding + +Binds a certificate to an HTTP port in order to enable TLS communication. + +#### Actions + +- `:create` - creates or updates a binding. +- `:delete` - deletes a binding. + +#### Properties + +- `cert_name` - name attribute. The thumbprint(hash) or subject that identifies the certificate to be bound. +- `name_kind` - indicates the type of cert_name. One of :subject (default) or :hash. +- `address` - the address to bind against. Default is 0.0.0.0 (all IP addresses). One of: + - IP v4 address `1.2.3.4` + - IP v6 address `[::1]` + - Host name `www.foo.com` +- `port` - the port to bind against. Default is 443. +- `app_id` - the GUID that defines the application that owns the binding. Default is the values used by IIS. +- `store_name` - the store to locate the certificate in. One of: + - MY (Personal) + - CA (Intermediate Certification Authorities) + - ROOT (Trusted Root Certification Authorities) + - TRUSTEDPUBLISHER (Trusted Publishers) + - CLIENTAUTHISSUER (Client Authentication Issuers) + - REMOTE DESKTOP (Remote Desktop) + - TRUSTEDDEVICES (Trusted Devices) + - WEBHOSTING (Web Hosting) + - AUTHROOT (Third-Party Root Certification Authorities) + - TRUSTEDPEOPLE (Trusted People) + - SMARTCARDROOT (Smart Card Trusted Roots) + - TRUST (Enterprise Trust) + +#### Examples + +```ruby +# Bind the first certificate matching the subject to the default TLS port +windows_certificate_binding "me.acme.com" do +end +``` + +```ruby +# Bind a cert from the CA store with the given hash to port 4334 +windows_certificate_binding "me.acme.com" do + cert_name "d234567890a23f567c901e345bc8901d34567890" + name_kind :hash + store_name "CA" + port 4334 +end +``` + +### windows_dns + +Configures A and CNAME records in Windows DNS. This requires the DNSCMD to be installed, which is done by adding the DNS role to the server or installing the Remote Server Admin Tools. + +#### Actions + +- :create: creates/updates the DNS entry +- :delete: deletes the DNS entry + +#### Properties + +- host_name: name attribute. FQDN of the entry to act on. +- dns_server: the DNS server to update. Default is local machine (.) +- record_type: the type of record to create. One of A (default) or CNAME +- target: for A records an array of IP addresses to associate with the host; for CNAME records the FQDN of the host to alias +- ttl: if > 0 then set the time to live of the record + +#### Examples + +```ruby +# Create A record linked to 2 addresses with a 10 minute ttl +windows_dns "m1.chef.test" do + target ['10.9.8.7', '1.2.3.4'] + ttl 600 +end +``` + +```ruby +# Delete records. target is mandatory although not used +windows_dns "m1.chef.test" do + action :delete + target [] +end +``` + +```ruby +# Set an alias against the node in a role +nodes = search( :node, "role:my_service" ) +windows_dns "myservice.chef.test" do + record_type 'CNAME' + target nodes[0]['fqdn'] +end +``` + +### windows_http_acl + +Sets the Access Control List for an http URL to grant non-admin accounts permission to open HTTP endpoints. + +#### Actions + +- `:create` - creates or updates the ACL for a URL. +- `:delete` - deletes the ACL from a URL. + +#### Properties + +- `url` - the name of the url to be created/deleted. +- `sddl` - the DACL string configuring all permissions to URL. Mandatory for create if user is not provided. Can't be use with `user`. +- `user` - the name (domain\user) of the user or group to be granted permission to the URL. Mandatory for create if sddl is not provided. Can't be use with `sddl`. Only one user or group can be granted permission so this replaces any previously defined entry. If you receive a parameter error your user may not exist. + +#### Examples + +```ruby +windows_http_acl 'http://+:50051/' do + user 'pc\\fred' +end +``` + +```ruby +# Grant access to users "NT SERVICE\WinRM" and "NT SERVICE\Wecsvc" via sddl +windows_http_acl 'http://+:5985/' do + sddl 'D:(A;;GX;;;S-1-5-80-569256582-2953403351-2909559716-1301513147-412116970)(A;;GX;;;S-1-5-80-4059739203-877974739-1245631912-527174227-2996563517)' +end +``` + +```ruby +windows_http_acl 'http://+:50051/' do + action :delete +end +``` + +### windows_share + +`Note`: This resource is now included in Chef 14.7 and later. There is no need to depend on the Windows cookbook for this resource. + +Creates, modifies and removes Windows shares. All properties are idempotent. + +`Note`: This resource uses PowerShell cmdlets introduced in Windows 2012/8. + +#### Actions + +- `:create`: creates/modifies a share +- `:delete`: deletes a share + +#### Properties + +property | type | default | description +------------------------ | ---------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- +`share_name` | String | resource name | the share to assign to the share +`path` | String | | The path of the location of the folder to share. Required when creating. If the share already exists on a different path then it is deleted and re-created. +`description` | String | | description to be applied to the share +`full_users` | Array | [] | users which should have "Full control" permissions +`change_users` | Array | [] | Users are granted modify permission to access the share. +`read_users` | Array | [] | users which should have "Read" permissions +`temporary` | True/False | false | The lifetime of the new SMB share. A temporary share does not persist beyond the next restart of the computer +`scope_name` | String | '*' | The scope name of the share. +`ca_timeout` | Integer | 0 | The continuous availability time-out for the share. +`continuously_available` | True/False | false | Indicates that the share is continuously available. +`concurrent_user_limit` | Integer | 0 (unlimited) | The maximum number of concurrently connected users the share can accommodate +`encrypt_data` | True/False | false | Indicates that the share is encrypted. + +#### Examples + +```ruby +windows_share "foo" do + action :create + path "C:\\foo" + full_users ["DOMAIN_A\\some_user", "DOMAIN_B\\some_other_user"] + read_users ["DOMAIN_C\\Domain users"] +end +``` + +```ruby +windows_share "foo" do + action :delete +end +``` + +### windows_user_privilege + +Adds the `principal` (User/Group) to the specified privileges (such as `Logon as a batch job` or `Logon as a Service`). + +#### Actions + +- `:add` - add the specified privileges to the `principal` +- `:remove` - remove the specified privilege of the `principal` + +#### Properties + +- `principal` - Name attribute, Required, String. The user or group to be granted privileges. +- `privilege` - Required, String/Array. The privilege(s) to be granted. + +#### Examples + +Grant the Administrator user the `Logon as a batch job` and `Logon as a service` privilege. + +```ruby +windows_user_privilege 'Administrator' do + privilege %w(SeBatchLogonRight SeServiceLogonRight) +end +``` + +Remove `Logon as a batch job` privilege of Administrator. + +```ruby +windows_user_privilege 'Administrator' do + privilege %w(SeBatchLogonRight) + action :remove +end +``` + +#### Available Privileges + +``` +SeTrustedCredManAccessPrivilege Access Credential Manager as a trusted caller +SeNetworkLogonRight Access this computer from the network +SeTcbPrivilege Act as part of the operating system +SeMachineAccountPrivilege Add workstations to domain +SeIncreaseQuotaPrivilege Adjust memory quotas for a process +SeInteractiveLogonRight Allow log on locally +SeRemoteInteractiveLogonRight Allow log on through Remote Desktop Services +SeBackupPrivilege Back up files and directories +SeChangeNotifyPrivilege Bypass traverse checking +SeSystemtimePrivilege Change the system time +SeTimeZonePrivilege Change the time zone +SeCreatePagefilePrivilege Create a pagefile +SeCreateTokenPrivilege Create a token object +SeCreateGlobalPrivilege Create global objects +SeCreatePermanentPrivilege Create permanent shared objects +SeCreateSymbolicLinkPrivilege Create symbolic links +SeDebugPrivilege Debug programs +SeDenyNetworkLogonRight Deny access this computer from the network +SeDenyBatchLogonRight Deny log on as a batch job +SeDenyServiceLogonRight Deny log on as a service +SeDenyInteractiveLogonRight Deny log on locally +SeDenyRemoteInteractiveLogonRight Deny log on through Remote Desktop Services +SeEnableDelegationPrivilege Enable computer and user accounts to be trusted for delegation +SeRemoteShutdownPrivilege Force shutdown from a remote system +SeAuditPrivilege Generate security audits +SeImpersonatePrivilege Impersonate a client after authentication +SeIncreaseWorkingSetPrivilege Increase a process working set +SeIncreaseBasePriorityPrivilege Increase scheduling priority +SeLoadDriverPrivilege Load and unload device drivers +SeLockMemoryPrivilege Lock pages in memory +SeBatchLogonRight Log on as a batch job +SeServiceLogonRight Log on as a service +SeSecurityPrivilege Manage auditing and security log +SeRelabelPrivilege Modify an object label +SeSystemEnvironmentPrivilege Modify firmware environment values +SeManageVolumePrivilege Perform volume maintenance tasks +SeProfileSingleProcessPrivilege Profile single process +SeSystemProfilePrivilege Profile system performance +SeUnsolicitedInputPrivilege "Read unsolicited input from a terminal device" +SeUndockPrivilege Remove computer from docking station +SeAssignPrimaryTokenPrivilege Replace a process level token +SeRestorePrivilege Restore files and directories +SeShutdownPrivilege Shut down the system +SeSyncAgentPrivilege Synchronize directory service data +SeTakeOwnershipPrivilege Take ownership of files or other objects +``` + +### windows_zipfile + +Most version of Windows do not ship with native cli utility for managing compressed files. This resource provides a pure-ruby implementation for managing zip files. Be sure to use the `not_if` or `only_if` meta parameters to guard the resource for idempotence or action will be taken every Chef run. + +#### Actions + +- `:unzip` - unzip a compressed file +- `:zip` - zip a directory (recursively) + +#### Properties + +- `path` - name attribute. The path where files will be (un)zipped to. +- `source` - source of the zip file (either a URI or local path) for :unzip, or directory to be zipped for :zip. +- `overwrite` - force an overwrite of the files if they already exist. +- `checksum` - for :unzip, useful if source is remote, if the local file matches the SHA-256 checksum, Chef will not download it. + +#### Examples + +Unzip a remote zip file locally + +```ruby +windows_zipfile 'c:/bin' do + source 'http://download.sysinternals.com/Files/SysinternalsSuite.zip' + action :unzip + not_if {::File.exists?('c:/bin/PsExec.exe')} +end +``` + +Unzip a local zipfile + +```ruby +windows_zipfile 'c:/the_codez' do + source 'c:/foo/baz/the_codez.zip' + action :unzip +end +``` + +Create a local zipfile + +```ruby +windows_zipfile 'c:/foo/baz/the_codez.zip' do + source 'c:/the_codez' + action :zip +end +``` + +## Libraries + +### WindowsHelper + +Helper that allows you to use helpful functions in windows + +#### installed_packages + +Returns a hash of all DisplayNames installed + +```ruby +# usage in a recipe +::Chef::Recipe.send(:include, Windows::Helper) +hash_of_installed_packages = installed_packages +``` + +#### is_package_installed? + +- `package_name` - The name of the package you want to query to see if it is installed +- `returns` - true if the package is installed, false if it the package is not installed + +Download a file if a package isn't installed + +```ruby +# usage in a recipe to not download a file if package is already installed +::Chef::Recipe.send(:include, Windows::Helper) +is_win_sdk_installed = is_package_installed?('Windows Software Development Kit') + +remote_file 'C:\windows\temp\windows_sdk.zip' do + source 'http://url_to_download/windows_sdk.zip' + action :create_if_missing + not_if {is_win_sdk_installed} +end +``` + +Do something if a package is installed + +```ruby +# usage in a provider +include Windows::Helper +if is_package_installed?('Windows Software Development Kit') + # do something if package is installed +end +``` + +### Windows::VersionHelper + +Helper that allows you to get information of the windows version running on your node. It leverages windows ohai from kernel.os_info, easy to mock and to use even on linux. + +#### core_version? + +Determines whether given node is running on a windows Core. + +```ruby +if ::Windows::VersionHelper.core_version? node + fail 'Windows Core is not supported' +end +``` + +#### workstation_version? + +Determines whether given node is a windows workstation version (XP, Vista, 7, 8, 8.1, 10) + +```ruby +if ::Windows::VersionHelper.workstation_version? node + fail 'Only server version of windows are supported' +end +``` + +#### server_version? + +Determines whether given node is a windows server version (Server 2003, Server 2008, Server 2012, Server 2016) + +```ruby +if ::Windows::VersionHelper.server_version? node + puts 'Server version of windows are cool' +end +``` + +#### nt_version + +Determines NT version of the given node + +```ruby +case ::Windows::VersionHelper.nt_version node + when '6.0' then 'Windows vista or Server 2008' + when '6.1' then 'Windows 7 or Server 2008R2' + when '6.2' then 'Windows 8 or Server 2012' + when '6.3' then 'Windows 8.1 or Server 2012R2' + when '10.0' then 'Windows 10' +end +``` + +## Usage + +Place an explicit dependency on this cookbook (using depends in the cookbook's metadata.rb) from any cookbook where you would like to use the Windows-specific resources/providers that ship with this cookbook. + +```ruby +depends 'windows' +``` + +## License & Authors + +- Author:: Seth Chisamore ([schisamo@chef.io](mailto:schisamo@chef.io)) +- Author:: Doug MacEachern ([dougm@vmware.com](mailto:dougm@vmware.com)) +- Author:: Paul Morton ([pmorton@biaprotect.com](mailto:pmorton@biaprotect.com)) +- Author:: Doug Ireton ([doug.ireton@nordstrom.com](mailto:doug.ireton@nordstrom.com)) + +```text +Copyright 2011-2018, Chef Software, Inc. +Copyright 2010, VMware, Inc. +Copyright 2011, Business Intelligence Associates, Inc +Copyright 2012, Nordstrom, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/cookbooks/windows/libraries/powershell_helper.rb b/cookbooks/windows/libraries/powershell_helper.rb new file mode 100644 index 0000000..be021a3 --- /dev/null +++ b/cookbooks/windows/libraries/powershell_helper.rb @@ -0,0 +1,53 @@ +# +# Author:: Seth Chisamore () +# Cookbook:: windows +# Library:: powershell_helper +# +# Copyright:: 2011-2018, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'chef/mixin/shell_out' + +module Powershell + module Helper + include Chef::Mixin::ShellOut + + def powershell_installed? + !powershell_version.nil? + end + + def interpreter + # force 64-bit powershell from 32-bit ruby process + if ::File.exist?("#{ENV['WINDIR']}\\sysnative\\WindowsPowershell\\v1.0\\powershell.exe") + "#{ENV['WINDIR']}\\sysnative\\WindowsPowershell\\v1.0\\powershell.exe" + elsif ::File.exist?("#{ENV['WINDIR']}\\system32\\WindowsPowershell\\v1.0\\powershell.exe") + "#{ENV['WINDIR']}\\system32\\WindowsPowershell\\v1.0\\powershell.exe" + else + 'powershell.exe' + end + end + + def powershell_version + cmd = shell_out("#{interpreter} -InputFormat none -Command \"& echo $PSVersionTable.psversion.major\"") + if cmd.stdout.empty? # PowerShell 1.0 doesn't have a $PSVersionTable + 1 + else + Regexp.last_match(1).to_i if cmd.stdout =~ /^(\d+)/ + end + rescue Errno::ENOENT + nil + end + end +end diff --git a/cookbooks/windows/libraries/registry_helper.rb b/cookbooks/windows/libraries/registry_helper.rb new file mode 100644 index 0000000..3ca2254 --- /dev/null +++ b/cookbooks/windows/libraries/registry_helper.rb @@ -0,0 +1,356 @@ +# +# Author:: Doug MacEachern () +# Author:: Seth Chisamore () +# Author:: Paul Morton () +# Cookbook:: windows +# Library:: registry_helper +# +# Copyright:: 2010-2017, VMware, Inc. +# Copyright:: 2011-2018, Chef Software, Inc. +# Copyright:: 2011-2017, Business Intelligence Associates, Inc +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if RUBY_PLATFORM =~ /mswin|mingw32|windows/ + require 'win32/registry' + require_relative 'wmi_helper' +end + +module Windows + module RegistryHelper + @@native_registry_constant = if ENV['PROCESSOR_ARCHITECTURE'] == 'AMD64' || + ENV['PROCESSOR_ARCHITEW6432'] == 'AMD64' + 0x0100 + else + 0x0200 + end + + def get_hive_name(path) + Chef::Log.debug('Resolving registry shortcuts to full names') + + reg_path = path.split('\\') + hive_name = reg_path.shift + + hkey = { + 'HKLM' => 'HKEY_LOCAL_MACHINE', + 'HKCU' => 'HKEY_CURRENT_USER', + 'HKU' => 'HKEY_USERS', + }[hive_name] || hive_name + + Chef::Log.debug("Hive resolved to #{hkey}") + hkey + end + + def get_hive(path) + Chef::Log.debug("Getting hive for #{path}") + reg_path = path.split('\\') + hive_name = reg_path.shift + + hkey = get_hive_name(path) + + hive = { + 'HKEY_LOCAL_MACHINE' => ::Win32::Registry::HKEY_LOCAL_MACHINE, + 'HKEY_USERS' => ::Win32::Registry::HKEY_USERS, + 'HKEY_CURRENT_USER' => ::Win32::Registry::HKEY_CURRENT_USER, + }[hkey] + + unless hive + Chef::Application.fatal!("Unsupported registry hive '#{hive_name}'") + end + + Chef::Log.debug("Registry hive resolved to #{hkey}") + hive + end + + def unload_hive(path) + hive = get_hive(path) + if hive == ::Win32::Registry::HKEY_USERS + reg_path = path.split('\\') + priv = Chef::WindowsPrivileged.new + begin + priv.reg_unload_key(reg_path[1]) + rescue + end + end + end + + def set_value(mode, path, values, type = nil) + hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path) + key_name = reg_path.join('\\') + + Chef::Log.debug("Creating #{path}") + + create_key(path) unless key_exists?(path, true) + + hive.send(mode, key_name, ::Win32::Registry::KEY_ALL_ACCESS | @@native_registry_constant) do |reg| + changed_something = false + values.each do |k, val| + key = k.to_s # wtf. avoid "can't modify frozen string" in win32/registry.rb + cur_val = nil + begin + cur_val = reg[key] + rescue + # subkey does not exist (ok) + end + + next unless cur_val != val + + Chef::Log.debug("setting #{key}=#{val}") + + type = :string if type.nil? + + reg_type = { + binary: ::Win32::Registry::REG_BINARY, + string: ::Win32::Registry::REG_SZ, + multi_string: ::Win32::Registry::REG_MULTI_SZ, + expand_string: ::Win32::Registry::REG_EXPAND_SZ, + dword: ::Win32::Registry::REG_DWORD, + dword_big_endian: ::Win32::Registry::REG_DWORD_BIG_ENDIAN, + qword: ::Win32::Registry::REG_QWORD, + }[type] + + reg.write(key, reg_type, val) + + ensure_hive_unloaded(hive_loaded) + + changed_something = true + end + return changed_something + end + false + end + + def get_value(path, value) + hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path) + key = reg_path.join('\\') + + hive.open(key, ::Win32::Registry::KEY_ALL_ACCESS | @@native_registry_constant) do |reg| + begin + return reg[value] + rescue + return nil + ensure + ensure_hive_unloaded(hive_loaded) + end + end + end + + def get_values(path) + hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path) + key = reg_path.join('\\') + hive.open(key, ::Win32::Registry::KEY_ALL_ACCESS | @@native_registry_constant) do |reg| + values = [] + begin + reg.each_value do |name, type, data| + values << [name, type, data] + end + rescue + ensure + ensure_hive_unloaded(hive_loaded) + end + values + end + end + + def delete_value(path, values) + hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path) + key = reg_path.join('\\') + Chef::Log.debug("Deleting values in #{path}") + hive.open(key, ::Win32::Registry::KEY_ALL_ACCESS | @@native_registry_constant) do |reg| + values.each_key do |key| + name = key.to_s + # Ensure delete operation is idempotent. + if value_exists?(path, key) + Chef::Log.debug("Deleting value #{name} in #{path}") + reg.delete_value(name) + else + Chef::Log.debug("Value #{name} in #{path} does not exist, skipping.") + end + end + end + end + + def create_key(path) + hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path) + key = reg_path.join('\\') + Chef::Log.debug("Creating registry key #{path}") + hive.create(key) + end + + def value_exists?(path, value) + if key_exists?(path, true) + + hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path) + key = reg_path.join('\\') + + Chef::Log.debug("Attempting to open #{key}") + Chef::Log.debug("Native Constant #{@@native_registry_constant}") + Chef::Log.debug("Hive #{hive}") + + hive.open(key, ::Win32::Registry::KEY_READ | @@native_registry_constant) do |reg| + begin + rtn_value = reg[value] + return true + rescue + return false + ensure + ensure_hive_unloaded(hive_loaded) + end + end + + end + false + end + + # TODO: Does not load user registry... + def key_exists?(path, load_hive = false) + if load_hive + hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path) + key = reg_path.join('\\') + else + hive = get_hive(path) + reg_path = path.split('\\') + hive_name = reg_path.shift + root_key = reg_path[0] + key = reg_path.join('\\') + hive_loaded = false + end + + begin + hive.open(key, ::Win32::Registry::Constants::KEY_READ | @@native_registry_constant) + return true + rescue + return false + ensure + ensure_hive_unloaded(hive_loaded) + end + end + + def get_user_hive_location(sid) + reg_key = "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\#{sid}" + Chef::Log.debug("Looking for profile at #{reg_key}") + if key_exists?(reg_key) + return get_value(reg_key, 'ProfileImagePath') + else + return nil + end + end + + def resolve_user_to_sid(username) + user_query = execute_wmi_query("select * from Win32_UserAccount where Name='#{username}'") + sid = nil + + user_query.each do |user| + sid = wmi_object_property(user, 'sid') + break + end + + Chef::Log.debug("Resolved user SID to #{sid}") + sid + rescue + nil + end + + def hive_loaded?(path) + hive = get_hive(path) + reg_path = path.split('\\') + hive_name = reg_path.shift + user_hive = path[0] + + if user_hive?(hive) + return key_exists?("#{hive_name}\\#{user_hive}") + else + return true + end + end + + def user_hive?(hive) + hive == ::Win32::Registry::HKEY_USERS + end + + def get_reg_path_info(path) + hive = get_hive(path) + reg_path = path.split('\\') + hive_name = reg_path.shift + root_key = reg_path[0] + hive_loaded = false + + if user_hive?(hive) && !key_exists?("#{hive_name}\\#{root_key}") + reg_path, hive_loaded = load_user_hive(hive, reg_path, root_key) + root_key = reg_path[0] + Chef::Log.debug("Resolved user (#{path}) to (#{reg_path.join('/')})") + end + + [hive, reg_path, hive_name, root_key, hive_loaded] + end + + def load_user_hive(hive, reg_path, user_hive) + Chef::Log.debug("Reg Path #{reg_path}") + # See if the hive is loaded. Logged in users will have a key that is named their SID + # if the user has specified the a path by SID and the user is logged in, this function + # should not be executed. + if user_hive?(hive) && !key_exists?("HKU\\#{user_hive}") + Chef::Log.debug('The user is not logged in and has not been specified by SID') + sid = resolve_user_to_sid(user_hive) + Chef::Log.debug("User SID resolved to (#{sid})") + # Now that the user has been resolved to a SID, check and see if the hive exists. + # If this exists by SID, the user is logged in and we should use that key. + # TODO: Replace the username with the sid and send it back because the username + # does not exist as the key location. + load_reg = false + if key_exists?("HKU\\#{sid}") + reg_path[0] = sid # use the active profile (user is logged on) + Chef::Log.debug("HKEY_USERS Mapped: #{user_hive} -> #{sid}") + else + Chef::Log.debug('User is not logged in') + load_reg = true + end + + # The user is not logged in, so we should load the registry from disk + if load_reg + profile_path = get_user_hive_location(sid) + unless profile_path.nil? + ntuser_dat = "#{profile_path}\\NTUSER.DAT" + if ::File.exist?(ntuser_dat) + priv = Chef::WindowsPrivileged.new + if priv.reg_load_key(sid, ntuser_dat) + Chef::Log.debug("RegLoadKey(#{sid}, #{user_hive}, #{ntuser_dat})") + reg_path[0] = sid + else + Chef::Log.debug("Failed RegLoadKey(#{sid}, #{user_hive}, #{ntuser_dat})") + end + end + end + end + end + + [reg_path, load_reg] + end + + private + + def ensure_hive_unloaded(hive_loaded = false) + if hive_loaded + Chef::Log.debug('Hive was loaded, we really should unload it') + unload_hive(path) + end + end + end +end + +module Registry + module_function # rubocop: disable Lint/UselessAccessModifier + + extend Windows::RegistryHelper +end diff --git a/cookbooks/windows/libraries/version.rb b/cookbooks/windows/libraries/version.rb new file mode 100644 index 0000000..48ff13f --- /dev/null +++ b/cookbooks/windows/libraries/version.rb @@ -0,0 +1,189 @@ +# +# Author:: Seth Chisamore () +# Cookbook:: windows +# Library:: version +# +# Copyright:: 2011-2018, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if RUBY_PLATFORM =~ /mswin|mingw32|windows/ + require_relative 'wmi_helper' +end + +module Windows + class Version + # http://msdn.microsoft.com/en-us/library/ms724833(v=vs.85).aspx + + # Suite Masks + # Microsoft BackOffice components are installed. + VER_SUITE_BACKOFFICE = 0x00000004 unless defined?(VER_SUITE_BACKOFFICE) + # Windows Server 2008 Datacenter, Windows Server 2003, Datacenter Edition, or Windows 2000 Datacenter Server is installed. + VER_SUITE_DATACENTER = 0x00000080 unless defined?(VER_SUITE_DATACENTER) + # Windows Server 2008 Enterprise, Windows Server 2003, Enterprise Edition, or Windows 2000 Advanced Server is installed. Refer to the Remarks section for more information about this bit flag. + VER_SUITE_ENTERPRISE = 0x00000002 unless defined?(VER_SUITE_ENTERPRISE) + # Windows XP Embedded is installed. + VER_SUITE_EMBEDDEDNT = 0x00000040 unless defined?(VER_SUITE_EMBEDDEDNT) + # Windows Vista Home Premium, Windows Vista Home Basic, or Windows XP Home Edition is installed. + VER_SUITE_PERSONAL = 0x00000200 unless defined?(VER_SUITE_PERSONAL) + # Remote Desktop is supported, but only one interactive session is supported. This value is set unless the system is running in application server mode. + VER_SUITE_SINGLEUSERTS = 0x00000100 unless defined?(VER_SUITE_SINGLEUSERTS) + # Microsoft Small Business Server was once installed on the system, but may have been upgraded to another version of Windows. Refer to the Remarks section for more information about this bit flag. + VER_SUITE_SMALLBUSINESS = 0x00000001 unless defined?(VER_SUITE_SMALLBUSINESS) + # Microsoft Small Business Server is installed with the restrictive client license in force. Refer to the Remarks section for more information about this bit flag. + VER_SUITE_SMALLBUSINESS_RESTRICTED = 0x00000020 unless defined?(VER_SUITE_SMALLBUSINESS_RESTRICTED) + # Terminal Services is installed. This value is always set. + # If VER_SUITE_TERMINAL is set but VER_SUITE_SINGLEUSERTS is not set, the system is running in application server mode. + VER_SUITE_TERMINAL = 0x00000010 unless defined?(VER_SUITE_TERMINAL) + # Windows Home Server is installed. + VER_SUITE_WH_SERVER = 0x00008000 unless defined?(VER_SUITE_WH_SERVER) + + # Product Type + # The system is a domain controller and the operating system is Windows Server 2012, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003, or Windows 2000 Server. + VER_NT_DOMAIN_CONTROLLER = 0x0000002 unless defined?(VER_NT_DOMAIN_CONTROLLER) + # The operating system is Windows Server 2012, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003, or Windows 2000 Server. + # Note that a server that is also a domain controller is reported as VER_NT_DOMAIN_CONTROLLER, not VER_NT_SERVER. + VER_NT_SERVER = 0x0000003 unless defined?(VER_NT_SERVER) + # The operating system is Windows 7, Windows Vista, Windows XP Professional, Windows XP Home Edition, or Windows 2000 Professional. + VER_NT_WORKSTATION = 0x0000001 unless defined?(VER_NT_WORKSTATION) + + # http://msdn.microsoft.com/en-us/library/ms724358(v=vs.85).aspx + SKU = { + 0x00000006 => { ms_const: 'PRODUCT_BUSINESS', name: 'Business' }, + 0x00000010 => { ms_const: 'PRODUCT_BUSINESS_N', name: 'Business N' }, + 0x00000012 => { ms_const: 'PRODUCT_CLUSTER_SERVER', name: 'HPC Edition' }, + 0x00000008 => { ms_const: 'PRODUCT_DATACENTER_SERVER', name: 'Server Datacenter (full installation)' }, + 0x0000000C => { ms_const: 'PRODUCT_DATACENTER_SERVER_CORE', name: 'Server Datacenter (core installation)' }, + 0x00000027 => { ms_const: 'PRODUCT_DATACENTER_SERVER_CORE_V', name: 'Server Datacenter without Hyper-V (core installation)' }, + 0x00000025 => { ms_const: 'PRODUCT_DATACENTER_SERVER_V', name: 'Server Datacenter without Hyper-V (full installation)' }, + 0x00000004 => { ms_const: 'PRODUCT_ENTERPRISE', name: 'Enterprise' }, + 0x00000046 => { ms_const: 'PRODUCT_ENTERPRISE_E', name: 'Not supported' }, + 0x0000001B => { ms_const: 'PRODUCT_ENTERPRISE_N', name: 'Enterprise N' }, + 0x0000000A => { ms_const: 'PRODUCT_ENTERPRISE_SERVER', name: 'Server Enterprise (full installation)' }, + 0x0000000E => { ms_const: 'PRODUCT_ENTERPRISE_SERVER_CORE', name: 'Server Enterprise (core installation)' }, + 0x00000029 => { ms_const: 'PRODUCT_ENTERPRISE_SERVER_CORE_V', name: 'Server Enterprise without Hyper-V (core installation)' }, + 0x0000000F => { ms_const: 'PRODUCT_ENTERPRISE_SERVER_IA64', name: 'Server Enterprise for Itanium-based Systems' }, + 0x00000026 => { ms_const: 'PRODUCT_ENTERPRISE_SERVER_V', name: 'Server Enterprise without Hyper-V (full installation)' }, + 0x00000002 => { ms_const: 'PRODUCT_HOME_BASIC', name: 'Home Basic' }, + 0x00000043 => { ms_const: 'PRODUCT_HOME_BASIC_E', name: 'Not supported' }, + 0x00000005 => { ms_const: 'PRODUCT_HOME_BASIC_N', name: 'Home Basic N' }, + 0x00000003 => { ms_const: 'PRODUCT_HOME_PREMIUM', name: 'Home Premium' }, + 0x00000044 => { ms_const: 'PRODUCT_HOME_PREMIUM_E', name: 'Not supported' }, + 0x0000001A => { ms_const: 'PRODUCT_HOME_PREMIUM_N', name: 'Home Premium N' }, + 0x0000002A => { ms_const: 'PRODUCT_HYPERV', name: 'Microsoft Hyper-V Server' }, + 0x0000001E => { ms_const: 'PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT', name: 'Windows Essential Business Server Management Server' }, + 0x00000020 => { ms_const: 'PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING', name: 'Windows Essential Business Server Messaging Server' }, + 0x0000001F => { ms_const: 'PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY', name: 'Windows Essential Business Server Security Server' }, + 0x00000030 => { ms_const: 'PRODUCT_PROFESSIONAL', name: 'Professional' }, + 0x00000045 => { ms_const: 'PRODUCT_PROFESSIONAL_E', name: 'Not supported' }, + 0x00000031 => { ms_const: 'PRODUCT_PROFESSIONAL_N', name: 'Professional N' }, + 0x00000067 => { ms_const: 'PRODUCT_PROFESSIONAL_WMC', name: 'Professional with Media Center' }, + 0x00000018 => { ms_const: 'PRODUCT_SERVER_FOR_SMALLBUSINESS', name: 'Windows Server 2008 for Windows Essential Server Solutions' }, + 0x00000023 => { ms_const: 'PRODUCT_SERVER_FOR_SMALLBUSINESS_V', name: 'Windows Server 2008 without Hyper-V for Windows Essential Server Solutions' }, + 0x00000021 => { ms_const: 'PRODUCT_SERVER_FOUNDATION', name: 'Server Foundation' }, + 0x00000022 => { ms_const: 'PRODUCT_HOME_PREMIUM_SERVER', name: 'Windows Home Server 2011' }, + 0x00000032 => { ms_const: 'PRODUCT_SB_SOLUTION_SERVER', name: 'Windows Small Business Server 2011 Essentials' }, + 0x00000013 => { ms_const: 'PRODUCT_HOME_SERVER', name: 'Windows Storage Server 2008 R2 Essentials' }, + 0x00000009 => { ms_const: 'PRODUCT_SMALLBUSINESS_SERVER', name: 'Windows Small Business Server' }, + 0x00000038 => { ms_const: 'PRODUCT_SOLUTION_EMBEDDEDSERVER', name: 'Windows MultiPoint Server' }, + 0x00000007 => { ms_const: 'PRODUCT_STANDARD_SERVER', name: 'Server Standard (full installation)' }, + 0x0000000D => { ms_const: 'PRODUCT_STANDARD_SERVER_CORE', name: 'Server Standard (core installation)' }, + 0x00000028 => { ms_const: 'PRODUCT_STANDARD_SERVER_CORE_V', name: 'Server Standard without Hyper-V (core installation)' }, + 0x00000024 => { ms_const: 'PRODUCT_STANDARD_SERVER_V', name: 'Server Standard without Hyper-V (full installation)' }, + 0x0000000B => { ms_const: 'PRODUCT_STARTER', name: 'Starter' }, + 0x00000042 => { ms_const: 'PRODUCT_STARTER_E', name: 'Not supported' }, + 0x0000002F => { ms_const: 'PRODUCT_STARTER_N', name: 'Starter N' }, + 0x00000017 => { ms_const: 'PRODUCT_STORAGE_ENTERPRISE_SERVER', name: 'Storage Server Enterprise' }, + 0x00000014 => { ms_const: 'PRODUCT_STORAGE_EXPRESS_SERVER', name: 'Storage Server Express' }, + 0x00000015 => { ms_const: 'PRODUCT_STORAGE_STANDARD_SERVER', name: 'Storage Server Standard' }, + 0x00000016 => { ms_const: 'PRODUCT_STORAGE_WORKGROUP_SERVER', name: 'Storage Server Workgroup' }, + 0x00000000 => { ms_const: 'PRODUCT_UNDEFINED', name: 'An unknown product' }, + 0x00000001 => { ms_const: 'PRODUCT_ULTIMATE', name: 'Ultimate' }, + 0x00000047 => { ms_const: 'PRODUCT_ULTIMATE_E', name: 'Not supported' }, + 0x0000001C => { ms_const: 'PRODUCT_ULTIMATE_N', name: 'Ultimate N' }, + 0x00000011 => { ms_const: 'PRODUCT_WEB_SERVER', name: 'Web Server (full installation)' }, + 0x0000001D => { ms_const: 'PRODUCT_WEB_SERVER_CORE', name: 'Web Server (core installation)' }, + }.freeze unless defined?(SKU) + + attr_reader :major_version, :minor_version, :build_number, :service_pack_major_version, :service_pack_minor_version + attr_reader :version, :product_type, :product_suite, :sku + + def initialize + unless RUBY_PLATFORM =~ /mswin|mingw32|windows/ + raise NotImplementedError, 'only valid on Windows platform' + end + @version, @product_type, @product_suite, @sku, @service_pack_major_version, @service_pack_minor_version = get_os_info + @major_version, @minor_version, @build_number = version.split('.').map(&:to_i) + end + + WIN_VERSIONS = { + 'Windows 10' => { major: 10, minor: 0, callable: -> { @product_type != VER_NT_WORKSTATION } }, + 'Windows Server 2012 R2' => { major: 6, minor: 3, callable: -> { @product_type != VER_NT_WORKSTATION } }, + 'Windows 8' => { major: 6, minor: 2, callable: -> { @product_type == VER_NT_WORKSTATION } }, + 'Windows Server 2012' => { major: 6, minor: 2, callable: -> { @product_type != VER_NT_WORKSTATION } }, + 'Windows 7' => { major: 6, minor: 1, callable: -> { @product_type == VER_NT_WORKSTATION } }, + 'Windows Server 2008 R2' => { major: 6, minor: 1, callable: -> { @product_type != VER_NT_WORKSTATION } }, + 'Windows Server 2008' => { major: 6, minor: 0, callable: -> { @product_type != VER_NT_WORKSTATION } }, + 'Windows Vista' => { major: 6, minor: 0, callable: -> { @product_type == VER_NT_WORKSTATION } }, + 'Windows Home Server' => { major: 5, minor: 2, callable: -> { (@product_suite & VER_SUITE_WH_SERVER) == VER_SUITE_WH_SERVER } }, + 'Windows XP' => { major: 5, minor: 1 }, + 'Windows 2000' => { major: 5, minor: 0 }, + }.freeze unless defined?(WIN_VERSIONS) + + marketing_names = [] + + # General Windows checks + WIN_VERSIONS.each do |k, v| + method_name = "#{k.gsub(/\s/, '_').downcase}?" + define_method(method_name) do + (@major_version == v[:major]) && + (@minor_version == v[:minor]) && + (v[:callable] ? v[:callable].call : true) + end + marketing_names << [k, method_name] + end + + define_method(:marketing_name) do + marketing_names.each do |mn| + break mn[0] if send(mn[1]) + end + end + + # Server Type checks + %w( core full datacenter ).each do |m| + define_method("server_#{m}?") do + if @sku + !(SKU[@sku][:name] =~ /#{m}/i).nil? + else + false + end + end + end + + private + + # query WMI Win32_OperatingSystem for required OS info + def get_os_info + cols = %w( Version ProductType OSProductSuite OperatingSystemSKU ServicePackMajorVersion ServicePackMinorVersion ) + os_info = execute_wmi_query('select * from Win32_OperatingSystem').each.next + cols.map do |c| + begin + wmi_object_property(os_info, c) + rescue # OperatingSystemSKU doesn't exist in all versions of Windows + nil + end + end + end + end +end diff --git a/cookbooks/windows/libraries/version_helper.rb b/cookbooks/windows/libraries/version_helper.rb new file mode 100644 index 0000000..fcb0aa7 --- /dev/null +++ b/cookbooks/windows/libraries/version_helper.rb @@ -0,0 +1,93 @@ +# +# Cookbook:: windows +# Library:: version_helper +# Author:: Baptiste Courtois () +# +# Copyright:: 2015-2017, Criteo +# +# 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. +# +module Windows + # Module based on windows ohai kernel.cs_info providing version helpers + module VersionHelper + # Module referencing CORE SKU contants from product type + # see. https://msdn.microsoft.com/windows/desktop/ms724358#PRODUCT_DATACENTER_SERVER_CORE + # n.b. Prefix - PRODUCT_ - and suffix - _CORE- have been removed + module CoreSKU + # Server Datacenter Core + DATACENTER_SERVER = 0x0C unless constants.include?(:DATACENTER_SERVER) + # Server Datacenter without Hyper-V Core + DATACENTER_SERVER_V = 0x27 unless constants.include?(:DATACENTER_SERVER_V) + # Server Enterprise Core + ENTERPRISE_SERVER = 0x0E unless constants.include?(:ENTERPRISE_SERVER) + # Server Enterprise without Hyper-V Core + ENTERPRISE_SERVER_V = 0x29 unless constants.include?(:ENTERPRISE_SERVER_V) + # Server Standard Core + STANDARD_SERVER = 0x0D unless constants.include?(:STANDARD_SERVER) + # Server Standard without Hyper-V Core + STANDARD_SERVER_V = 0x28 unless constants.include?(:STANDARD_SERVER_V) + # Small Business Server Premium Core + PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE = 0x3F unless constants.include?(:PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE) + # Server Solutions Premium Core + STANDARD_SERVER_SOLUTIONS = 0x35 unless constants.include?(:STANDARD_SERVER_SOLUTIONS) + # Storage Server Enterprise Core + STORAGE_ENTERPRISE_SERVER = 0x2E unless constants.include?(:STORAGE_ENTERPRISE_SERVER) + # Storage Server Express Core + STORAGE_EXPRESS_SERVER = 0x2B unless constants.include?(:STORAGE_EXPRESS_SERVER) + # Storage Server Standard Core + STORAGE_STANDARD_SERVER = 0x2C unless constants.include?(:STORAGE_STANDARD_SERVER) + # Storage Server Workgroup Core + STORAGE_WORKGROUP_SERVER = 0x2D unless constants.include?(:STORAGE_WORKGROUP_SERVER) + # Web Server Core + WEB_SERVER = 0x1D unless constants.include?(:WEB_SERVER) + end + + # Module referencing product type contants + # see. https://msdn.microsoft.com/windows/desktop/ms724833#VER_NT_SERVER + # n.b. Prefix - VER_NT_ - has been removed + module ProductType + WORKSTATION = 0x1 unless constants.include?(:WORKSTATION) + DOMAIN_CONTROLLER = 0x2 unless constants.include?(:DOMAIN_CONTROLLER) + SERVER = 0x3 unless constants.include?(:SERVER) + end + + # Determines whether current node is running a windows Core version + def self.core_version?(node) + validate_platform node + + CoreSKU.constants.any? { |c| CoreSKU.const_get(c) == node['kernel']['os_info']['operating_system_sku'] } + end + + # Determines whether current node is a workstation version + def self.workstation_version?(node) + validate_platform node + node['kernel']['os_info']['product_type'] == ProductType::WORKSTATION + end + + # Determines whether current node is a server version + def self.server_version?(node) + !workstation_version?(node) + end + + # Determines NT version of the current node + def self.nt_version(node) + validate_platform node + + node['platform_version'].to_f + end + + def self.validate_platform(node) + raise 'Windows helper are only supported on windows platform!' unless node['platform'] == 'windows' + end + end +end diff --git a/cookbooks/windows/libraries/windows_helper.rb b/cookbooks/windows/libraries/windows_helper.rb new file mode 100644 index 0000000..97ec431 --- /dev/null +++ b/cookbooks/windows/libraries/windows_helper.rb @@ -0,0 +1,165 @@ +# +# Author:: Seth Chisamore () +# Cookbook:: windows +# Library:: windows_helper +# +# Copyright:: 2011-2018, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require 'uri' +require 'chef/exceptions' +require 'openssl' +require 'chef/mixin/powershell_out' +require 'chef/mixin/windows_env_helper' +require 'chef/util/path_helper' + +module Windows + module Helper + AUTO_RUN_KEY = 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run'.freeze unless defined?(AUTO_RUN_KEY) + ENV_KEY = 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'.freeze unless defined?(ENV_KEY) + include Chef::Mixin::WindowsEnvHelper + + # returns windows friendly version of the provided path, + # ensures backslashes are used everywhere + def win_friendly_path(path) + Chef::Log.warn('The win_friendly_path helper has been deprecated and will be removed from the next major release of the windows cookbook. Please update any cookbooks using this helper to instead require `chef/util/path_helper` and then use `Chef::Util::PathHelper.cleanpath`.') + path.gsub(::File::SEPARATOR, ::File::ALT_SEPARATOR || '\\') if path + end + + # account for Window's wacky File System Redirector + # http://msdn.microsoft.com/en-us/library/aa384187(v=vs.85).aspx + # especially important for 32-bit processes (like Ruby) on a + # 64-bit instance of Windows. + def locate_sysnative_cmd(cmd) + if ::File.exist?("#{ENV['WINDIR']}\\sysnative\\#{cmd}") + "#{ENV['WINDIR']}\\sysnative\\#{cmd}" + elsif ::File.exist?("#{ENV['WINDIR']}\\system32\\#{cmd}") + "#{ENV['WINDIR']}\\system32\\#{cmd}" + else + cmd + end + end + + # singleton instance of the Windows Version checker + def win_version + @win_version ||= Windows::Version.new + end + + # Helper function to properly parse a URI + def as_uri(source) + URI.parse(source) + rescue URI::InvalidURIError + Chef::Log.warn("#{source} was an invalid URI. Trying to escape invalid characters") + URI.parse(URI.escape(source)) + end + + # if a file is local it returns a windows friendly path version + # if a file is remote it caches it locally + def cached_file(source, checksum = nil, windows_path = true) + @installer_file_path ||= begin + + if source =~ %r{^(file|ftp|http|https):\/\/} + uri = as_uri(source) + cache_file_path = "#{Chef::Config[:file_cache_path]}/#{::File.basename(::URI.unescape(uri.path))}" + Chef::Log.debug("Caching a copy of file #{source} at #{cache_file_path}") + remote_file cache_file_path do + source source + backup false + checksum checksum unless checksum.nil? + end.run_action(:create) + else + cache_file_path = source + end + + windows_path ? Chef::Util::PathHelper.cleanpath(cache_file_path) : cache_file_path + end + end + + # Expands the environment variables + def expand_env_vars(path) + # The windows Env provider does not correctly expand variables in + # the PATH environment variable. Ruby expects these to be expanded. + # Using Chef::Mixin::WindowsEnvHelper + expand_path(path) + end + + def is_package_installed?(package_name) # rubocop:disable Naming/PredicateName + installed_packages.include?(package_name) + end + + def installed_packages + @installed_packages || begin + installed_packages = {} + # Computer\HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall + installed_packages.merge!(extract_installed_packages_from_key(::Win32::Registry::HKEY_LOCAL_MACHINE)) # rescue nil + # 64-bit registry view + # Computer\HKEY_LOCAL_MACHINE\Software\Wow6464Node\Microsoft\Windows\CurrentVersion\Uninstall + installed_packages.merge!(extract_installed_packages_from_key(::Win32::Registry::HKEY_LOCAL_MACHINE, (::Win32::Registry::Constants::KEY_READ | 0x0100))) # rescue nil + # 32-bit registry view + # Computer\HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall + installed_packages.merge!(extract_installed_packages_from_key(::Win32::Registry::HKEY_LOCAL_MACHINE, (::Win32::Registry::Constants::KEY_READ | 0x0200))) # rescue nil + # Computer\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Uninstall + installed_packages.merge!(extract_installed_packages_from_key(::Win32::Registry::HKEY_CURRENT_USER)) # rescue nil + installed_packages + end + end + + # Returns an array + def to_array(var) + var = var.is_a?(Array) ? var : [var] + var.reject(&:nil?) + end + + private + + def extract_installed_packages_from_key(hkey = ::Win32::Registry::HKEY_LOCAL_MACHINE, desired = ::Win32::Registry::Constants::KEY_READ) + uninstall_subkey = 'Software\Microsoft\Windows\CurrentVersion\Uninstall' + packages = {} + begin + ::Win32::Registry.open(hkey, uninstall_subkey, desired) do |reg| + reg.each_key do |key, _wtime| + begin + k = reg.open(key, desired) + display_name = begin + k['DisplayName'] + rescue + nil + end + version = begin + k['DisplayVersion'] + rescue + 'NO VERSION' + end + uninstall_string = begin + k['UninstallString'] + rescue + nil + end + if display_name + packages[display_name] = { name: display_name, + version: version, + uninstall_string: uninstall_string } + end + rescue ::Win32::Registry::Error + end + end + end + rescue ::Win32::Registry::Error + end + packages + end + end +end + +Chef::Recipe.send(:include, Windows::Helper) diff --git a/cookbooks/windows/libraries/windows_privileged.rb b/cookbooks/windows/libraries/windows_privileged.rb new file mode 100644 index 0000000..68d96c3 --- /dev/null +++ b/cookbooks/windows/libraries/windows_privileged.rb @@ -0,0 +1,103 @@ +# +# Author:: Doug MacEachern +# Author:: Paul Morton () +# Cookbook:: windows +# Library:: windows_privileged +# +# Copyright:: 2010-2017, VMware, Inc. +# Copyright:: 2011-2017, Business Intelligence Associates, Inc +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# helpers for Windows API calls that require privilege adjustments +class Chef + class WindowsPrivileged + # File -> Load Hive... in regedit.exe + def reg_load_key(name, file) + load_deps + + run(SE_BACKUP_NAME, SE_RESTORE_NAME) do + rc = RegLoadKey(HKEY_USERS, name.to_s, file) + if rc == ERROR_SUCCESS + return true + elsif rc == ERROR_SHARING_VIOLATION + return false + else + raise get_last_error(rc) + end + end + end + + # File -> Unload Hive... in regedit.exe + def reg_unload_key(name) + load_deps + + run(SE_BACKUP_NAME, SE_RESTORE_NAME) do + rc = RegUnLoadKey(HKEY_USERS, name.to_s) + raise get_last_error(rc) if rc != ERROR_SUCCESS + end + end + + def run(*privileges) + load_deps + + token = [0].pack('L') + + unless OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, token) + raise get_last_error + end + token = token.unpack1('L') + + privileges.each do |name| + unless adjust_privilege(token, name, SE_PRIVILEGE_ENABLED) + raise get_last_error + end + end + + begin + yield + ensure # disable privs + privileges.each do |name| + adjust_privilege(token, name, 0) + end + end + end + + def adjust_privilege(token, priv, attr = 0) + load_deps + + luid = [0, 0].pack('Ll') + if LookupPrivilegeValue(nil, priv, luid) + new_state = [1, luid.unpack('Ll'), attr].flatten.pack('LLlL') + AdjustTokenPrivileges(token, 0, new_state, new_state.size, 0, 0) + end + end + + private + + def load_deps + if RUBY_PLATFORM =~ /mswin|mingw32|windows/ + require 'windows/error' + require 'windows/registry' + require 'windows/process' + require 'windows/security' + + include Windows::Error + include Windows::Registry + include Windows::Process + include Windows::Security + end + end + end +end diff --git a/cookbooks/windows/libraries/wmi_helper.rb b/cookbooks/windows/libraries/wmi_helper.rb new file mode 100644 index 0000000..2acdc38 --- /dev/null +++ b/cookbooks/windows/libraries/wmi_helper.rb @@ -0,0 +1,34 @@ +# +# Author:: Adam Edwards () +# Cookbook:: windows +# Library:: wmi_helper +# +# Copyright:: 2014-2018, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if RUBY_PLATFORM =~ /mswin|mingw32|windows/ + require 'win32ole' + + def execute_wmi_query(wmi_query) + wmi = ::WIN32OLE.connect('winmgmts://') + result = wmi.ExecQuery(wmi_query) + return nil unless result.each.count > 0 + result + end + + def wmi_object_property(wmi_object, wmi_property) + wmi_object.send(wmi_property) + end +end diff --git a/cookbooks/windows/metadata.json b/cookbooks/windows/metadata.json new file mode 100644 index 0000000..33a7cfd --- /dev/null +++ b/cookbooks/windows/metadata.json @@ -0,0 +1 @@ +{"name":"windows","version":"6.0.0","description":"Provides a set of useful Windows-specific primitives.","long_description":"# Windows Cookbook\n\n[![Build status](https://ci.appveyor.com/api/projects/status/9x4uepmm1g4rktie/branch/master?svg=true)](https://ci.appveyor.com/project/ChefWindowsCookbooks/windows/branch/master) [![Cookbook Version](https://img.shields.io/cookbook/v/windows.svg)](https://supermarket.chef.io/cookbooks/windows)\n\nProvides a set of Windows-specific resources to aid in the creation of cookbooks/recipes targeting the Windows platform.\n\n## Requirements\n\n### Platforms\n\n- Windows 7\n- Windows Server 2008 R2\n- Windows 8, 8.1\n- Windows Server 2012 (R1, R2)\n- Windows Server 2016\n\n### Chef\n\n- Chef 14+\n\n## Resources\n\n### Deprecated Resources Note\n\nAs of Chef 14.7+ the windows_share and windows_certificate resources are now included in the Chef Client. If you are running Chef 14.7+ the resources in Chef client will take precedence over the resources in this cookbook. In November 2019 we will release a new major version of this cookbook that removes these resources.\n\n### windows_certificate\n\n`Note`: This resource is now included in Chef 14.7 and later. There is no need to depend on the Windows cookbook for this resource.\n\nInstalls a certificate into the Windows certificate store from a file, and grants read-only access to the private key for designated accounts. Due to current limitations in WinRM, installing certificated remotely may not work if the operation requires a user profile. Operations on the local machine store should still work.\n\n#### Actions\n\n- `:create` - creates or updates a certificate.\n- `:delete` - deletes a certificate.\n- `:acl_add` - adds read-only entries to a certificate's private key ACL.\n- `:verify` - logs whether or not a certificate is valid\n\n#### Properties\n\n- `source` - name attribute. The source file (for create and acl_add), thumbprint (for delete and acl_add) or subject (for delete).\n- `pfx_password` - the password to access the source if it is a pfx file.\n- `private_key_acl` - array of 'domain\\account' entries to be granted read-only access to the certificate's private key. This is not idempotent.\n- `store_name` - the certificate store to manipulate. One of:\n - MY (Personal)\n - CA (Intermediate Certification Authorities)\n - ROOT (Trusted Root Certification Authorities)\n - TRUSTEDPUBLISHER (Trusted Publishers)\n - CLIENTAUTHISSUER (Client Authentication Issuers)\n - REMOTE DESKTOP (Remote Desktop)\n - TRUSTEDDEVICES (Trusted Devices)\n - WEBHOSTING (Web Hosting)\n - AUTHROOT (Third-Party Root Certification Authorities)\n - TRUSTEDPEOPLE (Trusted People)\n - SMARTCARDROOT (Smart Card Trusted Roots)\n - TRUST (Enterprise Trust)\n - DISALLOWED (Untrusted Certificates)\n- `user_store` - if false (default) then use the local machine store; if true then use the current user's store.\n\n#### Examples\n\n```ruby\n# Add PFX cert to local machine personal store and grant accounts read-only access to private key\nwindows_certificate \"c:/test/mycert.pfx\" do\n pfx_password \"password\"\n private_key_acl [\"acme\\fred\", \"pc\\jane\"]\nend\n```\n\n```ruby\n# Add cert to trusted intermediate store\nwindows_certificate \"c:/test/mycert.cer\" do\n store_name \"CA\"\nend\n```\n\n```ruby\n# Remove all certificates matching the subject\nwindows_certificate \"me.acme.com\" do\n action :delete\nend\n```\n\n### windows_certificate_binding\n\nBinds a certificate to an HTTP port in order to enable TLS communication.\n\n#### Actions\n\n- `:create` - creates or updates a binding.\n- `:delete` - deletes a binding.\n\n#### Properties\n\n- `cert_name` - name attribute. The thumbprint(hash) or subject that identifies the certificate to be bound.\n- `name_kind` - indicates the type of cert_name. One of :subject (default) or :hash.\n- `address` - the address to bind against. Default is 0.0.0.0 (all IP addresses). One of:\n - IP v4 address `1.2.3.4`\n - IP v6 address `[::1]`\n - Host name `www.foo.com`\n- `port` - the port to bind against. Default is 443.\n- `app_id` - the GUID that defines the application that owns the binding. Default is the values used by IIS.\n- `store_name` - the store to locate the certificate in. One of:\n - MY (Personal)\n - CA (Intermediate Certification Authorities)\n - ROOT (Trusted Root Certification Authorities)\n - TRUSTEDPUBLISHER (Trusted Publishers)\n - CLIENTAUTHISSUER (Client Authentication Issuers)\n - REMOTE DESKTOP (Remote Desktop)\n - TRUSTEDDEVICES (Trusted Devices)\n - WEBHOSTING (Web Hosting)\n - AUTHROOT (Third-Party Root Certification Authorities)\n - TRUSTEDPEOPLE (Trusted People)\n - SMARTCARDROOT (Smart Card Trusted Roots)\n - TRUST (Enterprise Trust)\n\n#### Examples\n\n```ruby\n# Bind the first certificate matching the subject to the default TLS port\nwindows_certificate_binding \"me.acme.com\" do\nend\n```\n\n```ruby\n# Bind a cert from the CA store with the given hash to port 4334\nwindows_certificate_binding \"me.acme.com\" do\n cert_name \"d234567890a23f567c901e345bc8901d34567890\"\n name_kind :hash\n store_name \"CA\"\n port 4334\nend\n```\n\n### windows_dns\n\nConfigures A and CNAME records in Windows DNS. This requires the DNSCMD to be installed, which is done by adding the DNS role to the server or installing the Remote Server Admin Tools.\n\n#### Actions\n\n- :create: creates/updates the DNS entry\n- :delete: deletes the DNS entry\n\n#### Properties\n\n- host_name: name attribute. FQDN of the entry to act on.\n- dns_server: the DNS server to update. Default is local machine (.)\n- record_type: the type of record to create. One of A (default) or CNAME\n- target: for A records an array of IP addresses to associate with the host; for CNAME records the FQDN of the host to alias\n- ttl: if > 0 then set the time to live of the record\n\n#### Examples\n\n```ruby\n# Create A record linked to 2 addresses with a 10 minute ttl\nwindows_dns \"m1.chef.test\" do\n target ['10.9.8.7', '1.2.3.4']\n ttl 600\nend\n```\n\n```ruby\n# Delete records. target is mandatory although not used\nwindows_dns \"m1.chef.test\" do\n action :delete\n target []\nend\n```\n\n```ruby\n# Set an alias against the node in a role\nnodes = search( :node, \"role:my_service\" )\nwindows_dns \"myservice.chef.test\" do\n record_type 'CNAME'\n target nodes[0]['fqdn']\nend\n```\n\n### windows_http_acl\n\nSets the Access Control List for an http URL to grant non-admin accounts permission to open HTTP endpoints.\n\n#### Actions\n\n- `:create` - creates or updates the ACL for a URL.\n- `:delete` - deletes the ACL from a URL.\n\n#### Properties\n\n- `url` - the name of the url to be created/deleted.\n- `sddl` - the DACL string configuring all permissions to URL. Mandatory for create if user is not provided. Can't be use with `user`.\n- `user` - the name (domain\\user) of the user or group to be granted permission to the URL. Mandatory for create if sddl is not provided. Can't be use with `sddl`. Only one user or group can be granted permission so this replaces any previously defined entry. If you receive a parameter error your user may not exist.\n\n#### Examples\n\n```ruby\nwindows_http_acl 'http://+:50051/' do\n user 'pc\\\\fred'\nend\n```\n\n```ruby\n# Grant access to users \"NT SERVICE\\WinRM\" and \"NT SERVICE\\Wecsvc\" via sddl\nwindows_http_acl 'http://+:5985/' do\n sddl 'D:(A;;GX;;;S-1-5-80-569256582-2953403351-2909559716-1301513147-412116970)(A;;GX;;;S-1-5-80-4059739203-877974739-1245631912-527174227-2996563517)'\nend\n```\n\n```ruby\nwindows_http_acl 'http://+:50051/' do\n action :delete\nend\n```\n\n### windows_share\n\n`Note`: This resource is now included in Chef 14.7 and later. There is no need to depend on the Windows cookbook for this resource.\n\nCreates, modifies and removes Windows shares. All properties are idempotent.\n\n`Note`: This resource uses PowerShell cmdlets introduced in Windows 2012/8.\n\n#### Actions\n\n- `:create`: creates/modifies a share\n- `:delete`: deletes a share\n\n#### Properties\n\nproperty | type | default | description\n------------------------ | ---------- | ------------- | -----------------------------------------------------------------------------------------------------------------------------------------------------------\n`share_name` | String | resource name | the share to assign to the share\n`path` | String | | The path of the location of the folder to share. Required when creating. If the share already exists on a different path then it is deleted and re-created.\n`description` | String | | description to be applied to the share\n`full_users` | Array | [] | users which should have \"Full control\" permissions\n`change_users` | Array | [] | Users are granted modify permission to access the share.\n`read_users` | Array | [] | users which should have \"Read\" permissions\n`temporary` | True/False | false | The lifetime of the new SMB share. A temporary share does not persist beyond the next restart of the computer\n`scope_name` | String | '*' | The scope name of the share.\n`ca_timeout` | Integer | 0 | The continuous availability time-out for the share.\n`continuously_available` | True/False | false | Indicates that the share is continuously available.\n`concurrent_user_limit` | Integer | 0 (unlimited) | The maximum number of concurrently connected users the share can accommodate\n`encrypt_data` | True/False | false | Indicates that the share is encrypted.\n\n#### Examples\n\n```ruby\nwindows_share \"foo\" do\n action :create\n path \"C:\\\\foo\"\n full_users [\"DOMAIN_A\\\\some_user\", \"DOMAIN_B\\\\some_other_user\"]\n read_users [\"DOMAIN_C\\\\Domain users\"]\nend\n```\n\n```ruby\nwindows_share \"foo\" do\n action :delete\nend\n```\n\n### windows_user_privilege\n\nAdds the `principal` (User/Group) to the specified privileges (such as `Logon as a batch job` or `Logon as a Service`).\n\n#### Actions\n\n- `:add` - add the specified privileges to the `principal`\n- `:remove` - remove the specified privilege of the `principal`\n\n#### Properties\n\n- `principal` - Name attribute, Required, String. The user or group to be granted privileges.\n- `privilege` - Required, String/Array. The privilege(s) to be granted.\n\n#### Examples\n\nGrant the Administrator user the `Logon as a batch job` and `Logon as a service` privilege.\n\n```ruby\nwindows_user_privilege 'Administrator' do\n privilege %w(SeBatchLogonRight SeServiceLogonRight)\nend\n```\n\nRemove `Logon as a batch job` privilege of Administrator.\n\n```ruby\nwindows_user_privilege 'Administrator' do\n privilege %w(SeBatchLogonRight)\n action :remove\nend\n```\n\n#### Available Privileges\n\n```\nSeTrustedCredManAccessPrivilege Access Credential Manager as a trusted caller\nSeNetworkLogonRight Access this computer from the network\nSeTcbPrivilege Act as part of the operating system\nSeMachineAccountPrivilege Add workstations to domain\nSeIncreaseQuotaPrivilege Adjust memory quotas for a process\nSeInteractiveLogonRight Allow log on locally\nSeRemoteInteractiveLogonRight Allow log on through Remote Desktop Services\nSeBackupPrivilege Back up files and directories\nSeChangeNotifyPrivilege Bypass traverse checking\nSeSystemtimePrivilege Change the system time\nSeTimeZonePrivilege Change the time zone\nSeCreatePagefilePrivilege Create a pagefile\nSeCreateTokenPrivilege Create a token object\nSeCreateGlobalPrivilege Create global objects\nSeCreatePermanentPrivilege Create permanent shared objects\nSeCreateSymbolicLinkPrivilege Create symbolic links\nSeDebugPrivilege Debug programs\nSeDenyNetworkLogonRight Deny access this computer from the network\nSeDenyBatchLogonRight Deny log on as a batch job\nSeDenyServiceLogonRight Deny log on as a service\nSeDenyInteractiveLogonRight Deny log on locally\nSeDenyRemoteInteractiveLogonRight Deny log on through Remote Desktop Services\nSeEnableDelegationPrivilege Enable computer and user accounts to be trusted for delegation\nSeRemoteShutdownPrivilege Force shutdown from a remote system\nSeAuditPrivilege Generate security audits\nSeImpersonatePrivilege Impersonate a client after authentication\nSeIncreaseWorkingSetPrivilege Increase a process working set\nSeIncreaseBasePriorityPrivilege Increase scheduling priority\nSeLoadDriverPrivilege Load and unload device drivers\nSeLockMemoryPrivilege Lock pages in memory\nSeBatchLogonRight Log on as a batch job\nSeServiceLogonRight Log on as a service\nSeSecurityPrivilege Manage auditing and security log\nSeRelabelPrivilege Modify an object label\nSeSystemEnvironmentPrivilege Modify firmware environment values\nSeManageVolumePrivilege Perform volume maintenance tasks\nSeProfileSingleProcessPrivilege Profile single process\nSeSystemProfilePrivilege Profile system performance\nSeUnsolicitedInputPrivilege \"Read unsolicited input from a terminal device\"\nSeUndockPrivilege Remove computer from docking station\nSeAssignPrimaryTokenPrivilege Replace a process level token\nSeRestorePrivilege Restore files and directories\nSeShutdownPrivilege Shut down the system\nSeSyncAgentPrivilege Synchronize directory service data\nSeTakeOwnershipPrivilege Take ownership of files or other objects\n```\n\n### windows_zipfile\n\nMost version of Windows do not ship with native cli utility for managing compressed files. This resource provides a pure-ruby implementation for managing zip files. Be sure to use the `not_if` or `only_if` meta parameters to guard the resource for idempotence or action will be taken every Chef run.\n\n#### Actions\n\n- `:unzip` - unzip a compressed file\n- `:zip` - zip a directory (recursively)\n\n#### Properties\n\n- `path` - name attribute. The path where files will be (un)zipped to.\n- `source` - source of the zip file (either a URI or local path) for :unzip, or directory to be zipped for :zip.\n- `overwrite` - force an overwrite of the files if they already exist.\n- `checksum` - for :unzip, useful if source is remote, if the local file matches the SHA-256 checksum, Chef will not download it.\n\n#### Examples\n\nUnzip a remote zip file locally\n\n```ruby\nwindows_zipfile 'c:/bin' do\n source 'http://download.sysinternals.com/Files/SysinternalsSuite.zip'\n action :unzip\n not_if {::File.exists?('c:/bin/PsExec.exe')}\nend\n```\n\nUnzip a local zipfile\n\n```ruby\nwindows_zipfile 'c:/the_codez' do\n source 'c:/foo/baz/the_codez.zip'\n action :unzip\nend\n```\n\nCreate a local zipfile\n\n```ruby\nwindows_zipfile 'c:/foo/baz/the_codez.zip' do\n source 'c:/the_codez'\n action :zip\nend\n```\n\n## Libraries\n\n### WindowsHelper\n\nHelper that allows you to use helpful functions in windows\n\n#### installed_packages\n\nReturns a hash of all DisplayNames installed\n\n```ruby\n# usage in a recipe\n::Chef::Recipe.send(:include, Windows::Helper)\nhash_of_installed_packages = installed_packages\n```\n\n#### is_package_installed?\n\n- `package_name` - The name of the package you want to query to see if it is installed\n- `returns` - true if the package is installed, false if it the package is not installed\n\nDownload a file if a package isn't installed\n\n```ruby\n# usage in a recipe to not download a file if package is already installed\n::Chef::Recipe.send(:include, Windows::Helper)\nis_win_sdk_installed = is_package_installed?('Windows Software Development Kit')\n\nremote_file 'C:\\windows\\temp\\windows_sdk.zip' do\n source 'http://url_to_download/windows_sdk.zip'\n action :create_if_missing\n not_if {is_win_sdk_installed}\nend\n```\n\nDo something if a package is installed\n\n```ruby\n# usage in a provider\ninclude Windows::Helper\nif is_package_installed?('Windows Software Development Kit')\n # do something if package is installed\nend\n```\n\n### Windows::VersionHelper\n\nHelper that allows you to get information of the windows version running on your node. It leverages windows ohai from kernel.os_info, easy to mock and to use even on linux.\n\n#### core_version?\n\nDetermines whether given node is running on a windows Core.\n\n```ruby\nif ::Windows::VersionHelper.core_version? node\n fail 'Windows Core is not supported'\nend\n```\n\n#### workstation_version?\n\nDetermines whether given node is a windows workstation version (XP, Vista, 7, 8, 8.1, 10)\n\n```ruby\nif ::Windows::VersionHelper.workstation_version? node\n fail 'Only server version of windows are supported'\nend\n```\n\n#### server_version?\n\nDetermines whether given node is a windows server version (Server 2003, Server 2008, Server 2012, Server 2016)\n\n```ruby\nif ::Windows::VersionHelper.server_version? node\n puts 'Server version of windows are cool'\nend\n```\n\n#### nt_version\n\nDetermines NT version of the given node\n\n```ruby\ncase ::Windows::VersionHelper.nt_version node\n when '6.0' then 'Windows vista or Server 2008'\n when '6.1' then 'Windows 7 or Server 2008R2'\n when '6.2' then 'Windows 8 or Server 2012'\n when '6.3' then 'Windows 8.1 or Server 2012R2'\n when '10.0' then 'Windows 10'\nend\n```\n\n## Usage\n\nPlace an explicit dependency on this cookbook (using depends in the cookbook's metadata.rb) from any cookbook where you would like to use the Windows-specific resources/providers that ship with this cookbook.\n\n```ruby\ndepends 'windows'\n```\n\n## License & Authors\n\n- Author:: Seth Chisamore ([schisamo@chef.io](mailto:schisamo@chef.io))\n- Author:: Doug MacEachern ([dougm@vmware.com](mailto:dougm@vmware.com))\n- Author:: Paul Morton ([pmorton@biaprotect.com](mailto:pmorton@biaprotect.com))\n- Author:: Doug Ireton ([doug.ireton@nordstrom.com](mailto:doug.ireton@nordstrom.com))\n\n```text\nCopyright 2011-2018, Chef Software, Inc.\nCopyright 2010, VMware, Inc.\nCopyright 2011, Business Intelligence Associates, Inc\nCopyright 2012, Nordstrom, Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"windows":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/chef-cookbooks/windows","issues_url":"https://github.com/chef-cookbooks/windows/issues","chef_version":[[">= 14"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/windows/metadata.rb b/cookbooks/windows/metadata.rb new file mode 100644 index 0000000..f65f147 --- /dev/null +++ b/cookbooks/windows/metadata.rb @@ -0,0 +1,11 @@ +name 'windows' +maintainer 'Chef Software, Inc.' +maintainer_email 'cookbooks@chef.io' +license 'Apache-2.0' +description 'Provides a set of useful Windows-specific primitives.' +long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) +version '6.0.0' +supports 'windows' +source_url 'https://github.com/chef-cookbooks/windows' +issues_url 'https://github.com/chef-cookbooks/windows/issues' +chef_version '>= 14' diff --git a/cookbooks/windows/providers/dns.rb b/cookbooks/windows/providers/dns.rb new file mode 100644 index 0000000..f6a8b31 --- /dev/null +++ b/cookbooks/windows/providers/dns.rb @@ -0,0 +1,153 @@ +# +# Author:: Richard Lavey (richard.lavey@calastone.com) +# Cookbook:: windows +# Provider:: dns +# +# Copyright:: 2015, Calastone Ltd. +# +# 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. +# + +# See this for info on DNSCMD +# https://technet.microsoft.com/en-gb/library/cc772069.aspx#BKMK_10 + +include Windows::Helper + +# Support whyrun +def whyrun_supported? + true +end + +action :create do + if @current_resource.exists + needs_change = (@new_resource.record_type != @current_resource.record_type) || + (@new_resource.ttl > 0 && @new_resource.ttl != @current_resource.ttl) || + (@new_resource.target.is_a?(String) && @new_resource.target != @current_resource.target) || + (@new_resource.target.is_a?(Array) && !(@new_resource.target - @current_resource.target).empty?) + + if needs_change + converge_by("Changing #{@new_resource.host_name}") do + update_dns + end + else + Chef::Log.debug("#{@new_resource.host_name} already exists - nothing to do") + end + else + converge_by("Creating #{@new_resource.host_name}") do + update_dns + end + end +end + +action :delete do + if @current_resource.exists + converge_by("Deleting #{@current_resource.host_name}") do + execute_command! 'recorddelete', "#{@current_resource.record_type} /f" + end + else + Chef::Log.debug("#{@new_resource.host_name} does not exist - nothing to do") + end +end + +def load_current_resource + # validate the new resource params : A records should be an array + if @new_resource.record_type == 'A' && @new_resource.target.is_a?(String) + raise 'target property must be an array for record_type A' + end + + @current_resource = Chef::Resource::WindowsDns.new(@new_resource.name) + @current_resource.host_name(@new_resource.host_name) + @current_resource.dns_server(@new_resource.dns_server) + + parts = @current_resource.host_name.scan(/(\w+)\.(.*)/) + @host = parts[0][0] + @domain = parts[0][1] + + fetch_attributes +end + +private + +def fetch_attributes + @command = locate_sysnative_cmd('dnscmd.exe') + cmd = shell_out("#{@command} #{@current_resource.dns_server} /enumrecords #{@domain} #{@host}") + Chef::Log.debug "dnscmd reports: #{cmd.stdout}" + + # extract values from returned text + if cmd.stdout.include?('DNS_ERROR_NAME_DOES_NOT_EXIST') + @current_resource.exists = false + @current_resource.target([]) + elsif cmd.exitstatus == 0 + @current_resource.exists = true + + m = cmd.stdout.scan(/(\d+)\s(A)\s+(\d+\.\d+\.\d+\.\d+)/) + if m.empty? + m = cmd.stdout.scan(/(\d+)\s(CNAME)\s+((?:\w+\.)+)/) + if m.empty? + @current_resource.exists = false + @current_resource.target([]) + else + # We have a cname record + @current_resource.record_type('CNAME') + @current_resource.ttl(m[0][0].to_i) + @current_resource.target(m[0][2].chomp('.')) + end + else + # we have A entries + @current_resource.record_type('A') + @current_resource.ttl(m[0][0].to_i) + addresses = [] + m.each do |match| + addresses.push(match[2]) + end + @current_resource.target(addresses) + end + else + raise "dnscmd returned error #{cmd.exitstatus} : #{cmd.stderr} #{cmd.stdout}" + end +end + +def update_dns + ttl = @new_resource.ttl if @new_resource.ttl > 0 + + if @current_resource.record_type != @new_resource.record_type + # delete current record(s) as we're changing the type + execute_command! 'recorddelete', "#{@current_resource.record_type} /f" + end + + if @new_resource.record_type == 'A' + # delete existing records that are no longer defined + (@current_resource.target - @new_resource.target).each do |address| + Chef::Log.info "Deleting #{address}" + execute_command! 'recorddelete', "A #{address} /f" + end + + # add new records that don't exist + # if ttl has changed then update all records + addresses = if @current_resource.ttl == @new_resource.ttl + (@new_resource.target - @current_resource.target) + else + @new_resource.target + end + addresses.each do |address| + Chef::Log.info "Adding/Changing #{address}" + execute_command! 'recordadd', "#{ttl} A #{address}" + end + else + execute_command! 'recordadd', "#{ttl} CNAME #{@new_resource.target}" + end +end + +def execute_command!(mode, options) + shell_out!("#{@command} #{@current_resource.dns_server} /#{mode} #{@domain} #{@host} #{options}") +end diff --git a/cookbooks/windows/recipes/default.rb b/cookbooks/windows/recipes/default.rb new file mode 100644 index 0000000..73845f6 --- /dev/null +++ b/cookbooks/windows/recipes/default.rb @@ -0,0 +1,21 @@ +# +# Author:: Seth Chisamore () +# Cookbook:: windows +# Recipe:: default +# +# Copyright:: 2011-2018, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +Chef::Log.warn('The windows::default recipe has been deprecated. The gems previously installed in this recipe ship in the Chef MSI.') diff --git a/cookbooks/windows/resources/certificate.rb b/cookbooks/windows/resources/certificate.rb new file mode 100644 index 0000000..4003fbb --- /dev/null +++ b/cookbooks/windows/resources/certificate.rb @@ -0,0 +1,301 @@ +# +# Author:: Richard Lavey (richard.lavey@calastone.com) +# Cookbook:: windows +# Resource:: certificate +# +# Copyright:: 2015-2017, Calastone Ltd. +# Copyright:: 2018-2019, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'chef/util/path_helper' + +chef_version_for_provides '< 14.7' if respond_to?(:chef_version_for_provides) +resource_name :windows_certificate + +property :source, String, name_property: true +property :pfx_password, String +property :private_key_acl, Array +property :store_name, String, default: 'MY', equal_to: ['TRUSTEDPUBLISHER', 'TrustedPublisher', 'CLIENTAUTHISSUER', 'REMOTE DESKTOP', 'ROOT', 'TRUSTEDDEVICES', 'WEBHOSTING', 'CA', 'AUTHROOT', 'TRUSTEDPEOPLE', 'MY', 'SMARTCARDROOT', 'TRUST', 'DISALLOWED'] +property :user_store, [TrueClass, FalseClass], default: false +property :cert_path, String +property :sensitive, [ TrueClass, FalseClass ], default: lazy { |r| r.pfx_password ? true : false } + +action :create do + load_gem + + # Extension of the certificate + ext = ::File.extname(new_resource.source) + cert_obj = fetch_cert_object(ext) # Fetch OpenSSL::X509::Certificate object + thumbprint = OpenSSL::Digest::SHA1.new(cert_obj.to_der).to_s # Fetch its thumbprint + + # Need to check if return value is Boolean:true + # If not then the given certificate should be added in certstore + if verify_cert(thumbprint) == true + Chef::Log.debug('Certificate is already present') + else + converge_by("Adding certificate #{new_resource.source} into Store #{new_resource.store_name}") do + if ext == '.pfx' + add_pfx_cert + else + add_cert(cert_obj) + end + end + end +end + +# acl_add is a modify-if-exists operation : not idempotent +action :acl_add do + if ::File.exist?(new_resource.source) + hash = '$cert.GetCertHashString()' + code_script = cert_script(false) + guard_script = cert_script(false) + else + # make sure we have no spaces in the hash string + hash = "\"#{new_resource.source.gsub(/\s/, '')}\"" + code_script = '' + guard_script = '' + end + code_script << acl_script(hash) + guard_script << cert_exists_script(hash) + + powershell_script "setting the acls on #{new_resource.source} in #{cert_location}\\#{new_resource.store_name}" do + guard_interpreter :powershell_script + convert_boolean_return true + code code_script + only_if guard_script + sensitive if new_resource.sensitive + end +end + +action :delete do + load_gem + + cert_obj = fetch_cert + if cert_obj + converge_by("Deleting certificate #{new_resource.source} from Store #{new_resource.store_name}") do + delete_cert + end + else + Chef::Log.debug('Certificate not found') + end +end + +action :fetch do + load_gem + + cert_obj = fetch_cert + if cert_obj + show_or_store_cert(cert_obj) + else + Chef::Log.debug('Certificate not found') + end +end + +action :verify do + load_gem + + out = verify_cert + if !!out == out + out = out ? 'Certificate is valid' : 'Certificate not valid' + end + Chef::Log.info(out.to_s) +end + +action_class do + require 'openssl' + + # load the gem and rescue a gem install if it fails to load + def load_gem + gem 'win32-certstore', '>= 0.2.4' + require 'win32-certstore' # until this is in core chef + rescue LoadError + Chef::Log.debug('Did not find win32-certstore >= 0.2.4 gem installed. Installing now') + chef_gem 'win32-certstore' do + compile_time true + action :upgrade + end + + require 'win32-certstore' + end + + def add_cert(cert_obj) + store = ::Win32::Certstore.open(new_resource.store_name) + store.add(cert_obj) + end + + def add_pfx_cert + store = ::Win32::Certstore.open(new_resource.store_name) + store.add_pfx(new_resource.source, new_resource.pfx_password) + end + + def delete_cert + store = ::Win32::Certstore.open(new_resource.store_name) + store.delete(new_resource.source) + end + + def fetch_cert + store = ::Win32::Certstore.open(new_resource.store_name) + store.get(new_resource.source) + end + + # Checks whether a certificate with the given thumbprint + # is already present and valid in certificate store + # If the certificate is not present, verify_cert returns a String: "Certificate not found" + # But if it is present but expired, it returns a Boolean: false + # Otherwise, it returns a Boolean: true + def verify_cert(thumbprint = new_resource.source) + store = ::Win32::Certstore.open(new_resource.store_name) + store.valid?(thumbprint) + end + + def show_or_store_cert(cert_obj) + if new_resource.cert_path + export_cert(cert_obj, new_resource.cert_path) + if ::File.size(new_resource.cert_path) > 0 + Chef::Log.info("Certificate export in #{new_resource.cert_path}") + else + ::File.delete(new_resource.cert_path) + end + else + Chef::Log.info(cert_obj.display) + end + end + + def export_cert(cert_obj, cert_path) + out_file = ::File.new(cert_path, 'w+') + case ::File.extname(cert_path) + when '.pem' + out_file.puts(cert_obj.to_pem) + when '.der' + out_file.puts(cert_obj.to_der) + when '.cer' + cert_out = powershell_out("openssl x509 -text -inform DER -in #{cert_obj.to_pem} -outform CER").stdout + out_file.puts(cert_out) + when '.crt' + cert_out = powershell_out("openssl x509 -text -inform DER -in #{cert_obj.to_pem} -outform CRT").stdout + out_file.puts(cert_out) + when '.pfx' + cert_out = powershell_out("openssl pkcs12 -export -nokeys -in #{cert_obj.to_pem} -outform PFX").stdout + out_file.puts(cert_out) + when '.p7b' + cert_out = powershell_out("openssl pkcs7 -export -nokeys -in #{cert_obj.to_pem} -outform P7B").stdout + out_file.puts(cert_out) + else + Chef::Log.info('Supported certificate format .pem, .der, .cer, .crt, .pfx and .p7b') + end + out_file.close + end + + def cert_location + @location ||= new_resource.user_store ? 'CurrentUser' : 'LocalMachine' + end + + def cert_script(persist) + cert_script = '$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2' + file = Chef::Util::PathHelper.cleanpath(new_resource.source) + cert_script << " \"#{file}\"" + if ::File.extname(file.downcase) == '.pfx' + cert_script << ", \"#{new_resource.pfx_password}\"" + if persist && new_resource.user_store + cert_script << ', ([System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet)' + elsif persist + cert_script << ', ([System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet -bor [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeyset)' + end + end + cert_script << "\n" + end + + def cert_exists_script(hash) + <<-EOH +$hash = #{hash} +Test-Path "Cert:\\#{cert_location}\\#{new_resource.store_name}\\$hash" + EOH + end + + def within_store_script + inner_script = yield '$store' + <<-EOH +$store = New-Object System.Security.Cryptography.X509Certificates.X509Store "#{new_resource.store_name}", ([System.Security.Cryptography.X509Certificates.StoreLocation]::#{cert_location}) +$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite) +#{inner_script} +$store.Close() + EOH + end + + def acl_script(hash) + return '' if new_resource.private_key_acl.nil? || new_resource.private_key_acl.empty? + + # this PS came from http://blogs.technet.com/b/operationsguy/archive/2010/11/29/provide-access-to-private-keys-commandline-vs-powershell.aspx + # and from https://msdn.microsoft.com/en-us/library/windows/desktop/bb204778(v=vs.85).aspx + set_acl_script = <<-EOH +$hash = #{hash} +$storeCert = Get-ChildItem "cert:\\#{cert_location}\\#{new_resource.store_name}\\$hash" +if ($storeCert -eq $null) { throw 'no key exists.' } +$keyname = $storeCert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName +if ($keyname -eq $null) { throw 'no private key exists.' } +if ($storeCert.PrivateKey.CspKeyContainerInfo.MachineKeyStore) +{ + $fullpath = "$Env:ProgramData\\Microsoft\\Crypto\\RSA\\MachineKeys\\$keyname" +} +else +{ + $currentUser = New-Object System.Security.Principal.NTAccount($Env:UserDomain, $Env:UserName) + $userSID = $currentUser.Translate([System.Security.Principal.SecurityIdentifier]).Value + $fullpath = "$Env:ProgramData\\Microsoft\\Crypto\\RSA\\$userSID\\$keyname" +} + EOH + new_resource.private_key_acl.each do |name| + set_acl_script << "$uname='#{name}'; icacls $fullpath /grant $uname`:RX\n" + end + set_acl_script + end + + # Method returns an OpenSSL::X509::Certificate object + # + # Based on its extension, the certificate contents are used to initialize + # PKCS12 (PFX), PKCS7 (P7B) objects which contains OpenSSL::X509::Certificate. + # + # @note Other then PEM, all the certificates are usually in binary format, and hence + # their contents are loaded by using File.binread + # + # @param ext [String] Extension of the certificate + # + # @return [OpenSSL::X509::Certificate] Object containing certificate's attributes + # + # @raise [OpenSSL::PKCS12::PKCS12Error] When incorrect password is provided for PFX certificate + # + def fetch_cert_object(ext) + contents = if binary_cert? + ::File.binread(new_resource.source) + else + ::File.read(new_resource.source) + end + + case ext + when '.pfx' + OpenSSL::PKCS12.new(contents, new_resource.pfx_password).certificate + when '.p7b' + OpenSSL::PKCS7.new(contents).certificates.first + else + OpenSSL::X509::Certificate.new(contents) + end + end + + # @return [Boolean] Whether the certificate file is binary encoded or not + # + def binary_cert? + powershell_out!("file -b --mime-encoding #{new_resource.source}").stdout.strip == 'binary' + end +end diff --git a/cookbooks/windows/resources/certificate_binding.rb b/cookbooks/windows/resources/certificate_binding.rb new file mode 100644 index 0000000..df0aa44 --- /dev/null +++ b/cookbooks/windows/resources/certificate_binding.rb @@ -0,0 +1,135 @@ +# +# Author:: Richard Lavey (richard.lavey@calastone.com) +# Cookbook:: windows +# Resource:: certificate_binding +# +# Copyright:: 2015-2017, Calastone Ltd. +# Copyright:: 2018, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include Chef::Mixin::PowershellOut +include Windows::Helper + +property :cert_name, String, name_property: true +property :name_kind, Symbol, equal_to: [:hash, :subject], default: :subject +property :address, String, default: '0.0.0.0' +property :port, Integer, default: 443 +property :app_id, String, default: '{4dc3e181-e14b-4a21-b022-59fc669b0914}' +property :store_name, String, default: 'MY', equal_to: ['TRUSTEDPUBLISHER', 'CLIENTAUTHISSUER', 'REMOTE DESKTOP', 'ROOT', 'TRUSTEDDEVICES', 'WEBHOSTING', 'CA', 'AUTHROOT', 'TRUSTEDPEOPLE', 'MY', 'SMARTCARDROOT', 'TRUST'] +property :exists, [true, false], desired_state: true + +load_current_value do |desired| + mode = desired.address.match(/(\d+\.){3}\d+|\[.+\]/).nil? ? 'hostnameport' : 'ipport' + cmd = shell_out("#{locate_sysnative_cmd('netsh.exe')} http show sslcert #{mode}=#{desired.address}:#{desired.port}") + Chef::Log.debug "netsh reports: #{cmd.stdout}" + + address desired.address + port desired.port + store_name desired.store_name + app_id desired.app_id + + if cmd.exitstatus == 0 + m = cmd.stdout.scan(/Certificate Hash\s+:\s?([A-Fa-f0-9]{40})/) + raise "Failed to extract hash from command output #{cmd.stdout}" if m.empty? + cert_name m[0][0] + name_kind :hash + exists true + else + exists false + end +end + +action :create do + hash = new_resource.name_kind == :subject ? hash_from_subject : new_resource.cert_name + + if current_resource.exists + needs_change = (hash.casecmp(current_resource.cert_name) != 0) + + if needs_change + converge_by("Changing #{current_resource.address}:#{current_resource.port}") do + delete_binding + add_binding hash + end + else + Chef::Log.debug("#{new_resource.address}:#{new_resource.port} already bound to #{hash} - nothing to do") + end + else + converge_by("Binding #{new_resource.address}:#{new_resource.port}") do + add_binding hash + end + end +end + +action :delete do + if current_resource.exists + converge_by("Deleting #{current_resource.address}:#{current_resource.port}") do + delete_binding + end + else + Chef::Log.debug("#{current_resource.address}:#{current_resource.port} not bound - nothing to do") + end +end + +action_class do + def netsh_command + locate_sysnative_cmd('netsh.exe') + end + + def add_binding(hash) + cmd = "#{netsh_command} http add sslcert" + mode = address_mode(current_resource.address) + cmd << " #{mode}=#{current_resource.address}:#{current_resource.port}" + cmd << " certhash=#{hash}" + cmd << " appid=#{current_resource.app_id}" + cmd << " certstorename=#{current_resource.store_name}" + check_hash hash + + shell_out!(cmd) + end + + def delete_binding + mode = address_mode(current_resource.address) + shell_out!("#{netsh_command} http delete sslcert #{mode}=#{current_resource.address}:#{current_resource.port}") + end + + def check_hash(hash) + p = powershell_out!("Test-Path \"cert:\\LocalMachine\\#{current_resource.store_name}\\#{hash}\"") + + unless p.stderr.empty? && p.stdout =~ /True/i + raise "A Cert with hash of #{hash} doesn't exist in keystore LocalMachine\\#{current_resource.store_name}" + end + nil + end + + def hash_from_subject + # escape wildcard subject name (*.acme.com) + subject = new_resource.cert_name.sub(/\*/, '`*') + ps_script = "& { gci cert:\\localmachine\\#{new_resource.store_name} | where { $_.subject -like '*#{subject}*' } | select -first 1 -expandproperty Thumbprint }" + + Chef::Log.debug "Running PS script #{ps_script}" + p = powershell_out!(ps_script) + + raise "#{ps_script} failed with #{p.stderr}" if !p.stderr.nil? && !p.stderr.empty? + raise "Couldn't find thumbprint for subject #{new_resource.cert_name}" if p.stdout.nil? || p.stdout.empty? + + # seem to get a UTF-8 string with BOM returned sometimes! Strip any such BOM + hash = p.stdout.strip + hash[0].ord == 239 ? hash.force_encoding('UTF-8').delete!("\xEF\xBB\xBF".force_encoding('UTF-8')) : hash + end + + def address_mode(address) + address.match(/(\d+\.){3}\d+|\[.+\]/).nil? ? 'hostnameport' : 'ipport' + end +end diff --git a/cookbooks/windows/resources/dns.rb b/cookbooks/windows/resources/dns.rb new file mode 100644 index 0000000..35b0274 --- /dev/null +++ b/cookbooks/windows/resources/dns.rb @@ -0,0 +1,30 @@ +# +# Author:: Richard Lavey (richard.lavey@calastone.com) +# Cookbook Name:: windows +# Resource:: dns +# +# Copyright:: 2015, Calastone Ltd. +# +# 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. +# + +actions :create, :delete +default_action :create + +attribute :host_name, kind_of: String, name_property: true, required: true +attribute :record_type, kind_of: String, default: 'A', regex: /^(?:A|CNAME)$/ +attribute :dns_server, kind_of: String, default: '.' +attribute :target, kind_of: [Array, String], required: true +attribute :ttl, kind_of: Integer, required: false, default: 0 + +attr_accessor :exists diff --git a/cookbooks/windows/resources/http_acl.rb b/cookbooks/windows/resources/http_acl.rb new file mode 100644 index 0000000..c675043 --- /dev/null +++ b/cookbooks/windows/resources/http_acl.rb @@ -0,0 +1,109 @@ +# +# Author:: Richard Lavey (richard.lavey@calastone.com) +# Cookbook:: windows +# Resource:: http_acl +# +# Copyright:: 2015-2017, Calastone Ltd. +# +# 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. +# + +include Windows::Helper + +property :url, String, name_property: true +property :user, String +property :sddl, String +property :exists, [true, false], desired_state: true + +# See https://msdn.microsoft.com/en-us/library/windows/desktop/cc307236%28v=vs.85%29.aspx for netsh info + +load_current_value do |desired| + cmd_out = shell_out!("#{locate_sysnative_cmd('netsh.exe')} http show urlacl url=#{desired.url}").stdout + Chef::Log.debug "netsh reports: #{cmd_out}" + + if cmd_out.include? desired.url + exists true + url desired.url + # Checks first for sddl, because it generates user(s) + sddl_match = cmd_out.match(/SDDL:\s*(?\S+)/) + if sddl_match + sddl sddl_match['sddl'] + else + # if no sddl, tries to find a single user + user_match = cmd_out.match(/User:\s*(?.+)/) + user user_match['user'] + end + else + exists false + end +end + +action :create do + raise '`user` xor `sddl` can\'t be used together' if new_resource.user && new_resource.sddl + raise 'When provided user property can\'t be empty' if new_resource.user && new_resource.user.empty? + raise 'When provided sddl property can\'t be empty' if new_resource.sddl && new_resource.sddl.empty? + + if current_resource.exists + sddl_changed = ( + new_resource.sddl && + current_resource.sddl && + current_resource.sddl.casecmp(new_resource.sddl) != 0 + ) + user_changed = ( + new_resource.user && + current_resource.user && + current_resource.user.casecmp(new_resource.user) != 0 + ) + + if sddl_changed || user_changed + converge_by("Changing #{new_resource.url}") do + delete_acl + apply_acl + end + else + Chef::Log.debug("#{new_resource.url} already set - nothing to do") + end + else + converge_by("Setting #{new_resource.url}") do + apply_acl + end + end +end + +action :delete do + if current_resource.exists + converge_by("Deleting #{new_resource.url}") do + delete_acl + end + else + Chef::Log.debug("#{new_resource.url} does not exist - nothing to do") + end +end + +action_class do + def netsh_command + locate_sysnative_cmd('netsh.exe') + end + + def apply_acl + if current_resource.sddl + shell_out!("#{netsh_command} http add urlacl url=#{new_resource.url} sddl=\"#{new_resource.sddl}\"") + else + shell_out!("#{netsh_command} http add urlacl url=#{new_resource.url} user=\"#{new_resource.user}\"") + end + end + + def delete_acl + shell_out!("#{netsh_command} http delete urlacl url=#{new_resource.url}") + end +end diff --git a/cookbooks/windows/resources/share.rb b/cookbooks/windows/resources/share.rb new file mode 100644 index 0000000..9e5196b --- /dev/null +++ b/cookbooks/windows/resources/share.rb @@ -0,0 +1,288 @@ +# +# Author:: Sölvi Páll Ásgeirsson () +# Author:: Richard Lavey (richard.lavey@calastone.com) +# Author:: Tim Smith (tsmith@chef.io) +# Cookbook:: windows +# Resource:: share +# +# Copyright:: 2014-2017, Sölvi Páll Ásgeirsson. +# Copyright:: 2018, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +chef_version_for_provides '< 14.7' if respond_to?(:chef_version_for_provides) +resource_name :windows_share + +require 'chef/json_compat' +require 'chef/util/path_helper' + +# Specifies a name for the SMB share. The name may be composed of any valid file name characters, but must be less than 80 characters long. The names pipe and mailslot are reserved for use by the computer. +property :share_name, String, name_property: true + +# Specifies the path of the location of the folder to share. The path must be fully qualified. Relative paths or paths that contain wildcard characters are not permitted. +property :path, String + +# Specifies an optional description of the SMB share. A description of the share is displayed by running the Get-SmbShare cmdlet. The description may not contain more than 256 characters. +property :description, String, default: '' + +# Specifies which accounts are granted full permission to access the share. Use a comma-separated list to specify multiple accounts. An account may not be specified more than once in the FullAccess, ChangeAccess, or ReadAccess parameter lists, but may be specified once in the FullAccess, ChangeAccess, or ReadAccess parameter list and once in the NoAccess parameter list. +property :full_users, Array, default: [], coerce: proc { |u| u.sort } + +# Specifies which users are granted modify permission to access the share +property :change_users, Array, default: [], coerce: proc { |u| u.sort } + +# Specifies which users are granted read permission to access the share. Multiple users can be specified by supplying a comma-separated list. +property :read_users, Array, default: [], coerce: proc { |u| u.sort } + +# Specifies the lifetime of the new SMB share. A temporary share does not persist beyond the next restart of the computer. By default, new SMB shares are persistent, and non-temporary. +property :temporary, [true, false], default: false + +# Specifies the scope name of the share. +property :scope_name, String, default: '*' + +# Specifies the continuous availability time-out for the share. +property :ca_timeout, Integer, default: 0 + +# Indicates that the share is continuously available. +property :continuously_available, [true, false], default: false + +# Specifies the caching mode of the offline files for the SMB share. +# property :caching_mode, String, equal_to: %w(None Manual Documents Programs BranchCache) + +# Specifies the maximum number of concurrently connected users that the new SMB share may accommodate. If this parameter is set to zero (0), then the number of users is unlimited. +property :concurrent_user_limit, Integer, default: 0 + +# Indicates that the share is encrypted. +property :encrypt_data, [true, false], default: false + +# Specifies which files and folders in the SMB share are visible to users. AccessBased: SMB does not the display the files and folders for a share to a user unless that user has rights to access the files and folders. By default, access-based enumeration is disabled for new SMB shares. Unrestricted: SMB displays files and folders to a user even when the user does not have permission to access the items. +# property :folder_enumeration_mode, String, equal_to: %(AccessBased Unrestricted) + +include Chef::Mixin::PowershellOut + +load_current_value do |desired| + # this command selects individual objects because EncryptData & CachingMode have underlying + # types that get converted to their Integer values by ConvertTo-Json & we need to make sure + # those get written out as strings + share_state_cmd = "Get-SmbShare -Name '#{desired.share_name}' | Select-Object Name,Path, Description, Temporary, CATimeout, ContinuouslyAvailable, ConcurrentUserLimit, EncryptData | ConvertTo-Json" + + Chef::Log.debug("Running '#{share_state_cmd}' to determine share state'") + ps_results = powershell_out(share_state_cmd) + + # detect a failure without raising and then set current_resource to nil + if ps_results.error? + Chef::Log.debug("Error fetching share state: #{ps_results.stderr}") + current_value_does_not_exist! + end + + Chef::Log.debug("The Get-SmbShare results were #{ps_results.stdout}") + results = Chef::JSONCompat.from_json(ps_results.stdout) + + path results['Path'] + description results['Description'] + temporary results['Temporary'] + ca_timeout results['CATimeout'] + continuously_available results['ContinuouslyAvailable'] + # caching_mode results['CachingMode'] + concurrent_user_limit results['ConcurrentUserLimit'] + encrypt_data results['EncryptData'] + # folder_enumeration_mode results['FolderEnumerationMode'] + + perm_state_cmd = %(Get-SmbShareAccess -Name "#{desired.share_name}" | Select-Object AccountName,AccessControlType,AccessRight | ConvertTo-Json) + + Chef::Log.debug("Running '#{perm_state_cmd}' to determine share permissions state'") + ps_perm_results = powershell_out(perm_state_cmd) + + # we raise here instead of warning like above because we'd only get here if the above Get-SmbShare + # command was successful and that continuing would leave us with 1/2 known state + raise "Could not determine #{desired.share_name} share permissions by running '#{perm_state_cmd}'" if ps_perm_results.error? + + Chef::Log.debug("The Get-SmbShareAccess results were #{ps_perm_results.stdout}") + + f_users, c_users, r_users = parse_permissions(ps_perm_results.stdout) + + full_users f_users + change_users c_users + read_users r_users +end + +def after_created + raise 'The windows_share resource relies on PowerShell cmdlets not present in Windows releases prior to 8/2012. Cannot continue!' if node['platform_version'].to_f < 6.3 +end + +# given the string output of Get-SmbShareAccess parse out +# arrays of full access users, change users, and read only users +def parse_permissions(results_string) + json_results = Chef::JSONCompat.from_json(results_string) + json_results = [json_results] unless json_results.is_a?(Array) # single result is not an array + + f_users = [] + c_users = [] + r_users = [] + + json_results.each do |perm| + next unless perm['AccessControlType'] == 0 # allow + case perm['AccessRight'] + when 0 then f_users << stripped_account(perm['AccountName']) # 0 full control + when 1 then c_users << stripped_account(perm['AccountName']) # 1 == change + when 2 then r_users << stripped_account(perm['AccountName']) # 2 == read + end + end + [f_users, c_users, r_users] +end + +# local names are returned from Get-SmbShareAccess in the full format MACHINE\\NAME +# but users of this resource would simply say NAME so we need to strip the values for comparison +def stripped_account(name) + name.slice!("#{node['hostname']}\\") + name +end + +action :create do + # we do this here instead of requiring the property because :delete doesn't need path set + raise 'No path property set' unless new_resource.path + + converge_if_changed do + # you can't actually change the path so you have to delete the old share first + if different_path? + Chef::Log.debug('The path has changed so we will delete and recreate share') + delete_share + create_share + elsif current_resource.nil? + # powershell cmdlet for create is different than updates + Chef::Log.debug('The current resource is nil so we will create a new share') + create_share + else + Chef::Log.debug('The current resource was not nil so we will update an existing share') + update_share + end + + # creating the share does not set permissions so we need to update + update_permissions + end +end + +action :delete do + if current_resource.nil? + Chef::Log.debug("#{new_resource.share_name} does not exist - nothing to do") + else + converge_by("delete #{new_resource.share_name}") do + delete_share + end + end +end + +action_class do + def different_path? + return false if current_resource.nil? # going from nil to something isn't different for our concerns + return false if current_resource.path == Chef::Util::PathHelper.cleanpath(new_resource.path) + true + end + + def delete_share + delete_command = "Remove-SmbShare -Name '#{new_resource.share_name}' -Force" + + Chef::Log.debug("Running '#{delete_command}' to remove the share") + powershell_out!(delete_command) + end + + def update_share + update_command = "Set-SmbShare -Name '#{new_resource.share_name}' -Description '#{new_resource.description}' -Force" + + Chef::Log.debug("Running '#{update_command}' to update the share") + powershell_out!(update_command) + end + + def create_share + raise "#{new_resource.path} is missing or not a directory. Shares cannot be created if the path doesn't first exist." unless ::File.directory? new_resource.path + + share_cmd = "New-SmbShare -Name '#{new_resource.share_name}' -Path '#{Chef::Util::PathHelper.cleanpath(new_resource.path)}' -Description '#{new_resource.description}' -ConcurrentUserLimit #{new_resource.concurrent_user_limit} -CATimeout #{new_resource.ca_timeout} -EncryptData:#{bool_string(new_resource.encrypt_data)} -ContinuouslyAvailable:#{bool_string(new_resource.continuously_available)}" + share_cmd << " -ScopeName #{new_resource.scope_name}" unless new_resource.scope_name == '*' # passing * causes the command to fail + share_cmd << " -Temporary:#{bool_string(new_resource.temporary)}" if new_resource.temporary # only set true + + Chef::Log.debug("Running '#{share_cmd}' to create the share") + powershell_out!(share_cmd) + + # New-SmbShare adds the "Everyone" user with read access no matter what so we need to remove it + # before we add our permissions + revoke_user_permissions(['Everyone']) + end + + # determine what users in the current state don't exist in the desired state + # users/groups will have their permissions updated with the same command that + # sets it, but removes must be performed with Revoke-SmbShareAccess + def users_to_revoke + @users_to_revoke ||= begin + # if the resource doesn't exist then nothing needs to be revoked + if current_resource.nil? + [] + else # if it exists then calculate the current to new resource diffs + (current_resource.full_users + current_resource.change_users + current_resource.read_users) - (new_resource.full_users + new_resource.change_users + new_resource.read_users) + end + end + end + + # update existing permissions on a share + def update_permissions + # revoke any users that had something, but now has nothing + revoke_user_permissions(users_to_revoke) unless users_to_revoke.empty? + + # set permissions for each of the permission types + %w(full read change).each do |perm_type| + # set permissions for a brand new share OR + # update permissions if the current state and desired state differ + next unless permissions_need_update?(perm_type) + grant_command = "Grant-SmbShareAccess -Name '#{new_resource.share_name}' -AccountName \"#{new_resource.send("#{perm_type}_users").join('","')}\" -Force -AccessRight #{perm_type}" + + Chef::Log.debug("Running '#{grant_command}' to update the share permissions") + powershell_out!(grant_command) + end + end + + # determine if permissions need to be updated. + # Brand new share with no permissions defined: no + # Brand new share with permissions defined: yes + # Existing share with differing permissions: yes + # + # @param [String] type the permissions type (Full, Read, or Change) + def permissions_need_update?(type) + property_name = "#{type}_users" + + # brand new share, but nothing to set + return false if current_resource.nil? && new_resource.send(property_name).empty? + + # brand new share with new permissions to set + return true if current_resource.nil? && !new_resource.send(property_name).empty? + + # there's a difference between the current and desired state + return true unless (new_resource.send(property_name) - current_resource.send(property_name)).empty? + + # anything else + false + end + + # revoke user permissions from a share + # @param [Array] users + def revoke_user_permissions(users) + revoke_command = "Revoke-SmbShareAccess -Name '#{new_resource.share_name}' -AccountName \"#{users.join('","')}\" -Force" + Chef::Log.debug("Running '#{revoke_command}' to revoke share permissions") + powershell_out!(revoke_command) + end + + # convert True/False into "$True" & "$False" + def bool_string(bool) + # bool ? 1 : 0 + bool ? '$true' : '$false' + end +end diff --git a/cookbooks/windows/resources/user_privilege.rb b/cookbooks/windows/resources/user_privilege.rb new file mode 100644 index 0000000..2264ded --- /dev/null +++ b/cookbooks/windows/resources/user_privilege.rb @@ -0,0 +1,40 @@ +# +# Author:: Jared Kauppila () +# Cookbook:: windows +# Resource:: user_privilege +# + +property :principal, String, name_property: true +property :privilege, [Array, String], required: true, coerce: proc { |v| [*v].sort } + +action :add do + ([*new_resource.privilege] - [*current_resource.privilege]).each do |user_right| + converge_by("adding user privilege #{user_right}") do + Chef::ReservedNames::Win32::Security.add_account_right(new_resource.principal, user_right) + end + end +end + +action :remove do + if Gem::Version.new(Chef::VERSION) < Gem::Version.new('14.4.10') + Chef::Log.warn('Chef 14.4.10 is required to use windows_privilege remove action') + else + curr_res_privilege = current_resource.privilege + new_res_privilege = new_resource.privilege + missing_res_privileges = (new_res_privilege - curr_res_privilege) + + if missing_res_privileges + Chef::Log.info("Privilege: #{missing_res_privileges.join(', ')} not present. Unable to delete") + end + + (new_res_privilege - missing_res_privileges).each do |user_right| + converge_by("removing user privilege #{user_right}") do + Chef::ReservedNames::Win32::Security.remove_account_right(new_resource.principal, user_right) + end + end + end +end + +load_current_value do |desired| + privilege Chef::ReservedNames::Win32::Security.get_account_right(desired.principal) +end diff --git a/cookbooks/windows/resources/zipfile.rb b/cookbooks/windows/resources/zipfile.rb new file mode 100644 index 0000000..424717b --- /dev/null +++ b/cookbooks/windows/resources/zipfile.rb @@ -0,0 +1,127 @@ +# +# Author:: Doug MacEachern () +# Author:: Seth Chisamore () +# Author:: Wade Peacock () +# Cookbook:: windows +# Resource:: zipfile +# +# Copyright:: 2010-2017, VMware, Inc. +# Copyright:: 2011-2018, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'chef/util/path_helper' + +property :path, String, name_property: true +property :source, String +property :overwrite, [true, false], default: false +property :checksum, String + +action :unzip do + ensure_rubyzip_gem_installed + Chef::Log.debug("unzip #{new_resource.source} => #{new_resource.path} (overwrite=#{new_resource.overwrite})") + + cache_file_path = if new_resource.source =~ %r{^(file|ftp|http|https):\/\/} # http://rubular.com/r/DGoIWjLfGI + uri = as_uri(new_resource.source) + local_cache_path = "#{Chef::Config[:file_cache_path]}/#{::File.basename(::URI.unescape(uri.path))}" + Chef::Log.debug("Caching a copy of file #{new_resource.source} at #{cache_file_path}") + + remote_file local_cache_path do + source new_resource.source + backup false + checksum new_resource.checksum unless new_resource.checksum.nil? + end + + local_cache_path + else + new_resource.source + end + + cache_file_path = Chef::Util::PathHelper.cleanpath(cache_file_path) + + converge_by("unzip #{new_resource.source}") do + ruby_block 'Unzipping' do + block do + Zip::File.open(cache_file_path) do |zip| + zip.each do |entry| + path = ::File.join(new_resource.path, entry.name) + FileUtils.mkdir_p(::File.dirname(path)) + if new_resource.overwrite && ::File.exist?(path) && !::File.directory?(path) + FileUtils.rm(path) + end + zip.extract(entry, path) unless ::File.exist?(path) + end + end + end + action :run + end + end +end + +action :zip do + ensure_rubyzip_gem_installed + # sanitize paths for windows. + new_resource.source.downcase.gsub!(::File::SEPARATOR, ::File::ALT_SEPARATOR) + new_resource.path.downcase.gsub!(::File::SEPARATOR, ::File::ALT_SEPARATOR) + Chef::Log.debug("zip #{new_resource.source} => #{new_resource.path} (overwrite=#{new_resource.overwrite})") + + if new_resource.overwrite == false && ::File.exist?(new_resource.path) + Chef::Log.info("file #{new_resource.path} already exists and overwrite is set to false, exiting") + else + # delete the archive if it already exists, because we are recreating it. + if ::File.exist?(new_resource.path) + converge_by("delete existing file at #{new_resource.path}") do + ::File.unlink(new_resource.path) + end + end + + # only supporting compression of a single directory (recursively). + if ::File.directory?(new_resource.source) + converge_by("zipping #{new_resource.source} to #{new_resource.path}") do + z = Zip::File.new(new_resource.path, true) + unless new_resource.source =~ /::File::ALT_SEPARATOR$/ + new_resource.source << ::File::ALT_SEPARATOR + end + Find.find(new_resource.source) do |f| + f.downcase.gsub!(::File::SEPARATOR, ::File::ALT_SEPARATOR) + # don't add root directory to the zipfile. + next if f == new_resource.source + # strip the root directory from the filename before adding it to the zipfile. + zip_fname = f.sub(new_resource.source, '') + Chef::Log.debug("adding #{zip_fname} to archive, sourcefile is: #{f}") + z.add(zip_fname, f) + end + z.close + end + else + Chef::Log.info("Single directory must be specified for compression, and #{new_resource.source} does not meet that criteria.") + end + end +end + +action_class do + include Windows::Helper + require 'find' + + def ensure_rubyzip_gem_installed + require 'zip' + rescue LoadError + Chef::Log.info("Missing gem 'rubyzip'...installing now.") + chef_gem 'rubyzip' do + action :install + compile_time true + end + require 'zip' + end +end diff --git a/cookbooks/yum-epel/CHANGELOG.md b/cookbooks/yum-epel/CHANGELOG.md new file mode 100644 index 0000000..08b13d6 --- /dev/null +++ b/cookbooks/yum-epel/CHANGELOG.md @@ -0,0 +1,162 @@ +# yum-epel Cookbook CHANGELOG + +This file is used to list changes made in each version of the yum-epel cookbook. + +## 3.3.0 (2018-10-09) + +- Fix cookbook to work on all releases of Amazon Linux 2 +- Test on Amazon Linux 2 in specs and in Travis + +## 3.2.0 (2018-07-24) + +- Support EPEL on ARM32. + +## 3.1.0 (2018-02-26) + +- Add support for Amazon Linux 2.0 + +## 3.0.0 (2018-02-16) + +- Require Chef 12.14+ and remove the compat_resource dependency + +## 2.1.2 (2017-06-15) + +- Switch from Rake testing to Local Delivery +- Update apache2 license string to be a SPDX compliant string +- Change yum repo location of gpgkey to download.fedoraproject.org instead of dl.fedoraproject.org +- Avoid chefspec deprecations and speed up specs + +## 2.1.1 (2017-01-05) + +- Revert how mirror list strings are generated to fix RHEL 7 + +## 2.1.0 (2016-12-22) + +- Test in Travis using the current build of chef/chef docker image +- Test on older Chef +- allow the use of any valid property via attributes +- fixing tests +- output versions in the job that is being ran +- cops + +## 2.0.0 (2016-11-26) + +- Clarify that we require Chef 12.1+ not 12.0+ +- Use compat_resource instead of the yum cookbook +- Add integration testing with inspec + +## 1.0.2 (2016-10-21) + +- Remove upper bound on yum constraint + +## 1.0.1 (2016-09-11) + +- Fix epel-testing attributes + +## 1.0.0 (2016-09-06) + +- Add chef_version metadata +- Testing updates +- Remove support for Chef 11 + +## v0.7.1 (2016-08-19) + +- Remove bats testing +- Fix attribute settings +- Cleanup travis file + +## v0.7.0 (2016-04-27) + +- Added support for IBM zlinux platform +- Added back the Test Kitchen support for local vagrant testing +- Added long_description to the metadata +- Loosen the dependency on the yum cookbook + +## v0.6.5 + +- updated to use `make_cache` option that yum cookbook allows for the yum resource to use. + +## v0.6.5 (2015-11-23) + +- Fix setting bool false properties + +## v0.6.4 (2015-10-27) + +- Updating default recipe for Chef 13 deprecation warnings. Not +- passing nil. + +## v0.6.3 (2015-09-22) + +- Added standard Chef gitignore and chefignore files +- Added the standard chef rubocop config +- Update contributing, maintainers, and testing docs +- Update Chefspec config to 4.X format +- Update distro versions in the Kitchen config +- Add Travis CI and cookbook version badges in the readme +- Expand the requirements section in the readme +- Add additional distros to the metadata +- Added source_url and issues_url metadata + +## v0.6.2 (2015-06-21) + +- Depending on yum ~> 3.2 +- Support for the password attribute wasn't added to the +- yum_repository LWRP until yum 3.2.0. + +## v0.6.1 (2015-06-21) + +- Switching to https for URL links +- Using metalink URLs + +## v0.6.0 (2015-01-03) + +- Adding EL7 support + +## v0.5.3 (2014-10-28) + +- Revert Use HTTPS for GPG keys and mirror lists + +## v0.5.2 (2014-10-28) + +- Use HTTPS for GPG keys and mirror lists +- Use local key on Amazon Linux + +## v0.5.0 (2014-09-02) + +- Add all attribute available to LWRP to allow for tuning. + +## v0.4.0 (2014-07-27) + +- [#9] Allowing list of repositories to reference configurable. + +## v0.3.6 (2014-04-09) + +- [COOK-4509] add RHEL7 support to yum-epel cookbook + +## v0.3.4 (2014-02-19) + +COOK-4353 - Fixing typo in readme + +## v0.3.2 (2014-02-13) + +Updating README to explain the 'managed' parameter + +## v0.3.0 (2014-02-12) + +[COOK-4292] - Do not manage secondary repos by default + +## v0.2.0 + +Adding Amazon Linux support + +## v0.1.6 + +Fixing up attribute values for EL6 + +## v0.1.4 + +Adding CHANGELOG.md + +## v0.1.0 + +initial release diff --git a/cookbooks/yum-epel/CONTRIBUTING.md b/cookbooks/yum-epel/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/yum-epel/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/cookbooks/yum-epel/README.md b/cookbooks/yum-epel/README.md new file mode 100644 index 0000000..734d106 --- /dev/null +++ b/cookbooks/yum-epel/README.md @@ -0,0 +1,175 @@ +# yum-epel Cookbook + +[![Build Status](https://travis-ci.org/chef-cookbooks/yum-epel.svg?branch=master)](http://travis-ci.org/chef-cookbooks/yum-epel) [![Cookbook Version](https://img.shields.io/cookbook/v/yum-epel.svg)](https://supermarket.chef.io/cookbooks/yum-epel) + +Extra Packages for Enterprise Linux (or EPEL) is a Fedora Special Interest Group that creates, maintains, and manages a high quality set of additional packages for Enterprise Linux, including, but not limited to, Red Hat Enterprise Linux (RHEL), CentOS and Scientific Linux (SL), Oracle Linux (OL). + +The yum-epel cookbook takes over management of the default repositoryids shipped with epel-release. It allows attribute manipulation of `epel`, `epel-debuginfo`, `epel-source`, `epel-testing`, `epel-testing-debuginfo`, and `epel-testing-source`. + +## Requirements + +### Platforms + +- RHEL/CentOS and derivatives + +### Chef + +- Chef 12.14+ + +### Cookbooks + +- none + +## Attributes + +The following attributes are set by default + +```ruby +default['yum-epel']['repos'] = %w( + epel + epel-debuginfo + epel-source + epel-testing + epel-testing-debuginfo + epel-testing-source +) +``` + +```ruby +default['yum']['epel']['repositoryid'] = 'epel' +default['yum']['epel']['description'] = 'Extra Packages for Enterprise Linux 6 - $basearch' +default['yum']['epel']['mirrorlist'] = 'http://mirrors.fedoraproject.org/mirrorlist?repo=epel-5&arch=$basearch' +default['yum']['epel']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6' +default['yum']['epel']['failovermethod'] = 'priority' +default['yum']['epel']['gpgcheck'] = true +default['yum']['epel']['enabled'] = true +default['yum']['epel']['managed'] = true +``` + +```ruby +default['yum']['epel-debuginfo']['repositoryid'] = 'epel-debuginfo' +default['yum']['epel-debuginfo']['description'] = 'Extra Packages for Enterprise Linux 6 - $basearch - Debug' +default['yum']['epel-debuginfo']['mirrorlist'] = 'https://mirrors.fedoraproject.org/metalink?repo=epel-debug-6&arch=$basearch' +default['yum']['epel-debuginfo']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6' +default['yum']['epel-debuginfo']['failovermethod'] = 'priority' +default['yum']['epel-debuginfo']['gpgcheck'] = true +default['yum']['epel-debuginfo']['enabled'] = false +default['yum']['epel-debuginfo']['managed'] = false +``` + +```ruby +default['yum']['epel-source']['repositoryid'] = 'epel-source' +default['yum']['epel-source']['description'] = 'Extra Packages for Enterprise Linux 6 - $basearch - Source' +default['yum']['epel-source']['mirrorlist'] = 'http://mirrors.fedoraproject.org/mirrorlist?repo=epel-source-6&arch=$basearch' +default['yum']['epel-source']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6' +default['yum']['epel-source']['failovermethod'] = 'priority' +default['yum']['epel-source']['gpgcheck'] = true +default['yum']['epel-source']['enabled'] = false +default['yum']['epel-source']['managed'] = false +``` + +```ruby +default['yum']['epel-testing']['repositoryid'] = 'epel-testing' +default['yum']['epel-testing']['description'] = 'Extra Packages for Enterprise Linux 6 - Testing - $basearch' +default['yum']['epel-testing']['mirrorlist'] = 'https://mirrors.fedoraproject.org/metalink?repo=testing-epel6&arch=$basearch' +default['yum']['epel-testing']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6r' +default['yum']['epel-testing']['failovermethod'] = 'priority' +default['yum']['epel-testing']['gpgcheck'] = true +default['yum']['epel-testing']['enabled'] = false +default['yum']['epel-testing']['managed'] = false +``` + +```ruby +default['yum']['epel-testing-debuginfo']['repositoryid'] = 'epel-testing-debuginfo' +default['yum']['epel-testing-debuginfo']['description'] = 'Extra Packages for Enterprise Linux 6 - Testing - $basearch Debug' +default['yum']['epel-testing-debuginfo']['mirrorlist'] = 'https://mirrors.fedoraproject.org/metalink?repo=testing-debug-epel6&arch=$basearch' +default['yum']['epel-testing-debuginfo']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6' +default['yum']['epel-testing-debuginfo']['failovermethod'] = 'priority' +default['yum']['epel-testing-debuginfo']['gpgcheck'] = true +default['yum']['epel-testing-debuginfo']['enabled'] = false +default['yum']['epel-testing-debuginfo']['managed'] = false +``` + +```ruby +default['yum']['epel-testing-source']['repositoryid'] = 'epel-testing-source' +default['yum']['epel-testing-source']['description'] = 'Extra Packages for Enterprise Linux 6 - Testing - $basearch Source' +default['yum']['epel-testing-source']['mirrorlist'] = 'https://mirrors.fedoraproject.org/metalink?repo=testing-source-epel6&arch=$basearch' +default['yum']['epel-testing-source']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6' +default['yum']['epel-testing-source']['failovermethod'] = 'priority' +default['yum']['epel-testing-source']['gpgcheck'] = true +default['yum']['epel-testing-source']['enabled'] = false +default['yum']['epel-testing-source']['managed'] = false +``` + +## Recipes + +- default - Walks through node attributes and feeds a yum_resource +- parameters. The following is an example a resource generated by the +- recipe during compilation. + +```ruby + yum_repository 'epel' do + mirrorlist 'http://mirrors.fedoraproject.org/mirrorlist?repo=epel-5&arch=$basearch' + description 'Extra Packages for Enterprise Linux 5 - $basearch' + enabled true + gpgcheck true + gpgkey 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL' + end +``` + +## Usage Example + +To disable the epel repository through a Role or Environment definition + +``` +default_attributes( + :yum => { + :epel => { + :enabled => { + false + } + } + } + ) +``` + +Uncommonly used repositoryids are not managed by default. This is speeds up integration testing pipelines by avoiding yum-cache builds that nobody cares about. To enable the epel-testing repository with a wrapper cookbook, place the following in a recipe: + +```ruby +node.default['yum']['epel-testing']['enabled'] = true +node.default['yum']['epel-testing']['managed'] = true +include_recipe 'yum-epel' +``` + +## More Examples + +Point the epel repositories at an internally hosted server. + +```ruby +node.default['yum']['epel']['enabled'] = true +node.default['yum']['epel']['mirrorlist'] = nil +node.default['yum']['epel']['baseurl'] = 'https://internal.example.com/centos/6/os/x86_64' +node.default['yum']['epel']['sslverify'] = false + +include_recipe 'yum-epel' +``` + +## License & Authors + +**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io)) + +**Copyright:** 2011-2016, Chef Software, Inc. + +``` +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/cookbooks/yum-epel/attributes/default.rb b/cookbooks/yum-epel/attributes/default.rb new file mode 100644 index 0000000..960a280 --- /dev/null +++ b/cookbooks/yum-epel/attributes/default.rb @@ -0,0 +1,8 @@ +default['yum-epel']['repos'] = %w( + epel + epel-debuginfo + epel-source + epel-testing + epel-testing-debuginfo + epel-testing-source +) diff --git a/cookbooks/yum-epel/attributes/epel-debuginfo.rb b/cookbooks/yum-epel/attributes/epel-debuginfo.rb new file mode 100644 index 0000000..f95a9e4 --- /dev/null +++ b/cookbooks/yum-epel/attributes/epel-debuginfo.rb @@ -0,0 +1,20 @@ +default['yum']['epel-debuginfo']['repositoryid'] = 'epel-debuginfo' +default['yum']['epel-debuginfo']['description'] = "Extra Packages for #{node['platform_version'].to_i} - $basearch - Debug" + +if platform?('amazon') + if node['platform_version'].to_i > 2010 + default['yum']['epel-debuginfo']['mirrorlist'] = 'http://mirrors.fedoraproject.org/mirrorlist?repo=epel-debug-6&arch=$basearch' + default['yum']['epel-debuginfo']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6' + else + default['yum']['epel-debuginfo']['mirrorlist'] = 'http://mirrors.fedoraproject.org/mirrorlist?repo=epel-debug-7&arch=$basearch' + default['yum']['epel-debuginfo']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7' + end +else + default['yum']['epel-debuginfo']['mirrorlist'] = "http://mirrors.fedoraproject.org/mirrorlist?repo=epel-debug-#{node['platform_version'].to_i}&arch=$basearch" + default['yum']['epel-debuginfo']['gpgkey'] = "https://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-#{node['platform_version'].to_i}" +end +default['yum']['epel-debuginfo']['failovermethod'] = 'priority' +default['yum']['epel-debuginfo']['gpgcheck'] = true +default['yum']['epel-debuginfo']['enabled'] = false +default['yum']['epel-debuginfo']['managed'] = false +default['yum']['epel-debuginfo']['make_cache'] = true diff --git a/cookbooks/yum-epel/attributes/epel-source.rb b/cookbooks/yum-epel/attributes/epel-source.rb new file mode 100644 index 0000000..51975ba --- /dev/null +++ b/cookbooks/yum-epel/attributes/epel-source.rb @@ -0,0 +1,20 @@ +default['yum']['epel-source']['repositoryid'] = 'epel-source' +default['yum']['epel-source']['description'] = "Extra Packages for #{node['platform_version'].to_i} - $basearch - Source" + +if platform?('amazon') + if node['platform_version'].to_i > 2010 + default['yum']['epel-source']['mirrorlist'] = 'http://mirrors.fedoraproject.org/mirrorlist?repo=epel-source-6&arch=$basearch' + default['yum']['epel-source']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6' + else + default['yum']['epel-source']['mirrorlist'] = 'http://mirrors.fedoraproject.org/mirrorlist?repo=epel-source-7&arch=$basearch' + default['yum']['epel-source']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7' + end +else + default['yum']['epel-source']['mirrorlist'] = "http://mirrors.fedoraproject.org/mirrorlist?repo=epel-source-#{node['platform_version'].to_i}&arch=$basearch" + default['yum']['epel-source']['gpgkey'] = "https://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-#{node['platform_version'].to_i}" +end +default['yum']['epel-source']['failovermethod'] = 'priority' +default['yum']['epel-source']['gpgcheck'] = true +default['yum']['epel-source']['enabled'] = false +default['yum']['epel-source']['managed'] = false +default['yum']['epel-source']['make_cache'] = true diff --git a/cookbooks/yum-epel/attributes/epel-testing-debuginfo.rb b/cookbooks/yum-epel/attributes/epel-testing-debuginfo.rb new file mode 100644 index 0000000..da874d3 --- /dev/null +++ b/cookbooks/yum-epel/attributes/epel-testing-debuginfo.rb @@ -0,0 +1,20 @@ +default['yum']['epel-testing-debuginfo']['repositoryid'] = 'epel-testing-debuginfo' +default['yum']['epel-testing-debuginfo']['description'] = "Extra Packages for #{node['platform_version'].to_i} - $basearch - Testing Debug" + +if platform?('amazon') + if node['platform_version'].to_i > 2010 + default['yum']['epel-testing-debuginfo']['mirrorlist'] = 'http://mirrors.fedoraproject.org/mirrorlist?repo=testing-debug-epel6&arch=$basearch' + default['yum']['epel-testing-debuginfo']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6' + else + default['yum']['epel-testing-debuginfo']['mirrorlist'] = 'http://mirrors.fedoraproject.org/mirrorlist?repo=testing-debug-epel7&arch=$basearch' + default['yum']['epel-testing-debuginfo']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7' + end +else + default['yum']['epel-testing-debuginfo']['mirrorlist'] = "http://mirrors.fedoraproject.org/mirrorlist?repo=testing-debug-epel#{node['platform_version'].to_i}&arch=$basearch" + default['yum']['epel-testing-debuginfo']['gpgkey'] = "https://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-#{node['platform_version'].to_i}" +end +default['yum']['epel-testing-debuginfo']['failovermethod'] = 'priority' +default['yum']['epel-testing-debuginfo']['gpgcheck'] = true +default['yum']['epel-testing-debuginfo']['enabled'] = false +default['yum']['epel-testing-debuginfo']['managed'] = false +default['yum']['epel-testing-debuginfo']['make_cache'] = true diff --git a/cookbooks/yum-epel/attributes/epel-testing-source.rb b/cookbooks/yum-epel/attributes/epel-testing-source.rb new file mode 100644 index 0000000..07bc64d --- /dev/null +++ b/cookbooks/yum-epel/attributes/epel-testing-source.rb @@ -0,0 +1,20 @@ +default['yum']['epel-testing-source']['repositoryid'] = 'epel-testing-source' +default['yum']['epel-testing-source']['description'] = "Extra Packages for #{node['platform_version'].to_i} - $basearch - Testing Source" + +if platform?('amazon') + if node['platform_version'].to_i > 2010 + default['yum']['epel-testing-source']['mirrorlist'] = 'http://mirrors.fedoraproject.org/mirrorlist?repo=testing-source-epel6&arch=$basearch' + default['yum']['epel-testing-source']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6' + else + default['yum']['epel-testing-source']['mirrorlist'] = 'http://mirrors.fedoraproject.org/mirrorlist?repo=testing-source-epel7&arch=$basearch' + default['yum']['epel-testing-source']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7' + end +else + default['yum']['epel-testing-source']['mirrorlist'] = "http://mirrors.fedoraproject.org/mirrorlist?repo=testing-source-epel#{node['platform_version'].to_i}&arch=$basearch" + default['yum']['epel-testing-source']['gpgkey'] = "https://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-#{node['platform_version'].to_i}" +end +default['yum']['epel-testing-source']['failovermethod'] = 'priority' +default['yum']['epel-testing-source']['gpgcheck'] = true +default['yum']['epel-testing-source']['enabled'] = false +default['yum']['epel-testing-source']['managed'] = false +default['yum']['epel-testing-source']['make_cache'] = true diff --git a/cookbooks/yum-epel/attributes/epel-testing.rb b/cookbooks/yum-epel/attributes/epel-testing.rb new file mode 100644 index 0000000..3fe52b8 --- /dev/null +++ b/cookbooks/yum-epel/attributes/epel-testing.rb @@ -0,0 +1,20 @@ +default['yum']['epel-testing']['repositoryid'] = 'epel-testing' +default['yum']['epel-testing']['description'] = "Extra Packages for #{node['platform_version'].to_i} - $basearch - Testing " + +if platform?('amazon') + if node['platform_version'].to_i > 2010 + default['yum']['epel-testing']['mirrorlist'] = 'http://mirrors.fedoraproject.org/mirrorlist?repo=testing-epel6&arch=$basearch' + default['yum']['epel-testing']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6' + else + default['yum']['epel-testing']['mirrorlist'] = 'http://mirrors.fedoraproject.org/mirrorlist?repo=testing-epel7&arch=$basearch' + default['yum']['epel-testing']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7' + end +else + default['yum']['epel-testing']['mirrorlist'] = "http://mirrors.fedoraproject.org/mirrorlist?repo=testing-epel#{node['platform_version'].to_i}&arch=$basearch" + default['yum']['epel-testing']['gpgkey'] = "https://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-#{node['platform_version'].to_i}" +end +default['yum']['epel-testing']['failovermethod'] = 'priority' +default['yum']['epel-testing']['gpgcheck'] = true +default['yum']['epel-testing']['enabled'] = false +default['yum']['epel-testing']['managed'] = false +default['yum']['epel-testing']['make_cache'] = true diff --git a/cookbooks/yum-epel/attributes/epel.rb b/cookbooks/yum-epel/attributes/epel.rb new file mode 100644 index 0000000..5e99bca --- /dev/null +++ b/cookbooks/yum-epel/attributes/epel.rb @@ -0,0 +1,28 @@ +default['yum']['epel']['repositoryid'] = 'epel' +default['yum']['epel']['description'] = "Extra Packages for #{node['platform_version'].to_i} - $basearch" +default['yum']['epel']['gpgcheck'] = true +case node['kernel']['machine'] +when 'armv7l', 'armv7hl' + default['yum']['epel']['baseurl'] = 'https://armv7.dev.centos.org/repodir/epel-pass-1/' + default['yum']['epel']['gpgcheck'] = false +when 's390x' + default['yum']['epel']['baseurl'] = 'https://kojipkgs.fedoraproject.org/rhel/rc/7/Server/s390x/os/' + default['yum']['epel']['gpgkey'] = 'https://kojipkgs.fedoraproject.org/rhel/rc/7/Server/s390x/os/RPM-GPG-KEY-redhat-release' +else + if platform?('amazon') + if node['platform_version'].to_i > 2010 + default['yum']['epel']['mirrorlist'] = 'http://mirrors.fedoraproject.org/mirrorlist?repo=epel-6&arch=$basearch' + default['yum']['epel']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6' + else + default['yum']['epel']['mirrorlist'] = 'http://mirrors.fedoraproject.org/mirrorlist?repo=epel-7&arch=$basearch' + default['yum']['epel']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7' + end + else + default['yum']['epel']['mirrorlist'] = "http://mirrors.fedoraproject.org/mirrorlist?repo=epel-#{node['platform_version'].to_i}&arch=$basearch" + default['yum']['epel']['gpgkey'] = "https://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-#{node['platform_version'].to_i}" + end +end +default['yum']['epel']['failovermethod'] = 'priority' +default['yum']['epel']['enabled'] = true +default['yum']['epel']['managed'] = true +default['yum']['epel']['make_cache'] = true diff --git a/cookbooks/yum-epel/metadata.json b/cookbooks/yum-epel/metadata.json new file mode 100644 index 0000000..399f0fd --- /dev/null +++ b/cookbooks/yum-epel/metadata.json @@ -0,0 +1 @@ +{"name":"yum-epel","version":"3.3.0","description":"Installs and configures the EPEL Yum repository","long_description":"# yum-epel Cookbook\n\n[![Build Status](https://travis-ci.org/chef-cookbooks/yum-epel.svg?branch=master)](http://travis-ci.org/chef-cookbooks/yum-epel) [![Cookbook Version](https://img.shields.io/cookbook/v/yum-epel.svg)](https://supermarket.chef.io/cookbooks/yum-epel)\n\nExtra Packages for Enterprise Linux (or EPEL) is a Fedora Special Interest Group that creates, maintains, and manages a high quality set of additional packages for Enterprise Linux, including, but not limited to, Red Hat Enterprise Linux (RHEL), CentOS and Scientific Linux (SL), Oracle Linux (OL).\n\nThe yum-epel cookbook takes over management of the default repositoryids shipped with epel-release. It allows attribute manipulation of `epel`, `epel-debuginfo`, `epel-source`, `epel-testing`, `epel-testing-debuginfo`, and `epel-testing-source`.\n\n## Requirements\n\n### Platforms\n\n- RHEL/CentOS and derivatives\n\n### Chef\n\n- Chef 12.14+\n\n### Cookbooks\n\n- none\n\n## Attributes\n\nThe following attributes are set by default\n\n```ruby\ndefault['yum-epel']['repos'] = %w(\n epel\n epel-debuginfo\n epel-source\n epel-testing\n epel-testing-debuginfo\n epel-testing-source\n)\n```\n\n```ruby\ndefault['yum']['epel']['repositoryid'] = 'epel'\ndefault['yum']['epel']['description'] = 'Extra Packages for Enterprise Linux 6 - $basearch'\ndefault['yum']['epel']['mirrorlist'] = 'http://mirrors.fedoraproject.org/mirrorlist?repo=epel-5&arch=$basearch'\ndefault['yum']['epel']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6'\ndefault['yum']['epel']['failovermethod'] = 'priority'\ndefault['yum']['epel']['gpgcheck'] = true\ndefault['yum']['epel']['enabled'] = true\ndefault['yum']['epel']['managed'] = true\n```\n\n```ruby\ndefault['yum']['epel-debuginfo']['repositoryid'] = 'epel-debuginfo'\ndefault['yum']['epel-debuginfo']['description'] = 'Extra Packages for Enterprise Linux 6 - $basearch - Debug'\ndefault['yum']['epel-debuginfo']['mirrorlist'] = 'https://mirrors.fedoraproject.org/metalink?repo=epel-debug-6&arch=$basearch'\ndefault['yum']['epel-debuginfo']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6'\ndefault['yum']['epel-debuginfo']['failovermethod'] = 'priority'\ndefault['yum']['epel-debuginfo']['gpgcheck'] = true\ndefault['yum']['epel-debuginfo']['enabled'] = false\ndefault['yum']['epel-debuginfo']['managed'] = false\n```\n\n```ruby\ndefault['yum']['epel-source']['repositoryid'] = 'epel-source'\ndefault['yum']['epel-source']['description'] = 'Extra Packages for Enterprise Linux 6 - $basearch - Source'\ndefault['yum']['epel-source']['mirrorlist'] = 'http://mirrors.fedoraproject.org/mirrorlist?repo=epel-source-6&arch=$basearch'\ndefault['yum']['epel-source']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6'\ndefault['yum']['epel-source']['failovermethod'] = 'priority'\ndefault['yum']['epel-source']['gpgcheck'] = true\ndefault['yum']['epel-source']['enabled'] = false\ndefault['yum']['epel-source']['managed'] = false\n```\n\n```ruby\ndefault['yum']['epel-testing']['repositoryid'] = 'epel-testing'\ndefault['yum']['epel-testing']['description'] = 'Extra Packages for Enterprise Linux 6 - Testing - $basearch'\ndefault['yum']['epel-testing']['mirrorlist'] = 'https://mirrors.fedoraproject.org/metalink?repo=testing-epel6&arch=$basearch'\ndefault['yum']['epel-testing']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6r'\ndefault['yum']['epel-testing']['failovermethod'] = 'priority'\ndefault['yum']['epel-testing']['gpgcheck'] = true\ndefault['yum']['epel-testing']['enabled'] = false\ndefault['yum']['epel-testing']['managed'] = false\n```\n\n```ruby\ndefault['yum']['epel-testing-debuginfo']['repositoryid'] = 'epel-testing-debuginfo'\ndefault['yum']['epel-testing-debuginfo']['description'] = 'Extra Packages for Enterprise Linux 6 - Testing - $basearch Debug'\ndefault['yum']['epel-testing-debuginfo']['mirrorlist'] = 'https://mirrors.fedoraproject.org/metalink?repo=testing-debug-epel6&arch=$basearch'\ndefault['yum']['epel-testing-debuginfo']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6'\ndefault['yum']['epel-testing-debuginfo']['failovermethod'] = 'priority'\ndefault['yum']['epel-testing-debuginfo']['gpgcheck'] = true\ndefault['yum']['epel-testing-debuginfo']['enabled'] = false\ndefault['yum']['epel-testing-debuginfo']['managed'] = false\n```\n\n```ruby\ndefault['yum']['epel-testing-source']['repositoryid'] = 'epel-testing-source'\ndefault['yum']['epel-testing-source']['description'] = 'Extra Packages for Enterprise Linux 6 - Testing - $basearch Source'\ndefault['yum']['epel-testing-source']['mirrorlist'] = 'https://mirrors.fedoraproject.org/metalink?repo=testing-source-epel6&arch=$basearch'\ndefault['yum']['epel-testing-source']['gpgkey'] = 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6'\ndefault['yum']['epel-testing-source']['failovermethod'] = 'priority'\ndefault['yum']['epel-testing-source']['gpgcheck'] = true\ndefault['yum']['epel-testing-source']['enabled'] = false\ndefault['yum']['epel-testing-source']['managed'] = false\n```\n\n## Recipes\n\n- default - Walks through node attributes and feeds a yum_resource\n- parameters. The following is an example a resource generated by the\n- recipe during compilation.\n\n```ruby\n yum_repository 'epel' do\n mirrorlist 'http://mirrors.fedoraproject.org/mirrorlist?repo=epel-5&arch=$basearch'\n description 'Extra Packages for Enterprise Linux 5 - $basearch'\n enabled true\n gpgcheck true\n gpgkey 'http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL'\n end\n```\n\n## Usage Example\n\nTo disable the epel repository through a Role or Environment definition\n\n```\ndefault_attributes(\n :yum => {\n :epel => {\n :enabled => {\n false\n }\n }\n }\n )\n```\n\nUncommonly used repositoryids are not managed by default. This is speeds up integration testing pipelines by avoiding yum-cache builds that nobody cares about. To enable the epel-testing repository with a wrapper cookbook, place the following in a recipe:\n\n```ruby\nnode.default['yum']['epel-testing']['enabled'] = true\nnode.default['yum']['epel-testing']['managed'] = true\ninclude_recipe 'yum-epel'\n```\n\n## More Examples\n\nPoint the epel repositories at an internally hosted server.\n\n```ruby\nnode.default['yum']['epel']['enabled'] = true\nnode.default['yum']['epel']['mirrorlist'] = nil\nnode.default['yum']['epel']['baseurl'] = 'https://internal.example.com/centos/6/os/x86_64'\nnode.default['yum']['epel']['sslverify'] = false\n\ninclude_recipe 'yum-epel'\n```\n\n## License & Authors\n\n**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io))\n\n**Copyright:** 2011-2016, Chef Software, Inc.\n\n```\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"amazon":">= 0.0.0","centos":">= 0.0.0","oracle":">= 0.0.0","redhat":">= 0.0.0","scientific":">= 0.0.0","zlinux":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/chef-cookbooks/yum-epel","issues_url":"https://github.com/chef-cookbooks/yum-epel/issues","chef_version":[[">= 12.14"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/yum-epel/recipes/default.rb b/cookbooks/yum-epel/recipes/default.rb new file mode 100644 index 0000000..4ac475c --- /dev/null +++ b/cookbooks/yum-epel/recipes/default.rb @@ -0,0 +1,27 @@ +# +# Author:: Sean OMeara () +# Cookbook:: yum-epel +# Recipe:: default +# +# Copyright:: 2013-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +node['yum-epel']['repos'].each do |repo| + next unless node['yum'][repo]['managed'] + yum_repository repo do + node['yum'][repo].each do |config, value| + send(config.to_sym, value) unless value.nil? || config == 'managed' + end + end +end diff --git a/cookbooks/yum/.foodcritic b/cookbooks/yum/.foodcritic new file mode 100644 index 0000000..b9f8767 --- /dev/null +++ b/cookbooks/yum/.foodcritic @@ -0,0 +1 @@ +~FC016 diff --git a/cookbooks/yum/CHANGELOG.md b/cookbooks/yum/CHANGELOG.md new file mode 100644 index 0000000..c7dcf30 --- /dev/null +++ b/cookbooks/yum/CHANGELOG.md @@ -0,0 +1,356 @@ +# yum Cookbook CHANGELOG + +This file is used to list changes made in each version of the yum cookbook. + +## 5.1.0 (2017-08-04) + +- Avoid spec deprecation warnings +- Use an empty string `releasever` to lock an Amazon Linux AMI to its current verison + +## 5.0.1 (2017-04-06) + +- Switch from Rake testing to Local Delivery +- Rename kitchen-docker to kitchen-dokken +- Update apache2 license string +- use true/false vs. TrueClass and FalseClass in the resource + +## 5.0.0 (2017-02-12) + +### Breaking changes + +- Removed the yum_repository resource and instead require chef-client 12.14 or later, which has the yum repository functionality built in. This resolves Chef 13 compatibility warnings for any cookbook with the yum cookbook. + +### Other changes + +- Convert yum_globalconfig from an LWRP to a custom resource + +## 4.2.0 (2017-02-12) + +- Make cache in the DNF compat recipe +- Fix `fastestmirror_enabled`. +- Require Chef 12.1 not 12.0 +- Convert to Inspec + +## 4.1.0 (2016-10-21) + +- Purge yum cache before removing a repo not after + +## 4.0.0 (2016-09-06) + +- Remove support for Chef 11 + +## 3.13.0 (2016-09-06) + +- Add deprecation warning for add/remove actions, which were replaced with create/delete in Yum 3.0 +- Remove support for Chef 10 + +## v3.12.0 (2016-08-25) + +- Fixing baseurl to support multiple urls +- Modify releasever attribute for Amazon to match Amazon's default policy for releasever + +## v3.11.0 (2016-06-01) + +- Install yum at compile time in the dnf compatibility recipe +- Add IBM zlinux as a supported platform in the metadata +- Use cookstyle instead of rubocop to provide a consistent linting experience + +## v3.10.0 (2016-02-04) + +- Add a new sensitive attribute to the repository resource so prevent writing the diff of the config to Chef output / logs +- Update testing dependencies and remove the Guardfile / Guard dependencies + +## v3.9.0 (2016-01-14) + +- Added dnf_yum_compat recipe to ensure yum is installed on Fedora systems for Chef package resource compatibility. This will no longer be necessary when native dnf package support ships in chef-client. + +## v3.8.2 (2015-10-28) + +- # 141 - Replace clean_headers with clean_metadata + +## v3.8.1 (2015-10-28) + +- Fixing up Chef13 deprecation warnings + +## v3.8.0 (2015-10-13) + +- adding clean_headers boolean property to yum_resource +- restoring Chef 10 backwards compat for the sake of ChefSpec +- (unique resource names needed to avoid cloning) +- Fixing localpkg_gpgcheck values + +## v3.7.1 (2015-09-08) + +- # 135 - reverting "yum clean headers" as it breaks dnf compat + +## v3.7.0 (2015-09-05) + +- Adding deltarpm toggle +- Cleaning 'headers' rather than 'all' + +## v3.6.3 (2015-07-13) + +- Normalizing sslverify option rendering behavior +- Setting default value on the resource to nil +- Explictly setting string to render in template if value is supplied +- Behavior should default to "True", per man page + +## v3.6.2 (2015-07-13) + +- Adding -y to makecache, to import key when repo_gpgcheck = true. +- Accepting Integer value for max_retries + +## v3.6.1 (2015-06-04) + +- Executing yum clean before makecache +- Adding repo_gpgcheck + +## v3.6.0 (2015-04-23) + +- Adding "yum clean" before "yum makecache" in yum_repository :create +- Adding why_run support to yum_globalconfig + +## v3.5.4 (2015-04-07) + +- Changing tolerant config line to stringified integer + +## v3.5.3 (2015-01-16) + +- Adding reposdir to globalconfig template + +## v3.5.2 (2014-12-24) + +- Fixing redhat-release detection for Redhat 7 + +## v3.5.1 (2014-11-24) + +- Reverting management of ca-certificates because EL5 was broken + +## v3.5.0 (2014-11-24) + +- Adding management of ca-certificates package to yum_repository provider + +## v3.4.1 (2014-10-29) + +- Run yum-makecache only_if new_resource.enabled +- Allow setting of reposdir in global yum config and man page +- Change default 'obsoletes' behavior to match yum defaults + +## v3.4.0 (2014-10-15) + +- Dynamically generate the new_resource attributes + +## v3.3.2 (2014-09-11) + +- Fix globalconfig resource param for http_caching + +## v3.3.1 (2014-09-04) + +- Fix issue with sslverify if set to false +- Add fancy badges + +## v3.3.0 (2014-09-03) + +- Adding tuning attributes for all supported resource parameters +- Adding options hash parameter +- Adding (real) rhel-6.5 and centos-7.0 to test-kitchen coverage +- Updating regex for mirror_expire and mirrorlist_expire to include /^\d+[mhd]$/ +- Updating README so keepcache reflects reality (defaults to false) +- Changing 'obsoletes' behavior in globalconfig resource to match +- default behavior. (now defaults to nil, yum defaults to false) +- Adding makecache action to repository resource +- Adding mode parameter to repository resource. Defaults to '0644'. + +## v3.2.4 (2014-08-20) + +- # 82 - Adding a makecache parameter + +## v3.2.2 (2014-06-11) + +- # 77 - Parameter default to be Trueclass instead of "1" + +- # 78 - add releasever parameter + +## v3.2.0 (2014-04-09) + +- [COOK-4510] - Adding username and password parameters to node attributes +- [COOK-4518] - Fix Scientific Linux distroverpkg + +## v3.1.6 (2014-03-27) + +- [COOK-4463] - support multiple GPG keys +- [COOK-4364] - yum_repository delete action fails + +## v3.1.4 (2014-03-12) + +- [COOK-4417] Expand test harness to encompass 32-bit boxes + +## v3.1.2 (2014-02-23) + +Fixing bugs around :delete action and cache clean Fixing specs to cover :remove and :delete aliasing properly Adding Travis-ci build matrix bits + +## v3.1.0 (2014-02-13) + +- Updating testing harness for integration testing on Travis-ci +- Adding TESTING.md and Guardfile +- PR #67 - Add skip_if_unvailable repository option +- PR #64 - Fix validation of 'metadata_expire' option to match documentation +- [COOK-3591] - removing node.name from repo template rendering +- [COOK-4275] - Enhancements to yum cookbook +- Adding full spec coverage +- Adding support for custom source template to yum_repository + +## v3.0.8 (2014-01-27) + +Fixing typo in default.rb. yum_globalconfig now passes proxy attribute correctly. + +## v3.0.6 (2014-01-27) + +Updating default.rb to consume node['yum']['main']['proxy'] + +## v3.0.4 (2013-12-29) + +### Bug + +- **[COOK-4156](https://tickets.chef.io/browse/COOK-4156)** - yum cookbook creates a yum.conf with "cachefir" directive + +## v3.0.2 + +Updating globalconfig provider for Chef 10 compatability + +## v3.0.0 + +3.0.0 Major rewrite with breaking changes. Recipes broken out into individual cookbooks yum_key resource has been removed yum_repository resource now takes gpgkey as a URL directly yum_repository actions have been reduced to :create and :delete 'name' has been changed to repositoryid to avoid ambiguity chefspec test coverage gpgcheck is set to 'true' by default and must be explicitly disabled + +## v2.4.4 + +Reverting to Ruby 1.8 hash syntax. + +## v2.4.2 + +[COOK-3275] LWRP repository.rb :add method fails to create yum repo in some cases which causes :update to fail Amazon rhel + +## v2.4.0 + +### Improvement + +- [COOK-3025] - Allow per-repo proxy definitions + +## v2.3.4 + +### Improvement + +- **[COOK-3689](https://tickets.chef.io/browse/COOK-3689)** - Fix warnings about resource cloning +- **[COOK-3574](https://tickets.chef.io/browse/COOK-3574)** - Add missing "description" field in metadata + +## v2.3.2 + +### Bug + +- **[COOK-3145](https://tickets.chef.io/browse/COOK-3145)** - Use correct download URL for epel `key_url` + +## v2.3.0 + +### New Feature + +- [COOK-2924]: Yum should allow type setting in repo file + +## v2.2.4 + +### Bug + +- [COOK-2360]: last commit to `yum_repository` changes previous behaviour +- [COOK-3015]: Yum cookbook test minitest to fail + +## v2.2.2 + +### Improvement + +- [COOK-2741]: yum::elrepo +- [COOK-2946]: update tests, test kitchen support in yum cookbook + +### Bug + +- [COOK-2639]: Yum cookbook - epel - always assumes url is a mirror list +- [COOK-2663]: Yum should allow metadata_expire setting in repo file +- [COOK-2751]: Update yum.ius_release version to 1.0-11 + +## v2.2.0 + +- [COOK-2189] - yum::ius failed on install (caused from rpm dependency) +- [COOK-2196] - Make includepkgs and exclude configurable for each repos +- [COOK-2244] - Allow configuring caching using attributes +- [COOK-2399] - yum cookbook LWRPs fail FoodCritic +- [COOK-2519] - Add priority option to Yum repo files +- [COOK-2593] - allow integer or string for yum priority +- [COOK-2643] - don't use conditional attribute for `yum_key` `remote_file` + +## v2.1.0 + +- [COOK-2045] - add remi repository recipe +- [COOK-2121] - add `:create` action to `yum_repository` + +## v2.0.6 + +- [COOK-2037] - minor style fixes +- [COOK-2038] - updated README + +## v2.0.4 + +- [COOK-1908] - unable to install repoforge on CentOS 6 32 bit + +## v2.0.2 + +- [COOK-1758] - Add default action for repository resource + +## v2.0.0 + +This version changes the behavior of the EPEL recipe (most commonly used in other Chef cookbooks) on Amazon, and removes an attribute, `node['yum']['epel_release']`. See the README for details. + +- [COOK-1772] - Simplify management of EPEL with LWRP + +## v1.0.0 + +`mirrorlist` in the `yum_repository` LWRP must be set to the mirror list URI to use rather than setting it to true. See README.md. + +- [COOK-1088] - use dl.fedoraproject.org for EPEL to prevent redirects +- [COOK-1653] - fix mirrorlist +- [COOK-1710] - support http proxy +- [COOK-1722] - update IUS version + +## v0.8.2 + +- [COOK-1521] - add :update action to `yum_repository` + +## v0.8.0 + +- [COOK-1204] - Make 'add' default action for yum_repository +- [COOK-1351] - option to not make the yum cache (via attribute) +- [COOK-1353] - x86_64 centos path fixes +- [COOK-1414] - recipe for repoforge + +## v0.6.2 + +- Updated README to remove git diff artifacts. + +## v0.6.0 + +- Default action for the yum_repository LWRP is now add. +- [COOK-1227] - clear Chefs internal cache after adding new yum repo +- [COOK-1262] - yum::epel should enable existing repo on Amazon Linux +- [COOK-1272], [COOK-1302] - update RPM file for CentOS / RHEL 6 +- [COOK-1330] - update cookbook documentation on excludes for yum +- [COOK-1346] - retry remote_file for EPEL in case we get an FTP mirror + +## v0.5.2 + +- [COOK-825] - epel and ius `remote_file` should notify the `rpm_package` to install + +## v0.5.0 + +- [COOK-675] - add recipe for handling EPEL repository +- [COOK-722] - add recipe for handling IUS repository + +## v.0.1.2 + +- Remove yum update in default recipe, that doesn't update caches, it updates packages installed. diff --git a/cookbooks/yum/CONTRIBUTING.md b/cookbooks/yum/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/yum/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/cookbooks/yum/README.md b/cookbooks/yum/README.md new file mode 100644 index 0000000..1c00047 --- /dev/null +++ b/cookbooks/yum/README.md @@ -0,0 +1,131 @@ +# yum Cookbook + +[![Build Status](https://travis-ci.org/chef-cookbooks/yum.svg?branch=master)](http://travis-ci.org/chef-cookbooks/yum) [![Cookbook Version](https://img.shields.io/cookbook/v/yum.svg)](https://supermarket.chef.io/cookbooks/yum) + +The Yum cookbook exposes the `yum_globalconfig` resource which allows a user to control global yum behavior. This resources aims to allow the user to configure all options listed in the `yum.conf` man page, found at + +## Requirements + +### Platforms + +- RHEL/CentOS and derivatives +- Fedora + +### Chef + +- Chef 12.14+ + +### Cookbooks + +- none + +## Resources + +### yum_globalconfig + +This renders a template with global yum configuration parameters. The default recipe uses it to render `/etc/yum.conf`. It is flexible enough to be used in other scenarios, such as building RPMs in isolation by modifying `installroot`. + +#### Example + +```ruby +yum_globalconfig '/my/chroot/etc/yum.conf' do + cachedir '/my/chroot/etc/yum.conf' + keepcache 'yes' + debuglevel '2' + installroot '/my/chroot' + action :create +end +``` + +#### Properties + +`yum_globalconfig` can take most of the same parameters as a `yum_repository`, plus more, too numerous to describe here. Below are a few of the more commonly used ones. For a complete list, please consult the `yum.conf` man page, found here: + +- `cachedir` - Directory where yum should store its cache and db files. The default is '/var/cache/yum'. +- `keepcache` - Either `true` or `false`. Determines whether or not yum keeps the cache of headers and packages after successful installation. Default is `false` +- `debuglevel` - Debug message output level. Practical range is 0-10\. Default is '2'. +- `exclude` - List of packages to exclude from updates or installs. This should be a space separated list. Shell globs using wildcards (eg. * and ?) are allowed. +- `installonlypkgs` = List of package provides that should only ever be installed, never updated. Kernels in particular fall into this category. Defaults to kernel, kernel-bigmem, kernel-enterprise, kernel-smp, kernel-debug, kernel-unsupported, kernel-source, kernel-devel, kernel-PAE, kernel-PAE-debug. +- `logfile` - Full directory and file name for where yum should write its log file. +- `exactarch` - Either `true` or `false`. Set to `true` to make 'yum update' only update the architectures of packages that you have installed. ie: with this enabled yum will not install an i686 package to update an x86_64 package. Default is `true` +- `gpgcheck` - Either `true` or `false`. This tells yum whether or not it should perform a GPG signature check on the packages gotten from this repository. + +### yum_repository + +This resource is now provided by chef-client 12.14 and later and has been removed from this cookbook. If you require this resource we highly recommend upgrading your chef-client, but if that is not an option you can pin the 4.X yum cookbook. + +## Recipes + +- `default` - Configures `yum_globalconfig[/etc/yum.conf]` with values found in node attributes at `node['yum']['main']` +- `dnf_yum_compat` - Installs the yum package using dnf on Fedora systems to provide support for the package resource in recipes. This is necessary on chef-client < 12.18\. This recipe should be 1st on a Fedora runlist + +## Attributes + +The following attributes are set by default + +```ruby +default['yum']['main']['cachedir'] = '/var/cache/yum/$basearch/$releasever' +default['yum']['main']['keepcache'] = false +default['yum']['main']['debuglevel'] = nil +default['yum']['main']['exclude'] = nil +default['yum']['main']['logfile'] = '/var/log/yum.log' +default['yum']['main']['exactarch'] = nil +default['yum']['main']['obsoletes'] = nil +default['yum']['main']['installonly_limit'] = nil +default['yum']['main']['installonlypkgs'] = nil +default['yum']['main']['installroot'] = nil +``` + +For Amazon platform nodes, the default is to receive a continuous flow of updates, + +```ruby +default['yum']['main']['releasever'] = 'latest' +``` + +To lock existing instances to the current version of the Amazon AMI, + +```ruby +default['yum']['main']['releasever'] = '' +``` + +## Related Cookbooks + +Recipes from older versions of this cookbook have been moved individual cookbooks. Recipes for managing platform yum configurations and installing specific repositories can be found in one (or more!) of the following cookbook. + +- yum-centos +- yum-fedora +- yum-amazon +- yum-epel +- yum-elrepo +- yum-repoforge +- yum-ius +- yum-percona +- yum-pgdg + +## Usage + +Put `depends 'yum'` in your metadata.rb to gain access to the yum_repository resource. + +## License & Authors + +- Author:: Eric G. Wolfe +- Author:: Matt Ray ([matt@chef.io](mailto:matt@chef.io)) +- Author:: Joshua Timberman ([joshua@chef.io](mailto:joshua@chef.io)) +- Author:: Sean OMeara ([someara@chef.io](mailto:someara@chef.io)) + +```text +Copyright:: 2011 Eric G. Wolfe +Copyright:: 2013-2017 Chef Software, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/cookbooks/yum/attributes/main.rb b/cookbooks/yum/attributes/main.rb new file mode 100644 index 0000000..5ac4af7 --- /dev/null +++ b/cookbooks/yum/attributes/main.rb @@ -0,0 +1,103 @@ +# http://linux.die.net/man/5/yum.conf +default['yum']['main']['cachedir'] = case node['platform_version'].to_i + when 5 + '/var/cache/yum' + else + '/var/cache/yum/$basearch/$releasever' + end + +default['yum']['main']['distroverpkg'] = case node['platform'] + when 'amazon' + 'system-release' + when 'scientific' + 'sl-release' + when 'redhat' + nil + else + "#{node['platform']}-release" + end +# default["yum"]["main"]["releasever"] = nil # /.*/ +default['yum']['main']['releasever'] = case node['platform'] + when 'amazon' + 'latest' + end +default['yum']['main']['alwaysprompt'] = nil # [true, false] +default['yum']['main']['assumeyes'] = nil # [true, false] +default['yum']['main']['bandwidth'] = nil # /^\d+$/ +default['yum']['main']['bugtracker_url'] = nil # /.*/ +default['yum']['main']['clean_requirements_on_remove'] = nil # [true, false] +default['yum']['main']['color'] = nil # %w{ always never } +default['yum']['main']['color_list_available_downgrade'] = nil # /.*/ +default['yum']['main']['color_list_available_install'] = nil # /.*/ +default['yum']['main']['color_list_available_reinstall'] = nil # /.*/ +default['yum']['main']['color_list_available_upgrade'] = nil # /.*/ +default['yum']['main']['color_list_installed_extra'] = nil # /.*/ +default['yum']['main']['color_list_installed_newer'] = nil # /.*/ +default['yum']['main']['color_list_installed_older'] = nil # /.*/ +default['yum']['main']['color_list_installed_reinstall'] = nil # /.*/ +default['yum']['main']['color_search_match'] = nil # /.*/ +default['yum']['main']['color_update_installed'] = nil # /.*/ +default['yum']['main']['color_update_local'] = nil # /.*/ +default['yum']['main']['color_update_remote'] = nil # /.*/ +default['yum']['main']['commands'] = nil # /.*/ +default['yum']['main']['deltarpm'] = nil # [true, false] +default['yum']['main']['debuglevel'] = nil # /^\d+$/ +default['yum']['main']['diskspacecheck'] = nil # [true, false] +default['yum']['main']['enable_group_conditionals'] = nil # [true, false] +default['yum']['main']['errorlevel'] = nil # /^\d+$/ +default['yum']['main']['exactarch'] = nil # [true, false] +default['yum']['main']['exclude'] = nil # /.*/ +default['yum']['main']['gpgcheck'] = true # [true, false] +default['yum']['main']['group_package_types'] = nil # /.*/ +default['yum']['main']['groupremove_leaf_only'] = nil # [true, false] +default['yum']['main']['history_list_view'] = nil # /.*/ +default['yum']['main']['history_record'] = nil # [true, false] +default['yum']['main']['history_record_packages'] = nil # /.*/ +default['yum']['main']['http_caching'] = nil # %w{ packages all none } +default['yum']['main']['installonly_limit'] = nil # /\d+/, /keep/ +default['yum']['main']['installonlypkgs'] = nil # /.*/ +default['yum']['main']['installroot'] = nil # /.*/ +default['yum']['main']['keepalive'] = nil # [true, false] +default['yum']['main']['keepcache'] = false # [true, false] +default['yum']['main']['kernelpkgnames'] = nil # /.*/ +default['yum']['main']['localpkg_gpgcheck'] = false # [true,# false] +default['yum']['main']['logfile'] = '/var/log/yum.log' # /.*/ +default['yum']['main']['max_retries'] = nil # /^\d+$/ +default['yum']['main']['mdpolicy'] = nil # %w{ packages all none } +default['yum']['main']['metadata_expire'] = nil # /^\d+$/ +default['yum']['main']['mirrorlist_expire'] = nil # /^\d+$/ +default['yum']['main']['multilib_policy'] = nil # %w{ all best } +default['yum']['main']['obsoletes'] = nil # [true, false] +default['yum']['main']['overwrite_groups'] = nil # [true, false] +default['yum']['main']['password'] = nil # /.*/ +default['yum']['main']['path'] = '/etc/yum.conf' # /.*/ +default['yum']['main']['persistdir'] = nil # /.*/ +default['yum']['main']['pluginconfpath'] = nil # /.*/ +default['yum']['main']['pluginpath'] = nil # /.*/ +default['yum']['main']['plugins'] = nil # [true, false] +default['yum']['main']['protected_multilib'] = nil # /.*/ +default['yum']['main']['protected_packages'] = nil # /.*/ +default['yum']['main']['proxy'] = nil # /.*/ +default['yum']['main']['proxy_password'] = nil # /.*/ +default['yum']['main']['proxy_username'] = nil # /.*/ +default['yum']['main']['password'] = nil # /.*/ +default['yum']['main']['recent'] = nil # /^\d+$/ +default['yum']['main']['repo_gpgcheck'] = nil # [true, false] +default['yum']['main']['reposdir'] = nil # /.*/ +default['yum']['main']['reset_nice'] = nil # [true, false] +default['yum']['main']['rpmverbosity'] = nil # %w{ info critical# emergency error warn debug } +default['yum']['main']['showdupesfromrepos'] = nil # [true, false] +default['yum']['main']['skip_broken'] = nil # [true, false] +default['yum']['main']['ssl_check_cert_permissions'] = nil # [true, false] +default['yum']['main']['sslcacert'] = nil # /.*/ +default['yum']['main']['sslclientcert'] = nil # /.*/ +default['yum']['main']['sslclientkey'] = nil # /.*/ +default['yum']['main']['sslverify'] = nil # [true, false] +default['yum']['main']['syslog_device'] = nil # /.*/ +default['yum']['main']['syslog_facility'] = nil # /.*/ +default['yum']['main']['syslog_ident'] = nil # /.*/ +default['yum']['main']['throttle'] = nil # [/\d+k/, /\d+M/, /\d+G/] +default['yum']['main']['timeout'] = nil # /\d+/ +default['yum']['main']['tolerant'] = false +default['yum']['main']['tsflags'] = nil # /.*/ +default['yum']['main']['username'] = nil # /.*/ diff --git a/cookbooks/yum/libraries/matchers.rb b/cookbooks/yum/libraries/matchers.rb new file mode 100644 index 0000000..220238a --- /dev/null +++ b/cookbooks/yum/libraries/matchers.rb @@ -0,0 +1,9 @@ +if defined?(ChefSpec) + def create_yum_globalconfig(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:yum_globalconfig, :create, resource_name) + end + + def delete_yum_globalconfig(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:yum_globalconfig, :delete, resource_name) + end +end diff --git a/cookbooks/yum/metadata.json b/cookbooks/yum/metadata.json new file mode 100644 index 0000000..44a7f68 --- /dev/null +++ b/cookbooks/yum/metadata.json @@ -0,0 +1 @@ +{"name":"yum","version":"5.1.0","description":"Configures various yum components on Red Hat-like systems","long_description":"","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"amazon":">= 0.0.0","centos":">= 0.0.0","fedora":">= 0.0.0","oracle":">= 0.0.0","redhat":">= 0.0.0","scientific":">= 0.0.0","zlinux":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/chef-cookbooks/yum","issues_url":"https://github.com/chef-cookbooks/yum/issues","chef_version":[[">= 12.14"]],"ohai_version":[]} \ No newline at end of file diff --git a/cookbooks/yum/recipes/default.rb b/cookbooks/yum/recipes/default.rb new file mode 100644 index 0000000..e489fb2 --- /dev/null +++ b/cookbooks/yum/recipes/default.rb @@ -0,0 +1,26 @@ +# +# Author:: Sean OMeara () +# Author:: Joshua Timberman () +# Recipe:: yum::default +# +# Copyright:: 2013-2017, Chef Software, Inc () +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +yum_globalconfig '/etc/yum.conf' do + node['yum']['main'].each do |config, value| + send(config.to_sym, value) unless value.nil? + end + + action :create +end diff --git a/cookbooks/yum/recipes/dnf_yum_compat.rb b/cookbooks/yum/recipes/dnf_yum_compat.rb new file mode 100644 index 0000000..d88fecf --- /dev/null +++ b/cookbooks/yum/recipes/dnf_yum_compat.rb @@ -0,0 +1,29 @@ +# +# Author:: Tim Smith () +# Recipe:: yum::fedora_yum_compat +# +# Copyright:: 2015-2017, Chef Software, Inc () +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +execute 'make yum cache' do + command 'yum makecache' + action :nothing +end + +execute 'install yum' do + command 'dnf install yum -y' + not_if { ::File.exist?('/var/lib/yum') } + action :nothing + notifies :run, 'execute[make yum cache]', :immediately +end.run_action(:run) diff --git a/cookbooks/yum/resources/globalconfig.rb b/cookbooks/yum/resources/globalconfig.rb new file mode 100644 index 0000000..d294767 --- /dev/null +++ b/cookbooks/yum/resources/globalconfig.rb @@ -0,0 +1,119 @@ +# +# Cookbook:: yum +# Resource:: repository +# +# Author:: Sean OMeara +# Copyright:: 2013-2017, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# http://linux.die.net/man/5/yum.conf +property :alwaysprompt, [true, false] +property :assumeyes, [true, false] +property :bandwidth, String, regex: /^\d+/ +property :bugtracker_url, String, regex: /.*/ +property :clean_requirements_on_remove, [true, false] +property :cachedir, String, regex: /.*/, default: '/var/cache/yum/$basearch/$releasever' +property :color, String, equal_to: %w(always never) +property :color_list_available_downgrade, String, regex: /.*/ +property :color_list_available_install, String, regex: /.*/ +property :color_list_available_reinstall, String, regex: /.*/ +property :color_list_available_upgrade, String, regex: /.*/ +property :color_list_installed_extra, String, regex: /.*/ +property :color_list_installed_newer, String, regex: /.*/ +property :color_list_installed_older, String, regex: /.*/ +property :color_list_installed_reinstall, String, regex: /.*/ +property :color_search_match, String, regex: /.*/ +property :color_update_installed, String, regex: /.*/ +property :color_update_local, String, regex: /.*/ +property :color_update_remote, String, regex: /.*/ +property :commands, String, regex: /.*/ +property :debuglevel, String, regex: /^\d+$/, default: '2' +property :deltarpm, [true, false] +property :diskspacecheck, [true, false] +property :distroverpkg, String, regex: /.*/ +property :enable_group_conditionals, [true, false] +property :errorlevel, String, regex: /^\d+$/ +property :exactarch, [true, false], default: true +property :exclude, String, regex: /.*/ +property :gpgcheck, [true, false], default: true +property :group_package_types, String, regex: /.*/ +property :groupremove_leaf_only, [true, false] +property :history_list_view, String, equal_to: %w(users commands single-user-commands) +property :history_record, [true, false] +property :history_record_packages, String, regex: /.*/ +property :http_caching, String, equal_to: %w(packages all none) +property :installonly_limit, String, regex: [/^\d+/, /keep/], default: '3' +property :installonlypkgs, String, regex: /.*/ +property :installroot, String, regex: /.*/ +property :keepalive, [true, false] +property :keepcache, [true, false], default: false +property :kernelpkgnames, String, regex: /.*/ +property :localpkg_gpgcheck, [true, false] +property :logfile, String, regex: /.*/, default: '/var/log/yum.log' +property :max_retries, String, regex: /^\d+$/ +property :mdpolicy, String, equal_to: %w(instant group:primary group:small group:main group:all) +property :metadata_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/, /never/] +property :mirrorlist_expire, String, regex: /^\d+$/ +property :multilib_policy, String, equal_to: %w(all best) +property :obsoletes, [true, false] +property :overwrite_groups, [true, false] +property :password, String, regex: /.*/ +property :path, String, regex: /.*/, name_property: true +property :persistdir, String, regex: /.*/ +property :pluginconfpath, String, regex: /.*/ +property :pluginpath, String, regex: /.*/ +property :plugins, [true, false], default: true +property :protected_multilib, [true, false] +property :protected_packages, String, regex: /.*/ +property :proxy, String, regex: /.*/ +property :proxy_password, String, regex: /.*/ +property :proxy_username, String, regex: /.*/ +property :recent, String, regex: /^\d+$/ +property :releasever, String, regex: /.*/ +property :repo_gpgcheck, [true, false] +property :reposdir, String, regex: /.*/ +property :reset_nice, [true, false] +property :rpmverbosity, String, equal_to: %w(info critical emergency error warn debug) +property :showdupesfromrepos, [true, false] +property :skip_broken, [true, false] +property :ssl_check_cert_permissions, [true, false] +property :sslcacert, String, regex: /.*/ +property :sslclientcert, String, regex: /.*/ +property :sslclientkey, String, regex: /.*/ +property :sslverify, [true, false] +property :syslog_device, String, regex: /.*/ +property :syslog_facility, String, regex: /.*/ +property :syslog_ident, String, regex: /.*/ +property :throttle, String, regex: [/\d+k/, /\d+M/, /\d+G/] +property :timeout, String, regex: /^\d+$/ +property :tolerant, [true, false] +property :tsflags, String, regex: /.*/ +property :username, String, regex: /.*/ +property :options, Hash + +action :create do + template new_resource.path do + source 'main.erb' + cookbook 'yum' + mode '0644' + variables(config: new_resource) + end +end + +action :delete do + file new_resource.path do + action :delete + end +end diff --git a/cookbooks/yum/templates/main.erb b/cookbooks/yum/templates/main.erb new file mode 100644 index 0000000..19e6710 --- /dev/null +++ b/cookbooks/yum/templates/main.erb @@ -0,0 +1,276 @@ +# This file was generated by Chef +# Do NOT modify this file by hand. + +[main] +<% if @config.alwaysprompt %> +alwaysprompt=<%= @config.alwaysprompt %> +<% end %> +<% if @config.assumeyes %> +assumeyes=<%= @config.assumeyes %> +<% end %> +<% if @config.bandwidth %> +bandwidth=<%= @config.bandwidth %> +<% end %> +<% if @config.bugtracker_url %> +bugtracker_url=<%= @config.bugtracker_url %> +<% end %> +<% if @config.cachedir %> +cachedir=<%= @config.cachedir %> +<% end %> +<% if @config.clean_requirements_on_remove %> +clean_requirements_on_remove=<%= @config.clean_requirements_on_remove %> +<% end %> +<% if @config.color %> +color=<%= @config.color %> +<% end %> +<% if @config.color_list_available_downgrade %> +color_list_available_downgrade=<%= @config.color_list_available_downgrade %> +<% end %> +<% if @config.color_list_available_install %> +color_list_available_install=<%= @config.color_list_available_install %> +<% end %> +<% if @config.color_list_available_reinstall %> +color_list_available_reinstall=<%= @config.color_list_available_reinstall %> +<% end %> +<% if @config.color_list_available_upgrade %> +color_list_available_upgrade=<%= @config.color_list_available_upgrade %> +<% end %> +<% if @config.color_list_installed_extra %> +color_list_installed_extra=<%= @config.color_list_installed_extra %> +<% end %> +<% if @config.color_list_installed_newer %> +color_list_installed_newer=<%= @config.color_list_installed_newer %> +<% end %> +<% if @config.color_list_installed_older %> +color_list_installed_older=<%= @config.color_list_installed_older %> +<% end %> +<% if @config.color_list_installed_reinstall %> +color_list_installed_reinstall=<%= @config.color_list_installed_reinstall %> +<% end %> +<% if @config.color_search_match %> +color_search_match=<%= @config.color_search_match %> +<% end %> +<% if @config.color_update_installed %> +color_update_installed=<%= @config.color_update_installed %> +<% end %> +<% if @config.color_update_local %> +color_update_local=<%= @config.color_update_local %> +<% end %> +<% if @config.color_update_remote %> +color_update_remote=<%= @config.color_update_remote %> +<% end %> +<% if @config.commands %> +commands=<%= @config.commands %> +<% end %> +<% if @config.debuglevel %> +debuglevel=<%= @config.debuglevel %> +<% end %> +<% if @config.deltarpm == true %> +deltarpm=1 +<% elsif @config.deltarpm == false %> +deltarpm=0 +<% end %> +<% if @config.diskspacecheck %> +diskspacecheck=<%= @config.diskspacecheck %> +<% end %> +<% if @config.distroverpkg %> +distroverpkg=<%= @config.distroverpkg %> +<% end %> +<% if @config.enable_group_conditionals %> +enable_group_conditionals=1 +<% end %> +<% if @config.errorlevel %> +errorlevel=<%= @config.errorlevel %> +<% end %> +<% if @config.exactarch %> +exactarch=1 +<% else %> +exactarch=0 +<% end %> +<% if @config.exclude %> +exclude=<%= @config.exclude %> +<% end %> +<% if @config.gpgcheck %> +gpgcheck=1 +<% else %> +gpgcheck=0 +<% end %> +<% if @config.group_package_types %> +group_package_types=<%= @config.group_package_types %> +<% end %> +<% if @config.groupremove_leaf_only %> +groupremove_leaf_only=<%= @config.groupremove_leaf_only %> +<% end %> +<% if @config.history_list_view %> +history_list_view=<%= @config.history_list_view %> +<% end %> +<% if @config.history_record %> +history_record=<%= @config.history_record %> +<% end %> +<% if @config.history_record_packages %> +history_record_packages=<%= @config.history_record_packages %> +<% end %> +<% if @config.http_caching %> +http_caching=<%= @config.http_caching %> +<% end %> +<% if @config.installonly_limit %> +installonly_limit=<%= @config.installonly_limit %> +<% end %> +<% if @config.installonlypkgs %> +installonlypkgs=<%= @config.installonlypkgs %> +<% end %> +<% if @config.installroot %> +installroot=<%= @config.installroot %> +<% end %> +<% if @config.keepalive %> +keepalive=<%= @config.keepalive %> +<% end %> +<% if @config.keepcache %> +keepcache=1 +<% else %> +keepcache=0 +<% end %> +<% if @config.kernelpkgnames %> +kernelpkgnames=<%= @config.kernelpkgnames %> +<% end %> +<% if @config.localpkg_gpgcheck %> +localpkg_gpgcheck=1 +<% else %> +localpkg_gpgcheck=0 +<% end %> +<% if @config.logfile %> +logfile=<%= @config.logfile %> +<% end %> +<% if @config.max_retries %> +max_retries=<%= @config.max_retries %> +<% end %> +<% if @config.mdpolicy %> +mdpolicy=<%= @config.mdpolicy %> +<% end %> +<% if @config.metadata_expire %> +metadata_expire=<%= @config.metadata_expire %> +<% end %> +<% if @config.mirrorlist_expire %> +mirrorlist_expire=<%= @config.mirrorlist_expire %> +<% end %> +<% if @config.multilib_policy %> +multilib_policy=<%= @config.multilib_policy %> +<% end %> +<% if @config.obsoletes == false %> +obsoletes=0 +<% else %> +obsoletes=1 +<% end %> +<% if @config.overwrite_groups %> +overwrite_groups=<%= @config.overwrite_groups %> +<% end %> +<% if @config.password %> +password=<%= @config.password %> +<% end %> +<% if @config.persistdir %> +persistdir=<%= @config.persistdir %> +<% end %> +<% if @config.pluginconfpath %> +pluginconfpath=<%= @config.pluginconfpath %> +<% end %> +<% if @config.pluginpath %> +pluginpath=<%= @config.pluginpath %> +<% end %> +<% if @config.plugins %> +plugins=1 +<% else %> +plugins=0 +<% end %> +<% if @config.protected_multilib %> +protected_multilib=<%= @config.protected_multilib %> +<% end %> +<% if @config.protected_packages %> +protected_packages=<%= @config.protected_packages %> +<% end %> +<% if @config.proxy %> +proxy=<%= @config.proxy %> +<% end %> +<% if @config.proxy_password %> +proxy_password=<%= @config.proxy_password %> +<% end %> +<% if @config.proxy_username %> +proxy_username=<%= @config.proxy_username %> +<% end %> +<% if @config.recent %> +recent=<%= @config.recent %> +<% end %> +<% if @config.releasever && @config.releasever.length > 0 %> +releasever=<%= @config.releasever %> +<% end %> +<% if @config.repo_gpgcheck %> +repo_gpgcheck=<%= @config.repo_gpgcheck %> +<% end %> +<% if @config.reposdir %> +reposdir=<%= @config.reposdir %> +<% end %> +<% if @config.reset_nice %> +reset_nice=<%= @config.reset_nice %> +<% end %> +<% if @config.rpmverbosity %> +rpmverbosity=<%= @config.rpmverbosity %> +<% end %> +<% if @config.showdupesfromrepos %> +showdupesfromrepos=<%= @config.showdupesfromrepos %> +<% end %> +<% if @config.skip_broken %> +skip_broken=<%= @config.skip_broken %> +<% end %> +<% if @config.ssl_check_cert_permissions %> +ssl_check_cert_permissions=<%= @config.ssl_check_cert_permissions %> +<% end %> +<% if @config.sslcacert %> +sslcacert=<%= @config.sslcacert %> +<% end %> +<% if @config.sslclientcert %> +sslclientcert=<%= @config.sslclientcert %> +<% end %> +<% if @config.sslclientkey %> +sslclientkey=<%= @config.sslclientkey %> +<% end %> +<% unless @config.sslverify.nil? %> +sslverify=<%= ( @config.sslverify ) ? 'true' : 'false' %> +<% end %> +<% if @config.syslog_device %> +syslog_device=<%= @config.syslog_device %> +<% end %> +<% if @config.syslog_facility %> +syslog_facility=<%= @config.syslog_facility %> +<% end %> +<% if @config.syslog_ident %> +syslog_ident=<%= @config.syslog_ident %> +<% end %> +<% if @config.throttle %> +throttle=<%= @config.throttle %> +<% end %> +<% if @config.timeout %> +timeout=<%= @config.timeout %> +<% end %> +<% if @config.tolerant %> +tolerant=<%= ( @config.tolerant ) ? '1' : '0' %> +<% end %> +<% if @config.tsflags %> +tsflags=<%= @config.tsflags %> +<% end %> +<% if @config.username %> +username=<%= @config.username %> +<% end %> +<% if @config.options -%> +<% @config.options.each do |key, value| -%> +<%= key %>=<%= + case value + when Array + value.join("\n ") + when TrueClass + '1' + when FalseClass + '0' + else + value + end %> +<% end -%> +<% end -%>