diff --git a/Batali b/Batali index 0259f81..e3d7a47 100644 --- a/Batali +++ b/Batali @@ -1,3 +1,5 @@ +# vim: set filetype=ruby + Batali.define do source 'https://supermarket.chef.io' @@ -9,6 +11,7 @@ Batali.define do cookbook 'application_nodejs', git: 'https://github.com/67p/application_nodejs.git', ref: 'master' + cookbook 'application', '4.1.6' cookbook 'users' cookbook 'chef-solo-search' cookbook 'sudo' @@ -26,6 +29,6 @@ Batali.define do cookbook 'omnibus_updater', '~> 1.0.4' cookbook 'timezone-ii' cookbook 'nodejs', '~> 2.4.4' + cookbook 'wordpress' end -# vim: set filetype=ruby diff --git a/batali.manifest b/batali.manifest index 084bab5..95a7660 100644 --- a/batali.manifest +++ b/batali.manifest @@ -25,7 +25,8 @@ "source": { "url": "https://github.com/67P/mediawiki-cookbook.git", "ref": "35e33e3d563987fa7c156def2d26654ecc4cb9a1", - "type": "Batali::Source::Git" + "type": "Batali::Source::Git", + "subdirectory": null } }, { @@ -53,7 +54,7 @@ ], [ "mysql", - ">= 0.0.0" + ">= 6.0.0" ], [ "yum-epel", @@ -68,11 +69,11 @@ ">= 0.0.0" ] ], - "version": "1.5.0", + "version": "1.7.2", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/php/versions/1.5.0/download", - "version": "1.5.0" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/php/versions/1.7.2/download", + "version": "1.7.2" } }, { @@ -99,11 +100,11 @@ ">= 0.0.0" ] ], - "version": "1.2.13", + "version": "2.0.0", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/xml/versions/1.2.13/download", - "version": "1.2.13" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/xml/versions/2.0.0/download", + "version": "2.0.0" } }, { @@ -111,11 +112,11 @@ "dependencies": [ ], - "version": "3.1.0", + "version": "3.3.0", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/chef-sugar/versions/3.1.0/download", - "version": "3.1.0" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/chef-sugar/versions/3.3.0/download", + "version": "3.3.0" } }, { @@ -130,11 +131,11 @@ ">= 0.0.0" ] ], - "version": "6.0.22", + "version": "6.1.2", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/mysql/versions/6.0.22/download", - "version": "6.0.22" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/mysql/versions/6.1.2/download", + "version": "6.1.2" } }, { @@ -142,14 +143,14 @@ "dependencies": [ [ "yum", - ">= 3.0" + ">= 3.2" ] ], - "version": "0.1.17", + "version": "0.1.21", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/yum-mysql-community/versions/0.1.17/download", - "version": "0.1.17" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/yum-mysql-community/versions/0.1.21/download", + "version": "0.1.21" } }, { @@ -157,11 +158,11 @@ "dependencies": [ ], - "version": "3.6.1", + "version": "3.10.0", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/yum/versions/3.6.1/download", - "version": "3.6.1" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/yum/versions/3.10.0/download", + "version": "3.10.0" } }, { @@ -172,11 +173,11 @@ ">= 1.0.1" ] ], - "version": "2.2.7", + "version": "2.2.8", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/smf/versions/2.2.7/download", - "version": "2.2.7" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/smf/versions/2.2.8/download", + "version": "2.2.8" } }, { @@ -196,14 +197,14 @@ "dependencies": [ [ "yum", - "~> 3.0" + "~> 3.2" ] ], - "version": "0.6.0", + "version": "0.6.5", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/yum-epel/versions/0.6.0/download", - "version": "0.6.0" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/yum-epel/versions/0.6.5/download", + "version": "0.6.5" } }, { @@ -214,11 +215,11 @@ ">= 0.0.0" ] ], - "version": "1.36.6", + "version": "1.38.4", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/windows/versions/1.36.6/download", - "version": "1.36.6" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/windows/versions/1.38.4/download", + "version": "1.38.4" } }, { @@ -226,11 +227,11 @@ "dependencies": [ ], - "version": "1.1.9", + "version": "1.3.0", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/chef_handler/versions/1.1.9/download", - "version": "1.1.9" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/chef_handler/versions/1.3.0/download", + "version": "1.3.0" } }, { @@ -241,11 +242,11 @@ ">= 1.34.6" ] ], - "version": "4.1.1", + "version": "4.1.6", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/iis/versions/4.1.1/download", - "version": "4.1.1" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/iis/versions/4.1.6/download", + "version": "4.1.6" } }, { @@ -256,11 +257,11 @@ ">= 1.0.0" ] ], - "version": "4.0.6", + "version": "4.0.9", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/database/versions/4.0.6/download", - "version": "4.0.6" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/database/versions/4.0.9/download", + "version": "4.0.9" } }, { @@ -276,14 +277,14 @@ ], [ "openssl", - "~> 4.0.0" + "~> 4.0" ] ], - "version": "3.4.20", + "version": "4.0.0", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/postgresql/versions/3.4.20/download", - "version": "3.4.20" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/postgresql/versions/4.0.0/download", + "version": "4.0.0" } }, { @@ -291,11 +292,11 @@ "dependencies": [ ], - "version": "2.7.0", + "version": "2.9.2", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/apt/versions/2.7.0/download", - "version": "2.7.0" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/apt/versions/2.9.2/download", + "version": "2.9.2" } }, { @@ -303,14 +304,14 @@ "dependencies": [ [ "chef-sugar", - ">= 0.0.0" + ">= 3.1.1" ] ], - "version": "4.0.0", + "version": "4.4.0", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/openssl/versions/4.0.0/download", - "version": "4.0.0" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/openssl/versions/4.4.0/download", + "version": "4.4.0" } }, { @@ -318,11 +319,11 @@ "dependencies": [ ], - "version": "3.6.2", + "version": "3.7.0", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/postfix/versions/3.6.2/download", - "version": "3.6.2" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/postfix/versions/3.7.0/download", + "version": "3.7.0" } }, { @@ -356,7 +357,8 @@ "source": { "url": "https://github.com/67p/application_nodejs.git", "ref": "54f280eb627866f24901c79c86678e6218d976f0", - "type": "Batali::Source::Git" + "type": "Batali::Source::Git", + "subdirectory": null } }, { @@ -393,35 +395,39 @@ { "name": "ark", "dependencies": [ + [ + "build-essential", + ">= 0.0.0" + ], [ "windows", ">= 0.0.0" ], [ - "7-zip", + "seven_zip", ">= 0.0.0" ] ], - "version": "0.9.0", + "version": "1.0.1", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/ark/versions/0.9.0/download", - "version": "0.9.0" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/ark/versions/1.0.1/download", + "version": "1.0.1" } }, { - "name": "7-zip", + "name": "seven_zip", "dependencies": [ [ "windows", ">= 1.2.2" ] ], - "version": "1.0.2", + "version": "1.0.4", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/7-zip/versions/1.0.2/download", - "version": "1.0.2" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/seven_zip/versions/1.0.4/download", + "version": "1.0.4" } }, { @@ -432,11 +438,38 @@ ">= 2.1.2" ] ], - "version": "1.12.0", + "version": "2.0.5", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/homebrew/versions/1.12.0/download", - "version": "1.12.0" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/homebrew/versions/2.0.5/download", + "version": "2.0.5" + } + }, + { + "name": "poise", + "dependencies": [ + + ], + "version": "2.6.0", + "source": { + "type": "Batali::Source::Site", + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/poise/versions/2.6.0/download", + "version": "2.6.0" + } + }, + { + "name": "poise-service", + "dependencies": [ + [ + "poise", + "~> 2.0" + ] + ], + "version": "1.1.1", + "source": { + "type": "Batali::Source::Site", + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/poise-service/versions/1.1.1/download", + "version": "1.1.1" } }, { @@ -456,11 +489,11 @@ "dependencies": [ ], - "version": "1.8.2", + "version": "2.0.3", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/users/versions/1.8.2/download", - "version": "1.8.2" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/users/versions/2.0.3/download", + "version": "2.0.3" } }, { @@ -480,11 +513,11 @@ "dependencies": [ ], - "version": "2.7.1", + "version": "2.9.0", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/sudo/versions/2.7.1/download", - "version": "2.7.1" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/sudo/versions/2.9.0/download", + "version": "2.9.0" } }, { @@ -526,7 +559,8 @@ "source": { "url": "https://github.com/phlipper/chef-redis.git", "ref": "7476279fc9c8727f082b8d77b5e1922dc2ef437b", - "type": "Batali::Source::Git" + "type": "Batali::Source::Git", + "subdirectory": null } }, { @@ -534,41 +568,29 @@ "dependencies": [ [ "firewall", - ">= 0.9.0" + ">= 2.0" ] ], - "version": "0.7.4", + "version": "1.0.0", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/ufw/versions/0.7.4/download", - "version": "0.7.4" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/ufw/versions/1.0.0/download", + "version": "1.0.0" } }, { "name": "firewall", "dependencies": [ [ - "poise", - "~> 2.0" + "chef-sugar", + ">= 0.0.0" ] ], - "version": "1.2.0", + "version": "2.4.0", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/firewall/versions/1.2.0/download", - "version": "1.2.0" - } - }, - { - "name": "poise", - "dependencies": [ - - ], - "version": "2.0.1", - "source": { - "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/poise/versions/2.0.1/download", - "version": "2.0.1" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/firewall/versions/2.4.0/download", + "version": "2.4.0" } }, { @@ -591,11 +613,11 @@ "dependencies": [ ], - "version": "1.0.8", + "version": "1.0.9", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/partial_search/versions/1.0.8/download", - "version": "1.0.8" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/partial_search/versions/1.0.9/download", + "version": "1.0.9" } }, { @@ -638,14 +660,14 @@ "dependencies": [ [ "rsyslog", - ">= 0.0.0" + "~> 2.0" ] ], - "version": "2.3.1", + "version": "2.4.1", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/bluepill/versions/2.3.1/download", - "version": "2.3.1" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/bluepill/versions/2.4.1/download", + "version": "2.4.1" } }, { @@ -653,11 +675,11 @@ "dependencies": [ ], - "version": "2.0.0", + "version": "2.2.0", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/rsyslog/versions/2.0.0/download", - "version": "2.0.0" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/rsyslog/versions/2.2.0/download", + "version": "2.2.0" } }, { @@ -665,11 +687,11 @@ "dependencies": [ ], - "version": "2.0.1", + "version": "2.1.0", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/ohai/versions/2.0.1/download", - "version": "2.0.1" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/ohai/versions/2.1.0/download", + "version": "2.1.0" } }, { @@ -680,11 +702,11 @@ ">= 0.0.0" ] ], - "version": "1.6.0", + "version": "1.7.6", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/runit/versions/1.6.0/download", - "version": "1.6.0" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/runit/versions/1.7.6/download", + "version": "1.7.6" } }, { @@ -692,11 +714,11 @@ "dependencies": [ ], - "version": "0.0.18", + "version": "0.2.0", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/packagecloud/versions/0.0.18/download", - "version": "0.0.18" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/packagecloud/versions/0.2.0/download", + "version": "0.2.0" } }, { @@ -708,18 +730,18 @@ ], [ "mysql", - ">= 0.0.0" + "~> 6.0" ], [ "mariadb", ">= 0.0.0" ] ], - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/mysql2_chef_gem/versions/1.0.1/download", - "version": "1.0.1" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/mysql2_chef_gem/versions/1.0.2/download", + "version": "1.0.2" } }, { @@ -738,11 +760,11 @@ ">= 0.0.0" ] ], - "version": "0.3.0", + "version": "0.3.1", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/mariadb/versions/0.3.0/download", - "version": "0.3.0" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/mariadb/versions/0.3.1/download", + "version": "0.3.1" } }, { @@ -750,11 +772,11 @@ "dependencies": [ ], - "version": "1.0.4", + "version": "1.0.6", "source": { "type": "Batali::Source::Site", - "url": "https://supermarket.chef.io:443/api/v1/cookbooks/omnibus_updater/versions/1.0.4/download", - "version": "1.0.4" + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/omnibus_updater/versions/1.0.6/download", + "version": "1.0.6" } }, { @@ -768,6 +790,108 @@ "url": "https://supermarket.chef.io:443/api/v1/cookbooks/timezone-ii/versions/0.2.0/download", "version": "0.2.0" } + }, + { + "name": "wordpress", + "dependencies": [ + [ + "php", + ">= 0.0.0" + ], + [ + "openssl", + ">= 0.0.0" + ], + [ + "apache2", + ">= 2.0.0" + ], + [ + "database", + ">= 1.6.0" + ], + [ + "mysql", + ">= 6.0" + ], + [ + "mysql2_chef_gem", + "~> 1.0.1" + ], + [ + "build-essential", + ">= 0.0.0" + ], + [ + "iis", + ">= 1.6.2" + ], + [ + "tar", + ">= 0.3.1" + ], + [ + "nginx", + "~> 2.7.4" + ], + [ + "php-fpm", + "~> 0.6.10" + ], + [ + "selinux", + "~> 0.7" + ] + ], + "version": "3.0.0", + "source": { + "type": "Batali::Source::Site", + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/wordpress/versions/3.0.0/download", + "version": "3.0.0" + } + }, + { + "name": "tar", + "dependencies": [ + + ], + "version": "0.7.0", + "source": { + "type": "Batali::Source::Site", + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/tar/versions/0.7.0/download", + "version": "0.7.0" + } + }, + { + "name": "php-fpm", + "dependencies": [ + [ + "apt", + ">= 0.0.0" + ], + [ + "yum", + ">= 3.0.0" + ] + ], + "version": "0.6.10", + "source": { + "type": "Batali::Source::Site", + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/php-fpm/versions/0.6.10/download", + "version": "0.6.10" + } + }, + { + "name": "selinux", + "dependencies": [ + + ], + "version": "0.9.0", + "source": { + "type": "Batali::Source::Site", + "url": "https://supermarket.chef.io:443/api/v1/cookbooks/selinux/versions/0.9.0/download", + "version": "0.9.0" + } } ] } \ No newline at end of file diff --git a/cookbooks/7-zip/metadata.json b/cookbooks/7-zip/metadata.json deleted file mode 100644 index 98ab32d..0000000 --- a/cookbooks/7-zip/metadata.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "7-zip", - "version": "1.0.2", - "description": "Installs/Configures the 7-zip file archiver", - "long_description": "7-zip Cookbook\n==============\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).\n\n\nRequirements\n------------\n### Platform\n- Windows XP\n- Windows Vista\n- Windows Server 2003 R2\n- Windows 7\n- Windows Server 2008 (R1, R2)\n- Windows 8\n- Windows Server 2012\n\n### Cookbooks\n- windows\n\n\nAttributes\n----------\n- `node['7-zip']['home']` - location to install 7-zip files to. default is `%SYSTEMDRIVE%\\7-zip`\n\n\nUsage\n-----\n### default\nDownloads and installs 7-zip to the location specified by `node['7-zip']['home']`. Also ensures `node['7-zip']['home']` is in the system path.\n\n\nLicense & Authors\n-----------------\n- Author:: Seth Chisamore ()\n\n```text\nCopyright:: 2011, Opscode, 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": "Opscode, Inc.", - "maintainer_email": "cookbooks@opscode.com", - "license": "Apache 2.0", - "platforms": { - "windows": ">= 0.0.0" - }, - "dependencies": { - "windows": ">= 1.2.2" - }, - "recommendations": { - }, - "suggestions": { - }, - "conflicting": { - }, - "providing": { - }, - "replacing": { - }, - "attributes": { - }, - "groupings": { - }, - "recipes": { - } -} \ No newline at end of file diff --git a/cookbooks/apt/.gitignore b/cookbooks/apt/.gitignore deleted file mode 100644 index 7a0d26f..0000000 --- a/cookbooks/apt/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -.vagrant -Berksfile.lock -Gemfile.lock -*~ -*# -.#* -\#*# -.*.sw[a-z] -*.un~ -.bundle -.cache -.kitchen -bin -.kitchen.local.yml -.coverage \ No newline at end of file diff --git a/cookbooks/apt/.kitchen.cloud.yml b/cookbooks/apt/.kitchen.cloud.yml deleted file mode 100644 index 72e2457..0000000 --- a/cookbooks/apt/.kitchen.cloud.yml +++ /dev/null @@ -1,47 +0,0 @@ ---- -driver_config: - digitalocean_client_id: <%= ENV['DIGITAL_OCEAN_CLIENT_ID'] %> - digitalocean_api_key: <%= ENV['DIGITAL_OCEAN_API_KEY'] %> - -provisioner: - name: chef_zero - require_chef_omnibus: latest - -platforms: -- name: ubuntu-1004 - driver_plugin: digitalocean - driver_config: - image_id: 5566812 - flavor_id: 63 - region_id: 4 - ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> - ssh_key: <%= ENV['DIGITAL_OCEAN_SSH_KEY_PATH'] %> - run_list: - - recipe[apt] - -- name: ubuntu-1204 - driver_plugin: digitalocean - driver_config: - image_id: 5588928 - flavor_id: 63 - region_id: 4 - ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> - ssh_key: <%= ENV['DIGITAL_OCEAN_SSH_KEY_PATH'] %> - run_list: - - recipe[apt] - -- name: ubuntu-1404 - driver_plugin: digitalocean - driver_config: - image_id: 5141286 - flavor_id: 63 - region_id: 4 - ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> - ssh_key: <%= ENV['DIGITAL_OCEAN_SSH_KEY_PATH'] %> - run_list: - - recipe[apt] - -suites: - - name: default - run_list: - - recipe[apt] diff --git a/cookbooks/apt/.kitchen.yml b/cookbooks/apt/.kitchen.yml deleted file mode 100644 index 4a60a98..0000000 --- a/cookbooks/apt/.kitchen.yml +++ /dev/null @@ -1,62 +0,0 @@ -driver: - name: vagrant - -platforms: - - name: debian-7.2.0 - run_list: apt::default - # - name: debian-8.0 - # run_list: apt::default - - name: ubuntu-10.04 - run_list: apt::default - - name: ubuntu-12.04 - run_list: apt::default - - name: ubuntu-13.04 - run_list: apt::default - - name: ubuntu-13.10 - run_list: apt::default - - name: ubuntu-14.04 - run_list: apt::default - # driver: - # box: chef/ubuntu-14.04 - -suites: - - name: default - run_list: - - recipe[minitest-handler] - - recipe[apt_test] - - - name: cacher-client - run_list: - - recipe[minitest-handler] - - recipe[apt_test::cacher-client] - - - name: cacher-ng - run_list: - - recipe[minitest-handler] - - recipe[apt_test::cacher-ng] - - - name: cacher-ng-client - run_list: - - recipe[minitest-handler] - - recipe[apt_test::cacher-ng-client] - attributes: - apt: - cacher_dir: '/tmp/apt-cacher' - cacher_port: '9876' - cacher_interface: 'eth0' - compiletime: true - - - name: lwrps - run_list: - - recipe[minitest-handler] - - recipe[apt_test::lwrps] - - - name: unattended-upgrades - run_list: - - recipe[minitest-handler] - - recipe[apt_test::unattended-upgrades] - attributes: - apt: - unattended_upgrades: - enable: true - diff --git a/cookbooks/apt/.rubocop.yml b/cookbooks/apt/.rubocop.yml deleted file mode 100644 index 6c26265..0000000 --- a/cookbooks/apt/.rubocop.yml +++ /dev/null @@ -1,37 +0,0 @@ -AllCops: - Exclude: - - vendor/** - - metadata.rb - - Guardfile - - test/cookbooks/apt_test/metadata.rb - - .kitchen/** - -# Disable ABCSize because it doesn't fit well with resources -AbcSize: - Enabled: false -AssignmentInCondition: - Enabled: false -ClassAndModuleChildren: - Enabled: false -ClassLength: - Enabled: false -CyclomaticComplexity: - Max: 15 -Documentation: - Enabled: false -Encoding: - Enabled: false -FileName: - Enabled: false -HashSyntax: - Enabled: false -LineLength: - Enabled: false -MethodLength: - Enabled: false -ParameterLists: - Enabled: false -# StringLiterals: -# EnforcedStyle: double_quotes -TrailingComma: - Enabled: false diff --git a/cookbooks/apt/.travis.yml b/cookbooks/apt/.travis.yml deleted file mode 100644 index d088058..0000000 --- a/cookbooks/apt/.travis.yml +++ /dev/null @@ -1,44 +0,0 @@ -language: ruby -bundler_args: --without kitchen_vagrant -rvm: -- 2.1.0 -before_install: -- echo -n $DO_KEY_CHUNK_{0..30} >> ~/.ssh/id_do.base64 -- cat ~/.ssh/id_do.base64 | tr -d ' ' | base64 --decode > ~/.ssh/id_do.pem -script: -- bundle exec rake travis --trace -after_script: -- bundle exec kitchen destroy -- cat .kitchen/logs/* -env: - global: - - secure: h2vmDV0AjfSWpUCerHIe9uAR9Od0QDoSRPidEiCjrhNCvaEIz+xFQl3M8eYmHBC31GABdEsiDLHQmj6bPtGOuvceKp37qc9V/h2/oPpPvW2HDjMT6mO6Qx1a5Pv4Xb0PhlUfseZCLDURi/0bM5czxGLH+oqluVEzgrM48m/YWaI= - - secure: fXvnhXK/ckP6EyFvGdYnh0YFwc1q+kF5HYUn3plOn7gytiERo+QwXqsnGtueiqrUzlCnqTWAj1T8wIuiPPmAUr3Ek/LUq1UwVcLYC9Wa2uGeTSooY6k1tzG1mtm+4njpIXxvOZ37NG2TwHLSG15iuJff6dtBE667/r88FjAGxgA= - - secure: NzFG53vCyET7REDbiDBA6AlKwgQtAUnb/2IyCyRwi/Svpf5UWdnqiHD9vepsaLQ+tnJPnCBelP5vM+H7Ln/uWLN39WPz4+36Dry6cWRgTIRG94jCKg3KQJvs6Z+V4bHwRdtvMO5HeAvJUCKRKsIW15odnnPPgPf3OrCHOfQK3Ko= - - secure: 3n0wmPKd+SBBP7prduer7jtIBLAvYP3T0/M+PupH6A8cKNL17kafQO9BwDSfcrRilX0UfOEND2Yq3Au6OfBjmKaFyScUdI5DOT+GWiBcYl9fbmtpz9KG6H8iWG8tIyJQ7vfV6pev8BGDQsmsIBu4SPYTUKUegtvkmmVoeV2je+4= - - secure: yrAlzIzT5sMpJ6VbjSjGLPlMH8LdPNBymaf/5FRxt1n5qLR2GQt9wxaCzGyjhgHo6iAdf3Dw9//YJ8vctnF61XqDOkpc6sW1d8IVZXHPOwb0mr94yQgYWXS/FLk7CFGuELYvKYMLIAXkq/QMOMyro2YLhTD25NblcxTpk5PuJXc= - - secure: 1FMkzei96uga+Fhqb3BK7dIiFj+ItiQhh1vHlotoLecDlDDT0o1YV8jBueLyZiVuFo/n4rKD8zMeCh3g5gfvWGQgZXbxEwMOLixtrW8bnOt/qAGs3qI6H57zXzWU2voUeyWa+ExorBMf1WL1RfIE6S/MlZNJW2OmWKceEaYrsLI= - - secure: ulI/7FdP1JVs61bi7CX3UwmG2v7SzHKfjf3P/wWvbCAO8Z/By/gnHmUn6I0EKsUEA4Gx3kXH8DmVtOZdcYLiNTnWGS38AxPnOfLYa0Lv/h7qqze4MFo5FliNB0iKaq0qn+L/eGYQSlr9e5Opf1Qdp2E47UUFd9VMaCSRKvIpqG4= - - secure: bcfXOTCxjA5Gv2BZWkjO8ukm5Z+t8AZglfvw7VRSqAe4BkyO62WmjONi2qYduB8nAX31IzKMEMOsA8zy9V96B+iAhdc3K5LTaa9VIocaNKoq0lgbLrqw3gW969p1vEbBzSiIn+3bDs7arX1LQ98e9UVt2hBQodSYicRzUuscbSw= - - secure: 2AeqJEMU9QYs40mfX6JppzAMsFJwrtFzYJVwgiN9EGCSqINzEIvnNB2z//nHsMlL6puP0VvapkCYHLDVHi2WHL0fSkkwyyGAfQVR01iM3CSjCl4j9h9Nv6bG78zNItQX64vg9FarTptqrZO/OnaT7dXUfGcAbr8cx9zJRv2fyMw= - - secure: Vx4VZUEF5ptw0lwHtLyMKcBRZwcpApsfAMgj/amqzAhFswjJoafHJ4Ryee+mrg46yXkaXed18xRu7pU/tXLGdp6vuvWFaC/1zCNfsdQBv+BAr46Ig4OB5mE/rwGOiNwbhSj9iHpKGPtUTwOHHqCqP/7ktR1TDIAmB5Esp0QBNFI= - - secure: 0ygYNLFO7ZBI7SH1PBt2ALmwtJfZ9ltCxOARP8ILkgCwLhczolcoT81/kfKigkP75dwYXU9LHiROm2GxFFH9reQdb5X2G3ik6/Xxn6KC1ewIuf8M7+qZx8p//ByazW7OZcvFrfGhsX/LJ5NfAC56Wii88oCUTYEGdM+MIPk8rzQ= - - secure: a0vsypNUkFkdnB2JiI/ZYd+hBfGC2pJt6JovUJr2sglZ0XvU7gyNT3iUmL3I22pM1gh+iAFPtS++OY0OSKRWnEbe7nMDY41soQW9UnfroexBVd+c1sYbJwbLJyTS2I3HxjIikWC2fGhySCX7ryghTQwJddGSh+q9eM0LgbvJ9Tc= - - secure: NUocMJTpGO7PWIMih4kjHGTRvb2vc6ep+fclviipkPzlQ5Ciabco1wW0HQJTX16JINgGVnzwFY16HFylyM74bcZoiSfGsN6E5GAmg5ZRxtpVs2wLHmsrMJxiT3VVMPHkBnZJXBNIcuMw6PAtiAcrOCyNY3Zuig1IuOERt12U2BY= - - secure: oLMuVgRvxDjYCb/hnA3YMJPDAAxyG2a7aUoGQHijSSBxL8VSW7BjfplUViCpWCsQADZgxLGHgfNUETAzHwheDm1TJT1KHVrYUXPDnLXgO89DvzrkLXlrr6JbaDMGUjG7fEEBNDnz5qycLiaoItX7x4/GPhSPOZ45q/64rW3Jvl4= - - secure: OnTKGDs568hSzE5sT9gQhY+nB1xHpnEMoT24UQybPn7Za79tJCkl3WlnqF2sd3+ImsT62xf6PNqRUue8TLVQLCVXCeStrIFPkdp0sps9xtFdNbi6Vb3yrq8QjU4RAQEz5+g8KcmycYMvF3M09lt7jAv8woebXkXdnzHz3IWhwTs= - - secure: 341IG8qb2JKqGDXGsx2a8xEVlkjILA6bSkWqZb9uhoEyW4je7PsqZdCfmKoAcau4I6+sBANu++qARJ58ZpWu+DJzuaKXkhSkdzo/MSykPK04I62v2qhRXUrhkpkXYAB4xK4wKFaCQWVHiCeV5jhEAayZxMB1gLwtxnZRRYXEhY0= - - secure: tvd71+q0xvglcUj6ugSw7oPlruTuNH/XGVh/k6B991zM27NQInmNeMWQa/WE7f8s2xSfG8f9cOtf11uDbPSHgyZj3T6CphfIl5sbT04zFO/1MfI5rbMRBXHvFpUWCb4gS+XUJ146DccuZInF9NI1e3aXNK6u3uPgxmn6DomVRlY= - - secure: BrMErE+J4TneCAGtDe5s8LQjhOJ6fTJSlA/dtmVx+LhzhyUA303wHCziPxrU2PJDL5fGe3r5zX83uoIXwKmU3kb2jRpy7SxF0kdsxqgdbzCnWINRDX5o0TH7AAViUA+nRccWF8wqNWsvkIhv6Pbr1u8B5xScPvBXhEuHJX2iVxo= - - secure: W3o/ae9BZDFNKe0UHGGDuYzriEvf/Eon+miqSwSZ/+rBuTeiX++3dyAMG/4XHeuNDgZ6H7qGtxlkqODK9AHZps5tFZ/zmVzXfzqRItIrGmGLKD7UvbIoS/C5fovhxIwMyWnlXdWeNf4o0QWJed6I188IlDumCxrmnWIWlueap6I= - - secure: rSCNg1LnxNjk/ux80iLQrcHqagWf80PBQf0kM9Wj5dD1nLWvbRMSSeXhiOdNY0ZD9RMROdjupsbFShdF788wAi7ITfhrMf09ys0D3/8ZDmCd51WAUvuutxMEz/TJKTWKItr2gbuRoXvv/hQ9DEWXyHx1A9DaDjwYGBH9bnYmgfs= - - secure: bHD0y307k3vUyA5cYdNc62Tq78r4HX8F4RG8bkgDAP0Z0u8SCfYunk89kw2NCF+qlo+ux84lhh2n/HKAwIdkupQSJaPGO4i241i8pUd1RA0T+CfjvdmMk6KjgbItauAhctgy61BTRJzoLAZQ75JurHLAjc5JNfSxsa1xQGsWIVQ= - - secure: A7NVQrmbAZhwIz+lkDcwX1zw+GJjLbwnW4/A0cCGcZObQxTqM7W6+B6UG9efm2vmxER9xtjstiH9wsLtJYerKxv05jwXoKlq/J+BVu2dTI9S6SqLas6Lo09XFfqtmYKgbV6R2CKDt8hT2a5A/Wp1hK4URjifu2gel/3MO6eeiJs= - - secure: BQCOwcb4u4spzd20vaUSkJycJ0oaojdyucmUV9pRYADH+jDEcCiL52L+bMxGZ+5vYPITG9wG2Kjv8VroyIuYfADMjZJjzMOMiwpjTWxoH7gA/12D8p7FcP9npllJgNg0TMvZUULVx2w2JQEGyq3Kfp2oKHfbgkBhtiSDH8mjSqc= - - secure: ODDYK3EogzOZ4rd/IW3HRAn+Ynpi1ob/lG7udBiiFhOZB8IWzZkNniRBZv60pOVq62YF0EidkNR4MK3Ln+wh3KLkqBWuR86ORgFmGazGxYlUbAfBfwt75FdK2+WAwyLGR3H7eqgTN+Y4U+GyPMUFfMBXbE73sX8Si2ldLy7n5ZE= - - secure: Mk6OHiJ5i4T+/3X5mLOhRuqif7M2cyTPbjNxNhW0oDQG4KB8M+18hDklwnQPpiXOL4LmuuSGDWgOZYnlZHFdLTzj5/nmbfh2qbr30Aqj8OgRnO/jjjU/BrcgBM2zrlH/TOKl5HqHp7bLesHkfTNzNy5IeIuRwZN/8qKNV1HZdtk= - - secure: GyPuciPuxMTNxr1igDPQAAvZdTE4bGIzVM4YpURvZngvhxQgWtvF09nV1FfNQAz643aq1bjbZ1ThfuOagWwTRUVqTgstxwCau/EGOAnoMXt1wDfvBuxpxLK2WDnO8PHYTDtpcnes5D6+45K5Z4bFAs0gIw/XoF0tZiCKVEo+OR0= - - secure: ix+m/F8qUKdjGpBLUW+okt00kmxFOAi7FKi0ndnjQPnHdygMec00tCxcvW4P16QsjpQq7w098Fsjc2V28hMo4RpH0JFPxnnfFttDZfk15UydrYD65EXhpyvh/xmQYd1cCK+YhymhPc0bOz0d7Ava7H7AGfBUkC0DzMdizpbB/pQ= - - secure: ZjxBwneeNa1whozgua2Jx3K9EA0EfaFCjsyB5SGmS8cALzLY4EJawH8iiSGapJrCxz58jK1z3ISdu9a7l5ne85fYI+WuHyTC7QVbW5OpRrOJMwTXf2/hRTVuavp9fA5W7B5nhoqgHMR56YXSaEO6juXiSztsYF7kJiGdCO0f6fQ= - - secure: zavu1UqfqRVh5hFaGdopn32B1ysW1sK769L+cSQnEQprDXB11uBcTJgBX104sw1zUnB0/QTfuZ3eKkhSpDpFg66I7IpqW/Aw7iWVa2EI/eGnQ5vOJwxWA/Bd08H5tpeXSCnjSOQp/Ac/0vhZy2DmhToKDPJakEtRP+/eaqbFNgc= - - secure: omEb6OGAUVSwHvFqUqqw3z16wDv0YrJzQZgHLZuKD8CvC3HvPDQaykqzvFtqrEWAUl5rZf1bSZ/jylximogKzx2+ENn5TjveJQTzQQwVw9FO/Jn8XVM0x7A3K86JpI0azG4LtFAaqpd4mWIAH5ZFeNYB2x6D2jrjXOajLoJ6zmM= diff --git a/cookbooks/apt/Berksfile b/cookbooks/apt/Berksfile deleted file mode 100644 index 4f6ada4..0000000 --- a/cookbooks/apt/Berksfile +++ /dev/null @@ -1,8 +0,0 @@ -source 'https://supermarket.chef.io' - -metadata - -group :integration do - cookbook 'minitest-handler' - cookbook 'apt_test', :path => './test/cookbooks/apt_test' -end diff --git a/cookbooks/apt/CHANGELOG.md b/cookbooks/apt/CHANGELOG.md index ac15bb4..93c71d7 100644 --- a/cookbooks/apt/CHANGELOG.md +++ b/cookbooks/apt/CHANGELOG.md @@ -1,6 +1,37 @@ apt Cookbook CHANGELOG ====================== +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 @@ -22,7 +53,7 @@ v2.5.3 (2014-08-14) v2.5.2 (2014-08-14) ------------------- -- Fully restore fully restore 2.3.10 behaviour +- Fully restore 2.3.10 behaviour v2.5.1 (2014-08-14) ------------------- diff --git a/cookbooks/apt/Gemfile b/cookbooks/apt/Gemfile deleted file mode 100644 index e1b8fa0..0000000 --- a/cookbooks/apt/Gemfile +++ /dev/null @@ -1,37 +0,0 @@ -source 'https://rubygems.org' - -group :lint do - gem 'foodcritic', '~> 3.0' - gem 'rubocop', '~> 0.23' - gem 'rainbow', '< 2.0' -end - -group :unit do - gem 'berkshelf', '~> 3.0.0.beta6' - gem 'chefspec', '~> 4.0' -end - -group :kitchen_common do - gem 'test-kitchen', '~> 1.2' -end - -group :kitchen_vagrant do - gem 'kitchen-vagrant', '~> 0.11' -end - -group :kitchen_cloud do - gem 'kitchen-digitalocean' - gem 'kitchen-ec2' -end - -group :development do - gem 'ruby_gntp' - gem 'growl' - gem 'rb-fsevent' - gem 'guard', '~> 2.4' - gem 'guard-kitchen' - gem 'guard-foodcritic' - gem 'guard-rspec' - gem 'guard-rubocop' - gem 'rake' -end diff --git a/cookbooks/apt/Guardfile b/cookbooks/apt/Guardfile deleted file mode 100644 index 11dc1de..0000000 --- a/cookbooks/apt/Guardfile +++ /dev/null @@ -1,35 +0,0 @@ -# A sample Guardfile -# More info at https://github.com/guard/guard#readme - -# guard 'kitchen' do -# watch(%r{test/.+}) -# watch(%r{^recipes/(.+)\.rb$}) -# watch(%r{^attributes/(.+)\.rb$}) -# watch(%r{^files/(.+)}) -# watch(%r{^templates/(.+)}) -# watch(%r{^providers/(.+)\.rb}) -# watch(%r{^resources/(.+)\.rb}) -# end - -guard 'foodcritic', cookbook_paths: '.', all_on_start: false do - watch(%r{attributes/.+\.rb$}) - watch(%r{providers/.+\.rb$}) - watch(%r{recipes/.+\.rb$}) - watch(%r{resources/.+\.rb$}) - watch('metadata.rb') -end - -guard 'rubocop', all_on_start: false do - watch(%r{attributes/.+\.rb$}) - watch(%r{providers/.+\.rb$}) - watch(%r{recipes/.+\.rb$}) - watch(%r{resources/.+\.rb$}) - watch('metadata.rb') -end - -guard :rspec, cmd: 'bundle exec rspec', all_on_start: false, notification: false do - watch(%r{^libraries/(.+)\.rb$}) - watch(%r{^spec/(.+)_spec\.rb$}) - watch(%r{^(recipes)/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } - watch('spec/spec_helper.rb') { 'spec' } -end diff --git a/cookbooks/apt/README.md b/cookbooks/apt/README.md index dc2e798..0bd79c9 100644 --- a/cookbooks/apt/README.md +++ b/cookbooks/apt/README.md @@ -1,11 +1,10 @@ apt Cookbook ============ -[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/chef-cookbooks/apt?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Build Status](https://img.shields.io/travis/chef-cookbooks/apt.svg)][travis] [![Cookbook Version](https://img.shields.io/cookbook/v/apt.svg)][cookbook] -[![Build Status](https://img.shields.io/travis/opscode-cookbooks/apt.svg)][travis] [cookbook]: https://community.chef.io/cookbooks/apt -[travis]: https://travis-ci.org/opscode-cookbooks/apt +[travis]: https://travis-ci.org/chef-cookbooks/apt 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 LWRP for managing APT repositories in /etc/apt/sources.list.d as well as an LWRP for pinning packages via /etc/apt/preferences.d. @@ -50,11 +49,9 @@ To do this, you need to override the `cache_bypass` attribute with an array of r ```json { - ..., - 'apt': { - ..., - 'cache_bypass': { - URL: PROTOCOL + "apt": { + "cache_bypass": { + "URL": "PROTOCOL" } } } @@ -64,9 +61,9 @@ For example, to prevent caching and directly connect to the repository at `downl ```json { - 'apt': { - 'cache_bypass': { - 'download.oracle.com': 'http' + "apt": { + "cache_bypass": { + "download.oracle.com": "http" } } } @@ -94,7 +91,7 @@ Attributes ### Caching * `['apt']['cacher_ipaddress']` - use a cacher server (or standard proxy server) not available via search -* `['apt']['cacher_interface]` - interface to connect to the cacher-ng service, no default. +* `['apt']['cacher_interface']` - interface to connect to the cacher-ng service, no default. * `['apt']['cacher_port']` - port for the cacher-ng service (either client or server), default is '3142' * `['apt']['cacher_ssl_support']` - indicates whether the cacher supports upstream SSL servers, default is 'false' * `['apt']['cacher_dir']` - directory used by cacher-ng service, default is '/var/cache/apt-cacher-ng' @@ -105,17 +102,22 @@ Attributes ### 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']['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']['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']['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']['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). + +### Configuration for APT + +* `['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 --------- @@ -154,6 +156,17 @@ apt_repository 'zenoss' do end ``` +Enable Ubuntu [multiverse](https://help.ubuntu.com/community/Repositories/Ubuntu) repositories: + +```ruby +apt_repository 'security-ubuntu-multiverse' do + uri 'http://security.ubuntu.com/ubuntu' + distribution 'trusty-security' + components ['multiverse'] + deb_src 'true' +end +``` + Add the Nginx PPA, autodetect the key and repository url: ```ruby @@ -265,7 +278,7 @@ License & Authors - Author:: Seth Chisamore (schisamo@chef.io) ```text -Copyright 2009-2013, Chef Software, Inc. +Copyright:: 2009-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. diff --git a/cookbooks/apt/Rakefile b/cookbooks/apt/Rakefile deleted file mode 100644 index 965b4bf..0000000 --- a/cookbooks/apt/Rakefile +++ /dev/null @@ -1,59 +0,0 @@ -require 'rspec/core/rake_task' -require 'rubocop/rake_task' -require 'foodcritic' -require 'kitchen' - -# Style tests. Rubocop and Foodcritic -namespace :style do - desc 'Run Ruby style checks' - RuboCop::RakeTask.new(:ruby) - - desc 'Run Chef style checks' - FoodCritic::Rake::LintTask.new(:chef) do |t| - t.options = { - fail_tags: ['any'], - tags: ['~FC005'] - } - end -end - -desc 'Run all style checks' -task style: ['style:chef', 'style:ruby'] - -# Rspec and ChefSpec -desc 'Run ChefSpec examples' -RSpec::Core::RakeTask.new(:spec) - -# Integration tests. Kitchen.ci -namespace :integration do - desc 'Run Test Kitchen with Vagrant' - task :vagrant do - Kitchen.logger = Kitchen.default_file_logger - Kitchen::Config.new.instances.each do |instance| - instance.test(:always) - end - end - - desc 'Run Test Kitchen with cloud plugins' - task :cloud do - run_kitchen = true - if ENV['TRAVIS'] == 'true' && ENV['TRAVIS_PULL_REQUEST'] != 'false' - run_kitchen = false - end - - if run_kitchen - Kitchen.logger = Kitchen.default_file_logger - @loader = Kitchen::Loader::YAML.new(project_config: './.kitchen.cloud.yml') - config = Kitchen::Config.new(loader: @loader) - config.instances.each do |instance| - instance.test(:always) - end - end - end -end - -desc 'Run all tests on Travis' -task travis: ['style', 'spec', 'integration:cloud'] - -# Default -task default: ['style', 'spec', 'integration:vagrant'] diff --git a/cookbooks/apt/TESTING.md b/cookbooks/apt/TESTING.md deleted file mode 100644 index 8036473..0000000 --- a/cookbooks/apt/TESTING.md +++ /dev/null @@ -1,187 +0,0 @@ -TESTING doc -======================== - -Bundler -------- -A ruby environment with Bundler installed is a prerequisite for using -the testing harness shipped with this cookbook. At the time of this -writing, it works with Ruby 2.0 and Bundler 1.5.3. All programs -involved, with the exception of Vagrant, can be installed by cd'ing -into the parent directory of this cookbook and running "bundle install" - -Rakefile --------- -The Rakefile ships with a number of tasks, each of which can be ran -individually, or in groups. Typing "rake" by itself will perform style -checks with Rubocop and Foodcritic, ChefSpec with rspec, and -integration with Test Kitchen using the Vagrant driver by -default.Alternatively, integration tests can be ran with Test Kitchen -cloud drivers. - -``` -$ rake -T -rake integration:cloud # Run Test Kitchen with cloud plugins -rake integration:vagrant # Run Test Kitchen with Vagrant -rake spec # Run ChefSpec examples -rake style # Run all style checks -rake style:chef # Lint Chef cookbooks -rake style:ruby # Run Ruby style checks -rake travis # Run all tests on Travis -``` - -Style Testing -------------- -Ruby style tests can be performed by Rubocop by issuing either -``` -bundle exec rubocop -``` -or -``` -rake style:ruby -``` - -Chef style tests can be performed with Foodcritic by issuing either -``` -bundle exec foodcritic -``` -or -``` -rake style:chef -``` - -Spec Testing -------------- -Unit testing is done by running Rspec examples. Rspec will test any -libraries, then test recipes using ChefSpec. This works by compiling a -recipe (but not converging it), and allowing the user to make -assertions about the resource_collection. - -Integration Testing -------------------- -Integration testing is performed by Test Kitchen. Test Kitchen will -use either the Vagrant driver or various cloud drivers to instantiate -machines and apply cookbooks. After a successful converge, tests are -uploaded and ran out of band of Chef. Tests should be designed to -ensure that a recipe has accomplished its goal. - -Integration Testing using Vagrant ---------------------------------- -Integration tests can be performed on a local workstation using -Virtualbox or VMWare. Detailed instructions for setting this up can be -found at the [Bento](https://github.com/chef/bento) project web site. - -Integration tests using Vagrant can be performed with either -``` -bundle exec kitchen test -``` -or -``` -rake integration:vagrant -``` - -Integration Testing using Cloud providers ------------------------------------------ -Integration tests can be performed on cloud providers using -Test Kitchen plugins. This cookbook ships a ```.kitchen.cloud.yml``` -that references environmental variables present in the shell that -```kitchen test``` is ran from. These usually contain authentication -tokens for driving IaaS APIs, as well as the paths to ssh private keys -needed for Test Kitchen log into them after they've been created. - -Examples of environment variables being set in ```~/.bash_profile```: -``` -# digital_ocean -export DIGITAL_OCEAN_CLIENT_ID='your_bits_here' -export DIGITAL_OCEAN_API_KEY='your_bits_here' -export DIGITAL_OCEAN_SSH_KEY_IDS='your_bits_here' - -# aws -export AWS_ACCESS_KEY_ID='your_bits_here' -export AWS_SECRET_ACCESS_KEY='your_bits_here' -export AWS_KEYPAIR_NAME='your_bits_here' - -# joyent -export SDC_CLI_ACCOUNT='your_bits_here' -export SDC_CLI_IDENTITY='your_bits_here' -export SDC_CLI_KEY_ID='your_bits_here' -``` - -Integration tests using cloud drivers can be performed with either -``` -export KITCHEN_YAML=.kitchen.cloud.yml -bundle exec kitchen test -``` -or -``` -rake integration:cloud -``` - -Digital Ocean Hint ------------------- -At the time of this writing, you cannot find the numerical values -needed for your SSH_KEY_IDS from the GUI. Instead, you will need to -access the API from the command line. - - curl -L 'https://api.digitalocean.com/ssh_keys/?client_id=your_bits_here&api_key=your_bits_here' - -Words about .travis.yml ------------------------ -In order for Travis to perform integration tests on public cloud -providers, two major things need to happen. First, the environment -variables referenced by ```.kitchen.cloud.yml``` need to be made -available. Second, the private half of the ssh keys needed to log into -machines need to be dropped off on the machine. - -The first part is straight forward. The travis gem can encrypt -environment variables against the public key on the Travis repository -and add them to the .travis.yml. - -``` -gem install travis -travis encrypt AWS_ACCESS_KEY_ID='your_bits_here' --add -travis encrypt AWS_SECRET_ACCESS_'your_bits_here' --add -travis encrypt AWS_KEYPAIR_NAME='your_bits_here' --add -travis encrypt EC2_SSH_KEY_PATH='~/.ssh/id_ec2.pem' --add - -travis encrypt DIGITAL_OCEAN_CLIENT_ID='your_bits_here' --add -travis encrypt DIGITAL_OCEAN_API_KEY='your_bits_here' --add -travis encrypt DIGITAL_OCEAN_SSH_KEY_IDS='your_bits_here' --add -travis encrypt DIGITAL_OCEAN_SSH_KEY_PATH='~/.ssh/id_do.pem' --add -``` - -The second part is a little more complicated. Travis ENV variables are -restricted to 90 bytes, and will not fit an entire SSH key. This can -be worked around by breaking them up into 90 byte chunks, stashing -them into ENV variables, then digging them out in the -```before_install``` section of .travis.yml - -Here is an AWK script to do the encoding. -``` -base64 ~/.ssh/travisci_cook_digitalocean.pem | \ -awk '{ - j=0; - for( i=1; i> ~/.ssh/id_do.base64 -- cat ~/.ssh/id_do.base64 | tr -d ' ' | base64 --decode > ~/.ssh/id_do.pem - - echo -n $EC2_KEY_CHUNK_{0..30} >> ~/.ssh/id_ec2.base64 - - cat ~/.ssh/id_ec2.base64 | tr -d ' ' | base64 --decode > ~/.ssh/id_ec2.pem -``` - diff --git a/cookbooks/apt/attributes/default.rb b/cookbooks/apt/attributes/default.rb index 02a4442..9a32ceb 100644 --- a/cookbooks/apt/attributes/default.rb +++ b/cookbooks/apt/attributes/default.rb @@ -46,3 +46,6 @@ 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']['confd']['install_recommends'] = true +default['apt']['confd']['install_suggests'] = false diff --git a/cookbooks/apt/libraries/helpers.rb b/cookbooks/apt/libraries/helpers.rb index 2adf9d2..c33bf34 100644 --- a/cookbooks/apt/libraries/helpers.rb +++ b/cookbooks/apt/libraries/helpers.rb @@ -27,6 +27,18 @@ module Apt !which('apt-get').nil? end + # Determines whether we need to run `apt-get update` + # + # @return [Boolean] + def apt_up_to_date? + if ::File.exist?('/var/lib/apt/periodic/update-success-stamp') && + ::File.mtime('/var/lib/apt/periodic/update-success-stamp') > Time.now - node['apt']['periodic_update_min_delay'] + true + else + false + end + end + # Finds a command in $PATH # # @return [String, nil] diff --git a/cookbooks/apt/metadata.json b/cookbooks/apt/metadata.json index 7885fd0..ef3c1a9 100644 --- a/cookbooks/apt/metadata.json +++ b/cookbooks/apt/metadata.json @@ -1,121 +1 @@ -{ - "name": "apt", - "description": "Configures apt and apt services and LWRPs for managing apt repositories and preferences", - "long_description": "apt Cookbook\n============\n[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/chef-cookbooks/apt?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n[![Cookbook Version](https://img.shields.io/cookbook/v/apt.svg)][cookbook]\n[![Build Status](https://img.shields.io/travis/opscode-cookbooks/apt.svg)][travis]\n\n[cookbook]: https://community.chef.io/cookbooks/apt\n[travis]: https://travis-ci.org/opscode-cookbooks/apt\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 LWRP for managing APT repositories in /etc/apt/sources.list.d as well as an LWRP for pinning packages via /etc/apt/preferences.d.\n\n\nRequirements\n------------\n**Version 2.0.0+ of this cookbook requires Chef 11.0.0 or later**. If your Chef version is earlier than 11.0.0, use version 1.10.0 of this cookbook.\n\nVersion 1.8.2 to 1.10.0 of this cookbook requires **Chef 10.16.4** or later.\n\nIf your Chef version is earlier than 10.16.4, use version 1.7.0 of this cookbook.\n\n### Platform\nPlease refer to the [TESTING file](TESTING.md) to see the currently (and passing) tested platforms. The release was tested on:\n\n* Ubuntu 10.04\n* Ubuntu 12.04\n* Ubuntu 13.04\n* Debian 7.1\n* Debian 6.0 (have with manual testing)\n\nMay work with or without modification on other Debian derivatives.\n\n\n-------\n### default\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) results in a noop.**\n\n### cacher-client\nConfigures the node to use the `apt-cacher-ng` server as a client.\n\n#### Bypassing the cache\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 array of repositories, with each array key as the repository URL and value as the protocol to use:\n\n```json\n{\n ...,\n 'apt': {\n ...,\n 'cache_bypass': {\n URL: PROTOCOL\n }\n }\n}\n```\n\nFor example, to prevent caching and directly connect to the repository at `download.oracle.com` via http:\n\n```json\n{\n 'apt': {\n 'cache_bypass': {\n 'download.oracle.com': 'http'\n }\n }\n}\n```\n\n### cacher-ng\nInstalls the `apt-cacher-ng` package and service so the system can provide APT caching. You can check the usage report at http://{hostname}:3142/acng-report.html.\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, you'd set `allowed_origins` to something link `[\"Ubuntu trusty-security\"]` (for Ubuntu trusty) or `[\"Debian wheezy-security\"]` (for Debian wheezy). \n\n\nAttributes\n----------\n\n### General \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) beetween 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_ipaddress']` - use a cacher server (or standard proxy server) not available via search\n* `['apt']['cacher_interface]` - interface to connect to the cacher-ng service, no default.\n* `['apt']['cacher_port']` - port for the cacher-ng service (either client or server), default is '3142'\n* `['apt']['cacher_ssl_support']` - indicates whether the cacher supports upstream SSL servers, default is 'false'\n* `['apt']['cacher_dir']` - directory used by cacher-ng service, default is '/var/cache/apt-cacher-ng'\n* `['apt']['cacher-client']['restrict_environment']` - restrict your node to using the `apt-cacher-ng` server in your Environment, default is 'false'\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* `['apt']['cache_bypass']` - array of URLs to bypass the cache. Accepts the URL and protocol to fetch directly from the remote repository and not attempt to cache\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']['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\nLibraries\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\nResources/Providers\n-------------------\n### `apt_repository`\nThis LWRP provides an easy way to manage additional APT repositories. Adding a new repository will notify running the `execute[apt-get-update]` resource immediately.\n\n#### Actions\n- :add: creates a repository file and builds the repository listing (default)\n- :remove: removes the repository file\n\n#### Attribute Parameters\n- repo_name: name attribute. The name of the channel to discover\n- uri: the base of the Debian distribution\n- distribution: this is usually your release's codename...ie something like `karmic`, `lucid` or `maverick`\n- components: package groupings... when in doubt use `main`\n- arch: constrain package to a particular arch like `i386`, `amd64` or even `armhf` or `powerpc`. Defaults to nil.\n- trusted: treat all packages from this repository as authenticated regardless of signature\n- deb_src: whether or not to add the repository as a source repo as well - value can be `true` or `false`, default `false`.\n- keyserver: the GPG keyserver where the key for the repo should be retrieved\n- key: if a `keyserver` is provided, this is assumed to be the fingerprint, otherwise it can be either the URI to the GPG key for the repo, or a cookbook_file.\n- key_proxy: if set, pass the specified proxy via `http-proxy=` to GPG.\n- cookbook: if key should be a cookbook_file, specify a cookbook where the key is located for files/default. Defaults to nil, so it will use the cookbook where the resource is used.\n\n#### Examples\n\nAdd the Zenoss repo:\n\n```ruby\napt_repository 'zenoss' do\n uri 'http://dev.zenoss.org/deb'\n components ['main', 'stable']\nend\n```\n\nAdd the Nginx PPA, autodetect the key and repository url:\n\n```ruby\napt_repository 'nginx-php' do\n uri 'ppa:nginx/stable'\n distribution node['lsb']['codename']\nend\n```\n\nAdd the JuJu PPA, grab the key from the keyserver, and add source repo:\n\n```ruby\napt_repository 'juju' do\n uri 'http://ppa.launchpad.net/juju/stable/ubuntu'\n components ['main']\n distribution 'trusty'\n key 'C8068B11'\n keyserver 'keyserver.ubuntu.com'\n action :add\n deb_src true\nend\n```\n\nAdd the Cloudera Repo of CDH4 packages for Ubuntu 12.04 on AMD64:\n\n```ruby\napt_repository 'cloudera' do\n uri 'http://archive.cloudera.com/cdh4/ubuntu/precise/amd64/cdh'\n arch 'amd64'\n distribution 'precise-cdh4'\n components ['contrib']\n key 'http://archive.cloudera.com/debian/archive.key'\nend\n```\n\nRemove Zenoss repo:\n\n```ruby\napt_repository 'zenoss' do\n action :remove\nend\n```\n\n### `apt_preference`\nThis LWRP provides an easy way to pin packages in /etc/apt/preferences.d. Although apt-pinning is quite helpful from time to time please note that Debian does not encourage its use without thorough consideration.\n\nFurther information regarding apt-pinning is available via http://wiki.debian.org/AptPreferences.\n\n#### Actions\n- :add: creates a preferences file under /etc/apt/preferences.d\n- :remove: Removes the file, therefore unpin the package\n\n#### Attribute Parameters\n- package_name: name attribute. The name of the package\n- glob: Pin by glob() expression or regexp surrounded by /.\n- pin: The package version/repository to pin\n- pin_priority: The pinning priority aka \"the highest package version wins\"\n\n#### Examples\nPin libmysqlclient16 to version 5.1.49-3:\n\n```ruby\napt_preference 'libmysqlclient16' do\n pin 'version 5.1.49-3'\n pin_priority '700'\nend\n```\n\nUnpin libmysqlclient16:\n\n```ruby\napt_preference 'libmysqlclient16' do\n action :remove\nend\n```\n\nPin all packages from dotdeb.org:\n\n```ruby\napt_preference 'dotdeb' do\n glob '*'\n pin 'origin packages.dotdeb.org'\n pin_priority '700'\nend\n```\n\n\nUsage\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\nLicense & Authors\n-----------------\n- Author:: Joshua Timberman (joshua@chef.io)\n- Author:: Matt Ray (matt@chef.io)\n- Author:: Seth Chisamore (schisamo@chef.io)\n\n```text\nCopyright 2009-2013, 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": { - "ubuntu": ">= 0.0.0", - "debian": ">= 0.0.0" - }, - "dependencies": { - - }, - "recommendations": { - - }, - "suggestions": { - - }, - "conflicting": { - - }, - "providing": { - - }, - "replacing": { - - }, - "attributes": { - "apt/cacher-client/restrict_environment": { - "description": "Whether to restrict the search for the caching server to the same environment as this node", - "default": "false", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "apt/cacher_port": { - "description": "Default listen port for the caching server", - "default": "3142", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "apt/cacher_ssl_support": { - "description": "The caching server supports upstream SSL servers via CONNECT", - "default": "false", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "apt/cacher_interface": { - "description": "Default listen interface for the caching server", - "default": null, - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "apt/key_proxy": { - "description": "Passed as the proxy passed to GPG for the apt_repository resource", - "default": "", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "apt/caching_server": { - "description": "Set this to true if the node is a caching server", - "default": "false", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - } - }, - "groupings": { - - }, - "recipes": { - "apt": "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" - }, - "version": "2.7.0", - "source_url": "", - "issues_url": "" -} +{"name":"apt","version":"2.9.2","description":"Configures apt and apt services. Ships resources for managing apt repositories","long_description":"","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"}} \ No newline at end of file diff --git a/cookbooks/apt/metadata.rb b/cookbooks/apt/metadata.rb deleted file mode 100644 index 752b98c..0000000 --- a/cookbooks/apt/metadata.rb +++ /dev/null @@ -1,38 +0,0 @@ -name 'apt' -maintainer 'Chef Software, Inc.' -maintainer_email 'cookbooks@chef.io' -license 'Apache 2.0' -description 'Configures apt and apt services and LWRPs for managing apt repositories and preferences' -long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) -version '2.7.0' -recipe 'apt', 'Runs apt-get update during compile phase and sets up preseed directories' -recipe 'apt::cacher-ng', 'Set up an apt-cacher-ng caching proxy' -recipe 'apt::cacher-client', 'Client for the apt::cacher-ng caching proxy' - -%w{ ubuntu debian }.each do |os| - supports os -end - -attribute 'apt/cacher-client/restrict_environment', - :description => 'Whether to restrict the search for the caching server to the same environment as this node', - :default => 'false' - -attribute 'apt/cacher_port', - :description => 'Default listen port for the caching server', - :default => '3142' - -attribute 'apt/cacher_ssl_support', - :description => 'The caching server supports upstream SSL servers via CONNECT', - :default => 'false' - -attribute 'apt/cacher_interface', - :description => 'Default listen interface for the caching server', - :default => nil - -attribute 'apt/key_proxy', - :description => 'Passed as the proxy passed to GPG for the apt_repository resource', - :default => '' - -attribute 'apt/caching_server', - :description => 'Set this to true if the node is a caching server', - :default => 'false' diff --git a/cookbooks/apt/providers/preference.rb b/cookbooks/apt/providers/preference.rb index 52d473b..20ca079 100644 --- a/cookbooks/apt/providers/preference.rb +++ b/cookbooks/apt/providers/preference.rb @@ -28,12 +28,16 @@ def build_pref(package_name, pin, pin_priority) "Package: #{package_name}\nPin: #{pin}\nPin-Priority: #{pin_priority}\n" end +def safe_name(name) + name.tr('.', '_').gsub('*', 'wildcard') +end + action :add do preference = build_pref( new_resource.glob || new_resource.package_name, new_resource.pin, new_resource.pin_priority - ) + ) directory '/etc/apt/preferences.d' do owner 'root' @@ -43,6 +47,16 @@ action :add do action :create end + name = safe_name(new_resource.name) + + file "/etc/apt/preferences.d/#{new_resource.name}.pref" do + action :delete + if ::File.exist?("/etc/apt/preferences.d/#{new_resource.name}.pref") + Chef::Log.warn "Replacing #{new_resource.name}.pref with #{name}.pref in /etc/apt/preferences.d/" + end + only_if { name != new_resource.name } + end + file "/etc/apt/preferences.d/#{new_resource.name}" do action :delete if ::File.exist?("/etc/apt/preferences.d/#{new_resource.name}") @@ -50,7 +64,7 @@ action :add do end end - file "/etc/apt/preferences.d/#{new_resource.name}.pref" do + file "/etc/apt/preferences.d/#{name}.pref" do owner 'root' group 'root' mode 00644 @@ -60,9 +74,10 @@ action :add do end action :remove do - if ::File.exist?("/etc/apt/preferences.d/#{new_resource.name}.pref") - Chef::Log.info "Un-pinning #{new_resource.name} from /etc/apt/preferences.d/" - file "/etc/apt/preferences.d/#{new_resource.name}.pref" do + name = safe_name(new_resource.name) + if ::File.exist?("/etc/apt/preferences.d/#{name}.pref") + Chef::Log.info "Un-pinning #{name} from /etc/apt/preferences.d/" + file "/etc/apt/preferences.d/#{name}.pref" do action :delete end end diff --git a/cookbooks/apt/providers/repository.rb b/cookbooks/apt/providers/repository.rb index 6f2895f..28efefe 100644 --- a/cookbooks/apt/providers/repository.rb +++ b/cookbooks/apt/providers/repository.rb @@ -24,25 +24,37 @@ def whyrun_supported? end # install apt key from keyserver -def install_key_from_keyserver(key, keyserver) +def install_key_from_keyserver(key, keyserver, key_proxy) execute "install-key #{key}" do - if !node['apt']['key_proxy'].empty? - command "apt-key adv --keyserver-options http-proxy=#{node['apt']['key_proxy']} --keyserver hkp://#{keyserver}:80 --recv #{key}" - else + if keyserver.start_with?('hkp://') command "apt-key adv --keyserver #{keyserver} --recv #{key}" + elsif key_proxy.empty? + command "apt-key adv --keyserver hkp://#{keyserver}:80 --recv #{key}" + else + command "apt-key adv --keyserver-options http-proxy=#{key_proxy} --keyserver hkp://#{keyserver}:80 --recv #{key}" end + sensitive new_resource.sensitive if respond_to?(:sensitive) action :run not_if do - extract_fingerprints_from_cmd('apt-key finger').any? do |fingerprint| + key_present = extract_fingerprints_from_cmd('apt-key finger').any? do |fingerprint| fingerprint.end_with?(key.upcase) end + + key_present && key_is_valid('apt-key list', key.upcase) end end + + ruby_block "validate-key #{key}" do + block do + fail "The key #{key} is no longer valid and cannot be used for an apt repository." + end + not_if { key_is_valid('apt-key list', key.upcase) } + end end # run command and extract gpg ids def extract_fingerprints_from_cmd(cmd) - so = Mixlib::ShellOut.new(cmd, env: { 'LANG' => 'en_US' }) + so = Mixlib::ShellOut.new(cmd, env: { 'LANG' => 'en_US', 'LANGUAGE' => 'en_US' }) so.run_command so.stdout.split(/\n/).map do |t| if z = t.match(/^ +Key fingerprint = ([0-9A-F ]+)/) @@ -51,14 +63,34 @@ def extract_fingerprints_from_cmd(cmd) end.compact end +# determine whether apt thinks the key is still valid +def key_is_valid(cmd, key) + valid = true + + so = Mixlib::ShellOut.new(cmd, env: { 'LANG' => 'en_US', 'LANGUAGE' => 'en_US' }) + so.run_command + # rubocop:disable Style/Next + so.stdout.split(/\n/).map do |t| + if t.match(%r{^\/#{key}.*\[expired: .*\]$}) + Chef::Log.debug "Found expired key: #{t}" + valid = false + break + end + end + + Chef::Log.debug "key #{key} validity: #{valid}" + valid +end + # install apt key from URI def install_key_from_uri(uri) - key_name = uri.split(/\//).last + key_name = uri.split(%r{\/}).last cached_keyfile = "#{Chef::Config[:file_cache_path]}/#{key_name}" if new_resource.key =~ /http/ remote_file cached_keyfile do source new_resource.key mode 00644 + sensitive new_resource.sensitive if respond_to?(:sensitive) action :create end else @@ -66,12 +98,20 @@ def install_key_from_uri(uri) source new_resource.key cookbook new_resource.cookbook mode 00644 + sensitive new_resource.sensitive if respond_to?(:sensitive) action :create end + + ruby_block "validate-key #{cached_keyfile}" do + block do + fail "The key #{cached_keyfile} is no longer valid and cannot be used for an apt repository." unless key_is_valid("gpg #{cached_keyfile}", '') + end + end end execute "install-key #{key_name}" do command "apt-key add #{cached_keyfile}" + sensitive new_resource.sensitive if respond_to?(:sensitive) action :run not_if do installed_keys = extract_fingerprints_from_cmd('apt-key finger') @@ -83,19 +123,19 @@ end # build repo file contents def build_repo(uri, distribution, components, trusted, arch, add_deb_src) + uri = '"' + uri + '"' unless uri.start_with?("\"", "'") components = components.join(' ') if components.respond_to?(:join) repo_options = [] repo_options << "arch=#{arch}" if arch repo_options << 'trusted=yes' if trusted - repo_options = '[' + repo_options.join(' ') + ']' unless repo_options.empty? - repo_info = "#{uri} #{distribution} #{components}\n" - repo_info = "#{repo_options} #{repo_info}" unless repo_options.empty? + repo_opts = '[' + repo_options.join(' ') + ']' unless repo_options.empty? + repo_info = "#{repo_opts} #{uri} #{distribution} #{components}\n".lstrip repo = "deb #{repo_info}" repo << "deb-src #{repo_info}" if add_deb_src repo end -def get_ppa_key(ppa_owner, ppa_repo) +def get_ppa_key(ppa_owner, ppa_repo, key_proxy) # Launchpad has currently only one stable API which is marked as EOL April 2015. # The new api in devel still uses the same api call for +archive, so I made the version # configurable to provide some sort of workaround if api 1.0 ceases to exist. @@ -115,12 +155,12 @@ def get_ppa_key(ppa_owner, ppa_repo) raise error end - install_key_from_keyserver(key_id, default_keyserver) + install_key_from_keyserver(key_id, default_keyserver, key_proxy) end # fetch ppa key, return full repo url -def get_ppa_url(ppa) - repo_schema = 'http://ppa.launchpad.net/%s/%s/ubuntu' +def get_ppa_url(ppa, key_proxy) + repo_schema = 'http://ppa.launchpad.net/%s/%s/ubuntu' # ppa:user/repo logic ported from # http://bazaar.launchpad.net/~ubuntu-core-dev/software-properties/main/view/head:/softwareproperties/ppa.py#L86 @@ -131,7 +171,7 @@ def get_ppa_url(ppa) ppa_repo = ppa_name.split('/')[1] ppa_repo = 'ppa' if ppa_repo.nil? - get_ppa_key(ppa_owner, ppa_repo) + get_ppa_key(ppa_owner, ppa_repo, key_proxy) format(repo_schema, ppa_owner, ppa_repo) end @@ -139,7 +179,7 @@ end action :add do # add key if new_resource.keyserver && new_resource.key - install_key_from_keyserver(new_resource.key, new_resource.keyserver) + install_key_from_keyserver(new_resource.key, new_resource.keyserver, new_resource.key_proxy) elsif new_resource.key install_key_from_uri(new_resource.key) end @@ -156,6 +196,7 @@ action :add do execute 'apt-get update' do command "apt-get update -o Dir::Etc::sourcelist='sources.list.d/#{new_resource.name}.list' -o Dir::Etc::sourceparts='-' -o APT::Get::List-Cleanup='0'" ignore_failure true + sensitive new_resource.sensitive if respond_to?(:sensitive) action :nothing notifies :run, 'execute[apt-cache gencaches]', :immediately end @@ -163,13 +204,13 @@ action :add do if new_resource.uri.start_with?('ppa:') # build ppa repo file repository = build_repo( - get_ppa_url(new_resource.uri), + get_ppa_url(new_resource.uri, new_resource.key_proxy), new_resource.distribution, 'main', new_resource.trusted, new_resource.arch, new_resource.deb_src - ) + ) else # build repo file repository = build_repo( @@ -179,7 +220,7 @@ action :add do new_resource.trusted, new_resource.arch, new_resource.deb_src - ) + ) end file "/etc/apt/sources.list.d/#{new_resource.name}.list" do @@ -187,6 +228,7 @@ action :add do group 'root' mode 00644 content repository + sensitive new_resource.sensitive if respond_to?(:sensitive) action :create notifies :delete, 'file[/var/lib/apt/periodic/update-success-stamp]', :immediately notifies :run, 'execute[apt-get update]', :immediately if new_resource.cache_rebuild @@ -197,6 +239,7 @@ action :remove do if ::File.exist?("/etc/apt/sources.list.d/#{new_resource.name}.list") Chef::Log.info "Removing #{new_resource.name} repository from /etc/apt/sources.list.d/" file "/etc/apt/sources.list.d/#{new_resource.name}.list" do + sensitive new_resource.sensitive if respond_to?(:sensitive) action :delete end end diff --git a/cookbooks/apt/recipes/cacher-client.rb b/cookbooks/apt/recipes/cacher-client.rb index 0f5b93e..2b6d46d 100644 --- a/cookbooks/apt/recipes/cacher-client.rb +++ b/cookbooks/apt/recipes/cacher-client.rb @@ -64,11 +64,11 @@ if servers.length > 0 group 'root' mode 00644 variables( - :proxy => cacher_ipaddress, - :port => servers[0]['apt']['cacher_port'], - :proxy_ssl => servers[0]['apt']['cacher_ssl_support'], - :bypass => node['apt']['cache_bypass'] - ) + proxy: cacher_ipaddress, + port: servers[0]['apt']['cacher_port'], + proxy_ssl: servers[0]['apt']['cacher_ssl_support'], + bypass: node['apt']['cache_bypass'] + ) action(node['apt']['compiletime'] ? :nothing : :create) notifies :run, 'execute[apt-get update]', :immediately end diff --git a/cookbooks/apt/recipes/cacher-ng.rb b/cookbooks/apt/recipes/cacher-ng.rb index c20d5c9..e8df076 100644 --- a/cookbooks/apt/recipes/cacher-ng.rb +++ b/cookbooks/apt/recipes/cacher-ng.rb @@ -38,6 +38,6 @@ template '/etc/apt-cacher-ng/acng.conf' do end service 'apt-cacher-ng' do - supports :restart => true, :status => false + supports restart: true, status: false action [:enable, :start] end diff --git a/cookbooks/apt/recipes/default.rb b/cookbooks/apt/recipes/default.rb index bfeabbd..a8abe4a 100644 --- a/cookbooks/apt/recipes/default.rb +++ b/cookbooks/apt/recipes/default.rb @@ -35,7 +35,7 @@ file '/var/lib/apt/periodic/update-success-stamp' do end # If compile_time_update run apt-get update at compile time -if node['apt']['compile_time_update'] && (!::File.exist?('/var/lib/apt/periodic/update-success-stamp') || !::File.exist?(first_run_file)) +if node['apt']['compile_time_update'] && (!apt_up_to_date? || !::File.exist?(first_run_file)) e = bash 'apt-get-update at compile time' do code <<-EOH apt-get update @@ -58,15 +58,6 @@ cookbook_file '/etc/apt/apt.conf.d/15update-stamp' do source '15update-stamp' end -# Run apt-get update to create the stamp file -execute 'apt-get-update' do - command 'apt-get update' - ignore_failure true - only_if { apt_installed? } - not_if { ::File.exist?('/var/lib/apt/periodic/update-success-stamp') } - notifies :touch, 'file[/var/lib/apt/periodic/update-success-stamp]', :immediately -end - # For other recipes to call to force an update execute 'apt-get update' do command 'apt-get update' @@ -93,11 +84,8 @@ end execute 'apt-get-update-periodic' do command 'apt-get update' ignore_failure true - only_if do - apt_installed? && - ::File.exist?('/var/lib/apt/periodic/update-success-stamp') && - ::File.mtime('/var/lib/apt/periodic/update-success-stamp') < Time.now - node['apt']['periodic_update_min_delay'] - end + only_if { apt_installed? } + not_if { apt_up_to_date? } notifies :touch, 'file[/var/lib/apt/periodic/update-success-stamp]', :immediately end @@ -110,3 +98,15 @@ end only_if { apt_installed? } end end + +template '/etc/apt/apt.conf.d/10recommends' do + owner 'root' + group 'root' + mode '644' + source '10recommends.erb' +end + +package 'apt-transport-https' do + only_if { apt_installed? } + action :install +end diff --git a/cookbooks/apt/resources/preference.rb b/cookbooks/apt/resources/preference.rb index 64eb34f..a1fdf3b 100644 --- a/cookbooks/apt/resources/preference.rb +++ b/cookbooks/apt/resources/preference.rb @@ -31,7 +31,7 @@ state_attrs :glob, :pin, :pin_priority -attribute :package_name, :kind_of => String, :name_attribute => true, :regex => [/^([a-z]|[A-Z]|[0-9]|_|-|\.)+$/] -attribute :glob, :kind_of => String -attribute :pin, :kind_of => String -attribute :pin_priority, :kind_of => String +attribute :package_name, kind_of: String, name_attribute: true, regex: [/^([a-z]|[A-Z]|[0-9]|_|-|\.|\*)+$/] +attribute :glob, kind_of: String +attribute :pin, kind_of: String +attribute :pin_priority, kind_of: String diff --git a/cookbooks/apt/resources/repository.rb b/cookbooks/apt/resources/repository.rb index b9268ee..8d3b3fc 100644 --- a/cookbooks/apt/resources/repository.rb +++ b/cookbooks/apt/resources/repository.rb @@ -34,22 +34,27 @@ state_attrs :arch, :distribution, :key, :keyserver, + :key_proxy, :repo_name, :trusted, - :uri + :uri, + :sensitive # name of the repo, used for source.list filename -attribute :repo_name, :kind_of => String, :name_attribute => true, :regex => [/^([a-z]|[A-Z]|[0-9]|_|-|\.)+$/] -attribute :uri, :kind_of => String -attribute :distribution, :kind_of => String -attribute :components, :kind_of => Array, :default => [] -attribute :arch, :kind_of => String, :default => nil -attribute :trusted, :kind_of => [TrueClass, FalseClass], :default => false +attribute :repo_name, kind_of: String, name_attribute: true, regex: [/^([a-z]|[A-Z]|[0-9]|_|-|\.)+$/] +attribute :uri, kind_of: String +attribute :distribution, kind_of: String +attribute :components, kind_of: Array, default: [] +attribute :arch, kind_of: String, default: nil +attribute :trusted, kind_of: [TrueClass, FalseClass], default: false # whether or not to add the repository as a source repo as well -attribute :deb_src, :default => false -attribute :keyserver, :kind_of => String, :default => nil -attribute :key, :kind_of => String, :default => nil -attribute :cookbook, :kind_of => String, :default => nil +attribute :deb_src, default: false +attribute :keyserver, kind_of: String, default: nil +attribute :key, kind_of: String, default: nil +attribute :key_proxy, kind_of: String, default: node['apt']['key_proxy'] +attribute :cookbook, kind_of: String, default: nil # trigger cache rebuild # If not you can trigger in the recipe itself after checking the status of resource.updated{_by_last_action}? -attribute :cache_rebuild, :kind_of => [TrueClass, FalseClass], :default => true +attribute :cache_rebuild, kind_of: [TrueClass, FalseClass], default: true +# Hide content of the source file, don't show output for commands being run, etc. +attribute :sensitive, kind_of: [TrueClass, FalseClass], default: false diff --git a/cookbooks/apt/templates/default/10recommends.erb b/cookbooks/apt/templates/default/10recommends.erb new file mode 100644 index 0000000..16b3664 --- /dev/null +++ b/cookbooks/apt/templates/default/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/ark/CHANGELOG.md b/cookbooks/ark/CHANGELOG.md index 98539d4..7e5a432 100644 --- a/cookbooks/ark/CHANGELOG.md +++ b/cookbooks/ark/CHANGELOG.md @@ -1,63 +1,80 @@ -ark Cookbook CHANGELOG -====================== +# ark Cookbook CHANGELOG This file is used to list changes made in each version of the ark cookbook. +## 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 -v0.9.0 (2014-06-06) -------------------- -* [COOK-3642] Add Windows support +## 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.8.2 (2014-04-23) -------------------- +## 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) -------------------- +## v0.8.0 (2014-04-10) - [COOK-2771] - Add support for XZ compression - -v0.7.2 (2014-03-28) -------------------- +## 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) -------------------- +## v0.7.0 (2014-03-18) - [COOK-4437] - configure and install_with_make should chown after unpack - -v0.6.0 (2014-02-27) -------------------- +## v0.6.0 (2014-02-27) [COOK-3786] - Unable to install multiple versions of archive without duplication - -v0.5.0 (2014-02-21) -------------------- +## 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 ------- +## 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 ------- +## v0.4.0 ### Improvement - **[COOK-3539](https://tickets.opscode.com/browse/COOK-3539)** - Allow dumping of bz2 and gzip files -v0.3.2 ------- +## 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 @@ -67,54 +84,41 @@ v0.3.2 ### Improvement - **[COOK-3179](https://tickets.opscode.com/browse/COOK-3179)** - README updates and refactor -v0.3.0 ------- +## 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 ------- +## 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 ------- +## 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 ------- +## 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 ------- +## v0.1.0 - [COOK-2335] - ark resource broken on Chef 11 -v0.0.1 ------- +## v0.0.1 - [COOK-2026] - Allow `cherry_pick` action to be used for directories as well as files -v0.0.1 ------- +## v0.0.1 - [COOK-1593] - README formatting updates for better display on Community Site -v0.0.1 ------- +## v0.0.1 ### Bug - dangling "unless" @@ -124,12 +128,11 @@ v0.0.1 - add foodcritic test - travis.ci support -v0.0.10 (May 23, 2012 ------- +## v0.0.10 (May 23, 2012 ### Bug -- `strip_leading_dir` not working for zip files https://github.com/bryanwb/chef-ark/issues/19 +- `strip_leading_dir` not working for zip files [https://github.com/bryanwb/chef-ark/issues/19](https://github.com/bryanwb/chef-ark/issues/19) ### Improvement -- use autogen.sh to generate configure script for configure action https://github.com/bryanwb/chef-ark/issues/16 -- support more file extensions https://github.com/bryanwb/chef-ark/pull/18 +- use autogen.sh to generate configure script for configure action [https://github.com/bryanwb/chef-ark/issues/16](https://github.com/bryanwb/chef-ark/issues/16) +- support more file extensions [https://github.com/bryanwb/chef-ark/pull/18](https://github.com/bryanwb/chef-ark/pull/18) - 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/README.md b/cookbooks/ark/README.md index 1aba35b..6c4ec8a 100644 --- a/cookbooks/ark/README.md +++ b/cookbooks/ark/README.md @@ -1,297 +1,245 @@ -# chef-ark [![Build Status](https://secure.travis-ci.org/opscode-cookbooks/ark.png?branch=master)](https://travis-ci.org/opscode-cookbooks/ark) +# ark cookbook +[![Build Status](https://travis-ci.org/burtlo/ark.svg?branch=master)](https://travis-ci.org/burtlo/ark) [![Cookbook Version](https://img.shields.io/cookbook/v/ark.svg)](https://supermarket.chef.io/cookbooks/ark) -Overview -======== +## 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 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 is a modified verion of Infochimp's awesome -[install_from cookbook](http://github.com/infochimps-cookbooks/install_from). -It has been heavily refactored and extended to meet different use -cases. +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: - ark 'pig' do - url 'http://apache.org/pig/pig-0.8.0.tar.gz' - end +```ruby +ark 'pig' do + url 'http://apache.org/pig/pig-0.8.0.tar.gz' +end +``` The provider 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 -* 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 enviroment `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`. -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. -At this time ark only handles files available from URLs. It does not -handle local files. +## Requirements +### Platforms +- Debian/Ubuntu +- RHEL/CentOS/Scientific/Oracle +- Fedora +- FreeBSD +- SmartOS +- Mac OS X -Requirements -============ +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. -This cookbook requires Chef 11 for the provider, as it uses the -`use_inline_resources` method. +### Chef +- Chef 11+ -More about -[use_inline_resources](http://docs.opscode.com/lwrp_common_inline_compile.html) -in the Chef documentation. +### Cookbooks +- build-essential +- seven_zip +- 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. +## 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. +- `node['ark']['prefix_root']` - default base location if the `prefix_root` is not passed into the resource. +- `node['ark']['prefix_bin']` - default binary location if the `prefix_bin` is not passed into the resource. +- `node['ark']['prefix_home']` - default home location if the `prefix_home` is not passed into the resource. +- `node['ark']['win_install_dir']` - directory where the files will be put on windows +- `node['ark']['package_dependencies']` - prerequisite system packages that need to be installed to support ark. -Attributes -========== +## Resources +- `ark` - does the extract/build/configure dance -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. -* `node['ark']['prefix_root']` - default base location if the - `prefix_root` is not passed into the resource. -* `node['ark']['prefix_bin']` - default binary location if the - `prefix_bin` is not passed into the resource. -* `node['ark']['prefix_home']` - default home location if the - `prefix_home` is not passed into the resource. -* `node['ark']['win_install_dir']` - directory where the files will - be put on windows -* `node['ark']['package_dependencies']` - prerequisite system - packages that need to be installed to support ark. - -Resources/Providers -=================== - -* `ark` - does the extract/build/configure dance - -Actions -------- - -- `:install`: extracts the file and creates a 'friendly' symbolic link - to the extracted directory path +### 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 `make`, - and `make install`. It does _not_ run the configure step at this - time -- `: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 +- `:install_with_make`: extracts the archive to a path, runs `make`, and `make install`. It does _not_ run the configure step at this time +- `: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_build`: runs the command "python setup.py build" in the - extracted directory -- `:setup_py_install`: runs the comand "python setup.py install" in - the extracted directory - -## :cherry_pick +- `: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 - +#### 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. +### :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 - +#### 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 +- `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. -Extract the archive to a specified path, does not create any symbolic -links. - -### Attribute Parameters for :put +### :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` -- `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, if true, append the `./bin` directory of - the extracted directory to the global `PATH` variable for all users. -Attribute Parameters --------------------- +- `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. +- `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`. -- `checksum`: sha256 checksum, used for security . - `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. +- `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. + +- `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. + +- `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. + +- `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. + +- `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` -### Examples +#### 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` -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 +``` - # 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: -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 +``` - 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: -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 +``` - 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: -Install Apache Ivy dependency resolution tool in /home/foobar/ivy, strip any -leading directory if one exists: +```ruby + ark "ivy" do + path "/home/foobar" + url 'http://someurl.example.com/ivy.tar.gz' + checksum '89ba5fde0c596db388c3bbd265b63007a9cc3df3a8e6d79a46780c1a39408cb5' + action :put + end +``` - ark "ivy" do - path "/home/foobar - url 'http://someurl.example.com/ivy.tar.gz' - checksum '89ba5fde0c596db388c3bbd265b63007a9cc3df3a8e6d79a46780c1a39408cb5' - action :put - 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: - 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: - - 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 +```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): - 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 +```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 alternave values for `prefix_root`, `prefix_home`, and `prefix_bin`: +Build and install haproxy and use alternative values for `prefix_root`, `prefix_home`, and `prefix_bin`: - 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 +```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 pass multiple actions to ark and supply the file extension in case -the file extension can not be determined by the URL: +You can also pass multiple actions to ark and supply the file extension in case the file extension can not be determined by the URL: - ark "test_autogen" do - url 'https://github.com/zeromq/libzmq/tarball/master' - extension "tar.gz" - action [ :configure, :install_with_make ] - end +```ruby + ark "test_autogen" do + url 'https://github.com/zeromq/libzmq/tarball/master' + extension "tar.gz" + action [ :configure, :install_with_make ] + end +``` -License and Author -================== - -- Author: Philip (flip) Kromer - Infochimps, Inc() -- Author: Bryan W. Berry () -- Author: Denis Barishev () -- Author: Sean OMeara () +## License and 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, Opscode, Inc +- Copyright: 2013, 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 @@ -303,3 +251,4 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 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 index c86cd03..0d427d6 100644 --- a/cookbooks/ark/attributes/default.rb +++ b/cookbooks/ark/attributes/default.rb @@ -1,16 +1,43 @@ +# +# Cookbook Name:: 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' -if node['platform_family'] === 'windows' - default['ark']['tar'] = "\"#{default['7-zip']['home']}\\7z.exe\"" -else - default['ark']['tar'] = '/bin/tar' -end +default['ark']['tar'] = case node['platform_family'] + when 'windows' + "\"#{ENV['SYSTEMDRIVE']}\\7-zip\\7z.exe\"" + when 'mac_os_x', 'freebsd' + '/usr/bin/tar' + when 'smartos' + '/bin/gtar' + else + '/bin/tar' + end -pkgs = %w(libtool autoconf) unless platform_family?('mac_os_x','windows') -pkgs += %w(unzip rsync make gcc) unless platform_family?('mac_os_x','windows') -pkgs += %w(autogen) unless platform_family?('rhel', 'fedora', 'mac_os_x', 'suse','windows') -pkgs += %w(gtar) if platform?('freebsd') +pkgs = %w(libtool autoconf) unless platform_family?('mac_os_x', 'windows') +pkgs += %w(make) unless platform_family?('mac_os_x', 'windows', 'freebsd') +pkgs += %w(unzip rsync gcc) unless platform_family?('mac_os_x', 'windows') +pkgs += %w(autogen) unless platform_family?('rhel', 'fedora', 'mac_os_x', 'suse', 'windows') +pkgs += %w(gtar) if platform?('freebsd') || platform?('smartos') +pkgs += %w(gmake) if platform?('freebsd') +pkgs += %w(xz-lzma-compat bzip2 tar) if platform_family?('rhel', 'fedora') +pkgs += %w(shtool pkg-config) if platform_family?('debian') default['ark']['package_dependencies'] = pkgs diff --git a/cookbooks/ark/files/default/tests/minitest/default_test.rb b/cookbooks/ark/files/default/tests/minitest/default_test.rb deleted file mode 100644 index e69de29..0000000 diff --git a/cookbooks/ark/files/default/tests/minitest/support/helpers.rb b/cookbooks/ark/files/default/tests/minitest/support/helpers.rb deleted file mode 100644 index e69de29..0000000 diff --git a/cookbooks/ark/files/default/tests/minitest/test_test.rb b/cookbooks/ark/files/default/tests/minitest/test_test.rb deleted file mode 100644 index c46812d..0000000 --- a/cookbooks/ark/files/default/tests/minitest/test_test.rb +++ /dev/null @@ -1,102 +0,0 @@ -require 'minitest/spec' - -describe_recipe 'ark::test' do - - # It's often convenient to load these includes in a separate - # helper along with - # your own helper methods, but here we just include them directly: - include MiniTest::Chef::Assertions - include MiniTest::Chef::Context - include MiniTest::Chef::Resources - - it 'installed the unzip package' do - package('unzip').must_be_installed - end - - if RUBY_PLATFORM =~ /freebsd/ - it 'installs the gnu tar package on freebsc' do - package('gtar').must_be_installed - end - end - - it 'puts an ark in the desired directory w/out symlinks' do - directory('/usr/local/test_put').must_exist - end - - it 'dumps the correct files into place with correct owner and group' do - file('/usr/local/foo_dump/foo1.txt').must_have(:owner, 'foobarbaz').and(:group, 'foobarbaz') - end - - it 'cherrypicks the mysql connector and set the correct owner and group' do - file('/usr/local/foo_cherry_pick/foo1.txt').must_have(:owner, 'foobarbaz').and(:group, 'foobarbaz') - end - - it 'cherrypicks the file from a zip' do - file('/usr/local/foo_cherry_pick_from_zip/foo1.txt').must_exist - end - - it 'creates directory and symlink properly for the full ark install' do - directory('/usr/local/foo-2').must_have(:owner, 'foobarbaz').and(:group, 'foobarbaz') - link('/usr/local/foo').must_exist.with(:link_type, :symbolic).and(:to, '/usr/local/foo-2') - end - - it 'symlinks multiple binary commands' do - link('/usr/local/bin/do_foo').must_exist.with(:link_type, :symbolic).and(:to, '/usr/local/foo-2/bin/do_foo') - link('/usr/local/bin/do_more_foo').must_exist.with(:link_type, :symbolic).and(:to, '/usr/local/foo-2/bin/do_more_foo') - end - - it 'appends to the environment PATH' do - unless RUBY_PLATFORM =~ /freebsd/ - file('/etc/profile.d/foo_append_env.sh').must_include '/usr/local/foo_append_env-7.0.26/bin' - - bin_path_present = !ENV['PATH'].scan('/usr/local/foo_append_env-7.0.26/bin').empty? - assert bin_path_present - end - end - - it 'doesnt strip top-level directory if specified' do - directory('/usr/local/foo_dont_strip/foo_sub').must_exist - end - - it 'does strip for zip file' do - file('/usr/local/foo_zip_strip/foo1.txt').must_exist - end - - it 'successfully compiles haproxy' do - file('/usr/local/haproxy-1.5/haproxy').must_exist - end - - unless RUBY_PLATFORM =~ /freebsd/ - it 'installs haproxy binary' do - file('/usr/local/sbin/haproxy').must_exist - directory('/usr/local/doc/haproxy').must_exist - end - end - - it 'creates an alternate prefix_bin' do - link('/opt/bin/do_foo').must_exist.with(:link_type, :symbolic).and(:to, '/opt/foo_alt_bin-3/bin/do_foo') - end - - it 'properly unpacks .tbz and .tgz archives' do - file('/usr/local/foo_tbz/foo1.txt').must_exist - file('/usr/local/foo_tgz/foo1.txt').must_exist - end - - it 'sends notification when resource updated' do - file('/tmp/foobarbaz/notification_successful.txt').must_exist - end - - it 'uses autogen.sh to generate configure script' do - file('/usr/local/test_autogen-1/configure').must_exist - end - - it 'strips 2 components out of foo_sub.tar.gz archive path' do - directory('/usr/local/foo_sub-1/bin').must_exist - file('/usr/local/foo_sub-1/foo1.txt').must_exist - end - - it 'strips 2 components out of foo_sub.zip archive path' do - directory('/usr/local/foo_sub-2/bin').must_exist - file('/usr/local/foo_sub-2/foo1.txt').must_exist - end -end diff --git a/cookbooks/ark/libraries/default.rb b/cookbooks/ark/libraries/default.rb index 4ee688c..c1a8e7f 100644 --- a/cookbooks/ark/libraries/default.rb +++ b/cookbooks/ark/libraries/default.rb @@ -1,234 +1,113 @@ -# libs +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 Opscode - module Ark - module ProviderHelpers - private +module Ark + module ProviderHelpers + extend ::Ark::PlatformSpecificBuilders - def unpack_type - case parse_file_extension - when /tar.gz|tgz/ then "tar_xzf" - when /tar.bz2|tbz/ then "tar_xjf" - when /tar.xz|txz/ then "tar_xJf" - when /zip|war|jar/ then "unzip" - else fail "Don't know how to expand #{new_resource.url}" - end - end + generates_archive_commands_for :seven_zip, + when_the: -> { node['platform_family'] == 'windows' }, + with_klass: ::Ark::SevenZipCommandBuilder - def parse_file_extension - if new_resource.extension.nil? - # purge any trailing redirect - url = new_resource.url.clone - url =~ %r{^https?:\/\/.*(.bin|bz2|gz|jar|tbz|tgz|txz|war|xz|zip)(\/.*\/)} - url.gsub!(Regexp.last_match(2), '') unless Regexp.last_match(2).nil? - # remove tailing 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)(\?.*)?/ - Chef::Log.debug("DEBUG: file_extension is #{Regexp.last_match(2)}") - new_resource.extension = Regexp.last_match(2) - end - new_resource.extension - end + generates_archive_commands_for :unzip, + when_the: -> { new_resource.extension =~ /zip|war|jar/ }, + with_klass: ::Ark::UnzipCommandBuilder - def unpack_command - if node['platform_family'] === 'windows' - cmd = sevenzip_command - else - case unpack_type - when "tar_xzf" - cmd = tar_command("xzf") - when "tar_xjf" - cmd = tar_command("xjf") - when "tar_xJf" - cmd = tar_command("xJf") - when "unzip" - cmd = unzip_command - end - end - Chef::Log.debug("DEBUG: cmd: #{cmd}") - cmd - end + generates_archive_commands_for :tar, + when_the: -> { true }, + with_klass: ::Ark::TarCommandBuilder - def tar_command(tar_args) - cmd = node['ark']['tar'] - cmd += " #{tar_args} " - cmd += new_resource.release_file - cmd += tar_strip_args - cmd - end + generates_owner_commands_for :windows, + when_the: -> { node['platform_family'] == 'windows' }, + with_klass: ::Ark::WindowsOwner - def unzip_command - if new_resource.strip_components > 0 - require 'tmpdir' - tmpdir = Dir.mktmpdir - strip_dir = '*/' * new_resource.strip_components - cmd = "unzip -q -u -o #{new_resource.release_file} -d #{tmpdir}" - cmd += " && rsync -a #{tmpdir}/#{strip_dir} #{new_resource.path}" - cmd += " && rm -rf #{tmpdir}" - cmd - else - "unzip -q -u -o #{new_resource.release_file} -d #{new_resource.path}" - end - end + generates_owner_commands_for :all_other_platforms, + when_the: -> { true }, + with_klass: ::Ark::GeneralOwner - def sevenzip_command - if new_resource.strip_components > 0 - require 'tmpdir' - tmpdir = Dir.mktmpdir - cmd = sevenzip_command_builder(tmpdir,'e') - cmd += " && " - currdir = tmpdir - var = 0 - while var < new_resource.strip_components do - var += 1 - cmd += "for /f %#{var} in ('dir /ad /b \"#{currdir.gsub! '/', '\\'}\"') do " - currdir += "\\%#{var}" - end - cmd += "xcopy \"#{currdir}\" \"#{new_resource.home_dir}\" /s /e" - else - cmd = sevenzip_command_builder(new_resource.path,'x') - end - cmd - end + def deprecations + ::Ark::ResourceDeprecations.on(new_resource) + end - def sevenzip_command_builder(dir, command) - cmd = "#{node['ark']['tar']} #{command} \""; - cmd += new_resource.release_file - cmd += "\" " - case parse_file_extension - when /tar.gz|tgz|tar.bz2|tbz|tar.xz|txz/ - cmd += " -so | #{node['ark']['tar']} x -aoa -si -ttar" - end - cmd += " -o\"#{dir}\" -uy" - cmd - end + def show_deprecations + deprecations.each { |message| Chef::Log.warn("DEPRECATED: #{message}") } + end - def dump_command - if node['platform_family'] === 'windows' - cmd = sevenzip_command_builder(new_resource.path,'e') - else - case unpack_type - when "tar_xzf", "tar_xjf", "tar_xJf" - cmd = "tar -mxf \"#{new_resource.release_file}\" -C \"#{new_resource.path}\"" - when "unzip" - cmd = "unzip -j -q -u -o \"#{new_resource.release_file}\" -d \"#{new_resource.path}\"" - end - end - Chef::Log.debug("DEBUG: cmd: #{cmd}") - cmd - end + def defaults + @resource_defaults ||= ::Ark::ResourceDefaults.new(new_resource) + end - def cherry_pick_command - if node['platform_family'] === 'windows' - cmd = sevenzip_command_builder(new_resource.path,'e') - cmd += " -r #{new_resource.creates}" - else - case unpack_type - when "tar_xzf" - cmd = cherry_pick_tar_command("xzf") - when "tar_xjf" - cmd = cherry_pick_tar_command("xjf") - when "tar_xJf" - cmd = cherry_pick_tar_command("xJf") - when "unzip" - cmd = "unzip -t #{new_resource.release_file} \"*/#{new_resource.creates}\" ; stat=$? ;" - cmd += "if [ $stat -eq 11 ] ; then " - cmd += "unzip -j -o #{new_resource.release_file} \"#{new_resource.creates}\" -d #{new_resource.path} ;" - cmd += "elif [ $stat -ne 0 ] ; then false ;" - cmd += "else " - cmd += "unzip -j -o #{new_resource.release_file} \"*/#{new_resource.creates}\" -d #{new_resource.path} ;" - cmd += "fi" - end - end - Chef::Log.debug("DEBUG: cmd: #{cmd}") - cmd - end + # rubocop:disable Metrics/AbcSize + 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 - def cherry_pick_tar_command(tar_args) - cmd = node['ark']['tar'] - cmd += " #{tar_args}" - cmd += " #{new_resource.release_file}" - cmd += " -C" - cmd += " #{new_resource.path}" - cmd += " #{new_resource.creates}" - cmd += tar_strip_args - cmd - end + # 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_paths - release_ext = parse_file_extension - prefix_bin = new_resource.prefix_bin.nil? ? new_resource.run_context.node['ark']['prefix_bin'] : new_resource.prefix_bin - prefix_root = new_resource.prefix_root.nil? ? new_resource.run_context.node['ark']['prefix_root'] : new_resource.prefix_root - if new_resource.prefix_home.nil? - default_home_dir = ::File.join(new_resource.run_context.node['ark']['prefix_home'], new_resource.name) - else - default_home_dir = ::File.join(new_resource.prefix_home, new_resource.name) - end - # set effective paths - new_resource.prefix_bin = prefix_bin - new_resource.version ||= "1" # initialize to one if nil - new_resource.home_dir ||= default_home_dir - if node['platform_family'] === 'windows' - new_resource.path = new_resource.win_install_dir - else - new_resource.path = ::File.join(prefix_root, "#{new_resource.name}-#{new_resource.version}") - end - Chef::Log.debug("path is #{new_resource.path}") - new_resource.release_file = ::File.join(Chef::Config[:file_cache_path], "#{new_resource.name}-#{new_resource.version}.#{release_ext}") - end + def set_put_paths + new_resource.extension = defaults.extension - def set_put_paths - release_ext = parse_file_extension - path = new_resource.path.nil? ? new_resource.run_context.node['ark']['prefix_root'] : new_resource.path - new_resource.path = ::File.join(path, new_resource.name) - Chef::Log.debug("DEBUG: path is #{new_resource.path}") - new_resource.release_file = ::File.join(Chef::Config[:file_cache_path], "#{new_resource.name}.#{release_ext}") - end + # 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 - release_ext = parse_file_extension - new_resource.release_file = ::File.join(Chef::Config[:file_cache_path], "#{new_resource.name}.#{release_ext}") - end + def set_dump_paths + new_resource.extension = defaults.extension + new_resource.release_file = defaults.release_file_without_version + end - def tar_strip_args - new_resource.strip_components > 0 ? " --strip-components=#{new_resource.strip_components}" : "" - end + def unpack_command + archive_application.unpack + end - def show_deprecations - if [true, false].include?(new_resource.strip_leading_dir) - Chef::Log.warn("DEPRECATED: strip_leading_dir attribute was deprecated. Use strip_components instead.") - end - end + def dump_command + archive_application.dump + end - def owner_command - if node['platform_family'] === 'windows' - cmd = "icacls #{new_resource.path}\\* /setowner #{new_resource.owner}" - else - cmd = "chown -R #{new_resource.owner}:#{new_resource.group} #{new_resource.path}" - end - cmd - end + def cherry_pick_command + archive_application.cherry_pick + end - # def unpacked?(path) - # if new_resource.creates - # full_path = ::File.join(new_resource.path, new_resource.creates) - # else - # full_path = path - # end - # if ::File.directory? full_path - # if ::File.stat(full_path).nlink == 2 - # false - # else - # true - # end - # elsif ::File.exists? full_path - # true - # else - # false - # end - # 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..2431a2f --- /dev/null +++ b/cookbooks/ark/libraries/matchers.rb @@ -0,0 +1,42 @@ + +if defined?(ChefSpec) + 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..93574cd --- /dev/null +++ b/cookbooks/ark/libraries/resource_defaults.rb @@ -0,0 +1,100 @@ +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 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)(\/.*\/)} + url.gsub!(Regexp.last_match(2), '') unless Regexp.last_match(2).nil? + # remove tailing 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)(\?.*)?/ + 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 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..66ae2a0 --- /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..ff7a40f --- /dev/null +++ b/cookbooks/ark/libraries/sevenzip_command_builder.rb @@ -0,0 +1,66 @@ +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, 'e')} -r #{resource.creates}" + end + + def initialize(resource) + @resource = resource + end + + private + + attr_reader :resource + + # rubocop:disable Metrics/AbcSize + def sevenzip_command + if resource.strip_components <= 0 + sevenzip_command_builder(resource.path, 'x') + return + end + + tmpdir = make_temp_directory + cmd = sevenzip_command_builder(tmpdir, 'e') + + cmd += " && " + currdir = tmpdir.tr('/', '\\') + + 1.upto(resource.strip_components).each do |count| + cmd += "for /f %#{count} in ('dir /ad /b \"#{currdir}\"') do " + currdir += "\\%#{count}" + end + + cmd += "xcopy \"#{currdir}\" \"#{resource.home_dir}\" /s /e" + end + # rubocop:enable Metrics/AbcSize + + def sevenzip_binary + resource.run_context.node['ark']['tar'] + 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 + "" + 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..e9cda0d --- /dev/null +++ b/cookbooks/ark/libraries/tar_command_builder.rb @@ -0,0 +1,49 @@ +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 + resource.run_context.node['ark']['tar'] + 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..1c1f4ef --- /dev/null +++ b/cookbooks/ark/libraries/unzip_command_builder.rb @@ -0,0 +1,50 @@ +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 + + # rubocop:disable Metrics/AbcSize + 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 + # rubocop:enable Metrics/AbcSize + + 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..e5c3ffd --- /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 + "icacls \"#{resource.path}\\*\" /setowner \"#{resource.owner}\"" + end + end +end diff --git a/cookbooks/ark/metadata.json b/cookbooks/ark/metadata.json index 4247a31..8857c95 100644 --- a/cookbooks/ark/metadata.json +++ b/cookbooks/ark/metadata.json @@ -1,38 +1 @@ -{ - "name": "ark", - "version": "0.9.0", - "description": "Installs/Configures ark", - "long_description": "# chef-ark [![Build Status](https://secure.travis-ci.org/opscode-cookbooks/ark.png?branch=master)](https://travis-ci.org/opscode-cookbooks/ark)\n\nOverview\n========\n\nThis cookbook provides `ark`, a resource for managing software\narchives. It manages the fetch-unpack-configure-build-install process\ncommon to installing software from source, or from binary\ndistributions that are not fully fledged OS packages.\n\nThis is a modified verion of Infochimp's awesome\n[install_from cookbook](http://github.com/infochimps-cookbooks/install_from).\nIt has been heavily refactored and extended to meet different use\ncases.\n\nGiven a simple project archive available at a url:\n\n ark 'pig' do\n url 'http://apache.org/pig/pig-0.8.0.tar.gz'\n end\n\nThe provider 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 enviroment `PATH` variable\n\nBy default, the ark will not run again if the `:path` is not empty.\nArk provides many actions to accommodate different use cases, such as\n`:dump`, `:cherry_pick`, `:put`, and `:install_with_make`.\n\nAt this time ark only handles files available from URLs. It does not\nhandle local files.\n\nRequirements\n============\n\nThis cookbook requires Chef 11 for the provider, as it uses the\n`use_inline_resources` method.\n\nMore about\n[use_inline_resources](http://docs.opscode.com/lwrp_common_inline_compile.html)\nin the Chef documentation.\n\nShould work on common Unix/Linux systems with typical userland\nutilities like tar, gzip, etc. May require the installation of build\ntools for compiling from source, but that installation is outside the\nscope of this cookbook.\n\nAttributes\n==========\n\nCustomize the attributes to suit site specific conventions and\ndefaults.\n\n* `node['ark']['apache_mirror']` - if the URL is an apache mirror,\n use the attribute as the default.\n* `node['ark']['prefix_root']` - default base location if the\n `prefix_root` is not passed into the resource.\n* `node['ark']['prefix_bin']` - default binary location if the\n `prefix_bin` is not passed into the resource.\n* `node['ark']['prefix_home']` - default home location if the\n `prefix_home` is not passed into the resource.\n* `node['ark']['win_install_dir']` - directory where the files will\n be put on windows\n* `node['ark']['package_dependencies']` - prerequisite system\n packages that need to be installed to support ark.\n\nResources/Providers\n===================\n\n* `ark` - does the extract/build/configure dance\n\nActions\n-------\n\n- `:install`: extracts the file and creates a 'friendly' symbolic link\n to the extracted directory path\n- `:configure`: configure ahead of the install action\n- `:install_with_make`: extracts the archive to a path, runs `make`,\n and `make install`. It does _not_ run the configure step at this\n time\n- `:dump`: strips all directories from the archive and dumps the\n contained files into a specified path\n- `:cherry_pick`: extract a specified file from an archive and places\n in specified path\n- `:put`: extract the archive to a specified path, does not create any\n symbolic links\n- `:remove`: removes the extracted directory and related symlink #TODO\n- `:setup_py_build`: runs the command \"python setup.py build\" in the\n extracted directory\n- `:setup_py_install`: runs the comand \"python setup.py install\" in\n 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\ninto 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 - Example: `0775`\n- `creates`: if you are appending files to a given directory, ark\n needs a condition to test whether the file has already been\n extracted. You can specify with creates, a file whose existence\n indicates the ark has previously been extracted and does not need to\n be extracted again.\n\n## :put\n\nExtract the archive to a specified path, does not create any symbolic\nlinks.\n\n### Attribute Parameters for :put\n\n- `path`: path to extract to.\n - Default: `/usr/local`\n- `has_binaries`: array of binary commands to symlink into\n `/usr/local/bin/`, you must specify the relative path.\n - Example: `[ 'bin/java', 'bin/javaws' ]`\n- `append_env_path`: boolean, if true, append the `./bin` directory of\n the extracted directory to the global `PATH` variable for all users.\n\nAttribute Parameters\n--------------------\n\n- `name`: name of the package, defaults to the resource name.\n- `url`: url for tarball, `.tar.gz`, `.bin` (oracle-specific), `.war`,\n and `.zip` currently supported. Also supports special syntax\n `:name:version:apache_mirror:` that will auto-magically construct\n download url from the apache mirrors site.\n- `version`: software version, defaults to `1`.\n- `checksum`: sha256 checksum, used for security .\n- `mode`: file mode for `app_home`, is an integer.\n- `prefix_root`: default `prefix_root`, for use with `:install*`\n actions.\n- `prefix_home`: default directory prefix for a friendly symlink to\n the path.\n - Example: `/usr/local/maven` -> `/usr/local/maven-2.2.1`\n- `prefix_bin`: default directory to place a symlink to a binary\n command.\n - Example: `/opt/bin/mvn` -> `/opt/maven-2.2.1/bin/mvn`, where the\n `prefix_bin` is `/opt/bin`\n- `path`: path to extract the ark to. The `:install*` actions\n overwrite any user-provided values for `:path`.\n - Default: `/usr/local/-` for the `:install`,\n `:install_with_make` actions\n- `home_dir`: symbolic link to the path `:prefix_root/:name-:version`,\n does not apply to `:dump`, `:put`, or `:cherry_pick` actions.\n - Default: `:prefix_root/:name`\n- `has_binaries`: array of binary commands to symlink into\n `/usr/local/bin/`, you must specify the relative path.\n - Example: `[ 'bin/java', 'bin/javaws' ]`\n- `append_env_path`: boolean, similar to `has_binaries` but less\n granular. If true, append the `./bin` directory of the extracted\n directory to. the `PATH` environment variable for all users, by\n placing a file in `/etc/profile.d/`. The commands are symbolically\n linked into `/usr/bin/*`. This option provides more granularity than\n the boolean option.\n - Example: `mvn`, `java`, `javac`, etc.\n- `environment`: hash of environment variables to pass to invoked\n shell commands like `tar`, `unzip`, `configure`, and `make`.\n- `strip_components`: number of components in path to strip when extracting archive.\n With default value of `1`, ark strips the leading directory from an archive, \n which is the default for both `unzip` and `tar` commands.\n- `autoconf_opts`: an array of command line options for use with the\n GNU `autoconf` script.\n - Example: `[ '--include=/opt/local/include', '--force' ]`\n- `make_opts`: an array of command line options for use with `make`.\n - Example: `[ '--warn-undefined-variables', '--load-average=2' ]`\n- `owner`: owner of extracted directory.\n - Default: `root`\n\n### Examples\n\nThis example copies `ivy.tar.gz` to\n`/var/cache/chef/ivy-2.2.0.tar.gz`, unpacks its contents to\n`/usr/local/ivy-2.2.0/` -- stripping the leading directory, and\nsymlinks `/usr/local/ivy` to `/usr/local/ivy-2.2.0`\n\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\nThis example copies `jdk-7u2-linux-x64.tar.gz` to\n`/var/cache/chef/jdk-7.2.tar.gz`, unpacks its contents to\n`/usr/local/jvm/jdk-7.2/` -- stripping the leading directory, symlinks\n`/usr/local/jvm/default` to `/usr/local/jvm/jdk-7.2`, and adds\n`/usr/local/jvm/jdk-7.2/bin/` to the global `PATH` for all users. The\nuser 'foobar' is the owner of the `/usr/local/jvm/jdk-7.2` directory:\n\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\nInstall Apache Ivy dependency resolution tool in /resource_name in this case\n`/usr/local/ivy`, do not symlink, and strip any leading directory if one\nexists in the tarball:\n\n ark \"ivy\" do\n url 'http://someurl.example.com/ivy.tar.gz'\n checksum '89ba5fde0c596db388c3bbd265b63007a9cc3df3a8e6d79a46780c1a39408cb5'\n action :put\n end\n\nInstall Apache Ivy dependency resolution tool in /home/foobar/ivy, strip any\nleading directory if one exists:\n\n ark \"ivy\" do\n path \"/home/foobar\n url 'http://someurl.example.com/ivy.tar.gz'\n checksum '89ba5fde0c596db388c3bbd265b63007a9cc3df3a8e6d79a46780c1a39408cb5'\n action :put\n end\n\n Strip all directories and dump files into path specified by the path attribute.\n You must specify the `creates` attribute in order to keep the extraction from\n running every time. The directory path will be created if it doesn't already exist:\n\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\nExtract specific files from a tarball (currently only handles one named file):\n\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\nBuild and install haproxy and use alternave values for `prefix_root`, `prefix_home`, and `prefix_bin`:\n\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\nYou can also pass multiple actions to ark and supply the file extension in case\nthe file extension can not be determined by the URL:\n\n ark \"test_autogen\" do\n url 'https://github.com/zeromq/libzmq/tarball/master'\n extension \"tar.gz\"\n action [ :configure, :install_with_make ]\n end\n\nLicense and Author\n==================\n\n- Author: Philip (flip) Kromer - Infochimps, Inc()\n- Author: Bryan W. Berry ()\n- Author: Denis Barishev ()\n- Author: Sean OMeara ()\n- Copyright: 2011, Philip (flip) Kromer - Infochimps, Inc\n- Copyright: 2012, Bryan W. Berry\n- Copyright: 2012, Denis Barishev\n- Copyright: 2013, Opscode, 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", - "maintainer": "Bryan W. Berry", - "maintainer_email": "bryan.berry@gmail.com", - "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", - "windows": ">= 0.0.0" - }, - "dependencies": { - "windows": ">= 0.0.0", - "7-zip": ">= 0.0.0" - }, - "recommendations": { - }, - "suggestions": { - }, - "conflicting": { - }, - "providing": { - }, - "replacing": { - }, - "attributes": { - }, - "groupings": { - }, - "recipes": { - "ark::default": "Installs and configures ark" - } -} \ No newline at end of file +{"name":"ark","version":"1.0.1","description":"Provides a custom resource for installing runtime artifacts in a predictable fashion","long_description":"# ark cookbook\n[![Build Status](https://travis-ci.org/burtlo/ark.svg?branch=master)](https://travis-ci.org/burtlo/ark) [![Cookbook Version](https://img.shields.io/cookbook/v/ark.svg)](https://supermarket.chef.io/cookbooks/ark)\n\n## Overview\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 provider will:\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### Platforms\n- Debian/Ubuntu\n- RHEL/CentOS/Scientific/Oracle\n- Fedora\n- FreeBSD\n- SmartOS\n- Mac OS X\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- Chef 11+\n\n### Cookbooks\n- build-essential\n- seven_zip\n- windows\n\n## Attributes\nCustomize the attributes to suit site specific conventions and defaults.\n- `node['ark']['apache_mirror']` - if the URL is an apache mirror, use the attribute as the default.\n- `node['ark']['prefix_root']` - default base location if the `prefix_root` is not passed into the resource.\n- `node['ark']['prefix_bin']` - default binary location if the `prefix_bin` is not passed into the resource.\n- `node['ark']['prefix_home']` - default home location if the `prefix_home` is not passed into the resource.\n- `node['ark']['win_install_dir']` - directory where the files will be put on windows\n- `node['ark']['package_dependencies']` - prerequisite system packages that need to be installed to support ark.\n\n## Resources\n- `ark` - does the extract/build/configure dance\n\n### Actions\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 `make`, and `make install`. It does _not_ run the configure step at this time\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\nExtract a specified file from an archive and places in specified path.\n\n#### Relevant Attribute Parameters for :cherry_pick\n- `path`: directory to place file in.\n- `creates`: specific file to cherry-pick.\n\n### :dump\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- `path`: path to dump files to.\n- `mode`: file mode for `app_home`, as an integer.\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\nExtract the archive to a specified path, does not create any symbolic links.\n\n#### Attribute Parameters for :put\n- `path`: path to extract to.\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- `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 - 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 - 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 - 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 - 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 - 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 - 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- `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- `autoconf_opts`: an array of command line options for use with the GNU `autoconf` script.\n - Example: `[ '--include=/opt/local/include', '--force' ]`\n\n- `make_opts`: an array of command line options for use with `make`.\n - Example: `[ '--warn-undefined-variables', '--load-average=2' ]`\n\n- `owner`: owner of extracted directory.\n - Default: `root`\n\n#### Examples\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:\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 end\n```\n\n 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:\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 pass multiple actions to ark and 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 [ :configure, :install_with_make ]\n end\n```\n\n## License and Authors\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, 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":"Franklin Webber","maintainer_email":"frank@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","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"}} \ No newline at end of file diff --git a/cookbooks/ark/metadata.rb b/cookbooks/ark/metadata.rb deleted file mode 100644 index 6514d1c..0000000 --- a/cookbooks/ark/metadata.rb +++ /dev/null @@ -1,16 +0,0 @@ -name 'ark' -maintainer 'Bryan W. Berry' -maintainer_email 'bryan.berry@gmail.com' -license 'Apache 2.0' -description 'Installs/Configures ark' -long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) -version '0.9.0' - -%w( debian ubuntu centos redhat fedora windows ).each do |os| - supports os -end - -recipe 'ark::default', 'Installs and configures ark' - -depends 'windows' -depends '7-zip' \ No newline at end of file diff --git a/cookbooks/ark/providers/default.rb b/cookbooks/ark/providers/default.rb index 623ec64..49eafcb 100644 --- a/cookbooks/ark/providers/default.rb +++ b/cookbooks/ark/providers/default.rb @@ -3,9 +3,11 @@ # Provider:: Ark # # Author:: Bryan W. Berry -# Author:: Sean OMeara # Copyright 2012, Bryan W. Berry -# Copyright 2013, Opscode, Inc. +# Copyright 2013, 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. @@ -20,14 +22,8 @@ # limitations under the License. # -use_inline_resources if defined?(use_inline_resources) -include ::Opscode::Ark::ProviderHelpers - -# From resources/default.rb -# :install, :put, :dump, :cherry_pick, :install_with_make, :configure, :setup_py_build, :setup_py_install, :setup_py -# -# Used in test.rb -# :install, :put, :dump, :cherry_pick, :install_with_make, :configure +use_inline_resources +include ::Ark::ProviderHelpers ################# # action :install @@ -51,9 +47,8 @@ action :install do end # unpack based on file extension - _unpack_command = unpack_command execute "unpack #{new_resource.release_file}" do - command _unpack_command + command unpack_command cwd new_resource.path environment new_resource.environment notifies :run, "execute[set owner on #{new_resource.path}]" @@ -61,14 +56,13 @@ action :install do end # set_owner - _owner_command = owner_command execute "set owner on #{new_resource.path}" do - command _owner_command + command owner_command action :nothing end # usually on windows there is no central directory with executables where the applciations are linked - if not node['platform_family'] === 'windows' + 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 @@ -89,7 +83,7 @@ action :install do group 'root' mode '0755' cookbook 'ark' - variables(:directory => "#{new_resource.path}/bin") + variables(directory: "#{new_resource.path}/bin") only_if { new_resource.append_env_path } end end @@ -100,7 +94,9 @@ action :install do block do ENV['PATH'] = bin_path + ':' + ENV['PATH'] end - only_if { new_resource.append_env_path && ENV['PATH'].scan(bin_path).empty? } + only_if do + new_resource.append_env_path && ENV['PATH'].scan(bin_path).empty? + end end end @@ -126,9 +122,8 @@ action :put do end # unpack based on file extension - _unpack_command = unpack_command execute "unpack #{new_resource.release_file}" do - command _unpack_command + command unpack_command cwd new_resource.path environment new_resource.environment notifies :run, "execute[set owner on #{new_resource.path}]" @@ -136,9 +131,8 @@ action :put do end # set_owner - _owner_command = owner_command execute "set owner on #{new_resource.path}" do - command _owner_command + command owner_command action :nothing end end @@ -166,9 +160,8 @@ action :dump do end # unpack based on file extension - _dump_command = dump_command execute "unpack #{new_resource.release_file}" do - command _dump_command + command dump_command cwd new_resource.path environment new_resource.environment notifies :run, "execute[set owner on #{new_resource.path}]" @@ -176,9 +169,8 @@ action :dump do end # set_owner - _owner_command = owner_command execute "set owner on #{new_resource.path}" do - command _owner_command + command owner_command action :nothing end end @@ -206,9 +198,8 @@ action :unzip do end # unpack based on file extension - _unzip_command = unzip_command execute "unpack #{new_resource.release_file}" do - command _unzip_command + command unzip_command cwd new_resource.path environment new_resource.environment notifies :run, "execute[set owner on #{new_resource.path}]" @@ -216,9 +207,8 @@ action :unzip do end # set_owner - _owner_command = owner_command execute "set owner on #{new_resource.path}" do - command _owner_command + command owner_command action :nothing end end @@ -245,20 +235,16 @@ action :cherry_pick do notifies :run, "execute[cherry_pick #{new_resource.creates} from #{new_resource.release_file}]" end - _unpack_type = unpack_type - _cherry_pick_command = cherry_pick_command execute "cherry_pick #{new_resource.creates} from #{new_resource.release_file}" do - Chef::Log.debug("DEBUG: unpack_type: #{_unpack_type}") - command _cherry_pick_command + 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 - _owner_command = owner_command execute "set owner on #{new_resource.path}" do - command _owner_command + command owner_command action :nothing end end @@ -285,9 +271,8 @@ action :install_with_make do end # unpack based on file extension - _unpack_command = unpack_command execute "unpack #{new_resource.release_file}" do - command _unpack_command + command unpack_command cwd new_resource.path environment new_resource.environment notifies :run, "execute[set owner on #{new_resource.path}]" @@ -299,9 +284,8 @@ action :install_with_make do end # set_owner - _owner_command = owner_command execute "set owner on #{new_resource.path}" do - command _owner_command + command owner_command action :nothing end @@ -335,9 +319,132 @@ action :install_with_make do environment new_resource.environment action :nothing end +end - # unless new_resource.creates and ::File.exists? new_resource.creates - # 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 @@ -359,9 +466,8 @@ action :configure do end # unpack based on file extension - _unpack_command = unpack_command execute "unpack #{new_resource.release_file}" do - command _unpack_command + command unpack_command cwd new_resource.path environment new_resource.environment notifies :run, "execute[set owner on #{new_resource.path}]" @@ -371,9 +477,8 @@ action :configure do end # set_owner - _owner_command = owner_command execute "set owner on #{new_resource.path}" do - command _owner_command + command owner_command action :nothing end diff --git a/cookbooks/ark/recipes/default.rb b/cookbooks/ark/recipes/default.rb index 2d8fc6a..a52cc47 100644 --- a/cookbooks/ark/recipes/default.rb +++ b/cookbooks/ark/recipes/default.rb @@ -22,6 +22,4 @@ Array(node['ark']['package_dependencies']).each do |pkg| package pkg end -if node['platform_family'] === 'windows' - include_recipe "7-zip" -end \ No newline at end of file +include_recipe "seven_zip" if node['platform_family'] == 'windows' diff --git a/cookbooks/ark/recipes/test.rb b/cookbooks/ark/recipes/test.rb deleted file mode 100644 index a23f272..0000000 --- a/cookbooks/ark/recipes/test.rb +++ /dev/null @@ -1,152 +0,0 @@ -# require 'fileutils' - -# remove file so we can test sending notification on its creation - -FileUtils.rm_f '/tmp/foobarbaz/foo1.txt' if ::File.exist? '/tmp/foobarbaz/foo1.txt' - -ruby_block 'test_notification' do - block do - FileUtils.touch '/tmp/foobarbaz/notification_successful.txt' if ::File.exist? '/tmp/foobarbaz/foo1.txt' - end - action :nothing -end - -user 'foobarbaz' - -directory '/opt/bin' do - recursive true -end - -ark 'foo' do - url 'https://github.com/opscode-cookbooks/ark/raw/master/files/default/foo.tar.gz' - checksum '5996e676f17457c823d86f1605eaa44ca8a81e70d6a0e5f8e45b51e62e0c52e8' - version '2' - prefix_root '/usr/local' - owner 'foobarbaz' - group 'foobarbaz' - has_binaries ['bin/do_foo', 'bin/do_more_foo'] - action :install -end - -ark 'test_put' do - url 'https://github.com/opscode-cookbooks/ark/raw/master/files/default/foo.tar.gz' - checksum '5996e676f17457c823d86f1605eaa44ca8a81e70d6a0e5f8e45b51e62e0c52e8' - owner 'foobarbaz' - group 'foobarbaz' - action :put -end - -ark 'test_dump' do - url 'https://github.com/opscode-cookbooks/ark/raw/master/files/default/foo.zip' - checksum 'deea3a324115c9ca0f3078362f807250080bf1b27516f7eca9d34aad863a11e0' - path '/usr/local/foo_dump' - creates 'foo1.txt' - owner 'foobarbaz' - group 'foobarbaz' - action :dump -end - -ark 'cherry_pick_test' do - url 'https://github.com/opscode-cookbooks/ark/raw/master/files/default/foo.tar.gz' - checksum '5996e676f17457c823d86f1605eaa44ca8a81e70d6a0e5f8e45b51e62e0c52e8' - path '/usr/local/foo_cherry_pick' - owner 'foobarbaz' - group 'foobarbaz' - creates 'foo_sub/foo1.txt' - action :cherry_pick -end - -ark 'cherry_pick_with_zip' do - url 'https://github.com/opscode-cookbooks/ark/raw/master/files/default/foo.zip' - checksum 'deea3a324115c9ca0f3078362f807250080bf1b27516f7eca9d34aad863a11e0' - path '/usr/local/foo_cherry_pick_from_zip' - creates 'foo_sub/foo1.txt' - action :cherry_pick -end - -ark 'foo_append_env' do - version '7.0.26' - url 'https://github.com/opscode-cookbooks/ark/raw/master/files/default/foo.tar.gz' - checksum '5996e676f17457c823d86f1605eaa44ca8a81e70d6a0e5f8e45b51e62e0c52e8' - append_env_path true - action :install -end - -ark 'foo_dont_strip' do - version '2' - url 'https://github.com/opscode-cookbooks/ark/raw/master/files/default/foo.tar.gz' - checksum '5996e676f17457c823d86f1605eaa44ca8a81e70d6a0e5f8e45b51e62e0c52e8' - strip_components 0 - action :install -end - -ark 'foo_zip_strip' do - version '2' - url 'https://github.com/opscode-cookbooks/ark/raw/master/files/default/foo.zip' - checksum 'deea3a324115c9ca0f3078362f807250080bf1b27516f7eca9d34aad863a11e0' - action :install -end - -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'] - action :install_with_make -end unless platform?('freebsd') - -ark 'foo_alt_bin' do - url 'https://github.com/opscode-cookbooks/ark/raw/master/files/default/foo.tar.gz' - checksum '5996e676f17457c823d86f1605eaa44ca8a81e70d6a0e5f8e45b51e62e0c52e8' - version '3' - prefix_root '/opt' - prefix_home '/opt' - prefix_bin '/opt/bin' - owner 'foobarbaz' - group 'foobarbaz' - has_binaries ['bin/do_foo'] - action :install -end - -ark 'foo_tbz' do - url 'https://github.com/opscode-cookbooks/ark/raw/master/files/default/foo.tbz' - version '3' -end - -ark 'foo_tgz' do - url 'https://github.com/opscode-cookbooks/ark/raw/master/files/default/foo.tgz' - version '3' -end - -ark 'foo_txz' do - url 'https://github.com/opscode-cookbooks/ark/raw/master/files/default/foo.txz' - version '3' -end - -ark 'test notification' do - url 'https://github.com/opscode-cookbooks/ark/raw/master/files/default/foo.zip' - path '/tmp/foobarbaz' - creates 'foo1.txt' - action :dump - notifies :create, 'ruby_block[test_notification]', :immediately -end - -ark 'test_autogen' do - url 'https://github.com/zeromq/libzmq/tarball/master' - extension 'tar.gz' - action :configure - # autoconf in RHEL < 6 is too old - not_if { platform_family?('rhel') && node['platform_version'].to_f < 6.0 } -end - -ark 'foo_sub' do - url 'https://github.com/opscode-cookbooks/ark/raw/master/files/default/foo_sub.tar.gz' - version '1' - strip_components 2 -end - -ark 'foo_sub' do - url 'https://github.com/opscode-cookbooks/ark/raw/master/files/default/foo_sub.zip' - version '2' - strip_components 2 -end diff --git a/cookbooks/ark/resources/default.rb b/cookbooks/ark/resources/default.rb index bdf2601..9d6c14d 100644 --- a/cookbooks/ark/resources/default.rb +++ b/cookbooks/ark/resources/default.rb @@ -18,38 +18,51 @@ # limitations under the License. # -def initialize(name, run_context = nil) - super - @resource_name = :ark - @allowed_actions.push(:install, :dump, :cherry_pick, :put, :install_with_make, :configure, :setup_py_build, :setup_py_install, :setup_py, :unzip) - @action = :install - @provider = Chef::Provider::Ark -end +actions( + :cherry_pick, + :configure, + :dump, + :install, + :install_with_make, + :put, + :setup_py, + :setup_py_build, + :setup_py_install, + :unzip +) -attr_accessor :path, :release_file, :prefix_bin, :prefix_root, :home_dir, :extension, :version +default_action :install -attribute :owner, :kind_of => String, :default => 'root' -attribute :group, :kind_of => [String, Fixnum], :default => 0 -attribute :url, :kind_of => String, :required => true -attribute :path, :kind_of => String, :default => nil -attribute :full_path, :kind_of => String, :default => nil -attribute :append_env_path, :kind_of => [TrueClass, FalseClass], :default => false -attribute :checksum, :regex => /^[a-zA-Z0-9]{64}$/, :default => nil -attribute :has_binaries, :kind_of => Array, :default => [] -attribute :creates, :kind_of => String, :default => nil -attribute :release_file, :kind_of => String, :default => '' -attribute :strip_leading_dir, :kind_of => [TrueClass, FalseClass, NilClass] -attribute :strip_components, :kind_of => Integer, :default => 1 -attribute :mode, :kind_of => Fixnum, :default => 0755 -attribute :prefix_root, :kind_of => String, :default => nil -attribute :prefix_home, :kind_of => String, :default => nil -attribute :prefix_bin, :kind_of => String, :default => nil -attribute :version, :kind_of => String, :default => nil -attribute :home_dir, :kind_of => String, :default => nil -attribute :win_install_dir, :kind_of => String, :default => nil -attribute :environment, :kind_of => Hash, :default => {} -attribute :autoconf_opts, :kind_of => Array, :default => [] -attribute :make_opts, :kind_of => Array, :default => [] -attribute :home_dir, :kind_of => String, :default => nil -attribute :autoconf_opts, :kind_of => Array, :default => [] -attribute :extension, :kind_of => String +attr_accessor :extension, + :home_dir, + :path, + :prefix_bin, + :prefix_root, + :release_file, + :version + +attribute :owner, kind_of: String, default: 'root' +attribute :group, kind_of: [String, Fixnum], default: 0 +attribute :url, kind_of: String, required: true +attribute :path, kind_of: String, default: nil +attribute :full_path, kind_of: String, default: nil +attribute :append_env_path, kind_of: [TrueClass, FalseClass], default: false +attribute :checksum, regex: /^[a-zA-Z0-9]{64}$/, default: nil +attribute :has_binaries, kind_of: Array, default: [] +attribute :creates, kind_of: String, default: nil +attribute :release_file, kind_of: String, default: '' +attribute :strip_leading_dir, kind_of: [TrueClass, FalseClass, NilClass] +attribute :strip_components, kind_of: Integer, default: 1 +attribute :mode, kind_of: Fixnum, default: 0755 +attribute :prefix_root, kind_of: String, default: nil +attribute :prefix_home, kind_of: String, default: nil +attribute :prefix_bin, kind_of: String, default: nil +attribute :version, kind_of: String, default: nil +attribute :home_dir, kind_of: String, default: nil +attribute :win_install_dir, kind_of: String, default: nil +attribute :environment, kind_of: Hash, default: {} +attribute :autoconf_opts, kind_of: Array, default: [] +attribute :make_opts, kind_of: Array, default: [] +attribute :home_dir, kind_of: String, default: nil +attribute :autoconf_opts, kind_of: Array, default: [] +attribute :extension, kind_of: String diff --git a/cookbooks/ark/templates/default/add_to_path.sh.erb b/cookbooks/ark/templates/default/add_to_path.sh.erb index 1ab1bfa..ffc4e31 100644 --- a/cookbooks/ark/templates/default/add_to_path.sh.erb +++ b/cookbooks/ark/templates/default/add_to_path.sh.erb @@ -1 +1 @@ -export PATH=<%= @directory -%>:$PATH \ No newline at end of file +export PATH=<%= @directory -%>:$PATH diff --git a/cookbooks/bluepill/CHANGELOG.md b/cookbooks/bluepill/CHANGELOG.md index f8c93ca..e2da6b1 100644 --- a/cookbooks/bluepill/CHANGELOG.md +++ b/cookbooks/bluepill/CHANGELOG.md @@ -2,17 +2,45 @@ bluepill Cookbook CHANGELOG =========================== This file is used to list changes made in each version of the bluepill cookbook. +2.4.1 (11-10-2015) +------ +- Require rsyslog ~> 2.0.0 to preserve Chef 11 compatibility +- Fix rsyslog restarting on RHEL +- Use platform_family when setting platform specific node attributes and fix bad syntax. This should improve RHEL support + +v2.4.0 (09-17-2015) +------ +- Updated the LSB Required-Start and Required-Stop comments of the LSB init script template to be valid +- Added name to the bluepill_test cookbook metadata for Chef 12 +- If a defaults file on RHEL or Debian based systems exist for the service source that within the init scripts. Example if /etc/default/bar exists on debian for the bar service then source that +- Added .kitchen.yml file with vagrant based testing for local testing and moved the cloud based kitchen to .kitchen.cloud.yml +- Add Travis CI config +- Added rubocop config +- Updated Berksfile to 3.X format and removed yum cookbook that wasn't used +- Updated contributing.md and added testing.md documentation +- Updated development and testing dependencies in the Gemfile +- Added maintainers.md and .toml and added Rake task for generating the MD file +- Opscode -> Chef Software everywhere +- Added Travis and cookbook version badges to the readme +- Add rake file to easy testing +- Resolved all Rubocop warnings +- Added a chefignore file and added additional files to the gitignore +- Added source_url and issues_url metadata for Supermarket + +v2.3.2 +------ +- Never actually released v2.3.1 ------ ### New Feature -- **[COOK-3705](https://tickets.opscode.com/browse/COOK-3705)** - Add init.d script with LSB style +- **[COOK-3705](https://tickets.chef.io/browse/COOK-3705)** - Add init.d script with LSB style v2.3.0 ------ ### Improvement -- **[COOK-3503](https://tickets.opscode.com/browse/COOK-3503)** - Add why-run support +- **[COOK-3503](https://tickets.chef.io/browse/COOK-3503)** - Add why-run support v2.2.2 ------ diff --git a/cookbooks/bluepill/README.md b/cookbooks/bluepill/README.md index 3bb173a..7efe25d 100644 --- a/cookbooks/bluepill/README.md +++ b/cookbooks/bluepill/README.md @@ -1,12 +1,23 @@ bluepill Cookbook ================= -Installs bluepill RubyGem and configures it to manage services. Also includes a LWRP. + +[![Build Status](https://travis-ci.org/chef-cookbooks/bluepill.svg?branch=master)](https://travis-ci.org/chef-cookbooks/bluepill) +[![Cookbook Version](https://img.shields.io/cookbook/v/bluepill.svg)](https://supermarket.chef.io/cookbooks/bluepill) + +Installs bluepill Ruby Gem and configures it to manage services. Also includes a LWRP. Requirements ------------ +#### Platforms Bluepill is a pure Ruby service management tool/library, so this cookbook should work on any system. The attributes do set up paths based on FHS locations, see below. +#### Chef +- Chef 11+ + +#### Cookbooks +- none + Attributes ---------- @@ -68,11 +79,12 @@ See bluepill's documentation for more information on creating pill templates. License & Authors ----------------- -- Author:: Joshua Timberman () -```text -Copyright 2010-2013, Opscode, Inc. +**Author:** Cookbook Engineering Team () +**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 diff --git a/cookbooks/bluepill/attributes/default.rb b/cookbooks/bluepill/attributes/default.rb index b857d19..abbff66 100644 --- a/cookbooks/bluepill/attributes/default.rb +++ b/cookbooks/bluepill/attributes/default.rb @@ -1,7 +1,7 @@ # Cookbook Name:: bluepill # Attributes:: default # -# Copyright 2010, Opscode, Inc. +# 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. @@ -15,21 +15,30 @@ # See the License for the specific language governing permissions and # limitations under the License. -default["bluepill"]["bin"] = "#{node['languages']['ruby']['bin_dir']}/bluepill" -default["bluepill"]["logfile"] = "/var/log/bluepill.log" -default["bluepill"]["pid_dir"] = "/var/run/bluepill" -default["bluepill"]["state_dir"] = "/var/lib/bluepill" -default["bluepill"]["group"] = 0 -default["bluepill"]["use_rsyslog"] = false +default['bluepill']['bin'] = "#{node['languages']['ruby']['bin_dir']}/bluepill" +default['bluepill']['logfile'] = '/var/log/bluepill.log' +default['bluepill']['pid_dir'] = '/var/run/bluepill' +default['bluepill']['state_dir'] = '/var/lib/bluepill' +default['bluepill']['group'] = 0 +default['bluepill']['use_rsyslog'] = false -case platform -when "arch" - default["bluepill"]["init_dir"] = "/etc/rc.d" - default["bluepill"]["conf_dir"] = "/etc/bluepill" -when "freebsd" - default["bluepill"]["init_dir"] = "/usr/local/etc/rc.d" - default["bluepill"]["conf_dir"] = "/usr/local/etc/bluepill" +case node['platform_family'] +when 'arch' + default['bluepill']['init_dir'] = '/etc/rc.d' + default['bluepill']['conf_dir'] = '/etc/bluepill' + default['bluepill']['defaults_dir'] = '/etc/default' +when 'freebsd' + default['bluepill']['init_dir'] = '/usr/local/etc/rc.d' + default['bluepill']['conf_dir'] = '/usr/local/etc/bluepill' + default['bluepill']['defaults_dir'] = '/etc/defaults' else - default["bluepill"]["init_dir"] = "/etc/init.d" - default["bluepill"]["conf_dir"] = "/etc/bluepill" + default['bluepill']['init_dir'] = '/etc/init.d' + default['bluepill']['conf_dir'] = '/etc/bluepill' +end + +case node['platform_family'] +when 'fedora', 'rhel' + default['bluepill']['defaults_dir'] = '/etc/sysconfig' +when 'debian' + default['bluepill']['defaults_dir'] = '/etc/default' end diff --git a/cookbooks/bluepill/metadata.json b/cookbooks/bluepill/metadata.json index 61515e9..6227366 100644 --- a/cookbooks/bluepill/metadata.json +++ b/cookbooks/bluepill/metadata.json @@ -1,31 +1 @@ -{ - "name": "bluepill", - "version": "2.3.1", - "description": "Installs bluepill gem and configures to manage services, includes bluepill_service LWRP", - "long_description": "bluepill Cookbook\n=================\nInstalls bluepill RubyGem and configures it to manage services. Also includes a LWRP.\n\n\nRequirements\n------------\nBluepill is a pure Ruby service management tool/library, so this cookbook should work on any system. The attributes do set up paths based on FHS locations, see below.\n\n\nAttributes\n----------\nDefault locations for bluepill are in \"FHS compliant\" locations.\n\n* `node[\"bluepill\"][\"bin\"]` - Path to bluepill program, default is 'bluepill' in the RubyGems binary directory.\n* `node[\"bluepill\"][\"logfile\"]` - Location of the bluepill log file, default \"/var/log/bluepill.log\".\n* `node[\"bluepill\"][\"conf_dir\"]` - Location of service config files (pills), default \"/etc/bluepill\".\n* `node[\"bluepill\"][\"pid_dir\"]` - Location of pidfiles, default \"/var/run/bluepill\"\n* `node[\"bluepill\"][\"state_dir\"]` - Location of state directory, default \"/var/lib/bluepill\"\n* `node[\"bluepill\"][\"init_dir\"]` - Location of init script directory, default selected by platform.\n* `node[\"bluepill\"][\"version\"]` - Version of bluepill to install, default is latest.\n* `node[\"bluepill\"][\"use_rsyslog\"]` - Enable configuration and use of rsyslog for bluepill.\n\n\nResources/Providers\n-------------------\nThis cookbook contains an LWRP, `bluepill_service`. This can be used with the normal Chef service resource, by using the `provider` parameter, or by specifying the `bluepill_service` shortcut. These two resources are equivalent.\n\n```ruby\nservice 'my_app' do\n provider bluepill_service\n action [:enable, :load, :start]\nend\n\nbluepill_service 'my_app' do\n action [:enable, :load, :start]\nend\n```\n\nThe load action should probably always be specified, to ensure that if bluepill isn't running already it gets started. The\n\nThe recipe using the service must contain a template resource for the pill and it must be named `my_app.pill.erb`, where `my_app` is the service name passed to the bluepill service resource.\n\n\nUsage\n-----\nBe sure to include the bluepill recipe in the run list to ensure that the gem and bluepill-related directories are created. This will also make the cookbook available on the system and other cookbooks won't need to explicitly depend on it in the metadata.\n\nIf the default directory locations in the attributes/default.rb aren't what you want, change them by setting them either in the attributes file itself, or create attributes in a role applied to any systems that will use bluepill.\n\nExample pill template resource and .erb file:\n\n```ruby\ntemplate '/etc/bluepill/my_app.pill' do\n source 'my_app.pill.erb'\nend\n\nBluepill.application('my_app') do |app|\n app.process('my_app') do |process|\n process.pid_file = '/var/run/my_app.pid'\n process.start_command = '/usr/bin/my_app'\n end\nend\n```\n\nSee bluepill's documentation for more information on creating pill templates.\n\n\nLicense & Authors\n-----------------\n- Author:: Joshua Timberman ()\n\n```text\nCopyright 2010-2013, Opscode, 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": "Opscode, Inc.", - "maintainer_email": "cookbooks@opscode.com", - "license": "Apache 2.0", - "platforms": { - }, - "dependencies": { - "rsyslog": ">= 0.0.0" - }, - "recommendations": { - }, - "suggestions": { - }, - "conflicting": { - }, - "providing": { - }, - "replacing": { - }, - "attributes": { - }, - "groupings": { - }, - "recipes": { - "bluepill::default": "Installs bluepill rubygem and set up management directories" - } -} \ No newline at end of file +{"name":"bluepill","version":"2.4.1","description":"Installs bluepill gem and configures to manage services, includes bluepill_service LWRP","long_description":"bluepill Cookbook\n=================\n\n[![Build Status](https://travis-ci.org/chef-cookbooks/bluepill.svg?branch=master)](https://travis-ci.org/chef-cookbooks/bluepill)\n[![Cookbook Version](https://img.shields.io/cookbook/v/bluepill.svg)](https://supermarket.chef.io/cookbooks/bluepill)\n\nInstalls bluepill Ruby Gem and configures it to manage services. Also includes a LWRP.\n\n\nRequirements\n------------\n#### Platforms\nBluepill is a pure Ruby service management tool/library, so this cookbook should work on any system. The attributes do set up paths based on FHS locations, see below.\n\n#### Chef\n- Chef 11+\n\n#### Cookbooks\n- none\n\n\nAttributes\n----------\nDefault locations for bluepill are in \"FHS compliant\" locations.\n\n* `node[\"bluepill\"][\"bin\"]` - Path to bluepill program, default is 'bluepill' in the RubyGems binary directory.\n* `node[\"bluepill\"][\"logfile\"]` - Location of the bluepill log file, default \"/var/log/bluepill.log\".\n* `node[\"bluepill\"][\"conf_dir\"]` - Location of service config files (pills), default \"/etc/bluepill\".\n* `node[\"bluepill\"][\"pid_dir\"]` - Location of pidfiles, default \"/var/run/bluepill\"\n* `node[\"bluepill\"][\"state_dir\"]` - Location of state directory, default \"/var/lib/bluepill\"\n* `node[\"bluepill\"][\"init_dir\"]` - Location of init script directory, default selected by platform.\n* `node[\"bluepill\"][\"version\"]` - Version of bluepill to install, default is latest.\n* `node[\"bluepill\"][\"use_rsyslog\"]` - Enable configuration and use of rsyslog for bluepill.\n\n\nResources/Providers\n-------------------\nThis cookbook contains an LWRP, `bluepill_service`. This can be used with the normal Chef service resource, by using the `provider` parameter, or by specifying the `bluepill_service` shortcut. These two resources are equivalent.\n\n```ruby\nservice 'my_app' do\n provider bluepill_service\n action [:enable, :load, :start]\nend\n\nbluepill_service 'my_app' do\n action [:enable, :load, :start]\nend\n```\n\nThe load action should probably always be specified, to ensure that if bluepill isn't running already it gets started. The\n\nThe recipe using the service must contain a template resource for the pill and it must be named `my_app.pill.erb`, where `my_app` is the service name passed to the bluepill service resource.\n\n\nUsage\n-----\nBe sure to include the bluepill recipe in the run list to ensure that the gem and bluepill-related directories are created. This will also make the cookbook available on the system and other cookbooks won't need to explicitly depend on it in the metadata.\n\nIf the default directory locations in the attributes/default.rb aren't what you want, change them by setting them either in the attributes file itself, or create attributes in a role applied to any systems that will use bluepill.\n\nExample pill template resource and .erb file:\n\n```ruby\ntemplate '/etc/bluepill/my_app.pill' do\n source 'my_app.pill.erb'\nend\n\nBluepill.application('my_app') do |app|\n app.process('my_app') do |process|\n process.pid_file = '/var/run/my_app.pid'\n process.start_command = '/usr/bin/my_app'\n end\nend\n```\n\nSee bluepill's documentation for more information on creating pill templates.\n\n\nLicense & Authors\n-----------------\n\n**Author:** Cookbook Engineering Team ()\n\n**Copyright:** 2010-2015, 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":{},"dependencies":{"rsyslog":"~> 2.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{"bluepill::default":"Installs bluepill rubygem and sets up management directories"}} \ No newline at end of file diff --git a/cookbooks/bluepill/metadata.rb b/cookbooks/bluepill/metadata.rb deleted file mode 100644 index d0975d8..0000000 --- a/cookbooks/bluepill/metadata.rb +++ /dev/null @@ -1,10 +0,0 @@ -name "bluepill" -maintainer "Opscode, Inc." -maintainer_email "cookbooks@opscode.com" -license "Apache 2.0" -description "Installs bluepill gem and configures to manage services, includes bluepill_service LWRP" -long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) -version "2.3.1" -recipe "bluepill::default", "Installs bluepill rubygem and set up management directories" - -depends "rsyslog" diff --git a/cookbooks/bluepill/providers/service.rb b/cookbooks/bluepill/providers/service.rb index f1e9c74..45e55f1 100644 --- a/cookbooks/bluepill/providers/service.rb +++ b/cookbooks/bluepill/providers/service.rb @@ -2,7 +2,7 @@ # Cookbook Name:: bluepill # Provider:: service # -# Copyright 2010, Opscode, Inc. +# Copyright 2010-2015, Chef Software, Inc. # Copyright 2012, Heavy Water Operations, LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,31 +31,30 @@ action :enable do config_file = ::File.join(node['bluepill']['conf_dir'], "#{new_resource.service_name}.pill") unless @current_resource.enabled - converge_by("enable #{ @new_resource }") do + converge_by("enable #{@new_resource}") do link "#{node['bluepill']['init_dir']}/#{new_resource.service_name}" do to node['bluepill']['bin'] - only_if { ::File.exists?(config_file) } + only_if { ::File.exist?(config_file) } end template_suffix = case node['platform_family'] - when "rhel", "fedora", "freebsd" then node['platform_family'] + when 'rhel', 'fedora', 'freebsd' then node['platform_family'] when 'debian' then 'lsb' - else nil end template "#{node['bluepill']['init_dir']}/bluepill-#{new_resource.service_name}" do source "bluepill_init.#{template_suffix}.erb" - cookbook "bluepill" - owner "root" + cookbook 'bluepill' + owner 'root' group node['bluepill']['group'] - mode "0755" + mode '0755' variables( - :service_name => new_resource.service_name, - :config_file => config_file - ) + service_name: new_resource.service_name, + config_file: config_file + ) end if template_suffix service "bluepill-#{new_resource.service_name}" do - action [ :enable ] + action [:enable] end end end @@ -63,14 +62,14 @@ end action :load do unless @current_resource.running - converge_by("load #{ @new_resource }") do + converge_by("load #{@new_resource}") do shell_out!(load_command) end end end action :reload do - converge_by("reload #{ @new_resource }") do + converge_by("reload #{@new_resource}") do shell_out!(stop_command) if @current_resource.running shell_out!(load_command) end @@ -78,7 +77,7 @@ end action :start do unless @current_resource.running - converge_by("start #{ @new_resource }") do + converge_by("start #{@new_resource}") do shell_out!(start_command) end end @@ -86,7 +85,7 @@ end action :disable do if @current_resource.enabled - converge_by("disable #{ @new_resource }") do + converge_by("disable #{@new_resource}") do file "#{node['bluepill']['conf_dir']}/#{new_resource.service_name}.pill" do action :delete end @@ -99,7 +98,7 @@ end action :stop do if @current_resource.running - converge_by("stop #{ @new_resource }") do + converge_by("stop #{@new_resource}") do shell_out!(stop_command) end end @@ -107,7 +106,7 @@ end action :restart do if @current_resource.running - converge_by("restart #{ @new_resource }") do + converge_by("restart #{@new_resource}") do Chef::Log.debug "Restarting #{new_resource.service_name}" shell_out!(restart_command) Chef::Log.debug "Restarted #{new_resource.service_name}" @@ -154,20 +153,18 @@ def determine_current_status! end def service_running? - begin - if shell_out(status_command).exitstatus == 0 - @current_resource.running true - Chef::Log.debug("#{new_resource} is running") - end - rescue Mixlib::ShellOut::ShellCommandFailed, SystemCallError - @current_resource.running false - nil + if shell_out(status_command).exitstatus == 0 + @current_resource.running true + Chef::Log.debug("#{new_resource} is running") end +rescue Mixlib::ShellOut::ShellCommandFailed, SystemCallError + @current_resource.running false + nil end def service_enabled? - if ::File.exists?("#{node['bluepill']['conf_dir']}/#{new_resource.service_name}.pill") && - ::File.symlink?("#{node['bluepill']['init_dir']}/#{new_resource.service_name}") + if ::File.exist?("#{node['bluepill']['conf_dir']}/#{new_resource.service_name}.pill") && + ::File.symlink?("#{node['bluepill']['init_dir']}/#{new_resource.service_name}") @current_resource.enabled true else @current_resource.enabled false diff --git a/cookbooks/bluepill/recipes/default.rb b/cookbooks/bluepill/recipes/default.rb index 4b11c3b..0ef7b4a 100644 --- a/cookbooks/bluepill/recipes/default.rb +++ b/cookbooks/bluepill/recipes/default.rb @@ -2,7 +2,7 @@ # Cookbook Name:: bluepill # Recipe:: default # -# Copyright 2010, Opscode, Inc. +# 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. @@ -17,32 +17,29 @@ # limitations under the License. # -gem_package "i18n" do - action :install -end +gem_package 'i18n' -gem_package "bluepill" do - version node["bluepill"]["version"] if node["bluepill"]["version"] - action :install +gem_package 'bluepill' do + version node['bluepill']['version'] if node['bluepill']['version'] end [ - node["bluepill"]["conf_dir"], - node["bluepill"]["pid_dir"], - node["bluepill"]["state_dir"] + node['bluepill']['conf_dir'], + node['bluepill']['pid_dir'], + node['bluepill']['state_dir'] ].each do |dir| directory dir do recursive true - owner "root" - group node["bluepill"]["group"] + owner 'root' + group node['bluepill']['group'] end end -file node["bluepill"]["logfile"] do - owner "root" - group node["bluepill"]["group"] - mode "0755" +file node['bluepill']['logfile'] do + owner 'root' + group node['bluepill']['group'] + mode '0755' action :create_if_missing end -include_recipe "bluepill::rsyslog" if node['bluepill']['use_rsyslog'] +include_recipe 'bluepill::rsyslog' if node['bluepill']['use_rsyslog'] diff --git a/cookbooks/bluepill/recipes/rsyslog.rb b/cookbooks/bluepill/recipes/rsyslog.rb index a19113b..ea7ad77 100644 --- a/cookbooks/bluepill/recipes/rsyslog.rb +++ b/cookbooks/bluepill/recipes/rsyslog.rb @@ -2,7 +2,7 @@ # Cookbook Name:: bluepill # Recipe:: rsyslog # -# Copyright 2010, Opscode, Inc. +# 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. @@ -17,12 +17,12 @@ # limitations under the License. # -include_recipe "rsyslog" +include_recipe 'rsyslog::default' -template "/etc/rsyslog.d/bluepill.conf" do - owner "root" - group "root" - mode 0644 - source "bluepill_rsyslog.conf.erb" - notifies :restart, "service[rsyslog]" +template '/etc/rsyslog.d/bluepill.conf' do + owner 'root' + group 'root' + mode '0644' + source 'bluepill_rsyslog.conf.erb' + notifies :restart, "service[#{node['rsyslog']['service_name']}]" end diff --git a/cookbooks/bluepill/resources/service.rb b/cookbooks/bluepill/resources/service.rb index e810fe1..af93fe4 100644 --- a/cookbooks/bluepill/resources/service.rb +++ b/cookbooks/bluepill/resources/service.rb @@ -2,7 +2,7 @@ # Cookbook Name:: bluepill # Resource:: service # -# Copyright 2010, Opscode, Inc. +# 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. @@ -20,8 +20,8 @@ actions :start, :stop, :enable, :disable, :load, :restart, :reload default_action :start -attribute :service_name, :name_attribute => true -attribute :enabled, :default => false -attribute :running, :default => false -attribute :variables, :kind_of => Hash -attribute :supports, :default => { :restart => true, :status => true } +attribute :service_name, name_attribute: true +attribute :enabled, default: false +attribute :running, default: false +attribute :variables, kind_of: Hash +attribute :supports, default: { restart: true, status: true } diff --git a/cookbooks/bluepill/templates/default/bluepill_init.fedora.erb b/cookbooks/bluepill/templates/default/bluepill_init.fedora.erb index 0044bc4..2731a17 100644 --- a/cookbooks/bluepill/templates/default/bluepill_init.fedora.erb +++ b/cookbooks/bluepill/templates/default/bluepill_init.fedora.erb @@ -12,6 +12,8 @@ BLUEPILL_BIN=<%= node['bluepill']['bin'] %> BLUEPILL_CONFIG=<%= @config_file %> SERVICE_NAME=<%= @service_name %> +[ -r <%= node['bluepill']['defaults_dir'] %>/$SERVICE_NAME ] && . <%= node['bluepill']['defaults_dir'] %>/$SERVICE_NAME + case "$1" in start) echo "Loading bluepill configuration for $SERVICE_NAME " diff --git a/cookbooks/bluepill/templates/default/bluepill_init.freebsd.erb b/cookbooks/bluepill/templates/default/bluepill_init.freebsd.erb index a85613f..697e407 100644 --- a/cookbooks/bluepill/templates/default/bluepill_init.freebsd.erb +++ b/cookbooks/bluepill/templates/default/bluepill_init.freebsd.erb @@ -24,6 +24,7 @@ status_cmd="${command} ${name} status" stop_cmd="${command} ${name} stop" stop_postcmd="${command} ${name} quit" +[ -r <%= node['bluepill']['defaults_dir'] %>/$name ] && . <%= node['bluepill']['defaults_dir'] %>/$name load_rc_config ${name} PATH="${PATH}:/usr/local/bin" diff --git a/cookbooks/bluepill/templates/default/bluepill_init.lsb.erb b/cookbooks/bluepill/templates/default/bluepill_init.lsb.erb index a49edc4..cd8b95f 100644 --- a/cookbooks/bluepill/templates/default/bluepill_init.lsb.erb +++ b/cookbooks/bluepill/templates/default/bluepill_init.lsb.erb @@ -2,7 +2,8 @@ # ### BEGIN INIT INFO # Provides: <%= @service_name %> -# Required-Start: bar +# Required-Start: +# Required-Stop: # Defalt-Start: 2 3 4 5 # Default-Stop: 0 1 2 6 # Description: Bluepill loader for <%= @service_name %> @@ -12,6 +13,8 @@ BLUEPILL_BIN=<%= node['bluepill']['bin'] %> BLUEPILL_CONFIG=<%= @config_file %> SERVICE_NAME=<%= @service_name %> +[ -r <%= node['bluepill']['defaults_dir'] %>/$SERVICE_NAME ] && . <%= node['bluepill']['defaults_dir'] %>/$SERVICE_NAME + case "$1" in start) echo "Loading bluepill configuration for $SERVICE_NAME " diff --git a/cookbooks/bluepill/templates/default/bluepill_init.rhel.erb b/cookbooks/bluepill/templates/default/bluepill_init.rhel.erb index 0044bc4..2731a17 100644 --- a/cookbooks/bluepill/templates/default/bluepill_init.rhel.erb +++ b/cookbooks/bluepill/templates/default/bluepill_init.rhel.erb @@ -12,6 +12,8 @@ BLUEPILL_BIN=<%= node['bluepill']['bin'] %> BLUEPILL_CONFIG=<%= @config_file %> SERVICE_NAME=<%= @service_name %> +[ -r <%= node['bluepill']['defaults_dir'] %>/$SERVICE_NAME ] && . <%= node['bluepill']['defaults_dir'] %>/$SERVICE_NAME + case "$1" in start) echo "Loading bluepill configuration for $SERVICE_NAME " diff --git a/cookbooks/chef-sugar/CHANGELOG.md b/cookbooks/chef-sugar/CHANGELOG.md index d0a52d5..1925309 100644 --- a/cookbooks/chef-sugar/CHANGELOG.md +++ b/cookbooks/chef-sugar/CHANGELOG.md @@ -2,6 +2,36 @@ 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 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 index 8b43ec4..fd9785a 100644 --- a/cookbooks/chef-sugar/README.md +++ b/cookbooks/chef-sugar/README.md @@ -4,7 +4,7 @@ Chef Sugar [![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-suguar +[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! @@ -82,6 +82,7 @@ API - `sparc?` - `ppc64?` - `ppc64le?` +- `powerpc?` #### Examples ```ruby @@ -249,6 +250,31 @@ class Chef 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. @@ -296,6 +322,9 @@ node.deep_fetch('apache2', 'config', 'root') => node['apache2']['config']['root' - `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: @@ -334,6 +363,7 @@ end - `slackware?` - `suse?` - `windows?` +- `wrlinux?` #### Examples ```ruby @@ -404,6 +434,7 @@ end - `lxc?` - `virtualbox?` - `vmware?` +- `openvz?` #### Examples ```ruby diff --git a/cookbooks/chef-sugar/metadata.json b/cookbooks/chef-sugar/metadata.json index 9f93a59..21028c7 100644 --- a/cookbooks/chef-sugar/metadata.json +++ b/cookbooks/chef-sugar/metadata.json @@ -1,29 +1 @@ -{ - "name": "chef-sugar", - "version": "3.1.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 +{"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 index 89200b8..93256c7 100644 --- a/cookbooks/chef-sugar/recipes/default.rb +++ b/cookbooks/chef-sugar/recipes/default.rb @@ -19,9 +19,16 @@ gem_version = run_context.cookbook_collection[cookbook_name].metadata.version -chef_gem('chef-sugar') do - version gem_version - action :nothing -end.run_action(:install) +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/chef_handler/CHANGELOG.md b/cookbooks/chef_handler/CHANGELOG.md index 2aa532f..707ca43 100644 --- a/cookbooks/chef_handler/CHANGELOG.md +++ b/cookbooks/chef_handler/CHANGELOG.md @@ -1,56 +1,56 @@ -chef_handler cookbook CHANGELOG -=============================== +# chef_handler cookbook CHANGELOG +This file is used to list changes made in each version of the chef_handler cookbook. -v1.1.9 (2015-05-26) -------------------- -Bugfixes from 1.1.8 - loading without source is not allowed again. -Class unloading is performed more carefully. -Tests for resource providers. +## v1.3.0 (2016-02-16) +- Added state attributes to the custom resource +- Added source_url and issues_url to metadata.rb +- Replaced attributes for root user and group with the Ohai defined values to simplify the logic of the cookbook +- Added lint, unit, and itegration testing in Travis CI +- Added Test Kitchen testing of the recipes and the custom resource via a test cookbook +- Added Berksfile +- Added chefignore and .gitignore files +- Added .rubocop.yml config and resolve multiple issues +- Updated contributing and testing docs to the latest +- Added all testing dependencies to the Gemfile +- Added maintainers.md and maintainers.toml files +- Expanded the Rakefile for simplified testing -v1.1.8 (2015-05-14) -------------------- -Updated Contribution and Readme docs. -Fix ChefSpec matchers. -Allow handler to load classes when no source is provided. +## v1.2.0 (2015-06-25) +- Move to support Chef 12+ only. Removes old 'handler class reload' behavior - it isn't necessary because chef-client forks and doesn't share a process between runs. -v1.1.6 (2014-04-09) -------------------- -[COOK-4494] - Add ChefSpec matchers +## v1.1.9 (2015-05-26) +- Bugfixes from 1.1.8 - loading without source is not allowed again. Class unloading is performed more carefully. Tests for resource providers. +## v1.1.8 (2015-05-14) +- Updated Contribution and Readme docs +- Fix ChefSpec matchers +- Allow handler to load classes when no source is provided. -v1.1.5 (2014-02-25) -------------------- +## v1.1.6 (2014-04-09) +- [COOK-4494] - Add ChefSpec matchers + +## v1.1.5 (2014-02-25) - [COOK-4117] - use the correct scope when searching the children class name - -v1.1.4 ------- +## v1.1.4 - [COOK-2146] - style updates -v1.1.2 ---------- +## v1.1.2 - [COOK-1989] - fix scope for handler local variable to the enable block -v1.1.0 ------- - +## v1.1.0 - [COOK-1645] - properly delete old handlers - [COOK-1322] - support platforms that use 'wheel' as root group' -v1.0.8 ------- +## v1.0.8 - [COOK-1177] - doesn't work on windows due to use of unix specific attributes -v1.0.6 ------- +## v1.0.6 - [COOK-1069] - typo in chef_handler readme -v1.0.4 ------- +## v1.0.4 - [COOK-654] dont try and access a class before it has been loaded - fix bad boolean check (if vs unless) -v1.0.2 ------- +## v1.0.2 - [COOK-620] ensure handler code is reloaded during daemonized chef runs - diff --git a/cookbooks/chef_handler/CONTRIBUTING.md b/cookbooks/chef_handler/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/chef_handler/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/chef_handler/MAINTAINERS.md b/cookbooks/chef_handler/MAINTAINERS.md new file mode 100644 index 0000000..c6a51ae --- /dev/null +++ b/cookbooks/chef_handler/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 +* [Tim Smith](https://github.com/tas50) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Sean OMeara](https://github.com/someara) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) diff --git a/cookbooks/chef_handler/README.md b/cookbooks/chef_handler/README.md index 4f13d39..75ec337 100644 --- a/cookbooks/chef_handler/README.md +++ b/cookbooks/chef_handler/README.md @@ -1,41 +1,40 @@ -Description -=========== +# chef_handler Cookbook +[![Build Status](https://travis-ci.org/chef-cookbooks/chef_handler.svg?branch=master)](https://travis-ci.org/chef-cookbooks/chef_handler) [![Cookbook Version](https://img.shields.io/cookbook/v/chef_handler.svg)](https://supermarket.chef.io/cookbooks/chef_handler) Creates a configured handler path for distributing [Chef report and exception handlers](http://docs.chef.io/handlers.html). Also exposes an LWRP for enabling Chef handlers from within recipe code (as opposed to hard coding in the client.rb file). This is useful for cookbook authors who may want to ship a product specific handler (see the `cloudkick` cookbook for an example) with their cookbook. -Requirements -============ +## Requirements +### Platforms +- Debian/Ubuntu +- RHEL/CentOS/Scientific/Amazon/Oracle +- Windows -* Ruby >= 1.9 +### Chef +- Chef 11+ -Attributes -========== +### Cookbooks +- none -`node["chef_handler"]["handler_path"]` - location to drop off handlers directory, default is `/var/chef/handlers`. - -Resource/Provider -================= - -`chef_handler` --------------- +## Attributes +`node['chef_handler']['handler_path']` - location to drop off handlers directory, default is a folder named 'handlers' in Chef's file cache directory +## Custom Resources +### chef_handler Requires, configures and enables handlers on the node for the current Chef run. Also has the ability to pass arguments to the handlers initializer. This allows initialization data to be pulled from a node's attribute data. It is best to declare `chef_handler` resources early on in the compile phase so they are available to fire for any exceptions during the Chef run. If you have a base role you would want any recipes that register Chef handlers to come first in the run_list. -### Actions +#### Actions +- `:enable:` Enables the Chef handler for the current Chef run on the current node +- `:disable:` Disables the Chef handler for the current Chef run on the current node -- :enable: Enables the Chef handler for the current Chef run on the current node -- :disable: Disables the Chef handler for the current Chef run on the current node +#### Attribute Parameters +- `class_name:` name attribute. The name of the handler class (can be module name-spaced). +- `source:` full path to the handler file. can also be a gem path if the handler ships as part of a Ruby gem. +- `arguments:` an array of arguments to pass the handler's class initializer +- `supports:` type of Chef Handler to register as, i.e. :report, :exception or both. default is `:report => true, :exception => true` -### Attribute Parameters - -- class_name: name attribute. The name of the handler class (can be module name-spaced). -- source: full path to the handler file. can also be a gem path if the handler ships as part of a Ruby gem. -- arguments: an array of arguments to pass the handler's class initializer -- supports: type of Chef Handler to register as, i.e. :report, :exception or both. default is `:report => true, :exception => true` - -### Example +#### Example ```ruby # register the Chef::Handler::JsonFile handler @@ -73,30 +72,18 @@ It is best to declare `chef_handler` resources early on in the compile phase so end ``` - -Usage -===== - -default -------- - +## Usage +### default Put the recipe `chef_handler` at the start of the node's run list to make sure that custom handlers are dropped off early on in the Chef run and available for later recipes. -For information on how to write report and exception handlers for Chef, please see the Chef wiki pages: -http://wiki.chef.io/display/chef/Exception+and+Report+Handlers - -json_file ---------- +For information on how to write report and exception handlers for Chef, please see the Chef wiki pages: [https://docs.chef.io/handlers.html](https://docs.chef.io/handlers.html) +### json_file Leverages the `chef_handler` LWRP to automatically register the `Chef::Handler::JsonFile` handler that ships as part of Chef. This handler serializes the run status data to a JSON file located at `/var/chef/reports`. - -Unit Testing -================== - +## Unit Testing chef_handler provides built in [chefspec](https://github.com/sethvargo/chefspec) matchers for assisting unit tests. These matchers will only be loaded if chefspec is already loaded. Following is an example of asserting against the jsonfile handler: - ```ruby expect(runner).to enable_chef_handler("Chef::Handler::JsonFile").with( source: "chef/handler/json_file", @@ -106,13 +93,12 @@ chef_handler provides built in [chefspec](https://github.com/sethvargo/chefspec) end ``` -License and Author -================== +## License & Authors +**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io)) -Author:: Seth Chisamore () - -Copyright:: 2011, Chef Software, Inc +**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 @@ -124,3 +110,4 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 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_handler/attributes/default.rb b/cookbooks/chef_handler/attributes/default.rb index e4a7b8c..1a97bcd 100644 --- a/cookbooks/chef_handler/attributes/default.rb +++ b/cookbooks/chef_handler/attributes/default.rb @@ -1,9 +1,9 @@ # # Author:: Seth Chisamore () -# Cookbook Name:: chef_handlers -# Attribute:: default +# Cookbook Name:: chef_handler +# Attributes:: default # -# Copyright 2011-2013, Chef Software, Inc +# 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. @@ -18,13 +18,4 @@ # limitations under the License. # -default["chef_handler"]["root_user"] = "root" - -case platform -when "openbsd", "freebsd", "mac_os_x", "mac_os_x_server" - default["chef_handler"]["root_group"] = "wheel" -else - default["chef_handler"]["root_group"] = "root" -end - -default["chef_handler"]["handler_path"] = "#{File.expand_path(File.join(Chef::Config[:file_cache_path], '..'))}/handlers" +default['chef_handler']['handler_path'] = "#{File.expand_path(File.join(Chef::Config[:file_cache_path], '..'))}/handlers" diff --git a/cookbooks/chef_handler/libraries/helpers.rb b/cookbooks/chef_handler/libraries/helpers.rb index f633eab..2f36aa6 100644 --- a/cookbooks/chef_handler/libraries/helpers.rb +++ b/cookbooks/chef_handler/libraries/helpers.rb @@ -1,6 +1,6 @@ # # Author:: Kartik Cating-Subramanian () -# Copyright:: Copyright (c) 2015 Chef, Inc. +# Copyright:: Copyright (c) 2015-2016 Chef Software, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,17 +15,15 @@ # See the License for the specific language governing permissions and # limitations under the License. - module ChefHandler module Helpers - # Registers a handler in Chef::Config. # # @param handler_type [Symbol] such as :report or :exception. # @param handler [Chef::Handler] handler to register. def register_handler(handler_type, handler) Chef::Log.info("Enabling #{handler.class.name} as a #{handler_type} handler.") - Chef::Config.send("#{handler_type.to_s}_handlers") << handler + Chef::Config.send("#{handler_type}_handlers") << handler end # Removes all handlers that match the given class name in Chef::Config. @@ -34,7 +32,7 @@ module ChefHandler # @param class_full_name [String] such as 'Chef::Handler::ErrorReport'. def unregister_handler(handler_type, class_full_name) Chef::Log.info("Disabling #{class_full_name} as a #{handler_type} handler.") - Chef::Config.send("#{handler_type.to_s}_handlers").delete_if { |v| v.class.name == class_full_name } + Chef::Config.send("#{handler_type}_handlers").delete_if { |v| v.class.name == class_full_name } end # Walks down the namespace heirarchy to return the class object for the given class name. @@ -51,38 +49,7 @@ module ChefHandler # (see COOK-4117). parent = ancestors.inject(Kernel) { |scope, const_name| scope.const_get(const_name, scope === Kernel) } child = parent.const_get(class_name, parent === Kernel) - return parent, child - end - - # Unloads a given class and reloads it from the file provided. - # - # @param class_full_name [String] full class name such as 'Chef::Handler::Foo'. If a class - # with that name currently exists, its definition is deleted from the enclosing module. - # @param file_name [String] full path to the ruby file to be loaded. If path doesn't end with - # .rb, that extension is appended. - # @return [Class] definition for the freshly loaded class. - def reload_class(class_full_name, file_name) - begin - parent, child = get_class(class_full_name) - rescue - Chef::Log.debug("#{class_full_name} was not previously loaded.") - end - - if child then - class_name = class_full_name.split('::').last - child = nil - parent = Object if parent === Kernel - parent.send(:remove_const, class_name) - GC.start - end - - # Use load instead of require because we need to explicitly avoid any caching that 'require' - # performs. If the file has changed, we want to get the changes. - file_name << '.rb' unless file_name =~ /.*\.rb$/ - load file_name - - parent, child = get_class(class_full_name) - return child + [parent, child] end end end diff --git a/cookbooks/chef_handler/libraries/matchers.rb b/cookbooks/chef_handler/libraries/matchers.rb index f82bf8a..f1c2936 100644 --- a/cookbooks/chef_handler/libraries/matchers.rb +++ b/cookbooks/chef_handler/libraries/matchers.rb @@ -3,7 +3,7 @@ # Cookbook Name:: chef_handler # Library:: matchers # -# Copyright 2014, Chef Software, Inc. +# 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. @@ -19,12 +19,12 @@ # if defined?(ChefSpec) - chefspec_version = Gem.loaded_specs["chefspec"].version - if chefspec_version < Gem::Version.new('4.1.0') - define_method = ChefSpec::Runner.method(:define_runner_method) - else - define_method = ChefSpec.method(:define_matcher) - end + 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 :chef_handler diff --git a/cookbooks/chef_handler/metadata.json b/cookbooks/chef_handler/metadata.json index 493c45d..8c776ba 100644 --- a/cookbooks/chef_handler/metadata.json +++ b/cookbooks/chef_handler/metadata.json @@ -1 +1 @@ -{"name":"chef_handler","version":"1.1.9","description":"Distribute and enable Chef Exception and Report handlers","long_description":"Description\n===========\n\nCreates a configured handler path for distributing [Chef report and exception handlers](http://docs.chef.io/handlers.html). Also exposes an LWRP for enabling Chef handlers from within recipe code (as opposed to hard coding in the client.rb file). This is useful for cookbook authors who may want to ship a product specific handler (see the `cloudkick` cookbook for an example) with their cookbook.\n\nRequirements\n============\n\n* Ruby >= 1.9\n\nAttributes\n==========\n\n`node[\"chef_handler\"][\"handler_path\"]` - location to drop off handlers directory, default is `/var/chef/handlers`.\n\nResource/Provider\n=================\n\n`chef_handler`\n--------------\n\nRequires, configures and enables handlers on the node for the current Chef run. Also has the ability to pass arguments to the handlers initializer. This allows initialization data to be pulled from a node's attribute data.\n\nIt is best to declare `chef_handler` resources early on in the compile phase so they are available to fire for any exceptions during the Chef run. If you have a base role you would want any recipes that register Chef handlers to come first in the run_list.\n\n### Actions\n\n- :enable: Enables the Chef handler for the current Chef run on the current node\n- :disable: Disables the Chef handler for the current Chef run on the current node\n\n### Attribute Parameters\n\n- class_name: name attribute. The name of the handler class (can be module name-spaced).\n- source: full path to the handler file. can also be a gem path if the handler ships as part of a Ruby gem.\n- arguments: an array of arguments to pass the handler's class initializer\n- supports: type of Chef Handler to register as, i.e. :report, :exception or both. default is `:report => true, :exception => true`\n\n### Example\n\n```ruby\n # register the Chef::Handler::JsonFile handler\n # that ships with the Chef gem\n chef_handler \"Chef::Handler::JsonFile\" do\n source \"chef/handler/json_file\"\n arguments :path => '/var/chef/reports'\n action :enable\n end\n\n # do the same but during the compile phase\n chef_handler \"Chef::Handler::JsonFile\" do\n source \"chef/handler/json_file\"\n arguments :path => '/var/chef/reports'\n action :nothing\n end.run_action(:enable)\n\n # handle exceptions only\n chef_handler \"Chef::Handler::JsonFile\" do\n source \"chef/handler/json_file\"\n arguments :path => '/var/chef/reports'\n supports :exception => true\n action :enable\n end\n\n\n # enable the CloudkickHandler which was\n # dropped off in the default handler path.\n # passes the oauth key/secret to the handler's\n # intializer.\n chef_handler \"CloudkickHandler\" do\n source \"#{node['chef_handler']['handler_path']}/cloudkick_handler.rb\"\n arguments [node['cloudkick']['oauth_key'], node['cloudkick']['oauth_secret']]\n action :enable\n end\n```\n\n\nUsage\n=====\n\ndefault\n-------\n\nPut the recipe `chef_handler` at the start of the node's run list to make sure that custom handlers are dropped off early on in the Chef run and available for later recipes.\n\nFor information on how to write report and exception handlers for Chef, please see the Chef wiki pages:\nhttp://wiki.chef.io/display/chef/Exception+and+Report+Handlers\n\njson_file\n---------\n\nLeverages the `chef_handler` LWRP to automatically register the `Chef::Handler::JsonFile` handler that ships as part of Chef. This handler serializes the run status data to a JSON file located at `/var/chef/reports`.\n\n\nUnit Testing\n==================\n\nchef_handler provides built in [chefspec](https://github.com/sethvargo/chefspec) matchers for assisting unit tests. These matchers will only be loaded if chefspec is already loaded. Following is an example of asserting against the jsonfile handler:\n\n\n```ruby\n expect(runner).to enable_chef_handler(\"Chef::Handler::JsonFile\").with(\n source: \"chef/handler/json_file\",\n arguments: { :path => '/var/chef/reports'},\n supports: {:exception => true}\n )\n end\n```\n\nLicense and Author\n==================\n\nAuthor:: Seth Chisamore ()\n\nCopyright:: 2011, 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","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache 2.0","platforms":{},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file +{"name":"chef_handler","version":"1.3.0","description":"Distribute and enable Chef Exception and Report handlers","long_description":"# chef_handler Cookbook\n[![Build Status](https://travis-ci.org/chef-cookbooks/chef_handler.svg?branch=master)](https://travis-ci.org/chef-cookbooks/chef_handler) [![Cookbook Version](https://img.shields.io/cookbook/v/chef_handler.svg)](https://supermarket.chef.io/cookbooks/chef_handler)\n\nCreates a configured handler path for distributing [Chef report and exception handlers](http://docs.chef.io/handlers.html). Also exposes an LWRP for enabling Chef handlers from within recipe code (as opposed to hard coding in the client.rb file). This is useful for cookbook authors who may want to ship a product specific handler (see the `cloudkick` cookbook for an example) with their cookbook.\n\n## Requirements\n### Platforms\n- Debian/Ubuntu\n- RHEL/CentOS/Scientific/Amazon/Oracle\n- Windows\n\n### Chef\n- Chef 11+\n\n### Cookbooks\n- none\n\n## Attributes\n`node['chef_handler']['handler_path']` - location to drop off handlers directory, default is a folder named 'handlers' in Chef's file cache directory\n\n## Custom Resources\n### chef_handler\nRequires, configures and enables handlers on the node for the current Chef run. Also has the ability to pass arguments to the handlers initializer. This allows initialization data to be pulled from a node's attribute data.\n\nIt is best to declare `chef_handler` resources early on in the compile phase so they are available to fire for any exceptions during the Chef run. If you have a base role you would want any recipes that register Chef handlers to come first in the run_list.\n\n#### Actions\n- `:enable:` Enables the Chef handler for the current Chef run on the current node\n- `:disable:` Disables the Chef handler for the current Chef run on the current node\n\n#### Attribute Parameters\n- `class_name:` name attribute. The name of the handler class (can be module name-spaced).\n- `source:` full path to the handler file. can also be a gem path if the handler ships as part of a Ruby gem.\n- `arguments:` an array of arguments to pass the handler's class initializer\n- `supports:` type of Chef Handler to register as, i.e. :report, :exception or both. default is `:report => true, :exception => true`\n\n#### Example\n\n```ruby\n # register the Chef::Handler::JsonFile handler\n # that ships with the Chef gem\n chef_handler \"Chef::Handler::JsonFile\" do\n source \"chef/handler/json_file\"\n arguments :path => '/var/chef/reports'\n action :enable\n end\n\n # do the same but during the compile phase\n chef_handler \"Chef::Handler::JsonFile\" do\n source \"chef/handler/json_file\"\n arguments :path => '/var/chef/reports'\n action :nothing\n end.run_action(:enable)\n\n # handle exceptions only\n chef_handler \"Chef::Handler::JsonFile\" do\n source \"chef/handler/json_file\"\n arguments :path => '/var/chef/reports'\n supports :exception => true\n action :enable\n end\n\n\n # enable the CloudkickHandler which was\n # dropped off in the default handler path.\n # passes the oauth key/secret to the handler's\n # intializer.\n chef_handler \"CloudkickHandler\" do\n source \"#{node['chef_handler']['handler_path']}/cloudkick_handler.rb\"\n arguments [node['cloudkick']['oauth_key'], node['cloudkick']['oauth_secret']]\n action :enable\n end\n```\n\n## Usage\n### default\nPut the recipe `chef_handler` at the start of the node's run list to make sure that custom handlers are dropped off early on in the Chef run and available for later recipes.\n\nFor information on how to write report and exception handlers for Chef, please see the Chef wiki pages: [https://docs.chef.io/handlers.html](https://docs.chef.io/handlers.html)\n\n### json_file\nLeverages the `chef_handler` LWRP to automatically register the `Chef::Handler::JsonFile` handler that ships as part of Chef. This handler serializes the run status data to a JSON file located at `/var/chef/reports`.\n\n## Unit Testing\nchef_handler provides built in [chefspec](https://github.com/sethvargo/chefspec) matchers for assisting unit tests. These matchers will only be loaded if chefspec is already loaded. Following is an example of asserting against the jsonfile handler:\n\n```ruby\n expect(runner).to enable_chef_handler(\"Chef::Handler::JsonFile\").with(\n source: \"chef/handler/json_file\",\n arguments: { :path => '/var/chef/reports'},\n supports: {:exception => true}\n )\n end\n```\n\n## License & Authors\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":{},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{"chef_handler":"Deploys all handlers to the handler path early during the run.","chef_handler::json_file":"Enables Chef::Handler::JsonFile to serialize run status data to /var/chef/reports."}} \ No newline at end of file diff --git a/cookbooks/chef_handler/providers/default.rb b/cookbooks/chef_handler/providers/default.rb index cd4e3ef..7da21b9 100644 --- a/cookbooks/chef_handler/providers/default.rb +++ b/cookbooks/chef_handler/providers/default.rb @@ -3,7 +3,7 @@ # Cookbook Name:: chef_handler # Provider:: default # -# Copyright:: 2011-2013, Chef Software, Inc +# 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. @@ -25,36 +25,27 @@ def whyrun_supported? end # This action needs to find an rb file that presumably contains the indicated class in it and the -# load that file. It needs to do this keeping in mind that the same handler class can get enabled -# and disabled multiple times and there may be multiple instances of them running around. The -# handler code may also have changed between actions. To handle all this, we parse the full class -# name and attempt to find its class object, in case it has already been loaded. If such a class -# is found, we then attempt to unload that class before we load the file requested. We use "load" -# instead of "require" because we want to reload the handler class in case it has changed and -# don't want the caching behavior of "require". -# -# Note that during this process, we also need to keep track of the current handler configuration. -# Any of the above steps might fail - in which case we would not want to be in a situation where -# we have a registered handler that has been unloaded or mangled. +# load that file. It then instantiates that class by name and registers it as a handler. action :enable do class_name = new_resource.class_name new_resource.supports.each do |type, enable| - if enable - converge_by("disable #{class_name} as a #{type} handler") do - unregister_handler(type, class_name) - end + next unless enable + converge_by("disable #{class_name} as a #{type} handler") do + unregister_handler(type, class_name) end end + handler = nil converge_by("load #{class_name} from #{new_resource.source}") do - klass = reload_class(class_name, new_resource.source) + require new_resource.source + _, klass = get_class(class_name) handler = klass.send(:new, *collect_args(new_resource.arguments)) end + new_resource.supports.each do |type, enable| - if enable - converge_by("enable #{new_resource} as a #{type} handler") do - register_handler(type, handler) - end + next unless enable + converge_by("enable #{new_resource} as a #{type} handler") do + register_handler(type, handler) end end end @@ -83,4 +74,3 @@ def collect_args(resource_args = []) [resource_args] end end - diff --git a/cookbooks/chef_handler/recipes/default.rb b/cookbooks/chef_handler/recipes/default.rb index b8935c5..3761c41 100644 --- a/cookbooks/chef_handler/recipes/default.rb +++ b/cookbooks/chef_handler/recipes/default.rb @@ -1,9 +1,9 @@ # # Author:: Seth Chisamore () -# Cookbook Name:: chef_handlers +# Cookbook Name:: chef_handler # Recipe:: default # -# Copyright 2011, Chef Software, Inc. +# 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. @@ -18,16 +18,15 @@ # limitations under the License. # -Chef::Log.info("Chef Handlers will be at: #{node['chef_handler']['handler_path']}") +Chef::Log.info("Chef Handlers will be located at: #{node['chef_handler']['handler_path']}") remote_directory node['chef_handler']['handler_path'] do source 'handlers' - # Just inherit permissions on Windows, don't try to set POSIX perms - if node["platform"] != "windows" - owner node['chef_handler']['root_user'] - group node['chef_handler']['root_group'] - mode "0755" + unless platform?('windows') + owner 'root' + mode '0755' recursive true end + group node['root_group'] action :nothing end.run_action(:create) diff --git a/cookbooks/chef_handler/recipes/json_file.rb b/cookbooks/chef_handler/recipes/json_file.rb index cd831bd..f6e37c5 100644 --- a/cookbooks/chef_handler/recipes/json_file.rb +++ b/cookbooks/chef_handler/recipes/json_file.rb @@ -1,9 +1,9 @@ # # Author:: Seth Chisamore () -# Cookbook Name:: chef_handlers +# Cookbook Name:: chef_handler # Recipe:: json_file # -# Copyright 2011, Chef Software, Inc. +# 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. @@ -18,11 +18,11 @@ # limitations under the License. # -# force resource actions in compile phase so exception handler +# force resource actions in compile phase so exception handler # fires for compile phase exceptions -chef_handler "Chef::Handler::JsonFile" do - source "chef/handler/json_file" - arguments :path => '/var/chef/reports' +chef_handler 'Chef::Handler::JsonFile' do + source 'chef/handler/json_file' + arguments path: '/var/chef/reports' action :nothing end.run_action(:enable) diff --git a/cookbooks/chef_handler/resources/default.rb b/cookbooks/chef_handler/resources/default.rb index 7b2ebd2..503113b 100644 --- a/cookbooks/chef_handler/resources/default.rb +++ b/cookbooks/chef_handler/resources/default.rb @@ -3,7 +3,7 @@ # Cookbook Name:: chef_handler # Resource:: default # -# Copyright:: 2011-2013, Chef Software, Inc +# 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. @@ -20,15 +20,20 @@ actions :enable, :disable -attribute :class_name, :kind_of => String, :name_attribute => true -attribute :source, :default => nil, :kind_of => String -attribute :arguments, :default => [] -attribute :supports, :kind_of => Hash, :default => { :report => true, :exception => true } +state_attrs :arguments, + :class_name, + :source, + :supports -# we have to set default for the supports attribute +attribute :class_name, kind_of: String, name_attribute: true +attribute :source, default: nil, kind_of: String +attribute :arguments, default: [] +attribute :supports, kind_of: Hash, default: { report: true, exception: true } + +# we have to set default for the supports attribute # in initializer since it is a 'reserved' attribute name def initialize(*args) super @action = :enable - @supports = { :report => true, :exception => true } + @supports = { report: true, exception: true } end diff --git a/cookbooks/rsyslog/.gitignore b/cookbooks/database/.gitignore similarity index 86% rename from cookbooks/rsyslog/.gitignore rename to cookbooks/database/.gitignore index e618bbe..2d3a156 100644 --- a/cookbooks/rsyslog/.gitignore +++ b/cookbooks/database/.gitignore @@ -23,11 +23,16 @@ _Store *.tmp *.bk *.bkup +.ruby-version +.ruby-gemset +.rvmrc # YARD artifacts .yardoc _yardoc doc/ +.idea +.ruby-version #chef stuff Berksfile.lock diff --git a/cookbooks/database/.kitchen.cloud.yml b/cookbooks/database/.kitchen.cloud.yml new file mode 100644 index 0000000..47ff814 --- /dev/null +++ b/cookbooks/database/.kitchen.cloud.yml @@ -0,0 +1,182 @@ +#<% require 'kitchen-sync' %> +--- +driver_config: + digitalocean_client_id: <%= ENV['DIGITAL_OCEAN_CLIENT_ID'] %> + google_client_email: <%= ENV['GOOGLE_CLIENT_EMAIL'] %> + google_key_location: <%= ENV['GOOGLE_KEY_LOCATION'] %> + google_project: <%= ENV['GOOGLE_PROJECT'] %> + joyent_username: <%= ENV['SDC_CLI_ACCOUNT'] %> + joyent_keyfile: <%= ENV['SDC_CLI_IDENTITY'] %> + joyent_keyname: <%= ENV['SDC_CLI_KEY_ID'] %> + joyent_url: <%= ENV['SDC_CLI_URL'] %> + aws_access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> + aws_secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> + aws_ssh_key_id: <%= ENV['AWS_KEYPAIR_NAME'] %> + flavor_id: <%= ENV['EC2_FLAVOR_ID'] %> + availability_zone: <%= ENV['AWS_AVAILABILITY_ZONE'] %> + +provisioner: + name: chef_zero + # require_chef_omnibus: 11.16.8 + # require_chef_omnibus: 12.0.3 + require_chef_omnibus: latest + +platforms: +- name: centos-5.8 + driver_plugin: digital_ocean + driver_config: + size: 2gb + image: centos-5-8-x64 + region: <%= ENV['DIGITAL_OCEAN_REGION'] %> + ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> + ssh_key: <%= ENV['DIGITAL_OCEAN_SSH_KEY_PATH'] %> + +- name: centos-6.5 + driver_plugin: digital_ocean + driver_config: + size: 2gb + image: centos-6-5-x64 + region: <%= ENV['DIGITAL_OCEAN_REGION'] %> + ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> + ssh_key: <%= ENV['DIGITAL_OCEAN_SSH_KEY_PATH'] %> + +- name: centos-7.0 + driver_plugin: digital_ocean + driver_config: + size: 2gb + image: centos-7-0-x64 + region: <%= ENV['DIGITAL_OCEAN_REGION'] %> + ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> + ssh_key: <%= ENV['DIGITAL_OCEAN_SSH_KEY_PATH'] %> + +- name: amazon-2014.09 + driver_plugin: ec2 + driver_config: + image_id: ami-9a6ed3f2 + username: ec2-user + ssh_key: <%= ENV['EC2_SSH_KEY_PATH'] %> + +- name: fedora-20 + driver_plugin: digital_ocean + driver_config: + size: 2gb + image: fedora-20-x64 + region: <%= ENV['DIGITAL_OCEAN_REGION'] %> + ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> + ssh_key: <%= ENV['DIGITAL_OCEAN_SSH_KEY_PATH'] %> + +- name: suse-11.3 + driver_plugin: ec2 + driver_config: + image_id: ami-e8084981 + username: root + ssh_key: <%= ENV['EC2_SSH_KEY_PATH'] %> + +- name: debian-7.0 + driver_plugin: gce + driver_config: + image_name: debian-7-wheezy-v20131120 + zone: <%= ENV['GCE_ZONE'] %> + area: <%= ENV['GCE_AREA'] %> + network: <%= ENV['GCE_NETWORK'] %> + username: <%= ENV['GCE_USERNAME'] %> + public_key_path: <%= ENV['GCE_PUBLIC_KEY_PATH'] %> + ssh_key: <%= ENV['GCE_SSH_KEY_PATH'] %> + run_list: + - recipe[apt] + +- name: ubuntu-10.04 + driver_plugin: digital_ocean + driver_config: + size: 2gb + image: ubuntu-10-04-x64 + region: <%= ENV['DIGITAL_OCEAN_REGION'] %> + ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> + ssh_key: <%= ENV['DIGITAL_OCEAN_SSH_KEY_PATH'] %> + run_list: + - recipe[apt] + +- name: ubuntu-12.04 + driver_plugin: digital_ocean + driver_config: + size: 2gb + image: ubuntu-12-04-x64 + region: <%= ENV['DIGITAL_OCEAN_REGION'] %> + ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> + ssh_key: <%= ENV['DIGITAL_OCEAN_SSH_KEY_PATH'] %> + run_list: + - recipe[apt] + +- name: ubuntu-14.04 + driver_plugin: digital_ocean + driver_config: + size: 2gb + image: ubuntu-14-04-x64 + region: <%= ENV['DIGITAL_OCEAN_REGION'] %> + ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> + ssh_key: <%= ENV['DIGITAL_OCEAN_SSH_KEY_PATH'] %> + run_list: + - recipe[apt] + +suites: + # + # database-test + # + - name: myclient50 + run_list: + - recipe[mysql_database_test] + attributes: + mysql: + version: '5.0' + includes: [ + 'centos-5.8' + ] + + - name: myclient51 + run_list: + - recipe[mysql_database_test] + attributes: + mysql: + version: '5.1' + includes: [ + 'centos-6.5', + 'ubuntu-10.04' + ] + + - name: myclient55 + run_list: + - recipe[mysql_database_test] + attributes: + mysql: + version: '5.5' + includes: [ + 'centos-6.5', + 'debian-7.0', + 'ubuntu-12.04', + 'ubuntu-14.04' + ] + + - name: myclient56 + run_list: + - recipe[mysql_database_test] + attributes: + mysql: + version: '5.6' + includes: [ + 'centos-5.8', + 'centos-6.5', + 'centos-7.0', + 'ubuntu-14.04' + ] + + - name: myclient57 + run_list: + - recipe[mysql_database_test] + attributes: + mysql: + version: '5.7' + includes: [ + 'centos-5.8', + 'centos-6.5', + 'centos-7.0' + ] diff --git a/cookbooks/database/.kitchen.yml b/cookbooks/database/.kitchen.yml new file mode 100644 index 0000000..7af544e --- /dev/null +++ b/cookbooks/database/.kitchen.yml @@ -0,0 +1,33 @@ +--- +driver: + name: vagrant + +provisioner: + name: chef_zero + +platforms: + - name: centos-5.11 + - name: centos-6.7 + - name: centos-7.1 + - name: debian-7.8 + run_list: + - recipe[apt] + - name: debian-8.1 + run_list: + - recipe[apt] + - name: fedora-21 + - name: ubuntu-12.04 + run_list: + - recipe[apt] + - name: ubuntu-14.04 + run_list: + - recipe[apt] + +suites: + # + # database-test + # + - name: default + run_list: + - recipe[mysql_database_test] + - recipe[postgresql_database_test] diff --git a/cookbooks/database/.rubocop.yml b/cookbooks/database/.rubocop.yml new file mode 100644 index 0000000..4df4b44 --- /dev/null +++ b/cookbooks/database/.rubocop.yml @@ -0,0 +1,35 @@ +AllCops: + Exclude: + - vendor/**/* + - 'Guardfile' + +AlignParameters: + Enabled: false + +Encoding: + Enabled: false + +ClassLength: + Enabled: false + +MethodLength: + Enabled: false + +LineLength: + Enabled: false + +Documentation: + Enabled: false + +PerceivedComplexity: + Enabled: false + +CyclomaticComplexity: + Enabled: false + +Style/FileName: + Enabled: false + +Metrics/AbcSize: + Enabled: false + diff --git a/cookbooks/database/.travis.yml b/cookbooks/database/.travis.yml new file mode 100644 index 0000000..c5dd1f0 --- /dev/null +++ b/cookbooks/database/.travis.yml @@ -0,0 +1,12 @@ +sudo: false +cache: bundler +language: ruby +bundler_args: --without kitchen_common kitchen_vagrant +rvm: + - 2.0 + - 2.1 + - 2.2 +script: + - bundle exec foodcritic -f any . + - bundle exec rubocop + - bundle exec rspec --color --format progress diff --git a/cookbooks/database/Berksfile b/cookbooks/database/Berksfile new file mode 100644 index 0000000..424aee1 --- /dev/null +++ b/cookbooks/database/Berksfile @@ -0,0 +1,12 @@ +source 'https://supermarket.chef.io' + +metadata + +group :integration do + cookbook 'apt' + cookbook 'selinux' + cookbook 'mysql2_chef_gem' +end + +cookbook 'mysql_database_test', path: 'test/fixtures/cookbooks/mysql_database_test' +cookbook 'postgresql_database_test', path: 'test/fixtures/cookbooks/postgresql_database_test' diff --git a/cookbooks/database/CHANGELOG.md b/cookbooks/database/CHANGELOG.md index 40a0234..bcb5c0d 100644 --- a/cookbooks/database/CHANGELOG.md +++ b/cookbooks/database/CHANGELOG.md @@ -1,6 +1,34 @@ Database cookbook README ======================== +v4.0.9 (2015-09-07) +------------------- +- Fix bad attribute name with postgresql_database in the readme +- Add `flags` attribute to the mysql provider +- Add `database` attribute to the mysql provider +- Use the correct database with the mssql provider +- Updated testing.md and contributing.md to point to documentation in the new community_cookbook_documentation repo +- Add oracle as a supported platform in the metadata +- Add source_url and issues_url metadata +- Add cookbook version and travis badges to the readme +- Clarify the minimum required Chef version in the readme +- Add a Travis config +- Resolve several rubocop and foodcritic warnings +- Update all platforms in the Kitchen config +- Update development dependencies to the latest releases +- Add a maintainers.md and maintainers.toml file +- Add a chefignore file +- Update list of ignored files in the gitignore + +v4.0.8 (2015-08-03) +------------------- +- #139 - Use a more reliable method of determining whether the + Postgres server accepts the REPLICATION attribute on user creation. + +v4.0.7 (2015-07-27) +------------------- +- #161 - Fixes multiple issues causing the MySQL database user creation to not be idempotent + v4.0.6 (2015-04-29) ------------------- - #126 - Use sql_query property instead of sql in the mysql provider for :query action diff --git a/cookbooks/database/CONTRIBUTING.md b/cookbooks/database/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/database/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/rsyslog/Gemfile b/cookbooks/database/Gemfile similarity index 76% rename from cookbooks/rsyslog/Gemfile rename to cookbooks/database/Gemfile index 16a38d5..34f3aa0 100644 --- a/cookbooks/rsyslog/Gemfile +++ b/cookbooks/database/Gemfile @@ -2,14 +2,13 @@ source 'https://rubygems.org' group :lint do gem 'foodcritic', '~> 4.0' - gem 'rubocop', '~> 0.31' + gem 'rubocop', '~> 0.33' gem 'rainbow', '< 2.0' - gem 'rake' end group :unit do - gem 'berkshelf', '~> 3.2.0' - gem 'chefspec', '~> 4.0' + gem 'berkshelf', '~> 3.2' + gem 'chefspec', '~> 4.3' end group :kitchen_common do @@ -23,6 +22,8 @@ end group :kitchen_cloud do gem 'kitchen-digitalocean' gem 'kitchen-ec2' + gem 'kitchen-joyent' + gem 'kitchen-gce' end group :development do @@ -34,4 +35,7 @@ group :development do gem 'guard-foodcritic' gem 'guard-rspec' gem 'guard-rubocop' + gem 'rake' + gem 'fauxhai' + gem 'pry-nav' end diff --git a/cookbooks/database/Guardfile b/cookbooks/database/Guardfile new file mode 100644 index 0000000..5b8e7dc --- /dev/null +++ b/cookbooks/database/Guardfile @@ -0,0 +1,24 @@ +# More info at https://github.com/guard/guard#readme + +guard 'foodcritic', :cookbook_paths => '.', :cli => '-t ~FC023 -t ~FC005', :all_on_start => false do + watch(/attributes\/.+\.rb$/) + watch(/providers\/.+\.rb$/) + watch(/recipes\/.+\.rb$/) + watch(/resources\/.+\.rb$/) + watch('metadata.rb') +end + +guard 'rubocop' do + watch(/attributes\/.+\.rb$/) + watch(/providers\/.+\.rb$/) + watch(/recipes\/.+\.rb$/) + watch(/resources\/.+\.rb$/) + watch('metadata.rb') +end + +guard :rspec, :cmd => 'chef exec /opt/chefdk/embedded/bin/rspec', :all_on_start => false, :notification => false do + watch(/^libraries\/(.+)\.rb$/) + watch(/^spec\/(.+)_spec\.rb$/) + watch(/^(recipes)\/(.+)\.rb$/) { |m| "spec/#{m[1]}_spec.rb" } + watch('spec/spec_helper.rb') { 'spec' } +end diff --git a/cookbooks/rsyslog/LICENSE b/cookbooks/database/LICENSE similarity index 99% rename from cookbooks/rsyslog/LICENSE rename to cookbooks/database/LICENSE index 11069ed..1b91cbb 100644 --- a/cookbooks/rsyslog/LICENSE +++ b/cookbooks/database/LICENSE @@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work. same "printed page" as the copyright notice for easier identification within third-party archives. -Copyright [yyyy] [name of copyright owner] +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. diff --git a/cookbooks/database/MAINTAINERS.md b/cookbooks/database/MAINTAINERS.md new file mode 100644 index 0000000..c6a51ae --- /dev/null +++ b/cookbooks/database/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 +* [Tim Smith](https://github.com/tas50) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Sean OMeara](https://github.com/someara) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) diff --git a/cookbooks/database/MAINTAINERS.toml b/cookbooks/database/MAINTAINERS.toml new file mode 100644 index 0000000..47778d6 --- /dev/null +++ b/cookbooks/database/MAINTAINERS.toml @@ -0,0 +1,46 @@ +# +# This file is structured to be consumed by both humans and computers. +# It is a TOML document containing Markdown +# +[Preamble] + title = "Maintainers" + text = """ +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. +""" + +[Org] + [Org.Components] + [Org.Components.Core] + title = "Project Maintainer" + + lieutenant = 'tas50' + + maintainers = [ + 'sigje', + 'someara', + 'tas50', + 'thommay' + ] + +[people] + [people.sigje] + name = "Jennifer Davis" + github = "sigje" + + [people.someara] + name = "Sean OMeara" + github = "someara" + + [people.tas50] + name = "Tim Smith" + github = "tas50" + + [people.thommay] + name = "Thom May" + github = "thommay" diff --git a/cookbooks/database/README.md b/cookbooks/database/README.md index a88f221..6da5bbd 100644 --- a/cookbooks/database/README.md +++ b/cookbooks/database/README.md @@ -1,5 +1,8 @@ Database Cookbook ================= +[![Build Status](https://travis-ci.org/opscode-cookbooks/database.svg?branch=master)](http://travis-ci.org/opscode-cookbooks/database) +[![Cookbook Version](https://img.shields.io/cookbook/v/database.svg)](https://supermarket.chef.io/cookbooks/database) + The main highlight of this cookbook is the `database` and `database_user` resources for managing databases and database users in a RDBMS. Providers for MySQL, PostgreSQL and SQL Server are also @@ -7,11 +10,13 @@ provided, see usage documentation below. Requirements ------------ -Chef version 0.11+ - ### Platforms -- Debian, Ubuntu -- Red Hat, CentOS, Scientific, Fedora, Amazon +- Debian / Ubuntu derivatives +- RHEL derivatives +- Fedora + +### Chef +- Chef 11+ ### Cookbooks The following Chef Software cookbooks are dependencies: diff --git a/cookbooks/rsyslog/Rakefile b/cookbooks/database/Rakefile similarity index 97% rename from cookbooks/rsyslog/Rakefile rename to cookbooks/database/Rakefile index 965b4bf..3c52bbb 100644 --- a/cookbooks/rsyslog/Rakefile +++ b/cookbooks/database/Rakefile @@ -3,6 +3,8 @@ require 'rubocop/rake_task' require 'foodcritic' require 'kitchen' +require_relative 'tasks/maintainers' + # Style tests. Rubocop and Foodcritic namespace :style do desc 'Run Ruby style checks' diff --git a/cookbooks/database/TESTING.md b/cookbooks/database/TESTING.md new file mode 100644 index 0000000..ca524ab --- /dev/null +++ b/cookbooks/database/TESTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/TESTING.MD diff --git a/cookbooks/rsyslog/chefignore b/cookbooks/database/chefignore similarity index 100% rename from cookbooks/rsyslog/chefignore rename to cookbooks/database/chefignore diff --git a/cookbooks/database/libraries/provider_database_mysql.rb b/cookbooks/database/libraries/provider_database_mysql.rb index b37286d..fd1bbe8 100644 --- a/cookbooks/database/libraries/provider_database_mysql.rb +++ b/cookbooks/database/libraries/provider_database_mysql.rb @@ -103,11 +103,11 @@ class Chef require 'mysql2' @test_client ||= Mysql2::Client.new( - host: new_resource.connection[:host], - socket: new_resource.connection[:socket], - username: new_resource.connection[:username], - password: new_resource.connection[:password], - port: new_resource.connection[:port] + host: new_resource.connection[:host], + socket: new_resource.connection[:socket], + username: new_resource.connection[:username], + password: new_resource.connection[:password], + port: new_resource.connection[:port] ) end @@ -121,11 +121,11 @@ class Chef require 'mysql2' @repair_client ||= Mysql2::Client.new( - host: new_resource.connection[:host], - socket: new_resource.connection[:socket], - username: new_resource.connection[:username], - password: new_resource.connection[:password], - port: new_resource.connection[:port] + host: new_resource.connection[:host], + socket: new_resource.connection[:socket], + username: new_resource.connection[:username], + password: new_resource.connection[:password], + port: new_resource.connection[:port] ) end @@ -139,11 +139,13 @@ class Chef require 'mysql2' @query_client ||= Mysql2::Client.new( - host: new_resource.connection[:host], - socket: new_resource.connection[:socket], - username: new_resource.connection[:username], - password: new_resource.connection[:password], - port: new_resource.connection[:port] + host: new_resource.connection[:host], + socket: new_resource.connection[:socket], + username: new_resource.connection[:username], + password: new_resource.connection[:password], + port: new_resource.connection[:port], + flags: new_resource.connection[:flags], + database: new_resource.database_name ) end diff --git a/cookbooks/database/libraries/provider_database_mysql_user.rb b/cookbooks/database/libraries/provider_database_mysql_user.rb index 5a650de..fa14265 100644 --- a/cookbooks/database/libraries/provider_database_mysql_user.rb +++ b/cookbooks/database/libraries/provider_database_mysql_user.rb @@ -94,21 +94,84 @@ class Chef db_name = new_resource.database_name ? "`#{new_resource.database_name}`" : '*' tbl_name = new_resource.table ? new_resource.table : '*' + test_table = new_resource.database_name ? 'mysql.db' : 'mysql.user' + possible_global_privs = [ + :select, + :insert, + :update, + :delete, + :create, + :drop, + :references, + :index, + :alter, + :create_tmp_table, + :lock_tables, + :create_view, + :show_view, + :create_routine, + :alter_routine, + :execute, + :event, + :trigger, + :reload, + :shutdown, + :process, + :file, + :show_db, + :super, + :repl_slave, + :repl_client, + :create_user + ] + possible_db_privs = [ + :select, + :insert, + :update, + :delete, + :create, + :drop, + :references, + :index, + :alter, + :create_tmp_table, + :lock_tables, + :create_view, + :show_view, + :create_routine, + :alter_routine, + :execute, + :event, + :trigger + ] + + if new_resource.privileges == [:all] && new_resource.database_name + desired_privs = possible_db_privs + elsif new_resource.privileges == [:all] + desired_privs = possible_global_privs + else + desired_privs = new_resource.privileges + end # Test incorrect_privs = nil begin - test_sql = 'SELECT * from mysql.db' + test_sql = "SELECT * from #{test_table}" test_sql += " WHERE User='#{new_resource.username}'" test_sql += " AND Host='#{new_resource.host}'" - test_sql += " AND Db='#{new_resource.database_name}'" + test_sql += " AND Db='#{new_resource.database_name}'" if new_resource.database_name test_sql_results = test_client.query test_sql incorrect_privs = true if test_sql_results.size == 0 # These should all by 'Y' test_sql_results.each do |r| - new_resource.privileges.each do |p| - key = "#{p.capitalize}_priv" + desired_privs.each do |p| + key = "#{p.capitalize}" + .gsub(' ', '_') + .gsub('Replication_', 'Repl_') + + key = "#{key}_priv" + incorrect_privs = true if r[key] != 'Y' end end @@ -156,11 +219,11 @@ class Chef require 'mysql2' @test_client ||= Mysql2::Client.new( - host: new_resource.connection[:host], - socket: new_resource.connection[:socket], - username: new_resource.connection[:username], - password: new_resource.connection[:password], - port: new_resource.connection[:port] + host: new_resource.connection[:host], + socket: new_resource.connection[:socket], + username: new_resource.connection[:username], + password: new_resource.connection[:password], + port: new_resource.connection[:port] ) end @@ -174,11 +237,11 @@ class Chef require 'mysql2' @repair_client ||= Mysql2::Client.new( - host: new_resource.connection[:host], - socket: new_resource.connection[:socket], - username: new_resource.connection[:username], - password: new_resource.connection[:password], - port: new_resource.connection[:port] + host: new_resource.connection[:host], + socket: new_resource.connection[:socket], + username: new_resource.connection[:username], + password: new_resource.connection[:password], + port: new_resource.connection[:port] ) end diff --git a/cookbooks/database/libraries/provider_database_postgresql.rb b/cookbooks/database/libraries/provider_database_postgresql.rb index 387c3b8..b49d8f3 100644 --- a/cookbooks/database/libraries/provider_database_postgresql.rb +++ b/cookbooks/database/libraries/provider_database_postgresql.rb @@ -41,9 +41,7 @@ class Chef unless exists? begin encoding = @new_resource.encoding - if encoding != 'DEFAULT' - encoding = "'#{@new_resource.encoding}'" - end + encoding = "'#{@new_resource.encoding}'" if encoding != 'DEFAULT' Chef::Log.debug("#{@new_resource}: Creating database #{new_resource.database_name}") create_sql = "CREATE DATABASE \"#{new_resource.database_name}\"" create_sql += " TEMPLATE = #{new_resource.template}" if new_resource.template @@ -100,14 +98,15 @@ class Chef ret end - # Test if text is psql keyword - def keyword?(text) + # Verify the postgres server's version number is greater than the integer passed in + def version_greater_than?(desired_version_int) begin - result = db('template1').exec_params('select * from pg_get_keywords() where word = $1', [text.downcase]).num_tuples != 0 + ret = db('template1').exec('SHOW server_version_num;') + server_version_int = ret.getvalue(0, 0).to_i ensure close end - result + server_version_int > desired_version_int end # @@ -124,7 +123,7 @@ class Chef port = @new_resource.connection[:port] || 5432 user = @new_resource.connection[:username] || 'postgres' Chef::Log.debug("#{@new_resource}: connecting to database #{dbname} on #{host}:#{port} as #{user}") - password = @new_resource.connection[:password] || node[:postgresql][:password][:postgres] + password = @new_resource.connection[:password] || node['postgresql']['password']['postgres'] @db = ::PGconn.new( host: host, port: port, diff --git a/cookbooks/database/libraries/provider_database_postgresql_user.rb b/cookbooks/database/libraries/provider_database_postgresql_user.rb index 079ae1d..8fc47a3 100644 --- a/cookbooks/database/libraries/provider_database_postgresql_user.rb +++ b/cookbooks/database/libraries/provider_database_postgresql_user.rb @@ -42,13 +42,11 @@ class Chef options += " #{@new_resource.createdb ? 'CREATEDB' : 'NOCREATEDB'}" options += " #{@new_resource.createrole ? 'CREATEROLE' : 'NOCREATEROLE'}" options += " #{@new_resource.login ? 'LOGIN' : 'NOLOGIN'}" - options += " #{@new_resource.replication ? 'REPLICATION' : 'NOREPLICATION'}" if keyword?('REPLICATION') + options += " #{@new_resource.replication ? 'REPLICATION' : 'NOREPLICATION'}" if version_greater_than?(90_100) options += " #{@new_resource.superuser ? 'SUPERUSER' : 'NOSUPERUSER'}" statement = "CREATE USER \"#{@new_resource.username}\"" - if options.length > 0 - statement += " WITH #{options}" - end + statement += " WITH #{options}" if options.length > 0 db('template1').query(statement) @new_resource.updated_by_last_action(true) diff --git a/cookbooks/database/libraries/provider_database_sql_server.rb b/cookbooks/database/libraries/provider_database_sql_server.rb index 518929c..62f2c51 100644 --- a/cookbooks/database/libraries/provider_database_sql_server.rb +++ b/cookbooks/database/libraries/provider_database_sql_server.rb @@ -61,8 +61,8 @@ class Chef def action_query if exists? begin - # db.select_db(@new_resource.database_name) if @new_resource.database_name Chef::Log.debug("#{@new_resource}: Performing query [#{new_resource.sql_query}]") + db.execute("USE [#{@new_resource.database_name}]").do if @new_resource.database_name db.execute(@new_resource.sql_query).do @new_resource.updated_by_last_action(true) ensure diff --git a/cookbooks/database/libraries/provider_database_sql_server_user.rb b/cookbooks/database/libraries/provider_database_sql_server_user.rb index d92338e..4580928 100644 --- a/cookbooks/database/libraries/provider_database_sql_server_user.rb +++ b/cookbooks/database/libraries/provider_database_sql_server_user.rb @@ -88,7 +88,7 @@ class Chef end Chef::Application.fatal!('Please provide a database_name, SQL Server does not support global GRANT statements.') unless @new_resource.database_name db.execute("USE [#{@new_resource.database_name}]").do - @new_resource.sql_roles.each do | sql_role, role_action | + @new_resource.sql_roles.each do |sql_role, role_action| alter_statement = "ALTER ROLE [#{sql_role}] #{role_action} MEMBER [#{@new_resource.username}]" Chef::Log.info("#{@new_resource} granting access with statement [#{alter_statement}]") db.execute(alter_statement).do @@ -105,7 +105,7 @@ class Chef server_version = db.execute("SELECT SERVERPROPERTY('productversion')").each.first.values.first Chef::Log.info("SQL Server Version: #{server_version.inspect}") db.execute('USE [master]').do - @new_resource.sql_sys_roles.each do | sql_sys_role, role_action | + @new_resource.sql_sys_roles.each do |sql_sys_role, role_action| case role_action when 'ADD' if server_version < '11.00.0000.00' diff --git a/cookbooks/database/libraries/resource_sql_server_database_user.rb b/cookbooks/database/libraries/resource_sql_server_database_user.rb index 083cb84..a63af38 100644 --- a/cookbooks/database/libraries/resource_sql_server_database_user.rb +++ b/cookbooks/database/libraries/resource_sql_server_database_user.rb @@ -35,7 +35,7 @@ class Chef def windows_user(arg = nil) set_or_return( - :windows_user, + :windows_user, arg, kind_of: [TrueClass, FalseClass], default: false @@ -45,7 +45,7 @@ class Chef def sql_roles(arg = nil) Chef::Log.debug("Received roles: #{arg.inspect}") set_or_return( - :sql_roles, + :sql_roles, arg, kind_of: Hash ) @@ -54,7 +54,7 @@ class Chef def sql_sys_roles(arg = nil) Chef::Log.debug("Received Server roles: #{arg.inspect}") set_or_return( - :sql_sys_roles, + :sql_sys_roles, arg, kind_of: Hash ) diff --git a/cookbooks/database/metadata.json b/cookbooks/database/metadata.json index 91e954a..99cc4ae 100644 --- a/cookbooks/database/metadata.json +++ b/cookbooks/database/metadata.json @@ -1 +1,49 @@ -{"name":"database","version":"4.0.6","description":"provides LWRPs for common database tasks","long_description":"","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","suse":">= 0.0.0","fedora":">= 0.0.0","redhat":">= 0.0.0","scientific":">= 0.0.0","amazon":">= 0.0.0"},"dependencies":{"postgresql":">= 1.0.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file +{ + "name": "database", + "description": "provides LWRPs for common database tasks", + "long_description": "", + "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", + "suse": ">= 0.0.0", + "fedora": ">= 0.0.0", + "redhat": ">= 0.0.0", + "scientific": ">= 0.0.0", + "oracle": ">= 0.0.0", + "amazon": ">= 0.0.0" + }, + "dependencies": { + "postgresql": ">= 1.0.0" + }, + "recommendations": { + + }, + "suggestions": { + + }, + "conflicting": { + + }, + "providing": { + + }, + "replacing": { + + }, + "attributes": { + + }, + "groupings": { + + }, + "recipes": { + + }, + "version": "4.0.9", + "source_url": "https://github.com/opscode-cookbooks/database", + "issues_url": "https://github.com/opscode-cookbooks/database/issues" +} diff --git a/cookbooks/database/metadata.rb b/cookbooks/database/metadata.rb new file mode 100644 index 0000000..982087d --- /dev/null +++ b/cookbooks/database/metadata.rb @@ -0,0 +1,21 @@ +name 'database' +maintainer 'Chef Software, Inc.' +maintainer_email 'cookbooks@chef.io' +license 'Apache 2.0' +description 'provides LWRPs for common database tasks' +version '4.0.9' + +supports 'debian' +supports 'ubuntu' +supports 'centos' +supports 'suse' +supports 'fedora' +supports 'redhat' +supports 'scientific' +supports 'oracle' +supports 'amazon' + +depends 'postgresql', '>= 1.0.0' + +source_url 'https://github.com/opscode-cookbooks/database' if respond_to?(:source_url) +issues_url 'https://github.com/opscode-cookbooks/database/issues' if respond_to?(:issues_url) diff --git a/cookbooks/firewall/CHANGELOG.md b/cookbooks/firewall/CHANGELOG.md index b74e18e..b1196ab 100644 --- a/cookbooks/firewall/CHANGELOG.md +++ b/cookbooks/firewall/CHANGELOG.md @@ -2,6 +2,112 @@ firewall Cookbook CHANGELOG ======================= This file is used to list changes made in each version of the firewall cookbook. +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 @@ -13,7 +119,7 @@ v1.1.2 (2015-05-19) v1.1.1 (2015-05-11) ------------------- -* #57 - Suppress warning: already initialized constant XXX while Chefspec +* #57 - Suppress warning: already initialized constant XXX while Chefspec v1.1.0 (2015-04-27) ------------------- 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/README.md b/cookbooks/firewall/README.md index a3b55ab..4daab3c 100644 --- a/cookbooks/firewall/README.md +++ b/cookbooks/firewall/README.md @@ -1,101 +1,199 @@ firewall Cookbook ================= -[![Build Status](https://secure.travis-ci.org/opscode-cookbooks/firewall.png?branch=master)](http://travis-ci.org/opscode-cookbooks/firewall) + +[![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 ------------ -### Platform -* Ubuntu -* Debian -* Redhat -* CentOS +**Chef 12.4.x+** is required. We are currently testing against 12.5.1. 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 12.04 -* Ubuntu 14.04 -* Debian 7.8 -* CentOS 6.5 -* CentOS 7.0 +* Ubuntu 12.04 & 14.04 with iptables, ufw +* Debian 7.8, 8.1 with ufw +* CentOS 5.11, 6.7 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' => 4, + 'COMMIT_FILTER' => 100, + '*nat' => 101, + ':PREROUTING DROP' => 102, + ':POSTROUTING DROP' => 103, + ':OUTPUT ACCEPT' => 104, + 'COMMIT_NAT' => 200 +} +``` + +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 -Recipes -------- ### default The default recipe creates a firewall resource with action install, and if `node['firewall']['allow_ssh']`, opens port 22 from the world. +# Attributes -Attributes ----------- +* `default['firewall']['allow_ssh'] = false`, set true to open port 22 for SSH 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']['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` -Resources/Providers -------------------- -- See `librariez/z_provider_mapping.rb` for a full list of providers for each platform and version. +* `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 -#### Actions -- `:enable`: *Default action* enable the firewall. this will make any rules that have been defined 'active'. -- `:disable`: disable the firewall. drop any rules and put the node in an unprotected state. -- `:flush`: Runs `iptables -F`. Only supported by the iptables firewall provider. -- `:save`: Runs `service iptables save` under iptables, adds rules permanently under firewall. Not supported in ufw. -#### Attribute Parameters -- name: name attribute. arbitrary name to uniquely identify this resource -- log_level: level of verbosity the firewall should log at. valid values are: :low, :medium, :high, :full. default is :low. +***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. 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.` #### Examples ```ruby +# all defaults +firewall 'default' + # enable platform default firewall -firewall 'ufw' do - action :enable +firewall 'default' do + action :install end # increase logging past default of 'low' -firewall 'debug firewalls' do +firewall 'default' do log_level :high - action :enable + action :install end ``` ### firewall_rule #### Actions -- `:allow`: the rule should allow incoming traffic. -- `:deny`: the rule should deny incoming traffic. -- `:reject`: *Default action: the rule should reject incoming traffic. -- `:masqerade`: Add masqerade rule -- `:redirect`: Add redirect-type rule -- `:log`: Configure logging -- `:remove`: Remove all rules +- `: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. -#### Attribute Parameters -- name: name attribute. arbitrary name to uniquely identify this firewall rule -- protocol: valid values are: :udp, :tcp. default is all protocols -- port: incoming 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. -- source: ip address or subnet to filter on incoming traffic. default is `0.0.0.0/0` (ie Anywhere) -- destination: ip address or subnet to filter on outgoing traffic. -- dest_port: outgoing port number. -- position: position to insert rule at. if not provided rule is inserted at the end of the rule list. -- direction: direction of the rule. valid values are: :in, :out, default is :in -- interface: interface to apply rule (ie. 'eth0'). -- 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. -- raw: for passing a raw command to the provider (for use with custom modules, also used by zap provider to clean up non-chef managed rules) +#### 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. + +- `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, enable firewall +# open standard ssh port firewall_rule 'ssh' do port 22 - action :allow - notifies :enable, 'firewall[ufw]' + command :allow end # open standard http port to tcp traffic only; insert as first rule @@ -103,7 +201,7 @@ firewall_rule 'http' do port 80 protocol :tcp position 1 - action :allow + command :allow end # restrict port 13579 to 10.0.111.0/24 on eth0 @@ -112,7 +210,26 @@ firewall_rule 'myapplication' do source '10.0.111.0/24' direction :in interface 'eth0' - action :allow + 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 @@ -120,7 +237,7 @@ end firewall_rule 'mosh' do protocol :udp port 60000..61000 - action :allow + command :allow end # open multiple ports for http/https, note that the protocol @@ -131,19 +248,33 @@ firewall_rule 'http/https' do action :allow end -firewall 'ufw' do +firewall 'default' do + enabled false action :nothing end ``` +#### Providers -Development ------------ +- 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:opscode-cookbooks/firewall.git + $ git clone git@github.com:chef-cookbooks/firewall.git 2. Create a git branch @@ -168,12 +299,15 @@ This section details "quick development" steps. For a detailed explanation, see - Test Kitchen will run and converge the recipes -License & Authors ------------------ +# License & Authors + - Author:: Seth Chisamore () +- Author:: Ronald Doorn () +- Author:: Martin Smith () +- Author:: Sander van Harmelen () ```text -Copyright:: Copyright (c) 2011-2015 Opscode, Inc. +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. diff --git a/cookbooks/firewall/attributes/default.rb b/cookbooks/firewall/attributes/default.rb index 0047bdf..a13dfba 100644 --- a/cookbooks/firewall/attributes/default.rb +++ b/cookbooks/firewall/attributes/default.rb @@ -1 +1,2 @@ default['firewall']['allow_ssh'] = false +default['firewall']['allow_winrm'] = 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..32113fc --- /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 index de9bc2f..957613a 100644 --- a/cookbooks/firewall/attributes/ufw.rb +++ b/cookbooks/firewall/attributes/ufw.rb @@ -1,12 +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' + 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/libraries/helpers.rb b/cookbooks/firewall/libraries/helpers.rb index 3e28585..a5dcb23 100644 --- a/cookbooks/firewall/libraries/helpers.rb +++ b/cookbooks/firewall/libraries/helpers.rb @@ -1,13 +1,91 @@ module FirewallCookbook module Helpers + def dport_calc(new_resource) + new_resource.dest_port || new_resource.port + end + def port_to_s(p) - if p && p.is_a?(Integer) + if p.is_a?(String) + p + elsif p && p.is_a?(Integer) p.to_s elsif p && p.is_a?(Array) - p.join(',') + p.map! { |o| port_to_s(o) } + p.sort.join(',') elsif p && p.is_a?(Range) - "#{p.first}:#{p.last} " + 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 k.start_with?('COMMIT') + 'COMMIT' + else + k + end + end + end + "#{contents.join("\n")}\n" + 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..6245b87 --- /dev/null +++ b/cookbooks/firewall/libraries/helpers_firewalld.rb @@ -0,0 +1,106 @@ +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) + cmd = shell_out('firewall-cmd', '--get-default-zone') + cmd.stdout =~ /^#{z.to_s}$/ + end + + def firewalld_default_zone!(z) + 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! + 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! + 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! + 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}' " + 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..44c1c7d --- /dev/null +++ b/cookbooks/firewall/libraries/helpers_iptables.rb @@ -0,0 +1,105 @@ +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'] == 'rhel' || current_node['platform'] == 'centos') && 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}\" " + 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) + if ipv6_enabled?(new_resource) + %w(iptables iptables-ipv6) + else + %w(iptables) + end + 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] + 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)) + 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..c073c7f --- /dev/null +++ b/cookbooks/firewall/libraries/helpers_ufw.rb @@ -0,0 +1,129 @@ +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.' + fail 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|icmp)$') + 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.' + fail 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.strip + 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..f8e2c80 --- /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 + parameters['service'] = new_resource.service ? new_resource.service : 'any' + 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.source_interface ? new_resource.source_interface : 'any' + parameters['remoteip'] = new_resource.destination ? fixup_cidr(new_resource.destination) : 'any' + parameters['remoteport'] = port_to_s(new_resource.dest_port) ? 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 index bca47cb..474b3c2 100644 --- a/cookbooks/firewall/libraries/matchers.rb +++ b/cookbooks/firewall/libraries/matchers.rb @@ -2,31 +2,29 @@ if defined?(ChefSpec) ChefSpec.define_matcher(:firewall) ChefSpec.define_matcher(:firewall_rule) - def enable_firewall(resource) - ChefSpec::Matchers::ResourceMatcher.new(:firewall, :enable, resource) + # 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 allow_firewall_rule(resource) - ChefSpec::Matchers::ResourceMatcher.new(:firewall_rule, :allow, resource) + def flush_firewall(resource) + ChefSpec::Matchers::ResourceMatcher.new(:firewall, :flush, resource) end - def deny_firewall_rule(resource) - ChefSpec::Matchers::ResourceMatcher.new(:firewall_rule, :deny, resource) + def save_firewall(resource) + ChefSpec::Matchers::ResourceMatcher.new(:firewall, :save, resource) end - def reject_firewall_rule(resource) - ChefSpec::Matchers::ResourceMatcher.new(:firewall_rule, :reject, resource) - end - - def log_firewall_rule(resource) - ChefSpec::Matchers::ResourceMatcher.new(:firewall_rule, :log, resource) - end - - def remove_firewall_rule(resource) - ChefSpec::Matchers::ResourceMatcher.new(:firewall_rule, :remove, resource) + 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 index 7a3c022..84c97f7 100644 --- a/cookbooks/firewall/libraries/provider_firewall_firewalld.rb +++ b/cookbooks/firewall/libraries/provider_firewall_firewalld.rb @@ -15,78 +15,141 @@ # See the License for the specific language governing permissions and # limitations under the License. # -require 'poise' - class Chef - class Provider::FirewallFirewalld < Provider - include Poise - include Chef::Mixin::ShellOut + class Provider::FirewallFirewalld < Chef::Provider::LWRPBase + include FirewallCookbook::Helpers::Firewalld - def action_enable - # prints all the firewall rules - # pp @new_resource.subresources - log_current_firewalld - if active? - Chef::Log.debug("#{@new_resource} already enabled.") - else - Chef::Log.debug("#{@new_resource} is about to be enabled") - shell_out!('service', 'firewalld', 'start') - shell_out!('firewall-cmd', '--set-default-zone=drop') - Chef::Log.info("#{@new_resource} enabled.") - new_resource.updated_by_last_action(true) - end + provides :firewall, os: 'linux', platform_family: %w(rhel fedora) do |node| + node['platform_version'].to_f >= 7.0 && !node['firewall']['redhat7_iptables'] end - def action_disable - if active? - shell_out!('firewall-cmd', '--set-default-zone=public') - shell_out!('firewall-cmd', '--direct', '--remove-rules', 'ipv4', 'filter', 'INPUT') - shell_out!('firewall-cmd', '--direct', '--remove-rules', 'ipv4', 'filter', 'OUTPUT') - Chef::Log.info("#{@new_resource} disabled") - new_resource.updated_by_last_action(true) - else - Chef::Log.debug("#{@new_resource} already disabled.") - end + def whyrun_supported? + false end - def action_flush - 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') - Chef::Log.info("#{@new_resource} flushed.") - end + action :install do + next if disabled?(new_resource) - def action_save - if shell_out!('firewall-cmd', '--direct', '--get-all-rules').stdout != shell_out!('firewall-cmd', '--direct', '--permanent', '--get-all-rules').stdout - 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}") + converge_by('install firewalld, create template for /etc/sysconfig') do + package 'firewalld' do + action :install end - Chef::Log.info("#{@new_resource} saved.") + + service 'firewalld' do + action [:enable, :start] + end + + file "create empty #{firewalld_rules_filename}" do + path firewalld_rules_filename + content '# created by chef to allow service to start' + not_if { ::File.exist?(firewalld_rules_filename) } + end + end + end + + action :restart do + next 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 = 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 + begin + firewalld_file = run_context.resource_collection.find(file: firewalld_rules_filename) + rescue + firewalld_file = file firewalld_rules_filename do + action :nothing + end + end + firewalld_file.content build_rule_file(new_resource.rules['firewalld']) + firewalld_file.run_action(:create) + + # ensure the service is running + service 'firewalld' do + action [:enable, :start] + 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 + if firewalld_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) - else - Chef::Log.info("#{@new_resource} already up-to-date.") end end - private + action :disable do + next if disabled?(new_resource) - def active? - @active ||= begin - cmd = shell_out('firewall-cmd', '--state') - cmd.stdout =~ /^running$/ + firewalld_flush! + firewalld_default_zone!(new_resource.disabled_zone) + new_resource.updated_by_last_action(true) + + service 'firewalld' do + action [:disable, :stop] + end + + file "create empty #{firewalld_rules_filename}" do + path firewalld_rules_filename + content '# created by chef to allow service to start' + action :create end end - def log_current_firewalld - cmdstr = 'firewall-cmd --direct --get-all-rules' - Chef::Log.info("#{@new_resource} log_current_firewalld (#{cmdstr}):") - cmd = shell_out!(cmdstr) - Chef::Log.info(cmd.inspect) - rescue - Chef::Log.info("#{@new_resource} log_current_firewalld failed!") + action :flush do + next if disabled?(new_resource) + + firewalld_flush! + new_resource.updated_by_last_action(true) + + file "create empty #{firewalld_rules_filename}" do + path firewalld_rules_filename + content '# created by chef to allow service to start' + action :create + end + end + + action :save do + next if disabled?(new_resource) + + unless firewalld_all_rules_permanent! + firewalld_save! + new_resource.updated_by_last_action(true) + end end end end diff --git a/cookbooks/firewall/libraries/provider_firewall_iptables.rb b/cookbooks/firewall/libraries/provider_firewall_iptables.rb index 1fbe910..a699e9b 100644 --- a/cookbooks/firewall/libraries/provider_firewall_iptables.rb +++ b/cookbooks/firewall/libraries/provider_firewall_iptables.rb @@ -17,94 +17,139 @@ # See the License for the specific language governing permissions and # limitations under the License. # -require 'poise' - class Chef - class Provider::FirewallIptables < Provider - include Poise - include Chef::Mixin::ShellOut + class Provider::FirewallIptables < Chef::Provider::LWRPBase + include FirewallCookbook::Helpers + include FirewallCookbook::Helpers::Iptables - def action_enable - converge_by('install package iptables and default DROP if no rules exist') do - package 'iptables' do - action :install + 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 + + action :install do + next if disabled?(new_resource) + + converge_by('install iptables and enable/start services') do + # can't pass an array without breaking chef 11 support + iptables_packages(new_resource).each do |p| + package p do + action :install + end end - # prints all the firewall rules - # pp new_resource.subresources - log_current_iptables - if active? - Chef::Log.info("#{new_resource} already enabled.") - else - Chef::Log.debug("#{new_resource} is about to be enabled") - shell_out!('iptables -P INPUT DROP') - shell_out!('iptables -P OUTPUT DROP') - shell_out!('iptables -P FORWARD DROP') + iptables_commands(new_resource).each do |svc| + # must create empty file for service to start + file "create empty /etc/sysconfig/#{svc}" do + path "/etc/sysconfig/#{svc}" + content '# created by chef to allow service to start' + not_if { ::File.exist?("/etc/sysconfig/#{svc}") } + end - shell_out!('ip6tables -P INPUT DROP') - shell_out!('ip6tables -P OUTPUT DROP') - shell_out!('ip6tables -P FORWARD DROP') - Chef::Log.info("#{new_resource} enabled.") - new_resource.updated_by_last_action(true) + service svc do + action [:enable, :start] + end end end end - def action_disable - if active? - shell_out!('iptables -P INPUT ACCEPT') - shell_out!('iptables -P OUTPUT ACCEPT') - shell_out!('iptables -P FORWARD ACCEPT') - shell_out!('iptables -F') + action :restart do + next if disabled?(new_resource) - shell_out!('ip6tables -P INPUT ACCEPT') - shell_out!('ip6tables -P OUTPUT ACCEPT') - shell_out!('ip6tables -P FORWARD ACCEPT') - shell_out!('ip6tables -F') - Chef::Log.info("#{new_resource} disabled") + # 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 = 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| + iptables_filename = "/etc/sysconfig/#{iptables_type}" + # ensure a file resource exists with the current iptables rules + begin + iptables_file = run_context.resource_collection.find(file: iptables_filename) + rescue + iptables_file = file iptables_filename do + action :nothing + end + end + + # this takes the commands in each hash entry and builds a rule file + 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? + + service_affected = service iptables_type do + action :nothing + end + + new_resource.notifies(:restart, service_affected, :delayed) new_resource.updated_by_last_action(true) - else - Chef::Log.debug("#{new_resource} already disabled.") end end - def action_flush - shell_out!('iptables -F') - shell_out!('ip6tables -F') - Chef::Log.info("#{new_resource} flushed.") - end + action :disable do + next if disabled?(new_resource) - def action_save - shell_out!('service iptables save') - shell_out!('service ip6tables save') - Chef::Log.info("#{new_resource} saved.") - end + iptables_flush!(new_resource) + iptables_default_allow!(new_resource) + new_resource.updated_by_last_action(true) - private + iptables_commands(new_resource).each do |svc| + service svc do + action [:disable, :stop] + end - def active? - @active ||= begin - cmd = shell_out!('iptables-save') - cmd.stdout =~ /INPUT ACCEPT/ + # must create empty file for service to start + file "create empty /etc/sysconfig/#{svc}" do + path "/etc/sysconfig/#{svc}" + content '# created by chef to allow service to start' + end end - @active_v6 ||= begin - cmd = shell_out!('ip6tables-save') - cmd.stdout =~ /INPUT ACCEPT/ - end - @active && @active_v6 end - def log_current_iptables - cmdstr = 'iptables -L' - Chef::Log.info("#{new_resource} log_current_iptables (#{cmdstr}):") - cmd = shell_out!(cmdstr) - Chef::Log.info(cmd.inspect) - cmdstr = 'ip6tables -L' - Chef::Log.info("#{new_resource} log_current_iptables (#{cmdstr}):") - cmd = shell_out!(cmdstr) - Chef::Log.info(cmd.inspect) - rescue - Chef::Log.info("#{new_resource} log_current_iptables failed!") + action :flush do + next 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 + file "create empty /etc/sysconfig/#{svc}" do + path "/etc/sysconfig/#{svc}" + content '# created by chef to allow service to start' + end + end 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..10c8b89 --- /dev/null +++ b/cookbooks/firewall/libraries/provider_firewall_iptables_ubuntu.rb @@ -0,0 +1,158 @@ +# +# 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::FirewallIptablesUbuntu < Chef::Provider::LWRPBase + include FirewallCookbook::Helpers + include FirewallCookbook::Helpers::Iptables + + provides :firewall, os: 'linux', platform_family: %w(debian) do |node| + node['firewall'] && node['firewall']['ubuntu_iptables'] + end + + def whyrun_supported? + false + end + + action :install do + next if disabled?(new_resource) + + converge_by('install iptables and enable/start services') do + # Can't pass an array without breaking chef 11 support + %w(iptables-persistent).each do |p| + package p do + action :install + end + end + + %w(rules.v4 rules.v6).each do |svc| + # must create empty file for service to start + file "create empty /etc/iptables/#{svc}" do + path "/etc/iptables/#{svc}" + content '# created by chef to allow service to start' + not_if { ::File.exist?("/etc/iptables/#{svc}") } + end + end + + service 'iptables-persistent' do + action [:enable, :start] + end + end + end + + action :restart do + next 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 = 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 + + %w(iptables ip6tables).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 = 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 + + action :disable do + next if disabled?(new_resource) + + iptables_flush!(new_resource) + iptables_default_allow!(new_resource) + new_resource.updated_by_last_action(true) + + service 'iptables-persistent' do + action [:disable, :stop] + end + + %w(rules.v4 rules.v6).each do |svc| + # must create empty file for service to start + file "create empty /etc/iptables/#{svc}" do + path "/etc/iptables/#{svc}" + content '# created by chef to allow service to start' + action :create + end + end + end + + action :flush do + next if disabled?(new_resource) + + iptables_flush!(new_resource) + new_resource.updated_by_last_action(true) + + %w(rules.v4 rules.v6).each do |svc| + # must create empty file for service to start + file "create empty /etc/iptables/#{svc}" do + path "/etc/iptables/#{svc}" + content '# created by chef to allow service to start' + end + end + 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..3a0dbb3 --- /dev/null +++ b/cookbooks/firewall/libraries/provider_firewall_rule.rb @@ -0,0 +1,34 @@ +# +# Author:: Ronald Doorn () +# Cookbook Name:: firewall +# Provider:: rule_iptables +# +# Copyright 2015, 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 + + action :create do + return unless new_resource.notify_firewall + + firewall_resource = run_context.resource_collection.find(firewall: new_resource.firewall_name) + fail '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_rule_firewalld.rb b/cookbooks/firewall/libraries/provider_firewall_rule_firewalld.rb deleted file mode 100644 index efd6592..0000000 --- a/cookbooks/firewall/libraries/provider_firewall_rule_firewalld.rb +++ /dev/null @@ -1,213 +0,0 @@ -# -# Author:: Ronald Doorn () -# Cookbook Name:: firewall -# Provider:: rule_iptables -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT 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' - -class Chef - class Provider::FirewallRuleFirewalld < Provider - include Poise - include Chef::Mixin::ShellOut - include FirewallCookbook::Helpers - - def action_allow - apply_rule(:allow) - end - - def action_deny - apply_rule(:deny) - end - - def action_reject - apply_rule(:reject) - end - - def action_redirect - apply_rule(:redirect) - end - - def action_masquerade - apply_rule(:masquerade) - end - - def action_log - apply_rule(:log) - end - - def action_remove - # TODO: specify which target to delete - # for now this will remove raw + all targeted lines - remove_rule(:allow) - remove_rule(:deny) - remove_rule(:reject) - remove_rule(:redirect) - remove_rule(:masquerade) - end - - private - - CHAIN = { :in => 'INPUT', :out => 'OUTPUT', :pre => 'PREROUTING', :post => 'POSTROUTING' } unless defined? CHAIN # , nil => "FORWARD"} - TARGET = { :allow => 'ACCEPT', :reject => 'REJECT', :deny => 'DROP', :masquerade => 'MASQUERADE', :redirect => 'REDIRECT', :log => 'LOG --log-prefix \'iptables: \' --log-level 7' } unless defined? TARGET - - def apply_rule(type = nil) - ip_versions.each do |ip_version| - firewall_command = 'firewall-cmd --direct --add-rule ' - - # TODO: implement logging for :connections :packets - firewall_rule = build_firewall_rule(type, ip_version) - - Chef::Log.debug("#{new_resource}: #{firewall_rule}") - if rule_exists?(firewall_rule) - Chef::Log.info("#{new_resource} #{type} rule exists... won't apply") - else - cmdstr = firewall_command + firewall_rule - converge_by("firewall_rule[#{new_resource.name}] #{firewall_rule}") do - notifying_block do - shell_out!(cmdstr) # shell_out! is already logged - new_resource.updated_by_last_action(true) - end - end - end - end - end - - def remove_rule(type = nil) - ip_versions.each do |_ip_version| - firewall_command = 'firewall-cmd --direct --remove-rule ' - - # TODO: implement logging for :connections :packets - firewall_rule = build_firewall_rule(type) - - Chef::Log.debug("#{new_resource}: #{firewall_rule}") - if rule_exists?(firewall_rule) - cmdstr = firewall_command + firewall_rule - converge_by("firewall_rule[#{new_resource.name}] #{firewall_rule}") do - notifying_block do - shell_out!(cmdstr) # shell_out! is already logged - new_resource.updated_by_last_action(true) - end - end - else - Chef::Log.info("#{new_resource} #{type} rule does not exists... won't remove") - end - end - end - - def ipv4_rule? - if (new_resource.source && IPAddr.new(new_resource.source).ipv4?) || - (new_resource.destination && IPAddr.new(new_resource.destination).ipv4?) - true - else - false - end - end - - def ipv6_rule? - if (new_resource.source && IPAddr.new(new_resource.source).ipv6?) || - (new_resource.destination && IPAddr.new(new_resource.destination).ipv6?) - true - else - false - end - end - - def ip_versions - if ipv4_rule? - versions = ['ipv4'] - elsif ipv6_rule? - versions = ['ipv6'] - else # no source or destination address, add rules for both ipv4 and ipv6 - versions = %w(ipv4 ipv6) - end - versions - end - - def build_firewall_rule(type = nil, ip_version = 'ipv4') - if new_resource.raw - firewall_rule = new_resource.raw.strip - else - firewall_rule = "#{ip_version} filter " - if new_resource.direction - firewall_rule << "#{CHAIN[new_resource.direction.to_sym]} " - else - firewall_rule << 'FORWARD ' - end - firewall_rule << "#{new_resource.position ? new_resource.position : 1} " - - 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.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 - firewall_rule << '-m tcp ' if new_resource.protocol.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)} " if dport_calc - - firewall_rule << "-m state --state #{new_resource.stateful.is_a?(Array) ? new_resource.stateful.join(',').upcase : new_resource.stateful.upcase} " if new_resource.stateful - firewall_rule << "-m comment --comment '#{new_resource.description}' " - firewall_rule << "-j #{TARGET[type]} " - firewall_rule << "--to-ports #{new_resource.redirect_port} " if type == 'redirect' - firewall_rule.strip! - end - firewall_rule - end - - def rule_exists?(rule) - fail 'no rule supplied' unless rule - - # match quotes generously - detect_rule = rule.gsub(/'/, "'*") - detect_rule = detect_rule.gsub(/"/, '"*') - - match = shell_out!('firewall-cmd --direct --get-all-rules').stdout.lines.find do |line| - # Chef::Log.debug("matching: [#{detect_rule}] to [#{line.chomp.rstrip}]") - line =~ /#{detect_rule}/ - end - - match - rescue Mixlib::ShellOut::ShellCommandFailed - Chef::Log.debug("#{new_resource} check fails with: " + match.inspect) - Chef::Log.debug("#{new_resource} assuming #{rule} rule does not exist") - false - end - - def dport_calc - new_resource.dest_port || new_resource.port - end - - def ip_with_mask(ip) - if ip.include?('/') - ip - elsif ipv4_rule? - "#{ip}/32" - elsif ipv6_rule? - "#{ip}/128" - else - ip - end - end - end -end diff --git a/cookbooks/firewall/libraries/provider_firewall_rule_iptables.rb b/cookbooks/firewall/libraries/provider_firewall_rule_iptables.rb deleted file mode 100644 index 18fbcef..0000000 --- a/cookbooks/firewall/libraries/provider_firewall_rule_iptables.rb +++ /dev/null @@ -1,231 +0,0 @@ -# -# Cookbook Name:: firewall -# Provider:: rule_iptables -# -# Copyright 2012, 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. -# -require 'poise' - -class Chef - class Provider::FirewallRuleIptables < Provider - include Poise - include Chef::Mixin::ShellOut - include FirewallCookbook::Helpers - - def action_allow - apply_rule(:allow) - end - - def action_deny - apply_rule(:deny) - end - - def action_reject - apply_rule(:reject) - end - - def action_redirect - apply_rule(:redirect) - end - - def action_masquerade - apply_rule(:masquerade) - end - - def action_log - apply_rule(:log) - end - - def action_remove - # TODO: specify which target to delete - # for now this will remove raw + all targeted lines - remove_rule(:allow) - remove_rule(:deny) - remove_rule(:reject) - remove_rule(:redirect) - remove_rule(:masquerade) - end - - private - - CHAIN = { :in => 'INPUT', :out => 'OUTPUT', :pre => 'PREROUTING', :post => 'POSTROUTING' } unless defined? CHAIN # , nil => "FORWARD"} - TARGET = { :allow => 'ACCEPT', :reject => 'REJECT', :deny => 'DROP', :masquerade => 'MASQUERADE', :redirect => 'REDIRECT', :log => 'LOG --log-prefix "iptables: " --log-level 7' } unless defined? TARGET - - def apply_rule(type = nil) - firewall_commands = determine_iptables_commands - firewall_commands.each do |firewall_command| - ipv6 = (firewall_command == 'ip6tables') ? true : false - if new_resource.position - firewall_command << ' -I ' - else - firewall_command << ' -A ' - end - - # TODO: implement logging for :connections :packets - firewall_rule = build_firewall_rule(type) - - Chef::Log.debug("#{new_resource}: #{firewall_rule}") - if rule_exists?(firewall_rule, ipv6) - Chef::Log.info("#{new_resource} #{type} rule exists... won't apply") - else - cmdstr = firewall_command + firewall_rule - converge_by("firewall_rule[#{new_resource.name}] #{firewall_rule}") do - notifying_block do - shell_out!(cmdstr) # shell_out! is already logged - new_resource.updated_by_last_action(true) - end - end - end - end - end - - def remove_rule(type = nil) - firewall_commands = determine_iptables_commands - firewall_commands.each do |firewall_command| - ipv6 = (firewall_command == 'ip6tables') ? true : false - - # TODO: implement logging for :connections :packets - firewall_rule = build_firewall_rule(type) - - Chef::Log.debug("#{new_resource}: #{firewall_rule}") - if rule_exists?(firewall_rule, ipv6) - cmdstr = firewall_command + firewall_rule - converge_by("firewall_rule[#{new_resource.name}] #{firewall_rule}") do - notifying_block do - shell_out!(cmdstr) # shell_out! is already logged - new_resource.updated_by_last_action(true) - end - end - else - Chef::Log.info("#{new_resource} #{type} rule does not exist... won't remove") - end - end - end - - def ipv4_rule? - if (new_resource.source && IPAddr.new(new_resource.source).ipv4?) || - (new_resource.destination && IPAddr.new(new_resource.destination).ipv4?) - true - else - false - end - end - - def ipv6_rule? - if (new_resource.source && IPAddr.new(new_resource.source).ipv6?) || - (new_resource.destination && IPAddr.new(new_resource.destination).ipv6?) - true - else - false - end - end - - def determine_iptables_commands - if ipv4_rule? - commands = ['iptables'] - elsif ipv6_rule? - commands = ['ip6tables'] - else # no source or destination address, add rules for both ipv4 and ipv6 - commands = %w(iptables ip6tables) - end - commands - end - - def build_firewall_rule(type = nil) - if new_resource.raw - firewall_rule = new_resource.raw.strip - else - firewall_rule = '' - if new_resource.direction - firewall_rule << "#{CHAIN[new_resource.direction.to_sym]} " - else - firewall_rule << 'FORWARD ' - end - firewall_rule << "#{new_resource.position} " if new_resource.position - - if [:pre, :post].include?(new_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(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 - firewall_rule << '-m tcp ' if new_resource.protocol.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)} " if dport_calc - - firewall_rule << "-m state --state #{new_resource.stateful.is_a?(Array) ? new_resource.stateful.join(',').upcase : new_resource.stateful.upcase} " if new_resource.stateful - firewall_rule << "-m comment --comment \"#{new_resource.description}\" " - firewall_rule << "-j #{TARGET[type]} " - firewall_rule << "--to-ports #{new_resource.redirect_port} " if type == 'redirect' - firewall_rule.strip! - end - firewall_rule - end - - def rule_exists?(rule, ipv6 = false) - fail 'no rule supplied' unless rule - if new_resource.position - detect_rule = rule.gsub(/#{CHAIN[new_resource.direction]}\s(\d+)/, '\1' + " -A #{CHAIN[new_resource.direction]}") - else - detect_rule = rule - end - - # match quotes generously - detect_rule = detect_rule.gsub(/'/, "'*") - detect_rule = detect_rule.gsub(/"/, '"*') - - line_number = 0 - match = shell_out!(ipv6 ? 'ip6tables-save' : 'iptables-save').stdout.lines.find do |line| - next if line !~ /#{CHAIN[new_resource.direction]}/ - next if line[0] != '-' - line_number += 1 - line = "#{line_number} #{line}" if new_resource.position - # Chef::Log.debug("matching: [#{detect_rule}] to [#{line.chomp.rstrip}]") - line =~ /#{detect_rule}/ - end - - match - rescue Mixlib::ShellOut::ShellCommandFailed - Chef::Log.debug("#{new_resource} check fails with: " + match.inspect) - Chef::Log.debug("#{new_resource} assuming #{rule} rule does not exist") - false - end - - def dport_calc - new_resource.dest_port || new_resource.port - end - - def ip_with_mask(ip) - if ip.include?('/') - ip - elsif ipv4_rule? - "#{ip}/32" - elsif ipv6_rule? - "#{ip}/128" - else - ip - end - end - end -end diff --git a/cookbooks/firewall/libraries/provider_firewall_rule_ufw.rb b/cookbooks/firewall/libraries/provider_firewall_rule_ufw.rb deleted file mode 100644 index e7f84e2..0000000 --- a/cookbooks/firewall/libraries/provider_firewall_rule_ufw.rb +++ /dev/null @@ -1,241 +0,0 @@ -# -# Author:: Seth Chisamore () -# Cookbook Name:: firwall -# Resource:: rule -# -# 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. -# -require 'poise' - -class Chef - class Provider::FirewallRuleUfw < Provider - include Poise - include Chef::Mixin::ShellOut - include FirewallCookbook::Helpers - - def action_allow - if rule_exists? - Chef::Log.info("#{new_resource.name} already allowed, skipping") - else - apply_rule(:allow) - end - end - - def action_deny - if rule_exists? - Chef::Log.info("#{new_resource.name} already denied, skipping") - else - apply_rule(:deny) - end - end - - def action_reject - if rule_exists? - Chef::Log.info("#{new_resource.name} already rejected, skipping") - else - apply_rule(:reject) - end - end - - private - - def apply_rule(type = nil) # rubocop:disable MethodLength - Chef::Log.info("#{new_resource.name} apply_rule #{type}") - # 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 << "#{type} a stateful rule using #{new_resource.stateful} " - msg << 'but ufw does not support this kind of rule. Consider guarding by platform_family.' - fail 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 - - ufw_command = ['ufw'] - if new_resource.position - ufw_command << 'insert' - ufw_command << new_resource.position.to_s - end - ufw_command << type.to_s - ufw_command << rule.split - - converge_by("firewall_rule[#{new_resource.name}] #{rule}") do - notifying_block do - # fail 'should be no actions' - shell_out!(*ufw_command.flatten) - shell_out!('ufw', 'status', 'verbose') # purely for the Chef::Log.debug output - new_resource.updated_by_last_action(true) - end - end - end - - def rule - rule = '' - rule << rule_interface - rule << rule_logging - rule << rule_proto - rule << rule_dest_port - rule << rule_source_port - rule.strip - end - - def rule_interface - rule = '' - rule << "#{new_resource.direction} " if new_resource.direction - if new_resource.interface - if new_resource.direction - rule << "on #{new_resource.interface} " - else - rule << "in on #{new_resource.interface} " - end - end - rule - end - - def rule_proto - rule = '' - rule << "proto #{new_resource.protocol} " if new_resource.protocol - rule - end - - def rule_dest_port - rule = '' - if new_resource.destination - rule << "to #{new_resource.destination} " - else - rule << 'to any ' - end - rule << "port #{port_to_s(dport_calc)} " if dport_calc - rule - end - - def rule_source_port - rule = '' - - if new_resource.source - rule << "from #{new_resource.source} " - else - rule << 'from any ' - end - - if new_resource.source_port - rule << "port #{port_to_s(new_resource.source_port)} " - end - rule - end - - def rule_logging - case new_resource.logging && new_resource.logging.to_sym - when :connections - 'log ' - when :packets - 'log-all ' - else - '' - end - end - - # TODO: currently only works when firewall is enabled - def rule_exists? - Chef::Log.info("#{new_resource.name} rule_exists?") - # To Action From - # -- ------ ---- - # 22 ALLOW Anywhere - # 192.168.0.1 25/tcp DENY 10.0.0.0/8 - # 22 ALLOW Anywhere - # 3309 on eth9 ALLOW Anywhere - # Anywhere ALLOW Anywhere - # 80 ALLOW Anywhere (log) - # 8080 DENY 192.168.1.0/24 - # 1.2.3.5 5469/udp ALLOW 1.2.3.4 5469/udp - # 3308 ALLOW OUT Anywhere on eth8 - - to = rule_exists_to? # col 1 - action = rule_exists_action? # col 2 - from = rule_exists_from? # col 3 - - # full regex from columns - regex = rule_exists_regex?(to, action, from) - - match = shell_out!('ufw', 'status').stdout.lines.find do |line| - # TODO: support IPv6 - return false if line =~ /\(v6\)$/ - line =~ regex - end - - match - end - - def rule_exists_to? - to = '' - to << rule_exists_dest? - - proto = rule_exists_proto? - to << proto if proto - - if to.empty? - to << "Anywhere\s" - else - to - end - end - - def rule_exists_action? - action = new_resource.action - action = action.first if action.is_a?(Enumerable) - "#{Regexp.escape(action.to_s.upcase)}\s" - end - - def rule_exists_from? - if new_resource.source && new_resource.source != '0.0.0.0/0' - Regexp.escape(new_resource.source) - elsif new_resource.source - Regexp.escape('Anywhere') - end - end - - def rule_exists_dest? - if new_resource.destination - "#{Regexp.escape(new_resource.destination)}\s" - else - '' - end - end - - def rule_exists_regex?(to, action, from) - if to && new_resource.direction && new_resource.direction.to_sym == :out - /^#{to}.*#{action}OUT\s.*#{from}$/ - elsif to - /^#{to}.*#{action}.*#{from}$/ - end - end - - def rule_exists_proto? - if new_resource.protocol && dport_calc - "#{Regexp.escape(port_to_s(dport_calc))}/#{Regexp.escape(new_resource.protocol)}\s " - elsif dport_calc - "#{Regexp.escape(port_to_s(dport_calc))}\s " - end - end - - def dport_calc - new_resource.dest_port || new_resource.port - end - end -end diff --git a/cookbooks/firewall/libraries/provider_firewall_ufw.rb b/cookbooks/firewall/libraries/provider_firewall_ufw.rb index a5d4148..3299a7b 100644 --- a/cookbooks/firewall/libraries/provider_firewall_ufw.rb +++ b/cookbooks/firewall/libraries/provider_firewall_ufw.rb @@ -17,18 +17,25 @@ # See the License for the specific language governing permissions and # limitations under the License. # -require 'poise' - class Chef - class Provider::FirewallUfw < Provider - include Poise - include Chef::Mixin::ShellOut + class Provider::FirewallUfw < Chef::Provider::LWRPBase + include FirewallCookbook::Helpers::Ufw - def action_enable - converge_by('install ufw, template some defaults, and ufw enable') do + provides :firewall, os: 'linux', platform_family: %w(debian) do |node| + !(node['firewall'] && node['firewall']['ubuntu_iptables']) + end + + def whyrun_supported? + false + end + + action :install do + next if disabled?(new_resource) + + converge_by('install ufw, create template for /etc/default') do package 'ufw' do - action :nothing - end.run_action(:install) # need this now if running in a provider + action :install + end template '/etc/default/ufw' do action [:create] @@ -37,40 +44,87 @@ class Chef mode '0644' source 'ufw/default.erb' cookbook 'firewall' - action :nothing - end.run_action(:create) # need this now if running in a provider + end - # new_resource.subresources contains all the firewall rules - if active? - Chef::Log.debug("#{new_resource} already enabled.") - else - shell_out!('ufw', 'enable', :input => 'yes') - Chef::Log.info("#{new_resource} enabled") - if new_resource.log_level - shell_out!('ufw', 'logging', new_resource.log_level.to_s) - Chef::Log.info("#{new_resource} logging enabled at '#{new_resource.log_level}' level") - end - new_resource.updated_by_last_action(true) + file "create empty #{ufw_rules_filename}" do + path ufw_rules_filename + content '# created by chef to allow service to start' + not_if { ::File.exist?(ufw_rules_filename) } end end end - def action_disable - if active? - shell_out!('ufw', 'disable') - Chef::Log.info("#{new_resource} disabled") + action :restart do + next 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 = 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 + begin + ufw_file = run_context.resource_collection.find(file: ufw_rules_filename) + rescue + ufw_file = file ufw_rules_filename do + action :nothing + end + end + ufw_file.content build_rule_file(new_resource.rules['ufw']) + ufw_file.run_action(:create) + + # if the file was changed, restart iptables + if 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) - else - Chef::Log.debug("#{new_resource} already disabled.") end end - private + action :disable do + next if disabled?(new_resource) - def active? - @active ||= begin - cmd = shell_out!('ufw', 'status') - cmd.stdout =~ /^Status:\sactive/ + file "create empty #{ufw_rules_filename}" do + path ufw_rules_filename + content '# created by chef to allow service to start' + end + + if ufw_active? + ufw_disable! + new_resource.updated_by_last_action(true) + end + end + + action :flush do + next if disabled?(new_resource) + + ufw_reset! + new_resource.updated_by_last_action(true) + + file "create empty #{ufw_rules_filename}" do + path ufw_rules_filename + content '# created by chef to allow service to start' 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..3fcf0e3 --- /dev/null +++ b/cookbooks/firewall/libraries/provider_firewall_windows.rb @@ -0,0 +1,112 @@ +# +# Author:: Sander van Harmelen () +# Cookbook Name:: 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 + + action :install do + next if disabled?(new_resource) + + converge_by('enable and start Windows Firewall service') do + service 'MpsSvc' do + action [:enable, :start] + end + end + end + + action :restart do + next 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 = 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 + + # ensure a file resource exists with the current rules + begin + windows_file = 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 + if 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 + end + + action :disable do + next if disabled?(new_resource) + + converge_by('disable and stop Windows Firewall service') do + 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 + + service 'MpsSvc' do + action [:disable, :stop] + end + end + end + + action :flush do + next if disabled?(new_resource) + + reset! + Chef::Log.info("#{new_resource} reset.") + end + end +end diff --git a/cookbooks/firewall/libraries/resource_firewall.rb b/cookbooks/firewall/libraries/resource_firewall.rb index 7551f47..0959e1c 100644 --- a/cookbooks/firewall/libraries/resource_firewall.rb +++ b/cookbooks/firewall/libraries/resource_firewall.rb @@ -1,10 +1,23 @@ -require 'poise' - class Chef - class Resource::Firewall < Resource - include Poise(:container => true) + class Resource::Firewall < Chef::Resource::LWRPBase + resource_name(:firewall) + provides(:firewall) + actions(:install, :restart, :disable, :flush, :save) + default_action(:install) - actions(:enable, :disable, :flush, :save) - attribute(:log_level, :kind_of => [Symbol, String], :equal_to => [:low, :medium, :high, :full, 'low', 'medium', 'high', 'full'], :default => :low) + # 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], 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) end end diff --git a/cookbooks/firewall/libraries/resource_firewall_rule.rb b/cookbooks/firewall/libraries/resource_firewall_rule.rb index 6dc3f6d..274a874 100644 --- a/cookbooks/firewall/libraries/resource_firewall_rule.rb +++ b/cookbooks/firewall/libraries/resource_firewall_rule.rb @@ -1,36 +1,53 @@ -require 'poise' +require 'ipaddr' class Chef - class Resource::FirewallRule < Resource - include Poise(Chef::Resource::Firewall) + class Resource::FirewallRule < Chef::Resource::LWRPBase + include FirewallCookbook::Helpers - actions(:reject, :allow, :deny, :masquerade, :redirect, :log, :remove) + resource_name(:firewall_rule) + provides(:firewall_rule) + actions(:create) + default_action(:create) - attribute(:protocol, :kind_of => [Symbol, String], :equal_to => [:udp, :tcp, :icmp, 'tcp', 'udp', 'icmp'], :default => :tcp) - attribute(:direction, :kind_of => [Symbol, String], :equal_to => [:in, :out, :pre, :post, 'in', 'out', 'pre', 'post'], :default => :in) - attribute(:logging, :kind_of => [Symbol, String], :equal_to => [:connections, :packets, 'connections', 'packets']) + attribute(:firewall_name, kind_of: String, default: 'default') - attribute(:source, :callbacks => { 'must be a valid ip address' => ->(s) { valid_ip?(s) } }) - attribute(:source_port, :kind_of => [Integer, Array, Range]) # source port - attribute(:interface, :kind_of => String) + attribute(:command, kind_of: Symbol, equal_to: [:reject, :allow, :deny, :masquerade, :redirect, :log], default: :allow) - attribute(:port, :kind_of => [Integer, Array, Range]) # shorthand for dest_port - attribute(:destination, :callbacks => { 'must be a valid ip address' => ->(s) { valid_ip?(s) } }) - attribute(:dest_port, :kind_of => [Integer, Array, Range]) - attribute(:dest_interface, :kind_of => String) + 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|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(:position, :kind_of => Integer) - attribute(:stateful, :kind_of => [Symbol, String, Array]) - attribute(:redirect_port, :kind_of => Integer) - attribute(:description, :kind_of => String, :name_attribute => true) + 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) + + # 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) + attribute(:raw, kind_of: String) - def self.valid_ip?(ip) - IPAddr.new(ip) ? true : false - rescue - false - end + # 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/libraries/z_provider_mapping.rb b/cookbooks/firewall/libraries/z_provider_mapping.rb deleted file mode 100644 index 99cc31a..0000000 --- a/cookbooks/firewall/libraries/z_provider_mapping.rb +++ /dev/null @@ -1,22 +0,0 @@ -# provider mappings for Chef 11 -# https://www.chef.io/blog/2015/02/10/chef-12-provider-resolver/ - -######### -# firewall -######### -Chef::Platform.set platform: :centos, version: '< 7.0', resource: :firewall, provider: Chef::Provider::FirewallIptables -Chef::Platform.set platform: :centos, version: '>= 7.0', resource: :firewall, provider: Chef::Provider::FirewallFirewalld -Chef::Platform.set platform: :redhat, version: '< 7.0', resource: :firewall, provider: Chef::Provider::FirewallIptables -Chef::Platform.set platform: :redhat, version: '>= 7.0', resource: :firewall, provider: Chef::Provider::FirewallFirewalld -Chef::Platform.set platform: :debian, resource: :firewall, provider: Chef::Provider::FirewallUfw -Chef::Platform.set platform: :ubuntu, resource: :firewall, provider: Chef::Provider::FirewallUfw - -######### -# firewall_rule -######### -Chef::Platform.set platform: :centos, version: '< 7.0', resource: :firewall_rule, provider: Chef::Provider::FirewallRuleIptables -Chef::Platform.set platform: :centos, version: '>= 7.0', resource: :firewall_rule, provider: Chef::Provider::FirewallRuleFirewalld -Chef::Platform.set platform: :redhat, version: '< 7.0', resource: :firewall_rule, provider: Chef::Provider::FirewallRuleIptables -Chef::Platform.set platform: :redhat, version: '>= 7.0', resource: :firewall_rule, provider: Chef::Provider::FirewallRuleFirewalld -Chef::Platform.set platform: :debian, resource: :firewall_rule, provider: Chef::Provider::FirewallRuleUfw -Chef::Platform.set platform: :ubuntu, resource: :firewall_rule, provider: Chef::Provider::FirewallRuleUfw diff --git a/cookbooks/firewall/metadata.json b/cookbooks/firewall/metadata.json index da2a86c..b96eee2 100644 --- a/cookbooks/firewall/metadata.json +++ b/cookbooks/firewall/metadata.json @@ -1 +1 @@ -{"name":"firewall","version":"1.2.0","description":"Provides a set of primitives for managing firewalls and associated rules.","long_description":"firewall Cookbook\n=================\n[![Build Status](https://secure.travis-ci.org/opscode-cookbooks/firewall.png?branch=master)](http://travis-ci.org/opscode-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\n\nRequirements\n------------\n### Platform\n* Ubuntu\n* Debian\n* Redhat\n* CentOS\n\nTested on:\n* Ubuntu 12.04\n* Ubuntu 14.04\n* Debian 7.8\n* CentOS 6.5\n* CentOS 7.0\n\n\nRecipes\n-------\n### default\nThe default recipe creates a firewall resource with action install, and if `node['firewall']['allow_ssh']`, opens port 22 from the world.\n\n\nAttributes\n----------\n\n* `default['firewall']['ufw']['defaults']` hash for template `/etc/default/ufw`\n\nResources/Providers\n-------------------\n- See `librariez/z_provider_mapping.rb` for a full list of providers for each platform and version.\n\n### firewall\n#### Actions\n- `:enable`: *Default action* enable the firewall. this will make any rules that have been defined 'active'.\n- `:disable`: disable the firewall. drop any rules and put the node in an unprotected state.\n- `:flush`: Runs `iptables -F`. Only supported by the iptables firewall provider.\n- `:save`: Runs `service iptables save` under iptables, adds rules permanently under firewall. Not supported in ufw.\n\n#### Attribute Parameters\n- name: name attribute. arbitrary name to uniquely identify this resource\n- log_level: level of verbosity the firewall should log at. valid values are: :low, :medium, :high, :full. default is :low.\n\n#### Examples\n\n```ruby\n# enable platform default firewall\nfirewall 'ufw' do\n action :enable\nend\n\n# increase logging past default of 'low'\nfirewall 'debug firewalls' do\n log_level :high\n action :enable\nend\n```\n\n### firewall_rule\n\n#### Actions\n- `:allow`: the rule should allow incoming traffic.\n- `:deny`: the rule should deny incoming traffic.\n- `:reject`: *Default action: the rule should reject incoming traffic.\n- `:masqerade`: Add masqerade rule\n- `:redirect`: Add redirect-type rule\n- `:log`: Configure logging\n- `:remove`: Remove all rules\n\n#### Attribute Parameters\n- name: name attribute. arbitrary name to uniquely identify this firewall rule\n- protocol: valid values are: :udp, :tcp. default is all protocols\n- port: incoming 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.\n- source: ip address or subnet to filter on incoming traffic. default is `0.0.0.0/0` (ie Anywhere)\n- destination: ip address or subnet to filter on outgoing traffic.\n- dest_port: outgoing port number.\n- position: position to insert rule at. if not provided rule is inserted at the end of the rule list.\n- direction: direction of the rule. valid values are: :in, :out, default is :in\n- interface: interface to apply rule (ie. 'eth0').\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- raw: for passing a raw command to the provider (for use with custom modules, also used by zap provider to clean up non-chef managed rules)\n\n#### Examples\n\n```ruby\n# open standard ssh port, enable firewall\nfirewall_rule 'ssh' do\n port 22\n action :allow\n notifies :enable, 'firewall[ufw]'\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 action :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 action :allow\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 action :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 action :allow\nend\n\nfirewall 'ufw' do\n action :nothing\nend\n```\n\n\nDevelopment\n-----------\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:opscode-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\nLicense & Authors\n-----------------\n- Author:: Seth Chisamore ()\n\n```text\nCopyright:: Copyright (c) 2011-2015 Opscode, 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":"Opscode, Inc.","maintainer_email":"cookbooks@opscode.com","license":"Apache 2.0","platforms":{"ubuntu":">= 0.0.0","redhat":">= 0.0.0","centos":">= 0.0.0"},"dependencies":{"poise":"~> 2.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file +{"name":"firewall","version":"2.4.0","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.4.x+** is required. We are currently testing against 12.5.1. 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 12.04 & 14.04 with iptables, ufw\n* Debian 7.8, 8.1 with ufw\n* CentOS 5.11, 6.7 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' => 4,\n 'COMMIT_FILTER' => 100,\n '*nat' => 101,\n ':PREROUTING DROP' => 102,\n ':POSTROUTING DROP' => 103,\n ':OUTPUT ACCEPT' => 104,\n 'COMMIT_NAT' => 200\n}\n```\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, and if `node['firewall']['allow_ssh']`, opens port 22 from the world.\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_winrm'] = false`, set true to open port 5989 for WinRM when the default recipe runs\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']['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. 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\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- `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 action :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","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"},"dependencies":{"chef-sugar":">= 0.0.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file diff --git a/cookbooks/firewall/recipes/default.rb b/cookbooks/firewall/recipes/default.rb index 6d87dbc..6b68cdc 100644 --- a/cookbooks/firewall/recipes/default.rb +++ b/cookbooks/firewall/recipes/default.rb @@ -17,13 +17,40 @@ # limitations under the License. # +include_recipe 'chef-sugar' + firewall 'default' do - action :enable + 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 world to ssh' do port 22 source '0.0.0.0/0' - action [:allow] - only_if { node['firewall']['allow_ssh'] } + 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 + +# 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/homebrew/CHANGELOG.md b/cookbooks/homebrew/CHANGELOG.md index 0361900..0273c91 100644 --- a/cookbooks/homebrew/CHANGELOG.md +++ b/cookbooks/homebrew/CHANGELOG.md @@ -1,15 +1,49 @@ -homebrew Cookbook CHANGELOG -=========================== +# homebrew Cookbook CHANGELOG This file is used to list changes made in each version of the homebrew cookbook. -v1.12.0 (2015-01-29) --------------------- +## 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) --------------------- - +## 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 @@ -17,123 +51,90 @@ v1.11.0 (2015-01-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) --------------------- - +## 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 Opscode. - -v1.9.2 (2014-10-09) -------------------- +- `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) -------------------- +- 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) +- versions of Chef (10.10) New Features: - - #44 Add `:install` and `:uninstall` actions and alias previous `:cask`, - `:uncask` actions to them +- `: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) +- 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 +- maintain backward compat for 6 day old version -v1.8.0 (2014-07-23) -------------------- +## v1.8.0 (2014-07-23) - Add recipes to install an array of formulas/casks -v1.7.2 (2014-06-26) -------------------- +## v1.7.2 (2014-06-26) - Implement attribute to control auto-update - -v1.7.0 (2014-06-26) -------------------- +## v1.7.0 (2014-06-26) #38 - Add homebrew::cask recipe - -v1.6.6 (2014-05-29) -------------------- +## 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) -------------------- +## v1.6.4 (2014-05-08) - Fixing cask provider correctly this time. "brew cask list" - -v1.6.2 (2014-05-08) -------------------- +## v1.6.2 (2014-05-08) - Fixing typo in cask provider: 's/brew brew/brew/' - -v1.6.0 (2014-04-23) -------------------- +## 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 ------- +## v1.5.4 - [COOK-4023] Fix installer script's URL. - Fixing up style for rubocop - -v1.5.2 ------- +## v1.5.2 - [COOK-3825] setting $HOME on homebrew_package - -v1.5.0 ------- +## v1.5.0 ### Bug -- **[COOK-3589](https://tickets.opscode.com/browse/COOK-3589)** - Add homebrew as the default package manager on OS X Server +- **[COOK-3589](https://tickets.chef.io/browse/COOK-3589)** - Add homebrew as the default package manager on OS X Server -v1.4.0 ------- +## v1.4.0 ### Bug -- **[COOK-3283](https://tickets.opscode.com/browse/COOK-3283)** - Support running homebrew cookbook as root user, with sudo, or a non-privileged user +- **[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 ------- +## 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 ------- +## v1.3.0 - [COOK-1425] - use new json output format for formula - [COOK-1578] - Use shell_out! instead of popen4 -v1.2.0 ------- -Opscode has taken maintenance of this cookbook as the original author has other commitments. This is the initial release with Opscode as maintainer. +## 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" 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..c6a51ae --- /dev/null +++ b/cookbooks/homebrew/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 +* [Tim Smith](https://github.com/tas50) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Sean OMeara](https://github.com/someara) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) diff --git a/cookbooks/homebrew/README.md b/cookbooks/homebrew/README.md index 2a18087..2d2aa11 100644 --- a/cookbooks/homebrew/README.md +++ b/cookbooks/homebrew/README.md @@ -1,19 +1,14 @@ # 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://mxcl.github.com/homebrew/) and under Chef 11 and earlier versions, its package provider replaces MacPorts as the *default package provider* for the package resource on OS X systems. - -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](http://woss.name/2011/01/23/converging-your-home-directory-with-chef/) +This cookbook installs [Homebrew](http://mxcl.github.com/homebrew/) and under Chef 11 and earlier versions, its package provider replaces MacPorts as the _default package provider_ for the package resource on OS X systems. # Requirements - -Chef 12: The package provider is not necessary on Chef 12, as the default [OS X package provider](https://github.com/opscode/chef-rfc/blob/master/rfc016-homebrew-osx-package-provider.md) is homebrew. +Chef 12: The package provider is not necessary on Chef 12, as the default [OS X package provider](https://github.com/chef/chef-rfc/blob/master/rfc016-homebrew-osx-package-provider.md) is homebrew. Chef <= 11: The package provider will be set as the default provider for OS X. ## Prerequisites - In order for this recipe to work, your userid must own `/usr/local`. This is outside the scope of the cookbook because it's possible that you'll run the cookbook as your own user, not root and you'd have to be root to take ownership of the directory. Easiest way to get started: ```bash @@ -22,40 +17,49 @@ sudo chown -R `whoami`:staff /usr/local Bear in mind that this will take ownership of the entire folder and its contents, so if you've already got stuff in there (eg MySQL owned by a `mysql` user) you'll need to be a touch more careful. This is a recommendation from the Homebrew project. -**Note** This cookbook *only* supports installing in `/usr/local`. While the Homebrew project itself allows for alternative installations, this cookbook doesn't. +**Note** This cookbook _only_ supports installing in `/usr/local`. While the Homebrew project itself allows for alternative installations, this cookbook doesn't. ## Platform - - Mac OS X (10.6+) The only platform supported by Homebrew itself at the time of this writing is Mac OS X. It should work fine on Server edition as well, and on platforms that Homebrew supports in the future. ## Cookbooks - - build-essential: homebrew itself doesn't work well if XCode is not installed. # 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 + ``` + - `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 and Providers - This cookbook includes a package resource provider to use homebrew. Under Chef 12+, this is not necessary, and the code doesn't actually get used on Chef 12+. This was preserved to maintain backwards compatiblity with older versions of Chef. ## package / homebrew\_package - This cookbook provides a package provider called `homebrew_package` which will install/remove packages using Homebrew. This becomes the default provider for `package` if your platform is Mac OS X. As this extends the built-in package resource/provider in Chef, it has all the resource attributes and actions available to the package resource. However, a couple notes: - - Homebrew itself doesn't have a notion of "upgrade" per se. The "upgrade" action will simply perform an install, and if the Homebrew Formula for the package is newer, it will upgrade. - Likewise, Homebrew doesn't have a purge, but the "purge" action will act like "remove". -#### Examples +### Examples ```ruby package 'mysql' do @@ -74,7 +78,6 @@ end ``` ### homebrew\_tap - LWRP for `brew tap`, a Homebrew command used to add additional formula repositories. From the `brew` man page: ```text @@ -97,15 +100,11 @@ 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. +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 @@ -132,30 +131,31 @@ homebrew_cask "google-chrome" do end ``` -Default action is `:cask` which installs the Application binary . Use `:uncask` to -uninstall a an Application. +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. -- Author:: Graeme Mathieson () -- Author:: Joshua Timberman () +[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, Opscode, Inc -Copyright:: 2014-2015, Chef Software, Inc. +Copyright:: 2012-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 +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 diff --git a/cookbooks/homebrew/attributes/default.rb b/cookbooks/homebrew/attributes/default.rb index 2431299..06d2380 100644 --- a/cookbooks/homebrew/attributes/default.rb +++ b/cookbooks/homebrew/attributes/default.rb @@ -1,10 +1,10 @@ # -# Author:: Joshua Timberman () +# Author:: Joshua Timberman () # Author:: Graeme Mathieson () # Cookbook Name:: homebrew # Attributes:: default # -# Copyright 2011-2013, Opscode, Inc. +# Copyright 2011-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. diff --git a/cookbooks/homebrew/libraries/homebrew_mixin.rb b/cookbooks/homebrew/libraries/homebrew_mixin.rb index cc0a2f6..4b802a9 100644 --- a/cookbooks/homebrew/libraries/homebrew_mixin.rb +++ b/cookbooks/homebrew/libraries/homebrew_mixin.rb @@ -1,10 +1,10 @@ # -# Author:: Joshua Timberman () +# Author:: Joshua Timberman () # Author:: Graeme Mathieson () # Cookbook Name:: homebrew # Libraries:: homebrew_mixin # -# Copyright 2011-2013, Opscode, Inc. +# Copyright 2011-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. @@ -30,7 +30,8 @@ module Homebrew def homebrew_owner if defined?(Chef::Mixin::HomebrewUser) begin - @homebrew_owner ||= Chef12HomebrewUser.new.find_homebrew_uid + require 'etc' + @homebrew_owner ||= ::Etc.getpwuid(Chef12HomebrewUser.new.find_homebrew_uid).name rescue Chef::Exceptions::CannotDetermineHomebrewOwner @homebrew_owner ||= calculate_owner end @@ -45,7 +46,7 @@ module Homebrew owner = homebrew_owner_attr || sudo_user || current_user if owner == 'root' fail Chef::Exceptions::User, - "Homebrew owner is 'root' which is not supported. " + + "Homebrew owner is 'root' which is not supported. " \ "To set an explicit owner, please set node['homebrew']['owner']." end owner diff --git a/cookbooks/homebrew/libraries/homebrew_package.rb b/cookbooks/homebrew/libraries/homebrew_package.rb index 21f80cf..cda2bcf 100644 --- a/cookbooks/homebrew/libraries/homebrew_package.rb +++ b/cookbooks/homebrew/libraries/homebrew_package.rb @@ -1,10 +1,10 @@ # -# Author:: Joshua Timberman () +# Author:: Joshua Timberman () # Author:: Graeme Mathieson () # Cookbook Name:: homebrew # Libraries:: homebrew_package # -# Copyright 2011-2013, Opscode, Inc. +# Copyright 2011-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. @@ -22,7 +22,7 @@ # present on a node. This approach should avoid creating this class if # the node already has Chef::Provider::Package::Homebrew, such as with # Chef 12. -# https://github.com/opscode/chef-rfc/blob/master/rfc016-homebrew-osx-package-provider.md +# https://github.com/chef/chef-rfc/blob/master/rfc016-homebrew-osx-package-provider.md unless defined?(Chef::Provider::Package::Homebrew) && Chef::Platform.find('mac_os_x', nil)[:package] == Chef::Provider::Package::Homebrew require 'chef/provider/package' require 'chef/resource/package' @@ -46,15 +46,15 @@ unless defined?(Chef::Provider::Package::Homebrew) && Chef::Platform.find('mac_o @current_resource end - def install_package(name, version) + def install_package(name, _version) brew('install', @new_resource.options, name) end - def upgrade_package(name, version) + def upgrade_package(name, _version) brew('upgrade', name) end - def remove_package(name, version) + def remove_package(name, _version) brew('uninstall', @new_resource.options, name) end @@ -71,30 +71,17 @@ unless defined?(Chef::Provider::Package::Homebrew) && Chef::Platform.find('mac_o end def current_installed_version - pkg = get_version_from_formula - versions = pkg.to_hash['installed'].map { |v| v['version'] } + versions = package_info['installed'].map { |v| v['version'] } versions.join(' ') unless versions.empty? end def candidate_version - pkg = get_version_from_formula - pkg.stable ? pkg.stable.version.to_s : pkg.version.to_s + package_info['versions']['stable'] ? package_info['versions']['stable'].to_s : package_info['versions'].find { |_k, v| v if v.is_a?(String) } end - def get_version_from_command(command) - version = get_response_from_command(command).chomp - version.empty? ? nil : version - end - - def get_version_from_formula - brew_cmd = shell_out!('brew --prefix', :user => homebrew_owner) - libpath = ::File.join(brew_cmd.stdout.chomp, 'Library', 'Homebrew') - $LOAD_PATH.unshift(libpath) - - require 'global' - require 'cmd/info' - - Formula[new_resource.package_name] + def package_info + require 'json' + JSON.parse(brew('info', @new_resource.package_name, '--json=v1'))[0] end def get_response_from_command(command) @@ -102,7 +89,7 @@ unless defined?(Chef::Provider::Package::Homebrew) && Chef::Platform.find('mac_o home_dir = Etc.getpwnam(homebrew_owner).dir Chef::Log.debug "Executing '#{command}' as #{homebrew_owner}" - output = shell_out!(command, :user => homebrew_owner, :environment => { 'HOME' => home_dir, 'RUBYOPT' => nil }) + output = shell_out!(command, user: homebrew_owner, environment: { 'USER' => homebrew_owner, 'HOME' => home_dir, 'RUBYOPT' => nil }) output.stdout end end @@ -110,6 +97,6 @@ unless defined?(Chef::Provider::Package::Homebrew) && Chef::Platform.find('mac_o end end - Chef::Platform.set :platform => :mac_os_x_server, :resource => :package, :provider => Chef::Provider::Package::Homebrew - Chef::Platform.set :platform => :mac_os_x, :resource => :package, :provider => Chef::Provider::Package::Homebrew + Chef::Platform.set platform: :mac_os_x_server, resource: :package, provider: Chef::Provider::Package::Homebrew + Chef::Platform.set platform: :mac_os_x, resource: :package, provider: Chef::Provider::Package::Homebrew end diff --git a/cookbooks/homebrew/metadata.json b/cookbooks/homebrew/metadata.json index 34032be..0163800 100644 --- a/cookbooks/homebrew/metadata.json +++ b/cookbooks/homebrew/metadata.json @@ -1,33 +1 @@ -{ - "name": "homebrew", - "version": "1.12.0", - "description": "Install Homebrew, and use it as the OS X package provider on Chef versions =< 11", - "long_description": "", - "maintainer": "Chef Software, Inc.", - "maintainer_email": "cookbooks@chef.io", - "license": "Apache 2.0", - "platforms": { - "mac_os_x": ">= 0.0.0", - "mac_os_x_server": ">= 0.0.0" - }, - "dependencies": { - "build-essential": ">= 2.1.2" - }, - "recommendations": { - }, - "suggestions": { - }, - "conflicting": { - }, - "providing": { - }, - "replacing": { - }, - "attributes": { - }, - "groupings": { - }, - "recipes": { - "homebrew": "Install Homebrew" - } -} \ No newline at end of file +{"name":"homebrew","version":"2.0.5","description":"Install Homebrew, and use it as the OS X package provider on Chef versions =< 11","long_description":"# Homebrew Cookbook\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://mxcl.github.com/homebrew/) and under Chef 11 and earlier versions, its package provider replaces MacPorts as the _default package provider_ for the package resource on OS X systems.\n\n# Requirements\nChef 12: The package provider is not necessary on Chef 12, as the default [OS X package provider](https://github.com/chef/chef-rfc/blob/master/rfc016-homebrew-osx-package-provider.md) is homebrew.\n\nChef <= 11: The package provider will be set as the default provider for OS X.\n\n## Prerequisites\nIn order for this recipe to work, your userid must own `/usr/local`. This is outside the scope of the cookbook because it's possible that you'll run the cookbook as your own user, not root and you'd have to be root to take ownership of the directory. Easiest way to get started:\n\n```bash\nsudo chown -R `whoami`:staff /usr/local\n```\n\nBear in mind that this will take ownership of the entire folder and its contents, so if you've already got stuff in there (eg MySQL owned by a `mysql` user) you'll need to be a touch more careful. This is a recommendation from the Homebrew project.\n\n**Note** This cookbook _only_ supports installing in `/usr/local`. While the Homebrew project itself allows for alternative installations, this cookbook doesn't.\n\n## Platform\n- Mac OS X (10.6+)\n\nThe only platform supported by Homebrew itself at the time of this writing is Mac OS X. It should work fine on Server edition as well, and on platforms that Homebrew supports in the future.\n\n## Cookbooks\n- build-essential: homebrew itself doesn't work well if XCode is not installed.\n\n# Attributes\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 - 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- `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- `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 and Providers\nThis cookbook includes a package resource provider to use homebrew. Under Chef 12+, this is not necessary, and the code doesn't actually get used on Chef 12+. This was preserved to maintain backwards compatiblity with older versions of Chef.\n\n## package / homebrew\\_package\nThis cookbook provides a package provider called `homebrew_package` which will install/remove packages using Homebrew. This becomes the default provider for `package` if your platform is Mac OS X.\n\nAs this extends the built-in package resource/provider in Chef, it has all the resource attributes and actions available to the package resource. However, a couple notes:\n- Homebrew itself doesn't have a notion of \"upgrade\" per se. The \"upgrade\" action will simply perform an install, and if the Homebrew Formula for the package is newer, it will upgrade.\n- Likewise, Homebrew doesn't have a purge, but the \"purge\" action will act like \"remove\".\n\n### Examples\n\n```ruby\npackage 'mysql' do\n action :install\nend\n\nhomebrew_package 'mysql'\n\npackage 'mysql' do\n provider Chef::Provider::Package::Homebrew\nend\n\npackage 'wireshark' do\n options '--with-qt --devel'\nend\n```\n\n### homebrew\\_tap\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\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\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\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\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-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","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache 2.0","platforms":{"mac_os_x":">= 0.0.0","mac_os_x_server":">= 0.0.0"},"dependencies":{"build-essential":">= 2.1.2"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{"homebrew":"Install Homebrew"}} \ No newline at end of file diff --git a/cookbooks/homebrew/metadata.rb b/cookbooks/homebrew/metadata.rb deleted file mode 100644 index 0a3f2e1..0000000 --- a/cookbooks/homebrew/metadata.rb +++ /dev/null @@ -1,10 +0,0 @@ -name 'homebrew' -maintainer 'Chef Software, Inc.' -maintainer_email 'cookbooks@chef.io' -license 'Apache 2.0' -description 'Install Homebrew, and use it as the OS X package provider on Chef versions =< 11' -version '1.12.0' -recipe 'homebrew', 'Install Homebrew' -supports 'mac_os_x' -supports 'mac_os_x_server' -depends 'build-essential', '>= 2.1.2' diff --git a/cookbooks/homebrew/providers/cask.rb b/cookbooks/homebrew/providers/cask.rb index 4073ccc..822fff3 100644 --- a/cookbooks/homebrew/providers/cask.rb +++ b/cookbooks/homebrew/providers/cask.rb @@ -1,34 +1,45 @@ -require 'chef/mixin/shell_out' -include Chef::Mixin::ShellOut +# +# Cookbook Name:: homebrew +# Providers:: cask +# +# 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. +# + include ::Homebrew::Mixin -use_inline_resources if defined?(:use_inline_resources) +use_inline_resources def whyrun_supported? true end -def load_current_resource - @cask = Chef::Resource::HomebrewCask.new(new_resource.name) - Chef::Log.debug("Checking whether #{new_resource.name} is installed") - @cask.casked shell_out("/usr/local/bin/brew cask list | grep #{new_resource.name}").exitstatus == 0 -end - action :install do - unless @cask.casked - execute "installing cask #{new_resource.name}" do - command "/usr/local/bin/brew cask install #{new_resource.name}" - user homebrew_owner - end + 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 - if @cask.casked - execute "uninstalling cask #{new_resource.name}" do - command "/usr/local/bin/brew cask uninstall #{new_resource.name}" - user homebrew_owner - end + 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 diff --git a/cookbooks/homebrew/providers/tap.rb b/cookbooks/homebrew/providers/tap.rb index f3b8461..f82002d 100644 --- a/cookbooks/homebrew/providers/tap.rb +++ b/cookbooks/homebrew/providers/tap.rb @@ -1,10 +1,10 @@ # -# Author:: Joshua Timberman () +# Author:: Joshua Timberman () # Author:: Graeme Mathieson () # Cookbook Name:: homebrew # Providers:: tap # -# Copyright 2011-2013, Opscode, Inc. +# 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. @@ -21,6 +21,8 @@ include ::Homebrew::Mixin +use_inline_resources + def load_current_resource @tap = Chef::Resource::HomebrewTap.new(new_resource.name) tap_dir = @tap.name.gsub('/', '/homebrew-') @@ -37,6 +39,7 @@ 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 @@ -47,6 +50,7 @@ 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 diff --git a/cookbooks/homebrew/recipes/cask.rb b/cookbooks/homebrew/recipes/cask.rb index a44c452..ec4a1f1 100644 --- a/cookbooks/homebrew/recipes/cask.rb +++ b/cookbooks/homebrew/recipes/cask.rb @@ -2,7 +2,7 @@ # Cookbook Name:: homebrew # Recipes:: cask # -# Copyright 2014, Chef Software, Inc +# Copyright 2014-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. @@ -20,20 +20,19 @@ Chef::Resource.send(:include, Homebrew::Mixin) homebrew_tap 'caskroom/cask' -package 'brew-cask' - -execute 'update homebrew cask from github' do - user node['homebrew']['owner'] || homebrew_owner - command '/usr/local/bin/brew upgrade brew-cask && /usr/local/bin/brew cask cleanup || true' - only_if { node['homebrew']['auto-update'] } +directory '/Library/Caches/Homebrew/Casks' do + owner homebrew_owner + mode 00775 + only_if { ::Dir.exist?('/Library/Caches/Homebrew') } end directory '/opt/homebrew-cask' do - owner node['homebrew']['owner'] || homebrew_owner + owner homebrew_owner mode 00775 + recursive true end directory '/opt/homebrew-cask/Caskroom' do - owner node['homebrew']['owner'] || homebrew_owner + owner homebrew_owner mode 00775 end diff --git a/cookbooks/homebrew/recipes/default.rb b/cookbooks/homebrew/recipes/default.rb index 2dabcc9..d0caa8a 100644 --- a/cookbooks/homebrew/recipes/default.rb +++ b/cookbooks/homebrew/recipes/default.rb @@ -1,10 +1,10 @@ # -# Author:: Joshua Timberman () +# Author:: Joshua Timberman () # Author:: Graeme Mathieson () # Cookbook Name:: homebrew -# Recipes:: default +# Recipe:: default # -# Copyright 2011-2013, Opscode, Inc. +# 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. @@ -33,7 +33,8 @@ end execute 'install homebrew' do command homebrew_go - user node['homebrew']['owner'] || homebrew_owner + environment lazy { { 'HOME' => ::Dir.home(homebrew_owner), 'USER' => homebrew_owner } } + user homebrew_owner not_if { ::File.exist? '/usr/local/bin/brew' } end @@ -43,6 +44,7 @@ if node['homebrew']['auto-update'] 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 diff --git a/cookbooks/homebrew/recipes/install_casks.rb b/cookbooks/homebrew/recipes/install_casks.rb index 8ac4827..8da97ca 100644 --- a/cookbooks/homebrew/recipes/install_casks.rb +++ b/cookbooks/homebrew/recipes/install_casks.rb @@ -1,8 +1,8 @@ # # Cookbook Name:: homebrew -# Recipes:: install_casks +# Recipe:: install_casks # -# Copyright 2014, Chef Software, Inc +# Copyright 2014-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. diff --git a/cookbooks/homebrew/recipes/install_formulas.rb b/cookbooks/homebrew/recipes/install_formulas.rb index 0bb8495..ac37e7d 100644 --- a/cookbooks/homebrew/recipes/install_formulas.rb +++ b/cookbooks/homebrew/recipes/install_formulas.rb @@ -2,7 +2,7 @@ # Cookbook Name:: homebrew # Recipes:: install_casks # -# Copyright 2014, Chef Software, Inc +# Copyright 2014-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. @@ -20,5 +20,12 @@ include_recipe 'homebrew' node['homebrew']['formulas'].each do |formula| - package formula + if formula.class == Chef::Node::ImmutableMash + package formula.fetch(:name) do + options '--HEAD' if formula.fetch(:head, false) + 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 index 83d0f7b..9dac2bc 100644 --- a/cookbooks/homebrew/recipes/install_taps.rb +++ b/cookbooks/homebrew/recipes/install_taps.rb @@ -2,7 +2,7 @@ # Cookbook Name:: homebrew # Recipes:: install_taps # -# Copyright 2015, Chef Software, Inc +# Copyright 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. diff --git a/cookbooks/homebrew/resources/cask.rb b/cookbooks/homebrew/resources/cask.rb index 587bcea..797a0d9 100644 --- a/cookbooks/homebrew/resources/cask.rb +++ b/cookbooks/homebrew/resources/cask.rb @@ -1,19 +1,14 @@ actions :cask, :uncask, :install, :uninstall +default_action :install + attribute :name, - :name_attribute => true, - :kind_of => String, - :regex => /^[\w-]+$/ + name_attribute: true, + kind_of: String, + regex: /^[\w-]+$/ -attribute :casked, - :kind_of => [TrueClass, FalseClass] +attribute :options, + kind_of: String -if defined?(:default_action) - default_action :install -else - Chef::Log.warn("It appears you have Chef version #{Chef::VERSION},") - Chef::Log.warn('homebrew_cask resource will remove support for versions of Chef < 10.10 in the next major release of the cookbook') - def initialize(*args) - super - @action = :install - end +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 index e912f77..1592f30 100644 --- a/cookbooks/homebrew/resources/tap.rb +++ b/cookbooks/homebrew/resources/tap.rb @@ -1,10 +1,10 @@ # -# Author:: Joshua Timberman () +# Author:: Joshua Timberman () # Author:: Graeme Mathieson () # Cookbook Name:: homebrew # Resources:: tap # -# Copyright 2011-2013, Opscode, Inc. +# Copyright 2011-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. @@ -20,16 +20,12 @@ # actions :tap, :untap +default_action :tap + attribute :name, - :name_attribute => true, - :kind_of => String, - :regex => /^[\w-]+(?:\/[\w-]+)+$/ + name_attribute: true, + kind_of: String, + regex: %r{^[\w-]+(?:\/[\w-]+)+$} attribute :tapped, - :kind_of => [TrueClass, FalseClass] - -### hax for default action -def initialize(*args) - super - @action = :tap -end + kind_of: [TrueClass, FalseClass] diff --git a/cookbooks/iis/CHANGELOG.md b/cookbooks/iis/CHANGELOG.md index fc4a489..ef955cd 100644 --- a/cookbooks/iis/CHANGELOG.md +++ b/cookbooks/iis/CHANGELOG.md @@ -1,27 +1,50 @@ -v4.1.1 (2015-05-07) -------------------- +# iis Cookbook CHANGELOG +This file is used to list changes made in each version of the iis cookbook. + +## v4.1.6 (2016-02-01) +- Resolves issues with [Unable to set app pool to be "No Managed Code"](https://github.com/chef-cookbooks/iis/issues/240) +- Resolves [Add_mime_maps is throwing compile error](https://github.com/chef-cookbooks/iis/issues/238) +- Resolves [FATAL: NameError: iis_root "xxx" had an error: NameError: No resource, method, or local variable named `was _updated' for`LWRP provider iis_root from cookbook iis](https://github.com/chef-cookbooks/iis/issues/236) + +## v4.1.5 (2015-11-18) +- Resolves issues with `iis_root` [#222](https://github.com/chef-cookbooks/iis/issues/222) + +## v4.1.4 (2015-11-2) +- Re-added functionality for iis_pool auto_start, this was a breaking change + +## v4.1.3 (2015-10-30) +- Resolves Robucop issues +- Bug Fix for [#217](https://github.com/chef-cookbooks/iis/issues/217) + +## v4.1.2 (2015-10-21) +- Bug fixes for application pool provider and site provider +- Added the ability to detect the IIS Version, allowing for some properties to only exist for specific IIS versions +- Fixed issue with Win32 being required on linux +- Added support for mimeTypes and defaultDocuments on iis_sites +- Added iis config set and clear abilities + +## v4.1.1 (2015-05-07) - Detects changes in the physical path of apps. - Adds support for gMSA identity. - Performing add on a site will now reconfigure it if necessary. - Lock and unlock commands on configuration sections now use -commit:apphost. - Fix issue where popeline_mode was ignored during configuration of a pool. -v4.1.0 (2015-03-04) -------------------- +## v4.1.0 (2015-03-04) - Removed iis_pool attribute 'set_profile_environment' incompatible with < IIS-8. - Added pester test framework. - Condensed and fixed change-log to show public releases only. - Fixed bug where bindings were being overwritten by :config. - Code-cleanup and cosmetic fixes. -v4.0.0 (2015-02-12) -------------------- +## v4.0.0 (2015-02-12) - [#91](https://github.com/chef-cookbooks/iis/pull/91) - bulk addition of new features - Virtual Directory Support (allows virtual directories to be added to both websites and to webapplications under sites). - section unlock and lock support (this is used to allow for the web.config of a site to define the authentication methods). - fixed issue with :add on pool provider not running all config (this was a known issue and is now resolved). - fixed issue with :config on all providers causing application pool recycles (every chef-client run). - moved to better method for XML checking of previous settings to detect changes (changed all check to use xml searching with appcmd instead of the previous method [none]). + - Improved pool resource with many more apppool properties that can be set. - Fixed bug with default attribute inheritance. - New recipe to enable ASP.NET 4.5. @@ -34,150 +57,112 @@ v4.0.0 (2015-02-12) - [#98] Fixed issues with bindings. - added backwards compatibility for chef-client < 12.x.x Chef::Util::PathHelper. -v2.1.6 (2014-11-12) -------------------- +## v2.1.6 (2014-11-12) - [#78] Adds new_resource.updated_by_last_action calls -v2.1.5 (2014-09-15) -------------------- +## v2.1.5 (2014-09-15) - [#68] Add win_friendly_path to all appcmd.exe /physicalPath arguments -v2.1.4 (2014-09-13) -------------------- +## v2.1.4 (2014-09-13) - [#72] Adds chefspec matchers - [#57] Fixes site_id not being updated on a :config action -v2.1.2 (2014-04-23) -------------------- +## v2.1.2 (2014-04-23) - [COOK-4559] Remove invalid UTF-8 characters +## v2.1.0 (2014-03-25) +[COOK-4426] - feature order correction for proper installation [COOK-4428] - Add IIS FTP Feature Installation -v2.1.0 (2014-03-25) -------------------- -[COOK-4426] - feature order correction for proper installation -[COOK-4428] - Add IIS FTP Feature Installation - - -v2.0.4 (2014-03-18) -------------------- +## v2.0.4 (2014-03-18) - [COOK-4420] Corrected incorrect feature names for mod_security - -v2.0.2 (2014-02-25) -------------------- +## v2.0.2 (2014-02-25) - [COOK-4108] - Add documentation for the 'bindings' attribute in 'iis_site' LWRP - -v2.0.0 (2014-01-03) -------------------- +## v2.0.0 (2014-01-03) Major version bump - -v1.6.6 ------- +## v1.6.6 Adding extra windows platform checks to helper library - -v1.6.4 ------- +## v1.6.4 ### Bug - **[COOK-4138](https://tickets.chef.io/browse/COOK-4138)** - iis cookbook won't load on non-Windows platforms - -v1.6.2 ------- +## v1.6.2 ### Improvement - **[COOK-3634](https://tickets.chef.io/browse/COOK-3634)** - provide ability to set app pool managedRuntimeVersion to "No Managed Code" - -v1.6.0 ------- +## v1.6.0 ### Improvement - **[COOK-3922](https://tickets.chef.io/browse/COOK-3922)** - refactor IIS cookbook to not require WebPI - -v1.5.6 ------- +## v1.5.6 ### Improvement - **[COOK-3770](https://tickets.chef.io/browse/COOK-3770)** - Add Enabled Protocols to IIS App Recipe - -v1.5.4 ------- +## v1.5.4 ### New Feature - **[COOK-3675](https://tickets.chef.io/browse/COOK-3675)** - Add recipe for CGI module -v1.5.2 ------- +## v1.5.2 ### Bug - **[COOK-3232](https://tickets.chef.io/browse/COOK-3232)** - Allow `iis_app` resource `:config` action with a virtual path -v1.5.0 ------- +## v1.5.0 ### Improvement - - [COOK-2370]: add MVC2, escape `application_pool` and add options for - recycling +- recycling - [COOK-2694]: update iis documentation to show that Windows 2012 and - Windows 8 are supported +- Windows 8 are supported ### Bug - - [COOK-2325]: `load_current_resource` does not load state of pool - correctly, always sets running to false +- correctly, always sets running to false - [COOK-2526]: Installing IIS after .NET framework will leave - installation in non-working state +- installation in non-working state - [COOK-2596]: iis cookbook fails with indecipherable error if EULA - not accepted +- not accepted -v1.4.0 ------- -* [COOK-2181] -Adding full module support to iis cookbook +## v1.4.0 +- [COOK-2181] -Adding full module support to iis cookbook -v1.3.6 ------- -* [COOK-2084] - Add support for additional options during site creation -* [COOK-2152] - Add recipe for IIS6 metabase compatibility +## v1.3.6 +- [COOK-2084] - Add support for additional options during site creation +- [COOK-2152] - Add recipe for IIS6 metabase compatibility -v1.3.4 ------- -* [COOK-2050] - IIS cookbook does not have returns resource defined +## v1.3.4 +- [COOK-2050] - IIS cookbook does not have returns resource defined -v1.3.2 ------- -* [COOK-1251] - Fix LWRP "NotImplementedError" +## v1.3.2 +- [COOK-1251] - Fix LWRP "NotImplementedError" -v1.3.0 ------- -* [COOK-1301] - Add a recycle action to the iis_pool resource -* [COOK-1665] - app pool identity and new node[iis][component] attribute -* [COOK-1666] - Recipe to remove default site and app pool -* [COOK-1858] - Recipe misspelled +## v1.3.0 +- [COOK-1301] - Add a recycle action to the iis_pool resource +- [COOK-1665] - app pool identity and new node[iis][component] attribute +- [COOK-1666] - Recipe to remove default site and app pool +- [COOK-1858] - Recipe misspelled -v1.2.0 ------- -* [COOK-1061] - `iis_site` doesn't allow setting the pool -* [COOK-1078] - handle advanced bindings -* [COOK-1283] - typo on pool -* [COOK-1284] - install iis application initialization -* [COOK-1285] - allow multiple host_header, port and protocol -* [COOK-1286] - allow directly setting which app pool on site creation -* [COOK-1449] - iis pool regex returns true if similar site exists -* [COOK-1647] - mod_ApplicationInitialization isn't RC +## v1.2.0 +- [COOK-1061] - `iis_site` doesn't allow setting the pool +- [COOK-1078] - handle advanced bindings +- [COOK-1283] - typo on pool +- [COOK-1284] - install iis application initialization +- [COOK-1285] - allow multiple host_header, port and protocol +- [COOK-1286] - allow directly setting which app pool on site creation +- [COOK-1449] - iis pool regex returns true if similar site exists +- [COOK-1647] - mod_ApplicationInitialization isn't RC -v1.1.0 ------- -* [COOK-1012] - support adding apps -* [COOK-1028] - support for config command -* [COOK-1041] - fix removal in app pools -* [COOK-835] - add app pool management -* [COOK-950] - documentation correction for version of IIS/OS +## v1.1.0 +- [COOK-1012] - support adding apps +- [COOK-1028] - support for config command +- [COOK-1041] - fix removal in app pools +- [COOK-835] - add app pool management +- [COOK-950] - documentation correction for version of IIS/OS -v1.0.2 ------- -* Ruby 1.9 compat fixes -* ensure carriage returns are removed before applying regex +## v1.0.2 +- Ruby 1.9 compat fixes +- ensure carriage returns are removed before applying regex -v1.0.0 ------- -* [COOK-718] initial release +## v1.0.0 +- [COOK-718] initial release diff --git a/cookbooks/iis/CONTRIBUTING.md b/cookbooks/iis/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/iis/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/iis/MAINTAINERS.md b/cookbooks/iis/MAINTAINERS.md new file mode 100644 index 0000000..7a42dae --- /dev/null +++ b/cookbooks/iis/MAINTAINERS.md @@ -0,0 +1,25 @@ + + +# 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 +* [Adam Edwards](https://github.com/adamedx) + +# Maintainers +* [Adam Edwards](https://github.com/adamedx) +* [Kartik Null Cating-Subramanian](https://github.com/ksubrama) +* [Steven Murawski](https://github.com/smurawski) +* [Matt Wrock](https://github.com/mwrock) +* [Jay Mundrawala](https://github.com/jaym) +* [Claire McQuin](https://github.com/mcquin) +* [Salim Alam](https://github.com/chefsalim) +* [Sean OMeara](https://github.com/someara) +* [Tim Smith](https://github.com/tas50) +* [Jennifer Davis](https://github.com/sigje) diff --git a/cookbooks/iis/README.md b/cookbooks/iis/README.md index 36fcddf..222c14e 100644 --- a/cookbooks/iis/README.md +++ b/cookbooks/iis/README.md @@ -1,7 +1,29 @@ -Description -=========== +iis Cookbook +============ -Installs and configures Microsoft Internet Information Services (IIS) 7.0/7.5/8.0 +[![Build Status](https://travis-ci.org/chef-cookbooks/iis.svg?branch=master)](https://travis-ci.org/chef-cookbooks/iis) +[![Cookbook Version](https://img.shields.io/cookbook/v/iis.svg)](https://supermarket.chef.io/cookbooks/iis) + +Installs and configures Microsoft Internet Information Services (IIS) 7.0 and later + +Contents +======== + + * [Attributes](#attributes) + * [Resource/Provider](#resourceprovider) + * [iis_root](#iis_root) Allows for easy management of the IIS Root Machine settings + * [iis_site](#iis_site) Allows for easy management of IIS virtual sites (ie vhosts). + * [iis_config](#iis_config) Runs a config command on your IIS instance. + * [iis_pool](#iis_pool) Creates an application pool in IIS. + * [iis_app](#iis_app) Creates an application in IIS. + * [iis_vdir](#iis_vdir) Allows easy management of IIS virtual directories (i.e. vdirs). + * [iis_section](#iis_section) Allows for the locking/unlocking of application web.config sections. + * [iis_module](#iis_module) Manages modules globally or on a per site basis. + * [Usage](#usage) + * [default](#default) Default recipe + * [mod\_\*](#mod_) Recipes for installing individual IIS modules (extensions). + * [Alternatives ](#alternatives) + * [License and Author](#license-and-author) Requirements ============ @@ -36,10 +58,53 @@ Attributes Resource/Provider ================= +iis_root +--------- + +Allows for easy management of the IIS Root Machine settings + +### Actions +`default` = `:config` + +- `:add` - only does addition operations will not delete anything to an Array object +- `:delete` - only does deletion operations will not add anything to an Array object +- `:config` - does both addition and deletion make sure your Array objects contain everything you want + +### Attribute Parameters + +- `default_documents_enabled` - Enables or disables default_documents for the root machine, Valid Values: true, false default: `true` +- `default_documents` - The items you want to set as the default document collection, only used during `:config`. Array of strings, default: `['Default.htm', 'Default.asp', 'index.htm', 'index.html', 'iisstart.htm', 'default.aspx']` +- `mime_maps` - The items you want to set as the mime-maps or mime-types collection, only used during `:config`. Array of strings, default: +```ruby +["fileExtension='.323',mimeType='text/h323'", "fileExtension='.3g2',mimeType='video/3gpp2'", "fileExtension='.3gp2',mimeType='video/3gpp2'", "fileExtension='.3gp',mimeType='video/3gpp'", "fileExtension='.3gpp',mimeType='video/3gpp'", "fileExtension='.aaf',mimeType='application/octet-stream'", "fileExtension='.aac',mimeType='audio/aac'", "fileExtension='.aca',mimeType='application/octet-stream'", "fileExtension='.accdb',mimeType='application/msaccess'", "fileExtension='.accde',mimeType='application/msaccess'", "fileExtension='.accdt',mimeType='application/msaccess'", "fileExtension='.acx',mimeType='application/internet-property-stream'", "fileExtension='.adt',mimeType='audio/vnd.dlna.adts'", "fileExtension='.adts',mimeType='audio/vnd.dlna.adts'", "fileExtension='.afm',mimeType='application/octet-stream'", "fileExtension='.ai',mimeType='application/postscript'", "fileExtension='.aif',mimeType='audio/x-aiff'", "fileExtension='.aifc',mimeType='audio/aiff'", "fileExtension='.aiff',mimeType='audio/aiff'", "fileExtension='.application',mimeType='application/x-ms-application'", "fileExtension='.art',mimeType='image/x-jg'", "fileExtension='.asd',mimeType='application/octet-stream'", "fileExtension='.asf',mimeType='video/x-ms-asf'", "fileExtension='.asi',mimeType='application/octet-stream'", "fileExtension='.asm',mimeType='text/plain'", "fileExtension='.asr',mimeType='video/x-ms-asf'", "fileExtension='.asx',mimeType='video/x-ms-asf'", "fileExtension='.atom',mimeType='application/atom+xml'", "fileExtension='.au',mimeType='audio/basic'", "fileExtension='.avi',mimeType='video/avi'", "fileExtension='.axs',mimeType='application/olescript'", "fileExtension='.bas',mimeType='text/plain'", "fileExtension='.bcpio',mimeType='application/x-bcpio'", "fileExtension='.bin',mimeType='application/octet-stream'", "fileExtension='.bmp',mimeType='image/bmp'", "fileExtension='.c',mimeType='text/plain'", "fileExtension='.cab',mimeType='application/vnd.ms-cab-compressed'", "fileExtension='.calx',mimeType='application/vnd.ms-office.calx'", "fileExtension='.cat',mimeType='application/vnd.ms-pki.seccat'", "fileExtension='.cdf',mimeType='application/x-cdf'", "fileExtension='.chm',mimeType='application/octet-stream'", "fileExtension='.class',mimeType='application/x-java-applet'", "fileExtension='.clp',mimeType='application/x-msclip'", "fileExtension='.cmx',mimeType='image/x-cmx'", "fileExtension='.cnf',mimeType='text/plain'", "fileExtension='.cod',mimeType='image/cis-cod'", "fileExtension='.cpio',mimeType='application/x-cpio'", "fileExtension='.cpp',mimeType='text/plain'", "fileExtension='.crd',mimeType='application/x-mscardfile'", "fileExtension='.crl',mimeType='application/pkix-crl'", "fileExtension='.crt',mimeType='application/x-x509-ca-cert'", "fileExtension='.csh',mimeType='application/x-csh'", "fileExtension='.css',mimeType='text/css'", "fileExtension='.csv',mimeType='application/octet-stream'", "fileExtension='.cur',mimeType='application/octet-stream'", "fileExtension='.dcr',mimeType='application/x-director'", "fileExtension='.deploy',mimeType='application/octet-stream'", "fileExtension='.der',mimeType='application/x-x509-ca-cert'", "fileExtension='.dib',mimeType='image/bmp'", "fileExtension='.dir',mimeType='application/x-director'", "fileExtension='.disco',mimeType='text/xml'", "fileExtension='.dll',mimeType='application/x-msdownload'", "fileExtension='.dll.config',mimeType='text/xml'", "fileExtension='.dlm',mimeType='text/dlm'", "fileExtension='.doc',mimeType='application/msword'", "fileExtension='.docm',mimeType='application/vnd.ms-word.document.macroEnabled.12'", "fileExtension='.docx',mimeType='application/vnd.openxmlformats-officedocument.wordprocessingml.document'", "fileExtension='.dot',mimeType='application/msword'", "fileExtension='.dotm',mimeType='application/vnd.ms-word.template.macroEnabled.12'", "fileExtension='.dotx',mimeType='application/vnd.openxmlformats-officedocument.wordprocessingml.template'", "fileExtension='.dsp',mimeType='application/octet-stream'", "fileExtension='.dtd',mimeType='text/xml'", "fileExtension='.dvi',mimeType='application/x-dvi'", "fileExtension='.dvr-ms',mimeType='video/x-ms-dvr'", "fileExtension='.dwf',mimeType='drawing/x-dwf'", "fileExtension='.dwp',mimeType='application/octet-stream'", "fileExtension='.dxr',mimeType='application/x-director'", "fileExtension='.eml',mimeType='message/rfc822'", "fileExtension='.emz',mimeType='application/octet-stream'", "fileExtension='.eot',mimeType='application/vnd.ms-fontobject'", "fileExtension='.eps',mimeType='application/postscript'", "fileExtension='.etx',mimeType='text/x-setext'", "fileExtension='.evy',mimeType='application/envoy'", "fileExtension='.exe',mimeType='application/octet-stream'", "fileExtension='.exe.config',mimeType='text/xml'", "fileExtension='.fdf',mimeType='application/vnd.fdf'", "fileExtension='.fif',mimeType='application/fractals'", "fileExtension='.fla',mimeType='application/octet-stream'", "fileExtension='.flr',mimeType='x-world/x-vrml'", "fileExtension='.flv',mimeType='video/x-flv'", "fileExtension='.gif',mimeType='image/gif'", "fileExtension='.gtar',mimeType='application/x-gtar'", "fileExtension='.gz',mimeType='application/x-gzip'", "fileExtension='.h',mimeType='text/plain'", "fileExtension='.hdf',mimeType='application/x-hdf'", "fileExtension='.hdml',mimeType='text/x-hdml'", "fileExtension='.hhc',mimeType='application/x-oleobject'", "fileExtension='.hhk',mimeType='application/octet-stream'", "fileExtension='.hhp',mimeType='application/octet-stream'", "fileExtension='.hlp',mimeType='application/winhlp'", "fileExtension='.hqx',mimeType='application/mac-binhex40'", "fileExtension='.hta',mimeType='application/hta'", "fileExtension='.htc',mimeType='text/x-component'", "fileExtension='.htm',mimeType='text/html'", "fileExtension='.html',mimeType='text/html'", "fileExtension='.htt',mimeType='text/webviewhtml'", "fileExtension='.hxt',mimeType='text/html'", "fileExtension='.ico',mimeType='image/x-icon'", "fileExtension='.ics',mimeType='text/calendar'", "fileExtension='.ief',mimeType='image/ief'", "fileExtension='.iii',mimeType='application/x-iphone'", "fileExtension='.inf',mimeType='application/octet-stream'", "fileExtension='.ins',mimeType='application/x-internet-signup'", "fileExtension='.isp',mimeType='application/x-internet-signup'", "fileExtension='.IVF',mimeType='video/x-ivf'", "fileExtension='.jar',mimeType='application/java-archive'", "fileExtension='.java',mimeType='application/octet-stream'", "fileExtension='.jck',mimeType='application/liquidmotion'", "fileExtension='.jcz',mimeType='application/liquidmotion'", "fileExtension='.jfif',mimeType='image/pjpeg'", "fileExtension='.jpb',mimeType='application/octet-stream'", "fileExtension='.jpe',mimeType='image/jpeg'", "fileExtension='.jpeg',mimeType='image/jpeg'", "fileExtension='.jpg',mimeType='image/jpeg'", "fileExtension='.js',mimeType='application/javascript'", "fileExtension='.json',mimeType='application/json'", "fileExtension='.jsx',mimeType='text/jscript'", "fileExtension='.latex',mimeType='application/x-latex'", "fileExtension='.lit',mimeType='application/x-ms-reader'", "fileExtension='.lpk',mimeType='application/octet-stream'", "fileExtension='.lsf',mimeType='video/x-la-asf'", "fileExtension='.lsx',mimeType='video/x-la-asf'", "fileExtension='.lzh',mimeType='application/octet-stream'", "fileExtension='.m13',mimeType='application/x-msmediaview'", "fileExtension='.m14',mimeType='application/x-msmediaview'", "fileExtension='.m1v',mimeType='video/mpeg'", "fileExtension='.m2ts',mimeType='video/vnd.dlna.mpeg-tts'", "fileExtension='.m3u',mimeType='audio/x-mpegurl'", "fileExtension='.m4a',mimeType='audio/mp4'", "fileExtension='.m4v',mimeType='video/mp4'", "fileExtension='.man',mimeType='application/x-troff-man'", "fileExtension='.manifest',mimeType='application/x-ms-manifest'", "fileExtension='.map',mimeType='text/plain'", "fileExtension='.mdb',mimeType='application/x-msaccess'", "fileExtension='.mdp',mimeType='application/octet-stream'", "fileExtension='.me',mimeType='application/x-troff-me'", "fileExtension='.mht',mimeType='message/rfc822'", "fileExtension='.mhtml',mimeType='message/rfc822'", "fileExtension='.mid',mimeType='audio/mid'", "fileExtension='.midi',mimeType='audio/mid'", "fileExtension='.mix',mimeType='application/octet-stream'", "fileExtension='.mmf',mimeType='application/x-smaf'", "fileExtension='.mno',mimeType='text/xml'", "fileExtension='.mny',mimeType='application/x-msmoney'", "fileExtension='.mov',mimeType='video/quicktime'", "fileExtension='.movie',mimeType='video/x-sgi-movie'", "fileExtension='.mp2',mimeType='video/mpeg'", "fileExtension='.mp3',mimeType='audio/mpeg'", "fileExtension='.mp4',mimeType='video/mp4'", "fileExtension='.mp4v',mimeType='video/mp4'", "fileExtension='.mpa',mimeType='video/mpeg'", "fileExtension='.mpe',mimeType='video/mpeg'", "fileExtension='.mpeg',mimeType='video/mpeg'", "fileExtension='.mpg',mimeType='video/mpeg'", "fileExtension='.mpp',mimeType='application/vnd.ms-project'", "fileExtension='.mpv2',mimeType='video/mpeg'", "fileExtension='.ms',mimeType='application/x-troff-ms'", "fileExtension='.msi',mimeType='application/octet-stream'", "fileExtension='.mso',mimeType='application/octet-stream'", "fileExtension='.mvb',mimeType='application/x-msmediaview'", "fileExtension='.mvc',mimeType='application/x-miva-compiled'", "fileExtension='.nc',mimeType='application/x-netcdf'", "fileExtension='.nsc',mimeType='video/x-ms-asf'", "fileExtension='.nws',mimeType='message/rfc822'", "fileExtension='.ocx',mimeType='application/octet-stream'", "fileExtension='.oda',mimeType='application/oda'", "fileExtension='.odc',mimeType='text/x-ms-odc'", "fileExtension='.ods',mimeType='application/oleobject'", "fileExtension='.oga',mimeType='audio/ogg'", "fileExtension='.ogg',mimeType='video/ogg'", "fileExtension='.ogv',mimeType='video/ogg'", "fileExtension='.one',mimeType='application/onenote'", "fileExtension='.onea',mimeType='application/onenote'", "fileExtension='.onetoc',mimeType='application/onenote'", "fileExtension='.onetoc2',mimeType='application/onenote'", "fileExtension='.onetmp',mimeType='application/onenote'", "fileExtension='.onepkg',mimeType='application/onenote'", "fileExtension='.osdx',mimeType='application/opensearchdescription+xml'", "fileExtension='.otf',mimeType='font/otf'", "fileExtension='.p10',mimeType='application/pkcs10'", "fileExtension='.p12',mimeType='application/x-pkcs12'", "fileExtension='.p7b',mimeType='application/x-pkcs7-certificates'", "fileExtension='.p7c',mimeType='application/pkcs7-mime'", "fileExtension='.p7m',mimeType='application/pkcs7-mime'", "fileExtension='.p7r',mimeType='application/x-pkcs7-certreqresp'", "fileExtension='.p7s',mimeType='application/pkcs7-signature'", "fileExtension='.pbm',mimeType='image/x-portable-bitmap'", "fileExtension='.pcx',mimeType='application/octet-stream'", "fileExtension='.pcz',mimeType='application/octet-stream'", "fileExtension='.pdf',mimeType='application/pdf'", "fileExtension='.pfb',mimeType='application/octet-stream'", "fileExtension='.pfm',mimeType='application/octet-stream'", "fileExtension='.pfx',mimeType='application/x-pkcs12'", "fileExtension='.pgm',mimeType='image/x-portable-graymap'", "fileExtension='.pko',mimeType='application/vnd.ms-pki.pko'", "fileExtension='.pma',mimeType='application/x-perfmon'", "fileExtension='.pmc',mimeType='application/x-perfmon'", "fileExtension='.pml',mimeType='application/x-perfmon'", "fileExtension='.pmr',mimeType='application/x-perfmon'", "fileExtension='.pmw',mimeType='application/x-perfmon'", "fileExtension='.png',mimeType='image/png'", "fileExtension='.pnm',mimeType='image/x-portable-anymap'", "fileExtension='.pnz',mimeType='image/png'", "fileExtension='.pot',mimeType='application/vnd.ms-powerpoint'", "fileExtension='.potm',mimeType='application/vnd.ms-powerpoint.template.macroEnabled.12'", "fileExtension='.potx',mimeType='application/vnd.openxmlformats-officedocument.presentationml.template'", "fileExtension='.ppam',mimeType='application/vnd.ms-powerpoint.addin.macroEnabled.12'", "fileExtension='.ppm',mimeType='image/x-portable-pixmap'", "fileExtension='.pps',mimeType='application/vnd.ms-powerpoint'", "fileExtension='.ppsm',mimeType='application/vnd.ms-powerpoint.slideshow.macroEnabled.12'", "fileExtension='.ppsx',mimeType='application/vnd.openxmlformats-officedocument.presentationml.slideshow'", "fileExtension='.ppt',mimeType='application/vnd.ms-powerpoint'", "fileExtension='.pptm',mimeType='application/vnd.ms-powerpoint.presentation.macroEnabled.12'", "fileExtension='.pptx',mimeType='application/vnd.openxmlformats-officedocument.presentationml.presentation'", "fileExtension='.prf',mimeType='application/pics-rules'", "fileExtension='.prm',mimeType='application/octet-stream'", "fileExtension='.prx',mimeType='application/octet-stream'", "fileExtension='.ps',mimeType='application/postscript'", "fileExtension='.psd',mimeType='application/octet-stream'", "fileExtension='.psm',mimeType='application/octet-stream'", "fileExtension='.psp',mimeType='application/octet-stream'", "fileExtension='.pub',mimeType='application/x-mspublisher'", "fileExtension='.qt',mimeType='video/quicktime'", "fileExtension='.qtl',mimeType='application/x-quicktimeplayer'", "fileExtension='.qxd',mimeType='application/octet-stream'", "fileExtension='.ra',mimeType='audio/x-pn-realaudio'", "fileExtension='.ram',mimeType='audio/x-pn-realaudio'", "fileExtension='.rar',mimeType='application/octet-stream'", "fileExtension='.ras',mimeType='image/x-cmu-raster'", "fileExtension='.rf',mimeType='image/vnd.rn-realflash'", "fileExtension='.rgb',mimeType='image/x-rgb'", "fileExtension='.rm',mimeType='application/vnd.rn-realmedia'", "fileExtension='.rmi',mimeType='audio/mid'", "fileExtension='.roff',mimeType='application/x-troff'", "fileExtension='.rpm',mimeType='audio/x-pn-realaudio-plugin'", "fileExtension='.rtf',mimeType='application/rtf'", "fileExtension='.rtx',mimeType='text/richtext'", "fileExtension='.scd',mimeType='application/x-msschedule'", "fileExtension='.sct',mimeType='text/scriptlet'", "fileExtension='.sea',mimeType='application/octet-stream'", "fileExtension='.setpay',mimeType='application/set-payment-initiation'", "fileExtension='.setreg',mimeType='application/set-registration-initiation'", "fileExtension='.sgml',mimeType='text/sgml'", "fileExtension='.sh',mimeType='application/x-sh'", "fileExtension='.shar',mimeType='application/x-shar'", "fileExtension='.sit',mimeType='application/x-stuffit'", "fileExtension='.sldm',mimeType='application/vnd.ms-powerpoint.slide.macroEnabled.12'", "fileExtension='.sldx',mimeType='application/vnd.openxmlformats-officedocument.presentationml.slide'", "fileExtension='.smd',mimeType='audio/x-smd'", "fileExtension='.smi',mimeType='application/octet-stream'", "fileExtension='.smx',mimeType='audio/x-smd'", "fileExtension='.smz',mimeType='audio/x-smd'", "fileExtension='.snd',mimeType='audio/basic'", "fileExtension='.snp',mimeType='application/octet-stream'", "fileExtension='.spc',mimeType='application/x-pkcs7-certificates'", "fileExtension='.spl',mimeType='application/futuresplash'", "fileExtension='.spx',mimeType='audio/ogg'", "fileExtension='.src',mimeType='application/x-wais-source'", "fileExtension='.ssm',mimeType='application/streamingmedia'", "fileExtension='.sst',mimeType='application/vnd.ms-pki.certstore'", "fileExtension='.stl',mimeType='application/vnd.ms-pki.stl'", "fileExtension='.sv4cpio',mimeType='application/x-sv4cpio'", "fileExtension='.sv4crc',mimeType='application/x-sv4crc'", "fileExtension='.svg',mimeType='image/svg+xml'", "fileExtension='.svgz',mimeType='image/svg+xml'", "fileExtension='.swf',mimeType='application/x-shockwave-flash'", "fileExtension='.t',mimeType='application/x-troff'", "fileExtension='.tar',mimeType='application/x-tar'", "fileExtension='.tcl',mimeType='application/x-tcl'", "fileExtension='.tex',mimeType='application/x-tex'", "fileExtension='.texi',mimeType='application/x-texinfo'", "fileExtension='.texinfo',mimeType='application/x-texinfo'", "fileExtension='.tgz',mimeType='application/x-compressed'", "fileExtension='.thmx',mimeType='application/vnd.ms-officetheme'", "fileExtension='.thn',mimeType='application/octet-stream'", "fileExtension='.tif',mimeType='image/tiff'", "fileExtension='.tiff',mimeType='image/tiff'", "fileExtension='.toc',mimeType='application/octet-stream'", "fileExtension='.tr',mimeType='application/x-troff'", "fileExtension='.trm',mimeType='application/x-msterminal'", "fileExtension='.ts',mimeType='video/vnd.dlna.mpeg-tts'", "fileExtension='.tsv',mimeType='text/tab-separated-values'", "fileExtension='.ttf',mimeType='application/octet-stream'", "fileExtension='.tts',mimeType='video/vnd.dlna.mpeg-tts'", "fileExtension='.txt',mimeType='text/plain'", "fileExtension='.u32',mimeType='application/octet-stream'", "fileExtension='.uls',mimeType='text/iuls'", "fileExtension='.ustar',mimeType='application/x-ustar'", "fileExtension='.vbs',mimeType='text/vbscript'", "fileExtension='.vcf',mimeType='text/x-vcard'", "fileExtension='.vcs',mimeType='text/plain'", "fileExtension='.vdx',mimeType='application/vnd.ms-visio.viewer'", "fileExtension='.vml',mimeType='text/xml'", "fileExtension='.vsd',mimeType='application/vnd.visio'", "fileExtension='.vss',mimeType='application/vnd.visio'", "fileExtension='.vst',mimeType='application/vnd.visio'", "fileExtension='.vsto',mimeType='application/x-ms-vsto'", "fileExtension='.vsw',mimeType='application/vnd.visio'", "fileExtension='.vsx',mimeType='application/vnd.visio'", "fileExtension='.vtx',mimeType='application/vnd.visio'", "fileExtension='.wav',mimeType='audio/wav'", "fileExtension='.wax',mimeType='audio/x-ms-wax'", "fileExtension='.wbmp',mimeType='image/vnd.wap.wbmp'", "fileExtension='.wcm',mimeType='application/vnd.ms-works'", "fileExtension='.wdb',mimeType='application/vnd.ms-works'", "fileExtension='.webm',mimeType='video/webm'", "fileExtension='.wks',mimeType='application/vnd.ms-works'", "fileExtension='.wm',mimeType='video/x-ms-wm'", "fileExtension='.wma',mimeType='audio/x-ms-wma'", "fileExtension='.wmd',mimeType='application/x-ms-wmd'", "fileExtension='.wmf',mimeType='application/x-msmetafile'", "fileExtension='.wml',mimeType='text/vnd.wap.wml'", "fileExtension='.wmlc',mimeType='application/vnd.wap.wmlc'", "fileExtension='.wmls',mimeType='text/vnd.wap.wmlscript'", "fileExtension='.wmlsc',mimeType='application/vnd.wap.wmlscriptc'", "fileExtension='.wmp',mimeType='video/x-ms-wmp'", "fileExtension='.wmv',mimeType='video/x-ms-wmv'", "fileExtension='.wmx',mimeType='video/x-ms-wmx'", "fileExtension='.wmz',mimeType='application/x-ms-wmz'", "fileExtension='.woff',mimeType='font/x-woff'", "fileExtension='.wps',mimeType='application/vnd.ms-works'", "fileExtension='.wri',mimeType='application/x-mswrite'", "fileExtension='.wrl',mimeType='x-world/x-vrml'", "fileExtension='.wrz',mimeType='x-world/x-vrml'", "fileExtension='.wsdl',mimeType='text/xml'", "fileExtension='.wtv',mimeType='video/x-ms-wtv'", "fileExtension='.wvx',mimeType='video/x-ms-wvx'", "fileExtension='.x',mimeType='application/directx'", "fileExtension='.xaf',mimeType='x-world/x-vrml'", "fileExtension='.xaml',mimeType='application/xaml+xml'", "fileExtension='.xap',mimeType='application/x-silverlight-app'", "fileExtension='.xbap',mimeType='application/x-ms-xbap'", "fileExtension='.xbm',mimeType='image/x-xbitmap'", "fileExtension='.xdr',mimeType='text/plain'", "fileExtension='.xht',mimeType='application/xhtml+xml'", "fileExtension='.xhtml',mimeType='application/xhtml+xml'", "fileExtension='.xla',mimeType='application/vnd.ms-excel'", "fileExtension='.xlam',mimeType='application/vnd.ms-excel.addin.macroEnabled.12'", "fileExtension='.xlc',mimeType='application/vnd.ms-excel'", "fileExtension='.xlm',mimeType='application/vnd.ms-excel'", "fileExtension='.xls',mimeType='application/vnd.ms-excel'", "fileExtension='.xlsb',mimeType='application/vnd.ms-excel.sheet.binary.macroEnabled.12'", "fileExtension='.xlsm',mimeType='application/vnd.ms-excel.sheet.macroEnabled.12'", "fileExtension='.xlsx',mimeType='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'", "fileExtension='.xlt',mimeType='application/vnd.ms-excel'", "fileExtension='.xltm',mimeType='application/vnd.ms-excel.template.macroEnabled.12'", "fileExtension='.xltx',mimeType='application/vnd.openxmlformats-officedocument.spreadsheetml.template'", "fileExtension='.xlw',mimeType='application/vnd.ms-excel'", "fileExtension='.xml',mimeType='text/xml'", "fileExtension='.xof',mimeType='x-world/x-vrml'", "fileExtension='.xpm',mimeType='image/x-xpixmap'", "fileExtension='.xps',mimeType='application/vnd.ms-xpsdocument'", "fileExtension='.xsd',mimeType='text/xml'", "fileExtension='.xsf',mimeType='text/xml'", "fileExtension='.xsl',mimeType='text/xml'", "fileExtension='.xslt',mimeType='text/xml'", "fileExtension='.xsn',mimeType='application/octet-stream'", "fileExtension='.xtp',mimeType='application/octet-stream'", "fileExtension='.xwd',mimeType='image/x-xwindowdump'", "fileExtension='.z',mimeType='application/x-compress'", "fileExtension='.zip',mimeType='application/x-zip-compressed'"] +``` +- `add_default_documents` - The items you want to add to the default document collection, only used during `:add`. Array of strings, default: `[]` +- `add_mime_maps` - The items you want to add to the mime-map/mime-type collection, only used during `:add`. Array of strings, default: `[]` +- `delete_default_documents` - The items you want to delete from the default document collection, only used during `:delete`. Array of strings, default: `[]` +- `delete_mime_maps` - The items you want to delete from the mime-map/mime-type collection, only used during `:delete`. Array of strings, default: `[]` + +### Examples + +```ruby +# Add foo.html to default documents, and add '.dmg' as mime type extension at root level +iis_root 'add stuff' do + add_default_documents ['foo.html'] + add_mime_maps ["fileExtension='.dmg',mimeType='application/octet-stream'"] + action :add +end +``` +```ruby +# Remove index.html from default document and .323 as a mime type at root level +iis_root 'delete stuff' do + delete_default_documents ['index.html'] + delete_mime_maps ["fileExtension='.323',mimeType='text/h323'"] + action :delete +end +``` iis_site --------- -Allows easy management of IIS virtual sites (ie vhosts). +Allows for easy management of IIS virtual sites (ie vhosts). ### Actions @@ -52,7 +117,6 @@ Allows easy management of IIS virtual sites (ie vhosts). ### Attribute Parameters -- `product_id` - name attribute. Specifies the ID of a product to install. - `site_name` - name attribute. - `site_id` - if not given IIS generates a unique ID for the site - `path` - IIS will create a root application and a root virtual directory mapped to this specified local path @@ -79,6 +143,12 @@ end ```ruby # create and start a new site that maps to # the physical location C:\inetpub\wwwroot\testfu +# first the physical location must exist +directory "#{node['iis']['docroot']}/testfu" do + action :create +end + +# now create and start the site (note this will use the default application pool which must exist) iis_site 'Testfu Site' do protocol :http port 80 @@ -89,6 +159,12 @@ end ```ruby # do the same but map to testfu.chef.io domain +# first the physical location must exist +directory "#{node['iis']['docroot']}/testfu" do + action :create +end + +# now create and start the site (note this will use the default application pool which must exist) iis_site 'Testfu Site' do protocol :http port 80 @@ -101,11 +177,17 @@ end ```ruby # create and start a new site that maps to # the physical C:\inetpub\wwwroot\testfu +# first the physical location must exist +directory "#{node['iis']['docroot']}/testfu" do + action :create +end + # also adds bindings to http and https # binding http to the ip address 10.12.0.136, # the port 80, and the host header www.domain.com # also binding https to any ip address, # the port 443, and the host header www.domain.com +# now create and start the site (note this will use the default application pool which must exist) iis_site 'FooBar Site' do bindings "http/10.12.0.136:80:www.domain.com,https/*:443:www.domain.com path "#{node['iis']['docroot']}/testfu" @@ -119,7 +201,9 @@ Runs a config command on your IIS instance. ### Actions -- `:config` - Runs the configuration command +- `:set` - Edit configuration section (appcmd set config) +- `:clear` - Clear the section configuration (appcmd clear config) +- `:config` - [ DEPRECATED ] use `:set` instead ### Attribute Parameters @@ -130,20 +214,57 @@ Runs a config command on your IIS instance. ```ruby # Sets up logging iis_config "/section:system.applicationHost/sites /siteDefaults.logfile.directory:\"D:\\logs\"" do - action :config + action :set end ``` +```ruby +# Increase file upload size for 'MySite' +iis_config "\"MySite\" /section:requestfiltering /requestlimits.maxallowedcontentlength:50000000" do + action :set +end +``` + +```ruby +# Set IUSR username and password authentication +iis_config "\"MyWebsite/aSite\" -section:system.webServer/security/authentication/anonymousAuthentication /enabled:\"True\" /userName:\"IUSR_foobar\" /password:\"p@assword\" /commit:apphost" do + action :set +end +``` + +```ruby +# Authenticate with application pool +iis_config "\"MyWebsite/aSite\" -section:system.webServer/security/authentication/anonymousAuthentication /enabled:\"True\" /userName:\"\" /commit:apphost" do + action :set +end + +``` + ```ruby # Loads an array of commands from the node cfg_cmds = node['iis']['cfg_cmd'] cfg_cmds.each do |cmd| iis_config "#{cmd}" do - action :config + action :set end end ``` +```ruby +# Add static machine key at site level +iis_config "MySite /commit:site /section:machineKey /validation:AES /validationKey:AAAAAA /decryptionKey:ZZZZZ" do + action :set +end +``` + +```ruby +# Remove machine key +iis_config "MySite /commit:site /section:machineKey" + action :clear +end +``` + + iis_pool --------- Creates an application pool in IIS. @@ -181,6 +302,7 @@ Creates an application pool in IIS. - `logon_type` - Specifies the logon type for the process identity. (For additional information about [logon types](http://msdn.microsoft.com/en-us/library/aa378184%28VS.85%29.aspx), see the LogonUser Function topic on Microsoft's MSDN Web site.) - Available [:LogonBatch, :LogonService] - default is :LogonBatch - optional - `manual_group_membership` - Specifies whether the IIS_IUSRS group Security Identifier (SID) is added to the worker process token. When false, IIS automatically uses an application pool identity as though it were a member of the built-in IIS_IUSRS group, which has access to necessary file and system resources. When true, an application pool identity must be explicitly added to all resources that a worker process requires at runtime. - default is false - optional - `idle_timeout` - Specifies how long (in minutes) a worker process should run idle if no new requests are received and the worker process is not processing requests. After the allocated time passes, the worker process should request that it be shut down by the WWW service. - default is '00:20:00' - optional +- `idle_timeout_action` - Specifies the option of suspending an idle worker process rather than terminating it. Valid values are :Terminate and :Suspend - optional - `shutdown_time_limit` - Specifies the time that the W3SVC service waits after it initiated a recycle. If the worker process does not shut down within the shutdownTimeLimit, it will be terminated by the W3SVC service. - default is '00:01:30' - optional - `startup_time_limit` - Specifies the time that IIS waits for an application pool to start. If the application pool does not startup within the startupTimeLimit, the worker process is terminated and the rapid-fail protection count is incremented. - default is '00:01:30' - optional - `pinging_enabled` - Specifies whether pinging is enabled for the worker process. - default is true - optional @@ -233,6 +355,7 @@ Creates an application in IIS. - `:add` - add a new application pool - `:delete` - delete an existing application pool +- `:config` - configures an existing application pool ### Attribute Parameters @@ -383,6 +506,8 @@ Manages modules globally or on a per site basis. - `:add` - add a new module - `:delete` - delete a module +- `:install` - install a native module from the filesystem (.dll) +- `:uninstall` - uninstall a native module ### Attribute Parameters @@ -390,6 +515,8 @@ Manages modules globally or on a per site basis. - `type` - The type of module - `precondition` - precondition for module - `application` - The application or site to add the module to +- `add` - Whether the module you install has to be globally added +- `image` - Location of the DLL of the module to install ### Example @@ -436,6 +563,11 @@ This cookbook also contains recipes for installing individual IIS modules (exten Note: Not every possible IIS module has a corresponding recipe. The foregoing recipes are included for convenience, but users may also place additional IIS modules that are installable as Windows features into the ``node['iis']['components']`` array. +Alternatives +===== +* [Powershell based IIS Cookbook (Pre-DSC)](https://github.com/ebsco/iisposh) +* DSC Based- [CWebAdministration](https://github.com/PowerShellOrg/cWebAdministration) / [XWebadministration](https://github.com/PowerShell/xWebAdministration) Powershell Module(s) + License and Author ================== diff --git a/cookbooks/iis/attributes/default.rb b/cookbooks/iis/attributes/default.rb index 0635ec4..c4cfc98 100644 --- a/cookbooks/iis/attributes/default.rb +++ b/cookbooks/iis/attributes/default.rb @@ -25,3 +25,5 @@ default['iis']['docroot'] = "#{ENV['SYSTEMDRIVE']}\\inetpub\\wwwroot" default['iis']['log_dir'] = "#{ENV['SYSTEMDRIVE']}\\inetpub\\logs\\LogFiles" default['iis']['cache_dir'] = "#{ENV['SYSTEMDRIVE']}\\inetpub\\temp" default['iis']['components'] = [] + +default['iis']['source'] = nil diff --git a/cookbooks/iis/libraries/helper.rb b/cookbooks/iis/libraries/helper.rb index b036774..0cb3c69 100644 --- a/cookbooks/iis/libraries/helper.rb +++ b/cookbooks/iis/libraries/helper.rb @@ -3,6 +3,7 @@ # Library:: helper # # Author:: Julian C. Dunn +# Author:: Justin Schuhmann # # Copyright 2013, Chef Software, Inc. # @@ -23,11 +24,17 @@ module Opscode module IIS # Contains functions that are used throughout this cookbook module Helper + @iis_version = nil + if RUBY_PLATFORM =~ /mswin|mingw32|windows/ require 'chef/win32/version' + require 'win32/registry' end require 'rexml/document' + require 'chef/mixin/shell_out' + + include Chef::Mixin::ShellOut include REXML include Windows::Helper @@ -82,6 +89,15 @@ module Opscode "#{node['iis']['home']}\\appcmd.exe" end end + + def iis_version + if @iis_version.nil? + version_string = Win32::Registry::HKEY_LOCAL_MACHINE.open('SOFTWARE\Microsoft\InetStp').read('VersionString')[1] + version_string.slice! 'Version ' + @iis_version = version_string + end + @iis_version + end end end end diff --git a/cookbooks/iis/libraries/matcher.rb b/cookbooks/iis/libraries/matcher.rb index d146d21..ef82295 100644 --- a/cookbooks/iis/libraries/matcher.rb +++ b/cookbooks/iis/libraries/matcher.rb @@ -5,57 +5,59 @@ if defined?(ChefSpec) end [:config, :add, :delete].each do |action| - self.class.send(:define_method, "#{action}_iis_app", proc do |app_name| + self.class.send(:define_method, "#{action}_iis_app", proc do |app_name| ChefSpec::Matchers::ResourceMatcher.new(:iis_app, action, app_name) end - ) + ) end [:config].each do |action| - self.class.send(:define_method, "#{action}_iis_lock", proc do |section| + self.class.send(:define_method, "#{action}_iis_lock", proc do |section| ChefSpec::Matchers::ResourceMatcher.new(:iis_lock, action, section) end - ) + ) end - [:add, :delete].each do |action| + [:add, :delete, :install, :uninstall].each do |action| self.class.send(:define_method, "#{action}_iis_module", proc do |module_name| ChefSpec::Matchers::ResourceMatcher.new(:iis_module, action, module_name) end - ) + ) end [:add, :config, :delete, :start, :stop, :restart, :recycle].each do |action| self.class.send(:define_method, "#{action}_iis_pool", proc do |pool_name| ChefSpec::Matchers::ResourceMatcher.new(:iis_pool, action, pool_name) end - ) + ) end [:add, :delete, :start, :stop, :restart, :config].each do |action| self.class.send(:define_method, "#{action}_iis_site", proc do |site_name| ChefSpec::Matchers::ResourceMatcher.new(:iis_site, action, site_name) end - ) + ) end [:config].each do |action| - self.class.send(:define_method, "#{action}_iis_unlock", proc do |section| + self.class.send(:define_method, "#{action}_iis_unlock", proc do |section| ChefSpec::Matchers::ResourceMatcher.new(:iis_unlock, action, section) end - ) + ) end [:add, :config, :delete].each do |action| - self.class.send(:define_method, "#{action}_iis_vdir", proc do |section| + self.class.send(:define_method, "#{action}_iis_vdir", proc do |section| ChefSpec::Matchers::ResourceMatcher.new(:iis_vdir, action, section) end - ) + ) end - define_method = (Gem.loaded_specs['chefspec'].version < Gem::Version.new('4.1.0')) ? - ChefSpec::Runner.method(:define_runner_method) : - ChefSpec.method(:define_matcher) + if Gem.loaded_specs['chefspec'].version < Gem::Version.new('4.1.0') + define_method = ChefSpec::Runner.method(:define_runner_method) + else + define_method = ChefSpec.method(:define_matcher) + end define_method.call :iis_app define_method.call :iis_config diff --git a/cookbooks/iis/libraries/processors.rb b/cookbooks/iis/libraries/processors.rb new file mode 100644 index 0000000..b610671 --- /dev/null +++ b/cookbooks/iis/libraries/processors.rb @@ -0,0 +1,117 @@ +# +# Cookbook Name:: iis +# Library:: helper +# +# Author:: Justin Schuhmann +# +# 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. +# + +module Opscode + module IIS + # Contains functions that are used throughout this cookbook + module Processors + def default_documents(default_document, default_documents_enabled, add = true, remove = true, specifier = '') + cmd = shell_out! get_default_documents_command specifier + return unless cmd.stderr.empty? + xml = cmd.stdout + doc = REXML::Document.new xml + + is_new_default_documents_enabled = new_value?(doc.root, 'CONFIG/system.webServer-defaultDocument/@enabled', default_documents_enabled.to_s) + current_default_documents = REXML::XPath.match(doc.root, 'CONFIG/system.webServer-defaultDocument/files/add/@value').map(&:value) + cmd = default_documents_command specifier + + if is_new_default_documents_enabled + cmd << " /enabled:#{default_documents_enabled}" + end + + if add || remove + default_document.each do |document| + if !current_default_documents.include?(document) && add + cmd << " /+files.[value='#{document}']" + elsif current_default_documents.include?(document) && remove + cmd << " /-files.[value='#{document}']" + end + end + end + + if add && remove + current_default_documents.each do |document| + unless default_document.include? document + cmd << " /-files.[value='#{document}']" + end + end + end + + return unless cmd != default_documents_command(specifier) + shell_out! cmd + Chef::Log.info('Default Documents updated') + @was_updated = true + end + + def mime_maps(new_resource_mime_maps, add = true, remove = true, specifier = '') + # handles mime maps + cmd = shell_out get_mime_map_command specifier + return unless cmd.stderr.empty? + xml = cmd.stdout + doc = REXML::Document.new xml + current_mime_maps = REXML::XPath.match(doc.root, 'CONFIG/system.webServer-staticContent/mimeMap').map { |x| "fileExtension='#{x.attribute 'fileExtension'}',mimeType='#{x.attribute 'mimeType'}'" } + + cmd = mime_map_command specifier + + if add || remove + new_resource_mime_maps.each do |mime_map| + if !current_mime_maps.include?(mime_map) && add + cmd << " /+\"[#{mime_map}]\"" + elsif current_mime_maps.include?(mime_map) && remove + cmd << " /-\"[#{mime_map}]\"" + end + end + end + + if add && remove + current_mime_maps.each do |mime_map| + unless new_resource_mime_maps.include? mime_map + cmd << " /-\"[#{mime_map}]\"" + end + end + end + + return unless (cmd != mime_map_command(specifier)) + shell_out! cmd + Chef::Log.info('mime maps updated') + @was_updated = true + end + + private + + def get_default_documents_command(specifier = '') + "#{appcmd(node)} list config #{specifier} /section:defaultDocument /config:* /xml" + end + + def default_documents_command(specifier = '') + "#{appcmd(node)} set config #{specifier} /section:defaultDocument" + end + + def get_mime_map_command(specifier = '') + "#{appcmd(node)} list config #{specifier} /section:staticContent /config:* /xml" + end + + def mime_map_command(specifier = '') + "#{appcmd(node)} set config #{specifier} /section:staticContent" + end + end + end +end diff --git a/cookbooks/iis/metadata.json b/cookbooks/iis/metadata.json index 10fc6e8..b521f57 100644 --- a/cookbooks/iis/metadata.json +++ b/cookbooks/iis/metadata.json @@ -1 +1 @@ -{"name":"iis","version":"4.1.1","description":"Installs/Configures Microsoft Internet Information Services","long_description":"Description\n===========\n\nInstalls and configures Microsoft Internet Information Services (IIS) 7.0/7.5/8.0\n\nRequirements\n============\n\nPlatform\n--------\n\n* Windows Vista\n* Windows 7\n* Windows 8\n* Windows Server 2008 (R1, R2)\n* Windows Server 2012\n* Windows Server 2012R2\n\nWindows 2003R2 is *not* supported because it lacks Add/Remove Features.\n\nCookbooks\n---------\n\n* windows\n\nAttributes\n==========\n\n* `node['iis']['home']` - IIS main home directory. default is `%WINDIR%\\System32\\inetsrv`\n* `node['iis']['conf_dir']` - location where main IIS configs lives. default is `%WINDIR%\\System32\\inetsrv\\config`\n* `node['iis']['pubroot']` - . default is `%SYSTEMDRIVE%\\inetpub`\n* `node['iis']['docroot']` - IIS web site home directory. default is `%SYSTEMDRIVE%\\inetpub\\wwwroot`\n* `node['iis']['log_dir']` - location of IIS logs. default is `%SYSTEMDRIVE%\\inetpub\\logs\\LogFiles`\n* `node['iis']['cache_dir']` - location of cached data. default is `%SYSTEMDRIVE%\\inetpub\\temp`\n\nResource/Provider\n=================\n\niis_site\n---------\n\nAllows easy management of IIS virtual sites (ie vhosts).\n\n### Actions\n\n- `:add` - add a new virtual site\n- `:config` - apply configuration to an existing virtual site\n- `:delete` - delete an existing virtual site\n- `:start` - start a virtual site\n- `:stop` - stop a virtual site\n- `:restart` - restart a virtual site\n\n### Attribute Parameters\n\n- `product_id` - name attribute. Specifies the ID of a product to install.\n- `site_name` - name attribute.\n- `site_id` - if not given IIS generates a unique ID for the site\n- `path` - IIS will create a root application and a root virtual directory mapped to this specified local path\n- `protocol` - http protocol type the site should respond to. valid values are :http, :https. default is :http\n- `port` - port site will listen on. default is 80\n- `host_header` - host header (also known as domains or host names) the site should map to. default is all host headers\n- `options` - additional options to configure the site\n- `bindings` - Advanced options to configure the information required for requests to communicate with a Web site. See http://www.iis.net/configreference/system.applicationhost/sites/site/bindings/binding for parameter format. When binding is used, port protocol and host_header should not be used.\n- `application_pool` - set the application pool of the site\n- `options` - support for additional options -logDir, -limits, -ftpServer, etc...\n- `log_directory` - specifies the logging directory, where the log file and logging-related support files are stored.\n- `log_period` - specifies how often iis creates a new log file\n- `log_truncsize` - specifies the maximum size of the log file (in bytes) after which to create a new log file.\n\n### Examples\n\n```ruby\n# stop and delete the default site\niis_site 'Default Web Site' do\n action [:stop, :delete]\nend\n```\n\n```ruby\n# create and start a new site that maps to\n# the physical location C:\\inetpub\\wwwroot\\testfu\niis_site 'Testfu Site' do\n protocol :http\n port 80\n path \"#{node['iis']['docroot']}/testfu\"\n action [:add,:start]\nend\n```\n\n```ruby\n# do the same but map to testfu.chef.io domain\niis_site 'Testfu Site' do\n protocol :http\n port 80\n path \"#{node['iis']['docroot']}/testfu\"\n host_header \"testfu.chef.io\"\n action [:add,:start]\nend\n```\n\n```ruby\n# create and start a new site that maps to\n# the physical C:\\inetpub\\wwwroot\\testfu\n# also adds bindings to http and https\n# binding http to the ip address 10.12.0.136,\n# the port 80, and the host header www.domain.com\n# also binding https to any ip address,\n# the port 443, and the host header www.domain.com\niis_site 'FooBar Site' do\n bindings \"http/10.12.0.136:80:www.domain.com,https/*:443:www.domain.com\n path \"#{node['iis']['docroot']}/testfu\"\n action [:add,:start]\nend\n```\n\niis_config\n-----------\nRuns a config command on your IIS instance.\n\n### Actions\n\n- `:config` - Runs the configuration command\n\n### Attribute Parameters\n\n- `cfg_cmd` - name attribute. What ever command you would pass in after \"appcmd.exe set config\"\n\n### Example\n\n```ruby\n# Sets up logging\niis_config \"/section:system.applicationHost/sites /siteDefaults.logfile.directory:\\\"D:\\\\logs\\\"\" do\n action :config\nend\n```\n\n```ruby\n# Loads an array of commands from the node\ncfg_cmds = node['iis']['cfg_cmd']\ncfg_cmds.each do |cmd|\n iis_config \"#{cmd}\" do\n action :config\n end\nend\n```\n\niis_pool\n---------\nCreates an application pool in IIS.\n\n### Actions\n\n- `:add` - add a new application pool\n- `:config` - apply configuration to an existing application pool\n- `:delete` - delete an existing application pool\n- `:start` - start a application pool\n- `:stop` - stop a application pool\n- `:restart` - restart a application pool\n- `:recycle` - recycle an application pool\n\n### Attribute Parameters\n\n#### Root Items\n- `pool_name` - name attribute. Specifies the name of the pool to create.\n- `runtime_version` - specifies what .NET version of the runtime to use.\n- `pipeline_mode` - specifies what pipeline mode to create the pool with, valid values are :Integrated or :Classic, the default is :Integrated\n- `no_managed_code` - allow Unmanaged Code in setting up IIS app pools is shutting down. - default is true - optional\n\n#### Add Items\n- `start_mode` - Specifies the startup type for the application pool - default :OnDemand (:OnDemand, :AlwaysRunning) - optional\n- `auto_start` - When true, indicates to the World Wide Web Publishing Service (W3SVC) that the application pool should be automatically started when it is created or when IIS is started. - boolean: default true - optional\n- `queue_length` - Indicates to HTTP.sys how many requests to queue for an application pool before rejecting future requests. - default is 1000 - optional\n- `thirty_two_bit` - set the pool to run in 32 bit mode, valid values are true or false, default is false - optional\n\n#### Process Model Items\n- `max_proc` - specifies the number of worker processes associated with the pool.\n- `load_user_profile` - This property is used only when a service starts in a named user account. - Default is false - optional\n- `pool_identity` - the account identity that they app pool will run as, valid values are :SpecificUser, :NetworkService, :LocalService, :LocalSystem, :ApplicationPoolIdentity\n- `pool_username` - username for the identity for the application pool\n- `pool_password` password for the identity for the application pool is started. Default is true - optional\n- `logon_type` - Specifies the logon type for the process identity. (For additional information about [logon types](http://msdn.microsoft.com/en-us/library/aa378184%28VS.85%29.aspx), see the LogonUser Function topic on Microsoft's MSDN Web site.) - Available [:LogonBatch, :LogonService] - default is :LogonBatch - optional\n- `manual_group_membership` - Specifies whether the IIS_IUSRS group Security Identifier (SID) is added to the worker process token. When false, IIS automatically uses an application pool identity as though it were a member of the built-in IIS_IUSRS group, which has access to necessary file and system resources. When true, an application pool identity must be explicitly added to all resources that a worker process requires at runtime. - default is false - optional\n- `idle_timeout` - Specifies how long (in minutes) a worker process should run idle if no new requests are received and the worker process is not processing requests. After the allocated time passes, the worker process should request that it be shut down by the WWW service. - default is '00:20:00' - optional\n- `shutdown_time_limit` - Specifies the time that the W3SVC service waits after it initiated a recycle. If the worker process does not shut down within the shutdownTimeLimit, it will be terminated by the W3SVC service. - default is '00:01:30' - optional\n- `startup_time_limit` - Specifies the time that IIS waits for an application pool to start. If the application pool does not startup within the startupTimeLimit, the worker process is terminated and the rapid-fail protection count is incremented. - default is '00:01:30' - optional\n- `pinging_enabled` - Specifies whether pinging is enabled for the worker process. - default is true - optional\n- `ping_interval` - Specifies the time between health-monitoring pings that the WWW service sends to a worker process - default is '00:00:30' - optional\n- `ping_response_time` - Specifies the time that a worker process is given to respond to a health-monitoring ping. After the time limit is exceeded, the WWW service terminates the worker process - default is '00:01:30' - optional\n\n#### Recycling Items\n- `disallow_rotation_on_config_change` - The DisallowRotationOnConfigChange property specifies whether or not the World Wide Web Publishing Service (WWW Service) should rotate worker processes in an application pool when the configuration has changed. - Default is false - optional\n- `disallow_overlapping_rotation` - Specifies whether the WWW Service should start another worker process to replace the existing worker process while that process\n- `recycle_after_time` - specifies a pool to recycle at regular time intervals, d.hh:mm:ss, d optional\n- `recycle_at_time` - schedule a pool to recycle at a specific time, d.hh:mm:ss, d optional\n- `private_mem` - specifies the amount of private memory (in kilobytes) after which you want the pool to recycle\n\n#### Failure Items\n- `load_balancer_capabilities` - Specifies behavior when a worker process cannot be started, such as when the request queue is full or an application pool is in rapid-fail protection. - default is :HttpLevel - optional\n- `orphan_worker_process` - Specifies whether to assign a worker process to an orphan state instead of terminating it when an application pool fails. - default is false - optional\n- `orphan_action_exe` - Specifies an executable to run when the WWW service orphans a worker process (if the orphanWorkerProcess attribute is set to true). You can use the orphanActionParams attribute to send parameters to the executable. - optional\n- `orphan_action_params` - Indicates command-line parameters for the executable named by the orphanActionExe attribute. To specify the process ID of the orphaned process, use %1%. - optional\n- `rapid_fail_protection` - Setting to true instructs the WWW service to remove from service all applications that are in an application pool - default is true - optional\n- `rapid_fail_protection_interval` - Specifies the number of minutes before the failure count for a process is reset. - default is '00:05:00' - optional\n- `rapid_fail_protection_max_crashes` - Specifies the maximum number of failures that are allowed within the number of minutes specified by the rapidFailProtectionInterval attribute. - default is 5 - optional\n- `auto_shutdown_exe` - Specifies an executable to run when the WWW service shuts down an application pool. - optional\n- `auto_shutdown_params` - Specifies command-line parameters for the executable that is specified in the autoShutdownExe attribute. - optional\n\n#### CPU Items\n- `cpu_action` - Configures the action that IIS takes when a worker process exceeds its configured CPU limit. The action attribute is configured on a per-application pool basis. - Available options [:NoAction, :KillW3wp, :Throttle, :ThrottleUnderLoad] - default is :NoAction - optional\n- `cpu_limit` - Configures the maximum percentage of CPU time (in 1/1000ths of one percent) that the worker processes in an application pool are allowed to consume over a period of time as indicated by the resetInterval attribute. If the limit set by the limit attribute is exceeded, an event is written to the event log and an optional set of events can be triggered. These optional events are determined by the action attribute. - default is 0 - optional\n- `cpu_reset_interval` - Specifies the reset period (in minutes) for CPU monitoring and throttling limits on an application pool. When the number of minutes elapsed since the last process accounting reset equals the number specified by this property, IIS resets the CPU timers for both the logging and limit intervals. - default is '00:05:00' - optional\n- `cpu_smp_affinitized` - Specifies whether a particular worker process assigned to an application pool should also be assigned to a given CPU. - default is false - optional\n- `smp_processor_affinity_mask` - Specifies the hexadecimal processor mask for multi-processor computers, which indicates to which CPU the worker processes in an application pool should be bound. Before this property takes effect, the smpAffinitized attribute must be set to true for the application pool. - default is 4294967295 - optional\n- `smp_processor_affinity_mask_2` - Specifies the high-order DWORD hexadecimal processor mask for 64-bit multi-processor computers, which indicates to which CPU the worker processes in an application pool should be bound. Before this property takes effect, the smpAffinitized attribute must be set to true for the application pool. - default is 4294967295 - optional\n\n### Example\n\n```ruby\n# creates a new app pool\niis_pool 'myAppPool_v1_1' do\n runtime_version \"2.0\"\n pipeline_mode :Classic\n action :add\nend\n```\n\niis_app\n--------\n\nCreates an application in IIS.\n\n### Actions\n\n- `:add` - add a new application pool\n- `:delete` - delete an existing application pool\n\n### Attribute Parameters\n\n- `site_name` - name attribute. The name of the site to add this app to\n- `path` -The virtual path for this application\n- `application_pool` - The pool this application belongs to\n- `physical_path` - The physical path where this app resides.\n- `enabled_protocols` - The enabled protocols that this app provides (http, https, net.pipe, net.tcp, etc)\n\n### Example\n\n```ruby\n# creates a new app\niis_app \"myApp\" do\n path \"/v1_1\"\n application_pool \"myAppPool_v1_1\"\n physical_path \"#{node['iis']['docroot']}/testfu/v1_1\"\n enabled_protocols \"http,net.pipe\"\n action :add\nend\n```\n\niis_vdir\n---------\n\nAllows easy management of IIS virtual directories (i.e. vdirs).\n\n### Actions\n\n- :add: - add a new virtual directory\n- :delete: - delete an existing virtual directory\n- :config: - configure a virtual directory\n\n### Attribute Parameters\n\n- `application_name`: name attribute. Specifies the name of the application attribute. This is the name of the website or application you are adding it to.\n- `path`: The virtual directory path on the site.\n- `physical_path`: The physical path of the virtual directory on the disk.\n- `username`: (optional) The username required to logon to the physical_path. If set to \"\" will clear username and password.\n- `password`: (optional) The password required to logon to the physical_path\n- `logon_method`: (optional, default: :ClearText) The method used to logon (:Interactive, :Batch, :Network, :ClearText). For more information on these types, see \"LogonUser Function\", Read more at [MSDN](http://msdn2.microsoft.com/en-us/library/aa378184.aspx)\n- `allow_sub_dir_config`: (optional, default: true) Boolean that specifies whether or not the Web server will look for configuration files located in the subdirectories of this virtual directory. Setting this to false can improve performance on servers with very large numbers of web.config files, but doing so prevents IIS configuration from being read in subdirectories.\n\n### Examples\n\n```ruby\n# add a virtual directory to default application\niis_vdir 'Default Web Site/' do\n action :add\n path '/Content/Test'\n physical_path 'C:\\wwwroot\\shared\\test'\nend\n```\n\n```ruby\n# add a virtual directory to an application under a site\niis_vdir 'Default Web Site/my application' do\n action :add\n path '/Content/Test'\n physical_path 'C:\\wwwroot\\shared\\test'\nend\n```\n\n```ruby\n# adds a virtual directory to default application which points to a smb share. (Remember to escape the \"\\\"'s)\niis_vdir 'Default Web Site/' do\n action :add\n path '/Content/Test'\n physical_path '\\\\\\\\sharename\\\\sharefolder\\\\1'\nend\n```\n\n```ruby\n# configure a virtual directory to have a username and password\niis_vdir 'Default Web Site/' do\n action :config\n path '/Content/Test'\n username 'domain\\myspecialuser'\n password 'myspecialpassword'\nend\n```\n\n```ruby\n# delete a virtual directory from the default application\niis_vdir 'Default Web Site/' do\n action :delete\n path '/Content/Test'\nend\n```\n\niis_section\n---------\n\nAllows for the locking/unlocking of sections ([listed here](http://www.iis.net/configreference) or via the command `appcmd list config \\\"\\\" /config:* /xml`)\n\nThis is valuable to allow the `web.config` of an individual application/website control it's own settings.\n\n### Actions\n\n- `:lock`: - locks the `section` passed\n- `:unlock`: - unlocks the `section` passed\n\n### Attribute Parameters\n\n- `section`: The name of the section to lock.\n- `returns`: The result of the `shell_out` command.\n\n### Examples\n\n```ruby\n# Sets the IIS global windows authentication to be locked globally\niis_section 'locks global configuration of windows auth' do\n section 'system.webServer/security/authentication/windowsAuthentication'\n action :lock\nend\n```\n\n```ruby\n# Sets the IIS global Basic authentication to be locked globally\niis_section 'locks global configuration of Basic auth' do\n section 'system.webServer/security/authentication/basicAuthentication'\n action :lock\nend\n```\n\n```ruby\n# Sets the IIS global windows authentication to be unlocked globally\niis_section 'unlocked web.config globally for windows auth' do\n action :unlock\n section 'system.webServer/security/authentication/windowsAuthentication'\nend\n```\n\n```ruby\n# Sets the IIS global Basic authentication to be unlocked globally\niis_section 'unlocked web.config globally for Basic auth' do\n action :unlock\n section 'system.webServer/security/authentication/basicAuthentication'\nend\n```\n\niis_module\n--------\n\nManages modules globally or on a per site basis.\n\n### Actions\n\n- `:add` - add a new module\n- `:delete` - delete a module\n\n### Attribute Parameters\n\n- `module_name` - The name of the module to add or delete\n- `type` - The type of module\n- `precondition` - precondition for module\n- `application` - The application or site to add the module to\n\n### Example\n\n```ruby\n# Adds a module called \"My 3rd Party Module\" to mySite/\niis_module \"My 3rd Party Module\" do\n application \"mySite/\"\n precondition \"bitness64\"\n action :add\nend\n```\n\n```ruby\n# Adds a module called \"MyModule\" to all IIS sites on the server\niis_module \"MyModule\"\n```\n\n\nUsage\n=====\n\ndefault\n-------\n\nInstalls and configures IIS 7.0/7.5/8.0 using the default configuration.\n\nmod_*\n-----\n\nThis cookbook also contains recipes for installing individual IIS modules (extensions). These recipes can be included in a node's run_list to build the minimal desired custom IIS installation.\n\n* `mod_aspnet` - installs ASP.NET runtime components\n* `mod_aspnet45` - installs ASP.NET 4.5 runtime components\n* `mod_auth_basic` - installs Basic Authentication support\n* `mod_auth_windows` - installs Windows Authentication (authenticate clients by using NTLM or Kerberos) support\n* `mod_compress_dynamic` - installs dynamic content compression support. *PLEASE NOTE* - enabling dynamic compression always gives you more efficient use of bandwidth, but if your server's processor utilization is already very high, the CPU load imposed by dynamic compression might make your site perform more slowly.\n* `mod_compress_static` - installs static content compression support\n* `mod_iis6_metabase_compat` - installs IIS 6 Metabase Compatibility component.\n* `mod_isapi` - installs ISAPI (Internet Server Application Programming Interface) extension and filter support.\n* `mod_logging` - installs and enables HTTP Logging (logging of Web site activity), Logging Tools (logging tools and scripts) and Custom Logging (log any of the HTTP request/response headers, IIS server variables, and client-side fields with simple configuration) support\n* `mod_management` - installs Web server Management Console which supports management of local and remote Web servers\n* `mod_security` - installs URL Authorization (Authorizes client access to the URLs that comprise a Web application), Request Filtering (configures rules to block selected client requests) and IP Security (allows or denies content access based on IP address or domain name) support.\n* `mod_tracing` - installs support for tracing ASP.NET applications and failed requests.\n\nNote: Not every possible IIS module has a corresponding recipe. The foregoing recipes are included for convenience, but users may also place additional IIS modules that are installable as Windows features into the ``node['iis']['components']`` array.\n\nLicense and Author\n==================\n\n* Author:: Seth Chisamore ()\n* Author:: Julian Dunn ()\n* Author:: Justin Schuhmann ()\n\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","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache 2.0","platforms":{"windows":">= 0.0.0"},"dependencies":{"windows":">= 1.34.6"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file +{"name":"iis","version":"4.1.6","description":"Installs/Configures Microsoft Internet Information Services","long_description":"iis Cookbook\n============\n\n[![Build Status](https://travis-ci.org/chef-cookbooks/iis.svg?branch=master)](https://travis-ci.org/chef-cookbooks/iis)\n[![Cookbook Version](https://img.shields.io/cookbook/v/iis.svg)](https://supermarket.chef.io/cookbooks/iis)\n\nInstalls and configures Microsoft Internet Information Services (IIS) 7.0 and later\n\nContents\n========\n\n * [Attributes](#attributes)\n * [Resource/Provider](#resourceprovider)\n * [iis_root](#iis_root) Allows for easy management of the IIS Root Machine settings\n * [iis_site](#iis_site) Allows for easy management of IIS virtual sites (ie vhosts).\n * [iis_config](#iis_config) Runs a config command on your IIS instance.\n * [iis_pool](#iis_pool) Creates an application pool in IIS.\n * [iis_app](#iis_app) Creates an application in IIS.\n * [iis_vdir](#iis_vdir) Allows easy management of IIS virtual directories (i.e. vdirs).\n * [iis_section](#iis_section) Allows for the locking/unlocking of application web.config sections.\n * [iis_module](#iis_module) Manages modules globally or on a per site basis.\n * [Usage](#usage)\n * [default](#default) Default recipe\n * [mod\\_\\*](#mod_) Recipes for installing individual IIS modules (extensions).\n * [Alternatives ](#alternatives)\n * [License and Author](#license-and-author)\n\nRequirements\n============\n\nPlatform\n--------\n\n* Windows Vista\n* Windows 7\n* Windows 8\n* Windows Server 2008 (R1, R2)\n* Windows Server 2012\n* Windows Server 2012R2\n\nWindows 2003R2 is *not* supported because it lacks Add/Remove Features.\n\nCookbooks\n---------\n\n* windows\n\nAttributes\n==========\n\n* `node['iis']['home']` - IIS main home directory. default is `%WINDIR%\\System32\\inetsrv`\n* `node['iis']['conf_dir']` - location where main IIS configs lives. default is `%WINDIR%\\System32\\inetsrv\\config`\n* `node['iis']['pubroot']` - . default is `%SYSTEMDRIVE%\\inetpub`\n* `node['iis']['docroot']` - IIS web site home directory. default is `%SYSTEMDRIVE%\\inetpub\\wwwroot`\n* `node['iis']['log_dir']` - location of IIS logs. default is `%SYSTEMDRIVE%\\inetpub\\logs\\LogFiles`\n* `node['iis']['cache_dir']` - location of cached data. default is `%SYSTEMDRIVE%\\inetpub\\temp`\n\nResource/Provider\n=================\n\niis_root\n---------\n\nAllows for easy management of the IIS Root Machine settings\n\n### Actions\n`default` = `:config`\n\n- `:add` - only does addition operations will not delete anything to an Array object\n- `:delete` - only does deletion operations will not add anything to an Array object\n- `:config` - does both addition and deletion make sure your Array objects contain everything you want\n\n### Attribute Parameters\n\n- `default_documents_enabled` - Enables or disables default_documents for the root machine, Valid Values: true, false default: `true`\n- `default_documents` - The items you want to set as the default document collection, only used during `:config`. Array of strings, default: `['Default.htm', 'Default.asp', 'index.htm', 'index.html', 'iisstart.htm', 'default.aspx']`\n- `mime_maps` - The items you want to set as the mime-maps or mime-types collection, only used during `:config`. Array of strings, default:\n```ruby\n[\"fileExtension='.323',mimeType='text/h323'\", \"fileExtension='.3g2',mimeType='video/3gpp2'\", \"fileExtension='.3gp2',mimeType='video/3gpp2'\", \"fileExtension='.3gp',mimeType='video/3gpp'\", \"fileExtension='.3gpp',mimeType='video/3gpp'\", \"fileExtension='.aaf',mimeType='application/octet-stream'\", \"fileExtension='.aac',mimeType='audio/aac'\", \"fileExtension='.aca',mimeType='application/octet-stream'\", \"fileExtension='.accdb',mimeType='application/msaccess'\", \"fileExtension='.accde',mimeType='application/msaccess'\", \"fileExtension='.accdt',mimeType='application/msaccess'\", \"fileExtension='.acx',mimeType='application/internet-property-stream'\", \"fileExtension='.adt',mimeType='audio/vnd.dlna.adts'\", \"fileExtension='.adts',mimeType='audio/vnd.dlna.adts'\", \"fileExtension='.afm',mimeType='application/octet-stream'\", \"fileExtension='.ai',mimeType='application/postscript'\", \"fileExtension='.aif',mimeType='audio/x-aiff'\", \"fileExtension='.aifc',mimeType='audio/aiff'\", \"fileExtension='.aiff',mimeType='audio/aiff'\", \"fileExtension='.application',mimeType='application/x-ms-application'\", \"fileExtension='.art',mimeType='image/x-jg'\", \"fileExtension='.asd',mimeType='application/octet-stream'\", \"fileExtension='.asf',mimeType='video/x-ms-asf'\", \"fileExtension='.asi',mimeType='application/octet-stream'\", \"fileExtension='.asm',mimeType='text/plain'\", \"fileExtension='.asr',mimeType='video/x-ms-asf'\", \"fileExtension='.asx',mimeType='video/x-ms-asf'\", \"fileExtension='.atom',mimeType='application/atom+xml'\", \"fileExtension='.au',mimeType='audio/basic'\", \"fileExtension='.avi',mimeType='video/avi'\", \"fileExtension='.axs',mimeType='application/olescript'\", \"fileExtension='.bas',mimeType='text/plain'\", \"fileExtension='.bcpio',mimeType='application/x-bcpio'\", \"fileExtension='.bin',mimeType='application/octet-stream'\", \"fileExtension='.bmp',mimeType='image/bmp'\", \"fileExtension='.c',mimeType='text/plain'\", \"fileExtension='.cab',mimeType='application/vnd.ms-cab-compressed'\", \"fileExtension='.calx',mimeType='application/vnd.ms-office.calx'\", \"fileExtension='.cat',mimeType='application/vnd.ms-pki.seccat'\", \"fileExtension='.cdf',mimeType='application/x-cdf'\", \"fileExtension='.chm',mimeType='application/octet-stream'\", \"fileExtension='.class',mimeType='application/x-java-applet'\", \"fileExtension='.clp',mimeType='application/x-msclip'\", \"fileExtension='.cmx',mimeType='image/x-cmx'\", \"fileExtension='.cnf',mimeType='text/plain'\", \"fileExtension='.cod',mimeType='image/cis-cod'\", \"fileExtension='.cpio',mimeType='application/x-cpio'\", \"fileExtension='.cpp',mimeType='text/plain'\", \"fileExtension='.crd',mimeType='application/x-mscardfile'\", \"fileExtension='.crl',mimeType='application/pkix-crl'\", \"fileExtension='.crt',mimeType='application/x-x509-ca-cert'\", \"fileExtension='.csh',mimeType='application/x-csh'\", \"fileExtension='.css',mimeType='text/css'\", \"fileExtension='.csv',mimeType='application/octet-stream'\", \"fileExtension='.cur',mimeType='application/octet-stream'\", \"fileExtension='.dcr',mimeType='application/x-director'\", \"fileExtension='.deploy',mimeType='application/octet-stream'\", \"fileExtension='.der',mimeType='application/x-x509-ca-cert'\", \"fileExtension='.dib',mimeType='image/bmp'\", \"fileExtension='.dir',mimeType='application/x-director'\", \"fileExtension='.disco',mimeType='text/xml'\", \"fileExtension='.dll',mimeType='application/x-msdownload'\", \"fileExtension='.dll.config',mimeType='text/xml'\", \"fileExtension='.dlm',mimeType='text/dlm'\", \"fileExtension='.doc',mimeType='application/msword'\", \"fileExtension='.docm',mimeType='application/vnd.ms-word.document.macroEnabled.12'\", \"fileExtension='.docx',mimeType='application/vnd.openxmlformats-officedocument.wordprocessingml.document'\", \"fileExtension='.dot',mimeType='application/msword'\", \"fileExtension='.dotm',mimeType='application/vnd.ms-word.template.macroEnabled.12'\", \"fileExtension='.dotx',mimeType='application/vnd.openxmlformats-officedocument.wordprocessingml.template'\", \"fileExtension='.dsp',mimeType='application/octet-stream'\", \"fileExtension='.dtd',mimeType='text/xml'\", \"fileExtension='.dvi',mimeType='application/x-dvi'\", \"fileExtension='.dvr-ms',mimeType='video/x-ms-dvr'\", \"fileExtension='.dwf',mimeType='drawing/x-dwf'\", \"fileExtension='.dwp',mimeType='application/octet-stream'\", \"fileExtension='.dxr',mimeType='application/x-director'\", \"fileExtension='.eml',mimeType='message/rfc822'\", \"fileExtension='.emz',mimeType='application/octet-stream'\", \"fileExtension='.eot',mimeType='application/vnd.ms-fontobject'\", \"fileExtension='.eps',mimeType='application/postscript'\", \"fileExtension='.etx',mimeType='text/x-setext'\", \"fileExtension='.evy',mimeType='application/envoy'\", \"fileExtension='.exe',mimeType='application/octet-stream'\", \"fileExtension='.exe.config',mimeType='text/xml'\", \"fileExtension='.fdf',mimeType='application/vnd.fdf'\", \"fileExtension='.fif',mimeType='application/fractals'\", \"fileExtension='.fla',mimeType='application/octet-stream'\", \"fileExtension='.flr',mimeType='x-world/x-vrml'\", \"fileExtension='.flv',mimeType='video/x-flv'\", \"fileExtension='.gif',mimeType='image/gif'\", \"fileExtension='.gtar',mimeType='application/x-gtar'\", \"fileExtension='.gz',mimeType='application/x-gzip'\", \"fileExtension='.h',mimeType='text/plain'\", \"fileExtension='.hdf',mimeType='application/x-hdf'\", \"fileExtension='.hdml',mimeType='text/x-hdml'\", \"fileExtension='.hhc',mimeType='application/x-oleobject'\", \"fileExtension='.hhk',mimeType='application/octet-stream'\", \"fileExtension='.hhp',mimeType='application/octet-stream'\", \"fileExtension='.hlp',mimeType='application/winhlp'\", \"fileExtension='.hqx',mimeType='application/mac-binhex40'\", \"fileExtension='.hta',mimeType='application/hta'\", \"fileExtension='.htc',mimeType='text/x-component'\", \"fileExtension='.htm',mimeType='text/html'\", \"fileExtension='.html',mimeType='text/html'\", \"fileExtension='.htt',mimeType='text/webviewhtml'\", \"fileExtension='.hxt',mimeType='text/html'\", \"fileExtension='.ico',mimeType='image/x-icon'\", \"fileExtension='.ics',mimeType='text/calendar'\", \"fileExtension='.ief',mimeType='image/ief'\", \"fileExtension='.iii',mimeType='application/x-iphone'\", \"fileExtension='.inf',mimeType='application/octet-stream'\", \"fileExtension='.ins',mimeType='application/x-internet-signup'\", \"fileExtension='.isp',mimeType='application/x-internet-signup'\", \"fileExtension='.IVF',mimeType='video/x-ivf'\", \"fileExtension='.jar',mimeType='application/java-archive'\", \"fileExtension='.java',mimeType='application/octet-stream'\", \"fileExtension='.jck',mimeType='application/liquidmotion'\", \"fileExtension='.jcz',mimeType='application/liquidmotion'\", \"fileExtension='.jfif',mimeType='image/pjpeg'\", \"fileExtension='.jpb',mimeType='application/octet-stream'\", \"fileExtension='.jpe',mimeType='image/jpeg'\", \"fileExtension='.jpeg',mimeType='image/jpeg'\", \"fileExtension='.jpg',mimeType='image/jpeg'\", \"fileExtension='.js',mimeType='application/javascript'\", \"fileExtension='.json',mimeType='application/json'\", \"fileExtension='.jsx',mimeType='text/jscript'\", \"fileExtension='.latex',mimeType='application/x-latex'\", \"fileExtension='.lit',mimeType='application/x-ms-reader'\", \"fileExtension='.lpk',mimeType='application/octet-stream'\", \"fileExtension='.lsf',mimeType='video/x-la-asf'\", \"fileExtension='.lsx',mimeType='video/x-la-asf'\", \"fileExtension='.lzh',mimeType='application/octet-stream'\", \"fileExtension='.m13',mimeType='application/x-msmediaview'\", \"fileExtension='.m14',mimeType='application/x-msmediaview'\", \"fileExtension='.m1v',mimeType='video/mpeg'\", \"fileExtension='.m2ts',mimeType='video/vnd.dlna.mpeg-tts'\", \"fileExtension='.m3u',mimeType='audio/x-mpegurl'\", \"fileExtension='.m4a',mimeType='audio/mp4'\", \"fileExtension='.m4v',mimeType='video/mp4'\", \"fileExtension='.man',mimeType='application/x-troff-man'\", \"fileExtension='.manifest',mimeType='application/x-ms-manifest'\", \"fileExtension='.map',mimeType='text/plain'\", \"fileExtension='.mdb',mimeType='application/x-msaccess'\", \"fileExtension='.mdp',mimeType='application/octet-stream'\", \"fileExtension='.me',mimeType='application/x-troff-me'\", \"fileExtension='.mht',mimeType='message/rfc822'\", \"fileExtension='.mhtml',mimeType='message/rfc822'\", \"fileExtension='.mid',mimeType='audio/mid'\", \"fileExtension='.midi',mimeType='audio/mid'\", \"fileExtension='.mix',mimeType='application/octet-stream'\", \"fileExtension='.mmf',mimeType='application/x-smaf'\", \"fileExtension='.mno',mimeType='text/xml'\", \"fileExtension='.mny',mimeType='application/x-msmoney'\", \"fileExtension='.mov',mimeType='video/quicktime'\", \"fileExtension='.movie',mimeType='video/x-sgi-movie'\", \"fileExtension='.mp2',mimeType='video/mpeg'\", \"fileExtension='.mp3',mimeType='audio/mpeg'\", \"fileExtension='.mp4',mimeType='video/mp4'\", \"fileExtension='.mp4v',mimeType='video/mp4'\", \"fileExtension='.mpa',mimeType='video/mpeg'\", \"fileExtension='.mpe',mimeType='video/mpeg'\", \"fileExtension='.mpeg',mimeType='video/mpeg'\", \"fileExtension='.mpg',mimeType='video/mpeg'\", \"fileExtension='.mpp',mimeType='application/vnd.ms-project'\", \"fileExtension='.mpv2',mimeType='video/mpeg'\", \"fileExtension='.ms',mimeType='application/x-troff-ms'\", \"fileExtension='.msi',mimeType='application/octet-stream'\", \"fileExtension='.mso',mimeType='application/octet-stream'\", \"fileExtension='.mvb',mimeType='application/x-msmediaview'\", \"fileExtension='.mvc',mimeType='application/x-miva-compiled'\", \"fileExtension='.nc',mimeType='application/x-netcdf'\", \"fileExtension='.nsc',mimeType='video/x-ms-asf'\", \"fileExtension='.nws',mimeType='message/rfc822'\", \"fileExtension='.ocx',mimeType='application/octet-stream'\", \"fileExtension='.oda',mimeType='application/oda'\", \"fileExtension='.odc',mimeType='text/x-ms-odc'\", \"fileExtension='.ods',mimeType='application/oleobject'\", \"fileExtension='.oga',mimeType='audio/ogg'\", \"fileExtension='.ogg',mimeType='video/ogg'\", \"fileExtension='.ogv',mimeType='video/ogg'\", \"fileExtension='.one',mimeType='application/onenote'\", \"fileExtension='.onea',mimeType='application/onenote'\", \"fileExtension='.onetoc',mimeType='application/onenote'\", \"fileExtension='.onetoc2',mimeType='application/onenote'\", \"fileExtension='.onetmp',mimeType='application/onenote'\", \"fileExtension='.onepkg',mimeType='application/onenote'\", \"fileExtension='.osdx',mimeType='application/opensearchdescription+xml'\", \"fileExtension='.otf',mimeType='font/otf'\", \"fileExtension='.p10',mimeType='application/pkcs10'\", \"fileExtension='.p12',mimeType='application/x-pkcs12'\", \"fileExtension='.p7b',mimeType='application/x-pkcs7-certificates'\", \"fileExtension='.p7c',mimeType='application/pkcs7-mime'\", \"fileExtension='.p7m',mimeType='application/pkcs7-mime'\", \"fileExtension='.p7r',mimeType='application/x-pkcs7-certreqresp'\", \"fileExtension='.p7s',mimeType='application/pkcs7-signature'\", \"fileExtension='.pbm',mimeType='image/x-portable-bitmap'\", \"fileExtension='.pcx',mimeType='application/octet-stream'\", \"fileExtension='.pcz',mimeType='application/octet-stream'\", \"fileExtension='.pdf',mimeType='application/pdf'\", \"fileExtension='.pfb',mimeType='application/octet-stream'\", \"fileExtension='.pfm',mimeType='application/octet-stream'\", \"fileExtension='.pfx',mimeType='application/x-pkcs12'\", \"fileExtension='.pgm',mimeType='image/x-portable-graymap'\", \"fileExtension='.pko',mimeType='application/vnd.ms-pki.pko'\", \"fileExtension='.pma',mimeType='application/x-perfmon'\", \"fileExtension='.pmc',mimeType='application/x-perfmon'\", \"fileExtension='.pml',mimeType='application/x-perfmon'\", \"fileExtension='.pmr',mimeType='application/x-perfmon'\", \"fileExtension='.pmw',mimeType='application/x-perfmon'\", \"fileExtension='.png',mimeType='image/png'\", \"fileExtension='.pnm',mimeType='image/x-portable-anymap'\", \"fileExtension='.pnz',mimeType='image/png'\", \"fileExtension='.pot',mimeType='application/vnd.ms-powerpoint'\", \"fileExtension='.potm',mimeType='application/vnd.ms-powerpoint.template.macroEnabled.12'\", \"fileExtension='.potx',mimeType='application/vnd.openxmlformats-officedocument.presentationml.template'\", \"fileExtension='.ppam',mimeType='application/vnd.ms-powerpoint.addin.macroEnabled.12'\", \"fileExtension='.ppm',mimeType='image/x-portable-pixmap'\", \"fileExtension='.pps',mimeType='application/vnd.ms-powerpoint'\", \"fileExtension='.ppsm',mimeType='application/vnd.ms-powerpoint.slideshow.macroEnabled.12'\", \"fileExtension='.ppsx',mimeType='application/vnd.openxmlformats-officedocument.presentationml.slideshow'\", \"fileExtension='.ppt',mimeType='application/vnd.ms-powerpoint'\", \"fileExtension='.pptm',mimeType='application/vnd.ms-powerpoint.presentation.macroEnabled.12'\", \"fileExtension='.pptx',mimeType='application/vnd.openxmlformats-officedocument.presentationml.presentation'\", \"fileExtension='.prf',mimeType='application/pics-rules'\", \"fileExtension='.prm',mimeType='application/octet-stream'\", \"fileExtension='.prx',mimeType='application/octet-stream'\", \"fileExtension='.ps',mimeType='application/postscript'\", \"fileExtension='.psd',mimeType='application/octet-stream'\", \"fileExtension='.psm',mimeType='application/octet-stream'\", \"fileExtension='.psp',mimeType='application/octet-stream'\", \"fileExtension='.pub',mimeType='application/x-mspublisher'\", \"fileExtension='.qt',mimeType='video/quicktime'\", \"fileExtension='.qtl',mimeType='application/x-quicktimeplayer'\", \"fileExtension='.qxd',mimeType='application/octet-stream'\", \"fileExtension='.ra',mimeType='audio/x-pn-realaudio'\", \"fileExtension='.ram',mimeType='audio/x-pn-realaudio'\", \"fileExtension='.rar',mimeType='application/octet-stream'\", \"fileExtension='.ras',mimeType='image/x-cmu-raster'\", \"fileExtension='.rf',mimeType='image/vnd.rn-realflash'\", \"fileExtension='.rgb',mimeType='image/x-rgb'\", \"fileExtension='.rm',mimeType='application/vnd.rn-realmedia'\", \"fileExtension='.rmi',mimeType='audio/mid'\", \"fileExtension='.roff',mimeType='application/x-troff'\", \"fileExtension='.rpm',mimeType='audio/x-pn-realaudio-plugin'\", \"fileExtension='.rtf',mimeType='application/rtf'\", \"fileExtension='.rtx',mimeType='text/richtext'\", \"fileExtension='.scd',mimeType='application/x-msschedule'\", \"fileExtension='.sct',mimeType='text/scriptlet'\", \"fileExtension='.sea',mimeType='application/octet-stream'\", \"fileExtension='.setpay',mimeType='application/set-payment-initiation'\", \"fileExtension='.setreg',mimeType='application/set-registration-initiation'\", \"fileExtension='.sgml',mimeType='text/sgml'\", \"fileExtension='.sh',mimeType='application/x-sh'\", \"fileExtension='.shar',mimeType='application/x-shar'\", \"fileExtension='.sit',mimeType='application/x-stuffit'\", \"fileExtension='.sldm',mimeType='application/vnd.ms-powerpoint.slide.macroEnabled.12'\", \"fileExtension='.sldx',mimeType='application/vnd.openxmlformats-officedocument.presentationml.slide'\", \"fileExtension='.smd',mimeType='audio/x-smd'\", \"fileExtension='.smi',mimeType='application/octet-stream'\", \"fileExtension='.smx',mimeType='audio/x-smd'\", \"fileExtension='.smz',mimeType='audio/x-smd'\", \"fileExtension='.snd',mimeType='audio/basic'\", \"fileExtension='.snp',mimeType='application/octet-stream'\", \"fileExtension='.spc',mimeType='application/x-pkcs7-certificates'\", \"fileExtension='.spl',mimeType='application/futuresplash'\", \"fileExtension='.spx',mimeType='audio/ogg'\", \"fileExtension='.src',mimeType='application/x-wais-source'\", \"fileExtension='.ssm',mimeType='application/streamingmedia'\", \"fileExtension='.sst',mimeType='application/vnd.ms-pki.certstore'\", \"fileExtension='.stl',mimeType='application/vnd.ms-pki.stl'\", \"fileExtension='.sv4cpio',mimeType='application/x-sv4cpio'\", \"fileExtension='.sv4crc',mimeType='application/x-sv4crc'\", \"fileExtension='.svg',mimeType='image/svg+xml'\", \"fileExtension='.svgz',mimeType='image/svg+xml'\", \"fileExtension='.swf',mimeType='application/x-shockwave-flash'\", \"fileExtension='.t',mimeType='application/x-troff'\", \"fileExtension='.tar',mimeType='application/x-tar'\", \"fileExtension='.tcl',mimeType='application/x-tcl'\", \"fileExtension='.tex',mimeType='application/x-tex'\", \"fileExtension='.texi',mimeType='application/x-texinfo'\", \"fileExtension='.texinfo',mimeType='application/x-texinfo'\", \"fileExtension='.tgz',mimeType='application/x-compressed'\", \"fileExtension='.thmx',mimeType='application/vnd.ms-officetheme'\", \"fileExtension='.thn',mimeType='application/octet-stream'\", \"fileExtension='.tif',mimeType='image/tiff'\", \"fileExtension='.tiff',mimeType='image/tiff'\", \"fileExtension='.toc',mimeType='application/octet-stream'\", \"fileExtension='.tr',mimeType='application/x-troff'\", \"fileExtension='.trm',mimeType='application/x-msterminal'\", \"fileExtension='.ts',mimeType='video/vnd.dlna.mpeg-tts'\", \"fileExtension='.tsv',mimeType='text/tab-separated-values'\", \"fileExtension='.ttf',mimeType='application/octet-stream'\", \"fileExtension='.tts',mimeType='video/vnd.dlna.mpeg-tts'\", \"fileExtension='.txt',mimeType='text/plain'\", \"fileExtension='.u32',mimeType='application/octet-stream'\", \"fileExtension='.uls',mimeType='text/iuls'\", \"fileExtension='.ustar',mimeType='application/x-ustar'\", \"fileExtension='.vbs',mimeType='text/vbscript'\", \"fileExtension='.vcf',mimeType='text/x-vcard'\", \"fileExtension='.vcs',mimeType='text/plain'\", \"fileExtension='.vdx',mimeType='application/vnd.ms-visio.viewer'\", \"fileExtension='.vml',mimeType='text/xml'\", \"fileExtension='.vsd',mimeType='application/vnd.visio'\", \"fileExtension='.vss',mimeType='application/vnd.visio'\", \"fileExtension='.vst',mimeType='application/vnd.visio'\", \"fileExtension='.vsto',mimeType='application/x-ms-vsto'\", \"fileExtension='.vsw',mimeType='application/vnd.visio'\", \"fileExtension='.vsx',mimeType='application/vnd.visio'\", \"fileExtension='.vtx',mimeType='application/vnd.visio'\", \"fileExtension='.wav',mimeType='audio/wav'\", \"fileExtension='.wax',mimeType='audio/x-ms-wax'\", \"fileExtension='.wbmp',mimeType='image/vnd.wap.wbmp'\", \"fileExtension='.wcm',mimeType='application/vnd.ms-works'\", \"fileExtension='.wdb',mimeType='application/vnd.ms-works'\", \"fileExtension='.webm',mimeType='video/webm'\", \"fileExtension='.wks',mimeType='application/vnd.ms-works'\", \"fileExtension='.wm',mimeType='video/x-ms-wm'\", \"fileExtension='.wma',mimeType='audio/x-ms-wma'\", \"fileExtension='.wmd',mimeType='application/x-ms-wmd'\", \"fileExtension='.wmf',mimeType='application/x-msmetafile'\", \"fileExtension='.wml',mimeType='text/vnd.wap.wml'\", \"fileExtension='.wmlc',mimeType='application/vnd.wap.wmlc'\", \"fileExtension='.wmls',mimeType='text/vnd.wap.wmlscript'\", \"fileExtension='.wmlsc',mimeType='application/vnd.wap.wmlscriptc'\", \"fileExtension='.wmp',mimeType='video/x-ms-wmp'\", \"fileExtension='.wmv',mimeType='video/x-ms-wmv'\", \"fileExtension='.wmx',mimeType='video/x-ms-wmx'\", \"fileExtension='.wmz',mimeType='application/x-ms-wmz'\", \"fileExtension='.woff',mimeType='font/x-woff'\", \"fileExtension='.wps',mimeType='application/vnd.ms-works'\", \"fileExtension='.wri',mimeType='application/x-mswrite'\", \"fileExtension='.wrl',mimeType='x-world/x-vrml'\", \"fileExtension='.wrz',mimeType='x-world/x-vrml'\", \"fileExtension='.wsdl',mimeType='text/xml'\", \"fileExtension='.wtv',mimeType='video/x-ms-wtv'\", \"fileExtension='.wvx',mimeType='video/x-ms-wvx'\", \"fileExtension='.x',mimeType='application/directx'\", \"fileExtension='.xaf',mimeType='x-world/x-vrml'\", \"fileExtension='.xaml',mimeType='application/xaml+xml'\", \"fileExtension='.xap',mimeType='application/x-silverlight-app'\", \"fileExtension='.xbap',mimeType='application/x-ms-xbap'\", \"fileExtension='.xbm',mimeType='image/x-xbitmap'\", \"fileExtension='.xdr',mimeType='text/plain'\", \"fileExtension='.xht',mimeType='application/xhtml+xml'\", \"fileExtension='.xhtml',mimeType='application/xhtml+xml'\", \"fileExtension='.xla',mimeType='application/vnd.ms-excel'\", \"fileExtension='.xlam',mimeType='application/vnd.ms-excel.addin.macroEnabled.12'\", \"fileExtension='.xlc',mimeType='application/vnd.ms-excel'\", \"fileExtension='.xlm',mimeType='application/vnd.ms-excel'\", \"fileExtension='.xls',mimeType='application/vnd.ms-excel'\", \"fileExtension='.xlsb',mimeType='application/vnd.ms-excel.sheet.binary.macroEnabled.12'\", \"fileExtension='.xlsm',mimeType='application/vnd.ms-excel.sheet.macroEnabled.12'\", \"fileExtension='.xlsx',mimeType='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'\", \"fileExtension='.xlt',mimeType='application/vnd.ms-excel'\", \"fileExtension='.xltm',mimeType='application/vnd.ms-excel.template.macroEnabled.12'\", \"fileExtension='.xltx',mimeType='application/vnd.openxmlformats-officedocument.spreadsheetml.template'\", \"fileExtension='.xlw',mimeType='application/vnd.ms-excel'\", \"fileExtension='.xml',mimeType='text/xml'\", \"fileExtension='.xof',mimeType='x-world/x-vrml'\", \"fileExtension='.xpm',mimeType='image/x-xpixmap'\", \"fileExtension='.xps',mimeType='application/vnd.ms-xpsdocument'\", \"fileExtension='.xsd',mimeType='text/xml'\", \"fileExtension='.xsf',mimeType='text/xml'\", \"fileExtension='.xsl',mimeType='text/xml'\", \"fileExtension='.xslt',mimeType='text/xml'\", \"fileExtension='.xsn',mimeType='application/octet-stream'\", \"fileExtension='.xtp',mimeType='application/octet-stream'\", \"fileExtension='.xwd',mimeType='image/x-xwindowdump'\", \"fileExtension='.z',mimeType='application/x-compress'\", \"fileExtension='.zip',mimeType='application/x-zip-compressed'\"]\n```\n- `add_default_documents` - The items you want to add to the default document collection, only used during `:add`. Array of strings, default: `[]`\n- `add_mime_maps` - The items you want to add to the mime-map/mime-type collection, only used during `:add`. Array of strings, default: `[]`\n- `delete_default_documents` - The items you want to delete from the default document collection, only used during `:delete`. Array of strings, default: `[]`\n- `delete_mime_maps` - The items you want to delete from the mime-map/mime-type collection, only used during `:delete`. Array of strings, default: `[]`\n\n### Examples\n\n```ruby\n# Add foo.html to default documents, and add '.dmg' as mime type extension at root level\niis_root 'add stuff' do\n add_default_documents ['foo.html']\n add_mime_maps [\"fileExtension='.dmg',mimeType='application/octet-stream'\"]\n action :add\nend\n```\n```ruby\n# Remove index.html from default document and .323 as a mime type at root level\niis_root 'delete stuff' do\n delete_default_documents ['index.html']\n delete_mime_maps [\"fileExtension='.323',mimeType='text/h323'\"]\n action :delete\nend\n```\niis_site\n---------\n\nAllows for easy management of IIS virtual sites (ie vhosts).\n\n### Actions\n\n- `:add` - add a new virtual site\n- `:config` - apply configuration to an existing virtual site\n- `:delete` - delete an existing virtual site\n- `:start` - start a virtual site\n- `:stop` - stop a virtual site\n- `:restart` - restart a virtual site\n\n### Attribute Parameters\n\n- `site_name` - name attribute.\n- `site_id` - if not given IIS generates a unique ID for the site\n- `path` - IIS will create a root application and a root virtual directory mapped to this specified local path\n- `protocol` - http protocol type the site should respond to. valid values are :http, :https. default is :http\n- `port` - port site will listen on. default is 80\n- `host_header` - host header (also known as domains or host names) the site should map to. default is all host headers\n- `options` - additional options to configure the site\n- `bindings` - Advanced options to configure the information required for requests to communicate with a Web site. See http://www.iis.net/configreference/system.applicationhost/sites/site/bindings/binding for parameter format. When binding is used, port protocol and host_header should not be used.\n- `application_pool` - set the application pool of the site\n- `options` - support for additional options -logDir, -limits, -ftpServer, etc...\n- `log_directory` - specifies the logging directory, where the log file and logging-related support files are stored.\n- `log_period` - specifies how often iis creates a new log file\n- `log_truncsize` - specifies the maximum size of the log file (in bytes) after which to create a new log file.\n\n### Examples\n\n```ruby\n# stop and delete the default site\niis_site 'Default Web Site' do\n action [:stop, :delete]\nend\n```\n\n```ruby\n# create and start a new site that maps to\n# the physical location C:\\inetpub\\wwwroot\\testfu\n# first the physical location must exist\ndirectory \"#{node['iis']['docroot']}/testfu\" do\n action :create\nend\n\n# now create and start the site (note this will use the default application pool which must exist)\niis_site 'Testfu Site' do\n protocol :http\n port 80\n path \"#{node['iis']['docroot']}/testfu\"\n action [:add,:start]\nend\n```\n\n```ruby\n# do the same but map to testfu.chef.io domain\n# first the physical location must exist\ndirectory \"#{node['iis']['docroot']}/testfu\" do\n action :create\nend\n\n# now create and start the site (note this will use the default application pool which must exist)\niis_site 'Testfu Site' do\n protocol :http\n port 80\n path \"#{node['iis']['docroot']}/testfu\"\n host_header \"testfu.chef.io\"\n action [:add,:start]\nend\n```\n\n```ruby\n# create and start a new site that maps to\n# the physical C:\\inetpub\\wwwroot\\testfu\n# first the physical location must exist\ndirectory \"#{node['iis']['docroot']}/testfu\" do\n action :create\nend\n\n# also adds bindings to http and https\n# binding http to the ip address 10.12.0.136,\n# the port 80, and the host header www.domain.com\n# also binding https to any ip address,\n# the port 443, and the host header www.domain.com\n# now create and start the site (note this will use the default application pool which must exist)\niis_site 'FooBar Site' do\n bindings \"http/10.12.0.136:80:www.domain.com,https/*:443:www.domain.com\n path \"#{node['iis']['docroot']}/testfu\"\n action [:add,:start]\nend\n```\n\niis_config\n-----------\nRuns a config command on your IIS instance.\n\n### Actions\n\n- `:set` - Edit configuration section (appcmd set config)\n- `:clear` - Clear the section configuration (appcmd clear config)\n- `:config` - [ DEPRECATED ] use `:set` instead\n\n### Attribute Parameters\n\n- `cfg_cmd` - name attribute. What ever command you would pass in after \"appcmd.exe set config\"\n\n### Example\n\n```ruby\n# Sets up logging\niis_config \"/section:system.applicationHost/sites /siteDefaults.logfile.directory:\\\"D:\\\\logs\\\"\" do\n action :set\nend\n```\n\n```ruby\n# Increase file upload size for 'MySite'\niis_config \"\\\"MySite\\\" /section:requestfiltering /requestlimits.maxallowedcontentlength:50000000\" do\n action :set\nend\n```\n\n```ruby\n# Set IUSR username and password authentication\niis_config \"\\\"MyWebsite/aSite\\\" -section:system.webServer/security/authentication/anonymousAuthentication /enabled:\\\"True\\\" /userName:\\\"IUSR_foobar\\\" /password:\\\"p@assword\\\" /commit:apphost\" do\n action :set\nend\n```\n\n```ruby\n# Authenticate with application pool\niis_config \"\\\"MyWebsite/aSite\\\" -section:system.webServer/security/authentication/anonymousAuthentication /enabled:\\\"True\\\" /userName:\\\"\\\" /commit:apphost\" do\n action :set\nend\n\n```\n\n```ruby\n# Loads an array of commands from the node\ncfg_cmds = node['iis']['cfg_cmd']\ncfg_cmds.each do |cmd|\n iis_config \"#{cmd}\" do\n action :set\n end\nend\n```\n\n```ruby\n# Add static machine key at site level\niis_config \"MySite /commit:site /section:machineKey /validation:AES /validationKey:AAAAAA /decryptionKey:ZZZZZ\" do\n action :set\nend\n```\n\n```ruby\n# Remove machine key\niis_config \"MySite /commit:site /section:machineKey\"\n action :clear\nend\n```\n\n\niis_pool\n---------\nCreates an application pool in IIS.\n\n### Actions\n\n- `:add` - add a new application pool\n- `:config` - apply configuration to an existing application pool\n- `:delete` - delete an existing application pool\n- `:start` - start a application pool\n- `:stop` - stop a application pool\n- `:restart` - restart a application pool\n- `:recycle` - recycle an application pool\n\n### Attribute Parameters\n\n#### Root Items\n- `pool_name` - name attribute. Specifies the name of the pool to create.\n- `runtime_version` - specifies what .NET version of the runtime to use.\n- `pipeline_mode` - specifies what pipeline mode to create the pool with, valid values are :Integrated or :Classic, the default is :Integrated\n- `no_managed_code` - allow Unmanaged Code in setting up IIS app pools is shutting down. - default is true - optional\n\n#### Add Items\n- `start_mode` - Specifies the startup type for the application pool - default :OnDemand (:OnDemand, :AlwaysRunning) - optional\n- `auto_start` - When true, indicates to the World Wide Web Publishing Service (W3SVC) that the application pool should be automatically started when it is created or when IIS is started. - boolean: default true - optional\n- `queue_length` - Indicates to HTTP.sys how many requests to queue for an application pool before rejecting future requests. - default is 1000 - optional\n- `thirty_two_bit` - set the pool to run in 32 bit mode, valid values are true or false, default is false - optional\n\n#### Process Model Items\n- `max_proc` - specifies the number of worker processes associated with the pool.\n- `load_user_profile` - This property is used only when a service starts in a named user account. - Default is false - optional\n- `pool_identity` - the account identity that they app pool will run as, valid values are :SpecificUser, :NetworkService, :LocalService, :LocalSystem, :ApplicationPoolIdentity\n- `pool_username` - username for the identity for the application pool\n- `pool_password` password for the identity for the application pool is started. Default is true - optional\n- `logon_type` - Specifies the logon type for the process identity. (For additional information about [logon types](http://msdn.microsoft.com/en-us/library/aa378184%28VS.85%29.aspx), see the LogonUser Function topic on Microsoft's MSDN Web site.) - Available [:LogonBatch, :LogonService] - default is :LogonBatch - optional\n- `manual_group_membership` - Specifies whether the IIS_IUSRS group Security Identifier (SID) is added to the worker process token. When false, IIS automatically uses an application pool identity as though it were a member of the built-in IIS_IUSRS group, which has access to necessary file and system resources. When true, an application pool identity must be explicitly added to all resources that a worker process requires at runtime. - default is false - optional\n- `idle_timeout` - Specifies how long (in minutes) a worker process should run idle if no new requests are received and the worker process is not processing requests. After the allocated time passes, the worker process should request that it be shut down by the WWW service. - default is '00:20:00' - optional\n- `idle_timeout_action` - Specifies the option of suspending an idle worker process rather than terminating it. Valid values are :Terminate and :Suspend - optional\n- `shutdown_time_limit` - Specifies the time that the W3SVC service waits after it initiated a recycle. If the worker process does not shut down within the shutdownTimeLimit, it will be terminated by the W3SVC service. - default is '00:01:30' - optional\n- `startup_time_limit` - Specifies the time that IIS waits for an application pool to start. If the application pool does not startup within the startupTimeLimit, the worker process is terminated and the rapid-fail protection count is incremented. - default is '00:01:30' - optional\n- `pinging_enabled` - Specifies whether pinging is enabled for the worker process. - default is true - optional\n- `ping_interval` - Specifies the time between health-monitoring pings that the WWW service sends to a worker process - default is '00:00:30' - optional\n- `ping_response_time` - Specifies the time that a worker process is given to respond to a health-monitoring ping. After the time limit is exceeded, the WWW service terminates the worker process - default is '00:01:30' - optional\n\n#### Recycling Items\n- `disallow_rotation_on_config_change` - The DisallowRotationOnConfigChange property specifies whether or not the World Wide Web Publishing Service (WWW Service) should rotate worker processes in an application pool when the configuration has changed. - Default is false - optional\n- `disallow_overlapping_rotation` - Specifies whether the WWW Service should start another worker process to replace the existing worker process while that process\n- `recycle_after_time` - specifies a pool to recycle at regular time intervals, d.hh:mm:ss, d optional\n- `recycle_at_time` - schedule a pool to recycle at a specific time, d.hh:mm:ss, d optional\n- `private_mem` - specifies the amount of private memory (in kilobytes) after which you want the pool to recycle\n\n#### Failure Items\n- `load_balancer_capabilities` - Specifies behavior when a worker process cannot be started, such as when the request queue is full or an application pool is in rapid-fail protection. - default is :HttpLevel - optional\n- `orphan_worker_process` - Specifies whether to assign a worker process to an orphan state instead of terminating it when an application pool fails. - default is false - optional\n- `orphan_action_exe` - Specifies an executable to run when the WWW service orphans a worker process (if the orphanWorkerProcess attribute is set to true). You can use the orphanActionParams attribute to send parameters to the executable. - optional\n- `orphan_action_params` - Indicates command-line parameters for the executable named by the orphanActionExe attribute. To specify the process ID of the orphaned process, use %1%. - optional\n- `rapid_fail_protection` - Setting to true instructs the WWW service to remove from service all applications that are in an application pool - default is true - optional\n- `rapid_fail_protection_interval` - Specifies the number of minutes before the failure count for a process is reset. - default is '00:05:00' - optional\n- `rapid_fail_protection_max_crashes` - Specifies the maximum number of failures that are allowed within the number of minutes specified by the rapidFailProtectionInterval attribute. - default is 5 - optional\n- `auto_shutdown_exe` - Specifies an executable to run when the WWW service shuts down an application pool. - optional\n- `auto_shutdown_params` - Specifies command-line parameters for the executable that is specified in the autoShutdownExe attribute. - optional\n\n#### CPU Items\n- `cpu_action` - Configures the action that IIS takes when a worker process exceeds its configured CPU limit. The action attribute is configured on a per-application pool basis. - Available options [:NoAction, :KillW3wp, :Throttle, :ThrottleUnderLoad] - default is :NoAction - optional\n- `cpu_limit` - Configures the maximum percentage of CPU time (in 1/1000ths of one percent) that the worker processes in an application pool are allowed to consume over a period of time as indicated by the resetInterval attribute. If the limit set by the limit attribute is exceeded, an event is written to the event log and an optional set of events can be triggered. These optional events are determined by the action attribute. - default is 0 - optional\n- `cpu_reset_interval` - Specifies the reset period (in minutes) for CPU monitoring and throttling limits on an application pool. When the number of minutes elapsed since the last process accounting reset equals the number specified by this property, IIS resets the CPU timers for both the logging and limit intervals. - default is '00:05:00' - optional\n- `cpu_smp_affinitized` - Specifies whether a particular worker process assigned to an application pool should also be assigned to a given CPU. - default is false - optional\n- `smp_processor_affinity_mask` - Specifies the hexadecimal processor mask for multi-processor computers, which indicates to which CPU the worker processes in an application pool should be bound. Before this property takes effect, the smpAffinitized attribute must be set to true for the application pool. - default is 4294967295 - optional\n- `smp_processor_affinity_mask_2` - Specifies the high-order DWORD hexadecimal processor mask for 64-bit multi-processor computers, which indicates to which CPU the worker processes in an application pool should be bound. Before this property takes effect, the smpAffinitized attribute must be set to true for the application pool. - default is 4294967295 - optional\n\n### Example\n\n```ruby\n# creates a new app pool\niis_pool 'myAppPool_v1_1' do\n runtime_version \"2.0\"\n pipeline_mode :Classic\n action :add\nend\n```\n\niis_app\n--------\n\nCreates an application in IIS.\n\n### Actions\n\n- `:add` - add a new application pool\n- `:delete` - delete an existing application pool\n- `:config` - configures an existing application pool\n\n### Attribute Parameters\n\n- `site_name` - name attribute. The name of the site to add this app to\n- `path` -The virtual path for this application\n- `application_pool` - The pool this application belongs to\n- `physical_path` - The physical path where this app resides.\n- `enabled_protocols` - The enabled protocols that this app provides (http, https, net.pipe, net.tcp, etc)\n\n### Example\n\n```ruby\n# creates a new app\niis_app \"myApp\" do\n path \"/v1_1\"\n application_pool \"myAppPool_v1_1\"\n physical_path \"#{node['iis']['docroot']}/testfu/v1_1\"\n enabled_protocols \"http,net.pipe\"\n action :add\nend\n```\n\niis_vdir\n---------\n\nAllows easy management of IIS virtual directories (i.e. vdirs).\n\n### Actions\n\n- :add: - add a new virtual directory\n- :delete: - delete an existing virtual directory\n- :config: - configure a virtual directory\n\n### Attribute Parameters\n\n- `application_name`: name attribute. Specifies the name of the application attribute. This is the name of the website or application you are adding it to.\n- `path`: The virtual directory path on the site.\n- `physical_path`: The physical path of the virtual directory on the disk.\n- `username`: (optional) The username required to logon to the physical_path. If set to \"\" will clear username and password.\n- `password`: (optional) The password required to logon to the physical_path\n- `logon_method`: (optional, default: :ClearText) The method used to logon (:Interactive, :Batch, :Network, :ClearText). For more information on these types, see \"LogonUser Function\", Read more at [MSDN](http://msdn2.microsoft.com/en-us/library/aa378184.aspx)\n- `allow_sub_dir_config`: (optional, default: true) Boolean that specifies whether or not the Web server will look for configuration files located in the subdirectories of this virtual directory. Setting this to false can improve performance on servers with very large numbers of web.config files, but doing so prevents IIS configuration from being read in subdirectories.\n\n### Examples\n\n```ruby\n# add a virtual directory to default application\niis_vdir 'Default Web Site/' do\n action :add\n path '/Content/Test'\n physical_path 'C:\\wwwroot\\shared\\test'\nend\n```\n\n```ruby\n# add a virtual directory to an application under a site\niis_vdir 'Default Web Site/my application' do\n action :add\n path '/Content/Test'\n physical_path 'C:\\wwwroot\\shared\\test'\nend\n```\n\n```ruby\n# adds a virtual directory to default application which points to a smb share. (Remember to escape the \"\\\"'s)\niis_vdir 'Default Web Site/' do\n action :add\n path '/Content/Test'\n physical_path '\\\\\\\\sharename\\\\sharefolder\\\\1'\nend\n```\n\n```ruby\n# configure a virtual directory to have a username and password\niis_vdir 'Default Web Site/' do\n action :config\n path '/Content/Test'\n username 'domain\\myspecialuser'\n password 'myspecialpassword'\nend\n```\n\n```ruby\n# delete a virtual directory from the default application\niis_vdir 'Default Web Site/' do\n action :delete\n path '/Content/Test'\nend\n```\n\niis_section\n---------\n\nAllows for the locking/unlocking of sections ([listed here](http://www.iis.net/configreference) or via the command `appcmd list config \\\"\\\" /config:* /xml`)\n\nThis is valuable to allow the `web.config` of an individual application/website control it's own settings.\n\n### Actions\n\n- `:lock`: - locks the `section` passed\n- `:unlock`: - unlocks the `section` passed\n\n### Attribute Parameters\n\n- `section`: The name of the section to lock.\n- `returns`: The result of the `shell_out` command.\n\n### Examples\n\n```ruby\n# Sets the IIS global windows authentication to be locked globally\niis_section 'locks global configuration of windows auth' do\n section 'system.webServer/security/authentication/windowsAuthentication'\n action :lock\nend\n```\n\n```ruby\n# Sets the IIS global Basic authentication to be locked globally\niis_section 'locks global configuration of Basic auth' do\n section 'system.webServer/security/authentication/basicAuthentication'\n action :lock\nend\n```\n\n```ruby\n# Sets the IIS global windows authentication to be unlocked globally\niis_section 'unlocked web.config globally for windows auth' do\n action :unlock\n section 'system.webServer/security/authentication/windowsAuthentication'\nend\n```\n\n```ruby\n# Sets the IIS global Basic authentication to be unlocked globally\niis_section 'unlocked web.config globally for Basic auth' do\n action :unlock\n section 'system.webServer/security/authentication/basicAuthentication'\nend\n```\n\niis_module\n--------\n\nManages modules globally or on a per site basis.\n\n### Actions\n\n- `:add` - add a new module\n- `:delete` - delete a module\n- `:install` - install a native module from the filesystem (.dll)\n- `:uninstall` - uninstall a native module\n\n### Attribute Parameters\n\n- `module_name` - The name of the module to add or delete\n- `type` - The type of module\n- `precondition` - precondition for module\n- `application` - The application or site to add the module to\n- `add` - Whether the module you install has to be globally added\n- `image` - Location of the DLL of the module to install\n\n### Example\n\n```ruby\n# Adds a module called \"My 3rd Party Module\" to mySite/\niis_module \"My 3rd Party Module\" do\n application \"mySite/\"\n precondition \"bitness64\"\n action :add\nend\n```\n\n```ruby\n# Adds a module called \"MyModule\" to all IIS sites on the server\niis_module \"MyModule\"\n```\n\n\nUsage\n=====\n\ndefault\n-------\n\nInstalls and configures IIS 7.0/7.5/8.0 using the default configuration.\n\nmod_*\n-----\n\nThis cookbook also contains recipes for installing individual IIS modules (extensions). These recipes can be included in a node's run_list to build the minimal desired custom IIS installation.\n\n* `mod_aspnet` - installs ASP.NET runtime components\n* `mod_aspnet45` - installs ASP.NET 4.5 runtime components\n* `mod_auth_basic` - installs Basic Authentication support\n* `mod_auth_windows` - installs Windows Authentication (authenticate clients by using NTLM or Kerberos) support\n* `mod_compress_dynamic` - installs dynamic content compression support. *PLEASE NOTE* - enabling dynamic compression always gives you more efficient use of bandwidth, but if your server's processor utilization is already very high, the CPU load imposed by dynamic compression might make your site perform more slowly.\n* `mod_compress_static` - installs static content compression support\n* `mod_iis6_metabase_compat` - installs IIS 6 Metabase Compatibility component.\n* `mod_isapi` - installs ISAPI (Internet Server Application Programming Interface) extension and filter support.\n* `mod_logging` - installs and enables HTTP Logging (logging of Web site activity), Logging Tools (logging tools and scripts) and Custom Logging (log any of the HTTP request/response headers, IIS server variables, and client-side fields with simple configuration) support\n* `mod_management` - installs Web server Management Console which supports management of local and remote Web servers\n* `mod_security` - installs URL Authorization (Authorizes client access to the URLs that comprise a Web application), Request Filtering (configures rules to block selected client requests) and IP Security (allows or denies content access based on IP address or domain name) support.\n* `mod_tracing` - installs support for tracing ASP.NET applications and failed requests.\n\nNote: Not every possible IIS module has a corresponding recipe. The foregoing recipes are included for convenience, but users may also place additional IIS modules that are installable as Windows features into the ``node['iis']['components']`` array.\n\nAlternatives\n=====\n* [Powershell based IIS Cookbook (Pre-DSC)](https://github.com/ebsco/iisposh)\n* DSC Based- [CWebAdministration](https://github.com/PowerShellOrg/cWebAdministration) / [XWebadministration](https://github.com/PowerShell/xWebAdministration) Powershell Module(s)\n\nLicense and Author\n==================\n\n* Author:: Seth Chisamore ()\n* Author:: Julian Dunn ()\n* Author:: Justin Schuhmann ()\n\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","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache 2.0","platforms":{"windows":">= 0.0.0"},"dependencies":{"windows":">= 1.34.6"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file diff --git a/cookbooks/iis/providers/app.rb b/cookbooks/iis/providers/app.rb index 0e61a4d..0c3d1f5 100644 --- a/cookbooks/iis/providers/app.rb +++ b/cookbooks/iis/providers/app.rb @@ -25,6 +25,7 @@ require 'rexml/document' include Chef::Mixin::ShellOut include REXML include Opscode::IIS::Helper +include Opscode::IIS::Processors action :add do if !@current_resource.exists @@ -33,6 +34,7 @@ action :add do cmd << " /applicationPool:\"#{new_resource.application_pool}\"" if new_resource.application_pool cmd << " /physicalPath:\"#{windows_cleanpath(new_resource.physical_path)}\"" if new_resource.physical_path cmd << " /enabledProtocols:\"#{new_resource.enabled_protocols}\"" if new_resource.enabled_protocols + cmd << " /commit:\"MACHINE/WEBROOT/APPHOST\"" Chef::Log.debug(cmd) shell_out!(cmd) new_resource.updated_by_last_action(true) @@ -43,7 +45,7 @@ action :add do end action :config do - was_updated = false + @was_updated = false cmd_current_values = "#{appcmd(node)} list app \"#{site_identifier}\" /config:* /xml" Chef::Log.debug(cmd_current_values) cmd_current_values = shell_out(cmd_current_values) @@ -56,9 +58,9 @@ action :config do is_new_physical_path = new_or_empty_value?(doc.root, 'APP/application/virtualDirectory/@physicalPath', new_resource.physical_path.to_s) # only get the beginning of the command if there is something that changeds - cmd = "#{appcmd(node)} set app \"#{site_identifier}\"" if ((new_resource.path && is_new_path) || - (new_resource.application_pool && is_new_application_pool) || - (new_resource.enabled_protocols && is_new_enabled_protocols)) + cmd = "#{appcmd(node)} set app \"#{site_identifier}\"" if (new_resource.path && is_new_path) || + (new_resource.application_pool && is_new_application_pool) || + (new_resource.enabled_protocols && is_new_enabled_protocols) # adds path to the cmd cmd << " /path:\"#{new_resource.path}\"" if new_resource.path && is_new_path # adds applicationPool to the cmd @@ -67,27 +69,27 @@ action :config do cmd << " /enabledProtocols:\"#{new_resource.enabled_protocols}\"" if new_resource.enabled_protocols && is_new_enabled_protocols Chef::Log.debug(cmd) - if (cmd.nil?) + if cmd.nil? Chef::Log.debug("#{new_resource} application - nothing to do") else shell_out!(cmd) - was_updated = true + @was_updated = true end - if ((new_resource.path && is_new_path) || - (new_resource.application_pool && is_new_application_pool) || - (new_resource.enabled_protocols && is_new_enabled_protocols)) - was_updated = true + if (new_resource.path && is_new_path) || + (new_resource.application_pool && is_new_application_pool) || + (new_resource.enabled_protocols && is_new_enabled_protocols) + @was_updated = true end if new_resource.physical_path && is_new_physical_path - was_updated = true + @was_updated = true cmd = "#{appcmd(node)} set vdir /vdir.name:\"#{vdir_identifier}\"" cmd << " /physicalPath:\"#{windows_cleanpath(new_resource.physical_path)}\"" Chef::Log.debug(cmd) shell_out!(cmd) end - if was_updated + if @was_updated new_resource.updated_by_last_action(true) Chef::Log.info("#{new_resource} configured application") else diff --git a/cookbooks/iis/providers/config.rb b/cookbooks/iis/providers/config.rb index 37a3787..c278979 100644 --- a/cookbooks/iis/providers/config.rb +++ b/cookbooks/iis/providers/config.rb @@ -23,9 +23,23 @@ require 'chef/mixin/shell_out' include Chef::Mixin::ShellOut include Opscode::IIS::Helper +include Opscode::IIS::Processors +# :config deprecated, use :set instead action :config do - cmd = "#{appcmd(node)} set config #{new_resource.cfg_cmd}" + config +end + +action :set do + config +end + +action :clear do + config(:clear) +end + +def config(action = :set) + cmd = "#{appcmd(node)} #{action} config #{new_resource.cfg_cmd}" Chef::Log.debug(cmd) shell_out!(cmd, returns: new_resource.returns) Chef::Log.info('IIS Config command run') diff --git a/cookbooks/iis/providers/module.rb b/cookbooks/iis/providers/module.rb index 8315107..9906dc1 100644 --- a/cookbooks/iis/providers/module.rb +++ b/cookbooks/iis/providers/module.rb @@ -21,6 +21,7 @@ require 'chef/mixin/shell_out' include Chef::Mixin::ShellOut include Opscode::IIS::Helper +include Opscode::IIS::Processors # Support whyrun def whyrun_supported? @@ -38,15 +39,13 @@ action :add do cmd << " /app.name:\"#{new_resource.application}\"" end - if new_resource.type - cmd << " /type:\"#{new_resource.type}\"" - end + cmd << " /type:\"#{new_resource.type}\"" if new_resource.type if new_resource.precondition cmd << " /preCondition:\"#{new_resource.precondition}\"" end - shell_out!(cmd, returns: [0, 42]) + shell_out!(cmd, returns: [0, 42]) Chef::Log.info("#{new_resource} added module '#{new_resource.module_name}'") end @@ -63,7 +62,7 @@ action :delete do cmd << " /app.name:\"#{new_resource.application}\"" end - shell_out!(cmd, returns: [0, 42]) + shell_out!(cmd, returns: [0, 42]) end Chef::Log.info("#{new_resource} deleted") @@ -72,6 +71,40 @@ action :delete do end end +# appcmd syntax for installing native modules +# appcmd install module /name:string /add:string(true|false) /image:string +action :install do + if !@current_resource.exists + converge_by("install IIS module #{new_resource.module_name}") do + cmd = "#{appcmd(node)} install module /name:\"#{new_resource.module_name}\"" + cmd << " /add:\"#{new_resource.add}\"" unless new_resource.add.nil? + cmd << " /image:\"#{new_resource.image}\"" if new_resource.image + + shell_out!(cmd, returns: [0, 42]) + + Chef::Log.info("#{new_resource} installed module '#{new_resource.module_name}'") + end + else + Chef::Log.debug("#{new_resource} module already exists - nothing to do") + end +end + +# appcmd syntax for uninstalling native modules +# appcmd uninstall module +action :uninstall do + if @current_resource.exists + converge_by("uninstall IIS module #{new_resource.module_name}") do + cmd = "#{appcmd(node)} uninstall module \"#{new_resource.module_name}\"" + + shell_out!(cmd, returns: [0, 42]) + end + + Chef::Log.info("#{new_resource} uninstalled module '#{new_resource.module_name}'") + else + Chef::Log.debug("#{new_resource} module does not exists - nothing to do") + end +end + def load_current_resource @current_resource = Chef::Resource::IisModule.new(new_resource.name) @current_resource.module_name(new_resource.module_name) diff --git a/cookbooks/iis/providers/pool.rb b/cookbooks/iis/providers/pool.rb index e3f2373..8c45e07 100644 --- a/cookbooks/iis/providers/pool.rb +++ b/cookbooks/iis/providers/pool.rb @@ -25,13 +25,18 @@ require 'rexml/document' include Chef::Mixin::ShellOut include REXML include Opscode::IIS::Helper +include Opscode::IIS::Processors action :add do if !@current_resource.exists cmd = "#{appcmd(node)} add apppool /name:\"#{new_resource.pool_name}\"" - cmd << ' /managedRuntimeVersion:' if new_resource.runtime_version || new_resource.no_managed_code - cmd << "v#{new_resource.runtime_version}" if new_resource.runtime_version && !new_resource.no_managed_code + if new_resource.no_managed_code + cmd << ' /managedRuntimeVersion:' + else + cmd << " /managedRuntimeVersion:v#{new_resource.runtime_version}" if new_resource.runtime_version + end cmd << " /managedPipelineMode:#{new_resource.pipeline_mode.capitalize}" if new_resource.pipeline_mode + cmd << " /commit:\"MACHINE/WEBROOT/APPHOST\"" Chef::Log.debug(cmd) shell_out!(cmd) configure @@ -43,7 +48,7 @@ action :add do end action :config do - configure + new_resource.updated_by_last_action(true) if configure end action :delete do @@ -98,7 +103,7 @@ def load_current_resource Chef::Log.debug("#{new_resource} list apppool command output: #{cmd.stdout}") if cmd.stderr.empty? result = cmd.stdout.gsub(/\r\n?/, "\n") # ensure we have no carriage returns - result = result.match(/^APPPOOL\s\"(#{new_resource.pool_name})\"\s\(MgdVersion:(.*),MgdMode:(.*),state:(.*)\)$/) + result = result.match(/^APPPOOL\s\"(#{new_resource.pool_name})\"\s\(MgdVersion:(.*),MgdMode:(.*),state:(.*)\)$/i) Chef::Log.debug("#{new_resource} current_resource match output: #{result}") if result @current_resource.exists = true @@ -108,7 +113,7 @@ def load_current_resource @current_resource.running = false end else - log "Failed to run iis_pool action :load_current_resource, #{cmd_current_values.stderr}" do + log "Failed to run iis_pool action :load_current_resource, #{cmd.stderr}" do level :warn end end @@ -131,23 +136,36 @@ def configure # root items is_new_managed_runtime_version = new_value?(doc.root, 'APPPOOL/@RuntimeVersion', "v#{new_resource.runtime_version}") - is_new_pipeline_mode = new_value?(doc.root, 'APPPOOL/@PipelineMode'.capitalize, "#{new_resource.pipeline_mode}".to_s.capitalize) + is_new_pipeline_mode = new_value?(doc.root, 'APPPOOL/@PipelineMode', new_resource.pipeline_mode) # add items - is_new_start_mode = new_value?(doc.root, 'APPPOOL/add/@startMode', new_resource.start_mode.to_s) - is_new_auto_start = new_value?(doc.root, 'APPPOOL/add/@autoStart', new_resource.auto_start.to_s) + if iis_version >= '7.0' + is_new_auto_start = new_value?(doc.root, 'APPPOOL/add/@autoStart', new_resource.auto_start.to_s) + end + + if iis_version > '7.0' + is_new_start_mode = new_value?(doc.root, 'APPPOOL/add/@startMode', new_resource.start_mode.to_s) + end + is_new_queue_length = new_value?(doc.root, 'APPPOOL/add/@queueLength', new_resource.queue_length.to_s) is_new_enable_32_bit_app_on_win_64 = new_value?(doc.root, 'APPPOOL/add/@enable32BitAppOnWin64', new_resource.thirty_two_bit.to_s) # processModel items is_new_max_processes = new_or_empty_value?(doc.root, 'APPPOOL/add/processModel/@maxProcesses', new_resource.max_proc.to_s) is_new_load_user_profile = new_value?(doc.root, 'APPPOOL/add/processModel/@loadUserProfile', new_resource.load_user_profile.to_s) - is_new_identity_type = new_value?(doc.root, 'APPPOOL/add/processModel/@identityType', new_resource.pool_identity.to_s) + if iis_version > '7.0' + is_new_identity_type = new_value?(doc.root, 'APPPOOL/add/processModel/@identityType', new_resource.pool_identity.to_s) + end is_new_user_name = new_or_empty_value?(doc.root, 'APPPOOL/add/processModel/@userName', new_resource.pool_username.to_s) is_new_password = new_or_empty_value?(doc.root, 'APPPOOL/add/processModel/@password', new_resource.pool_password.to_s) - is_new_logon_type = new_value?(doc.root, 'APPPOOL/add/processModel/@logonType', new_resource.logon_type.to_s) + if iis_version > '7.0' + is_new_logon_type = new_value?(doc.root, 'APPPOOL/add/processModel/@logonType', new_resource.logon_type.to_s) + end is_new_manual_group_membership = new_value?(doc.root, 'APPPOOL/add/processModel/@manualGroupMembership', new_resource.manual_group_membership.to_s) is_new_idle_timeout = new_value?(doc.root, 'APPPOOL/add/processModel/@idleTimeout', new_resource.idle_timeout.to_s) + if iis_version >= '8.5' + is_new_idle_timeout_action = new_value?(doc.root, 'APPPOOL/add/processModel/@idleTimeoutAction', new_resource.idle_timeout_action) + end is_new_shutdown_time_limit = new_value?(doc.root, 'APPPOOL/add/processModel/@shutdownTimeLimit', new_resource.shutdown_time_limit.to_s) is_new_startup_time_limit = new_value?(doc.root, 'APPPOOL/add/processModel/@startupTimeLimit', new_resource.startup_time_limit.to_s) is_new_pinging_enabled = new_value?(doc.root, 'APPPOOL/add/processModel/@pingingEnabled', new_resource.pinging_enabled.to_s) @@ -169,7 +187,7 @@ def configure is_new_disallow_overlapping_rotation = new_value?(doc.root, 'APPPOOL/add/recycling/@disallowOverlappingRotation', new_resource.disallow_overlapping_rotation.to_s) is_new_disallow_rotation_on_config_change = new_value?(doc.root, 'APPPOOL/add/recycling/@disallowRotationOnConfigChange', new_resource.disallow_rotation_on_config_change.to_s) is_new_recycle_after_time = new_or_empty_value?(doc.root, 'APPPOOL/add/recycling/periodicRestart/@time', new_resource.recycle_after_time.to_s) - is_new_recycle_at_time = new_or_empty_value?(doc.root, 'APPPOOL/add/recycling/periodicRestart/schedule/add/@value', new_resource.recycle_at_time.to_s) + is_new_recycle_at_time = new_or_empty_value?(doc.root, "APPPOOL/add/recycling/periodicRestart/schedule/add[@value='#{new_resource.recycle_at_time}']/@value", new_resource.recycle_at_time.to_s) is_new_private_memory = new_or_empty_value?(doc.root, 'APPPOOL/add/recycling/periodicRestart/@privateMemory', new_resource.private_mem.to_s) is_new_log_event_on_recycle = new_value?(doc.root, 'APPPOOL/add/recycling/@logEventOnRecycle', 'Time, Requests, Schedule, Memory, IsapiUnhealthy, OnDemand, ConfigChange, PrivateMemory') @@ -185,9 +203,19 @@ def configure @cmd = "#{appcmd(node)} set config /section:applicationPools" # root items - configure_application_pool(is_new_auto_start, "autoStart:#{new_resource.auto_start}") - configure_application_pool(is_new_start_mode, "startMode:#{new_resource.start_mode}") - configure_application_pool(new_resource.runtime_version && is_new_managed_runtime_version, "managedRuntimeVersion:v#{new_resource.runtime_version}") + if iis_version >= '7.0' + configure_application_pool(is_new_auto_start, "autoStart:#{new_resource.auto_start}") + end + + if iis_version >= '7.5' + configure_application_pool(is_new_start_mode, "startMode:#{new_resource.start_mode}") + end + + if new_resource.no_managed_code + configure_application_pool(is_new_managed_runtime_version, 'managedRuntimeVersion:') + else + configure_application_pool(new_resource.runtime_version && is_new_managed_runtime_version, "managedRuntimeVersion:v#{new_resource.runtime_version}") + end configure_application_pool(new_resource.pipeline_mode && is_new_pipeline_mode, "managedPipelineMode:#{new_resource.pipeline_mode}") configure_application_pool(new_resource.thirty_two_bit && is_new_enable_32_bit_app_on_win_64, "enable32BitAppOnWin64:#{new_resource.thirty_two_bit}") configure_application_pool(new_resource.queue_length && is_new_queue_length, "queueLength:#{new_resource.queue_length}") @@ -198,20 +226,28 @@ def configure configure_application_pool(is_new_logon_type, "processModel.logonType:#{new_resource.logon_type}") configure_application_pool(is_new_manual_group_membership, "processModel.manualGroupMembership:#{new_resource.manual_group_membership}") configure_application_pool(is_new_idle_timeout, "processModel.idleTimeout:#{new_resource.idle_timeout}") + if iis_version >= '8.5' + configure_application_pool(is_new_idle_timeout_action, "processModel.idleTimeoutAction:#{new_resource.idle_timeout_action}") + end configure_application_pool(is_new_shutdown_time_limit, "processModel.shutdownTimeLimit:#{new_resource.shutdown_time_limit}") configure_application_pool(is_new_startup_time_limit, "processModel.startupTimeLimit:#{new_resource.startup_time_limit}") configure_application_pool(is_new_pinging_enabled, "processModel.pingingEnabled:#{new_resource.pinging_enabled}") configure_application_pool(is_new_ping_interval, "processModel.pingInterval:#{new_resource.ping_interval}") configure_application_pool(is_new_ping_response_time, "processModel.pingResponseTime:#{new_resource.ping_response_time}") + node_array = XPath.match(doc.root, 'APPPOOL/add/recycling/periodicRestart/schedule/add') + should_clear_apppool_schedules = (new_resource.recycle_at_time && is_new_recycle_at_time) || node_array.length > 1 + # recycling items ## Special case this collection removal for now. - if (new_resource.recycle_at_time && is_new_recycle_at_time) + if should_clear_apppool_schedules @was_updated = true - cmd = "#{appcmd(node)} set config /section:applicationPools \"/-[name='#{new_resource.pool_name}'].recycling.periodicRestart.schedule\"" - Chef::Log.debug(@cmd) - shell_out!(@cmd) + is_new_recycle_at_time = true + clear_pool_schedule_cmd = "#{appcmd(node)} set config /section:applicationPools \"/-[name='#{new_resource.pool_name}'].recycling.periodicRestart.schedule\"" + Chef::Log.debug(clear_pool_schedule_cmd) + shell_out!(clear_pool_schedule_cmd) end + configure_application_pool(new_resource.recycle_after_time && is_new_recycle_after_time, "recycling.periodicRestart.time:#{new_resource.recycle_after_time}") configure_application_pool(new_resource.recycle_at_time && is_new_recycle_at_time, "recycling.periodicRestart.schedule.[value='#{new_resource.recycle_at_time}']", '+') configure_application_pool(is_new_log_event_on_recycle, 'recycling.logEventOnRecycle:PrivateMemory,Memory,Schedule,Requests,Time,ConfigChange,OnDemand,IsapiUnhealthy') @@ -244,17 +280,17 @@ def configure end # Application Pool Identity Settings - if ((new_resource.pool_username && new_resource.pool_username != '') && (is_new_user_name || is_new_password)) + if (new_resource.pool_username && new_resource.pool_username != '') && (is_new_user_name || is_new_password) @was_updated = true cmd = "#{appcmd(node)} set config /section:applicationPools" cmd << " \"/[name='#{new_resource.pool_name}'].processModel.identityType:SpecificUser\"" cmd << " \"/[name='#{new_resource.pool_name}'].processModel.userName:#{new_resource.pool_username}\"" - cmd << " \"/[name='#{new_resource.pool_name}'].processModel.password:#{new_resource.pool_password}\"" if (new_resource.pool_password && new_resource.pool_password != '' && is_new_password) + cmd << " \"/[name='#{new_resource.pool_name}'].processModel.password:#{new_resource.pool_password}\"" if new_resource.pool_password && new_resource.pool_password != '' && is_new_password Chef::Log.debug(cmd) shell_out!(cmd) - elsif ((new_resource.pool_username.nil? || new_resource.pool_username == '') && - (new_resource.pool_password.nil? || new_resource.pool_username == '') && - (is_new_identity_type && new_resource.pool_identity != 'SpecificUser')) + elsif (new_resource.pool_username.nil? || new_resource.pool_username == '') && + (new_resource.pool_password.nil? || new_resource.pool_username == '') && + (is_new_identity_type && new_resource.pool_identity != 'SpecificUser') @was_updated = true cmd = "#{appcmd(node)} set config /section:applicationPools" cmd << " \"/[name='#{new_resource.pool_name}'].processModel.identityType:#{new_resource.pool_identity}\"" @@ -263,7 +299,6 @@ def configure end if @was_updated - new_resource.updated_by_last_action(true) Chef::Log.info("#{new_resource} configured application pool") else Chef::Log.debug("#{new_resource} application pool - nothing to do") @@ -273,14 +308,14 @@ def configure level :warn end end + + @was_updated end private def configure_application_pool(condition, config, add_remove = '') - unless condition - return - end + return unless condition @was_updated = true @cmd << " \"/#{add_remove}[name='#{new_resource.pool_name}'].#{config}\"" diff --git a/cookbooks/iis/providers/root.rb b/cookbooks/iis/providers/root.rb new file mode 100644 index 0000000..1538b58 --- /dev/null +++ b/cookbooks/iis/providers/root.rb @@ -0,0 +1,68 @@ +# +# Author:: Justin Schuhmann () +# Cookbook Name:: iis +# Provider:: root +# +# Copyright:: Justin Schuhmann +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 Opscode::IIS::Helper +include Opscode::IIS::Processors + +action :add do + @was_updated = false + + @was_updated = default_documents(new_resource.add_default_documents, new_resource.default_documents_enabled, true, false) | @was_updated + @was_updated = mime_maps(new_resource.add_mime_maps, true, false) | @was_updated + + if @was_updated + new_resource.updated_by_last_action(true) + else + Chef::Log.debug("#{new_resource} - nothing to do") + end +end + +action :delete do + @was_updated = false + + @was_updated = default_documents(new_resource.delete_default_documents, new_resource.default_documents_enabled, false) | @was_updated + @was_updated = mime_maps(new_resource.delete_mime_maps, false) | @was_updated + + if @was_updated + new_resource.updated_by_last_action(true) + else + Chef::Log.debug("#{new_resource} - nothing to do") + end +end + +action :config do + @was_updated = false + + @was_updated = default_documents(new_resource.default_documents, new_resource.default_documents_enabled) | @was_updated + @was_updated = mime_maps(new_resource.mime_maps) | @was_updated + + if @was_updated + new_resource.updated_by_last_action(true) + else + Chef::Log.debug("#{new_resource} - nothing to do") + end +end + +def load_current_resource + @current_resource = Chef::Resource::IisRoot.new(new_resource.name) + @current_resource.default_documents(new_resource.default_documents) + @current_resource.default_documents_enabled(new_resource.default_documents_enabled) + @current_resource.mime_maps(new_resource.mime_maps) +end diff --git a/cookbooks/iis/providers/section.rb b/cookbooks/iis/providers/section.rb index a96132f..398f3c3 100644 --- a/cookbooks/iis/providers/section.rb +++ b/cookbooks/iis/providers/section.rb @@ -24,11 +24,12 @@ require 'rexml/document' include Chef::Mixin::ShellOut include REXML include Opscode::IIS::Helper +include Opscode::IIS::Processors action :lock do @current_resource.exists = new_value?(doc.root, 'CONFIG/@overrideMode', 'Deny') - if !@current_resource.exists + if @current_resource.exists cmd = "#{appcmd(node)} lock config -section:\"#{new_resource.section}\" -commit:apphost" Chef::Log.debug(cmd) shell_out!(cmd, returns: new_resource.returns) @@ -42,7 +43,7 @@ end action :unlock do @current_resource.exists = new_value?(doc.root, 'CONFIG/@overrideMode', 'Allow') - if !@current_resource.exists + if @current_resource.exists cmd = "#{appcmd(node)} unlock config -section:\"#{new_resource.section}\" -commit:apphost" Chef::Log.debug(cmd) shell_out!(cmd, returns: new_resource.returns) @@ -59,7 +60,7 @@ def load_current_resource end def doc - cmd_current_values = "#{appcmd(node)} list config \"\" -section:#{new_resource.section} /config:* /xml" + cmd_current_values = "#{appcmd(node)} list config -section:#{new_resource.section} /config:* /xml" Chef::Log.debug(cmd_current_values) cmd_current_values = shell_out(cmd_current_values) if cmd_current_values.stderr.empty? diff --git a/cookbooks/iis/providers/site.rb b/cookbooks/iis/providers/site.rb index 8d6f9bf..aa2b9e3 100644 --- a/cookbooks/iis/providers/site.rb +++ b/cookbooks/iis/providers/site.rb @@ -24,6 +24,7 @@ require 'rexml/document' include Chef::Mixin::ShellOut include REXML include Opscode::IIS::Helper +include Opscode::IIS::Processors action :add do if !@current_resource.exists @@ -39,15 +40,13 @@ action :add do end # support for additional options -logDir, -limits, -ftpServer, etc... - if new_resource.options - cmd << " #{new_resource.options}" - end - shell_out!(cmd, returns: [0, 42]) + cmd << " #{new_resource.options}" if new_resource.options + shell_out!(cmd, returns: [0, 42]) configure if new_resource.application_pool - shell_out!("#{appcmd(node)} set app \"#{new_resource.site_name}/\" /applicationPool:\"#{new_resource.application_pool}\"", returns: [0, 42]) + shell_out!("#{appcmd(node)} set app \"#{new_resource.site_name}/\" /applicationPool:\"#{new_resource.application_pool}\"", returns: [0, 42]) end new_resource.updated_by_last_action(true) Chef::Log.info("#{new_resource} added new site '#{new_resource.site_name}'") @@ -57,13 +56,13 @@ action :add do end action :config do - configure + new_resource.updated_by_last_action(true) if configure end action :delete do if @current_resource.exists Chef::Log.info("#{appcmd(node)} stop site /site.name:\"#{new_resource.site_name}\"") - shell_out!("#{appcmd(node)} delete site /site.name:\"#{new_resource.site_name}\"", returns: [0, 42]) + shell_out!("#{appcmd(node)} delete site /site.name:\"#{new_resource.site_name}\"", returns: [0, 42]) new_resource.updated_by_last_action(true) Chef::Log.info("#{new_resource} deleted") else @@ -73,7 +72,7 @@ end action :start do if !@current_resource.running - shell_out!("#{appcmd(node)} start site /site.name:\"#{new_resource.site_name}\"", returns: [0, 42]) + shell_out!("#{appcmd(node)} start site /site.name:\"#{new_resource.site_name}\"", returns: [0, 42]) new_resource.updated_by_last_action(true) Chef::Log.info("#{new_resource} started") else @@ -84,7 +83,7 @@ end action :stop do if @current_resource.running Chef::Log.info("#{appcmd(node)} stop site /site.name:\"#{new_resource.site_name}\"") - shell_out!("#{appcmd(node)} stop site /site.name:\"#{new_resource.site_name}\"", returns: [0, 42]) + shell_out!("#{appcmd(node)} stop site /site.name:\"#{new_resource.site_name}\"", returns: [0, 42]) new_resource.updated_by_last_action(true) Chef::Log.info("#{new_resource} stopped") else @@ -93,9 +92,9 @@ action :stop do end action :restart do - shell_out!("#{appcmd(node)} stop site /site.name:\"#{new_resource.site_name}\"", returns: [0, 42]) + shell_out!("#{appcmd(node)} stop site /site.name:\"#{new_resource.site_name}\"", returns: [0, 42]) sleep 2 - shell_out!("#{appcmd(node)} start site /site.name:\"#{new_resource.site_name}\"", returns: [0, 42]) + shell_out!("#{appcmd(node)} start site /site.name:\"#{new_resource.site_name}\"", returns: [0, 42]) new_resource.updated_by_last_action(true) Chef::Log.info("#{new_resource} restarted") end @@ -109,7 +108,7 @@ def load_current_resource Chef::Log.debug("#{new_resource} list site command output: #{cmd.stdout}") if cmd.stderr.empty? result = cmd.stdout.gsub(/\r\n?/, "\n") # ensure we have no carriage returns - result = result.match(/^SITE\s\"(#{new_resource.site_name})\"\s\(id:(.*),bindings:(.*),state:(.*)\)$/) + result = result.match(/^SITE\s\"(#{new_resource.site_name})\"\s\(id:(.*),bindings:(.*),state:(.*)\)$/i) Chef::Log.debug("#{new_resource} current_resource match output: #{result}") if result @current_resource.site_id(result[2].to_i) @@ -128,94 +127,100 @@ def load_current_resource end private - def configure - was_updated = false - cmd_current_values = "#{appcmd(node)} list site \"#{new_resource.site_name}\" /config:* /xml" - Chef::Log.debug(cmd_current_values) - cmd_current_values = shell_out(cmd_current_values) - if cmd_current_values.stderr.empty? - xml = cmd_current_values.stdout - doc = Document.new(xml) - is_new_bindings = new_value?(doc.root, 'SITE/@bindings', new_resource.bindings.to_s) - is_new_physical_path = new_or_empty_value?(doc.root, 'SITE/site/application/virtualDirectory/@physicalPath', new_resource.path.to_s) - is_new_port_host_provided = !"#{XPath.first(doc.root, 'SITE/@bindings')},".include?("#{new_resource.protocol}/*:#{new_resource.port}:#{new_resource.host_header},") - is_new_site_id = new_value?(doc.root, 'SITE/site/@id', new_resource.site_id.to_s) - is_new_log_directory = new_or_empty_value?(doc.root, 'SITE/logFiles/@directory', new_resource.log_directory.to_s) - is_new_log_period = new_or_empty_value?(doc.root, 'SITE/logFile/@period', new_resource.log_period.to_s) - is_new_log_trunc = new_or_empty_value?(doc.root, 'SITE/logFiles/@truncateSize', new_resource.log_truncsize.to_s) - is_new_application_pool = new_value?(doc.root, 'SITE/site/application/@applicationPool', new_resource.application_pool) - if (new_resource.bindings && is_new_bindings) - was_updated = true - cmd = "#{appcmd(node)} set site /site.name:\"#{new_resource.site_name}\"" - cmd << " /bindings:\"#{new_resource.bindings}\"" - shell_out!(cmd) - new_resource.updated_by_last_action(true) - elsif (((new_resource.port || new_resource.host_header || new_resource.protocol) && is_new_port_host_provided) && !new_resource.bindings) - was_updated = true - cmd = "#{appcmd(node)} set site \"#{new_resource.site_name}\"" - cmd << " /bindings:#{new_resource.protocol}/*:#{new_resource.port}:#{new_resource.host_header}" - Chef::Log.debug(cmd) - shell_out!(cmd) - new_resource.updated_by_last_action(true) - end +def configure + @was_updated = false + cmd_current_values = "#{appcmd(node)} list site \"#{new_resource.site_name}\" /config:* /xml" + Chef::Log.debug(cmd_current_values) + cmd_current_values = shell_out(cmd_current_values) + if cmd_current_values.stderr.empty? + xml = cmd_current_values.stdout + doc = Document.new(xml) + is_new_bindings = new_value?(doc.root, 'SITE/@bindings', new_resource.bindings.to_s) + is_new_physical_path = new_or_empty_value?(doc.root, 'SITE/site/application/virtualDirectory/@physicalPath', new_resource.path.to_s) + is_new_port_host_provided = !"#{XPath.first(doc.root, 'SITE/@bindings')},".include?("#{new_resource.protocol}/*:#{new_resource.port}:#{new_resource.host_header},") + is_new_site_id = new_value?(doc.root, 'SITE/site/@id', new_resource.site_id.to_s) + is_new_log_directory = new_or_empty_value?(doc.root, 'SITE/logFiles/@directory', new_resource.log_directory.to_s) + is_new_log_period = new_or_empty_value?(doc.root, 'SITE/logFile/@period', new_resource.log_period.to_s) + is_new_log_trunc = new_or_empty_value?(doc.root, 'SITE/logFiles/@truncateSize', new_resource.log_truncsize.to_s) + is_new_application_pool = new_value?(doc.root, 'SITE/site/application/@applicationPool', new_resource.application_pool) - if new_resource.application_pool && is_new_application_pool - was_updated = true - cmd = "#{appcmd(node)} set app \"#{new_resource.site_name}/\" /applicationPool:\"#{new_resource.application_pool}\"" - Chef::Log.debug(cmd) - shell_out!(cmd, returns: [0, 42]) - end - - if new_resource.path && is_new_physical_path - was_updated = true - cmd = "#{appcmd(node)} set vdir \"#{new_resource.site_name}/\"" - cmd << " /physicalPath:\"#{windows_cleanpath(new_resource.path)}\"" - Chef::Log.debug(cmd) - shell_out!(cmd) - end + if new_resource.bindings && is_new_bindings + @was_updated = true + cmd = "#{appcmd(node)} set site /site.name:\"#{new_resource.site_name}\"" + cmd << " /bindings:\"#{new_resource.bindings}\"" + shell_out!(cmd) + new_resource.updated_by_last_action(true) + elsif ((new_resource.port || new_resource.host_header || new_resource.protocol) && is_new_port_host_provided) && !new_resource.bindings + @was_updated = true + cmd = "#{appcmd(node)} set site \"#{new_resource.site_name}\"" + cmd << " /bindings:#{new_resource.protocol}/*:#{new_resource.port}:#{new_resource.host_header}" + Chef::Log.debug(cmd) + shell_out!(cmd) + new_resource.updated_by_last_action(true) + end - if new_resource.site_id && is_new_site_id - cmd = "#{appcmd(node)} set site \"#{new_resource.site_name}\"" - cmd << " /id:#{new_resource.site_id}" - Chef::Log.debug(cmd) - shell_out!(cmd) - new_resource.updated_by_last_action(true) - end + if new_resource.application_pool && is_new_application_pool + @was_updated = true + cmd = "#{appcmd(node)} set app \"#{new_resource.site_name}/\" /applicationPool:\"#{new_resource.application_pool}\"" + Chef::Log.debug(cmd) + shell_out!(cmd, returns: [0, 42]) + end - if new_resource.log_directory && is_new_log_directory - cmd = "#{appcmd(node)} set site \"#{new_resource.site_name}\"" - cmd << " /logFile.directory:#{windows_cleanpath(new_resource.log_directory)}" - Chef::Log.debug(cmd) - shell_out!(cmd) - new_resource.updated_by_last_action(true) - end + if new_resource.path && is_new_physical_path + @was_updated = true + cmd = "#{appcmd(node)} set vdir \"#{new_resource.site_name}/\"" + cmd << " /physicalPath:\"#{windows_cleanpath(new_resource.path)}\"" + Chef::Log.debug(cmd) + shell_out!(cmd) + end - if new_resource.log_period && is_new_log_period - cmd = "#{appcmd(node)} set site \"#{new_resource.site_name}\"" - cmd << " /logFile.period:#{new_resource.log_period}" - Chef::Log.debug(cmd) - shell_out!(cmd) - new_resource.updated_by_last_action(true) - end + if new_resource.site_id && is_new_site_id + @was_updated = true + cmd = "#{appcmd(node)} set site \"#{new_resource.site_name}\"" + cmd << " /id:#{new_resource.site_id}" + Chef::Log.debug(cmd) + shell_out!(cmd) + new_resource.updated_by_last_action(true) + end - if new_resource.log_truncsize && is_new_log_trunc - cmd = "#{appcmd(node)} set site \"#{new_resource.site_name}\"" - cmd << " /logFile.truncateSize:#{new_resource.log_truncsize}" - Chef::Log.debug(cmd) - shell_out!(cmd) - new_resource.updated_by_last_action(true) - end + if new_resource.log_directory && is_new_log_directory + @was_updated = true + cmd = "#{appcmd(node)} set site \"#{new_resource.site_name}\"" + cmd << " /logFile.directory:#{windows_cleanpath(new_resource.log_directory)}" + Chef::Log.debug(cmd) + shell_out!(cmd) + new_resource.updated_by_last_action(true) + end - if was_updated - new_resource.updated_by_last_action(true) - Chef::Log.info("#{new_resource} configured site '#{new_resource.site_name}'") - else - Chef::Log.debug("#{new_resource} site - nothing to do") - end + if new_resource.log_period && is_new_log_period + @was_updated = true + cmd = "#{appcmd(node)} set site \"#{new_resource.site_name}\"" + cmd << " /logFile.period:#{new_resource.log_period}" + Chef::Log.debug(cmd) + shell_out!(cmd) + new_resource.updated_by_last_action(true) + end + + if new_resource.log_truncsize && is_new_log_trunc + @was_updated = true + cmd = "#{appcmd(node)} set site \"#{new_resource.site_name}\"" + cmd << " /logFile.truncateSize:#{new_resource.log_truncsize}" + Chef::Log.debug(cmd) + shell_out!(cmd) + new_resource.updated_by_last_action(true) + end + + if @was_updated + Chef::Log.info("#{new_resource} configured site '#{new_resource.site_name}'") else - log "Failed to run iis_site action :config, #{cmd_current_values.stderr}" do - level :warn - end + Chef::Log.debug("#{new_resource} site - nothing to do") + end + else + log "Failed to run iis_site action :config, #{cmd_current_values.stderr}" do + level :warn end end + + @was_updated +end diff --git a/cookbooks/iis/providers/vdir.rb b/cookbooks/iis/providers/vdir.rb index b2d2332..908b543 100644 --- a/cookbooks/iis/providers/vdir.rb +++ b/cookbooks/iis/providers/vdir.rb @@ -24,6 +24,7 @@ require 'rexml/document' include Chef::Mixin::ShellOut include REXML include Opscode::IIS::Helper +include Opscode::IIS::Processors action :add do if !@current_resource.exists @@ -34,9 +35,10 @@ action :add do cmd << " /password:\"#{new_resource.password}\"" if new_resource.password cmd << " /logonMethod:#{new_resource.logon_method}" if new_resource.logon_method cmd << " /allowSubDirConfig:#{new_resource.allow_sub_dir_config}" if new_resource.allow_sub_dir_config + cmd << " /commit:\"MACHINE/WEBROOT/APPHOST\"" Chef::Log.info(cmd) - shell_out!(cmd, returns: [0, 42, 183]) + shell_out!(cmd, returns: [0, 42, 183]) new_resource.updated_by_last_action(true) Chef::Log.info("#{new_resource} added new virtual directory to application: '#{new_resource.application_name}'") else @@ -45,7 +47,7 @@ action :add do end action :config do - was_updated = false + @was_updated = false cmd_current_values = "#{appcmd(node)} list vdir \"#{application_identifier}\" /config:* /xml" Chef::Log.debug(cmd_current_values) cmd_current_values = shell_out!(cmd_current_values) @@ -59,41 +61,41 @@ action :config do is_new_allow_sub_dir_config = new_or_empty_value?(doc.root, 'VDIR/virtualDirectory/@allowSubDirConfig', new_resource.allow_sub_dir_config.to_s) if new_resource.physical_path && is_new_physical_path - was_updated = true + @was_updated = true cmd = "#{appcmd(node)} set vdir \"#{application_identifier}\" /physicalPath:\"#{new_resource.physical_path}\"" Chef::Log.debug(cmd) shell_out!(cmd) end if new_resource.username && is_new_user_name - was_updated = true + @was_updated = true cmd = "#{appcmd(node)} set vdir \"#{application_identifier}\" /userName:\"#{new_resource.username}\"" Chef::Log.debug(cmd) shell_out!(cmd) end if new_resource.password && is_new_password - was_updated = true + @was_updated = true cmd = "#{appcmd(node)} set vdir \"#{application_identifier}\" /password:\"#{new_resource.password}\"" Chef::Log.debug(cmd) shell_out!(cmd) end if new_resource.logon_method && is_new_logon_method - was_updated = true + @was_updated = true cmd = "#{appcmd(node)} set vdir \"#{application_identifier}\" /logonMethod:#{new_resource.logon_method}" Chef::Log.debug(cmd) shell_out!(cmd) end if new_resource.allow_sub_dir_config && is_new_allow_sub_dir_config - was_updated = true + @was_updated = true cmd = "#{appcmd(node)} set vdir \"#{application_identifier}\" /allowSubDirConfig:#{new_resource.allow_sub_dir_config}" Chef::Log.debug(cmd) shell_out!(cmd) end - if was_updated + if @was_updated new_resource.updated_by_last_action(true) Chef::Log.info("#{new_resource} configured virtual directory to application: '#{new_resource.application_name}'") else @@ -108,7 +110,7 @@ end action :delete do if @current_resource.exists - shell_out!("#{appcmd(node)} delete vdir \"#{application_identifier}\"", returns: [0, 42]) + shell_out!("#{appcmd(node)} delete vdir \"#{application_identifier}\"", returns: [0, 42]) new_resource.updated_by_last_action(true) Chef::Log.info("#{new_resource} deleted") else @@ -121,13 +123,13 @@ def load_current_resource @current_resource.application_name(application_name_check) @current_resource.path(new_resource.path) @current_resource.physical_path(new_resource.physical_path) - cmd = shell_out("#{ appcmd(node) } list vdir \"#{application_identifier}\"") - Chef::Log.debug("#{ new_resource } list vdir command output: #{ cmd.stdout }") + cmd = shell_out("#{appcmd(node)} list vdir \"#{application_identifier}\"") + Chef::Log.debug("#{new_resource} list vdir command output: #{cmd.stdout}") if cmd.stderr.empty? # VDIR "Testfu Site/Content/Test" result = cmd.stdout.match(/^VDIR\s\"#{Regexp.escape(application_identifier)}\"/) - Chef::Log.debug("#{ new_resource } current_resource match output: #{ result }") + Chef::Log.debug("#{new_resource} current_resource match output: #{result}") if result @current_resource.exists = true else diff --git a/cookbooks/iis/recipes/default.rb b/cookbooks/iis/recipes/default.rb index 5c8c6e5..710f05a 100644 --- a/cookbooks/iis/recipes/default.rb +++ b/cookbooks/iis/recipes/default.rb @@ -25,6 +25,7 @@ default = Opscode::IIS::Helper.older_than_windows2008r2? ? 'Web-Server' : 'IIS-W windows_feature feature do action :install all !Opscode::IIS::Helper.older_than_windows2012? + source node['iis']['source'] unless node['iis']['source'].nil? end end diff --git a/cookbooks/iis/resources/app.rb b/cookbooks/iis/resources/app.rb index b3993e4..c51a85f 100644 --- a/cookbooks/iis/resources/app.rb +++ b/cookbooks/iis/resources/app.rb @@ -26,4 +26,7 @@ attribute :path, kind_of: String, default: '/' attribute :application_pool, kind_of: String attribute :physical_path, kind_of: String attribute :enabled_protocols, kind_of: String +attribute :default_documents, kind_of: Array, default: [] +attribute :mime_maps, kind_of: Array, default: [] + attr_accessor :exists, :running diff --git a/cookbooks/iis/resources/config.rb b/cookbooks/iis/resources/config.rb index ad65fe8..6351f3b 100644 --- a/cookbooks/iis/resources/config.rb +++ b/cookbooks/iis/resources/config.rb @@ -18,8 +18,8 @@ # limitations under the License. # -actions :config -default_action :config +actions :config, :clear, :set +default_action :set attribute :cfg_cmd, kind_of: String, name_attribute: true attribute :returns, kind_of: [Integer, Array], default: 0 diff --git a/cookbooks/iis/resources/module.rb b/cookbooks/iis/resources/module.rb index 4ca8360..b5b26f5 100644 --- a/cookbooks/iis/resources/module.rb +++ b/cookbooks/iis/resources/module.rb @@ -18,11 +18,13 @@ # limitations under the License. # -actions :add, :delete +actions :add, :delete, :install, :uninstall default_action :add attribute :module_name, kind_of: String, name_attribute: true attribute :type, kind_of: String, default: nil +attribute :add, kind_of: [FalseClass, TrueClass], default: nil +attribute :image, kind_of: String, default: nil attribute :precondition, kind_of: String, default: nil attribute :application, kind_of: String, default: nil diff --git a/cookbooks/iis/resources/pool.rb b/cookbooks/iis/resources/pool.rb index 72a2a16..9c02161 100644 --- a/cookbooks/iis/resources/pool.rb +++ b/cookbooks/iis/resources/pool.rb @@ -43,6 +43,7 @@ attribute :pool_password, kind_of: String attribute :logon_type, kind_of: Symbol, equal_to: [:LogonBatch, :LogonService], default: :LogonBatch attribute :manual_group_membership, kind_of: [TrueClass, FalseClass], default: false attribute :idle_timeout, kind_of: String, default: '00:20:00' +attribute :idle_timeout_action, kind_of: Symbol, equal_to: [:Terminate, :Suspend], default: :Terminate attribute :shutdown_time_limit, kind_of: String, default: '00:01:30' attribute :startup_time_limit, kind_of: String, default: '00:01:30' attribute :pinging_enabled, kind_of: [TrueClass, FalseClass], default: true diff --git a/cookbooks/iis/resources/root.rb b/cookbooks/iis/resources/root.rb new file mode 100644 index 0000000..0ca1ce9 --- /dev/null +++ b/cookbooks/iis/resources/root.rb @@ -0,0 +1,31 @@ +# +# Author:: Justin Schuhmann () +# Cookbook Name:: iis +# Resource:: root +# +# Copyright:: Justin Schuhmann +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 :config, :add, :delete +default_action :config + +# default documents +attribute :default_documents_enabled, kind_of: [TrueClass, FalseClass], default: true +attribute :default_documents, kind_of: Array, default: ['Default.htm', 'Default.asp', 'index.htm', 'index.html', 'iisstart.htm', 'default.aspx'] +attribute :mime_maps, kind_of: Array, default: ["fileExtension='.323',mimeType='text/h323'", "fileExtension='.3g2',mimeType='video/3gpp2'", "fileExtension='.3gp2',mimeType='video/3gpp2'", "fileExtension='.3gp',mimeType='video/3gpp'", "fileExtension='.3gpp',mimeType='video/3gpp'", "fileExtension='.aaf',mimeType='application/octet-stream'", "fileExtension='.aac',mimeType='audio/aac'", "fileExtension='.aca',mimeType='application/octet-stream'", "fileExtension='.accdb',mimeType='application/msaccess'", "fileExtension='.accde',mimeType='application/msaccess'", "fileExtension='.accdt',mimeType='application/msaccess'", "fileExtension='.acx',mimeType='application/internet-property-stream'", "fileExtension='.adt',mimeType='audio/vnd.dlna.adts'", "fileExtension='.adts',mimeType='audio/vnd.dlna.adts'", "fileExtension='.afm',mimeType='application/octet-stream'", "fileExtension='.ai',mimeType='application/postscript'", "fileExtension='.aif',mimeType='audio/x-aiff'", "fileExtension='.aifc',mimeType='audio/aiff'", "fileExtension='.aiff',mimeType='audio/aiff'", "fileExtension='.application',mimeType='application/x-ms-application'", "fileExtension='.art',mimeType='image/x-jg'", "fileExtension='.asd',mimeType='application/octet-stream'", "fileExtension='.asf',mimeType='video/x-ms-asf'", "fileExtension='.asi',mimeType='application/octet-stream'", "fileExtension='.asm',mimeType='text/plain'", "fileExtension='.asr',mimeType='video/x-ms-asf'", "fileExtension='.asx',mimeType='video/x-ms-asf'", "fileExtension='.atom',mimeType='application/atom+xml'", "fileExtension='.au',mimeType='audio/basic'", "fileExtension='.avi',mimeType='video/avi'", "fileExtension='.axs',mimeType='application/olescript'", "fileExtension='.bas',mimeType='text/plain'", "fileExtension='.bcpio',mimeType='application/x-bcpio'", "fileExtension='.bin',mimeType='application/octet-stream'", "fileExtension='.bmp',mimeType='image/bmp'", "fileExtension='.c',mimeType='text/plain'", "fileExtension='.cab',mimeType='application/vnd.ms-cab-compressed'", "fileExtension='.calx',mimeType='application/vnd.ms-office.calx'", "fileExtension='.cat',mimeType='application/vnd.ms-pki.seccat'", "fileExtension='.cdf',mimeType='application/x-cdf'", "fileExtension='.chm',mimeType='application/octet-stream'", "fileExtension='.class',mimeType='application/x-java-applet'", "fileExtension='.clp',mimeType='application/x-msclip'", "fileExtension='.cmx',mimeType='image/x-cmx'", "fileExtension='.cnf',mimeType='text/plain'", "fileExtension='.cod',mimeType='image/cis-cod'", "fileExtension='.cpio',mimeType='application/x-cpio'", "fileExtension='.cpp',mimeType='text/plain'", "fileExtension='.crd',mimeType='application/x-mscardfile'", "fileExtension='.crl',mimeType='application/pkix-crl'", "fileExtension='.crt',mimeType='application/x-x509-ca-cert'", "fileExtension='.csh',mimeType='application/x-csh'", "fileExtension='.css',mimeType='text/css'", "fileExtension='.csv',mimeType='application/octet-stream'", "fileExtension='.cur',mimeType='application/octet-stream'", "fileExtension='.dcr',mimeType='application/x-director'", "fileExtension='.deploy',mimeType='application/octet-stream'", "fileExtension='.der',mimeType='application/x-x509-ca-cert'", "fileExtension='.dib',mimeType='image/bmp'", "fileExtension='.dir',mimeType='application/x-director'", "fileExtension='.disco',mimeType='text/xml'", "fileExtension='.dll',mimeType='application/x-msdownload'", "fileExtension='.dll.config',mimeType='text/xml'", "fileExtension='.dlm',mimeType='text/dlm'", "fileExtension='.doc',mimeType='application/msword'", "fileExtension='.docm',mimeType='application/vnd.ms-word.document.macroEnabled.12'", "fileExtension='.docx',mimeType='application/vnd.openxmlformats-officedocument.wordprocessingml.document'", "fileExtension='.dot',mimeType='application/msword'", "fileExtension='.dotm',mimeType='application/vnd.ms-word.template.macroEnabled.12'", "fileExtension='.dotx',mimeType='application/vnd.openxmlformats-officedocument.wordprocessingml.template'", "fileExtension='.dsp',mimeType='application/octet-stream'", "fileExtension='.dtd',mimeType='text/xml'", "fileExtension='.dvi',mimeType='application/x-dvi'", "fileExtension='.dvr-ms',mimeType='video/x-ms-dvr'", "fileExtension='.dwf',mimeType='drawing/x-dwf'", "fileExtension='.dwp',mimeType='application/octet-stream'", "fileExtension='.dxr',mimeType='application/x-director'", "fileExtension='.eml',mimeType='message/rfc822'", "fileExtension='.emz',mimeType='application/octet-stream'", "fileExtension='.eot',mimeType='application/vnd.ms-fontobject'", "fileExtension='.eps',mimeType='application/postscript'", "fileExtension='.etx',mimeType='text/x-setext'", "fileExtension='.evy',mimeType='application/envoy'", "fileExtension='.exe',mimeType='application/octet-stream'", "fileExtension='.exe.config',mimeType='text/xml'", "fileExtension='.fdf',mimeType='application/vnd.fdf'", "fileExtension='.fif',mimeType='application/fractals'", "fileExtension='.fla',mimeType='application/octet-stream'", "fileExtension='.flr',mimeType='x-world/x-vrml'", "fileExtension='.flv',mimeType='video/x-flv'", "fileExtension='.gif',mimeType='image/gif'", "fileExtension='.gtar',mimeType='application/x-gtar'", "fileExtension='.gz',mimeType='application/x-gzip'", "fileExtension='.h',mimeType='text/plain'", "fileExtension='.hdf',mimeType='application/x-hdf'", "fileExtension='.hdml',mimeType='text/x-hdml'", "fileExtension='.hhc',mimeType='application/x-oleobject'", "fileExtension='.hhk',mimeType='application/octet-stream'", "fileExtension='.hhp',mimeType='application/octet-stream'", "fileExtension='.hlp',mimeType='application/winhlp'", "fileExtension='.hqx',mimeType='application/mac-binhex40'", "fileExtension='.hta',mimeType='application/hta'", "fileExtension='.htc',mimeType='text/x-component'", "fileExtension='.htm',mimeType='text/html'", "fileExtension='.html',mimeType='text/html'", "fileExtension='.htt',mimeType='text/webviewhtml'", "fileExtension='.hxt',mimeType='text/html'", "fileExtension='.ico',mimeType='image/x-icon'", "fileExtension='.ics',mimeType='text/calendar'", "fileExtension='.ief',mimeType='image/ief'", "fileExtension='.iii',mimeType='application/x-iphone'", "fileExtension='.inf',mimeType='application/octet-stream'", "fileExtension='.ins',mimeType='application/x-internet-signup'", "fileExtension='.isp',mimeType='application/x-internet-signup'", "fileExtension='.IVF',mimeType='video/x-ivf'", "fileExtension='.jar',mimeType='application/java-archive'", "fileExtension='.java',mimeType='application/octet-stream'", "fileExtension='.jck',mimeType='application/liquidmotion'", "fileExtension='.jcz',mimeType='application/liquidmotion'", "fileExtension='.jfif',mimeType='image/pjpeg'", "fileExtension='.jpb',mimeType='application/octet-stream'", "fileExtension='.jpe',mimeType='image/jpeg'", "fileExtension='.jpeg',mimeType='image/jpeg'", "fileExtension='.jpg',mimeType='image/jpeg'", "fileExtension='.js',mimeType='application/javascript'", "fileExtension='.json',mimeType='application/json'", "fileExtension='.jsx',mimeType='text/jscript'", "fileExtension='.latex',mimeType='application/x-latex'", "fileExtension='.lit',mimeType='application/x-ms-reader'", "fileExtension='.lpk',mimeType='application/octet-stream'", "fileExtension='.lsf',mimeType='video/x-la-asf'", "fileExtension='.lsx',mimeType='video/x-la-asf'", "fileExtension='.lzh',mimeType='application/octet-stream'", "fileExtension='.m13',mimeType='application/x-msmediaview'", "fileExtension='.m14',mimeType='application/x-msmediaview'", "fileExtension='.m1v',mimeType='video/mpeg'", "fileExtension='.m2ts',mimeType='video/vnd.dlna.mpeg-tts'", "fileExtension='.m3u',mimeType='audio/x-mpegurl'", "fileExtension='.m4a',mimeType='audio/mp4'", "fileExtension='.m4v',mimeType='video/mp4'", "fileExtension='.man',mimeType='application/x-troff-man'", "fileExtension='.manifest',mimeType='application/x-ms-manifest'", "fileExtension='.map',mimeType='text/plain'", "fileExtension='.mdb',mimeType='application/x-msaccess'", "fileExtension='.mdp',mimeType='application/octet-stream'", "fileExtension='.me',mimeType='application/x-troff-me'", "fileExtension='.mht',mimeType='message/rfc822'", "fileExtension='.mhtml',mimeType='message/rfc822'", "fileExtension='.mid',mimeType='audio/mid'", "fileExtension='.midi',mimeType='audio/mid'", "fileExtension='.mix',mimeType='application/octet-stream'", "fileExtension='.mmf',mimeType='application/x-smaf'", "fileExtension='.mno',mimeType='text/xml'", "fileExtension='.mny',mimeType='application/x-msmoney'", "fileExtension='.mov',mimeType='video/quicktime'", "fileExtension='.movie',mimeType='video/x-sgi-movie'", "fileExtension='.mp2',mimeType='video/mpeg'", "fileExtension='.mp3',mimeType='audio/mpeg'", "fileExtension='.mp4',mimeType='video/mp4'", "fileExtension='.mp4v',mimeType='video/mp4'", "fileExtension='.mpa',mimeType='video/mpeg'", "fileExtension='.mpe',mimeType='video/mpeg'", "fileExtension='.mpeg',mimeType='video/mpeg'", "fileExtension='.mpg',mimeType='video/mpeg'", "fileExtension='.mpp',mimeType='application/vnd.ms-project'", "fileExtension='.mpv2',mimeType='video/mpeg'", "fileExtension='.ms',mimeType='application/x-troff-ms'", "fileExtension='.msi',mimeType='application/octet-stream'", "fileExtension='.mso',mimeType='application/octet-stream'", "fileExtension='.mvb',mimeType='application/x-msmediaview'", "fileExtension='.mvc',mimeType='application/x-miva-compiled'", "fileExtension='.nc',mimeType='application/x-netcdf'", "fileExtension='.nsc',mimeType='video/x-ms-asf'", "fileExtension='.nws',mimeType='message/rfc822'", "fileExtension='.ocx',mimeType='application/octet-stream'", "fileExtension='.oda',mimeType='application/oda'", "fileExtension='.odc',mimeType='text/x-ms-odc'", "fileExtension='.ods',mimeType='application/oleobject'", "fileExtension='.oga',mimeType='audio/ogg'", "fileExtension='.ogg',mimeType='video/ogg'", "fileExtension='.ogv',mimeType='video/ogg'", "fileExtension='.one',mimeType='application/onenote'", "fileExtension='.onea',mimeType='application/onenote'", "fileExtension='.onetoc',mimeType='application/onenote'", "fileExtension='.onetoc2',mimeType='application/onenote'", "fileExtension='.onetmp',mimeType='application/onenote'", "fileExtension='.onepkg',mimeType='application/onenote'", "fileExtension='.osdx',mimeType='application/opensearchdescription+xml'", "fileExtension='.otf',mimeType='font/otf'", "fileExtension='.p10',mimeType='application/pkcs10'", "fileExtension='.p12',mimeType='application/x-pkcs12'", "fileExtension='.p7b',mimeType='application/x-pkcs7-certificates'", "fileExtension='.p7c',mimeType='application/pkcs7-mime'", "fileExtension='.p7m',mimeType='application/pkcs7-mime'", "fileExtension='.p7r',mimeType='application/x-pkcs7-certreqresp'", "fileExtension='.p7s',mimeType='application/pkcs7-signature'", "fileExtension='.pbm',mimeType='image/x-portable-bitmap'", "fileExtension='.pcx',mimeType='application/octet-stream'", "fileExtension='.pcz',mimeType='application/octet-stream'", "fileExtension='.pdf',mimeType='application/pdf'", "fileExtension='.pfb',mimeType='application/octet-stream'", "fileExtension='.pfm',mimeType='application/octet-stream'", "fileExtension='.pfx',mimeType='application/x-pkcs12'", "fileExtension='.pgm',mimeType='image/x-portable-graymap'", "fileExtension='.pko',mimeType='application/vnd.ms-pki.pko'", "fileExtension='.pma',mimeType='application/x-perfmon'", "fileExtension='.pmc',mimeType='application/x-perfmon'", "fileExtension='.pml',mimeType='application/x-perfmon'", "fileExtension='.pmr',mimeType='application/x-perfmon'", "fileExtension='.pmw',mimeType='application/x-perfmon'", "fileExtension='.png',mimeType='image/png'", "fileExtension='.pnm',mimeType='image/x-portable-anymap'", "fileExtension='.pnz',mimeType='image/png'", "fileExtension='.pot',mimeType='application/vnd.ms-powerpoint'", "fileExtension='.potm',mimeType='application/vnd.ms-powerpoint.template.macroEnabled.12'", "fileExtension='.potx',mimeType='application/vnd.openxmlformats-officedocument.presentationml.template'", "fileExtension='.ppam',mimeType='application/vnd.ms-powerpoint.addin.macroEnabled.12'", "fileExtension='.ppm',mimeType='image/x-portable-pixmap'", "fileExtension='.pps',mimeType='application/vnd.ms-powerpoint'", "fileExtension='.ppsm',mimeType='application/vnd.ms-powerpoint.slideshow.macroEnabled.12'", "fileExtension='.ppsx',mimeType='application/vnd.openxmlformats-officedocument.presentationml.slideshow'", "fileExtension='.ppt',mimeType='application/vnd.ms-powerpoint'", "fileExtension='.pptm',mimeType='application/vnd.ms-powerpoint.presentation.macroEnabled.12'", "fileExtension='.pptx',mimeType='application/vnd.openxmlformats-officedocument.presentationml.presentation'", "fileExtension='.prf',mimeType='application/pics-rules'", "fileExtension='.prm',mimeType='application/octet-stream'", "fileExtension='.prx',mimeType='application/octet-stream'", "fileExtension='.ps',mimeType='application/postscript'", "fileExtension='.psd',mimeType='application/octet-stream'", "fileExtension='.psm',mimeType='application/octet-stream'", "fileExtension='.psp',mimeType='application/octet-stream'", "fileExtension='.pub',mimeType='application/x-mspublisher'", "fileExtension='.qt',mimeType='video/quicktime'", "fileExtension='.qtl',mimeType='application/x-quicktimeplayer'", "fileExtension='.qxd',mimeType='application/octet-stream'", "fileExtension='.ra',mimeType='audio/x-pn-realaudio'", "fileExtension='.ram',mimeType='audio/x-pn-realaudio'", "fileExtension='.rar',mimeType='application/octet-stream'", "fileExtension='.ras',mimeType='image/x-cmu-raster'", "fileExtension='.rf',mimeType='image/vnd.rn-realflash'", "fileExtension='.rgb',mimeType='image/x-rgb'", "fileExtension='.rm',mimeType='application/vnd.rn-realmedia'", "fileExtension='.rmi',mimeType='audio/mid'", "fileExtension='.roff',mimeType='application/x-troff'", "fileExtension='.rpm',mimeType='audio/x-pn-realaudio-plugin'", "fileExtension='.rtf',mimeType='application/rtf'", "fileExtension='.rtx',mimeType='text/richtext'", "fileExtension='.scd',mimeType='application/x-msschedule'", "fileExtension='.sct',mimeType='text/scriptlet'", "fileExtension='.sea',mimeType='application/octet-stream'", "fileExtension='.setpay',mimeType='application/set-payment-initiation'", "fileExtension='.setreg',mimeType='application/set-registration-initiation'", "fileExtension='.sgml',mimeType='text/sgml'", "fileExtension='.sh',mimeType='application/x-sh'", "fileExtension='.shar',mimeType='application/x-shar'", "fileExtension='.sit',mimeType='application/x-stuffit'", "fileExtension='.sldm',mimeType='application/vnd.ms-powerpoint.slide.macroEnabled.12'", "fileExtension='.sldx',mimeType='application/vnd.openxmlformats-officedocument.presentationml.slide'", "fileExtension='.smd',mimeType='audio/x-smd'", "fileExtension='.smi',mimeType='application/octet-stream'", "fileExtension='.smx',mimeType='audio/x-smd'", "fileExtension='.smz',mimeType='audio/x-smd'", "fileExtension='.snd',mimeType='audio/basic'", "fileExtension='.snp',mimeType='application/octet-stream'", "fileExtension='.spc',mimeType='application/x-pkcs7-certificates'", "fileExtension='.spl',mimeType='application/futuresplash'", "fileExtension='.spx',mimeType='audio/ogg'", "fileExtension='.src',mimeType='application/x-wais-source'", "fileExtension='.ssm',mimeType='application/streamingmedia'", "fileExtension='.sst',mimeType='application/vnd.ms-pki.certstore'", "fileExtension='.stl',mimeType='application/vnd.ms-pki.stl'", "fileExtension='.sv4cpio',mimeType='application/x-sv4cpio'", "fileExtension='.sv4crc',mimeType='application/x-sv4crc'", "fileExtension='.svg',mimeType='image/svg+xml'", "fileExtension='.svgz',mimeType='image/svg+xml'", "fileExtension='.swf',mimeType='application/x-shockwave-flash'", "fileExtension='.t',mimeType='application/x-troff'", "fileExtension='.tar',mimeType='application/x-tar'", "fileExtension='.tcl',mimeType='application/x-tcl'", "fileExtension='.tex',mimeType='application/x-tex'", "fileExtension='.texi',mimeType='application/x-texinfo'", "fileExtension='.texinfo',mimeType='application/x-texinfo'", "fileExtension='.tgz',mimeType='application/x-compressed'", "fileExtension='.thmx',mimeType='application/vnd.ms-officetheme'", "fileExtension='.thn',mimeType='application/octet-stream'", "fileExtension='.tif',mimeType='image/tiff'", "fileExtension='.tiff',mimeType='image/tiff'", "fileExtension='.toc',mimeType='application/octet-stream'", "fileExtension='.tr',mimeType='application/x-troff'", "fileExtension='.trm',mimeType='application/x-msterminal'", "fileExtension='.ts',mimeType='video/vnd.dlna.mpeg-tts'", "fileExtension='.tsv',mimeType='text/tab-separated-values'", "fileExtension='.ttf',mimeType='application/octet-stream'", "fileExtension='.tts',mimeType='video/vnd.dlna.mpeg-tts'", "fileExtension='.txt',mimeType='text/plain'", "fileExtension='.u32',mimeType='application/octet-stream'", "fileExtension='.uls',mimeType='text/iuls'", "fileExtension='.ustar',mimeType='application/x-ustar'", "fileExtension='.vbs',mimeType='text/vbscript'", "fileExtension='.vcf',mimeType='text/x-vcard'", "fileExtension='.vcs',mimeType='text/plain'", "fileExtension='.vdx',mimeType='application/vnd.ms-visio.viewer'", "fileExtension='.vml',mimeType='text/xml'", "fileExtension='.vsd',mimeType='application/vnd.visio'", "fileExtension='.vss',mimeType='application/vnd.visio'", "fileExtension='.vst',mimeType='application/vnd.visio'", "fileExtension='.vsto',mimeType='application/x-ms-vsto'", "fileExtension='.vsw',mimeType='application/vnd.visio'", "fileExtension='.vsx',mimeType='application/vnd.visio'", "fileExtension='.vtx',mimeType='application/vnd.visio'", "fileExtension='.wav',mimeType='audio/wav'", "fileExtension='.wax',mimeType='audio/x-ms-wax'", "fileExtension='.wbmp',mimeType='image/vnd.wap.wbmp'", "fileExtension='.wcm',mimeType='application/vnd.ms-works'", "fileExtension='.wdb',mimeType='application/vnd.ms-works'", "fileExtension='.webm',mimeType='video/webm'", "fileExtension='.wks',mimeType='application/vnd.ms-works'", "fileExtension='.wm',mimeType='video/x-ms-wm'", "fileExtension='.wma',mimeType='audio/x-ms-wma'", "fileExtension='.wmd',mimeType='application/x-ms-wmd'", "fileExtension='.wmf',mimeType='application/x-msmetafile'", "fileExtension='.wml',mimeType='text/vnd.wap.wml'", "fileExtension='.wmlc',mimeType='application/vnd.wap.wmlc'", "fileExtension='.wmls',mimeType='text/vnd.wap.wmlscript'", "fileExtension='.wmlsc',mimeType='application/vnd.wap.wmlscriptc'", "fileExtension='.wmp',mimeType='video/x-ms-wmp'", "fileExtension='.wmv',mimeType='video/x-ms-wmv'", "fileExtension='.wmx',mimeType='video/x-ms-wmx'", "fileExtension='.wmz',mimeType='application/x-ms-wmz'", "fileExtension='.woff',mimeType='font/x-woff'", "fileExtension='.wps',mimeType='application/vnd.ms-works'", "fileExtension='.wri',mimeType='application/x-mswrite'", "fileExtension='.wrl',mimeType='x-world/x-vrml'", "fileExtension='.wrz',mimeType='x-world/x-vrml'", "fileExtension='.wsdl',mimeType='text/xml'", "fileExtension='.wtv',mimeType='video/x-ms-wtv'", "fileExtension='.wvx',mimeType='video/x-ms-wvx'", "fileExtension='.x',mimeType='application/directx'", "fileExtension='.xaf',mimeType='x-world/x-vrml'", "fileExtension='.xaml',mimeType='application/xaml+xml'", "fileExtension='.xap',mimeType='application/x-silverlight-app'", "fileExtension='.xbap',mimeType='application/x-ms-xbap'", "fileExtension='.xbm',mimeType='image/x-xbitmap'", "fileExtension='.xdr',mimeType='text/plain'", "fileExtension='.xht',mimeType='application/xhtml+xml'", "fileExtension='.xhtml',mimeType='application/xhtml+xml'", "fileExtension='.xla',mimeType='application/vnd.ms-excel'", "fileExtension='.xlam',mimeType='application/vnd.ms-excel.addin.macroEnabled.12'", "fileExtension='.xlc',mimeType='application/vnd.ms-excel'", "fileExtension='.xlm',mimeType='application/vnd.ms-excel'", "fileExtension='.xls',mimeType='application/vnd.ms-excel'", "fileExtension='.xlsb',mimeType='application/vnd.ms-excel.sheet.binary.macroEnabled.12'", "fileExtension='.xlsm',mimeType='application/vnd.ms-excel.sheet.macroEnabled.12'", "fileExtension='.xlsx',mimeType='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'", "fileExtension='.xlt',mimeType='application/vnd.ms-excel'", "fileExtension='.xltm',mimeType='application/vnd.ms-excel.template.macroEnabled.12'", "fileExtension='.xltx',mimeType='application/vnd.openxmlformats-officedocument.spreadsheetml.template'", "fileExtension='.xlw',mimeType='application/vnd.ms-excel'", "fileExtension='.xml',mimeType='text/xml'", "fileExtension='.xof',mimeType='x-world/x-vrml'", "fileExtension='.xpm',mimeType='image/x-xpixmap'", "fileExtension='.xps',mimeType='application/vnd.ms-xpsdocument'", "fileExtension='.xsd',mimeType='text/xml'", "fileExtension='.xsf',mimeType='text/xml'", "fileExtension='.xsl',mimeType='text/xml'", "fileExtension='.xslt',mimeType='text/xml'", "fileExtension='.xsn',mimeType='application/octet-stream'", "fileExtension='.xtp',mimeType='application/octet-stream'", "fileExtension='.xwd',mimeType='image/x-xwindowdump'", "fileExtension='.z',mimeType='application/x-compress'", "fileExtension='.zip',mimeType='application/x-zip-compressed'"] +attribute :add_default_documents, kind_of: Array, default: [] +attribute :delete_default_documents, kind_of: Array, default: [] +attribute :add_mime_maps, kind_of: Array, default: [] +attribute :delete_mime_maps, kind_of: Array, default: [] diff --git a/cookbooks/iis/resources/site.rb b/cookbooks/iis/resources/site.rb index 0b95215..4353063 100644 --- a/cookbooks/iis/resources/site.rb +++ b/cookbooks/iis/resources/site.rb @@ -30,7 +30,7 @@ attribute :host_header, kind_of: String, default: nil attribute :bindings, kind_of: String, default: nil attribute :application_pool, kind_of: String, default: nil attribute :options, kind_of: String, default: '' -attribute :log_directory, kind_of: String, default: "#{node['iis']['pubroot']}\\logs\\LogFiles" +attribute :log_directory, kind_of: String, default: node['iis']['log_dir'] attribute :log_period, kind_of: Symbol, default: :Daily, equal_to: [:Daily, :Hourly, :MaxSize, :Monthly, :Weekly] attribute :log_truncsize, kind_of: Integer, default: 1_048_576 diff --git a/cookbooks/mariadb/CHANGELOG.md b/cookbooks/mariadb/CHANGELOG.md index 7ca51c6..d19b938 100644 --- a/cookbooks/mariadb/CHANGELOG.md +++ b/cookbooks/mariadb/CHANGELOG.md @@ -3,6 +3,18 @@ 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 diff --git a/cookbooks/mariadb/attributes/default.rb b/cookbooks/mariadb/attributes/default.rb index c33dcae..7523035 100644 --- a/cookbooks/mariadb/attributes/default.rb +++ b/cookbooks/mariadb/attributes/default.rb @@ -21,7 +21,11 @@ end default['mariadb']['forbid_remote_root'] = true default['mariadb']['server_root_password'] = '' default['mariadb']['allow_root_pass_change'] = false -default['mariadb']['mysqld']['service_name'] = 'mysql' +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' @@ -82,6 +86,9 @@ 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 # @@ -92,6 +99,7 @@ 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 diff --git a/cookbooks/mariadb/libraries/mariadb_helper.rb b/cookbooks/mariadb/libraries/mariadb_helper.rb index 6ce317a..8e8e706 100644 --- a/cookbooks/mariadb/libraries/mariadb_helper.rb +++ b/cookbooks/mariadb/libraries/mariadb_helper.rb @@ -53,7 +53,7 @@ module MariaDB 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 + if os_platform == 'fedora' && os_version.to_i >= 19 service_name = 'mysqld' end service_name diff --git a/cookbooks/mariadb/metadata.json b/cookbooks/mariadb/metadata.json index 6ea0725..049ad57 100644 --- a/cookbooks/mariadb/metadata.json +++ b/cookbooks/mariadb/metadata.json @@ -1,36 +1 @@ -{ - "name": "mariadb", - "version": "0.3.0", - "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 +{"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 index 35bf433..46adea3 100644 --- a/cookbooks/mariadb/providers/configuration.rb +++ b/cookbooks/mariadb/providers/configuration.rb @@ -20,7 +20,7 @@ action :add do owner 'root' group 'mysql' mode '0640' - cookbook new_resource.cookbook + cookbook 'mariadb' variables variables_hash end end diff --git a/cookbooks/mariadb/recipes/_redhat_server.rb b/cookbooks/mariadb/recipes/_redhat_server.rb index c279a2b..4c0805a 100644 --- a/cookbooks/mariadb/recipes/_redhat_server.rb +++ b/cookbooks/mariadb/recipes/_redhat_server.rb @@ -43,3 +43,6 @@ execute 'change first install root password' do 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 index fe2b8da..527a371 100644 --- a/cookbooks/mariadb/recipes/_redhat_server_native.rb +++ b/cookbooks/mariadb/recipes/_redhat_server_native.rb @@ -22,16 +22,16 @@ 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' -end - -package 'mariadb-server' do - action :install - notifies :enable, 'service[mysql]' notifies :start, 'service[mysql]', :immediately notifies :run, 'execute[change first install root password]', :immediately end diff --git a/cookbooks/mariadb/recipes/config.rb b/cookbooks/mariadb/recipes/config.rb index 7cab1b3..33ce0e1 100644 --- a/cookbooks/mariadb/recipes/config.rb +++ b/cookbooks/mariadb/recipes/config.rb @@ -48,7 +48,7 @@ if node['mariadb']['innodb']['bps_percentage_memory'] ( node['mariadb']['innodb']['buffer_pool_size'].to_f * (node['memory']['total'][0..-3].to_i / 1024) - ).round).to_s + 'M' + ).round).to_s + 'M' else innodb_options['innodb_buffer_pool_size'] = \ node['mariadb']['innodb']['buffer_pool_size'] @@ -73,6 +73,7 @@ mariadb_configuration 'innodb' do end replication_opts = {} + replication_opts['log_bin'] = node['mariadb']['replication']['log_bin'] replication_opts['log_bin_index'] = \ node['mariadb']['replication']['log_bin_index'] @@ -83,10 +84,8 @@ replication_opts['max_binlog_size'] = \ unless node['mariadb']['replication']['server_id'].empty? replication_opts['server-id'] = node['mariadb']['replication']['server_id'] end -if node['mariadb']['replication'].key?('options') - node['mariadb']['replication']['options'].each do |key, value| - replication_opts[key] = value - end +node['mariadb']['replication']['options'].each do |key, value| + replication_opts[key] = value end mariadb_configuration 'replication' do diff --git a/cookbooks/mariadb/recipes/galera.rb b/cookbooks/mariadb/recipes/galera.rb index 7b13f8a..df98265 100644 --- a/cookbooks/mariadb/recipes/galera.rb +++ b/cookbooks/mariadb/recipes/galera.rb @@ -37,7 +37,7 @@ if node['mariadb']['galera']['wsrep_sst_method'] == 'rsync' action :install end else - if node['mariadb']['galera']['wsrep_sst_method'] == 'xtrabackup' + if node['mariadb']['galera']['wsrep_sst_method'] =~ /^xtrabackup(-v2)?/ package 'percona-xtrabackup' do action :install end @@ -52,7 +52,12 @@ include_recipe "#{cookbook_name}::config" galera_cluster_nodes = [] if !node['mariadb'].attribute?('rspec') && Chef::Config[:solo] - Chef::Log.warn('This recipe uses search. Chef Solo does not support search.') + 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( @@ -116,17 +121,28 @@ if platform?('debian', 'ubuntu') 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 'mysql -r -B -N -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\"" + command grants_command action :run only_if do cmd = Mixlib::ShellOut.new("/usr/bin/mysql --user=\"" + \ @@ -139,3 +155,25 @@ if platform?('debian', 'ubuntu') 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/repository.rb b/cookbooks/mariadb/recipes/repository.rb index 4720cbf..e8081eb 100644 --- a/cookbooks/mariadb/recipes/repository.rb +++ b/cookbooks/mariadb/recipes/repository.rb @@ -12,7 +12,7 @@ if node['mariadb']['use_default_repository'] apt_repository "mariadb-#{node['mariadb']['install']['version']}" do uri 'http://' + node['mariadb']['apt_repository']['base_url'] + '/' + \ - node['mariadb']['install']['version'] + '/' + node['platform'] + node['mariadb']['install']['version'] + '/' + node['platform'] distribution node['lsb']['codename'] components ['main'] keyserver 'hkp://keyserver.ubuntu.com:80' @@ -21,7 +21,7 @@ if node['mariadb']['use_default_repository'] when 'yum' include_recipe 'yum::default' - if node['platform'] == 'redhat' + 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}" @@ -35,7 +35,7 @@ if node['mariadb']['use_default_repository'] end case node['platform'] - when 'redhat', 'centos' + when 'redhat', 'centos', 'scientific' include_recipe 'yum-epel::default' end end diff --git a/cookbooks/mariadb/recipes/server.rb b/cookbooks/mariadb/recipes/server.rb index d261ba5..aa5db89 100644 --- a/cookbooks/mariadb/recipes/server.rb +++ b/cookbooks/mariadb/recipes/server.rb @@ -82,7 +82,7 @@ execute 'mariadb-service-restart-needed' do command 'true' only_if do mariadb_service_restart_required?( - '127.0.0.1', + node['mariadb']['mysqld']['bind_address'], node['mariadb']['mysqld']['port'], node['mariadb']['mysqld']['socket'] ) diff --git a/cookbooks/mediawiki/.gitignore b/cookbooks/mediawiki/.gitignore deleted file mode 100644 index cbccf1e..0000000 --- a/cookbooks/mediawiki/.gitignore +++ /dev/null @@ -1,20 +0,0 @@ -*~ -*# -.#* -\#*# -.*.sw[a-z] -*.un~ -pkg/ - -# Berkshelf -.vagrant -/cookbooks -Berksfile.lock - -# Bundler -Gemfile.lock -bin/* -.bundle/* - -.kitchen/ -.kitchen.local.yml diff --git a/cookbooks/mysql/CHANGELOG.md b/cookbooks/mysql/CHANGELOG.md index a716e4a..5bfcd9f 100644 --- a/cookbooks/mysql/CHANGELOG.md +++ b/cookbooks/mysql/CHANGELOG.md @@ -1,6 +1,57 @@ mysql Cookbook CHANGELOG ======================== +v6.1.2 (2015-10-05) +-------------------- +- 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 diff --git a/cookbooks/mysql/README.md b/cookbooks/mysql/README.md index e8dd43f..07be6b2 100644 --- a/cookbooks/mysql/README.md +++ b/cookbooks/mysql/README.md @@ -37,6 +37,8 @@ The following platforms have been tested with Test Kitchen: |----------------+-----+-----+-----+-----+-----| | ubuntu-14.04 | | | X | X | | |----------------+-----+-----+-----+-----+-----| +| ubuntu-15.04 | | | | X | | +|----------------+-----+-----+-----+-----+-----| | centos-5 | X | X | X | X | X | |----------------+-----+-----+-----+-----+-----| | centos-6 | | X | X | X | X | @@ -85,7 +87,7 @@ 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-default +# Chef generated my.cnf for instance mysql-foo [client] default-character-set = utf8 @@ -195,6 +197,8 @@ to reference is `mysql_service[name]`, not `service[mysql]`. 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 @@ -219,6 +223,14 @@ omitted, it will default to the platform's native location. 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'. @@ -228,11 +240,15 @@ omitted, it will default to the platform's native location. - `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 @@ -255,28 +271,28 @@ but you can specify one if your platform support it. mysql_service[instance-1] do port '1234' data_dir '/mnt/lottadisk' - provider Chef::Provider::MysqlService::Sysvinit + provider Chef::Provider::MysqlServiceSysvinit action [:create, :start] end ``` -- `Chef::Provider::MysqlService` - Configures everything needed t run +- `Chef::Provider::MysqlServiceBase` - Configures everything needed t 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::MysqlService::Smf` - Starts a `mysql_service` using +- `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::MysqlService::Systemd` - Starts a `mysql_service` +- `Chef::Provider::MysqlServiceSystemd` - Starts a `mysql_service` using SystemD. Manages the unit file and activation state -- `Chef::Provider::MysqlService::Sysvinit` - Starts a `mysql_service` +- `Chef::Provider::MysqlServiceSysvinit` - Starts a `mysql_service` using SysVinit. Manages the init script and status. -- `Chef::Provider::MysqlService::Upstart` - Starts a `mysql_service` +- `Chef::Provider::MysqlServiceUpstart` - Starts a `mysql_service` using Upstart. Manages job definitions and status. ### mysql_config @@ -503,7 +519,7 @@ 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-default/mysqld.sock -Pwhatever` +`mysql -S /var/run/mysql-foo/mysqld.sock -Pwhatever` Or to connect over the network, use something like this: connect over the network.. diff --git a/cookbooks/mysql/libraries/helpers.rb b/cookbooks/mysql/libraries/helpers.rb index 0e53eeb..e4bdd8b 100644 --- a/cookbooks/mysql/libraries/helpers.rb +++ b/cookbooks/mysql/libraries/helpers.rb @@ -34,6 +34,7 @@ module MysqlCookbook end def error_log + return new_resource.error_log if new_resource.error_log "#{log_dir}/error.log" end @@ -60,7 +61,7 @@ module MysqlCookbook end def pkg_ver_string - parsed_version.gsub('.', '') if node['platform_family'] == 'omnios' + parsed_version.delete('.') if node['platform_family'] == 'omnios' end def prefix_dir @@ -105,6 +106,24 @@ module MysqlCookbook true end + def password_column_name + return 'authentication_string' if v57plus + 'password' + end + + def password_expired + return ", password_expired='N'" if v57plus + '' + end + + def root_password + if new_resource.initial_root_password == '' + Chef::Log.info('Root password is empty') + return '' + end + Shellwords.escape(new_resource.initial_root_password) + end + # database and initial records # initialization commands @@ -148,10 +167,11 @@ module MysqlCookbook mkdir /tmp/#{mysql_name} cat > /tmp/#{mysql_name}/my.sql <<-EOSQL -DELETE FROM mysql.user ; -CREATE USER 'root'@'%' IDENTIFIED BY '#{Shellwords.escape(new_resource.initial_root_password)}' ; -GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION ; +UPDATE mysql.user SET #{password_column_name}=PASSWORD('#{root_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 @@ -204,6 +224,7 @@ EOSQL end def pid_file + return new_resource.pid_file if new_resource.pid_file "#{run_dir}/mysqld.pid" end @@ -228,6 +249,7 @@ EOSQL end def tmp_dir + return new_resource.tmp_dir if new_resource.tmp_dir '/tmp' end @@ -256,6 +278,8 @@ EOSQL @pkginfo.set['debian']['14.10']['5.5']['server_package'] = 'mysql-server-5.5' @pkginfo.set['debian']['14.10']['5.6']['client_package'] = %w(mysql-client-5.6 libmysqlclient-dev) @pkginfo.set['debian']['14.10']['5.6']['server_package'] = 'mysql-server-5.6' + @pkginfo.set['debian']['15.04']['5.6']['client_package'] = %w(mysql-client-5.6 libmysqlclient-dev) + @pkginfo.set['debian']['15.04']['5.6']['server_package'] = 'mysql-server-5.6' @pkginfo.set['debian']['6']['5.1']['client_package'] = %w(mysql-client libmysqlclient-dev) @pkginfo.set['debian']['6']['5.1']['server_package'] = 'mysql-server-5.1' @pkginfo.set['debian']['7']['5.5']['client_package'] = %w(mysql-client libmysqlclient-dev) @@ -272,6 +296,14 @@ EOSQL @pkginfo.set['fedora']['20']['5.6']['server_package'] = 'mysql-community-server' @pkginfo.set['fedora']['20']['5.7']['client_package'] = %w(mysql-community-client mysql-community-devel) @pkginfo.set['fedora']['20']['5.7']['server_package'] = 'mysql-community-server' + @pkginfo.set['fedora']['21']['5.6']['client_package'] = %w(mysql-community-client mysql-community-devel) + @pkginfo.set['fedora']['21']['5.6']['server_package'] = 'mysql-community-server' + @pkginfo.set['fedora']['21']['5.7']['client_package'] = %w(mysql-community-client mysql-community-devel) + @pkginfo.set['fedora']['21']['5.7']['server_package'] = 'mysql-community-server' + @pkginfo.set['fedora']['22']['5.6']['client_package'] = %w(mysql-community-client mysql-community-devel) + @pkginfo.set['fedora']['22']['5.6']['server_package'] = 'mysql-community-server' + @pkginfo.set['fedora']['22']['5.7']['client_package'] = %w(mysql-community-client mysql-community-devel) + @pkginfo.set['fedora']['22']['5.7']['server_package'] = 'mysql-community-server' @pkginfo.set['freebsd']['10']['5.5']['client_package'] = %w(mysql55-client) @pkginfo.set['freebsd']['10']['5.5']['server_package'] = 'mysql55-server' @pkginfo.set['freebsd']['9']['5.5']['client_package'] = %w(mysql55-client) @@ -296,6 +328,14 @@ EOSQL @pkginfo.set['rhel']['2015.03']['5.6']['server_package'] = 'mysql-community-server' @pkginfo.set['rhel']['2015.03']['5.7']['client_package'] = %w(mysql-community-client mysql-community-devel) @pkginfo.set['rhel']['2015.03']['5.7']['server_package'] = 'mysql-community-server' + @pkginfo.set['rhel']['2015.09']['5.1']['server_package'] = %w(mysql51 mysql51-devel) + @pkginfo.set['rhel']['2015.09']['5.1']['server_package'] = 'mysql51-server' + @pkginfo.set['rhel']['2015.09']['5.5']['client_package'] = %w(mysql-community-client mysql-community-devel) + @pkginfo.set['rhel']['2015.09']['5.5']['server_package'] = 'mysql-community-server' + @pkginfo.set['rhel']['2015.09']['5.6']['client_package'] = %w(mysql-community-client mysql-community-devel) + @pkginfo.set['rhel']['2015.09']['5.6']['server_package'] = 'mysql-community-server' + @pkginfo.set['rhel']['2015.09']['5.7']['client_package'] = %w(mysql-community-client mysql-community-devel) + @pkginfo.set['rhel']['2015.09']['5.7']['server_package'] = 'mysql-community-server' @pkginfo.set['rhel']['5']['5.0']['client_package'] = %w(mysql mysql-devel) @pkginfo.set['rhel']['5']['5.0']['server_package'] = 'mysql-server' @pkginfo.set['rhel']['5']['5.1']['client_package'] = %w(mysql51-mysql) @@ -326,6 +366,8 @@ EOSQL @pkginfo.set['smartos']['5.11']['5.6']['server_package'] = 'mysql-server' @pkginfo.set['suse']['11.3']['5.5']['client_package'] = %w(mysql-client) @pkginfo.set['suse']['11.3']['5.5']['server_package'] = 'mysql' + @pkginfo.set['suse']['12.0']['5.5']['client_package'] = %w(mysql-client) + @pkginfo.set['suse']['12.0']['5.5']['server_package'] = 'mysql' @pkginfo end @@ -372,7 +414,7 @@ EOSQL node['platform_version'], parsed_version, :client_package - ) + ) end def server_package @@ -382,7 +424,7 @@ EOSQL node['platform_version'], parsed_version, :server_package - ) + ) end def server_package_name @@ -403,7 +445,6 @@ EOSQL return '5.5' if node['platform_family'] == 'debian' && node['platform_version'] == '14.10' return '5.5' if node['platform_family'] == 'debian' && node['platform_version'].to_i == 7 return '5.5' if node['platform_family'] == 'debian' && node['platform_version'].to_i == 8 - return '5.5' if node['platform_family'] == 'fedora' return '5.5' if node['platform_family'] == 'freebsd' return '5.5' if node['platform_family'] == 'omnios' return '5.5' if node['platform_family'] == 'rhel' && node['platform_version'].to_i == 2014 @@ -411,6 +452,8 @@ EOSQL return '5.5' if node['platform_family'] == 'rhel' && node['platform_version'].to_i == 7 return '5.5' if node['platform_family'] == 'smartos' return '5.5' if node['platform_family'] == 'suse' + return '5.6' if node['platform_family'] == 'fedora' + return '5.6' if node['platform_family'] == 'debian' && node['platform_version'] == '15.04' end end end diff --git a/cookbooks/mysql/libraries/matchers.rb b/cookbooks/mysql/libraries/matchers.rb index f806d00..373e3cb 100644 --- a/cookbooks/mysql/libraries/matchers.rb +++ b/cookbooks/mysql/libraries/matchers.rb @@ -1,4 +1,17 @@ if defined?(ChefSpec) + if ChefSpec.respond_to?(:define_matcher) + # ChefSpec >= 4.1 + ChefSpec.define_matcher :mysql_config + ChefSpec.define_matcher :mysql_service + ChefSpec.define_matcher :mysql_client + elsif defined?(ChefSpec::Runner) && + ChefSpec::Runner.respond_to?(:define_runner_method) + # ChefSpec < 4.1 + ChefSpec::Runner.define_runner_method :mysql_config + ChefSpec::Runner.define_runner_method :mysql_service + ChefSpec::Runner.define_runner_method :mysql_client + end + # config def create_mysql_config(resource_name) ChefSpec::Matchers::ResourceMatcher.new(:mysql_config, :create, resource_name) @@ -17,6 +30,22 @@ if defined?(ChefSpec) 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 + # client def create_mysql_client(resource_name) ChefSpec::Matchers::ResourceMatcher.new(:mysql_client, :create, resource_name) diff --git a/cookbooks/mysql/libraries/provider_mysql_client.rb b/cookbooks/mysql/libraries/provider_mysql_client.rb index 0aca4e2..c796d11 100644 --- a/cookbooks/mysql/libraries/provider_mysql_client.rb +++ b/cookbooks/mysql/libraries/provider_mysql_client.rb @@ -5,6 +5,7 @@ class Chef class Provider class MysqlClient < Chef::Provider::LWRPBase include MysqlCookbook::Helpers + provides :mysql_client if defined?(provides) use_inline_resources if defined?(use_inline_resources) diff --git a/cookbooks/mysql/libraries/provider_mysql_config.rb b/cookbooks/mysql/libraries/provider_mysql_config.rb index dc277ab..3732c1c 100644 --- a/cookbooks/mysql/libraries/provider_mysql_config.rb +++ b/cookbooks/mysql/libraries/provider_mysql_config.rb @@ -5,6 +5,7 @@ class Chef class Provider class MysqlConfig < Chef::Provider::LWRPBase include MysqlCookbook::Helpers + provides :mysql_config if defined?(provides) use_inline_resources if defined?(use_inline_resources) diff --git a/cookbooks/mysql/libraries/provider_mysql_service.rb b/cookbooks/mysql/libraries/provider_mysql_service_base.rb similarity index 98% rename from cookbooks/mysql/libraries/provider_mysql_service.rb rename to cookbooks/mysql/libraries/provider_mysql_service_base.rb index 3784fab..5f19a45 100644 --- a/cookbooks/mysql/libraries/provider_mysql_service.rb +++ b/cookbooks/mysql/libraries/provider_mysql_service_base.rb @@ -3,8 +3,7 @@ require_relative 'helpers' class Chef class Provider - class MysqlService < Chef::Provider::LWRPBase - # Chef 11 LWRP DSL Methods + class MysqlServiceBase < Chef::Provider::LWRPBase use_inline_resources if defined?(use_inline_resources) def whyrun_supported? @@ -138,7 +137,7 @@ class Chef socket_file: socket_file, tmp_dir: tmp_dir, data_dir: parsed_data_dir - ) + ) action :create end @@ -234,7 +233,7 @@ class Chef run_dir: run_dir, pid_file: pid_file, socket_file: socket_file - ) + ) action :create notifies :restart, "service[#{new_resource.name} :create apparmor]", :immediately end diff --git a/cookbooks/mysql/libraries/provider_mysql_service_smf.rb b/cookbooks/mysql/libraries/provider_mysql_service_smf.rb index 3b247ca..7fe35b6 100644 --- a/cookbooks/mysql/libraries/provider_mysql_service_smf.rb +++ b/cookbooks/mysql/libraries/provider_mysql_service_smf.rb @@ -1,83 +1,89 @@ class Chef class Provider - class MysqlService - class Smf < Chef::Provider::MysqlService - action :start do - method_script_path = "/lib/svc/method/#{mysql_name}" if node['platform'] == 'omnios' - method_script_path = "/opt/local/lib/svc/method/#{mysql_name}" if node['platform'] == 'smartos' + class MysqlServiceSmf < Chef::Provider::MysqlServiceBase + # FIXME: we should have a service_helper to determine if the platform supports SMF similarly + # to how we handle systemd on linux + if defined?(provides) + provides :mysql_service, os: %w(solaris2 omnios smartos openindiana opensolaris nexentacore) do + File.exist?('/usr/sbin/svccfg') + end + end - template "#{new_resource.name} :start #{method_script_path}" do - path method_script_path - cookbook 'mysql' - source 'smf/svc.method.mysqld.erb' - owner 'root' - group 'root' - mode '0555' - variables( - base_dir: base_dir, - data_dir: parsed_data_dir, - defaults_file: defaults_file, - error_log: error_log, - mysql_name: mysql_name, - mysqld_bin: mysqld_bin, - pid_file: pid_file - ) - action :create - end + action :start do + method_script_path = "/lib/svc/method/#{mysql_name}" if node['platform'] == 'omnios' + method_script_path = "/opt/local/lib/svc/method/#{mysql_name}" if node['platform'] == 'smartos' - smf "#{new_resource.name} :start #{mysql_name}" do - name mysql_name - user new_resource.run_user - group new_resource.run_group - start_command "#{method_script_path} start" - end - - service "#{new_resource.name} :start #{mysql_name}" do - service_name mysql_name - provider Chef::Provider::Service::Solaris - supports restart: true - action [:enable] - end + template "#{new_resource.name} :start #{method_script_path}" do + path method_script_path + cookbook 'mysql' + source 'smf/svc.method.mysqld.erb' + owner 'root' + group 'root' + mode '0555' + variables( + base_dir: base_dir, + data_dir: parsed_data_dir, + defaults_file: defaults_file, + error_log: error_log, + mysql_name: mysql_name, + mysqld_bin: mysqld_bin, + pid_file: pid_file + ) + action :create end - action :stop do - service "#{new_resource.name} :stop #{mysql_name}" do - service_name mysql_name - provider Chef::Provider::Service::Solaris - supports restart: true - action :stop - end + smf "#{new_resource.name} :start #{mysql_name}" do + name mysql_name + user new_resource.run_user + group new_resource.run_group + start_command "#{method_script_path} start" end - action :restart do - service "#{new_resource.name} :restart #{mysql_name}" do - service_name mysql_name - provider Chef::Provider::Service::Solaris - supports restart: true - action :restart - end + service "#{new_resource.name} :start #{mysql_name}" do + service_name mysql_name + provider Chef::Provider::Service::Solaris + supports restart: true + action [:enable] end + end - action :reload do - service "#{new_resource.name} :reload #{mysql_name}" do - provider Chef::Provider::Service::Solaris - service_name mysql_name - supports reload: true - action :reload - end + action :stop do + service "#{new_resource.name} :stop #{mysql_name}" do + service_name mysql_name + provider Chef::Provider::Service::Solaris + supports restart: true + action :stop end + end - def create_stop_system_service - # nothing to do here + action :restart do + service "#{new_resource.name} :restart #{mysql_name}" do + service_name mysql_name + provider Chef::Provider::Service::Solaris + supports restart: true + action :restart end + end - def delete_stop_service - service "#{new_resource.name} :delete #{mysql_name}" do - service_name mysql_name - provider Chef::Provider::Service::Solaris - supports restart: true - action :stop - end + action :reload do + service "#{new_resource.name} :reload #{mysql_name}" do + provider Chef::Provider::Service::Solaris + service_name mysql_name + supports reload: true + action :reload + end + end + + def create_stop_system_service + # nothing to do here + end + + def delete_stop_service + service "#{new_resource.name} :delete #{mysql_name}" do + service_name mysql_name + provider Chef::Provider::Service::Solaris + supports restart: true + action :stop end end end diff --git a/cookbooks/mysql/libraries/provider_mysql_service_systemd.rb b/cookbooks/mysql/libraries/provider_mysql_service_systemd.rb index 2fccfb4..07ee6e1 100644 --- a/cookbooks/mysql/libraries/provider_mysql_service_systemd.rb +++ b/cookbooks/mysql/libraries/provider_mysql_service_systemd.rb @@ -1,119 +1,133 @@ +require_relative 'provider_mysql_service_base' + class Chef class Provider - class MysqlService - class Systemd < Chef::Provider::MysqlService - action :start do - # this script is called by the main systemd unit file, and - # spins around until the service is actually up and running. - template "#{new_resource.name} :start /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 + class MysqlServiceSystemd < Chef::Provider::MysqlServiceBase + if defined?(provides) + provides :mysql_service, os: 'linux' do + Chef::Platform::ServiceHelpers.service_resource_providers.include?(:systemd) + end + end - # this is the main systemd unit file - template "#{new_resource.name} :start /usr/lib/systemd/system/#{mysql_name}.service" do - path "/usr/lib/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.name} :start systemctl daemon-reload]", :immediately - action :create - end - - # avoid 'Unit file changed on disk' warning - execute "#{new_resource.name} :start systemctl daemon-reload" do - command '/usr/bin/systemctl daemon-reload' - action :nothing - end - - # tmpfiles.d config so the service survives reboot - template "#{new_resource.name} :start /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 "#{new_resource.name} :start #{mysql_name}" do - service_name mysql_name - provider Chef::Provider::Service::Systemd - supports restart: true, status: true - action [:enable, :start] - end + action :start do + # Needed for Debian / Ubuntu + directory '/usr/libexec' do + owner 'root' + group 'root' + mode '0755' + action :create end - action :stop do - # service management resource - service "#{new_resource.name} :stop #{mysql_name}" 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 + # this script is called by the main systemd unit file, and + # spins around until the service is actually up and running. + template "#{new_resource.name} :start /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 - action :restart do - # service management resource - service "#{new_resource.name} :restart #{mysql_name}" do - service_name mysql_name - provider Chef::Provider::Service::Systemd - supports restart: true - action :restart - end + # this is the main systemd unit file + template "#{new_resource.name} :start /lib/systemd/system/#{mysql_name}.service" do + path "/lib/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.name} :start systemctl daemon-reload]", :immediately + action :create end - action :reload do - # service management resource - service "#{new_resource.name} :reload #{mysql_name}" do - service_name mysql_name - provider Chef::Provider::Service::Systemd - action :reload - end + # avoid 'Unit file changed on disk' warning + execute "#{new_resource.name} :start systemctl daemon-reload" do + command '/bin/systemctl daemon-reload' + action :nothing end - def create_stop_system_service - # service management resource - service "#{new_resource.name} :create mysql" do - service_name 'mysqld' - provider Chef::Provider::Service::Systemd - supports status: true - action [:stop, :disable] - end + # tmpfiles.d config so the service survives reboot + template "#{new_resource.name} :start /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 - def delete_stop_service - # service management resource - service "#{new_resource.name} :delete #{mysql_name}" 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 + # service management resource + service "#{new_resource.name} :start #{mysql_name}" 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 "#{new_resource.name} :stop #{mysql_name}" 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 "#{new_resource.name} :restart #{mysql_name}" do + service_name mysql_name + provider Chef::Provider::Service::Systemd + supports restart: true + action :restart + end + end + + action :reload do + # service management resource + service "#{new_resource.name} :reload #{mysql_name}" do + service_name mysql_name + provider Chef::Provider::Service::Systemd + action :reload + end + end + + def create_stop_system_service + # service management resource + service "#{new_resource.name} :create 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 "#{new_resource.name} :delete #{mysql_name}" 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 diff --git a/cookbooks/mysql/libraries/provider_mysql_service_sysvinit.rb b/cookbooks/mysql/libraries/provider_mysql_service_sysvinit.rb index 5b197ac..b3f2259 100644 --- a/cookbooks/mysql/libraries/provider_mysql_service_sysvinit.rb +++ b/cookbooks/mysql/libraries/provider_mysql_service_sysvinit.rb @@ -1,85 +1,87 @@ +require_relative 'provider_mysql_service_base' + class Chef class Provider - class MysqlService - class Sysvinit < Chef::Provider::MysqlService - action :start do - template "#{new_resource.name} :start /etc/init.d/#{mysql_name}" do - path "/etc/init.d/#{mysql_name}" - source 'sysvinit/mysqld.erb' - owner 'root' - group 'root' - mode '0755' - variables( - config: new_resource, - defaults_file: defaults_file, - error_log: error_log, - mysql_name: mysql_name, - mysqladmin_bin: mysqladmin_bin, - mysqld_safe_bin: mysqld_safe_bin, - pid_file: pid_file, - scl_name: scl_name - ) - cookbook 'mysql' - action :create - end + class MysqlServiceSysvinit < Chef::Provider::MysqlServiceBase + provides :mysql_service, os: '!windows' if defined?(provides) - service "#{new_resource.name} :start #{mysql_name}" do - service_name mysql_name - provider Chef::Provider::Service::Init::Redhat if node['platform_family'] == 'redhat' - provider Chef::Provider::Service::Init::Insserv if node['platform_family'] == 'debian' - supports restart: true, status: true - action [:enable, :start] - end + action :start do + template "#{new_resource.name} :start /etc/init.d/#{mysql_name}" do + path "/etc/init.d/#{mysql_name}" + source 'sysvinit/mysqld.erb' + owner 'root' + group 'root' + mode '0755' + variables( + config: new_resource, + defaults_file: defaults_file, + error_log: error_log, + mysql_name: mysql_name, + mysqladmin_bin: mysqladmin_bin, + mysqld_safe_bin: mysqld_safe_bin, + pid_file: pid_file, + scl_name: scl_name + ) + cookbook 'mysql' + action :create end - action :stop do - service "#{new_resource.name} :stop #{mysql_name}" do - service_name mysql_name - provider Chef::Provider::Service::Init::Redhat if node['platform_family'] == 'redhat' - provider Chef::Provider::Service::Init::Insserv if node['platform_family'] == 'debian' - supports restart: true, status: true - action [:stop] - end + service "#{new_resource.name} :start #{mysql_name}" do + service_name mysql_name + provider Chef::Provider::Service::Init::Redhat if node['platform_family'] == 'redhat' + provider Chef::Provider::Service::Init::Insserv if node['platform_family'] == 'debian' + supports restart: true, status: true + action [:enable, :start] end + end - action :restart do - service "#{new_resource.name} :restart #{mysql_name}" do - service_name mysql_name - provider Chef::Provider::Service::Init::Redhat if node['platform_family'] == 'redhat' - provider Chef::Provider::Service::Init::Insserv if node['platform_family'] == 'debian' - supports restart: true - action :restart - end + action :stop do + service "#{new_resource.name} :stop #{mysql_name}" do + service_name mysql_name + provider Chef::Provider::Service::Init::Redhat if node['platform_family'] == 'redhat' + provider Chef::Provider::Service::Init::Insserv if node['platform_family'] == 'debian' + supports restart: true, status: true + action [:stop] end + end - action :reload do - service "#{new_resource.name} :reload #{mysql_name}" do - service_name mysql_name - provider Chef::Provider::Service::Init::Redhat if node['platform_family'] == 'redhat' - provider Chef::Provider::Service::Init::Insserv if node['platform_family'] == 'debian' - action :reload - end + action :restart do + service "#{new_resource.name} :restart #{mysql_name}" do + service_name mysql_name + provider Chef::Provider::Service::Init::Redhat if node['platform_family'] == 'redhat' + provider Chef::Provider::Service::Init::Insserv if node['platform_family'] == 'debian' + supports restart: true + action :restart end + end - def create_stop_system_service - service "#{new_resource.name} :create #{system_service_name}" do - service_name system_service_name - provider Chef::Provider::Service::Init::Redhat if node['platform_family'] == 'redhat' - provider Chef::Provider::Service::Init::Insserv if node['platform_family'] == 'debian' - supports status: true - action [:stop, :disable] - end + action :reload do + service "#{new_resource.name} :reload #{mysql_name}" do + service_name mysql_name + provider Chef::Provider::Service::Init::Redhat if node['platform_family'] == 'redhat' + provider Chef::Provider::Service::Init::Insserv if node['platform_family'] == 'debian' + action :reload end + end - def delete_stop_service - service "#{new_resource.name} :delete #{mysql_name}" do - service_name mysql_name - provider Chef::Provider::Service::Init::Redhat if node['platform_family'] == 'redhat' - provider Chef::Provider::Service::Init::Insserv if node['platform_family'] == 'debian' - supports status: true - action [:disable, :stop] - only_if { ::File.exist?("#{etc_dir}/init.d/#{mysql_name}") } - end + def create_stop_system_service + service "#{new_resource.name} :create #{system_service_name}" do + service_name system_service_name + provider Chef::Provider::Service::Init::Redhat if node['platform_family'] == 'redhat' + provider Chef::Provider::Service::Init::Insserv if node['platform_family'] == 'debian' + supports status: true + action [:stop, :disable] + end + end + + def delete_stop_service + service "#{new_resource.name} :delete #{mysql_name}" do + service_name mysql_name + provider Chef::Provider::Service::Init::Redhat if node['platform_family'] == 'redhat' + provider Chef::Provider::Service::Init::Insserv if node['platform_family'] == 'debian' + supports status: true + action [:disable, :stop] + only_if { ::File.exist?("#{etc_dir}/init.d/#{mysql_name}") } end end end diff --git a/cookbooks/mysql/libraries/provider_mysql_service_upstart.rb b/cookbooks/mysql/libraries/provider_mysql_service_upstart.rb index 2a45166..8e532c0 100644 --- a/cookbooks/mysql/libraries/provider_mysql_service_upstart.rb +++ b/cookbooks/mysql/libraries/provider_mysql_service_upstart.rb @@ -1,105 +1,112 @@ +require_relative 'provider_mysql_service_base' + class Chef class Provider - class MysqlService - class Upstart < Chef::Provider::MysqlService - action :start do - template "#{new_resource.name} :start /usr/sbin/#{mysql_name}-wait-ready" do - path "/usr/sbin/#{mysql_name}-wait-ready" - source 'upstart/mysqld-wait-ready.erb' - owner 'root' - group 'root' - mode '0755' - variables(socket_file: socket_file) - cookbook 'mysql' - action :create - end + class MysqlServiceUpstart < Chef::Provider::MysqlServiceBase + if defined?(provides) + provides :mysql_service, os: 'linux' do + Chef::Platform::ServiceHelpers.service_resource_providers.include?(:upstart) && + !Chef::Platform::ServiceHelpers.service_resource_providers.include?(:redhat) + end + end - template "#{new_resource.name} :start /etc/init/#{mysql_name}.conf" do - path "/etc/init/#{mysql_name}.conf" - 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: socket_dir - ) - cookbook 'mysql' - action :create - end - - service "#{new_resource.name} :start #{mysql_name}" do - service_name mysql_name - provider Chef::Provider::Service::Upstart - supports status: true - action [:start] - end + action :start do + template "#{new_resource.name} :start /usr/sbin/#{mysql_name}-wait-ready" do + path "/usr/sbin/#{mysql_name}-wait-ready" + source 'upstart/mysqld-wait-ready.erb' + owner 'root' + group 'root' + mode '0755' + variables(socket_file: socket_file) + cookbook 'mysql' + action :create end - action :stop do - service "#{new_resource.name} :stop #{mysql_name}" do - service_name mysql_name - provider Chef::Provider::Service::Upstart - supports restart: true, status: true - action [:stop] - end + template "#{new_resource.name} :start /etc/init/#{mysql_name}.conf" do + path "/etc/init/#{mysql_name}.conf" + 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: socket_dir + ) + cookbook 'mysql' + action :create 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 "#{new_resource.name} :restart stop #{mysql_name}" do - service_name mysql_name - provider Chef::Provider::Service::Upstart - action :stop - end + service "#{new_resource.name} :start #{mysql_name}" do + service_name mysql_name + provider Chef::Provider::Service::Upstart + supports status: true + action [:start] + end + end - service "#{new_resource.name} :restart start #{mysql_name}" do - service_name mysql_name - provider Chef::Provider::Service::Upstart - action :start - end + action :stop do + service "#{new_resource.name} :stop #{mysql_name}" do + service_name mysql_name + 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 "#{new_resource.name} :restart stop #{mysql_name}" do + service_name mysql_name + provider Chef::Provider::Service::Upstart + action :stop 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 "#{new_resource.name} :reload stop #{mysql_name}" do - service_name mysql_name - provider Chef::Provider::Service::Upstart - action :stop - end + service "#{new_resource.name} :restart start #{mysql_name}" do + service_name mysql_name + provider Chef::Provider::Service::Upstart + action :start + end + end - service "#{new_resource.name} :reload start #{mysql_name}" do - service_name mysql_name - provider Chef::Provider::Service::Upstart - action :start - 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 "#{new_resource.name} :reload stop #{mysql_name}" do + service_name mysql_name + provider Chef::Provider::Service::Upstart + action :stop end - def create_stop_system_service - service "#{new_resource.name} :create #{system_service_name}" do - service_name system_service_name - provider Chef::Provider::Service::Upstart - supports status: true - action [:stop, :disable] - end + service "#{new_resource.name} :reload start #{mysql_name}" do + service_name mysql_name + provider Chef::Provider::Service::Upstart + action :start end + end - def delete_stop_service - service "#{new_resource.name} :delete #{mysql_name}" do - service_name mysql_name - provider Chef::Provider::Service::Upstart - action [:disable, :stop] - only_if { ::File.exist?("#{etc_dir}/init/#{mysql_name}") } - end + def create_stop_system_service + service "#{new_resource.name} :create #{system_service_name}" do + service_name system_service_name + provider Chef::Provider::Service::Upstart + supports status: true + action [:stop, :disable] + end + end + + def delete_stop_service + service "#{new_resource.name} :delete #{mysql_name}" do + service_name mysql_name + provider Chef::Provider::Service::Upstart + action [:disable, :stop] + only_if { ::File.exist?("#{etc_dir}/init/#{mysql_name}") } end end end diff --git a/cookbooks/mysql/libraries/provider_priority_linux.rb b/cookbooks/mysql/libraries/provider_priority_linux.rb new file mode 100644 index 0000000..e284025 --- /dev/null +++ b/cookbooks/mysql/libraries/provider_priority_linux.rb @@ -0,0 +1,45 @@ + +begin + require 'chef/platform/provider_priority_map' +rescue LoadError +end + +require_relative 'provider_mysql_service_smf' +require_relative 'provider_mysql_service_systemd' +require_relative 'provider_mysql_service_sysvinit' +require_relative 'provider_mysql_service_upstart' +require_relative 'provider_mysql_config' +require_relative 'provider_mysql_client' + +if defined? Chef::Platform::ProviderPriorityMap + Chef::Platform::ProviderPriorityMap.instance.priority( + :mysql_service, + [Chef::Provider::MysqlServiceSystemd, Chef::Provider::MysqlServiceUpstart, Chef::Provider::MysqlServiceSysvinit], + os: 'linux' + ) +else + # provider mappings for Chef 11 + + # systemd service + Chef::Platform.set platform: :fedora, version: '>= 19', resource: :mysql_service, provider: Chef::Provider::MysqlServiceSystemd + Chef::Platform.set platform: :redhat, version: '>= 7.0', resource: :mysql_service, provider: Chef::Provider::MysqlServiceSystemd + Chef::Platform.set platform: :centos, version: '>= 7.0', resource: :mysql_service, provider: Chef::Provider::MysqlServiceSystemd + Chef::Platform.set platform: :scientific, version: '>= 7.0', resource: :mysql_service, provider: Chef::Provider::MysqlServiceSystemd + Chef::Platform.set platform: :oracle, version: '>= 7.0', resource: :mysql_service, provider: Chef::Provider::MysqlServiceSystemd + + # smf service + Chef::Platform.set platform: :omnios, resource: :mysql_service, provider: Chef::Provider::MysqlServiceSmf + Chef::Platform.set platform: :smartos, resource: :mysql_service, provider: Chef::Provider::MysqlServiceSmf + + # upstart service + Chef::Platform.set platform: :ubuntu, resource: :mysql_service, provider: Chef::Provider::MysqlServiceUpstart + + # default service + Chef::Platform.set resource: :mysql_service, provider: Chef::Provider::MysqlServiceSysvinit + + # config + Chef::Platform.set resource: :mysql_config, provider: Chef::Provider::MysqlConfig + + # client + Chef::Platform.set resource: :mysql_client, provider: Chef::Provider::MysqlClient +end diff --git a/cookbooks/mysql/libraries/resource_mysql_client.rb b/cookbooks/mysql/libraries/resource_mysql_client.rb index 5940505..8585dbe 100644 --- a/cookbooks/mysql/libraries/resource_mysql_client.rb +++ b/cookbooks/mysql/libraries/resource_mysql_client.rb @@ -3,6 +3,8 @@ require 'chef/resource/lwrp_base' class Chef class Resource class MysqlClient < Chef::Resource::LWRPBase + provides :mysql_client + self.resource_name = :mysql_client actions :create, :delete default_action :create diff --git a/cookbooks/mysql/libraries/resource_mysql_config.rb b/cookbooks/mysql/libraries/resource_mysql_config.rb index 3a5305f..a8767ce 100644 --- a/cookbooks/mysql/libraries/resource_mysql_config.rb +++ b/cookbooks/mysql/libraries/resource_mysql_config.rb @@ -3,6 +3,8 @@ require 'chef/resource/lwrp_base' class Chef class Resource class MysqlConfig < Chef::Resource::LWRPBase + provides :mysql_config + self.resource_name = :mysql_config actions :create, :delete default_action :create diff --git a/cookbooks/mysql/libraries/resource_mysql_service.rb b/cookbooks/mysql/libraries/resource_mysql_service.rb index 5c85f2d..8d4f5d3 100644 --- a/cookbooks/mysql/libraries/resource_mysql_service.rb +++ b/cookbooks/mysql/libraries/resource_mysql_service.rb @@ -3,6 +3,8 @@ require 'chef/resource/lwrp_base' class Chef class Resource class MysqlService < Chef::Resource::LWRPBase + provides :mysql_service + self.resource_name = :mysql_service actions :create, :delete, :start, :stop, :restart, :reload default_action :create @@ -15,11 +17,15 @@ class Chef attribute :package_name, kind_of: String, default: nil attribute :package_version, kind_of: String, default: nil attribute :bind_address, kind_of: String, default: nil - attribute :port, kind_of: String, default: '3306' + attribute :port, kind_of: [String, Integer], default: '3306' attribute :run_group, kind_of: String, default: 'mysql' attribute :run_user, kind_of: String, default: 'mysql' attribute :socket, kind_of: String, default: nil + attribute :mysqld_options, kind_of: Hash, default: {} attribute :version, kind_of: String, default: nil + attribute :error_log, kind_of: String, default: nil + attribute :tmp_dir, kind_of: String, default: nil + attribute :pid_file, kind_of: String, default: nil end end end diff --git a/cookbooks/mysql/libraries/z_provider_mapping.rb b/cookbooks/mysql/libraries/z_provider_mapping.rb deleted file mode 100644 index 7c70bde..0000000 --- a/cookbooks/mysql/libraries/z_provider_mapping.rb +++ /dev/null @@ -1,47 +0,0 @@ -# provider mappings for Chef 11 - -######### -# service -######### -Chef::Platform.set platform: :amazon, resource: :mysql_service, provider: Chef::Provider::MysqlService::Sysvinit -Chef::Platform.set platform: :centos, version: '< 7.0', resource: :mysql_service, provider: Chef::Provider::MysqlService::Sysvinit -Chef::Platform.set platform: :centos, version: '>= 7.0', resource: :mysql_service, provider: Chef::Provider::MysqlService::Systemd -Chef::Platform.set platform: :debian, resource: :mysql_service, provider: Chef::Provider::MysqlService::Sysvinit -Chef::Platform.set platform: :fedora, version: '< 19', resource: :mysql_service, provider: Chef::Provider::MysqlService::Sysvinit -Chef::Platform.set platform: :fedora, version: '>= 19', resource: :mysql_service, provider: Chef::Provider::MysqlService::Systemd -Chef::Platform.set platform: :omnios, resource: :mysql_service, provider: Chef::Provider::MysqlService::Smf -Chef::Platform.set platform: :redhat, version: '< 7.0', resource: :mysql_service, provider: Chef::Provider::MysqlService::Sysvinit -Chef::Platform.set platform: :redhat, version: '>= 7.0', resource: :mysql_service, provider: Chef::Provider::MysqlService::Systemd -Chef::Platform.set platform: :scientific, version: '< 7.0', resource: :mysql_service, provider: Chef::Provider::MysqlService::Sysvinit -Chef::Platform.set platform: :scientific, version: '>= 7.0', resource: :mysql_service, provider: Chef::Provider::MysqlService::Systemd -Chef::Platform.set platform: :smartos, resource: :mysql_service, provider: Chef::Provider::MysqlService::Smf -Chef::Platform.set platform: :suse, resource: :mysql_service, provider: Chef::Provider::MysqlService::Sysvinit -Chef::Platform.set platform: :ubuntu, resource: :mysql_service, provider: Chef::Provider::MysqlService::Upstart - -######### -# config -######### -Chef::Platform.set platform: :amazon, resource: :mysql_config, provider: Chef::Provider::MysqlConfig -Chef::Platform.set platform: :centos, resource: :mysql_config, provider: Chef::Provider::MysqlConfig -Chef::Platform.set platform: :debian, resource: :mysql_config, provider: Chef::Provider::MysqlConfig -Chef::Platform.set platform: :fedora, resource: :mysql_config, provider: Chef::Provider::MysqlConfig -Chef::Platform.set platform: :omnios, resource: :mysql_config, provider: Chef::Provider::MysqlConfig -Chef::Platform.set platform: :redhat, resource: :mysql_config, provider: Chef::Provider::MysqlConfig -Chef::Platform.set platform: :scientific, resource: :mysql_config, provider: Chef::Provider::MysqlConfig -Chef::Platform.set platform: :smartos, resource: :mysql_config, provider: Chef::Provider::MysqlConfig -Chef::Platform.set platform: :suse, resource: :mysql_config, provider: Chef::Provider::MysqlConfig -Chef::Platform.set platform: :ubuntu, resource: :mysql_config, provider: Chef::Provider::MysqlConfig - -######### -# client -######### -Chef::Platform.set platform: :amazon, resource: :mysql_client, provider: Chef::Provider::MysqlClient -Chef::Platform.set platform: :centos, resource: :mysql_client, provider: Chef::Provider::MysqlClient -Chef::Platform.set platform: :debian, resource: :mysql_client, provider: Chef::Provider::MysqlClient -Chef::Platform.set platform: :fedora, resource: :mysql_client, provider: Chef::Provider::MysqlClient -Chef::Platform.set platform: :omnios, resource: :mysql_client, provider: Chef::Provider::MysqlClient -Chef::Platform.set platform: :redhat, resource: :mysql_client, provider: Chef::Provider::MysqlClient -Chef::Platform.set platform: :scientific, resource: :mysql_client, provider: Chef::Provider::MysqlClient -Chef::Platform.set platform: :smartos, resource: :mysql_client, provider: Chef::Provider::MysqlClient -Chef::Platform.set platform: :suse, resource: :mysql_client, provider: Chef::Provider::MysqlClient -Chef::Platform.set platform: :ubuntu, resource: :mysql_client, provider: Chef::Provider::MysqlClient diff --git a/cookbooks/mysql/metadata.json b/cookbooks/mysql/metadata.json index 1c9d9f1..69e6d19 100644 --- a/cookbooks/mysql/metadata.json +++ b/cookbooks/mysql/metadata.json @@ -1 +1 @@ -{"name":"mysql","version":"6.0.22","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":{"amazon":">= 0.0.0","redhat":">= 0.0.0","centos":">= 0.0.0","scientific":">= 0.0.0","fedora":">= 0.0.0","debian":">= 0.0.0","ubuntu":">= 0.0.0","smartos":">= 0.0.0","omnios":">= 0.0.0","suse":">= 0.0.0"},"dependencies":{"yum-mysql-community":">= 0.0.0","smf":">= 0.0.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file +{"name":"mysql","version":"6.1.2","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":{"amazon":">= 0.0.0","redhat":">= 0.0.0","centos":">= 0.0.0","scientific":">= 0.0.0","fedora":">= 0.0.0","debian":">= 0.0.0","ubuntu":">= 0.0.0","smartos":">= 0.0.0","omnios":">= 0.0.0","suse":">= 0.0.0"},"dependencies":{"yum-mysql-community":">= 0.0.0","smf":">= 0.0.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file diff --git a/cookbooks/mysql/templates/default/my.cnf.erb b/cookbooks/mysql/templates/default/my.cnf.erb index 15dc9c2..faa8d3e 100644 --- a/cookbooks/mysql/templates/default/my.cnf.erb +++ b/cookbooks/mysql/templates/default/my.cnf.erb @@ -38,6 +38,9 @@ datadir = <%= @data_dir %> <% if @tmp_dir %> tmpdir = <%= @tmp_dir %> <% end %> +<% @config.mysqld_options.each do |option,value| %> +<%= option %> = <%= value %> +<% end %> <% if @lc_messages_dir %> lc-messages-dir = <%= @lc_messages_dir %> <% end %> diff --git a/cookbooks/mysql/templates/default/sysvinit/mysqld.erb b/cookbooks/mysql/templates/default/sysvinit/mysqld.erb index c167fa7..45b952d 100644 --- a/cookbooks/mysql/templates/default/sysvinit/mysqld.erb +++ b/cookbooks/mysql/templates/default/sysvinit/mysqld.erb @@ -30,8 +30,9 @@ # Variables #### -STARTTIMEOUT=30 -STOPTIMEOUT=15 +STARTTIMEOUT=900 +STOPTIMEOUT=900 +PID_DELAY=60 #### # Helper functions @@ -131,6 +132,7 @@ print_stop_failure() { start_command() { # Attempt to start <%= @mysql_name %> echo "Starting MySQL instance <%= @mysql_name %>" + local scl_name="<%= @scl_name %>" if [ -z $scl_name ]; then @@ -176,21 +178,32 @@ start() { 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 - # Handle timeout - if [ $TIMEOUT -eq 0 ]; then + 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 - - # successbaby.gif - print_start_success - return 0 } # Reload <%= @mysql_name %> diff --git a/cookbooks/mysql2_chef_gem/CHANGELOG.md b/cookbooks/mysql2_chef_gem/CHANGELOG.md index ba5b39d..f41303c 100644 --- a/cookbooks/mysql2_chef_gem/CHANGELOG.md +++ b/cookbooks/mysql2_chef_gem/CHANGELOG.md @@ -1,6 +1,10 @@ mysql2_chef_gem CHANGELOG ======================== +1.0.2 (2015-06-29) +------------------ +- Updating metadata to depend on mysql ~> 6.0 + 1.0.1 (2014-12-25) ------------------ - Moving from recipe_eval in to include_recipe LWRP diff --git a/cookbooks/mysql2_chef_gem/README.md b/cookbooks/mysql2_chef_gem/README.md index ef0cadf..97c4f68 100644 --- a/cookbooks/mysql2_chef_gem/README.md +++ b/cookbooks/mysql2_chef_gem/README.md @@ -83,9 +83,9 @@ end #### Parameters - `gem_version` - The version of the `mysql` Rubygem to install into the Chef environment. Defaults to '0.3.17' -- `connectors_url` - URL of a tarball containing pre-compiled MySQL connector libraries -- `connectors_checksum` - sha256sum of the `connectors_url` tarball +- `client_version` - The version of the mysql client libraries to + install and link against #### Actions - `:install` - Build and install the gem into the Chef environment @@ -104,5 +104,5 @@ end Authors ------- -- Author:: Sean OMeara () +- Author:: Sean OMeara () - Author:: Nicolas Blanc() diff --git a/cookbooks/mysql2_chef_gem/metadata.json b/cookbooks/mysql2_chef_gem/metadata.json index 292454f..5021c36 100644 --- a/cookbooks/mysql2_chef_gem/metadata.json +++ b/cookbooks/mysql2_chef_gem/metadata.json @@ -1,39 +1 @@ -{ - "name": "mysql2_chef_gem", - "version": "1.0.1", - "description": "Provides the mysql2_chef_gem resource", - "long_description": "", - "maintainer": "Nicolas Blanc", - "maintainer_email": "sinfomicien@gmail.com", - "license": "Apache 2.0", - "platforms": { - "amazon": ">= 0.0.0", - "redhat": ">= 0.0.0", - "centos": ">= 0.0.0", - "scientific": ">= 0.0.0", - "fedora": ">= 0.0.0", - "debian": ">= 0.0.0", - "ubuntu": ">= 0.0.0" - }, - "dependencies": { - "build-essential": ">= 0.0.0", - "mysql": ">= 0.0.0", - "mariadb": ">= 0.0.0" - }, - "recommendations": { - }, - "suggestions": { - }, - "conflicting": { - }, - "providing": { - }, - "replacing": { - }, - "attributes": { - }, - "groupings": { - }, - "recipes": { - } -} \ No newline at end of file +{"name":"mysql2_chef_gem","version":"1.0.2","description":"Provides the mysql2_chef_gem resource","long_description":"","maintainer":"Nicolas Blanc","maintainer_email":"sinfomicien@gmail.com","license":"Apache 2.0","platforms":{"amazon":">= 0.0.0","redhat":">= 0.0.0","centos":">= 0.0.0","scientific":">= 0.0.0","fedora":">= 0.0.0","debian":">= 0.0.0","ubuntu":">= 0.0.0"},"dependencies":{"build-essential":">= 0.0.0","mysql":"~> 6.0","mariadb":">= 0.0.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file diff --git a/cookbooks/ohai/CHANGELOG.md b/cookbooks/ohai/CHANGELOG.md index 1a903a1..d4d23ac 100644 --- a/cookbooks/ohai/CHANGELOG.md +++ b/cookbooks/ohai/CHANGELOG.md @@ -1,51 +1,67 @@ -ohai Cookbook CHANGELOG -======================= +# ohai Cookbook CHANGELOG This file is used to list changes made in each version of the ohai cookbook. +## 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.1 (2014-06-07) -------------------- -* [COOK-4683] Remove warnings about reopening resource +## v2.0.4 (2015-10-30) +- Resolved deprecation warnings with the Chefspec matchers -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/opscode-cookbooks/ohai/pull/16/files) for more info. +## 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 -v2.0.0 (2014-02-25) -------------------- +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 -------- +## v1.1.12 - Dummy release due to a Community Site upload failure -v1.1.10 -------- +## v1.1.10 ### Bug -- **[COOK-3091](https://tickets.opscode.com/browse/COOK-3091)** - Fix checking `Chef::Config[:config_file]` +- **[COOK-3091](https://tickets.chef.io/browse/COOK-3091)** - Fix checking `Chef::Config[:config_file]` -v1.1.8 ------- +## 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 ------- +## v1.1.6 - [COOK-2057] - distribution from another cookbok fails if ohai attributes are loaded after the other cookbook -v1.1.4 ------- +## v1.1.4 - [COOK-1128] - readme update, Replace reference to deprecated chef cookbook with one to chef-client -v1.1.2 ------- +## v1.1.2 - [COOK-1424] - prevent plugin_path growth to infinity -v1.1.0 ------- +## v1.1.0 - [COOK-1174] - custom_plugins is only conditionally available - [COOK-1383] - allow plugins from other cookbooks -v1.0.2 ------- +## 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/MAINTAINERS.md b/cookbooks/ohai/MAINTAINERS.md new file mode 100644 index 0000000..c6a51ae --- /dev/null +++ b/cookbooks/ohai/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 +* [Tim Smith](https://github.com/tas50) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Sean OMeara](https://github.com/someara) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) diff --git a/cookbooks/ohai/README.md b/cookbooks/ohai/README.md index 1734390..eca46f7 100644 --- a/cookbooks/ohai/README.md +++ b/cookbooks/ohai/README.md @@ -1,59 +1,64 @@ -ohai Cookbook -============= +# ohai Cookbook +[![Build Status](https://travis-ci.org/chef-cookbooks/ohai.svg?branch=master)](https://travis-ci.org/chef-cookbooks/ohai) [![Cookbook Version](https://img.shields.io/cookbook/v/ohai.svg)](https://supermarket.chef.io/cookbooks/ohai) + Creates a configured plugin path for distributing custom Ohai plugins, and reloads them via Ohai within the context of a Chef Client run during the compile phase (if needed). +## Requirements +### Platforms +- Debian/Ubuntu +- RHEL/CentOS/Scientific/Amazon/Oracle +- FreeBSD +- Windows -Attributes ----------- +### Chef +- Chef 11+ + +### Cookbooks +- none + +## Attributes - `node['ohai']['plugin_path']` - location to drop off plugins directory, default is `/etc/chef/ohai_plugins`. This is not FHS-compliant, an FHS location would be something like `/var/lib/ohai/plugins`, or `/var/lib/chef/ohai_plugins` or similar. Neither an FHS location or the default value of this attribute are in the default Ohai plugin path. Set the Ohai plugin path with the config setting "`Ohai::Config[:plugin_path]`" in the Chef config file (the `chef-client::config` recipe does this automatically for you!). The attribute is not set to the default plugin path that Ohai ships with because we don't want to risk destroying existing essential plugins for Ohai. - `node['ohai']['plugins']` - sources of plugins, defaults to the `files/default/plugins` directory of this cookbook. You can add additional cookbooks by adding the name of the cookbook as a key and the path of the files directory as the value. You have to make sure that you don't have any file conflicts between multiple cookbooks. The last one to write wins. - - `node['ohai']['hints_path']` - location to drop off hints directory, default is `/etc/chef/ohai/hints`. -Usage ------ +## Usage Put the recipe `ohai` at the start of the node's run list to make sure that custom plugins are loaded early on in the Chef run and data is available for later recipes. The execution of the custom plugins occurs within the recipe during the compile phase, so you can write new plugins and use the data they return in your Chef recipes. For information on how to write custom plugins for Ohai, please see the Chef wiki pages. -http://wiki.opscode.com/display/chef/Writing+Ohai+Plugins +[http://wiki.chef.io/display/chef/Writing+Ohai+Plugins](http://wiki.chef.io/display/chef/Writing+Ohai+Plugins) -*PLEASE NOTE* - This recipe reloads the Ohai plugins a 2nd time during the Chef run if: - -* The "`Ohai::Config[:plugin_path]`" config setting has *NOT* been properly set in the Chef config file +_PLEASE NOTE_ - This recipe reloads the Ohai plugins a 2nd time during the Chef run if: +- The "`Ohai::Config[:plugin_path]`" config setting has _NOT_ been properly set in the Chef config file - The "`Ohai::Config[:plugin_path]`" config setting has been properly set in the Chef config file and there are updated plugins dropped off at "`node['ohai']['plugin_path']`". -LWRP ----- - +## LWRP ### `ohai_hint` - Create hints file. You can find usage examples at `test/cookbooks/ohai_test/recipes/*.rb`. #### 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 class. - - `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 class. +#### 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 - -Example -------- +## Example For an example implementation, inspect the ohai_plugin.rb recipe in the nginx community cookbook. +## License & Authors +**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io)) -License & Authors ------------------ -- Author:: Joshua Timberman () -- Author:: Seth Chisamore () - -```text -Copyright:: 2010-2011, Opscode, Inc +**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 diff --git a/cookbooks/ohai/attributes/default.rb b/cookbooks/ohai/attributes/default.rb index 4b463bc..6880a48 100644 --- a/cookbooks/ohai/attributes/default.rb +++ b/cookbooks/ohai/attributes/default.rb @@ -2,7 +2,7 @@ # Cookbook Name:: ohai # Attribute:: default # -# Copyright 2010, Opscode, Inc +# Copyright 2010-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. @@ -18,14 +18,14 @@ # # FHS location would be /var/lib/chef/ohai_plugins or similar. -case node["platform_family"] -when "windows" - default["ohai"]["plugin_path"] = "C:/chef/ohai_plugins" - default["ohai"]["hints_path"] = "C:/chef/ohai/hints" +case node['platform_family'] +when 'windows' + default['ohai']['plugin_path'] = "#{ENV['systemdrive']}/chef/ohai_plugins" + default['ohai']['hints_path'] = "#{ENV['systemdrive']}/chef/ohai/hints" else - default["ohai"]["plugin_path"] = "/etc/chef/ohai_plugins" - default["ohai"]["hints_path"] = "/etc/chef/ohai/hints" + default['ohai']['plugin_path'] = '/etc/chef/ohai_plugins' + default['ohai']['hints_path'] = '/etc/chef/ohai/hints' end # The list of plugins and their respective file locations -default["ohai"]["plugins"]["ohai"] = "plugins" +default['ohai']['plugins']['ohai'] = 'plugins' diff --git a/cookbooks/ohai/libraries/matchers.rb b/cookbooks/ohai/libraries/matchers.rb new file mode 100644 index 0000000..6f06502 --- /dev/null +++ b/cookbooks/ohai/libraries/matchers.rb @@ -0,0 +1,21 @@ +# encoding: utf-8 + +if defined?(ChefSpec) + if ChefSpec.respond_to?(:define_matcher) + # ChefSpec >= 4.1 + ChefSpec.define_matcher(:ohai_hint) + elsif defined?(ChefSpec::Runner) && + ChefSpec::Runner.respond_to?(:define_runner_method) + # ChefSpec < 4.1 + ChefSpec::Runner.define_runner_method(:ohai_hint) + end + + def create_ohai_hint(resource) + ChefSpec::Matchers::ResourceMatcher.new(:ohai_hint, :create, resource) + end + + def delete_ohai_hint(resource) + ChefSpec::Matchers::ResourceMatcher.new(:ohai_hint, :delete, resource) + end + +end diff --git a/cookbooks/ohai/metadata.json b/cookbooks/ohai/metadata.json index 31065ad..e9fb4ef 100644 --- a/cookbooks/ohai/metadata.json +++ b/cookbooks/ohai/metadata.json @@ -1,46 +1 @@ -{ - "name": "ohai", - "version": "2.0.1", - "description": "Distributes a directory of custom ohai plugins", - "long_description": "ohai Cookbook\n=============\nCreates a configured plugin path for distributing custom Ohai plugins, and reloads them via Ohai within the context of a Chef Client run during the compile phase (if needed).\n\n\nAttributes\n----------\n- `node['ohai']['plugin_path']` - location to drop off plugins directory, default is `/etc/chef/ohai_plugins`. This is not FHS-compliant, an FHS location would be something like `/var/lib/ohai/plugins`, or `/var/lib/chef/ohai_plugins` or similar.\n\n Neither an FHS location or the default value of this attribute are in the default Ohai plugin path. Set the Ohai plugin path with the config setting \"`Ohai::Config[:plugin_path]`\" in the Chef config file (the `chef-client::config` recipe does this automatically for you!). The attribute is not set to the default plugin path that Ohai ships with because we don't want to risk destroying existing essential plugins for Ohai.\n\n- `node['ohai']['plugins']` - sources of plugins, defaults to the `files/default/plugins` directory of this cookbook. You can add additional cookbooks by adding the name of the cookbook as a key and the path of the files directory as the value. You have to make sure that you don't have any file conflicts between multiple cookbooks. The last one to write wins.\n\n- `node['ohai']['hints_path']` - location to drop off hints directory, default is `/etc/chef/ohai/hints`.\n\nUsage\n-----\nPut the recipe `ohai` at the start of the node's run list to make sure that custom plugins are loaded early on in the Chef run and data is available for later recipes.\n\nThe execution of the custom plugins occurs within the recipe during the compile phase, so you can write new plugins and use the data they return in your Chef recipes.\n\nFor information on how to write custom plugins for Ohai, please see the Chef wiki pages.\n\nhttp://wiki.opscode.com/display/chef/Writing+Ohai+Plugins\n\n*PLEASE NOTE* - This recipe reloads the Ohai plugins a 2nd time during the Chef run if:\n\n* The \"`Ohai::Config[:plugin_path]`\" config setting has *NOT* been properly set in the Chef config file\n- The \"`Ohai::Config[:plugin_path]`\" config setting has been properly set in the Chef config file and there are updated plugins dropped off at \"`node['ohai']['plugin_path']`\".\n\nLWRP\n----\n\n### `ohai_hint`\n\nCreate hints file. You can find usage examples at `test/cookbooks/ohai_test/recipes/*.rb`.\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 class.\n\n\nExample\n-------\nFor an example implementation, inspect the ohai_plugin.rb recipe in the nginx community cookbook.\n\n\nLicense & Authors\n-----------------\n- Author:: Joshua Timberman ()\n- Author:: Seth Chisamore ()\n\n```text\nCopyright:: 2010-2011, Opscode, 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": "Opscode, Inc", - "maintainer_email": "cookbooks@opscode.com", - "license": "Apache 2.0", - "platforms": { - }, - "dependencies": { - }, - "recommendations": { - }, - "suggestions": { - }, - "conflicting": { - }, - "providing": { - }, - "replacing": { - }, - "attributes": { - "ohai/plugin_path": { - "display_name": "Ohai Plugin Path", - "description": "Distribute plugins to this path.", - "type": "string", - "required": "optional", - "default": "/etc/chef/ohai_plugins" - }, - "ohai/plugins": { - "display_name": "Ohai Plugin Sources", - "description": "Read plugins from these cookbooks and paths", - "type": "hash", - "required": "optional", - "default": { - "ohai": "plugins" - } - } - }, - "groupings": { - }, - "recipes": { - "ohai::default": "Distributes a directory of custom ohai plugins" - } -} \ No newline at end of file +{"name":"ohai","version":"2.1.0","description":"Distributes a directory of custom ohai plugins","long_description":"# ohai Cookbook\n[![Build Status](https://travis-ci.org/chef-cookbooks/ohai.svg?branch=master)](https://travis-ci.org/chef-cookbooks/ohai) [![Cookbook Version](https://img.shields.io/cookbook/v/ohai.svg)](https://supermarket.chef.io/cookbooks/ohai)\n\nCreates a configured plugin path for distributing custom Ohai plugins, and reloads them via Ohai within the context of a Chef Client run during the compile phase (if needed).\n\n## Requirements\n### Platforms\n- Debian/Ubuntu\n- RHEL/CentOS/Scientific/Amazon/Oracle\n- FreeBSD\n- Windows\n\n### Chef\n- Chef 11+\n\n### Cookbooks\n- none\n\n## Attributes\n- `node['ohai']['plugin_path']` - location to drop off plugins directory, default is `/etc/chef/ohai_plugins`. This is not FHS-compliant, an FHS location would be something like `/var/lib/ohai/plugins`, or `/var/lib/chef/ohai_plugins` or similar.\n\n Neither an FHS location or the default value of this attribute are in the default Ohai plugin path. Set the Ohai plugin path with the config setting \"`Ohai::Config[:plugin_path]`\" in the Chef config file (the `chef-client::config` recipe does this automatically for you!). The attribute is not set to the default plugin path that Ohai ships with because we don't want to risk destroying existing essential plugins for Ohai.\n\n- `node['ohai']['plugins']` - sources of plugins, defaults to the `files/default/plugins` directory of this cookbook. You can add additional cookbooks by adding the name of the cookbook as a key and the path of the files directory as the value. You have to make sure that you don't have any file conflicts between multiple cookbooks. The last one to write wins.\n- `node['ohai']['hints_path']` - location to drop off hints directory, default is `/etc/chef/ohai/hints`.\n\n## Usage\nPut the recipe `ohai` at the start of the node's run list to make sure that custom plugins are loaded early on in the Chef run and data is available for later recipes.\n\nThe execution of the custom plugins occurs within the recipe during the compile phase, so you can write new plugins and use the data they return in your Chef recipes.\n\nFor information on how to write custom plugins for Ohai, please see the Chef wiki pages.\n\n[http://wiki.chef.io/display/chef/Writing+Ohai+Plugins](http://wiki.chef.io/display/chef/Writing+Ohai+Plugins)\n\n_PLEASE NOTE_ - This recipe reloads the Ohai plugins a 2nd time during the Chef run if:\n- The \"`Ohai::Config[:plugin_path]`\" config setting has _NOT_ been properly set in the Chef config file\n- The \"`Ohai::Config[:plugin_path]`\" config setting has been properly set in the Chef config file and there are updated plugins dropped off at \"`node['ohai']['plugin_path']`\".\n\n## LWRP\n### `ohai_hint`\nCreate hints file. You can find usage examples at `test/cookbooks/ohai_test/recipes/*.rb`.\n\n#### Resource Attributes\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 class.\n\n#### ChefSpec Matchers\nYou can check for the creation or deletion of ohai hints with chefspec using these custom matches:\n- create_ohai_hint\n- delete_ohai_hint\n\n## Example\nFor an example implementation, inspect the ohai_plugin.rb recipe in the nginx community cookbook.\n\n## License & Authors\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":{"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","freebsd":">= 0.0.0","windows":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{"ohai::default":"Distributes a directory of custom ohai plugins"}} \ No newline at end of file diff --git a/cookbooks/ohai/metadata.rb b/cookbooks/ohai/metadata.rb deleted file mode 100644 index 82b7e63..0000000 --- a/cookbooks/ohai/metadata.rb +++ /dev/null @@ -1,23 +0,0 @@ -name "ohai" -maintainer "Opscode, Inc" -maintainer_email "cookbooks@opscode.com" -license "Apache 2.0" -description "Distributes a directory of custom ohai plugins" -long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) -version "2.0.1" - -recipe "ohai::default", "Distributes a directory of custom ohai plugins" - -attribute "ohai/plugin_path", - :display_name => "Ohai Plugin Path", - :description => "Distribute plugins to this path.", - :type => "string", - :required => "optional", - :default => "/etc/chef/ohai_plugins" - -attribute "ohai/plugins", - :display_name => "Ohai Plugin Sources", - :description => "Read plugins from these cookbooks and paths", - :type => "hash", - :required => "optional", - :default => {'ohai' => 'plugins'} diff --git a/cookbooks/ohai/providers/hint.rb b/cookbooks/ohai/providers/hint.rb index 391032a..c83ea38 100644 --- a/cookbooks/ohai/providers/hint.rb +++ b/cookbooks/ohai/providers/hint.rb @@ -2,33 +2,44 @@ def why_run_supported? true end -def build_ohai_hint_path - ::File.join(node[:ohai][:hints_path], "#{new_resource.name}.json") +def ohai_hint_path + ::File.join(node['ohai']['hints_path'], "#{new_resource.name}.json") +end + +def build_content + # passing nil to file produces deprecation warnings so pass an empty string + return '' if new_resource.content.nil? || new_resource.content.empty? + JSON.pretty_generate(new_resource.content) end use_inline_resources action :create do - if @current_resource.content != new_resource.content - directory node[:ohai][:hints_path] do + # don't create the file if the existing file was empty and so is the new one + # this avoids bogus content updates on every chef run + unless (@current_resource.content && @current_resource.content.empty?) && new_resource.content.nil? + directory node['ohai']['hints_path'] do action :create recursive true end - file build_ohai_hint_path do + file ohai_hint_path do action :create - content JSON.pretty_generate(new_resource.content) + content build_content end end end - def load_current_resource @current_resource = Chef::Resource::OhaiHint.new(new_resource.name) - if ::File.exist?(build_ohai_hint_path) - @current_resource.content(JSON.parse(::File.read(build_ohai_hint_path))) - else - @current_resource.content(nil) + if ::File.exist?(ohai_hint_path) + Chef::Log.debug("Existing ohai hint at #{ohai_hint_path} found. Attempting to parse JSON") + begin + @current_resource.content(JSON.parse(::File.read(ohai_hint_path))) + rescue JSON::ParserError + @current_resource.content({}) + Chef::Log.debug("Could not parse JSON in ohai hint at #{ohai_hint_path}. It's probably an empty hint file") + end end @current_resource diff --git a/cookbooks/ohai/recipes/default.rb b/cookbooks/ohai/recipes/default.rb index 204addd..f54332b 100644 --- a/cookbooks/ohai/recipes/default.rb +++ b/cookbooks/ohai/recipes/default.rb @@ -2,7 +2,7 @@ # Cookbook Name:: ohai # Recipe:: default # -# Copyright 2011, Opscode, Inc +# 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. @@ -29,7 +29,6 @@ Chef::Log.info("ohai plugins will be at: #{node['ohai']['plugin_path']}") # This is done during the compile phase so new plugins can be used in # resources later in the run. node['ohai']['plugins'].each_pair do |source_cookbook, path| - rd = remote_directory "#{node['ohai']['plugin_path']} for cookbook #{source_cookbook}" do path node['ohai']['plugin_path'] cookbook source_cookbook @@ -50,6 +49,4 @@ end # Reload ohai if the client's plugin_path did not contain # node['ohai']['plugin_path'], or new plugins were loaded -if reload_ohai - resource.run_action(:reload) -end +resource.run_action(:reload) if reload_ohai diff --git a/cookbooks/ohai/resources/hint.rb b/cookbooks/ohai/resources/hint.rb index 1922a58..abfd70c 100644 --- a/cookbooks/ohai/resources/hint.rb +++ b/cookbooks/ohai/resources/hint.rb @@ -1,6 +1,5 @@ actions :create, :delete default_action :create - -attribute :hint_name, :kind_of => String, :name_attribute => true -attribute :content, :kind_of => Hash, :default => {} +attribute :hint_name, kind_of: String, name_attribute: true +attribute :content, kind_of: Hash diff --git a/cookbooks/omnibus_updater/CHANGELOG.md b/cookbooks/omnibus_updater/CHANGELOG.md index d29acac..826e85d 100644 --- a/cookbooks/omnibus_updater/CHANGELOG.md +++ b/cookbooks/omnibus_updater/CHANGELOG.md @@ -1,3 +1,13 @@ +v1.0.6 +====== +* Get rid of warnings about defined constant +* update Chef download url +* Updates supported versions +* require chef/rest +* use Chef::Mash explicitly +* Define the Chef::Mash constant if not provided by chef +* add test suites for ubuntu 14.04 and centos 7 + v1.0.4 ====== * file_cache_path path to store chef-client diff --git a/cookbooks/omnibus_updater/README.md b/cookbooks/omnibus_updater/README.md index 08d1fd4..b4c8454 100644 --- a/cookbooks/omnibus_updater/README.md +++ b/cookbooks/omnibus_updater/README.md @@ -6,6 +6,19 @@ Chef package into your system if you are currently running via gem install, and it can keep your omnibus install up to date. +Supports +======== + +- redhat +- centos +- amazon +- scientific +- oracle +- debian +- ubuntu +- mac_os_x +- solaris + Usage ===== diff --git a/cookbooks/omnibus_updater/libraries/omnitrucker.rb b/cookbooks/omnibus_updater/libraries/omnitrucker.rb index 92d1e8d..0179dd3 100644 --- a/cookbooks/omnibus_updater/libraries/omnitrucker.rb +++ b/cookbooks/omnibus_updater/libraries/omnitrucker.rb @@ -17,13 +17,21 @@ # limitations under the License. # +require "chef/rest" +require "chef/mash" +require "net/http" + +unless(Chef.constants.include?(:Mash)) + Chef::Mash = Mash +end + module OmnibusTrucker class << self URL_MAP = { :p => :platform, :pv => :platform_version, :m => :machine, :v => :version, :prerelease => :prerelease, :nightlies => :nightlies - } + } unless defined?(URL_MAP) def build_url(*opts) args = node = nil @@ -40,7 +48,7 @@ module OmnibusTrucker if(node) args = collect_attributes(node).merge(args) end - url = args[:url] || "http://www.opscode.com/chef/download#{'-server' if args[:server]}" + url = args[:url] || "http://www.chef.io/chef/download#{'-server' if args[:server]}" u_args = URL_MAP.map do |u_k, a_k| "#{u_k}=#{args[a_k]}" unless args[a_k].nil? end.compact @@ -48,7 +56,7 @@ module OmnibusTrucker end def collect_attributes(node, args={}) - set = Mash[ + set = Chef::Mash[ [:platform_family, :platform, :platform_version].map do |k| [k, args[k] || node[k]] end diff --git a/cookbooks/omnibus_updater/metadata.json b/cookbooks/omnibus_updater/metadata.json index ead25c9..ff2316d 100644 --- a/cookbooks/omnibus_updater/metadata.json +++ b/cookbooks/omnibus_updater/metadata.json @@ -1,29 +1,56 @@ { "name": "omnibus_updater", "description": "Chef omnibus package updater and installer", - "long_description": "OmnibusUpdater\n==============\n\nUpdate your omnibus! This cookbook can install the omnibus\nChef package into your system if you are currently running\nvia gem install, and it can keep your omnibus install up\nto date.\n\nUsage\n=====\n\nAdd the recipe to your run list and specify what version should\nbe installed on the node:\n\n`knife node run_list add recipe[omnibus_updater]`\n\nIn your role you'll likely want to set the version. It defaults\nto nothing, and will install the latest..\n\n```\noverride_attributes(\n :omnibus_updater => {\n :version => '11.4.0'\n }\n)\n```\n\nIt can also uninstall Chef from the system Ruby installation\nif you tell it to:\n\n```\noverride_attributes(\n :omnibus_updater => {\n :remove_chef_system_gem => true\n }\n)\n```\n\nFeatures\n========\n\nLatest Version\n--------------\n\nForce installation of the latest version regardless of value stored in version\nattribute by setting the `force_latest` attribute.\n\nChef Killing\n------------\n\nBy default the omnibus updater will kill the chef instance by raising an exception.\nYou can turn this off using the `kill_chef_on_upgrade` attribute. It is not\nrecommended to turn this off. Internal chef libraries may change, move, or no\nlonger exist. The currently running instance can encounter unexpected states because\nof this. To prevent this, the updater will attempt to kill the Chef instance so\nthat it can be restarted in a normal state.\n\nRestart chef-client Service\n---------------------------\n\nUse the `restart_chef_service` attribute to restart chef-client if you have it running as a service.\n\nPrerelease\n--------\n\nPrereleases can be installed via the auto-installation using `prerelease` attribute.\n\nDisable\n-------\n\nIf you want to disable the updater you can set the `disabled`\nattribute to true. This might be useful if the cookbook is added\nto a role but should then be skipped for example on a Chef server.\n\nPrevent Downgrade\n-----------------\n\nIf you want to prevent the updater from downgrading chef on a node, you \ncan set the `prevent_downgrade` attribute to true. This can be useful\nfor testing new versions manually. Note that the `always_download` \nattribute takes precedence if set.\n\nInfos\n=====\n\n* Repo: https://github.com/hw-cookbooks/omnibus_updater\n* IRC: Freenode @ #heavywater\n* Cookbook: http://ckbk.it/omnibus_updater\n", + "long_description": "OmnibusUpdater\n==============\n\nUpdate your omnibus! This cookbook can install the omnibus\nChef package into your system if you are currently running\nvia gem install, and it can keep your omnibus install up\nto date.\n\nSupports\n========\n\n- redhat\n- centos\n- amazon\n- scientific\n- oracle\n- debian\n- ubuntu\n- mac_os_x\n- solaris\n\nUsage\n=====\n\nAdd the recipe to your run list and specify what version should\nbe installed on the node:\n\n`knife node run_list add recipe[omnibus_updater]`\n\nIn your role you'll likely want to set the version. It defaults\nto nothing, and will install the latest..\n\n```\noverride_attributes(\n :omnibus_updater => {\n :version => '11.4.0'\n }\n)\n```\n\nIt can also uninstall Chef from the system Ruby installation\nif you tell it to:\n\n```\noverride_attributes(\n :omnibus_updater => {\n :remove_chef_system_gem => true\n }\n)\n```\n\nFeatures\n========\n\nLatest Version\n--------------\n\nForce installation of the latest version regardless of value stored in version\nattribute by setting the `force_latest` attribute.\n\nChef Killing\n------------\n\nBy default the omnibus updater will kill the chef instance by raising an exception.\nYou can turn this off using the `kill_chef_on_upgrade` attribute. It is not\nrecommended to turn this off. Internal chef libraries may change, move, or no\nlonger exist. The currently running instance can encounter unexpected states because\nof this. To prevent this, the updater will attempt to kill the Chef instance so\nthat it can be restarted in a normal state.\n\nRestart chef-client Service\n---------------------------\n\nUse the `restart_chef_service` attribute to restart chef-client if you have it running as a service.\n\nPrerelease\n--------\n\nPrereleases can be installed via the auto-installation using `prerelease` attribute.\n\nDisable\n-------\n\nIf you want to disable the updater you can set the `disabled`\nattribute to true. This might be useful if the cookbook is added\nto a role but should then be skipped for example on a Chef server.\n\nPrevent Downgrade\n-----------------\n\nIf you want to prevent the updater from downgrading chef on a node, you \ncan set the `prevent_downgrade` attribute to true. This can be useful\nfor testing new versions manually. Note that the `always_download` \nattribute takes precedence if set.\n\nInfos\n=====\n\n* Repo: https://github.com/hw-cookbooks/omnibus_updater\n* IRC: Freenode @ #heavywater\n* Cookbook: http://ckbk.it/omnibus_updater\n", "maintainer": "Chris Roberts", "maintainer_email": "chrisroberts.code@gmail.com", "license": "Apache 2.0", "platforms": { + "redhat": ">= 0.0.0", + "centos": ">= 0.0.0", + "amazon": ">= 0.0.0", + "scientific": ">= 0.0.0", + "oracle": ">= 0.0.0", + "debian": ">= 0.0.0", + "ubuntu": ">= 0.0.0", + "mac_os_x": ">= 0.0.0", + "solaris": ">= 0.0.0" }, "dependencies": { + }, "recommendations": { + }, "suggestions": { + }, "conflicting": { + }, "providing": { + }, "replacing": { + }, "attributes": { + }, "groupings": { + }, "recipes": { + }, - "version": "1.0.4" -} \ No newline at end of file + "version": "1.0.6", + "source_url": "", + "issues_url": "", + "privacy": false, + "chef_versions": [ + + ], + "ohai_versions": [ + + ] +} diff --git a/cookbooks/omnibus_updater/metadata.rb b/cookbooks/omnibus_updater/metadata.rb index 644a420..f8c32fe 100644 --- a/cookbooks/omnibus_updater/metadata.rb +++ b/cookbooks/omnibus_updater/metadata.rb @@ -4,4 +4,8 @@ maintainer_email "chrisroberts.code@gmail.com" license "Apache 2.0" description "Chef omnibus package updater and installer" long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) -version "1.0.4" +version "1.0.6" + +%w(redhat centos amazon scientific oracle debian ubuntu mac_os_x solaris).each do |plat| + supports plat +end diff --git a/cookbooks/omnibus_updater/recipes/default.rb b/cookbooks/omnibus_updater/recipes/default.rb index 5989259..e6f646d 100644 --- a/cookbooks/omnibus_updater/recipes/default.rb +++ b/cookbooks/omnibus_updater/recipes/default.rb @@ -21,6 +21,8 @@ if(node[:omnibus_updater][:disabled]) Chef::Log.warn 'Omnibus updater disabled via `disabled` attribute' elsif(node[:platform] == 'debian' && Gem::Version.new(node[:platform_version]) < Gem::Version.new('6.0.0')) Chef::Log.warn 'Omnibus updater does not support Debian 5' +elsif(node[:platform] == 'raspbian') + Chef::Log.warn 'Omnibus updater does not support Raspbian' else include_recipe 'omnibus_updater::downloader' include_recipe 'omnibus_updater::installer' diff --git a/cookbooks/openssl/CHANGELOG.md b/cookbooks/openssl/CHANGELOG.md index c297559..4c67fbc 100644 --- a/cookbooks/openssl/CHANGELOG.md +++ b/cookbooks/openssl/CHANGELOG.md @@ -2,13 +2,54 @@ openssl Cookbook CHANGELOG ========================== This file is used to list changes made in each version of the openssl cookbook. -v4.0.0 (2014-02-19) +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 (2014-12-30) +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) ------------------- diff --git a/cookbooks/openssl/README.md b/cookbooks/openssl/README.md index 6f0b13c..f329acc 100644 --- a/cookbooks/openssl/README.md +++ b/cookbooks/openssl/README.md @@ -1,88 +1,54 @@ -openssl Cookbook +OpenSSL Cookbook ================ +[![Build Status](https://travis-ci.org/opscode-cookbooks/openssl.svg?branch=master)](https://travis-ci.org/opscode-cookbooks/openssl) -This cookbook provides a library method to generate secure random passwords in recipes using the Ruby OpenSSL library. - -It also provides an attribute-driven recipe for upgrading OpenSSL packages. +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. +- An LWRP for generating RSA private keys. +- An LWRP for generating x509 certificates. +- An LWRP for generating dhparam.pem files. +- An attribute-driven recipe for upgrading OpenSSL packages. Requirements ------------ -The `secure_password` works on any platform with OpenSSL Ruby bindings installed, which are a requirement for Chef anyway. +The `random_password` mixin works on any platform with the Ruby SecureRandom module. This module is already included with Chef. -The upgrade recipe works on the following tested platforms: +The `openssl_x509`, `openssl_rsa_key` and `openssl_dhparam` LWRPs work on any platform with the OpenSSL Ruby bindings installed. These bindings are already included with Chef. + +The `upgrade` recipe has been tested on the following platforms: * Ubuntu 12.04, 14.04 * Debian 7.4 * CentOS 6.5 -It may work on other platforms or versions of the above platforms with or without modification. +The recipe may work on other platforms or different versions of the above platforms, but this has not been tested. -[Chef Sugar](https://github.com/sethvargo/chef-sugar) was introduced as a dependency to provide helpers that make the default attribute settings (see Attributes) easier to reason about. +Dependencies +------------ + +This cookbook depends on the [Chef Sugar](http://supermarket.chef.io/cookbooks/chef-sugar/) cookbook. [Chef Sugar](http://supermarket.chef.io/cookbooks/chef-sugar/) is used to make the default attribute settings easier to reason about. (See [Attributes](#attributes)) Attributes ---------- -* `node['openssl']['packages']` - An array of packages of openssl. The default attributes attempt to be smart about which packages are the default, but this may need to be changed by users of the `openssl::upgrade` recipe. -* `node['openssl']['restart_services']` - An array of service resources that use the `node['openssl']['packages']`. This is empty by default as Chef has no reliably reasonable way to detect which applications or services are compiled against these packages. *Note* These each need to be "`service`" resources specified somewhere in the recipes in the node's run list. +* `node['openssl']['packages']` - An array of packages required to use openssl. The default attributes attempt to be smart about which packages are the default, but this may need to be changed by users of the `openssl::upgrade` recipe. +* `node['openssl']['restart_services']` - An array of service resources that depend on the packages listed in the `node['openssl']['packages']` attribute. 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 ------- +### default + +An empty placeholder recipe. Takes no action. + ### 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 `:restart` notification to service resources named by the `node['openssl']['restart_services']` attribute. +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. -Usage ------ - -Most often this will be used to generate a secure password for an attribute. In a recipe: - -```ruby -::Chef::Recipe.send(:include, Chef::OpenSSL::Password) -node.set_unless[:my_password] = secure_password -``` - -To use the `openssl::upgrade` recipe, set the attributes as mentioned above. For example, we have a "stats_collector" service that uses openssl. It has a recipe that looks like this: - -LWRP -==== - -This cookbook includes an LWRP for generating Self Signed Certificates - -## openssl_x509 -generate a pem formatted x509 cert + key - -### Attributes -`common_name` A String representing the `CN` ssl field -`org` A String representing the `O` ssl field -`org_unit` A String representing the `OU` ssl field -`country` A String representing the `C` ssl field -`expire` A Fixnum reprenting the number of days from _now_ to expire the cert -`key_file` Optional A string to the key file to use. If no key is present it will generate and store one. -`key_pass` A String that is the key's passphrase -`key_length` A Fixnum reprenting your desired Bit Length _Default: 2048_ -`owner` The owner of the files _Default: "root"_ -`group` The group of the files _Default: "root"_ -`mode` The mode to store the files in _Default: "0400"_ - -### Example usage - - openssl_x509 "/tmp/mycert.pem" do - common_name "www.f00bar.com" - org "Foo Bar" - org_unit "Lab" - country "US" - end - - -License and Author -================== - -Author:: Jesse Nelson () -Author:: Joshua Timberman () -======= +#### 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'] @@ -95,11 +61,139 @@ end include_recipe 'openssl::upgrade' ``` -This will ensure that openssl is upgraded to the latest version so the `stats_collector` service won't be exploited (hopefully!). +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 & LWRPs +----------------- + +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.set['my_secure_attribute'] = random_password +node.set_unless['my_secure_attribute'] = random_password +node.set['my_secure_attribute'] = random_password(length: 50) +node.set['my_secure_attribute'] = random_password(length: 50, mode: :base64) +node.set['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. + +### ~~secure_password (`Opscode::OpenSSL::Password`)~~ + +This library should be considered deprecated and will be removed in a future version. Please use `OpenSSLCookbook::RandomPassword` instead. The documentation is kept here for historical reasons. + +#### ~~Example Usage~~ +```ruby +::Chef::Recipe.send(:include, Opscode::OpenSSL::Password) +node.set_unless['my_password'] = secure_password +``` + +~~Note that node attributes are widely accessible. Storing unencrypted passwords in node attributes, as in this example, carries risk.~~ + +### openssl_x509 + +This LWRP generates self-signed, PEM-formatted x509 certificates. If no existing key is specified, the LWRP will automatically generate a passwordless key with the certificate. + +#### Attributes +| Name | Type | Description | +| ----- | ---- | ------------ | +| `common_name` | String (Required) | Value for the `CN` certificate field. | +| `org` | String (Required) | Value for the `O` certificate field. | +| `org_unit` | String (Required) | Value for the `OU` certificate field. | +| `country` | String (Required) | Value for the `C` ssl field. | +| `expire` | Fixnum (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. | +| `key_file` | String (Optional) | The path to a certificate key file on the filesystem. If the `key_file` attribute is specified, the LWRP will attempt to source a key from this location. If no key file is found, the LWRP will generate a new key file at this location. If the `key_file` attribute is not specified, the LWRP 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_length` | Fixnum (Optional) | The desired Bit Length of the generated key. _Default: 2048_ | +| `owner` | String (optional) | The owner of all files created by the LWRP. _Default: "root"_ | +| `group` | String (optional) | The group of all files created by the LWRP. _Default: "root"_ | +| `mode` | String or Fixnum (Optional) | The permission mode of all files created by the LWRP. _Default: "0400"_ | + +#### 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`. + +### openssl_dhparam + +This LWRP 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. + +#### Attributes +| Name | Type | Description | +| ----- | ---- | ------------ | +| `key_length` | Fixnum (Optional) | The desired Bit Length of the generated key. _Default: 2048_ | +| `generator` | Fixnum (Optional) | The desired Diffie-Hellmann generator. Can be _2_ or _5_. | +| `owner` | String (optional) | The owner of all files created by the LWRP. _Default: "root"_ | +| `group` | String (optional) | The group of all files created by the LWRP. _Default: "root"_ | +| `mode` | String or Fixnum (Optional) | The permission mode of all files created by the LWRP. _Default: "0644"_ | + +#### 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_key + +This LWRP generates rsa 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. + +#### Attributes +| Name | Type | Description | +| ----- | ---- | ------------ | +| `key_length` | Fixnum (Optional) | The desired Bit Length of the generated key. _Default: 2048_ | +| `key_pass` | String (Optional) | The desired passphrase for the key. | +| `owner` | String (optional) | The owner of all files created by the LWRP. _Default: "root"_ | +| `group` | String (optional) | The group of all files created by the LWRP. _Default: "root"_ | +| `mode` | String or Fixnum (Optional) | The permission mode of all files created by the LWRP. _Default: "0644"_ | + +#### 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_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`. + + +License and Author +------------------ + +Author:: Jesse Nelson () +Author:: Seth Vargo () +Author:: Charles Johnson () +Author:: Joshua Timberman () + +======= ```text -Copyright:: 2009-2011, Chef Software, Inc -Copyright:: 2014, Chef Software, Inc +Copyright:: 2009-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. diff --git a/cookbooks/openssl/libraries/helpers.rb b/cookbooks/openssl/libraries/helpers.rb new file mode 100644 index 0000000..bb81dff --- /dev/null +++ b/cookbooks/openssl/libraries/helpers.rb @@ -0,0 +1,60 @@ +module OpenSSLCookbook + # Helper functions for the OpenSSL cookbook. + module Helpers + def self.included(_base) + require 'openssl' unless defined?(OpenSSL) + end + + # Path helpers + 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 + + # Validation helpers + def key_length_valid?(number) + number >= 1024 && number & (number - 1) == 0 + end + + 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 + + def key_file_valid?(key_file_path, key_password = nil) + # Check if the key file exists + # Verify the key file contains a private key + return false unless File.exist?(key_file_path) + key = OpenSSL::PKey::RSA.new File.read(key_file_path), key_password + key.private? + end + + # Generators + def gen_dhparam(key_length, generator) + fail ArgumentError, 'Key length must be a power of 2 greater than or equal to 1024' unless key_length_valid?(key_length) + fail TypeError, 'Generator must be an integer' unless generator.is_a?(Integer) + + OpenSSL::PKey::DH.new(key_length, generator) + end + + def gen_rsa_key(key_length) + fail 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 + + # Key manipulation helpers + # Returns a pem string + def encrypt_rsa_key(rsa_key, key_password) + fail TypeError, 'rsa_key must be a Ruby OpenSSL::PKey::RSA object' unless rsa_key.is_a?(OpenSSL::PKey::RSA) + fail TypeError, 'RSA key password must be a string' unless key_password.is_a?(String) + + cipher = OpenSSL::Cipher::Cipher.new('des3') + rsa_key.to_pem(cipher, key_password) + end + end +end diff --git a/cookbooks/openssl/libraries/matchers.rb b/cookbooks/openssl/libraries/matchers.rb new file mode 100644 index 0000000..59ee84c --- /dev/null +++ b/cookbooks/openssl/libraries/matchers.rb @@ -0,0 +1,13 @@ +if defined?(ChefSpec) + def create_x509_certificate(name) + ChefSpec::Matchers::ResourceMatcher.new(:openssl_x509, :create, name) + end + + def create_dhparam_pem(name) + ChefSpec::Matchers::ResourceMatcher.new(:openssl_dhparam, :create, name) + end + + def create_rsa_key(name) + ChefSpec::Matchers::ResourceMatcher.new(:openssl_rsa_key, :create, name) + end +end diff --git a/cookbooks/openssl/libraries/random_password.rb b/cookbooks/openssl/libraries/random_password.rb new file mode 100644 index 0000000..c488301 --- /dev/null +++ b/cookbooks/openssl/libraries/random_password.rb @@ -0,0 +1,82 @@ +# +# Cookbook Name:: openssl +# Library:: random_password +# Author:: Seth Vargo +# +# Copyright 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. +# 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) + 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 + fail 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 index ee8ec7f..75f7f50 100644 --- a/cookbooks/openssl/libraries/secure_password.rb +++ b/cookbooks/openssl/libraries/secure_password.rb @@ -18,13 +18,14 @@ # limitations under the License. # -require 'openssl' +include OpenSSLCookbook::Helpers module Opscode module OpenSSL + # Generate secure passwords with OpenSSL module Password def secure_password(length = 20) - pw = String.new + pw = '' while pw.length < length pw << ::OpenSSL::Random.random_bytes(1).gsub(/\W/, '') diff --git a/cookbooks/openssl/metadata.json b/cookbooks/openssl/metadata.json index 04077bb..aef92df 100644 --- a/cookbooks/openssl/metadata.json +++ b/cookbooks/openssl/metadata.json @@ -1,31 +1 @@ -{ - "name": "openssl", - "version": "4.0.0", - "description": "Provides a library with a method for generating secure random passwords.", - "long_description": "openssl Cookbook\n================\n\nThis cookbook provides a library method to generate secure random passwords in recipes using the Ruby OpenSSL library.\n\nIt also provides an attribute-driven recipe for upgrading OpenSSL packages.\n\nRequirements\n------------\n\nThe `secure_password` works on any platform with OpenSSL Ruby bindings installed, which are a requirement for Chef anyway.\n\nThe upgrade recipe works on the following tested platforms:\n\n* Ubuntu 12.04, 14.04\n* Debian 7.4\n* CentOS 6.5\n\nIt may work on other platforms or versions of the above platforms with or without modification.\n\n[Chef Sugar](https://github.com/sethvargo/chef-sugar) was introduced as a dependency to provide helpers that make the default attribute settings (see Attributes) easier to reason about.\n\nAttributes\n----------\n\n* `node['openssl']['packages']` - An array of packages of openssl. The default attributes attempt to be smart about which packages are the default, but this may need to be changed by users of the `openssl::upgrade` recipe.\n* `node['openssl']['restart_services']` - An array of service resources that use the `node['openssl']['packages']`. This is empty by default as Chef has no reliably reasonable way to detect which applications or services are compiled against these packages. *Note* These each need to be \"`service`\" resources specified somewhere in the recipes in the node's run list.\n\nRecipes\n-------\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 `:restart` notification to service resources named by the `node['openssl']['restart_services']` attribute.\n\nUsage\n-----\n\nMost often this will be used to generate a secure password for an attribute. In a recipe:\n\n```ruby\n::Chef::Recipe.send(:include, Chef::OpenSSL::Password)\nnode.set_unless[:my_password] = secure_password\n```\n\nTo use the `openssl::upgrade` recipe, set the attributes as mentioned above. For example, we have a \"stats_collector\" service that uses openssl. It has a recipe that looks like this:\n\nLWRP\n==== \n\nThis cookbook includes an LWRP for generating Self Signed Certificates\n\n## openssl_x509\ngenerate a pem formatted x509 cert + key \n\n### Attributes\n`common_name` A String representing the `CN` ssl field\n`org` A String representing the `O` ssl field\n`org_unit` A String representing the `OU` ssl field\n`country` A String representing the `C` ssl field\n`expire` A Fixnum reprenting the number of days from _now_ to expire the cert\n`key_file` Optional A string to the key file to use. If no key is present it will generate and store one. \n`key_pass` A String that is the key's passphrase\n`key_length` A Fixnum reprenting your desired Bit Length _Default: 2048_\n`owner` The owner of the files _Default: \"root\"_\n`group` The group of the files _Default: \"root\"_\n`mode` The mode to store the files in _Default: \"0400\"_\n\n### Example usage\n\n openssl_x509 \"/tmp/mycert.pem\" do\n common_name \"www.f00bar.com\"\n org \"Foo Bar\"\n org_unit \"Lab\"\n country \"US\"\n end\n\n \nLicense and Author\n==================\n\nAuthor:: Jesse Nelson ()\nAuthor:: Joshua Timberman ()\n=======\n\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\nThis will ensure that openssl is upgraded to the latest version so the `stats_collector` service won't be exploited (hopefully!).\n\n```text\nCopyright:: 2009-2011, Chef Software, Inc\nCopyright:: 2014, 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": { - }, - "dependencies": { - "chef-sugar": ">= 0.0.0" - }, - "recommendations": { - }, - "suggestions": { - }, - "conflicting": { - }, - "providing": { - }, - "replacing": { - }, - "attributes": { - }, - "groupings": { - }, - "recipes": { - "openssl": "Empty, this cookbook provides a library, see README.md" - } -} \ No newline at end of file +{"name":"openssl","version":"4.4.0","description":"Provides a library with a method for generating secure random passwords.","long_description":"OpenSSL Cookbook\n================\n[![Build Status](https://travis-ci.org/opscode-cookbooks/openssl.svg?branch=master)](https://travis-ci.org/opscode-cookbooks/openssl)\n\nThis cookbook provides tools for working with the Ruby OpenSSL library. It includes:\n- A library method to generate secure random passwords in recipes, using the Ruby SecureRandom library.\n- An LWRP for generating RSA private keys.\n- An LWRP for generating x509 certificates.\n- An LWRP for generating dhparam.pem files.\n- An attribute-driven recipe for upgrading OpenSSL packages.\n\nRequirements\n------------\n\nThe `random_password` mixin works on any platform with the Ruby SecureRandom module. This module is already included with Chef.\n\nThe `openssl_x509`, `openssl_rsa_key` and `openssl_dhparam` LWRPs work on any platform with the OpenSSL Ruby bindings installed. These bindings are already included with Chef.\n\nThe `upgrade` recipe has been tested on the following platforms:\n\n* Ubuntu 12.04, 14.04\n* Debian 7.4\n* CentOS 6.5\n\nThe recipe may work on other platforms or different versions of the above platforms, but this has not been tested.\n\nDependencies\n------------\n\nThis cookbook depends on the [Chef Sugar](http://supermarket.chef.io/cookbooks/chef-sugar/) cookbook. [Chef Sugar](http://supermarket.chef.io/cookbooks/chef-sugar/) is used to make the default attribute settings easier to reason about. (See [Attributes](#attributes))\n\nAttributes\n----------\n\n* `node['openssl']['packages']` - An array of packages required to use openssl. The default attributes attempt to be smart about which packages are the default, but this may need to be changed by users of the `openssl::upgrade` recipe.\n* `node['openssl']['restart_services']` - An array of service resources that depend on the packages listed in the `node['openssl']['packages']` attribute. 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\nRecipes\n-------\n\n### default\n\nAn empty placeholder recipe. Takes no action.\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\nLibraries & LWRPs\n-----------------\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```ruby\nChef::Recipe.send(:include, OpenSSLCookbook::RandomPassword)\nnode.set['my_secure_attribute'] = random_password\nnode.set_unless['my_secure_attribute'] = random_password\nnode.set['my_secure_attribute'] = random_password(length: 50)\nnode.set['my_secure_attribute'] = random_password(length: 50, mode: :base64)\nnode.set['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### ~~secure_password (`Opscode::OpenSSL::Password`)~~\n\nThis library should be considered deprecated and will be removed in a future version. Please use `OpenSSLCookbook::RandomPassword` instead. The documentation is kept here for historical reasons.\n\n#### ~~Example Usage~~\n```ruby\n::Chef::Recipe.send(:include, Opscode::OpenSSL::Password)\nnode.set_unless['my_password'] = secure_password\n```\n\n~~Note that node attributes are widely accessible. Storing unencrypted passwords in node attributes, as in this example, carries risk.~~\n\n### openssl_x509\n\nThis LWRP generates self-signed, PEM-formatted x509 certificates. If no existing key is specified, the LWRP will automatically generate a passwordless key with the certificate.\n\n#### Attributes\n| Name | Type | Description |\n| ----- | ---- | ------------ |\n| `common_name` | String (Required) | Value for the `CN` certificate field. |\n| `org` | String (Required) | Value for the `O` certificate field. |\n| `org_unit` | String (Required) | Value for the `OU` certificate field. |\n| `country` | String (Required) | Value for the `C` ssl field. |\n| `expire` | Fixnum (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. |\n| `key_file` | String (Optional) | The path to a certificate key file on the filesystem. If the `key_file` attribute is specified, the LWRP will attempt to source a key from this location. If no key file is found, the LWRP will generate a new key file at this location. If the `key_file` attribute is not specified, the LWRP 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_length` | Fixnum (Optional) | The desired Bit Length of the generated key. _Default: 2048_ |\n| `owner` | String (optional) | The owner of all files created by the LWRP. _Default: \"root\"_ |\n| `group` | String (optional) | The group of all files created by the LWRP. _Default: \"root\"_ |\n| `mode` | String or Fixnum (Optional) | The permission mode of all files created by the LWRP. _Default: \"0400\"_ |\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\n### openssl_dhparam\n\nThis LWRP 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#### Attributes\n| Name | Type | Description |\n| ----- | ---- | ------------ |\n| `key_length` | Fixnum (Optional) | The desired Bit Length of the generated key. _Default: 2048_ |\n| `generator` | Fixnum (Optional) | The desired Diffie-Hellmann generator. Can be _2_ or _5_. |\n| `owner` | String (optional) | The owner of all files created by the LWRP. _Default: \"root\"_ |\n| `group` | String (optional) | The group of all files created by the LWRP. _Default: \"root\"_ |\n| `mode` | String or Fixnum (Optional) | The permission mode of all files created by the LWRP. _Default: \"0644\"_ |\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_key\n\nThis LWRP generates rsa 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\n#### Attributes\n| Name | Type | Description |\n| ----- | ---- | ------------ |\n| `key_length` | Fixnum (Optional) | The desired Bit Length of the generated key. _Default: 2048_ |\n| `key_pass` | String (Optional) | The desired passphrase for the key. |\n| `owner` | String (optional) | The owner of all files created by the LWRP. _Default: \"root\"_ |\n| `group` | String (optional) | The group of all files created by the LWRP. _Default: \"root\"_ |\n| `mode` | String or Fixnum (Optional) | The permission mode of all files created by the LWRP. _Default: \"0644\"_ |\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_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\nLicense and Author\n------------------\n\nAuthor:: Jesse Nelson () \nAuthor:: Seth Vargo () \nAuthor:: Charles Johnson () \nAuthor:: Joshua Timberman ()\n\n=======\n\n```text\nCopyright:: 2009-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","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache 2.0","platforms":{},"dependencies":{"chef-sugar":">= 3.1.1"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{"openssl":"Empty, this cookbook provides a library, see README.md","upgrade":"Upgrade OpenSSL library and restart dependent services"}} \ No newline at end of file diff --git a/cookbooks/openssl/providers/dhparam.rb b/cookbooks/openssl/providers/dhparam.rb new file mode 100644 index 0000000..4b6e4c3 --- /dev/null +++ b/cookbooks/openssl/providers/dhparam.rb @@ -0,0 +1,33 @@ +# +# dhparam.pem provider +# +# Author:: Charles Johnson +# + +include OpenSSLCookbook::Helpers + +use_inline_resources + +def whyrun_supported? + true +end + +action :create do + converge_by("Create a dhparam file #{@new_resource}") do + unless dhparam_pem_valid?(new_resource.name) + 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.name}, this may take some time" + + file new_resource.name do + action :create + owner new_resource.owner + group new_resource.group + mode new_resource.mode + sensitive true + content dhparam_content + end + end + end +end diff --git a/cookbooks/openssl/providers/rsa_key.rb b/cookbooks/openssl/providers/rsa_key.rb new file mode 100644 index 0000000..0a4dd42 --- /dev/null +++ b/cookbooks/openssl/providers/rsa_key.rb @@ -0,0 +1,39 @@ +# +# dhparam.pem provider +# +# Author:: Charles Johnson +# + +include OpenSSLCookbook::Helpers + +use_inline_resources + +def whyrun_supported? + true +end + +action :create do + converge_by("Create an RSA key #{@new_resource}") do + unless key_file_valid?(new_resource.name, new_resource.key_pass) + + log "Generating #{new_resource.key_length} bit "\ + "RSA key file at #{new_resource.name}, this may take some time" + + if new_resource.key_pass + unencrypted_rsa_key = gen_rsa_key(new_resource.key_length) + rsa_key_content = encrypt_rsa_key(unencrypted_rsa_key, new_resource.key_pass) + else + rsa_key_content = gen_rsa_key(new_resource.key_length).to_pem + end + + file new_resource.name do + action :create + owner new_resource.owner + group new_resource.group + mode new_resource.mode + sensitive true + content rsa_key_content + end + end + end +end diff --git a/cookbooks/openssl/providers/x509.rb b/cookbooks/openssl/providers/x509.rb index 120e20c..433300a 100644 --- a/cookbooks/openssl/providers/x509.rb +++ b/cookbooks/openssl/providers/x509.rb @@ -3,51 +3,61 @@ # # Author:: Jesse Nelson # -require 'openssl' + +include OpenSSLCookbook::Helpers use_inline_resources +def whyrun_supported? + true +end + attr_reader :key_file, :key, :cert, :ef -action :create do - unless ::File.exists? new_resource.name - create_keys - cert_content = cert.to_pem - key_content = key.to_pem +action :create do + converge_by("Create #{@new_resource}") do + unless ::File.exist? new_resource.name + create_keys + cert_content = cert.to_pem + key_content = key.to_pem - file new_resource.name do - action :create_if_missing - mode new_resource.mode - owner new_resource.owner - group new_resource.group - content cert_content + file new_resource.name do + action :create_if_missing + mode new_resource.mode + owner new_resource.owner + group new_resource.group + sensitive true + content cert_content + end + + file new_resource.key_file do + action :create_if_missing + mode new_resource.mode + owner new_resource.owner + group new_resource.group + sensitive true + content key_content + end + new_resource.updated_by_last_action(true) end - - file new_resource.key_file do - action :create_if_missing - mode new_resource.mode - owner new_resource.owner - group new_resource.group - content key_content - end - end end protected + # rubocop:disable Metrics/AbcSize, Style/IndentationConsistency def key_file unless new_resource.key_file - path, file= ::File.split(new_resource.name) - filename = ::File.basename(file, ::File.extname(file) ) - new_resource.key_file path + "/" + filename + ".key" + path, file = ::File.split(new_resource.name) + filename = ::File.basename(file, ::File.extname(file)) + new_resource.key_file path + '/' + filename + '.key' end new_resource.key_file end def key - @key ||= if ::File.exists? key_file - OpenSSL::PKey::RSA.new File.read(key_file), new_resource.key_pass + @key ||= if key_file_valid?(key_file, new_resource.key_pass) + OpenSSL::PKey::RSA.new ::File.read(key_file), new_resource.key_pass else OpenSSL::PKey::RSA.new(new_resource.key_length) end @@ -69,16 +79,16 @@ protected end def subject - @subject ||= "/C=" + new_resource.country + - "/O=" + new_resource.org + - "/OU=" + new_resource.org_unit + - "/CN=" + new_resource.common_name + @subject ||= '/C=' + new_resource.country + + '/O=' + new_resource.org + + '/OU=' + new_resource.org_unit + + '/CN=' + new_resource.common_name end def extensions [ - ef.create_extension("basicConstraints","CA:TRUE", true), - ef.create_extension("subjectKeyIdentifier", "hash"), + ef.create_extension('basicConstraints', 'CA:TRUE', true), + ef.create_extension('subjectKeyIdentifier', 'hash') ] end @@ -88,7 +98,7 @@ protected ef.subject_certificate = cert ef.issuer_certificate = cert cert.extensions = extensions - cert.add_extension ef.create_extension("authorityKeyIdentifier", - "keyid:always,issuer:always") - cert.sign key, OpenSSL::Digest::SHA1.new + cert.add_extension ef.create_extension('authorityKeyIdentifier', + 'keyid:always,issuer:always') + cert.sign key, OpenSSL::Digest::SHA256.new end diff --git a/cookbooks/openssl/recipes/upgrade.rb b/cookbooks/openssl/recipes/upgrade.rb index 7698e7e..c31923b 100644 --- a/cookbooks/openssl/recipes/upgrade.rb +++ b/cookbooks/openssl/recipes/upgrade.rb @@ -2,7 +2,7 @@ # Cookbook Name:: openssl # Recipe:: upgrade # -# Copyright 2014, Chef Software, Inc. +# Copyright 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. @@ -18,16 +18,18 @@ # include_recipe 'chef-sugar' -node.default['openssl']['packages'] = case - when debian_before_or_at_squeeze?, ubuntu_before_or_at_lucid? - %w{libssl0.9.8 openssl} - when debian_after_or_at_wheezy?, ubuntu_after_or_at_precise? - %w{libssl1.0.0 openssl} - when rhel? - %w{openssl} - else - [] - end +# Attributes are set here and not in attributes/default.rb because of the +# chef-sugar dependency for the methods evaluated in the case statement. +case +when debian_before_or_at_squeeze?, ubuntu_before_or_at_lucid? + node.default['openssl']['packages'] = %w(libssl0.9.8 openssl) +when debian_after_or_at_wheezy?, ubuntu_after_or_at_precise? + node.default['openssl']['packages'] = %w(libssl1.0.0 openssl) +when rhel? + node.default['openssl']['packages'] = %w(openssl) +else + node.default['openssl']['packages'] = [] +end node['openssl']['packages'].each do |ssl_pkg| package ssl_pkg do diff --git a/cookbooks/openssl/resources/dhparam.rb b/cookbooks/openssl/resources/dhparam.rb new file mode 100644 index 0000000..1a8bd14 --- /dev/null +++ b/cookbooks/openssl/resources/dhparam.rb @@ -0,0 +1,10 @@ + +actions [:create] +default_action :create + +attribute :name, :kind_of => String, :name_attribute => true +attribute :key_length, :equal_to => [1024, 2048, 4096, 8192], :default => 2048 +attribute :generator, :equal_to => [2, 5], :default => 2 +attribute :owner, :kind_of => String +attribute :group, :kind_of => String +attribute :mode, :kind_of => [Integer, String] diff --git a/cookbooks/openssl/resources/rsa_key.rb b/cookbooks/openssl/resources/rsa_key.rb new file mode 100644 index 0000000..f1e46bb --- /dev/null +++ b/cookbooks/openssl/resources/rsa_key.rb @@ -0,0 +1,10 @@ + +actions [:create] +default_action :create + +attribute :name, :kind_of => String, :name_attribute => true +attribute :key_length, :equal_to => [1024, 2048, 4096, 8192], :default => 2048 +attribute :key_pass, :kind_of => String, :default => nil +attribute :owner, :kind_of => String +attribute :group, :kind_of => String +attribute :mode, :kind_of => [Integer, String] diff --git a/cookbooks/openssl/resources/x509.rb b/cookbooks/openssl/resources/x509.rb index 77d1485..5685778 100644 --- a/cookbooks/openssl/resources/x509.rb +++ b/cookbooks/openssl/resources/x509.rb @@ -1,16 +1,16 @@ -actions [ :create ] +actions [:create] default_action :create -attribute :name, :kind_of => String, :name_attribute => true +attribute :name, :kind_of => String, :name_attribute => true attribute :owner, :kind_of => String -attribute :group, :kind_of => String -attribute :expire, :kind_of => Fixnum -attribute :mode -attribute :org, :kind_of => String, :required => true -attribute :org_unit, :kind_of => String, :required => true -attribute :country, :kind_of => String, :required => true +attribute :group, :kind_of => String +attribute :expire, :kind_of => Integer +attribute :mode, :kind_of => [Integer, String] +attribute :org, :kind_of => String, :required => true +attribute :org_unit, :kind_of => String, :required => true +attribute :country, :kind_of => String, :required => true attribute :common_name, :kind_of => String, :required => true -attribute :key_file, :kind_of => String, :default => nil -attribute :key_pass, :kind_of => String, :default => nil -attribute :key_length, :kind_of => Fixnum, :default => 2048 +attribute :key_file, :kind_of => String, :default => nil +attribute :key_pass, :kind_of => String, :default => nil +attribute :key_length, :equal_to => [1024, 2048, 4096, 8192], :default => 2048 diff --git a/cookbooks/packagecloud/0001-chef-on-amazon-2014.patch b/cookbooks/packagecloud/0001-chef-on-amazon-2014.patch deleted file mode 100644 index e653dfc..0000000 --- a/cookbooks/packagecloud/0001-chef-on-amazon-2014.patch +++ /dev/null @@ -1,65 +0,0 @@ -From e705e0beb6cd93447dec04aea8bdda004fbb8ab7 Mon Sep 17 00:00:00 2001 -From: capotej -Date: Tue, 28 Oct 2014 12:47:17 -0700 -Subject: [PATCH] chef on amazon 2014 - ---- - .kitchen.yml | 23 ++++++++++++++++++++--- - Gemfile | 1 + - 2 files changed, 21 insertions(+), 3 deletions(-) - -diff --git a/.kitchen.yml b/.kitchen.yml -index a389d99..fbebe56 100644 ---- a/.kitchen.yml -+++ b/.kitchen.yml -@@ -25,7 +25,7 @@ platforms: - - name: ubuntu-14.04 - driver_config: - box: opscode-ubuntu-14.04 -- box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/opscode_ubuntu-14.04_provisionerless.box -+ box_url: http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-14.04_chef-provisionerless.box - run_list: - - recipe[packagecloud_test::trusty_deps] - - recipe[packagecloud_test::deb] -@@ -56,7 +56,24 @@ platforms: - - recipe[packagecloud_test::rpm] - - recipe[packagecloud_test::rubygems_private] - -+- name: amazon-2014.09 -+ driver_plugin: ec2 -+ driver_config: -+ image_id: ami-b5a7ea85 -+ username: ec2-user -+ aws_access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> -+ aws_secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> -+ aws_ssh_key_id: <%= ENV['AWS_KEYPAIR_NAME'] %> -+ ssh_key: <%= ENV['AWS_SSH_KEY_PATH'] %> -+ availability_zone: us-west-2a -+ region: us-west-2 -+ flavor_id: t2.micro -+ security_group_ids: sg-598e583c -+ run_list: -+ - recipe[packagecloud_test::rpm] -+ - recipe[packagecloud_test::rubygems] -+ - suites: - - name: default -- run_list: -- attributes: {} -+run_list: -+attributes: {} -diff --git a/Gemfile b/Gemfile -index 9ce1223..9b9ee17 100644 ---- a/Gemfile -+++ b/Gemfile -@@ -2,6 +2,7 @@ source 'https://rubygems.org' - - gem 'rake' - gem 'berkshelf', '~> 3.1.4' -+gem 'kitchen-ec2' - - group :test do - gem 'foodcritic', '~> 4.0.0' --- -1.9.2 - diff --git a/cookbooks/packagecloud/CHANGELOG.md b/cookbooks/packagecloud/CHANGELOG.md index d5f156d..a6002f3 100644 --- a/cookbooks/packagecloud/CHANGELOG.md +++ b/cookbooks/packagecloud/CHANGELOG.md @@ -2,6 +2,12 @@ packagecloud =============== This is the Changelog for the packagecloud cookbook +v0.2.0 (2015-02-17) +------------------- +Rework GPG paths to support new GPG endpoints for repos with repo-specific GPG +keys. Old endpoints/URLs still work, too. + + v0.0.1 (2014-06-05) ------------------- Initial release. diff --git a/cookbooks/packagecloud/Gemfile b/cookbooks/packagecloud/Gemfile index 9b9ee17..51dbdc7 100644 --- a/cookbooks/packagecloud/Gemfile +++ b/cookbooks/packagecloud/Gemfile @@ -3,6 +3,7 @@ source 'https://rubygems.org' gem 'rake' gem 'berkshelf', '~> 3.1.4' gem 'kitchen-ec2' +gem 'stove' group :test do gem 'foodcritic', '~> 4.0.0' diff --git a/cookbooks/packagecloud/README.md b/cookbooks/packagecloud/README.md index e16c92b..f9d32b8 100644 --- a/cookbooks/packagecloud/README.md +++ b/cookbooks/packagecloud/README.md @@ -2,6 +2,8 @@ This cookbook provides an LWRP for installing https://packagecloud.io repositories. +NOTE: Please see the Changelog below for important changes if upgrading from 0.0.19 to 0.1.0. + ## Usage Be sure to depend on `packagecloud` in `metadata.rb` so that the packagecloud @@ -25,6 +27,7 @@ end ``` For packagecloud:enterprise users, add `base_url` to your resource: + ``` packagecloud_repo "computology/packagecloud-cookbook-test-private" do base_url "https://packages.example.com" @@ -33,6 +36,16 @@ packagecloud_repo "computology/packagecloud-cookbook-test-private" do end ``` +For forcing the os and dist for repository install: + +``` +packagecloud_repo 'computology/packagecloud-cookbook-test-public' do + type 'rpm' + force_os 'rhel' + force_dist '6.5' +end +``` + Valid options for `type` include `deb`, `rpm`, and `gem`. ## Interactions with other cookbooks @@ -60,5 +73,19 @@ the yum chef cookbook is set to the system default, unless you use the `cachedir`, you should make sure to setup packagecloud repos after that resource is set so that the GPG keys end up in the right place. +## Changelog + +packagecloud cookbook versions 0.0.19 used an attribute called +`default['packagecloud']['hostname']` for caching the local machine's hostname +to avoid regenerating read tokens. + +This attribute has been removed as it is confusing and in some edge cases, +buggy. + +Beginning in 0.1.0, you can use +`default['packagecloud']['hostname_override']` to specify a hostname if ohai +is unable to determine the hostname of the node on its own. + + ## Credits Computology, LLC. diff --git a/cookbooks/packagecloud/THANKS b/cookbooks/packagecloud/THANKS index 06242b2..81877d1 100644 --- a/cookbooks/packagecloud/THANKS +++ b/cookbooks/packagecloud/THANKS @@ -3,3 +3,4 @@ The following people have contributed to packagecloud chef cookbook (If you're n THANKS ------ Guilhem Lettron (@guilhem) +Michael S. Fischer (@mfischer-zd) diff --git a/cookbooks/packagecloud/attributes/default.rb b/cookbooks/packagecloud/attributes/default.rb index 3d34858..21b1d16 100644 --- a/cookbooks/packagecloud/attributes/default.rb +++ b/cookbooks/packagecloud/attributes/default.rb @@ -1,5 +1,6 @@ default['packagecloud']['base_repo_path'] = "/install/repositories/" -default['packagecloud']['gpg_key_path'] = "/gpg.key" +default['packagecloud']['gpg_key_path'] = "/gpgkey" +default['packagecloud']['hostname_override'] = nil default['packagecloud']['default_type'] = value_for_platform_family( 'debian' => 'deb', diff --git a/cookbooks/packagecloud/metadata.json b/cookbooks/packagecloud/metadata.json index 58fa0f9..e5d00e7 100644 --- a/cookbooks/packagecloud/metadata.json +++ b/cookbooks/packagecloud/metadata.json @@ -35,7 +35,14 @@ "recipes": { }, - "version": "0.0.18", - "source_url": "", - "issues_url": "" + "version": "0.2.0", + "source_url": "https://github.com/computology/packagecloud-cookbook", + "issues_url": "https://github.com/computology/packagecloud-cookbook/issues", + "privacy": false, + "chef_versions": [ + + ], + "ohai_versions": [ + + ] } diff --git a/cookbooks/packagecloud/metadata.rb b/cookbooks/packagecloud/metadata.rb index eedc2b9..32e6d79 100644 --- a/cookbooks/packagecloud/metadata.rb +++ b/cookbooks/packagecloud/metadata.rb @@ -4,4 +4,6 @@ maintainer_email 'joe@packagecloud.io' license 'Apache 2.0' description 'Installs/Configures packagecloud.io repositories.' long_description 'Installs/Configures packagecloud.io repositories.' -version '0.0.18' +version '0.2.0' +source_url 'https://github.com/computology/packagecloud-cookbook' if respond_to?(:source_url) +issues_url 'https://github.com/computology/packagecloud-cookbook/issues' if respond_to?(:issues_url) diff --git a/cookbooks/packagecloud/providers/repo.rb b/cookbooks/packagecloud/providers/repo.rb index 045901d..c6c23e7 100644 --- a/cookbooks/packagecloud/providers/repo.rb +++ b/cookbooks/packagecloud/providers/repo.rb @@ -17,19 +17,34 @@ action :add do end end +def gpg_url(base_url, repo, format, master_token) + base_install_url = ::File.join(base_url, node['packagecloud']['base_repo_path']) + ext = (format == :deb) ? 'list' : 'repo' + gpg_key_url_endpoint = construct_uri_with_options({base_url: base_install_url, repo: repo, endpoint: "gpg_key_url.#{ext}"}) + if !master_token.nil? + gpg_key_url_endpoint.user = master_token + gpg_key_url_endpoint.password = '' + end + + URI(get(gpg_key_url_endpoint, install_endpoint_params).body.chomp) +end + def install_deb base_url = new_resource.base_url repo_url = construct_uri_with_options({base_url: base_url, repo: new_resource.repository, endpoint: node['platform']}) Chef::Log.debug("#{new_resource.name} deb repo url = #{repo_url}") + package 'wget' package 'apt-transport-https' + repo_url = read_token(repo_url) + template "/etc/apt/sources.list.d/#{filename}.list" do source 'apt.erb' cookbook 'packagecloud' mode '0644' - variables :base_url => read_token(repo_url).to_s, + variables :base_url => repo_url.to_s, :distribution => node['lsb']['codename'], :component => 'main' @@ -37,10 +52,10 @@ def install_deb notifies :run, "execute[apt-get-update-#{filename}]", :immediately end - gpg_key_url = ::File.join(base_url, node['packagecloud']['gpg_key_path']) + gpg_url = gpg_url(new_resource.base_url, new_resource.repository, :deb, new_resource.master_token) execute "apt-key-add-#{filename}" do - command "wget -qO - #{gpg_key_url} | apt-key add -" + command "wget --auth-no-challenge -qO - #{gpg_url.to_s} | apt-key add -" action :nothing end @@ -54,13 +69,9 @@ end def install_rpm given_base_url = new_resource.base_url - base_repo_url = ::File.join(given_base_url, node['packagecloud']['base_repo_path']) - base_url_endpoint = construct_uri_with_options({base_url: base_repo_url, repo: new_resource.repository, endpoint: 'rpm_base_url'}) - gpg_filename = URI.parse(base_repo_url).host.gsub!('.', '_') - if new_resource.master_token base_url_endpoint.user = new_resource.master_token base_url_endpoint.password = '' @@ -91,18 +102,15 @@ def install_rpm not_if 'rpm -qa | grep -qw pygpgme' end - remote_file "/etc/pki/rpm-gpg/RPM-GPG-KEY-#{gpg_filename}" do - source ::File.join(given_base_url, node['packagecloud']['gpg_key_path']) - mode '0644' - end + gpg_url = gpg_url(new_resource.base_url, new_resource.repository, :rpm, new_resource.master_token) template "/etc/yum.repos.d/#{filename}.repo" do source 'yum.erb' cookbook 'packagecloud' mode '0644' - variables :base_url => read_token(base_url).to_s, - :gpg_filename => gpg_filename, + variables :base_url => base_url.to_s, :name => filename, + :gpg_url => gpg_url.to_s, :repo_gpgcheck => 1, :description => filename, :priority => new_resource.priority, @@ -138,6 +146,7 @@ def install_gem end end + def read_token(repo_url, gems=false) return repo_url unless new_resource.master_token @@ -163,19 +172,27 @@ def read_token(repo_url, gems=false) end def install_endpoint_params - dist = value_for_platform_family( + dist = new_resource.force_dist || value_for_platform_family( 'debian' => node['lsb']['codename'], ['rhel', 'fedora'] => node['platform_version'], ) - if node['fqdn'].nil? - Chef::Log.fatal("This node's fqdn is set to nil, so a read token cannot be issued!" \ - "Please change your fqdn settings.") + hostname = node['packagecloud']['hostname_override'] || + node['fqdn'] || + node['hostname'] + + if !hostname + raise("Can't determine hostname! Set node['packagecloud']['hostname_override'] " \ + "if it cannot be automatically determined by Ohai.") end - { :os => node['platform'], + { :os => os_platform, :dist => dist, - :name => node['fqdn'] } + :name => hostname } +end + +def os_platform + new_resource.force_os || node['platform'] end def filename @@ -203,5 +220,5 @@ def construct_uri_with_options(options) end def append_trailing_slash(str) - str.end_with?("/") ? str : str << "/" + str.end_with?("/") ? str : str + "/" end diff --git a/cookbooks/packagecloud/resources/repo.rb b/cookbooks/packagecloud/resources/repo.rb index 6167e15..783223f 100644 --- a/cookbooks/packagecloud/resources/repo.rb +++ b/cookbooks/packagecloud/resources/repo.rb @@ -3,8 +3,9 @@ default_action :add attribute :repository, :kind_of => String, :name_attribute => true attribute :master_token, :kind_of => String +attribute :force_os, :kind_of => String +attribute :force_dist, :kind_of => String attribute :type, :kind_of => String, :equal_to => ['deb', 'rpm', 'gem'], :default => node['packagecloud']['default_type'] attribute :base_url, :kind_of => String, :default => "https://packagecloud.io" -attribute :gpg_key_url, :kind_of => String, :default => node['packagecloud']['gpg_key_url'] attribute :priority, :kind_of => [Fixnum, TrueClass, FalseClass], :default => false attribute :metadata_expire, :kind_of => String, :regex => [/^\d+[d|h|m]?$/], :default => nil diff --git a/cookbooks/packagecloud/templates/default/yum.erb b/cookbooks/packagecloud/templates/default/yum.erb index f862018..81c3f68 100644 --- a/cookbooks/packagecloud/templates/default/yum.erb +++ b/cookbooks/packagecloud/templates/default/yum.erb @@ -7,7 +7,7 @@ priority=<%=@priority %> <% end -%> gpgcheck=0 enabled=1 -gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-<%= @gpg_filename %> +gpgkey=<%= @gpg_url %> sslverify=1 sslcacert=/etc/pki/tls/certs/ca-bundle.crt <% if @metadata_expire %> diff --git a/cookbooks/partial_search/CHANGELOG.md b/cookbooks/partial_search/CHANGELOG.md index 5f12087..92503bf 100644 --- a/cookbooks/partial_search/CHANGELOG.md +++ b/cookbooks/partial_search/CHANGELOG.md @@ -2,27 +2,43 @@ partial_search Cookbook CHANGELOG ================================= This file is used to list changes made in each version of the partial_search cookbook. +v1.0.9 (2015-10-21) +------------------- +------------------- +* Updated description to clarify that this cookbook is no longer needed for chef-client 12.0 +* Updated .gitignore file +* Added .foodcritic file to exclude rules that don't apply +* Added Test Kitchen config +* Added Chef standard Rubocop config +* Added Travis CI testing to use Chef DK +* Added Berksfile +* Added Gemfile with the latest development dependencies +* Updated contributing and testing docs +* Added maintainers.md and maintainers.toml files +* Added Travis and cookbook version badges to the readme +* 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 basic convergence Chefspec test v1.0.8 (2014-02-25) ------------------- - [COOK-4260] Update compatibility in README.md - v1.0.6 ------ - **Hotfix** - Revert client-side caching bug - v1.0.4 ------ ### New Feature -- **[COOK-2584](https://tickets.opscode.com/browse/COOK-2584)** - Add client-side result cache - +- **[COOK-2584](https://tickets.chef.io/browse/COOK-2584)** - Add client-side result cache v1.0.2 ------ ### Bug - - [COOK-3164]: `partial_search` should use `Chef::Config[:chef_server_url]` instead of `search_url` diff --git a/cookbooks/partial_search/README.md b/cookbooks/partial_search/README.md index 9efe16e..0d9a90f 100644 --- a/cookbooks/partial_search/README.md +++ b/cookbooks/partial_search/README.md @@ -1,7 +1,10 @@ Partial Search Cookbook ======================= -[Partial Search](http://docs.opscode.com/essentials_search.html#partial-search) -is a search API available on Chef Server. (see Notes below for version compatibility) +[![Build Status](https://travis-ci.org/chef-cookbooks/partial_search.svg?branch=master)](http://travis-ci.org/chef-cookbooks/partial_search) +[![Cookbook Version](https://img.shields.io/cookbook/v/partial_search.svg)](https://supermarket.chef.io/cookbooks/partial_search) + +[Partial Search](http://docs.chef.io/essentials_search.html#partial-search) +is a search API available on Chef Server. (see Notes below for version compatibility) It can be used to reduce the network bandwidth and the memory used by chef-client to process search results. @@ -9,14 +12,13 @@ This cookbook provides an experimental interface to the partial search API by providing a `partial_search` method that can be used instead of the `search` method in your recipes. -Since Chef Client 11.10.0 the partial_search capability has been built-in -so it does not require this cookbook. - The `partial_search` method allows you to retrieve just the attributes of interest. For example, you can execute a search to return just the name and IP addresses of the nodes in your infrastructure rather than receiving an array of complete node objects and post-processing them. +NOTE: Since Chef Client 12.0 the partial_search capability has been built-in +so it does not require this cookbook. Install ------- @@ -62,11 +64,11 @@ Notes License & Authors ----------------- -- Author:: Adam Jacob () -- Author:: John Keiser () +- Author:: Adam Jacob () +- Author:: John Keiser () ```text -Copyright:: 2012-2013, Opscode, Inc. +Copyright:: 2012-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. diff --git a/cookbooks/partial_search/libraries/partial_search.rb b/cookbooks/partial_search/libraries/partial_search.rb index f506548..5a29368 100644 --- a/cookbooks/partial_search/libraries/partial_search.rb +++ b/cookbooks/partial_search/libraries/partial_search.rb @@ -1,7 +1,7 @@ # -# Author:: Adam Jacob () -# Author:: John Keiser () -# Copyright:: Copyright (c) 2012 Opscode, Inc. +# Author:: Adam Jacob () +# Author:: John Keiser () +# Copyright:: Copyright (c) 2012 Chef Software, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,17 +29,16 @@ require 'chef/data_bag_item' class Chef class PartialSearch - attr_accessor :rest - def initialize(url=nil) + def initialize(url = nil) @rest = ::Chef::REST.new(url || ::Chef::Config[:chef_server_url]) end # Search Solr for objects of a given type, for a given query. If you give # it a block, it will handle the paging for you dynamically. - def search(type, query='*:*', args={}, &block) - raise ArgumentError, "Type must be a string or a symbol!" unless (type.kind_of?(String) || type.kind_of?(Symbol)) + def search(type, query = '*:*', args = {}, &block) + fail ArgumentError, 'Type must be a string or a symbol!' unless type.is_a?(String) || type.is_a?(Symbol) sort = args.include?(:sort) ? args[:sort] : 'X_CHEF_id_CHEF_X asc' start = args.include?(:start) ? args[:start] : 0 @@ -53,31 +52,32 @@ class Chef response_rows = response['rows'] end if block - response_rows.each { |o| block.call(o) unless o.nil?} - unless (response["start"] + response_rows.length) >= response["total"] - nstart = response["start"] + rows + response_rows.each { |o| block.call(o) unless o.nil? } + unless (response['start'] + response_rows.length) >= response['total'] + nstart = response['start'] + rows args_hash = { - :keys => args[:keys], - :sort => sort, - :start => nstart, - :rows => rows + keys: args[:keys], + sort: sort, + start: nstart, + rows: rows } search(type, query, args_hash, &block) end true else - [ response_rows, response["start"], response["total"] ] + [response_rows, response['start'], response['total']] end end def list_indexes - response = @rest.get_rest("search") + @rest.get_rest('search') end private - def escape(s) - s && URI.escape(s.to_s) - end + + def escape(s) + s && URI.escape(s.to_s) + end end end @@ -123,7 +123,7 @@ end # puts "#{node[:name]}: #{node[:ip]}" # end # -def partial_search(type, query='*:*', *args, &block) +def partial_search(type, query = '*:*', *args, &block) # Support both the old (positional args) and new (hash args) styles of calling if args.length == 1 && args[0].is_a?(Hash) args_hash = args[0] @@ -138,7 +138,7 @@ def partial_search(type, query='*:*', *args, &block) Chef::PartialSearch.new.search(type, query, args_hash, &block) # Otherwise, do the iteration for the end user else - results = Array.new + results = [] Chef::PartialSearch.new.search(type, query, args_hash) do |o| results << o end diff --git a/cookbooks/partial_search/metadata.json b/cookbooks/partial_search/metadata.json index eca0a08..f1aa073 100644 --- a/cookbooks/partial_search/metadata.json +++ b/cookbooks/partial_search/metadata.json @@ -1,29 +1 @@ -{ - "name": "partial_search", - "version": "1.0.8", - "description": "Provides experimental interface to partial search API in Opscode Hosted Chef", - "long_description": "Partial Search Cookbook\n=======================\n[Partial Search](http://docs.opscode.com/essentials_search.html#partial-search)\nis a search API available on Chef Server. (see Notes below for version compatibility) \nIt can be used to reduce the network bandwidth and the memory used by\nchef-client to process search results.\n\nThis cookbook provides an experimental interface to the partial search\nAPI by providing a `partial_search` method that can be used instead of\nthe `search` method in your recipes.\n\nSince Chef Client 11.10.0 the partial_search capability has been built-in\nso it does not require this cookbook.\n\nThe `partial_search` method allows you to retrieve just the attributes\nof interest. For example, you can execute a search to return just the\nname and IP addresses of the nodes in your infrastructure rather than\nreceiving an array of complete node objects and post-processing them.\n\n\nInstall\n-------\nUpload this cookbook and include it in the dependencies of any\ncookbook where you would like to use `partial_search`.\n\n\nUsage\n-----\nWhen you call `partial_search`, you need to specify the key paths of the\nattributes you want returned. Key paths are specified as an array\nof strings. Each key path is mapped to a short name of your\nchoosing. Consider the following example:\n\n```ruby\npartial_search(:node, 'role:web',\n :keys => { 'name' => [ 'name' ],\n 'ip' => [ 'ipaddress' ],\n 'kernel_version' => [ 'kernel', 'version' ]\n }\n).each do |result|\n puts result['name']\n puts result['ip']\n puts result['kernel_version']\nend\n```\n\nIn the example above, two attributes will be extracted (on the\nserver) from the nodes that match the search query. The result will\nbe a simple hash with keys 'name' and 'ip'.\n\n\nNotes\n-----\n* We would like your feedback on this feature and the interface\n provided by this cookbook. Please send comments to the chef-dev\n mailing list.\n\n* The partial search API is available in the Open Source Chef Server since 11.0.4\n\n* The partial search API is available in Enterprise Chef Server since 1.2.2\n\n\nLicense & Authors\n-----------------\n- Author:: Adam Jacob ()\n- Author:: John Keiser ()\n\n```text\nCopyright:: 2012-2013, Opscode, 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": "Opscode, Inc.", - "maintainer_email": "cookbooks@opscode.com", - "license": "Apache 2.0", - "platforms": { - }, - "dependencies": { - }, - "recommendations": { - }, - "suggestions": { - }, - "conflicting": { - }, - "providing": { - }, - "replacing": { - }, - "attributes": { - }, - "groupings": { - }, - "recipes": { - } -} \ No newline at end of file +{"name":"partial_search","version":"1.0.9","description":"Provides experimental interface to partial search API in Chef Software Hosted Chef for Chef-Client pre-12.0","long_description":"Partial Search Cookbook\n=======================\n[![Build Status](https://travis-ci.org/chef-cookbooks/partial_search.svg?branch=master)](http://travis-ci.org/chef-cookbooks/partial_search)\n[![Cookbook Version](https://img.shields.io/cookbook/v/partial_search.svg)](https://supermarket.chef.io/cookbooks/partial_search)\n\n[Partial Search](http://docs.chef.io/essentials_search.html#partial-search)\nis a search API available on Chef Server. (see Notes below for version compatibility)\nIt can be used to reduce the network bandwidth and the memory used by\nchef-client to process search results.\n\nThis cookbook provides an experimental interface to the partial search\nAPI by providing a `partial_search` method that can be used instead of\nthe `search` method in your recipes.\n\nThe `partial_search` method allows you to retrieve just the attributes\nof interest. For example, you can execute a search to return just the\nname and IP addresses of the nodes in your infrastructure rather than\nreceiving an array of complete node objects and post-processing them.\n\nNOTE: Since Chef Client 12.0 the partial_search capability has been built-in\nso it does not require this cookbook.\n\nInstall\n-------\nUpload this cookbook and include it in the dependencies of any\ncookbook where you would like to use `partial_search`.\n\n\nUsage\n-----\nWhen you call `partial_search`, you need to specify the key paths of the\nattributes you want returned. Key paths are specified as an array\nof strings. Each key path is mapped to a short name of your\nchoosing. Consider the following example:\n\n```ruby\npartial_search(:node, 'role:web',\n :keys => { 'name' => [ 'name' ],\n 'ip' => [ 'ipaddress' ],\n 'kernel_version' => [ 'kernel', 'version' ]\n }\n).each do |result|\n puts result['name']\n puts result['ip']\n puts result['kernel_version']\nend\n```\n\nIn the example above, two attributes will be extracted (on the\nserver) from the nodes that match the search query. The result will\nbe a simple hash with keys 'name' and 'ip'.\n\n\nNotes\n-----\n* We would like your feedback on this feature and the interface\n provided by this cookbook. Please send comments to the chef-dev\n mailing list.\n\n* The partial search API is available in the Open Source Chef Server since 11.0.4\n\n* The partial search API is available in Enterprise Chef Server since 1.2.2\n\n\nLicense & Authors\n-----------------\n- Author:: Adam Jacob ()\n- Author:: John Keiser ()\n\n```text\nCopyright:: 2012-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","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache 2.0","platforms":{},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file diff --git a/cookbooks/partial_search/metadata.rb b/cookbooks/partial_search/metadata.rb deleted file mode 100644 index 23d01f0..0000000 --- a/cookbooks/partial_search/metadata.rb +++ /dev/null @@ -1,7 +0,0 @@ -name "partial_search" -maintainer "Opscode, Inc." -maintainer_email "cookbooks@opscode.com" -license "Apache 2.0" -description "Provides experimental interface to partial search API in Opscode Hosted Chef" -long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) -version "1.0.8" diff --git a/cookbooks/php-fpm/README.md b/cookbooks/php-fpm/README.md new file mode 100644 index 0000000..081ce4a --- /dev/null +++ b/cookbooks/php-fpm/README.md @@ -0,0 +1,97 @@ +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 +--------- + +* apt (leverages apt_repository LWRP) +* yum (leverages yum_repository LWRP) + +The `apt_repository` and `yum_repository` LWRPs are used from these cookbooks to create the proper repository entries so the php-fpm package downloaded and installed. + +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-fpm.org/wiki/Configuration_File). + +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" => [ + { + :name => "default" + }, + { + :name => "www", + :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 +``` + +License and Author +================== + +Author:: Seth Chisamore () + +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. diff --git a/cookbooks/php-fpm/attributes/default.rb b/cookbooks/php-fpm/attributes/default.rb new file mode 100644 index 0000000..6c2263a --- /dev/null +++ b/cookbooks/php-fpm/attributes/default.rb @@ -0,0 +1,43 @@ +if node.platform_family == "rhel" + 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" + conf_dir = "/etc/php5/fpm/conf.d" + pool_conf_dir = "/etc/php5/fpm/pool.d" + if node.platform == "ubuntu" and node.platform_version.to_f <= 10.04 + conf_file = "/etc/php5/fpm/php5-fpm.conf" + else + conf_file = "/etc/php5/fpm/php-fpm.conf" + end + error_log = "/var/log/php5-fpm.log" + pid ="/var/run/php5-fpm.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']['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']['pools'] = [ + { + :name => "www" + } +] + +default['php-fpm']['skip_repository_install'] = false + +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" 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..eb3a597 --- /dev/null +++ b/cookbooks/php-fpm/definitions/php_fpm_pool.rb @@ -0,0 +1,62 @@ +# +# Cookbook Name:: php-fpm +# Definition:: php_fpm_pool +# +# Copyright 2008-2009, 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. +# + +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 00644 + cookbook params[:cookbook] || "php-fpm" + variables( + :pool_name => pool_name, + :listen => params[:listen], + :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], + :group => params[:group], + :process_manager => params[:process_manager], + :max_children => params[:max_children], + :start_servers => params[:start_servers], + :min_spare_servers => params[:min_spare_servers], + :max_spare_servers => params[:max_spare_servers], + :max_requests => params[:max_requests], + :catch_workers_output => params[:catch_workers_output], + :security_limit_extensions => params[:security_limit_extensions] || node['php-fpm']['security_limit_extensions'], + :php_options => params[:php_options] || {}, + :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..d35cdb8 --- /dev/null +++ b/cookbooks/php-fpm/metadata.json @@ -0,0 +1,37 @@ +{ + "name": "php-fpm", + "version": "0.6.10", + "description": "Installs/Configures php-fpm", + "long_description": "Description\n===========\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\nRequirements\n============\n\nPlatform\n--------\n\n* Debian, Ubuntu\n* CentOS, Red Hat, Fedora\n* Amazon Linux\n\nCookbooks\n---------\n\n* apt (leverages apt_repository LWRP)\n* yum (leverages yum_repository LWRP)\n\nThe `apt_repository` and `yum_repository` LWRPs are used from these cookbooks to create the proper repository entries so the php-fpm package downloaded and installed.\n\nDescription\n==========\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-fpm.org/wiki/Configuration_File).\n\nUsage\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```ruby\nname \"php-fpm\"\ndescription \"php fpm role\"\nrun_list \"recipe[php-fpm]\"\noverride_attributes \"php-fpm\" => {\n\t\"pools\" => [\n\t\t{\n\t\t\t:name => \"default\"\n\t\t},\n\t\t{\n\t\t\t:name => \"www\",\n\t\t\t:cookbook => \"another-cookbook\",\n\t\t\t:process_manager => \"dynamic\",\n\t\t\t:max_requests => 5000,\n\t\t\t:php_options => { 'php_admin_flag[log_errors]' => 'on', 'php_admin_value[memory_limit]' => '32M' }\n\t\t}\n\t]\n}\n```\n\nCreating pools in recipes\n=========================\n### Create PHP-FPM pool named 'www' with default settings:\n```ruby\nphp_fpm_pool \"www\"\n```\n\n### Create PHP-FPM pool named 'www' with custom settings:\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```ruby\nphp_fpm_pool \"www\" do\n enable false\nend\n```\n\nLicense and Author\n==================\n\nAuthor:: Seth Chisamore ()\n\nCopyright:: 2011, Opscode, 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", + "maintainer": "Opscode, Inc.", + "maintainer_email": "cookbooks@opscode.com", + "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" + }, + "dependencies": { + "apt": ">= 0.0.0", + "yum": ">= 3.0.0" + }, + "recommendations": { + }, + "suggestions": { + }, + "conflicting": { + }, + "providing": { + }, + "replacing": { + }, + "attributes": { + }, + "groupings": { + }, + "recipes": { + } +} \ No newline at end of file diff --git a/cookbooks/php-fpm/metadata.rb b/cookbooks/php-fpm/metadata.rb new file mode 100644 index 0000000..d69aeac --- /dev/null +++ b/cookbooks/php-fpm/metadata.rb @@ -0,0 +1,14 @@ +name "php-fpm" +maintainer "Opscode, Inc." +maintainer_email "cookbooks@opscode.com" +license "Apache 2.0" +description "Installs/Configures php-fpm" +long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) +version "0.6.10" + +depends "apt" +depends "yum", ">= 3.0" + +%w{ debian ubuntu centos redhat fedora amazon }.each do |os| + supports os +end diff --git a/cookbooks/php-fpm/recipes/configure.rb b/cookbooks/php-fpm/recipes/configure.rb new file mode 100644 index 0000000..097e577 --- /dev/null +++ b/cookbooks/php-fpm/recipes/configure.rb @@ -0,0 +1,37 @@ +# +# Author:: Seth Chisamore () +# Cookbook Name:: php-fpm +# Recipe:: package +# +# 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. +# + +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| + php_fpm_pool pool[:name] do + pool.each do |k, v| + self.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..80e91d7 --- /dev/null +++ b/cookbooks/php-fpm/recipes/default.rb @@ -0,0 +1,22 @@ +# +# Author:: Seth Chisamore () +# Cookbook Name:: php-fpm +# Recipe:: 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. +# + +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..e0a51c8 --- /dev/null +++ b/cookbooks/php-fpm/recipes/install.rb @@ -0,0 +1,53 @@ +# +# Author:: Seth Chisamore () +# Cookbook Name:: php-fpm +# Recipe:: package +# +# 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. +# + +include_recipe 'php-fpm::repository' unless node['php-fpm']['skip_repository_install'] + +if node['php-fpm']['package_name'].nil? + if platform_family?("rhel") + php_fpm_package_name = "php-fpm" + else + php_fpm_package_name = "php5-fpm" + end +else + php_fpm_package_name = node['php-fpm']['package_name'] +end + +package php_fpm_package_name do + action :upgrade +end + +if node['php-fpm']['service_name'].nil? + php_fpm_service_name = php_fpm_package_name +else + php_fpm_service_name = node['php-fpm']['service_name'] +end + +service_provider = nil +if node['platform'] == 'ubuntu' and node['platform_version'].to_f >= 13.10 + service_provider = ::Chef::Provider::Service::Upstart +end + +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..bbb2e39 --- /dev/null +++ b/cookbooks/php-fpm/recipes/repository.rb @@ -0,0 +1,84 @@ +# +# Author:: Seth Chisamore () +# Cookbook Name:: php-fpm +# Recipe:: package +# +# 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. +# + +case node['platform'] +when 'ubuntu' + if node['platform_version'].to_f <= 10.04 + # Configure Brian's PPA + # We'll install php5-fpm from the Brian's PPA backports + apt_repository "brianmercer-php" do + uri "http://ppa.launchpad.net/brianmercer/php/ubuntu" + distribution node['lsb']['codename'] + components ["main"] + keyserver "keyserver.ubuntu.com" + key "8D0DC64F" + action :add + end + # FIXME: apt-get update didn't trigger in above + execute "apt-get update" + end +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 >= 7.0 + apt_repository "dotdeb" do + uri "http://packages.dotdeb.org" + distribution "stable" + components ['all'] + key "http://www.dotdeb.org/dotdeb.gpg" + action :add + end + elsif node.platform_version.to_f >= 6.0 + apt_repository "dotdeb" do + uri "http://packages.dotdeb.org" + distribution "squeeze" + components ['all'] + key "http://www.dotdeb.org/dotdeb.gpg" + action :add + end + else + apt_repository "dotdeb" do + uri "http://packages.dotdeb.org" + distribution "oldstable" + components ['all'] + key "http://www.dotdeb.org/dotdeb.gpg" + action :add + end + apt_repository "dotdeb-php53" do + uri "http://php53.dotdeb.org" + distribution "oldstable" + components ['all'] + key "http://www.dotdeb.org/dotdeb.gpg" + action :add + end + end + +when 'amazon', 'fedora', 'centos', 'redhat' + unless platform?('centos', 'redhat') && node['platform_version'].to_f >= 6.4 + 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/templates/default/php-fpm.conf.erb b/cookbooks/php-fpm/templates/default/php-fpm.conf.erb new file mode 100644 index 0000000..900eb7c --- /dev/null +++ b/cookbooks/php-fpm/templates/default/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/default/pool.conf.erb b/cookbooks/php-fpm/templates/default/pool.conf.erb new file mode 100644 index 0000000..cfa0de9 --- /dev/null +++ b/cookbooks/php-fpm/templates/default/pool.conf.erb @@ -0,0 +1,412 @@ +; 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 || node['php-fpm']['user'] %> +group = <%= @group || node['php-fpm']['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 || "/var/run/php-fpm-#{@pool_name}.sock" %> + +; 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 || "0660" %> + +; 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 || "ondemand" %> + +; 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 || 50 %> + +<% 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 || 5 %> + +; 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 || 35 %> +<% 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 || 500 %> + +; 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 +;access.log = log/$pool.access.log + +; 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 +;slowlog = log/$pool.log.slow + +; 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 +;request_slowlog_timeout = 0 + +; 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 = 0 + +; 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 || "no" %> + +; 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 || ".php" %> + +; 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 index ece8dcb..b56c711 100644 --- a/cookbooks/php/CHANGELOG.md +++ b/cookbooks/php/CHANGELOG.md @@ -2,6 +2,31 @@ php Cookbook CHANGELOG ====================== This file is used to list changes made in each version of the php cookbook. +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 diff --git a/cookbooks/php/README.md b/cookbooks/php/README.md index df386de..cdd1195 100644 --- a/cookbooks/php/README.md +++ b/cookbooks/php/README.md @@ -1,6 +1,11 @@ php Cookbook ============ -Installs and configures PHP 5.3 and the PEAR package management system. Also includes LWRPs for managing PEAR (and PECL) packages along with PECL channels. + +[![Join the chat at https://gitter.im/opscode-cookbooks/php](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/opscode-cookbooks/php?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Cookbook Version](https://img.shields.io/cookbook/v/php.svg)](https://supermarket.chef.io/cookbooks/php) +[![Build Status](https://travis-ci.org/opscode-cookbooks/php.svg?branch=master)](https://travis-ci.org/opscode-cookbooks/php) + +Installs and configures PHP 5.3 and the PEAR package management system. Also includes LWRPs for managing PEAR (and PECL) packages, PECL channels, and PHP-FPM pools. Requirements ------------ @@ -150,6 +155,42 @@ php_pear "YAML" do 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: http://php.net/manual/en/install.fpm.php + +#### 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 + http://php.net/manual/en/install.fpm.configuration.php. 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: `/` + +#### Examples +```ruby +# Install a FPM pool named "default" +php_fpm_pool "default" do + action :install +end +``` Recipes ------- @@ -244,12 +285,12 @@ This section details "quick development" steps. For a detailed explanation, see License & Authors ----------------- -- Author:: Seth Chisamore () -- Author:: Joshua Timberman () +- Author:: Seth Chisamore () +- Author:: Joshua Timberman () - Author:: Julian C. Dunn () ```text -Copyright:: 2013, Chef Software, Inc. +Copyright:: 2013-2014, 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. @@ -269,29 +310,29 @@ Microsoft Windows platform only to correct an (upstream bug)[http://pear.php.net `go-pear.phar` is licensed under the (PHP License version 2.02)[http://www.php.net/license/2_02.txt]: ``` --------------------------------------------------------------------- +-------------------------------------------------------------------- The PHP License, version 2.02 Copyright (c) 1999 - 2002 The PHP Group. All rights reserved. --------------------------------------------------------------------- +-------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without modification, is permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following + notice, this list of conditions and the following disclaimer. + + 2. 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. - - 3. The name "PHP" must not be used to endorse or promote products - derived from this software without prior permission from the + + 3. The name "PHP" must not be used to endorse or promote products + derived from this software without prior permission from the PHP Group. This does not apply to add-on libraries or tools that work in conjunction with PHP. In such a case the PHP name may be used to indicate that the product supports PHP. - + 4. The PHP Group may publish revised and/or new versions of the license from time to time. Each version will be given a distinguishing version number. @@ -318,30 +359,30 @@ are met: modify the Zend Engine, or any portion thereof, your use of the separated or modified Zend Engine software shall not be governed by this license, and instead shall be governed by the license - set forth at http://www.zend.com/license/ZendLicense/. + set forth at http://www.zend.com/license/ZendLicense/. -THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND +THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP -DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +DEVELOPMENT TEAM OR ITS 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. --------------------------------------------------------------------- +-------------------------------------------------------------------- This software consists of voluntary contributions made by many individuals on behalf of the PHP Group. The PHP Group can be contacted via Email at group@php.net. -For more information on the PHP Group and the PHP project, +For more information on the PHP Group and the PHP project, please see . ``` diff --git a/cookbooks/php/attributes/default.rb b/cookbooks/php/attributes/default.rb index 2c67f7d..233322d 100644 --- a/cookbooks/php/attributes/default.rb +++ b/cookbooks/php/attributes/default.rb @@ -1,9 +1,9 @@ # -# Author:: Seth Chisamore () +# Author:: Seth Chisamore () # Cookbook Name:: php # Attribute:: default # -# Copyright 2011, Opscode, Inc. +# Copyright 2011-2014, 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. @@ -34,23 +34,51 @@ when 'rhel', 'fedora' default['php']['fpm_user'] = 'nobody' default['php']['fpm_group'] = 'nobody' default['php']['ext_dir'] = "/usr/#{lib_dir}/php/modules" + 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 mhash-devel) if node['platform_version'].to_f < 6 - default['php']['packages'] = %w{ php53 php53-devel php53-cli php-pear } + default['php']['packages'] = %w(php53 php53-devel php53-cli php-pear) + default['php']['mysql']['package'] = 'php53-mysql' else - default['php']['packages'] = %w{ php php-devel php-cli php-pear } + default['php']['packages'] = %w(php php-devel php-cli php-pear) + default['php']['mysql']['package'] = 'php-mysql' + default['php']['fpm_package'] = 'php-fpm' + 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' + end end when 'debian' default['php']['conf_dir'] = '/etc/php5/cli' - default['php']['ext_conf_dir'] = '/etc/php5/conf.d' + case node['platform'] + when 'ubuntu' + if node['platform_version'].to_f >= 12.10 + default['php']['ext_conf_dir'] = '/etc/php5/mods-available' + else + default['php']['ext_conf_dir'] = '/etc/php5/conf.d' + end + else + default['php']['ext_conf_dir'] = '/etc/php5/conf.d' + end + 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']['packages'] = %w(php5-cgi php5 php5-dev php5-cli php-pear) + default['php']['mysql']['package'] = 'php5-mysql' + 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']['packages'] = %w{ php5-cgi php5 php5-dev php5-cli php-pear } + default['php']['fpm_service'] = 'php5-fpm' + default['php']['fpm_default_conf'] = '/etc/php5/fpm/pool.d/www.conf' 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) default['php']['fpm_user'] = 'wwwrun' default['php']['fpm_group'] = 'www' - default['php']['packages'] = %w{ apache2-mod_php5 php5-pear } + default['php']['packages'] = %w(apache2-mod_php5 php5-pear) + default['php']['mysql']['package'] = 'php5-mysql' lib_dir = node['kernel']['machine'] =~ /x86_64/ ? 'lib64' : 'lib' when 'windows' default['php']['windows']['msi_name'] = 'PHP 5.3.28' @@ -59,24 +87,34 @@ when 'windows' default['php']['conf_dir'] = 'C:\Program Files (x86)\PHP' default['php']['ext_conf_dir'] = node['php']['conf_dir'] # These extensions are installed by default by the GUI MSI - default['php']['packages'] = %w{ cgi ScriptExecutable PEAR - iis4FastCGI ext_php_bz2 ext_php_curl - ext_php_exif ext_php_gd2 ext_php_gettext - ext_php_gmp ext_php_imap ext_php_mbstring - ext_php_mysql ext_php_mysqli ext_php_openssl - ext_php_pdo_mysql ext_php_pdo_odbc ext_php_pdo_sqlite - ext_php_pgsql ext_php_soap ext_php_sockets - ext_php_sqlite3 ext_php_tidy ext_php_xmlrpc - } - default['php']['package_options'] = "" # Use this to customise your yum or apt command + default['php']['packages'] = %w(cgi ScriptExecutable PEAR + iis4FastCGI ext_php_bz2 ext_php_curl + ext_php_exif ext_php_gd2 ext_php_gettext + ext_php_gmp ext_php_imap ext_php_mbstring + ext_php_mysql ext_php_mysqli ext_php_openssl + ext_php_pdo_mysql ext_php_pdo_odbc ext_php_pdo_sqlite + ext_php_pgsql ext_php_soap ext_php_sockets + ext_php_sqlite3 ext_php_tidy ext_php_xmlrpc + ) + default['php']['package_options'] = '' # Use this to customise your yum or apt command default['php']['pear'] = 'pear.bat' default['php']['pecl'] = 'pecl.bat' +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']['packages'] = %w( php56 pear ) + default['php']['mysql']['package'] = 'php56-mysqli' else 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) default['php']['fpm_user'] = 'www-data' default['php']['fpm_group'] = 'www-data' - default['php']['packages'] = %w{ php5-cgi php5 php5-dev php5-cli php-pear } + default['php']['packages'] = %w(php5-cgi php5 php5-dev php5-cli php-pear) + default['php']['mysql']['package'] = 'php5-mysql' end default['php']['url'] = 'http://us1.php.net/get' @@ -84,7 +122,7 @@ default['php']['version'] = '5.5.9' default['php']['checksum'] = '378de162efdaeeb725ed38d7fe956c9f0b9084ff' default['php']['prefix_dir'] = '/usr/local' -default['php']['configure_options'] = %W{--prefix=#{php['prefix_dir']} +default['php']['configure_options'] = %W(--prefix=#{php['prefix_dir']} --with-libdir=#{lib_dir} --with-config-file-path=#{php['conf_dir']} --with-config-file-scan-dir=#{php['ext_conf_dir']} @@ -120,7 +158,7 @@ default['php']['configure_options'] = %W{--prefix=#{php['prefix_dir']} --with-mysql-sock --with-sqlite3 --with-pdo-mysql - --with-pdo-sqlite} + --with-pdo-sqlite) -default['php']['ini']['template'] = "php.ini.erb" -default['php']['ini']['cookbook'] = "php" +default['php']['ini']['template'] = 'php.ini.erb' +default['php']['ini']['cookbook'] = 'php' diff --git a/cookbooks/php/libraries/helpers.rb b/cookbooks/php/libraries/helpers.rb index f58873e..24d9fcb 100644 --- a/cookbooks/php/libraries/helpers.rb +++ b/cookbooks/php/libraries/helpers.rb @@ -1,5 +1,5 @@ # -# Author:: Joshua Timberman () +# Author:: Joshua Timberman () # Cookbook Name:: php # Libraries:: helpers # diff --git a/cookbooks/php/libraries/matchers.rb b/cookbooks/php/libraries/matchers.rb new file mode 100644 index 0000000..3546e5f --- /dev/null +++ b/cookbooks/php/libraries/matchers.rb @@ -0,0 +1,35 @@ +if defined?(ChefSpec) + ChefSpec.define_matcher :php_pear + def install_php_pear(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:php_pear, :install, resource_name) + end + + def remove_php_pear(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:php_pear, :remove, resource_name) + end + + def upgrade_php_pear(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:php_pear, :upgrade, resource_name) + end + + def purge_php_pear(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:php_pear, :purge, resource_name) + end + + ChefSpec.define_matcher :php_pear_channel + def discover_php_pear_channel(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:php_pear_channel, :discover, resource_name) + end + + def remove_php_pear_channel(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:php_pear_channel, :remove, resource_name) + end + + def update_php_pear_channel(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:php_pear_channel, :update, resource_name) + end + + def add_php_pear_channel(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:php_pear_channel, :add, resource_name) + end +end diff --git a/cookbooks/php/metadata.json b/cookbooks/php/metadata.json index 63fbf2f..0f77757 100644 --- a/cookbooks/php/metadata.json +++ b/cookbooks/php/metadata.json @@ -1,57 +1 @@ -{ - "name": "php", - "version": "1.5.0", - "description": "Installs and maintains php and php modules", - "long_description": "", - "maintainer": "Opscode, Inc.", - "maintainer_email": "cookbooks@opscode.com", - "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", - "scientific": ">= 0.0.0", - "amazon": ">= 0.0.0", - "windows": ">= 0.0.0", - "oracle": ">= 0.0.0" - }, - "dependencies": { - "build-essential": ">= 0.0.0", - "xml": ">= 0.0.0", - "mysql": ">= 0.0.0", - "yum-epel": ">= 0.0.0", - "windows": ">= 0.0.0", - "iis": ">= 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.", - "php::module_apc": "Install the php5-apc package", - "php::module_curl": "Install the php5-curl package", - "php::module_fileinfo": "Install the php5-fileinfo package", - "php::module_fpdf": "Install the php-fpdf package", - "php::module_gd": "Install the php5-gd package", - "php::module_ldap": "Install the php5-ldap package", - "php::module_memcache": "Install the php5-memcache package", - "php::module_mysql": "Install the php5-mysql package", - "php::module_pgsql": "Install the php5-pgsql packag", - "php::module_sqlite3": "Install the php5-sqlite3 package" - } -} \ No newline at end of file +{"name":"php","version":"1.7.2","description":"Installs and maintains php and php modules","long_description":"","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@getchef.com","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","scientific":">= 0.0.0","amazon":">= 0.0.0","windows":">= 0.0.0","oracle":">= 0.0.0"},"dependencies":{"build-essential":">= 0.0.0","xml":">= 0.0.0","mysql":">= 6.0.0","yum-epel":">= 0.0.0","windows":">= 0.0.0","iis":">= 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.","php::module_apc":"Install the php5-apc package","php::module_curl":"Install the php5-curl package","php::module_fileinfo":"Install the php5-fileinfo package","php::module_fpdf":"Install the php-fpdf package","php::module_gd":"Install the php5-gd package","php::module_ldap":"Install the php5-ldap package","php::module_memcache":"Install the php5-memcache package","php::module_mysql":"Install the php5-mysql package","php::module_pgsql":"Install the php5-pgsql packag","php::module_sqlite3":"Install the php5-sqlite3 package"}} \ No newline at end of file diff --git a/cookbooks/php/metadata.rb b/cookbooks/php/metadata.rb deleted file mode 100644 index 18259d0..0000000 --- a/cookbooks/php/metadata.rb +++ /dev/null @@ -1,31 +0,0 @@ -name 'php' -maintainer 'Opscode, Inc.' -maintainer_email 'cookbooks@opscode.com' -license 'Apache 2.0' -description 'Installs and maintains php and php modules' -version '1.5.0' - -depends 'build-essential' -depends 'xml' -depends 'mysql' -depends 'yum-epel' -depends 'windows' -depends 'iis' - -%w{ debian ubuntu centos redhat fedora scientific amazon windows oracle }.each do |os| - supports os -end - -recipe 'php', 'Installs php' -recipe 'php::package', 'Installs php using packages.' -recipe 'php::source', 'Installs php from source.' -recipe 'php::module_apc', 'Install the php5-apc package' -recipe 'php::module_curl', 'Install the php5-curl package' -recipe 'php::module_fileinfo', 'Install the php5-fileinfo package' -recipe 'php::module_fpdf', 'Install the php-fpdf package' -recipe 'php::module_gd', 'Install the php5-gd package' -recipe 'php::module_ldap', 'Install the php5-ldap package' -recipe 'php::module_memcache', 'Install the php5-memcache package' -recipe 'php::module_mysql', 'Install the php5-mysql package' -recipe 'php::module_pgsql', 'Install the php5-pgsql packag' -recipe 'php::module_sqlite3', 'Install the php5-sqlite3 package' diff --git a/cookbooks/php/providers/fpm_pool.rb b/cookbooks/php/providers/fpm_pool.rb new file mode 100644 index 0000000..c44df54 --- /dev/null +++ b/cookbooks/php/providers/fpm_pool.rb @@ -0,0 +1,86 @@ +# +# Author:: Chris Marchesi +# Cookbook Name:: php +# Provider:: fpm_pool +# +# Copyright:: 2015, 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. +# + +def whyrun_supported? + true +end + +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' + + if node['php']['fpm_package'].nil? + raise 'PHP-FPM package not found (you probably have an unsupported distro)' + else + 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']}]" + end + end +end + +def register_fpm_service + service node['php']['fpm_service'] do + action :enable + end +end + +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? + t = 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_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_package']}]" + end + new_resource.updated_by_last_action(t.updated_by_last_action?) +end + +action :uninstall do + # Ensure the FPM pacakge is installed, and the service is registered + register_fpm_service + # Delete the FPM pool. + f = file "#{node['php']['fpm_pooldir']}/#{new_resource.pool_name}" do + action :delete + end + new_resource.updated_by_last_action(f.updated_by_last_action?) +end diff --git a/cookbooks/php/providers/pear.rb b/cookbooks/php/providers/pear.rb index ae5a63d..a21715b 100644 --- a/cookbooks/php/providers/pear.rb +++ b/cookbooks/php/providers/pear.rb @@ -1,9 +1,9 @@ # -# Author:: Seth Chisamore +# Author:: Seth Chisamore # Cookbook Name:: php # Provider:: pear_package # -# Copyright:: 2011, Opscode, Inc +# 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. @@ -64,7 +64,6 @@ action :remove do Chef::Log.info("Removing #{@new_resource}") remove_package(@current_resource.package_name, @new_resource.version) end - else end end @@ -117,10 +116,9 @@ end def current_installed_version @current_installed_version ||= begin - v = nil version_check_cmd = "#{@bin} -d " - version_check_cmd << " preferred_state=#{can_haz(@new_resource, "preferred_state")}" - version_check_cmd << " list#{expand_channel(can_haz(@new_resource, "channel"))}" + version_check_cmd << " preferred_state=#{can_haz(@new_resource, 'preferred_state')}" + version_check_cmd << " list#{expand_channel(can_haz(@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 @@ -131,9 +129,9 @@ end def candidate_version @candidate_version ||= begin candidate_version_cmd = "#{@bin} -d " - candidate_version_cmd << "preferred_state=#{can_haz(@new_resource, "preferred_state")}" - candidate_version_cmd << " search#{expand_channel(can_haz(@new_resource, "channel"))}" - candidate_version_cmd << "#{@new_resource.package_name}" + candidate_version_cmd << "preferred_state=#{can_haz(@new_resource, 'preferred_state')}" + candidate_version_cmd << " search#{expand_channel(can_haz(@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 @@ -142,32 +140,47 @@ def candidate_version end def install_package(name, version) - command = "echo \"\r\" | #{@bin} -d" - command << " preferred_state=#{can_haz(@new_resource, "preferred_state")}" + command = "printf \"\r\" | #{@bin} -d" + command << " preferred_state=#{can_haz(@new_resource, 'preferred_state')}" command << " install -a#{expand_options(@new_resource.options)}" - command << " #{prefix_channel(can_haz(@new_resource, "channel"))}#{name}" + command << " #{prefix_channel(can_haz(@new_resource, 'channel'))}#{name}" command << "-#{version}" if version && !version.empty? pear_shell_out(command) manage_pecl_ini(name, :create, can_haz(@new_resource, 'directives'), can_haz(@new_resource, 'zend_extensions')) if pecl? + enable_package(name) end def upgrade_package(name, version) - command = "echo \"\r\" | #{@bin} -d" - command << " preferred_state=#{can_haz(@new_resource, "preferred_state")}" + command = "printf \"\r\" | #{@bin} -d" + command << " preferred_state=#{can_haz(@new_resource, 'preferred_state')}" command << " upgrade -a#{expand_options(@new_resource.options)}" - command << " #{prefix_channel(can_haz(@new_resource, "channel"))}#{name}" + command << " #{prefix_channel(can_haz(@new_resource, 'channel'))}#{name}" command << "-#{version}" if version && !version.empty? pear_shell_out(command) manage_pecl_ini(name, :create, can_haz(@new_resource, 'directives'), can_haz(@new_resource, 'zend_extensions')) if pecl? + enable_package(name) end def remove_package(name, version) command = "#{@bin} uninstall" command << " #{expand_options(@new_resource.options)}" - command << " #{prefix_channel(can_haz(@new_resource, "channel"))}#{name}" + command << " #{prefix_channel(can_haz(@new_resource, 'channel'))}#{name}" command << "-#{version}" if version && !version.empty? pear_shell_out(command) - manage_pecl_ini(name, :delete) if pecl? + disable_package(name) + manage_pecl_ini(name, :delete, nil, nil) if pecl? +end + +def enable_package(name) + execute "/usr/sbin/php5enmod #{name}" do + only_if { platform?('ubuntu') && node['platform_version'].to_f >= 12.04 && ::File.exist?('/usr/sbin/php5enmod') } + end +end + +def disable_package(name) + execute "/usr/sbin/php5dismod #{name}" do + only_if { platform?('ubuntu') && node['platform_version'].to_f >= 12.04 && ::File.exist?('/usr/sbin/php5dismod') } + end end def pear_shell_out(command) @@ -216,14 +229,21 @@ def manage_pecl_ini(name, action, directives, zend_extensions) 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 + 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' @@ -259,9 +279,9 @@ def pecl? @pecl ||= begin # search as a pear first since most 3rd party channels will report pears as pecls! - search_args = String.new - search_args << " -d preferred_state=#{can_haz(@new_resource, "preferred_state")}" - search_args << " search#{expand_channel(can_haz(@new_resource, "channel"))} #{@new_resource.package_name}" + search_args = '' + search_args << " -d preferred_state=#{can_haz(@new_resource, 'preferred_state')}" + search_args << " search#{expand_channel(can_haz(@new_resource, 'channel'))} #{@new_resource.package_name}" if grep_for_version(shell_out(node['php']['pear'] + search_args).stdout, @new_resource.package_name) false diff --git a/cookbooks/php/providers/pear_channel.rb b/cookbooks/php/providers/pear_channel.rb index 34ab648..daa4f48 100644 --- a/cookbooks/php/providers/pear_channel.rb +++ b/cookbooks/php/providers/pear_channel.rb @@ -1,9 +1,9 @@ # -# Author:: Seth Chisamore +# Author:: Seth Chisamore # Cookbook Name:: php # Provider:: pear_channel # -# Copyright:: 2011, Opscode, Inc +# 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. @@ -84,10 +84,8 @@ end private def exists? - begin - shell_out!("#{node['php']['pear']} channel-info #{@current_resource.channel_name}") - true - rescue Mixlib::ShellOut::ShellCommandFailed - false - end + shell_out!("#{node['php']['pear']} channel-info #{@current_resource.channel_name}") + true +rescue Mixlib::ShellOut::ShellCommandFailed + false end diff --git a/cookbooks/php/recipes/default.rb b/cookbooks/php/recipes/default.rb index 38ca7f4..e94b6c4 100644 --- a/cookbooks/php/recipes/default.rb +++ b/cookbooks/php/recipes/default.rb @@ -1,10 +1,10 @@ # -# Author:: Joshua Timberman () -# Author:: Seth Chisamore () +# Author:: Joshua Timberman () +# Author:: Seth Chisamore () # Cookbook Name:: php # Recipe:: default # -# Copyright 2009-2011, Opscode, Inc. +# Copyright 2009-2014, 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. @@ -30,4 +30,4 @@ php_pear_channel 'pecl.php.net' do action :update end -include_recipe "php::ini" +include_recipe 'php::ini' diff --git a/cookbooks/php/recipes/ini.rb b/cookbooks/php/recipes/ini.rb index b3d737a..ee0f15e 100644 --- a/cookbooks/php/recipes/ini.rb +++ b/cookbooks/php/recipes/ini.rb @@ -3,7 +3,7 @@ # Cookbook Name:: php # Recipe:: ini # -# Copyright 2011, Opscode, Inc. +# Copyright 2011-2014, 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. @@ -19,12 +19,12 @@ # template "#{node['php']['conf_dir']}/php.ini" do - source node['php']['ini']['template'] - cookbook node['php']['ini']['cookbook'] - unless platform?('windows') - owner 'root' - group 'root' - mode '0644' - end - variables(:directives => node['php']['directives']) + source node['php']['ini']['template'] + cookbook node['php']['ini']['cookbook'] + unless platform?('windows') + owner 'root' + group node['root_group'] + mode '0644' + end + variables(:directives => node['php']['directives']) end diff --git a/cookbooks/php/recipes/module_apc.rb b/cookbooks/php/recipes/module_apc.rb index e45d7eb..a3b69ab 100644 --- a/cookbooks/php/recipes/module_apc.rb +++ b/cookbooks/php/recipes/module_apc.rb @@ -1,10 +1,10 @@ # -# Author:: Joshua Timberman () -# Author:: Seth Chisamore () +# Author:: Joshua Timberman () +# Author:: Seth Chisamore () # Cookbook Name:: php # Recipe:: module_apc # -# Copyright 2009-2011, Opscode, Inc. +# Copyright 2009-2014, 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. @@ -21,7 +21,7 @@ case node['platform_family'] when 'rhel', 'fedora' - %w{ httpd-devel pcre pcre-devel }.each do |pkg| + %w(httpd-devel pcre pcre-devel).each do |pkg| package pkg do action :install end diff --git a/cookbooks/php/recipes/module_curl.rb b/cookbooks/php/recipes/module_curl.rb index 3848672..7fa7abd 100644 --- a/cookbooks/php/recipes/module_curl.rb +++ b/cookbooks/php/recipes/module_curl.rb @@ -1,10 +1,10 @@ # -# Author:: Joshua Timberman () -# Author:: Seth Chisamore () +# Author:: Joshua Timberman () +# Author:: Seth Chisamore () # Cookbook Name:: php # Recipe:: module_curl # -# Copyright 2009-2011, Opscode, Inc. +# Copyright 2009-2014, 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. diff --git a/cookbooks/php/recipes/module_fpdf.rb b/cookbooks/php/recipes/module_fpdf.rb index 519fe93..673de15 100644 --- a/cookbooks/php/recipes/module_fpdf.rb +++ b/cookbooks/php/recipes/module_fpdf.rb @@ -1,10 +1,10 @@ # -# Author:: Joshua Timberman () -# Author:: Seth Chisamore () +# Author:: Joshua Timberman () +# Author:: Seth Chisamore () # Cookbook Name:: php # Recipe:: module_fpdf # -# Copyright 2009-2011, Opscode, Inc. +# Copyright 2009-2014, 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. diff --git a/cookbooks/php/recipes/module_gd.rb b/cookbooks/php/recipes/module_gd.rb index 1482323..4236389 100644 --- a/cookbooks/php/recipes/module_gd.rb +++ b/cookbooks/php/recipes/module_gd.rb @@ -1,10 +1,10 @@ # -# Author:: Joshua Timberman () -# Author:: Seth Chisamore () +# Author:: Joshua Timberman () +# Author:: Seth Chisamore () # Cookbook Name:: php # Recipe:: module_gd # -# Copyright 2009-2011, Opscode, Inc. +# Copyright 2009-2014, 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. @@ -24,6 +24,9 @@ pkg = value_for_platform( el5_range => 'php53-gd', 'default' => 'php-gd' }, + 'freebsd' => { + 'default' => 'php56-gd' + }, 'default' => 'php5-gd' ) diff --git a/cookbooks/php/recipes/module_ldap.rb b/cookbooks/php/recipes/module_ldap.rb index bb919ed..0b8e8bf 100644 --- a/cookbooks/php/recipes/module_ldap.rb +++ b/cookbooks/php/recipes/module_ldap.rb @@ -1,10 +1,10 @@ # -# Author:: Joshua Timberman () -# Author:: Seth Chisamore () +# Author:: Joshua Timberman () +# Author:: Seth Chisamore () # Cookbook Name:: php # Recipe:: module_ldap # -# Copyright 2009-2011, Opscode, Inc. +# Copyright 2009-2014, 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. diff --git a/cookbooks/php/recipes/module_memcache.rb b/cookbooks/php/recipes/module_memcache.rb index 8f3669c..4c05266 100644 --- a/cookbooks/php/recipes/module_memcache.rb +++ b/cookbooks/php/recipes/module_memcache.rb @@ -1,10 +1,10 @@ # -# Author:: Joshua Timberman () -# Author:: Seth Chisamore () +# Author:: Joshua Timberman () +# Author:: Seth Chisamore () # Cookbook Name:: php # Recipe:: module_memcache # -# Copyright 2009-2011, Opscode, Inc. +# Copyright 2009-2014, 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. @@ -21,7 +21,7 @@ case node['platform_family'] when 'rhel', 'fedora' - %w{ zlib-devel }.each do |pkg| + %w(zlib-devel).each do |pkg| package pkg do action :install end diff --git a/cookbooks/php/recipes/module_mysql.rb b/cookbooks/php/recipes/module_mysql.rb index 44a8b80..7b7d2ab 100644 --- a/cookbooks/php/recipes/module_mysql.rb +++ b/cookbooks/php/recipes/module_mysql.rb @@ -1,10 +1,10 @@ # -# Author:: Joshua Timberman () -# Author:: Seth Chisamore () +# Author:: Joshua Timberman () +# Author:: Seth Chisamore () # Cookbook Name:: php # Recipe:: module_mysql # -# Copyright 2009-2011, Opscode, Inc. +# Copyright 2009-2014, 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. @@ -19,14 +19,6 @@ # limitations under the License. # -pkg = value_for_platform( - %w(centos redhat scientific fedora amazon oracle) => { - el5_range => 'php53-mysql', - 'default' => 'php-mysql' - }, - 'default' => 'php5-mysql' -) - -package pkg do +package node['php']['mysql']['package'] do action :install end diff --git a/cookbooks/php/recipes/module_pgsql.rb b/cookbooks/php/recipes/module_pgsql.rb index fef279e..f7837d8 100644 --- a/cookbooks/php/recipes/module_pgsql.rb +++ b/cookbooks/php/recipes/module_pgsql.rb @@ -1,10 +1,10 @@ # -# Author:: Joshua Timberman () -# Author:: Seth Chisamore () +# Author:: Joshua Timberman () +# Author:: Seth Chisamore () # Cookbook Name:: php # Recipe:: module_pgsql # -# Copyright 2009-2011, Opscode, Inc. +# Copyright 2009-2014, 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. diff --git a/cookbooks/php/recipes/module_sqlite3.rb b/cookbooks/php/recipes/module_sqlite3.rb index 2542d52..5d887c1 100644 --- a/cookbooks/php/recipes/module_sqlite3.rb +++ b/cookbooks/php/recipes/module_sqlite3.rb @@ -1,10 +1,10 @@ # -# Author:: Joshua Timberman () -# Author:: Seth Chisamore () +# Author:: Joshua Timberman () +# Author:: Seth Chisamore () # Cookbook Name:: php # Recipe:: module_sqlite3 # -# Copyright 2009-2011, Opscode, Inc. +# Copyright 2009-2014, 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. diff --git a/cookbooks/php/recipes/package.rb b/cookbooks/php/recipes/package.rb index 890c83b..06799ef 100644 --- a/cookbooks/php/recipes/package.rb +++ b/cookbooks/php/recipes/package.rb @@ -1,10 +1,10 @@ # -# Author:: Seth Chisamore () -# Author:: Lucas Hansen () +# Author:: Seth Chisamore () +# Author:: Lucas Hansen () # Cookbook Name:: php # Recipe:: package # -# Copyright 2013, Opscode, Inc. +# Copyright 2013-2014, 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. @@ -28,11 +28,11 @@ if platform?('windows') source node['php']['windows']['msi_source'] installer_type :msi - options %W[ - /quiet - INSTALLDIR="#{install_dir}" - ADDLOCAL=#{node['php']['packages'].join(',')} - ].join(' ') + options %W( + /quiet + INSTALLDIR="#{install_dir}" + ADDLOCAL=#{node['php']['packages'].join(',')} + ).join(' ') end # WARNING: This is not the out-of-the-box go-pear.phar. It's been modified to patch this bug: @@ -63,4 +63,4 @@ else end end -include_recipe "php::ini" +include_recipe 'php::ini' diff --git a/cookbooks/php/recipes/recompile.rb b/cookbooks/php/recipes/recompile.rb new file mode 100644 index 0000000..1a090cd --- /dev/null +++ b/cookbooks/php/recipes/recompile.rb @@ -0,0 +1,51 @@ +# +# Author:: David Kinzer () +# Cookbook Name:: php +# Recipe:: recompile +# +# Copyright 2014, 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 "#{node['php']['url']}/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 && make install) + EOF +end diff --git a/cookbooks/php/recipes/source.rb b/cookbooks/php/recipes/source.rb index 4805034..9825911 100644 --- a/cookbooks/php/recipes/source.rb +++ b/cookbooks/php/recipes/source.rb @@ -1,9 +1,9 @@ # -# Author:: Seth Chisamore () +# Author:: Seth Chisamore () # Cookbook Name:: php # Recipe:: package # -# Copyright 2011, Opscode, Inc. +# Copyright 2011-2014, 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. @@ -22,16 +22,14 @@ configure_options = node['php']['configure_options'].join(' ') include_recipe 'build-essential' include_recipe 'xml' -include_recipe 'mysql::client' if configure_options =~ /mysql/ include_recipe 'yum-epel' if node['platform_family'] == 'rhel' -pkgs = value_for_platform_family( - %w{ rhel fedora } => %w{ bzip2-devel libc-client-devel curl-devel freetype-devel gmp-devel libjpeg-devel krb5-devel libmcrypt-devel libpng-devel openssl-devel t1lib-devel mhash-devel }, - %w{ debian ubuntu } => %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' => %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 } - ) +mysql_client 'default' do + action :create + only_if { configure_options =~ /mysql/ } +end -pkgs.each do |pkg| +node['php']['src_deps'].each do |pkg| package pkg do action :install end @@ -82,4 +80,4 @@ directory node['php']['ext_conf_dir'] do recursive true end -include_recipe "php::ini" +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..0a6c6ab --- /dev/null +++ b/cookbooks/php/resources/fpm_pool.rb @@ -0,0 +1,34 @@ +# +# Author:: Chris Marchesi +# Cookbook Name:: php +# Resource:: fpm_pool +# +# Copyright:: 2015, 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. +# + +default_action :install +actions :install, :uninstall + +attribute :pool_name, :kind_of => String, :name_attribute => true +attribute :listen, :default => '/var/run/php5-fpm.sock' +attribute :user, :kind_of => String, :default => node['php']['fpm_user'] +attribute :group, :kind_of => String, :default => node['php']['fpm_user'] +attribute :process_manager, :kind_of => String, :default => 'dynamic' +attribute :max_children, :kind_of => Integer, :default => 5 +attribute :start_servers, :kind_of => Integer, :default => 2 +attribute :min_spare_servers, :kind_of => Integer, :default => 1 +attribute :max_spare_servers, :kind_of => Integer, :default => 3 +attribute :chdir, :kind_of => String, :default => '/' +attribute :additional_config, :kind_of => Hash, :default => {} diff --git a/cookbooks/php/resources/pear.rb b/cookbooks/php/resources/pear.rb index d548531..9052393 100644 --- a/cookbooks/php/resources/pear.rb +++ b/cookbooks/php/resources/pear.rb @@ -1,9 +1,9 @@ # -# Author:: Seth Chisamore +# Author:: Seth Chisamore # Cookbook Name:: php # Resource:: pear_package # -# Copyright:: 2011, Opscode, Inc +# Copyright:: 2011-2014, 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. @@ -21,6 +21,14 @@ default_action :install actions :install, :upgrade, :remove, :purge +state_attrs :channel, + :directives, + :options, + :package_name, + :preferred_state, + :version, + :zend_extensions + attribute :package_name, :kind_of => String, :name_attribute => true attribute :version, :default => nil attribute :channel, :kind_of => String diff --git a/cookbooks/php/resources/pear_channel.rb b/cookbooks/php/resources/pear_channel.rb index 2a88f05..33c33f9 100644 --- a/cookbooks/php/resources/pear_channel.rb +++ b/cookbooks/php/resources/pear_channel.rb @@ -1,9 +1,9 @@ # -# Author:: Seth Chisamore +# Author:: Seth Chisamore # Cookbook Name:: php # Resource:: pear_channel # -# Copyright:: 2011, Opscode, Inc +# Copyright:: 2011-2014, 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. @@ -21,6 +21,9 @@ default_action :discover actions :discover, :add, :update, :remove +state_attrs :channel_name, + :channel_xml + attribute :channel_name, :kind_of => String, :name_attribute => true attribute :channel_xml, :kind_of => String diff --git a/cookbooks/php/templates/centos/php.ini.erb b/cookbooks/php/templates/centos/php.ini.erb index c84d60d..a9e5d16 100644 --- a/cookbooks/php/templates/centos/php.ini.erb +++ b/cookbooks/php/templates/centos/php.ini.erb @@ -1221,5 +1221,5 @@ soap.wsdl_cache_ttl=86400 ; End: <% @directives.sort_by { |key, val| key }.each do |directive, value| -%> -<%= "#{directive}=\"#{value}\"" %> +<%= "#{directive}=#{value}" %> <% end -%> diff --git a/cookbooks/php/templates/debian/php.ini.erb b/cookbooks/php/templates/debian/php.ini.erb index 1bd0a47..9588925 100644 --- a/cookbooks/php/templates/debian/php.ini.erb +++ b/cookbooks/php/templates/debian/php.ini.erb @@ -1853,5 +1853,5 @@ ldap.max_links = -1 ; End: <% @directives.sort_by { |key, val| key }.each do |directive, value| -%> -<%= "#{directive}=\"#{value}\"" %> +<%= "#{directive}=#{value}" %> <% end -%> diff --git a/cookbooks/php/templates/default/extension.ini.erb b/cookbooks/php/templates/default/extension.ini.erb index 11a9830..13c5122 100644 --- a/cookbooks/php/templates/default/extension.ini.erb +++ b/cookbooks/php/templates/default/extension.ini.erb @@ -3,5 +3,5 @@ <%= 'zend_' if zend %>extension=<%= filepath %> <% end -%> <% @directives.each do |k,v| -%> -<%= "#{@name}.#{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..aa01b8f --- /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_user %> +listen.group = <%= @fpm_pool_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 index 55efd4c..7fcb3b7 100644 --- a/cookbooks/php/templates/default/php.ini.erb +++ b/cookbooks/php/templates/default/php.ini.erb @@ -1896,5 +1896,5 @@ ldap.max_links = -1 ; End: <% @directives.sort_by { |key, val| key }.each do |directive, value| -%> -<%= "#{directive}=\"#{value}\"" %> +<%= "#{directive}=#{value}" %> <% end -%> diff --git a/cookbooks/php/templates/redhat/php.ini.erb b/cookbooks/php/templates/redhat/php.ini.erb index c84d60d..a9e5d16 100644 --- a/cookbooks/php/templates/redhat/php.ini.erb +++ b/cookbooks/php/templates/redhat/php.ini.erb @@ -1221,5 +1221,5 @@ soap.wsdl_cache_ttl=86400 ; End: <% @directives.sort_by { |key, val| key }.each do |directive, value| -%> -<%= "#{directive}=\"#{value}\"" %> +<%= "#{directive}=#{value}" %> <% end -%> diff --git a/cookbooks/php/templates/ubuntu/php.ini.erb b/cookbooks/php/templates/ubuntu/php.ini.erb index 1bd0a47..9588925 100644 --- a/cookbooks/php/templates/ubuntu/php.ini.erb +++ b/cookbooks/php/templates/ubuntu/php.ini.erb @@ -1853,5 +1853,5 @@ ldap.max_links = -1 ; End: <% @directives.sort_by { |key, val| key }.each do |directive, value| -%> -<%= "#{directive}=\"#{value}\"" %> +<%= "#{directive}=#{value}" %> <% end -%> diff --git a/cookbooks/php/templates/windows/php.ini.erb b/cookbooks/php/templates/windows/php.ini.erb index e492f09..0a0caaa 100644 --- a/cookbooks/php/templates/windows/php.ini.erb +++ b/cookbooks/php/templates/windows/php.ini.erb @@ -1931,5 +1931,5 @@ extension=php_exif.dll include_path=".;<%= node['php']['conf_dir'].gsub('/', '\\') %>" <% @directives.each do |directive, value| -%> -<%= "#{directive}=\"#{value}\"" %> +<%= "#{directive}=#{value}" %> <% end -%> diff --git a/cookbooks/poise-service/CHANGELOG.md b/cookbooks/poise-service/CHANGELOG.md new file mode 100644 index 0000000..519f68c --- /dev/null +++ b/cookbooks/poise-service/CHANGELOG.md @@ -0,0 +1,35 @@ +# Poise-Service Changelog + +## 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..8c753b7 --- /dev/null +++ b/cookbooks/poise-service/README.md @@ -0,0 +1,410 @@ +# 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. If unspecified it will be automatically allocated. +* `gid` – GID of the group. If unspecified it will be automatically allocated. +* `home` – Home directory of the user. + +## 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. +* `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_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_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_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)* + +### `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_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. + +## 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..db757ec --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/resources/poise_service.rb @@ -0,0 +1,162 @@ +# +# 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 + # For root we always want the system root path. + unless user == 'root' + # Force a reload in case any users were created earlier in the run. + Etc.endpwent + home = begin + Dir.home(user) + rescue ArgumentError + nil + end + end + # Better than nothing + home || case node['platform_family'] + when 'windows' + ENV.fetch('SystemRoot', 'C:\\') + else + '/' + end + 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..4aac59c --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/resources/poise_service_test.rb @@ -0,0 +1,241 @@ +# +# 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('STOP', '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..0073528 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/resources/poise_service_user.rb @@ -0,0 +1,138 @@ +# +# 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 + # 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 resource. + # Set to false to disable group creation. + # @return [String, false] + attribute(:group, kind_of: [String, FalseClass], name_attribute: true) + # @!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 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) + 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. + def create_group + group new_resource.group do + gid new_resource.gid + system true + end + end + + # Create the system user. + 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 '/bin/false' + system true + uid new_resource.uid + end + end + + # Remove the system group. + def remove_group + create_group.tap do |r| + r.action(:remove) + end + end + + # Remove the system user. + 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..da88a86 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/service_mixin.rb @@ -0,0 +1,192 @@ +# +# 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.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..0d9a58b --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/base.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 '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 + notify_if_service do + service_resource.run_action(:start) + end + end + + def action_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.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 'root' + 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 'poise-service' + 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..7cc6378 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/dummy.rb @@ -0,0 +1,156 @@ +# +# 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) + + def action_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: + 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") + IO.write(pid_file, Process.pid) + Chef::Log.debug("[#{new_resource}] 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 + end + Chef::Log.debug("[#{new_resource}] Changed privs to #{new_resource.user} (#{ent.uid}:#{ent.gid})") + # Split the command so we don't get an extra sh -c. + Chef::Log.debug("[#{new_resource}] Execing #{new_resource.command}") + Kernel.exec(*Shellwords.split(new_resource.command)) + # Just in case, bail out. + exit! + # :nocov: + end + Chef::Log.debug("[#{new_resource}] Started.") + end + + def action_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 + 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 + + 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..8b984e9 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/systemd.rb @@ -0,0 +1,83 @@ +# +# 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) + # Don't allow systemd under docker, it won't work in most cases. + return false if node['virtualization'] && %w{docker lxc}.include?(node['virtualization']['system']) + 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, + }) + 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']) + end + end + + def destroy_service + file "/etc/systemd/system/#{new_resource.service_name}.service" do + action :delete + 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..ab70d61 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/sysvinit.rb @@ -0,0 +1,91 @@ +# +# 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' + Chef::Provider::Service::Redhat + else + # This will explode later in the template, but better than nothing for later. + Chef::Provider::Service::Init + end) + r.init_command(script_path) + 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'], + 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..61b2318 --- /dev/null +++ b/cookbooks/poise-service/files/halite_gem/poise_service/service_providers/upstart.rb @@ -0,0 +1,128 @@ +# +# 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) + # Don't allow upstart under docker, it won't work. + return false if node['virtualization'] && %w{docker lxc}.include?(node['virtualization']['system']) + service_resource_hints.include?(:upstart) + 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 + 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..e1b4f86 --- /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.1.1' +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..12f9686 --- /dev/null +++ b/cookbooks/poise-service/metadata.json @@ -0,0 +1 @@ +{"name":"poise-service","version":"1.1.1","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. If unspecified it will be automatically allocated.\n* `gid` – GID of the group. If unspecified it will be automatically allocated.\n* `home` – Home directory of the user.\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* `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_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_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_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\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_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## 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":{},"dependencies":{"poise":"~> 2.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ 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..b309dbf --- /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}\"] = \"#{value}\"" }.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..6252cc1 --- /dev/null +++ b/cookbooks/poise-service/templates/default/systemd.service.erb @@ -0,0 +1,13 @@ +[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 %> + +[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 index ee9a7c2..8252642 100644 --- a/cookbooks/poise/CHANGELOG.md +++ b/cookbooks/poise/CHANGELOG.md @@ -1,5 +1,90 @@ # Changelog +## 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. diff --git a/cookbooks/poise/README.md b/cookbooks/poise/README.md index 6636536..cfb594e 100644 --- a/cookbooks/poise/README.md +++ b/cookbooks/poise/README.md @@ -10,7 +10,7 @@ ## What is Poise? The poise cookbook is a set of libraries for writing reusable cookbooks. It -providers helpers for common patterns and a standard structure to make it easier to create flexible cookbooks. +provides helpers for common patterns and a standard structure to make it easier to create flexible cookbooks. ## Writing your first resource @@ -21,35 +21,51 @@ the resource, which is in turn based on the class name. This means that the file An example of a simple shell to start from: ```ruby -class Chef - class Resource::MyApp < Resource - include Poise +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 + # Other attribute definitions. end - class Provider::MyApp < Provider + class Provider < Chef::Provider include Poise + provides(:my_app) def action_enable - converge_by("enable resource #{new_resource.name}") do - notifying_block do - ... # Normal Chef recipe code goes here - end + notifying_block do + ... # Normal Chef recipe code goes here end end end end ``` -Starting from the top, first 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. In order to load the helpers into the class, we -include the `Poise` mixin. Then we use the familiar DSL, though with a few additions we'll cover later. +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. Rather than use the `action :enable do ... end` DSL from LWRPs, we just define the action method directly, and use the `converge_by` method to provide a description of what the action does. 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`. +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: @@ -177,6 +193,25 @@ 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! diff --git a/cookbooks/poise/files/halite_gem/poise.rb b/cookbooks/poise/files/halite_gem/poise.rb index 26a817a..9457039 100644 --- a/cookbooks/poise/files/halite_gem/poise.rb +++ b/cookbooks/poise/files/halite_gem/poise.rb @@ -22,12 +22,44 @@ 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: @@ -57,7 +89,7 @@ def Poise(options={}) # 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]) if options[:container] + 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 @@ -69,3 +101,7 @@ def Poise(options={}) 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..f537118 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/backports.rb @@ -0,0 +1,28 @@ +# +# 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 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..ffb3190 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/backports/not_passed.rb @@ -0,0 +1,52 @@ +# +# 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. +# + +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, 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..616b421 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/backports/verify_path.rb @@ -0,0 +1,33 @@ +# +# 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 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/helpers.rb b/cookbooks/poise/files/halite_gem/poise/helpers.rb index ea0057a..43d1bc9 100644 --- a/cookbooks/poise/files/halite_gem/poise/helpers.rb +++ b/cookbooks/poise/files/halite_gem/poise/helpers.rb @@ -26,7 +26,9 @@ module Poise 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' 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 index b8337fb..4777161 100644 --- a/cookbooks/poise/files/halite_gem/poise/helpers/chefspec_matchers.rb +++ b/cookbooks/poise/files/halite_gem/poise/helpers/chefspec_matchers.rb @@ -60,9 +60,13 @@ module Poise # Create a resource-level matcher for this resource. # # @see Resource::ResourceName.provides - def provides(name) + def provides(name, *args, &block) + super(name, *args, &block) ChefSpec.define_matcher(name) if defined?(ChefSpec) - super + # 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. @@ -72,7 +76,7 @@ module Poise super.tap do |actions| actions.each do |action| ChefspecMatchers.create_matcher(resource_name, action) - end + end if resource_name && resource_name != :resource && !names.empty? 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 index 18bf9f5..32666ec 100644 --- a/cookbooks/poise/files/halite_gem/poise/helpers/defined_in.rb +++ b/cookbooks/poise/files/halite_gem/poise/helpers/defined_in.rb @@ -65,9 +65,9 @@ module Poise # @return [String] def poise_defined_in_cookbook(run_context, file=nil) file ||= poise_defined_in - Chef::Log.debug("[#{self.name}] Checking cookbook name for #{file}") + Poise.debug("[#{self.name}] Checking cookbook name for #{file}") Poise::Utils.find_cookbook_name(run_context, file).tap do |cookbook| - Chef::Log.debug("[#{self.name}] found cookbook #{cookbook.inspect}") + Poise.debug("[#{self.name}] found cookbook #{cookbook.inspect}") end end diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/inversion.rb b/cookbooks/poise/files/halite_gem/poise/helpers/inversion.rb index beb6e22..2965619 100644 --- a/cookbooks/poise/files/halite_gem/poise/helpers/inversion.rb +++ b/cookbooks/poise/files/halite_gem/poise/helpers/inversion.rb @@ -19,6 +19,7 @@ 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' @@ -77,13 +78,28 @@ module Poise # end def provider(val=nil) if val && !val.is_a?(Class) - provider_class = Poise::Helpers::Inversion.provider_for(resource_name, node, val) - Chef::Log.debug("[#{self}] Checking for an inversion provider for #{val}: #{provider_class && provider_class.name}") + 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. @@ -117,6 +133,9 @@ module Poise 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 @@ -126,6 +145,9 @@ module Poise 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 @@ -134,9 +156,9 @@ module Poise # # @param name [Symbol] Resource name # return [void] - def provides(name) + def provides(name, *args, &block) create_inversion_options_resource!(name) if inversion_options_resource - super if defined?(super) + super(name, *args, &block) if defined?(super) end def included(klass) @@ -170,40 +192,48 @@ module Poise module ClassMethods # @overload inversion_resource() # Return the inversion resource name for this class. - # @return [Symbol] + # @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] - def inversion_resource(val=nil) - if val + # @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 - @poise_inversion_resource || (superclass.respond_to?(:inversion_resource) ? superclass.inversion_resource : nil) + 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] + # @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] - def inversion_attribute(val=nil) - if val + # @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 - @poise_inversion_attribute || (superclass.respond_to?(:inversion_attribute) ? superclass.inversion_attribute : nil) + 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 @@ -235,6 +265,7 @@ module Poise 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}") @@ -257,19 +288,21 @@ module Poise # Class-level defaults. opts.update(default_inversion_options(node, resource)) # Resource options for all providers. - opts.update(resource.options) + 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)) + 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 @@ -323,10 +356,17 @@ module Poise # @return [Boolean] def provides?(node, resource) raise Poise::Error.new("Inversion resource name not set for #{self.name}") unless inversion_resource - return false unless resource.resource_name == 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) - Chef::Log.debug("[#{resource}] Checking provides? on #{self.name}. Got provider_name #{provider_name.inspect}") - provider_name == provides.to_s || ( provider_name == 'auto' && provides_auto?(node, resource) ) + 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. diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/lazy_default.rb b/cookbooks/poise/files/halite_gem/poise/helpers/lazy_default.rb index d35dc0c..b417266 100644 --- a/cookbooks/poise/files/halite_gem/poise/helpers/lazy_default.rb +++ b/cookbooks/poise/files/halite_gem/poise/helpers/lazy_default.rb @@ -14,6 +14,8 @@ # limitations under the License. # +require 'chef/version' + module Poise module Helpers @@ -29,13 +31,28 @@ module Poise # 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 validation && validation[:default].is_a?(Chef::DelayedEvaluator) + if LazyDefault.needs_polyfill? && validation && validation[:default].is_a?(Chef::DelayedEvaluator) validation = validation.dup - validation[:default] = instance_eval(&validation[:default]) + 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 diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/lwrp_polyfill.rb b/cookbooks/poise/files/halite_gem/poise/helpers/lwrp_polyfill.rb index a5a815d..cf7afcf 100644 --- a/cookbooks/poise/files/halite_gem/poise/helpers/lwrp_polyfill.rb +++ b/cookbooks/poise/files/halite_gem/poise/helpers/lwrp_polyfill.rb @@ -14,6 +14,8 @@ # limitations under the License. # +require 'chef/resource' + require 'poise/utils/resource_provider_mixin' @@ -30,35 +32,92 @@ module Poise module Resource def initialize(*args) super - # Try to not stomp on stuff if already set in a parent - @action = self.class.default_action if @action == :nothing + # 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 - # @!classmethods 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) + 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 - @default_action || ( respond_to?(:superclass) && superclass.respond_to?(:default_action) && superclass.default_action ) || actions.first || :nothing 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 : [] ) - (@actions << names).flatten!.uniq! - @actions + @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 - def attribute(name, opts) - # Ruby 1.8 can go to hell + # 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 + 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) @@ -70,6 +129,17 @@ module Poise # 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) @@ -78,14 +148,11 @@ module Poise # Mask Chef::Provider#load_current_resource because it throws NotImplementedError. if klass.is_a?(Class) && klass.superclass == Chef::Provider - klass.class_exec do - def load_current_resource - end - end + klass.send(:include, LoadCurrentResource) end # Reinstate the Chef DSL, removed in Chef 12. - klass.class_exec { include Chef::DSL::Recipe } + klass.send(:include, Chef::DSL::Recipe) 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 index f66900c..2ce7464 100644 --- a/cookbooks/poise/files/halite_gem/poise/helpers/option_collector.rb +++ b/cookbooks/poise/files/halite_gem/poise/helpers/option_collector.rb @@ -44,18 +44,25 @@ module Poise class OptionEvalContext attr_reader :_options - def initialize(parent) + 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.length > 0 || block + 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. @@ -86,8 +93,12 @@ module Poise # @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. - def option_collector_attribute(name, default: {}, parser: nil) + # @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) # 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}" @@ -110,7 +121,7 @@ module Poise value.update(arg) end if block - ctx = OptionEvalContext.new(self) + ctx = OptionEvalContext.new(self, forced_keys) ctx.instance_exec(&block) value.update(ctx._options) 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..8da99f9 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/resource_cloning.rb @@ -0,0 +1,72 @@ +# +# Copyright 2013-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 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 index 174ca1a..f4dcfec 100644 --- a/cookbooks/poise/files/halite_gem/poise/helpers/resource_name.rb +++ b/cookbooks/poise/files/halite_gem/poise/helpers/resource_name.rb @@ -51,7 +51,7 @@ module Poise # include Poise::Resource::ResourceName # provides(:my_resource) # end - def provides(name) + 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) @@ -61,9 +61,9 @@ module Poise end end # Store the name for later. - @provides_name = name + @provides_name ||= name # Call the original if present. The defined? is for old Chef. - super if defined?(super) + super(name, *args, &block) if defined?(super) end # Retreive the DSL name for the resource class. If not set explicitly @@ -72,11 +72,19 @@ module Poise # @param auto [Boolean] Try to auto-detect based on class name. # @return [Symbol] def resource_name(auto=true) - return @provides_name if @provides_name - @provides_name || if name && name.start_with?('Chef::Resource') - Chef::Mixin::ConvertToClassName.convert_to_snake_case(name, 'Chef::Resource').to_sym - elsif name - Chef::Mixin::ConvertToClassName.convert_to_snake_case(name.split('::').last).to_sym + # 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 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..e80b27e --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/helpers/resource_subclass.rb @@ -0,0 +1,82 @@ +# +# 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/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'] = Chef.provider_priority_map if defined?(Chef.provider_priority_map) + # 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 index b6b5bbe..1908294 100644 --- a/cookbooks/poise/files/halite_gem/poise/helpers/subcontext_block.rb +++ b/cookbooks/poise/files/halite_gem/poise/helpers/subcontext_block.rb @@ -27,10 +27,24 @@ module Poise private def subcontext_block(parent_context=nil, &block) - # Setup a sub-run-context. + # 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. diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/subresources/child.rb b/cookbooks/poise/files/halite_gem/poise/helpers/subresources/child.rb index a5fc9ea..4e93dc3 100644 --- a/cookbooks/poise/files/halite_gem/poise/helpers/subresources/child.rb +++ b/cookbooks/poise/files/halite_gem/poise/helpers/subresources/child.rb @@ -37,6 +37,10 @@ module Poise @resource = resource end + def inspect + to_text + end + def to_text if @resource.nil? 'nil' @@ -56,8 +60,12 @@ module Poise # string), or a type:name hash. # @param val [String, Hash, Chef::Resource] Parent resource to set. # @return [Chef::Resource, nil] - def parent(val=nil) - _parent(:parent, self.class.parent_type, self.class.parent_optional, self.class.parent_auto, val) + 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. @@ -67,7 +75,7 @@ module Poise super self.class.parent_attributes.each_key do |name| parent = self.send(name) - parent.register_subresource(self) if parent + parent.register_subresource(self) if parent && parent.respond_to?(:register_subresource) end end @@ -77,40 +85,68 @@ module Poise # # @since 2.0.0 # @see #parent - def _parent(name, parent_type, parent_optional, parent_auto, val=nil) + 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 val - if val.is_a?(String) && !val.include?('[') - raise Poise::Error.new('Cannot use a string parent without defining a parent type') if parent_type == Chef::Resource - val = "#{parent_type.resource_name}[#{val}]" - end - if val.is_a?(String) || val.is_a?(Hash) - parent = @run_context.resource_collection.find(val) + if !args.empty? + val = args.first + if val.nil? + # Unsetting the parent. + parent = parent_ref = nil else - parent = val + 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 - if !parent.is_a?(parent_type) - raise Poise::Error.new("Parent resource is not an instance of #{parent_type.name}: #{val.inspect}") + 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 - parent_ref = ParentRef.new(parent) - elsif !parent_ref - if parent_auto + # 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) + 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 parent found for #{self}") unless parent || parent_optional + 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. @@ -128,9 +164,12 @@ module Poise 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 - @parent_type = type + # Setting to true shouldn't actually do anything if a type was already set. + @parent_type = type unless type == true && !@parent_type.nil? end - @parent_type || (superclass.respond_to?(:parent_type) ? superclass.parent_type : Chef::Resource) + # 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() @@ -145,7 +184,7 @@ module Poise @parent_optional = val end if @parent_optional.nil? - superclass.respond_to?(:parent_optional) ? superclass.parent_optional : false + Poise::Utils.ancestor_send(self, :parent_optional, default: false) else @parent_optional end @@ -163,12 +202,32 @@ module Poise @parent_auto = val end if @parent_auto.nil? - superclass.respond_to?(:parent_auto) ? superclass.parent_auto : true + 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 @@ -178,11 +237,11 @@ module Poise # @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) + def parent_attribute(name, type: Chef::Resource, optional: false, auto: true, default: nil) name = :"parent_#{name}" (@parent_attributes ||= {})[name] = type - define_method(name) do |val=nil| - _parent(name, type, optional, auto, val) + define_method(name) do |*args| + _parent(name, type, optional, auto, default, *args) end end @@ -193,7 +252,7 @@ module Poise def parent_attributes {}.tap do |attrs| # Grab superclass's attributes if possible. - attrs.update(superclass.parent_attributes) if superclass.respond_to?(:parent_attributes) + attrs.update(Poise::Utils.ancestor_send(self, :parent_attributes, default: {})) # Local default parent. attrs[:parent] = parent_type # Extra locally defined parents. diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/subresources/container.rb b/cookbooks/poise/files/halite_gem/poise/helpers/subresources/container.rb index 6616303..0dc524c 100644 --- a/cookbooks/poise/files/halite_gem/poise/helpers/subresources/container.rb +++ b/cookbooks/poise/files/halite_gem/poise/helpers/subresources/container.rb @@ -31,6 +31,10 @@ module Poise # 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 @@ -40,23 +44,29 @@ module Poise include Chef::DSL::Recipe attr_reader :subresources + attr_reader :subcontexts def initialize(*args) super @subresources = NoPrintingResourceCollection.new + @subcontexts = [] end def after_created super - # Register - Poise::Helpers::Subresources::DefaultContainers.register!(self, run_context) + # 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_) @@ -71,12 +81,30 @@ module Poise # 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) - @subresources.each do |r| - Chef::Log.debug(" * #{r}") - @run_context.resource_collection.insert(r) + @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 @@ -90,7 +118,7 @@ module Poise 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. - subcontext_block do + @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 @@ -111,8 +139,13 @@ module Poise 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. - parent(self_) if respond_to?(:parent) + # 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 @@ -124,11 +157,19 @@ module Poise 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 @@ -145,16 +186,39 @@ module Poise def container_namespace(val=nil) @container_namespace = val unless val.nil? if @container_namespace.nil? - # Not set here, look at the superclass of true by default for backwards compat. - superclass.respond_to?(:container_namespace) ? superclass.container_namespace : true + # 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_get(:HIDDEN_IVARS) << :@subcontexts + klass.const_get(:FORBIDDEN_IVARS) << :@subcontexts 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 index eb66da0..46f52b5 100644 --- a/cookbooks/poise/files/halite_gem/poise/helpers/subresources/default_containers.rb +++ b/cookbooks/poise/files/halite_gem/poise/helpers/subresources/default_containers.rb @@ -47,10 +47,10 @@ module Poise # @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) + 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) + return resource if resource.is_a?(klass) && (!self_resource || self_resource != resource) end # Nothing found. nil @@ -65,6 +65,8 @@ module Poise # @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 diff --git a/cookbooks/poise/files/halite_gem/poise/helpers/template_content.rb b/cookbooks/poise/files/halite_gem/poise/helpers/template_content.rb index f59ad5d..8c0fd8c 100644 --- a/cookbooks/poise/files/halite_gem/poise/helpers/template_content.rb +++ b/cookbooks/poise/files/halite_gem/poise/helpers/template_content.rb @@ -68,6 +68,9 @@ module Poise # 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| @@ -97,7 +100,7 @@ module Poise old_after_created = instance_method(:after_created) define_method(:after_created) do old_after_created.bind(self).call - send("_#{name_prefix}validate") + send("_#{name_prefix}validate") if Array(action) == Array(self.class.default_action) end end diff --git a/cookbooks/poise/files/halite_gem/poise/provider.rb b/cookbooks/poise/files/halite_gem/poise/provider.rb index 275870f..d1a9c11 100644 --- a/cookbooks/poise/files/halite_gem/poise/provider.rb +++ b/cookbooks/poise/files/halite_gem/poise/provider.rb @@ -15,6 +15,7 @@ # require 'poise/helpers' +require 'poise/utils' module Poise @@ -35,6 +36,7 @@ module Poise include Poise::Helpers::IncludeRecipe include Poise::Helpers::LWRPPolyfill include Poise::Helpers::NotifyingBlock + include Poise::Utils::ShellOut # @!classmethods module ClassMethods diff --git a/cookbooks/poise/files/halite_gem/poise/resource.rb b/cookbooks/poise/files/halite_gem/poise/resource.rb index e11558b..ec582ce 100644 --- a/cookbooks/poise/files/halite_gem/poise/resource.rb +++ b/cookbooks/poise/files/halite_gem/poise/resource.rb @@ -15,6 +15,7 @@ # require 'poise/helpers' +require 'poise/utils' module Poise @@ -34,18 +35,22 @@ module Poise module Resource include Poise::Helpers::ChefspecMatchers include Poise::Helpers::DefinedIn - include Poise::Helpers::LazyDefault + 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::Utils::ShellOut # @!classmethods module ClassMethods - def poise_subresource_container(namespace=nil) + 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) diff --git a/cookbooks/poise/files/halite_gem/poise/subcontext/resource_collection.rb b/cookbooks/poise/files/halite_gem/poise/subcontext/resource_collection.rb index 4c25653..ea15cc3 100644 --- a/cookbooks/poise/files/halite_gem/poise/subcontext/resource_collection.rb +++ b/cookbooks/poise/files/halite_gem/poise/subcontext/resource_collection.rb @@ -40,7 +40,10 @@ module Poise @parent.lookup(resource) end - # Iterate and expand all nested contexts + # 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) @@ -51,6 +54,22 @@ module Poise 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 index 5020a41..831357f 100644 --- a/cookbooks/poise/files/halite_gem/poise/subcontext/runner.rb +++ b/cookbooks/poise/files/halite_gem/poise/subcontext/runner.rb @@ -36,8 +36,8 @@ module Poise # ever fire because the superclass re-raises if there is an error. return super if error delayed_actions.each do |notification| - notifications = run_context.delayed_notifications(@resource) - if run_context.delayed_notifications(@resource).any? { |existing_notification| existing_notification.duplicates?(notification) } + 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 diff --git a/cookbooks/poise/files/halite_gem/poise/utils.rb b/cookbooks/poise/files/halite_gem/poise/utils.rb index 5cf4cbf..e54ffaf 100644 --- a/cookbooks/poise/files/halite_gem/poise/utils.rb +++ b/cookbooks/poise/files/halite_gem/poise/utils.rb @@ -20,6 +20,7 @@ require 'poise/error' module Poise module Utils autoload :ResourceProviderMixin, 'poise/utils/resource_provider_mixin' + autoload :ShellOut, 'poise/utils/shell_out' extend self @@ -37,15 +38,14 @@ module Poise # end def find_cookbook_name(run_context, filename) possibles = {} - Chef::Log.debug("[Poise] Checking cookbook for #{filename.inspect}") + 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 /. - Chef::Log.debug("") if filename.start_with?(File.join(ver.halite_root, '')) - Chef::Log.debug("[Poise] Found matching halite_root in #{name}: #{ver.halite_root.inspect}") + Poise.debug("[Poise] Found matching halite_root in #{name}: #{ver.halite_root.inspect}") possibles[ver.halite_root] = name end else @@ -53,9 +53,9 @@ module Poise ver.segment_filenames(seg).each do |file| # Put this behind an environment variable because it is verbose # even for normal debugging-level output. - Chef::Log.debug("[Poise] Checking #{seg} in #{name}: #{file.inspect}") if ENV['POISE_DEBUG'] + Poise.debug("[Poise] Checking #{seg} in #{name}: #{file.inspect}") if file == filename - Chef::Log.debug("[Poise] Found matching #{seg} in #{name}: #{file.inspect}") + Poise.debug("[Poise] Found matching #{seg} in #{name}: #{file.inspect}") possibles[file] = name end end @@ -66,5 +66,112 @@ module Poise # 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 index 908dd30..7d4a9d3 100644 --- a/cookbooks/poise/files/halite_gem/poise/utils/resource_provider_mixin.rb +++ b/cookbooks/poise/files/halite_gem/poise/utils/resource_provider_mixin.rb @@ -48,10 +48,10 @@ module Poise # 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 + 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 + 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 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..55842c7 --- /dev/null +++ b/cookbooks/poise/files/halite_gem/poise/utils/shell_out.rb @@ -0,0 +1,85 @@ +# +# 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 '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 + # 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/version.rb b/cookbooks/poise/files/halite_gem/poise/version.rb index e7d3576..ad2ac1f 100644 --- a/cookbooks/poise/files/halite_gem/poise/version.rb +++ b/cookbooks/poise/files/halite_gem/poise/version.rb @@ -16,5 +16,5 @@ module Poise - VERSION = '2.0.1' + VERSION = '2.6.0' end diff --git a/cookbooks/poise/metadata.json b/cookbooks/poise/metadata.json index fa7cd1a..c535d88 100644 --- a/cookbooks/poise/metadata.json +++ b/cookbooks/poise/metadata.json @@ -1 +1 @@ -{"name":"poise","version":"2.0.1","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\nproviders 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\nclass Chef\n class Resource::MyApp < Resource\n include Poise\n\n actions(:enable)\n\n attribute(:path, kind_of: String)\n ... # Other attribute definitions\n end\n\n class Provider::MyApp < Provider\n include Poise\n\n def action_enable\n converge_by(\"enable resource #{new_resource.name}\") do\n notifying_block do\n ... # Normal Chef recipe code goes here\n end\n end\n end\n end\nend\n```\n\nStarting from the top, first we declare the resource class, which inherits from\n`Chef::Resource`. This is similar to the `resources/` file in an LWRP, and a similar DSL can be used. In order to load the helpers into the class, we\ninclude the `Poise` mixin. Then we use the familiar DSL, though with a few additions we'll cover later.\n\nThen 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. Rather than use the `action :enable do ... end` DSL from LWRPs, we just define the action method directly, and use the `converge_by` method to provide a description of what the action does. 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`.\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## Sponsors\n\nThe Poise test server infrastructure is generously sponsored by [Rackspace](https://rackspace.com/). Thanks Rackspace!\n\n## License\n\nCopyright 2013-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":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file +{"name":"poise","version":"2.6.0","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-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":"Noah Kantrowitz","maintainer_email":"noah@coderanger.net","license":"Apache 2.0","platforms":{},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file diff --git a/cookbooks/postfix/CHANGELOG.md b/cookbooks/postfix/CHANGELOG.md index 173cbad..b2f7f2e 100644 --- a/cookbooks/postfix/CHANGELOG.md +++ b/cookbooks/postfix/CHANGELOG.md @@ -2,6 +2,11 @@ postfix Cookbook CHANGELOG ========================== This file is used to list changes made in each version of the postfix cookbook. +v3.7.0 (2015-04-30) +------------------- +- Adding support for relay restrictions +- Update chefspec and serverspec tests + v3.6.2 (2014-10-31) ------------------- - Fix FreeBSDisms @@ -71,47 +76,47 @@ v3.1.4 (2014-02-27) v3.1.2 (2014-02-19) ------------------- ### Bug -- **[COOK-4357](https://tickets.opscode.com/browse/COOK-4357)** - postfix::sasl_auth recipe fails to converge +- **[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.opscode.com/browse/COOK-4322)** - Postfix cookbook has incorrect default path for sasl_passwd +- **[COOK-4322](https://tickets.chef.io/browse/COOK-4322)** - Postfix cookbook has incorrect default path for sasl_passwd ### New Feature -- **[COOK-4086](https://tickets.opscode.com/browse/COOK-4086)** - use conf_dir attribute for sasl recipe, and add omnios support -- **[COOK-2551](https://tickets.opscode.com/browse/COOK-2551)** - Support creating the sender_canonical map file +- **[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.opscode.com/browse/COOK-3824)** - main.cf.erb mishandles lists +- **[COOK-3824](https://tickets.chef.io/browse/COOK-3824)** - main.cf.erb mishandles lists ### Improvement -- **[COOK-3822](https://tickets.opscode.com/browse/COOK-3822)** - postfix cookbook readme has an incorrect example +- **[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.opscode.com/browse/COOK-2551)** - Support creating the sender_canonical map file +- **[COOK-2551](https://tickets.chef.io/browse/COOK-2551)** - Support creating the sender_canonical map file v3.0.2 ------ ### Bug -- **[COOK-3617](https://tickets.opscode.com/browse/COOK-3617)** - Fix error when no there is no FQDN -- **[COOK-3530](https://tickets.opscode.com/browse/COOK-3530)** - Update `client.rb` after 3.0.0 refactor -- **[COOK-2499](https://tickets.opscode.com/browse/COOK-2499)** - Do not use resource cloning +- **[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.opscode.com/browse/COOK-3116)** - Add SmartOS support +- **[COOK-3116](https://tickets.chef.io/browse/COOK-3116)** - Add SmartOS support v3.0.0 ------ ### Improvement -- **[COOK-3328](https://tickets.opscode.com/browse/COOK-3328)** - Postfix main/master and attributes refactor +- **[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']`. diff --git a/cookbooks/postfix/README.md b/cookbooks/postfix/README.md index bce9a32..586881a 100644 --- a/cookbooks/postfix/README.md +++ b/cookbooks/postfix/README.md @@ -29,6 +29,7 @@ See `attributes/default.rb` for default values. * `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. @@ -121,8 +122,12 @@ 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. -http://wiki.opscode.com/display/chef/Templates#Templates-TemplateLocationSpecificity + +http://wiki.chef.io/display/chef/Templates#Templates-TemplateLocationSpecificity Usage @@ -268,9 +273,24 @@ override_attributes( ) ``` +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:: Joshua Timberman +- Author:: Joshua Timberman ```text Copyright:: 2009-2014, Chef Software, Inc diff --git a/cookbooks/postfix/attributes/default.rb b/cookbooks/postfix/attributes/default.rb index e826932..f14a4cf 100644 --- a/cookbooks/postfix/attributes/default.rb +++ b/cookbooks/postfix/attributes/default.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -# Author:: Joshua Timberman +# Author:: Joshua Timberman # Copyright:: Copyright 2009-2014, Chef Software, Inc. # License:: Apache License, Version 2.0 # @@ -25,6 +25,7 @@ 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_restirictions_maps'] = false default['postfix']['transports'] = {} default['postfix']['access'] = {} default['postfix']['virtual_aliases'] = {} @@ -47,6 +48,7 @@ when 'smartos' 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' @@ -54,6 +56,7 @@ when 'freebsd' 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' @@ -61,6 +64,7 @@ when 'omnios' 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' @@ -69,6 +73,7 @@ else 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 @@ -87,6 +92,8 @@ 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' @@ -113,7 +120,6 @@ end # Master.cf attributes default['postfix']['master']['submission'] = false - # OS Aliases case node['platform'] when 'freebsd' @@ -135,3 +141,8 @@ when 'freebsd' else default['postfix']['aliases'] = {} end + +if node['postfix']['use_relay_restirictions_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 index 256f842..5371d01 100644 --- a/cookbooks/postfix/metadata.json +++ b/cookbooks/postfix/metadata.json @@ -1,89 +1 @@ -{ - "name": "postfix", - "version": "3.6.2", - "description": "Installs and configures postfix for client or outbound relayhost, or to do SASL auth", - "long_description": "", - "maintainer": "Chef Software, Inc.", - "maintainer_email": "cookbooks@getchef.com", - "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", - "scientific": ">= 0.0.0", - "smartos": ">= 0.0.0" - }, - "dependencies": { - }, - "recommendations": { - }, - "suggestions": { - }, - "conflicting": { - }, - "providing": { - }, - "replacing": { - }, - "attributes": { - "postfix/main": { - "display_name": "postfix/main", - "description": "Hash of Postfix main.cf attributes", - "type": "hash" - }, - "postfix/aliases": { - "display_name": "Postfix Aliases", - "description": "Hash of Postfix aliases mapping a name to a value. Example 'root' => 'operator@example.com'. See aliases man page for details.", - "type": "hash" - }, - "postfix/transports": { - "display_name": "Postfix Transports", - "description": "Hash of Postfix transports mapping a destination to a smtp server. Example 'my.domain' => 'smtp:outbound-relay.my.domain'. See transport man page for details.", - "type": "hash" - }, - "postfix/access": { - "display_name": "Postfix Access Table", - "description": "Hash of Postfix accesses mapping a pattern to a action. Example 'domain.tld' => 'OK'. See access man page for details.", - "type": "hash" - }, - "postfix/mail_type": { - "display_name": "Postfix Mail Type", - "description": "Is this node a client or server?", - "default": "client" - }, - "postfix/smtp_sasl_user_name": { - "display_name": "Postfix SMTP SASL Username", - "description": "User to auth SMTP via SASL", - "default": "" - }, - "postfix/smtp_sasl_passwd": { - "display_name": "Postfix SMTP SASL Password", - "description": "Password for smtp_sasl_user_name", - "default": "" - }, - "postfix/relayhost_role": { - "display_name": "Postfix Relayhost's role", - "description": "String containing the role name", - "default": "relayhost" - }, - "postfix/use_procmail": { - "display_name": "Postfix Use procmail?", - "description": "Whether procmail should be used as the local delivery agent for a server", - "default": "no" - } - }, - "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" - } -} \ No newline at end of file +{"name":"postfix","version":"3.7.0","description":"Installs and configures postfix for client or outbound relayhost, or to do SASL auth","long_description":"","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","scientific":">= 0.0.0","smartos":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{"postfix/main":{"display_name":"postfix/main","description":"Hash of Postfix main.cf attributes","type":"hash"},"postfix/aliases":{"display_name":"Postfix Aliases","description":"Hash of Postfix aliases mapping a name to a value. Example 'root' => 'operator@example.com'. See aliases man page for details.","type":"hash"},"postfix/transports":{"display_name":"Postfix Transports","description":"Hash of Postfix transports mapping a destination to a smtp server. Example 'my.domain' => 'smtp:outbound-relay.my.domain'. See transport man page for details.","type":"hash"},"postfix/access":{"display_name":"Postfix Access Table","description":"Hash of Postfix accesses mapping a pattern to a action. Example 'domain.tld' => 'OK'. See access man page for details.","type":"hash"},"postfix/mail_type":{"display_name":"Postfix Mail Type","description":"Is this node a client or server?","default":"client"},"postfix/smtp_sasl_user_name":{"display_name":"Postfix SMTP SASL Username","description":"User to auth SMTP via SASL","default":""},"postfix/smtp_sasl_passwd":{"display_name":"Postfix SMTP SASL Password","description":"Password for smtp_sasl_user_name","default":""},"postfix/relayhost_role":{"display_name":"Postfix Relayhost's role","description":"String containing the role name","default":"relayhost"},"postfix/use_procmail":{"display_name":"Postfix Use procmail?","description":"Whether procmail should be used as the local delivery agent for a server","default":"no"}},"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"},"source_url":"https://github.com/opscode-cookbooks/postfix","issues_url":"https://github.com/opscode-cookbooks/postfix/issues"} \ No newline at end of file diff --git a/cookbooks/postfix/metadata.rb b/cookbooks/postfix/metadata.rb deleted file mode 100644 index f47c338..0000000 --- a/cookbooks/postfix/metadata.rb +++ /dev/null @@ -1,64 +0,0 @@ -# encoding: utf-8 -name 'postfix' -description 'Installs and configures postfix for client or outbound relayhost, or to do SASL auth' -maintainer 'Chef Software, Inc.' -maintainer_email 'cookbooks@getchef.com' -license 'Apache 2.0' -version '3.6.2' -recipe 'postfix', 'Installs and configures postfix' -recipe 'postfix::sasl_auth', 'Set up postfix to auth to a server with sasl' -recipe 'postfix::aliases', 'Manages /etc/aliases' -recipe 'postfix::transports', 'Manages /etc/postfix/transport' -recipe 'postfix::access', 'Manages /etc/postfix/access' -recipe 'postfix::virtual_aliases', 'Manages /etc/postfix/virtual' -recipe 'postfix::client', 'Searches for the relayhost based on an attribute' -recipe 'postfix::server', 'Sets the mail_type attribute to master' - -%w(ubuntu debian redhat centos amazon scientific smartos).each do |os| - supports os -end - -attribute 'postfix/main', - display_name: 'postfix/main', - description: 'Hash of Postfix main.cf attributes', - type: 'hash' - -attribute 'postfix/aliases', - display_name: 'Postfix Aliases', - description: "Hash of Postfix aliases mapping a name to a value. Example 'root' => 'operator@example.com'. See aliases man page for details.", - type: 'hash' - -attribute 'postfix/transports', - display_name: 'Postfix Transports', - description: "Hash of Postfix transports mapping a destination to a smtp server. Example 'my.domain' => 'smtp:outbound-relay.my.domain'. See transport man page for details.", - type: 'hash' - -attribute 'postfix/access', - display_name: 'Postfix Access Table', - description: "Hash of Postfix accesses mapping a pattern to a action. Example 'domain.tld' => 'OK'. See access man page for details.", - type: 'hash' - -attribute 'postfix/mail_type', - display_name: 'Postfix Mail Type', - description: 'Is this node a client or server?', - default: 'client' - -attribute 'postfix/smtp_sasl_user_name', - display_name: 'Postfix SMTP SASL Username', - description: 'User to auth SMTP via SASL', - default: '' - -attribute 'postfix/smtp_sasl_passwd', - display_name: 'Postfix SMTP SASL Password', - description: 'Password for smtp_sasl_user_name', - default: '' - -attribute 'postfix/relayhost_role', - display_name: "Postfix Relayhost's role", - description: 'String containing the role name', - default: 'relayhost' - -attribute 'postfix/use_procmail', - display_name: 'Postfix Use procmail?', - description: 'Whether procmail should be used as the local delivery agent for a server', - default: 'no' diff --git a/cookbooks/postfix/recipes/_attributes.rb b/cookbooks/postfix/recipes/_attributes.rb index 0a84eea..01d7ca8 100644 --- a/cookbooks/postfix/recipes/_attributes.rb +++ b/cookbooks/postfix/recipes/_attributes.rb @@ -40,15 +40,15 @@ if node['postfix']['main']['smtp_sasl_auth_enable'] == 'yes' end if node['postfix']['use_alias_maps'] - node.default['postfix']['main']['alias_maps'] = ["hash:#{node['postfix']['aliases_db']}"] + node.default['postfix']['main']['alias_maps'] = ["hash:#{node['postfix']['aliases_db']}"] end if node['postfix']['use_transport_maps'] - node.default['postfix']['main']['transport_maps'] = ["hash:#{node['postfix']['transport_db']}"] + node.default['postfix']['main']['transport_maps'] = ["hash:#{node['postfix']['transport_db']}"] end if node['postfix']['use_access_maps'] - node.default['postfix']['main']['access_maps'] = ["hash:#{node['postfix']['access_db']}"] + node.default['postfix']['main']['access_maps'] = ["hash:#{node['postfix']['access_db']}"] end if node['postfix']['use_virtual_aliases'] diff --git a/cookbooks/postfix/recipes/_common.rb b/cookbooks/postfix/recipes/_common.rb index c91483a..b8fc106 100644 --- a/cookbooks/postfix/recipes/_common.rb +++ b/cookbooks/postfix/recipes/_common.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -# Author:: Joshua Timberman() +# Author:: Joshua Timberman() # Cookbook Name:: common # Recipe:: default # @@ -110,7 +110,7 @@ unless node['postfix']['smtp_generic_map_entries'].empty? end end -%w{main master}.each do |cfg| +%w( main master ).each do |cfg| template "#{node['postfix']['conf_dir']}/#{cfg}.cf" do source "#{cfg}.cf.erb" owner 'root' diff --git a/cookbooks/postfix/recipes/access.rb b/cookbooks/postfix/recipes/access.rb index eb75bb6..b28ab07 100644 --- a/cookbooks/postfix/recipes/access.rb +++ b/cookbooks/postfix/recipes/access.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -# Copyright:: Copyright (c) 2012, Opscode, Inc. +# Copyright:: Copyright (c) 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. diff --git a/cookbooks/postfix/recipes/client.rb b/cookbooks/postfix/recipes/client.rb index c6817ff..2f304f1 100644 --- a/cookbooks/postfix/recipes/client.rb +++ b/cookbooks/postfix/recipes/client.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -# Author:: Joshua Timberman() +# Author:: Joshua Timberman() # Cookbook Name:: postfix # Recipe:: client # diff --git a/cookbooks/postfix/recipes/default.rb b/cookbooks/postfix/recipes/default.rb index 1aecbd3..ba28cdc 100644 --- a/cookbooks/postfix/recipes/default.rb +++ b/cookbooks/postfix/recipes/default.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -# Author:: Joshua Timberman() +# Author:: Joshua Timberman() # Cookbook Name:: postfix # Recipe:: default # @@ -43,3 +43,8 @@ end if node['postfix']['use_virtual_aliases_domains'] include_recipe 'postfix::virtual_aliases_domains' end + +if node['postfix']['use_relay_restrictions_maps'] + include_recipe 'postfix::relay_restrictions' +end + diff --git a/cookbooks/postfix/recipes/relay_restrictions.rb b/cookbooks/postfix/recipes/relay_restrictions.rb new file mode 100644 index 0000000..a96d482 --- /dev/null +++ b/cookbooks/postfix/recipes/relay_restrictions.rb @@ -0,0 +1,29 @@ +# encoding: utf-8 +# Copyright:: Copyright (c) 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. +# + +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 index bf47568..519798d 100644 --- a/cookbooks/postfix/recipes/sasl_auth.rb +++ b/cookbooks/postfix/recipes/sasl_auth.rb @@ -1,6 +1,6 @@ # encoding: utf-8 # -# Author:: Joshua Timberman() +# Author:: Joshua Timberman() # Cookbook Name:: postfix # Recipe:: sasl_auth # @@ -49,6 +49,7 @@ execute 'postmap-sasl_passwd' do end template node['postfix']['sasl_password_file'] do + sensitive true source 'sasl_passwd.erb' owner 'root' group node['root_group'] diff --git a/cookbooks/postfix/recipes/server.rb b/cookbooks/postfix/recipes/server.rb index 3f26a52..e733d47 100644 --- a/cookbooks/postfix/recipes/server.rb +++ b/cookbooks/postfix/recipes/server.rb @@ -1,6 +1,6 @@ # encoding: utf-8 # -# Author:: Joshua Timberman() +# Author:: Joshua Timberman() # Cookbook Name:: postfix # Recipe:: server # diff --git a/cookbooks/postfix/recipes/transports.rb b/cookbooks/postfix/recipes/transports.rb index 709d0d4..24e610d 100644 --- a/cookbooks/postfix/recipes/transports.rb +++ b/cookbooks/postfix/recipes/transports.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -# Copyright:: Copyright (c) 2012, Opscode, Inc. +# Copyright:: Copyright (c) 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. diff --git a/cookbooks/postfix/recipes/virtual_aliases.rb b/cookbooks/postfix/recipes/virtual_aliases.rb index c2c3acf..dadde7f 100644 --- a/cookbooks/postfix/recipes/virtual_aliases.rb +++ b/cookbooks/postfix/recipes/virtual_aliases.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -# Copyright:: Copyright (c) 2012, Opscode, Inc. +# Copyright:: Copyright (c) 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. diff --git a/cookbooks/postfix/recipes/virtual_aliases_domains.rb b/cookbooks/postfix/recipes/virtual_aliases_domains.rb index 3e91e99..2c708c0 100644 --- a/cookbooks/postfix/recipes/virtual_aliases_domains.rb +++ b/cookbooks/postfix/recipes/virtual_aliases_domains.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -# Copyright:: Copyright (c) 2012, Opscode, Inc. +# Copyright:: Copyright (c) 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. diff --git a/cookbooks/postfix/templates/default/relay_restrictions.erb b/cookbooks/postfix/templates/default/relay_restrictions.erb new file mode 100644 index 0000000..4c404c4 --- /dev/null +++ b/cookbooks/postfix/templates/default/relay_restrictions.erb @@ -0,0 +1,11 @@ +# +# This file is generated by Chef for <%= node['fqdn'] %> +# +# Local changes 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/postgresql/CHANGELOG.md b/cookbooks/postgresql/CHANGELOG.md index 2307305..f794009 100644 --- a/cookbooks/postgresql/CHANGELOG.md +++ b/cookbooks/postgresql/CHANGELOG.md @@ -2,11 +2,42 @@ postgresql Cookbook CHANGELOG ============================= This file is used to list changes made in each version of the postgresql cookbook. +v4.0.0 +----- +* Potential breaking change: Restructured default attributes to avoid compile time deriving other attribute values from value of the `node[‘postgresql’][‘version’]` +(#313, #302, #295, #288, #280, #261, #260, #254, #248, #217, #214, #167, #143) +* Correct issues which caused the inability to override installation version defaults +* Correct issues which caused configuration file entries with miss matching version numbers and incorrect file system paths being defined +* Remove method pgdgrepo_rpm_info compile time use of derived attributes case many issues +* Use correct directory path and check for the correct not_if condition to determine if the database has been initialized +* Ensure that correct packages are installed in all scenarios where pg gem is compiled +* Fix errors in configuration files for unix_socket_directory and unix_socket_directories +* Updates to test-kitchen suite configuration +* Added more grey hair to my beard + +v3.4.24 +------- +* Corrections to address repositories signed with newer certificates that some distributions have in their default ca-certificates package +* Updates to more accurately determine distributions service init systems adds better support for systemd systems +* Correct how version attribute is evaluated in certain places +* test-kitchen suite configuration corrections +* Opensuse support + +v3.4.23 +------- +- Skipping 3.4.22 with Develop branch 3.4.23 to return to releasing cookbook from master on even numbers and develop on odd numbers. + +v3.4.21 +------- +- Use more optimistic openssl version constraint +- Add Postgresql 9.4 package sources for RHEL platforms +- Update testing infrastructure to address bit rot + v3.4.20 ------- - Revert [#251](https://github.com/hw-cookbooks/postgresql/pull/251), a change which caused the postgresql service to restart every Chef run. -v3.4.19 [YANKED] +v3.4.19 ------- - node.save could better not be run on every chef run since it causes node.default attributes stored to the node objects to differ during a chef run and when - Missing attribute in docs for yum_pgdg_postgresql diff --git a/cookbooks/postgresql/README.md b/cookbooks/postgresql/README.md index ba7f14b..847ff32 100644 --- a/cookbooks/postgresql/README.md +++ b/cookbooks/postgresql/README.md @@ -15,8 +15,8 @@ Requirements Tested on: -* Ubuntu 10.04, 11.10, 12.04, 14.04, 14.10 -* Red Hat 6.1, Scientific 6.1, CentOS 6.3 +* Ubuntu 12.04, 14.04, 14.10 +* Red Hat 6.1, Scientific 6.1, CentOS 6.3, 7.0, OpenSuse ## Cookbooks @@ -69,10 +69,6 @@ The following attributes are set based on the platform, see the The following attributes are generated in `recipe[postgresql::server]`. -* `node['postgresql']['password']['postgres']` - randomly generated - password by the `openssl` cookbook's library. - (TODO: This is broken, as it disables the password.) - Configuration ------------- @@ -172,14 +168,6 @@ Installs the packages defined in the ruby ---- -**NOTE** This recipe may not currently work when installing Chef with - the - ["Omnibus" full stack installer](http://opscode.com/chef/install) on - some platforms due to an incompatibility with OpenSSL. See - [COOK-1406](http://tickets.opscode.com/browse/COOK-1406). You can - build from source into the Chef omnibus installation to work around - this issue. - Install the `pg` gem under Chef's Ruby environment so it can be used in other recipes. The build-essential packages and postgresql client packages will be installed during the compile phase, so that the @@ -193,7 +181,6 @@ appropriate server packages installed and service managed. Also manages the configuration for the server: * generates a strong default password (via `openssl`) for `postgres` - (TODO: This is broken, as it disables the password.) * sets the password for postgres * manages the `postgresql.conf` file. * manages the `pg_hba.conf` file. @@ -449,7 +436,7 @@ License and Author - Author:: Lamont Granquist () - Author:: Chris Roberts () - Author:: David Crane () -- Author:: Aaron Baer () +- Author:: Aaron Baer () Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/cookbooks/postgresql/attributes/default.rb b/cookbooks/postgresql/attributes/default.rb index 8c568a7..345ed7d 100644 --- a/cookbooks/postgresql/attributes/default.rb +++ b/cookbooks/postgresql/attributes/default.rb @@ -16,63 +16,130 @@ # default['postgresql']['enable_pgdg_apt'] = false +default['postgresql']['enable_pgdg_yum'] = false + default['postgresql']['server']['config_change_notify'] = :restart default['postgresql']['assign_postgres_password'] = true # Establish default database name default['postgresql']['database_name'] = 'template1' +# Sets OS init system (upstart, systemd, ...), instead of relying on Ohai +default['postgresql']['server']['init_package'] = case node['platform'] + when 'debian' + case + when node['platform_version'].to_f < 7.0 + 'sysv' + else + 'systemd' + end + when 'ubuntu' + case + when node['platform_version'].to_f < 15.04 + 'upstart' + else + 'systemd' + end + when 'amazon' + 'upstart' + when 'redhat', 'centos', 'scientific', 'oracle' + case + when node['platform_version'].to_f < 6.0 + 'sysv' + when node['platform_version'].to_f < 7.0 + 'upstart' + else + 'systemd' + end + when 'fedora' + case + when node['platform_version'].to_f < 15 + 'upstart' + else + 'systemd' + end + when 'opensuse' + case + when node['platform_version'].to_f < 13 + 'sysv' + else + 'systemd' + end + else + 'upstart' + end + case node['platform'] when "debian" case when node['platform_version'].to_f < 6.0 # All 5.X default['postgresql']['version'] = "8.3" + default['postgresql']['dir'] = "/etc/postgresql/8.3/main" + default['postgresql']['client']['packages'] = ["postgresql-client-8.3","libpq-dev"] + default['postgresql']['server']['packages'] = ["postgresql-8.3"] + default['postgresql']['contrib']['packages'] = ["postgresql-contrib-8.3"] when node['platform_version'].to_f < 7.0 # All 6.X default['postgresql']['version'] = "8.4" + default['postgresql']['dir'] = "/etc/postgresql/8.4/main" + default['postgresql']['client']['packages'] = ["postgresql-client-8.4","libpq-dev"] + default['postgresql']['server']['packages'] = ["postgresql-8.4"] + default['postgresql']['contrib']['packages'] = ["postgresql-contrib-8.4"] when node['platform_version'].to_f < 8.0 # All 7.X default['postgresql']['version'] = "9.1" + default['postgresql']['dir'] = "/etc/postgresql/9.1/main" + default['postgresql']['client']['packages'] = ["postgresql-client-9.1","libpq-dev"] + default['postgresql']['server']['packages'] = ["postgresql-9.1"] + default['postgresql']['contrib']['packages'] = ["postgresql-contrib-9.1"] else default['postgresql']['version'] = "9.4" + default['postgresql']['dir'] = "/etc/postgresql/9.4/main" + default['postgresql']['client']['packages'] = ["postgresql-client-9.4","libpq-dev"] + default['postgresql']['server']['packages'] = ["postgresql-9.4"] + default['postgresql']['contrib']['packages'] = ["postgresql-contrib-9.4"] end - default['postgresql']['dir'] = "/etc/postgresql/#{node['postgresql']['version']}/main" case when node['platform_version'].to_f < 6.0 # All 5.X - default['postgresql']['server']['service_name'] = "postgresql-#{node['postgresql']['version']}" + default['postgresql']['server']['service_name'] = "postgresql-8.3" else default['postgresql']['server']['service_name'] = "postgresql" end - default['postgresql']['client']['packages'] = ["postgresql-client-#{node['postgresql']['version']}","libpq-dev"] - default['postgresql']['server']['packages'] = ["postgresql-#{node['postgresql']['version']}"] - default['postgresql']['contrib']['packages'] = ["postgresql-contrib-#{node['postgresql']['version']}"] when "ubuntu" case when node['platform_version'].to_f <= 9.04 default['postgresql']['version'] = "8.3" + default['postgresql']['dir'] = "/etc/postgresql/8.3/main" + default['postgresql']['server']['service_name'] = "postgresql-8.3" + default['postgresql']['client']['packages'] = ["postgresql-client-8.3","libpq-dev"] + default['postgresql']['server']['packages'] = ["postgresql-8.3"] + default['postgresql']['contrib']['packages'] = ["postgresql-contrib-8.3"] when node['platform_version'].to_f <= 11.04 default['postgresql']['version'] = "8.4" + default['postgresql']['dir'] = "/etc/postgresql/8.4/main" + default['postgresql']['server']['service_name'] = "postgresql" + default['postgresql']['client']['packages'] = ["postgresql-client-8.4","libpq-dev"] + default['postgresql']['server']['packages'] = ["postgresql-8.4"] + default['postgresql']['contrib']['packages'] = ["postgresql-contrib-8.4"] when node['platform_version'].to_f <= 13.10 default['postgresql']['version'] = "9.1" + default['postgresql']['dir'] = "/etc/postgresql/9.1/main" + default['postgresql']['server']['service_name'] = "postgresql" + default['postgresql']['client']['packages'] = ["postgresql-client-9.1","libpq-dev"] + default['postgresql']['server']['packages'] = ["postgresql-9.1"] + default['postgresql']['contrib']['packages'] = ["postgresql-contrib-9.1"] else default['postgresql']['version'] = "9.3" - end - - default['postgresql']['dir'] = "/etc/postgresql/#{node['postgresql']['version']}/main" - case - when (node['platform_version'].to_f <= 10.04) && (! node['postgresql']['enable_pgdg_apt']) - default['postgresql']['server']['service_name'] = "postgresql-#{node['postgresql']['version']}" - else + default['postgresql']['dir'] = "/etc/postgresql/9.3/main" default['postgresql']['server']['service_name'] = "postgresql" + default['postgresql']['client']['packages'] = ["postgresql-client-9.3","libpq-dev"] + default['postgresql']['server']['packages'] = ["postgresql-9.3"] + default['postgresql']['contrib']['packages'] = ["postgresql-contrib-9.3"] end - default['postgresql']['client']['packages'] = ["postgresql-client-#{node['postgresql']['version']}","libpq-dev"] - default['postgresql']['server']['packages'] = ["postgresql-#{node['postgresql']['version']}"] - default['postgresql']['contrib']['packages'] = ["postgresql-contrib-#{node['postgresql']['version']}"] - when "fedora" if node['platform_version'].to_f <= 12 @@ -81,6 +148,8 @@ when "fedora" default['postgresql']['version'] = "8.4" end + default['postgresql']['setup_script'] = "postgresql-setup" + default['postgresql']['dir'] = "/var/lib/pgsql/data" default['postgresql']['client']['packages'] = %w{postgresql-devel} default['postgresql']['server']['packages'] = %w{postgresql-server} @@ -89,9 +158,12 @@ when "fedora" when "amazon" - if node['platform_version'].to_f >= 2012.03 + if node['platform_version'].to_f == 2012.03 default['postgresql']['version'] = "9.0" default['postgresql']['dir'] = "/var/lib/pgsql9/data" + elsif node['platform_version'].to_f >= 2015.03 + default['postgresql']['version'] = "9.2" + default['postgresql']['dir'] = "/var/lib/pgsql9/data" else default['postgresql']['version'] = "8.4" default['postgresql']['dir'] = "/var/lib/pgsql/data" @@ -105,28 +177,39 @@ when "amazon" when "redhat", "centos", "scientific", "oracle" default['postgresql']['version'] = "8.4" + + default['postgresql']['client']['packages'] = ["postgresql84-devel"] + default['postgresql']['server']['packages'] = ["postgresql84-server"] + default['postgresql']['contrib']['packages'] = ["postgresql84-contrib"] + + default['postgresql']['setup_script'] = "postgresql-setup" + default['postgresql']['server']['service_name'] = "postgresql" + + if node['platform_version'].to_f >= 6.0 && node['postgresql']['version'].to_f == 8.4 + default['postgresql']['client']['packages'] = ['postgresql-devel'] + default['postgresql']['server']['packages'] = ['postgresql-server'] + default['postgresql']['contrib']['packages'] = ['postgresql-contrib'] + end + +when "opensuse" + default['postgresql']['dir'] = "/var/lib/pgsql/data" - if node['platform_version'].to_f >= 6.0 && node['postgresql']['version'] == '8.4' - default['postgresql']['client']['packages'] = %w{postgresql-devel} - default['postgresql']['server']['packages'] = %w{postgresql-server} - default['postgresql']['contrib']['packages'] = %w{postgresql-contrib} - else - default['postgresql']['client']['packages'] = ["postgresql#{node['postgresql']['version'].split('.').join}-devel"] - default['postgresql']['server']['packages'] = ["postgresql#{node['postgresql']['version'].split('.').join}-server"] - default['postgresql']['contrib']['packages'] = ["postgresql#{node['postgresql']['version'].split('.').join}-contrib"] + if node['platform_version'].to_f == 13.2 + default['postgresql']['version'] = '9.3' + default['postgresql']['client']['packages'] = ['postgresql93', 'postgresql93-devel'] + default['postgresql']['server']['packages'] = ['postgresql93-server'] + default['postgresql']['contrib']['packages'] = ['postgresql93-contrib'] + elsif node['platform_version'].to_f == 13.1 + default['postgresql']['version'] = '9.2' + default['postgresql']['client']['packages'] = ['postgresql92', 'postgresql92-devel'] + default['postgresql']['server']['packages'] = ['postgresql92-server'] + default['postgresql']['contrib']['packages'] = ['postgresql92-contrib'] end - if node['platform_version'].to_f >= 6.0 && node['postgresql']['version'] != '8.4' - default['postgresql']['dir'] = "/var/lib/pgsql/#{node['postgresql']['version']}/data" - default['postgresql']['server']['service_name'] = "postgresql-#{node['postgresql']['version']}" - else - default['postgresql']['dir'] = "/var/lib/pgsql/data" - default['postgresql']['server']['service_name'] = "postgresql" - end + default['postgresql']['server']['service_name'] = "postgresql" when "suse" - if node['platform_version'].to_f <= 11.1 default['postgresql']['version'] = "8.3" default['postgresql']['client']['packages'] = ['postgresql', 'rubygem-pg'] @@ -144,46 +227,24 @@ when "suse" else default['postgresql']['version'] = "8.4" - default['postgresql']['dir'] = "/etc/postgresql/#{node['postgresql']['version']}/main" + default['postgresql']['dir'] = "/etc/postgresql/8.4/main" default['postgresql']['client']['packages'] = ["postgresql"] default['postgresql']['server']['packages'] = ["postgresql"] default['postgresql']['contrib']['packages'] = ["postgresql"] default['postgresql']['server']['service_name'] = "postgresql" end -# These defaults have disparity between which postgresql configuration -# settings are used because they were extracted from the original -# configuration files that are now removed in favor of dynamic -# generation. -# -# While the configuration ends up being the same as the default -# in previous versions of the cookbook, the content of the rendered -# template will change, and this will result in service notification -# if you upgrade the cookbook on existing systems. -# -# The ssl config attribute is generated in the recipe to avoid awkward -# merge/precedence order during the Chef run. case node['platform_family'] when 'debian' - default['postgresql']['config']['data_directory'] = "/var/lib/postgresql/#{node['postgresql']['version']}/main" - default['postgresql']['config']['hba_file'] = "/etc/postgresql/#{node['postgresql']['version']}/main/pg_hba.conf" - default['postgresql']['config']['ident_file'] = "/etc/postgresql/#{node['postgresql']['version']}/main/pg_ident.conf" - default['postgresql']['config']['external_pid_file'] = "/var/run/postgresql/#{node['postgresql']['version']}-main.pid" default['postgresql']['config']['listen_addresses'] = 'localhost' default['postgresql']['config']['port'] = 5432 default['postgresql']['config']['max_connections'] = 100 - default['postgresql']['config']['unix_socket_directory'] = '/var/run/postgresql' if node['postgresql']['version'].to_f < 9.3 - default['postgresql']['config']['unix_socket_directories'] = '/var/run/postgresql' if node['postgresql']['version'].to_f >= 9.3 default['postgresql']['config']['shared_buffers'] = '24MB' - default['postgresql']['config']['max_fsm_pages'] = 153600 if node['postgresql']['version'].to_f < 8.4 default['postgresql']['config']['log_line_prefix'] = '%t ' default['postgresql']['config']['datestyle'] = 'iso, mdy' default['postgresql']['config']['default_text_search_config'] = 'pg_catalog.english' default['postgresql']['config']['ssl'] = true - default['postgresql']['config']['ssl_cert_file'] = '/etc/ssl/certs/ssl-cert-snakeoil.pem' if node['postgresql']['version'].to_f >= 9.2 - default['postgresql']['config']['ssl_key_file'] = '/etc/ssl/private/ssl-cert-snakeoil.key'if node['postgresql']['version'].to_f >= 9.2 when 'rhel', 'fedora', 'suse' - default['postgresql']['config']['data_directory'] = node['postgresql']['dir'] default['postgresql']['config']['listen_addresses'] = 'localhost' default['postgresql']['config']['port'] = 5432 default['postgresql']['config']['max_connections'] = 100 @@ -216,334 +277,5 @@ when 'debian' default['postgresql']['pgdg']['release_apt_codename'] = node['lsb']['codename'] end -default['postgresql']['enable_pgdg_yum'] = false - -default['postgresql']['initdb_locale'] = nil - -# The PostgreSQL RPM Building Project built repository RPMs for easy -# access to the PGDG yum repositories. Links to RPMs for installation -# on the supported version/platform combinations are listed at -# http://yum.postgresql.org/repopackages.php, and the links for -# PostgreSQL 8.4, 9.0, 9.1, 9.2 and 9.3 are captured below. -# -# The correct RPM for installing /etc/yum.repos.d is based on: -# * the attribute configuring the desired Postgres Software: -# node['postgresql']['version'] e.g., "9.1" -# * the chef ohai description of the target Operating System: -# node['platform'] e.g., "centos" -# node['platform_version'] e.g., "5.7", truncated as "5" -# node['kernel']['machine'] e.g., "i386" or "x86_64" -default['postgresql']['pgdg']['repo_rpm_url'] = { - "9.4" => { - "redhat" => { - "7" => { - "x86_64" => "http://yum.postgresql.org/9.4/redhat/rhel-7-x86_64/pgdg-redhat94-9.4-1.noarch.rpm" - } - } - }, - "9.3" => { - "amazon" => { - "2015" => { - "i386" => "http://yum.postgresql.org/9.3/redhat/rhel-6-i386/pgdg-redhat93-9.3-1.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/pgdg-redhat93-9.3-1.noarch.rpm" - }, - "2014" => { - "i386" => "http://yum.postgresql.org/9.3/redhat/rhel-6-i386/pgdg-redhat93-9.3-1.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/pgdg-redhat93-9.3-1.noarch.rpm" - }, - "2013" => { - "i386" => "http://yum.postgresql.org/9.3/redhat/rhel-6-i386/pgdg-redhat93-9.3-1.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/pgdg-redhat93-9.3-1.noarch.rpm" - } - }, - "centos" => { - "7" => { - "x86_64" => "http://yum.postgresql.org/9.3/redhat/rhel-7-x86_64/pgdg-centos93-9.3-1.noarch.rpm" - }, - "6" => { - "i386" => "http://yum.postgresql.org/9.3/redhat/rhel-6-i386/pgdg-centos93-9.3-1.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/pgdg-centos93-9.3-1.noarch.rpm" - }, - "5" => { - "i386" => "http://yum.postgresql.org/9.3/redhat/rhel-5-i386/pgdg-centos93-9.3-1.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.3/redhat/rhel-5-x86_64/pgdg-centos93-9.3-1.noarch.rpm" - } - }, - "redhat" => { - "7" => { - "x86_64" => "http://yum.postgresql.org/9.3/redhat/rhel-7-x86_64/pgdg-redhat93-9.3-1.noarch.rpm" - }, - "6" => { - "i386" => "http://yum.postgresql.org/9.3/redhat/rhel-6-i386/pgdg-redhat93-9.3-1.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/pgdg-redhat93-9.3-1.noarch.rpm" - }, - "5" => { - "i386" => "http://yum.postgresql.org/9.3/redhat/rhel-5-i386/pgdg-redhat93-9.3-1.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.3/redhat/rhel-5-x86_64/pgdg-redhat93-9.3-1.noarch.rpm" - } - }, - "oracle" => { - "6" => { - "i386" => "http://yum.postgresql.org/9.3/redhat/rhel-6-i386/pgdg-redhat93-9.3-1.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/pgdg-redhat93-9.3-1.noarch.rpm" - }, - "5" => { - "i386" => "http://yum.postgresql.org/9.3/redhat/rhel-5-i386/pgdg-redhat93-9.3-1.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.3/redhat/rhel-5-x86_64/pgdg-redhat93-9.3-1.noarch.rpm" - } - }, - "scientific" => { - "6" => { - "i386" => "http://yum.postgresql.org/9.3/redhat/rhel-6-i386/pgdg-sl93-9.3-1.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/pgdg-sl93-9.3-1.noarch.rpm" - }, - "5" => { - "i386" => "http://yum.postgresql.org/9.3/redhat/rhel-5-i386/pgdg-sl93-9.3-1.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.3/redhat/rhel-5-x86_64/pgdg-sl93-9.3-1.noarch.rpm" - } - }, - "fedora" => { - "20" => { - "x86_64" => "http://yum.postgresql.org/9.3/fedora/fedora-20-x86_64/pgdg-fedora93-9.3-1.noarch.rpm" - }, - "19" => { - "x86_64" => "http://yum.postgresql.org/9.3/fedora/fedora-19-x86_64/pgdg-fedora93-9.3-1.noarch.rpm" - }, - "18" => { - "i386" => "http://yum.postgresql.org/9.3/fedora/fedora-18-i386/pgdg-fedora93-9.3-1.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.3/fedora/fedora-18-x86_64/pgdg-fedora93-9.3-1.noarch.rpm" - }, - "17" => { - "i386" => "http://yum.postgresql.org/9.3/fedora/fedora-17-i386/pgdg-fedora93-9.3-1.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.3/fedora/fedora-17-x86_64/pgdg-fedora93-9.3-1.noarch.rpm" - } - } - }, - "9.2" => { - "centos" => { - "6" => { - "i386" => "http://yum.postgresql.org/9.2/redhat/rhel-6-i386/pgdg-centos92-9.2-6.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.2/redhat/rhel-6-x86_64/pgdg-centos92-9.2-6.noarch.rpm" - }, - "5" => { - "i386" => "http://yum.postgresql.org/9.2/redhat/rhel-5-i386/pgdg-centos92-9.2-6.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.2/redhat/rhel-5-x86_64/pgdg-centos92-9.2-6.noarch.rpm" - } - }, - "redhat" => { - "6" => { - "i386" => "http://yum.postgresql.org/9.2/redhat/rhel-6-i386/pgdg-redhat92-9.2-7.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.2/redhat/rhel-6-x86_64/pgdg-redhat92-9.2-7.noarch.rpm" - }, - "5" => { - "i386" => "http://yum.postgresql.org/9.2/redhat/rhel-5-i386/pgdg-redhat92-9.2-7.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.2/redhat/rhel-5-x86_64/pgdg-redhat92-9.2-7.noarch.rpm" - } - }, - "oracle" => { - "6" => { - "i386" => "http://yum.postgresql.org/9.2/redhat/rhel-6-i386/pgdg-redhat92-9.2-7.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.2/redhat/rhel-6-x86_64/pgdg-redhat92-9.2-7.noarch.rpm" - }, - "5" => { - "i386" => "http://yum.postgresql.org/9.2/redhat/rhel-5-i386/pgdg-redhat92-9.2-7.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.2/redhat/rhel-5-x86_64/pgdg-redhat92-9.2-7.noarch.rpm" - } - }, - "scientific" => { - "6" => { - "i386" => "http://yum.postgresql.org/9.2/redhat/rhel-6-i386/pgdg-sl92-9.2-8.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.2/redhat/rhel-6-x86_64/pgdg-sl92-9.2-8.noarch.rpm" - }, - "5" => { - "i386" => "http://yum.postgresql.org/9.2/redhat/rhel-5-i386/pgdg-sl92-9.2-8.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.2/redhat/rhel-5-x86_64/pgdg-sl92-9.2-8.noarch.rpm" - } - }, - "fedora" => { - "19" => { - "i386" => "http://yum.postgresql.org/9.2/fedora/fedora-19-i386/pgdg-fedora92-9.2-6.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.2/fedora/fedora-19-x86_64/pgdg-fedora92-9.2-6.noarch.rpm" - }, - "18" => { - "i386" => "http://yum.postgresql.org/9.2/fedora/fedora-18-i386/pgdg-fedora92-9.2-6.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.2/fedora/fedora-18-x86_64/pgdg-fedora92-9.2-6.noarch.rpm" - }, - "17" => { - "i386" => "http://yum.postgresql.org/9.2/fedora/fedora-17-i386/pgdg-fedora92-9.2-6.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.2/fedora/fedora-17-x86_64/pgdg-fedora92-9.2-5.noarch.rpm" - }, - "16" => { - "i386" => "http://yum.postgresql.org/9.2/fedora/fedora-16-i386/pgdg-fedora92-9.2-5.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.2/fedora/fedora-16-x86_64/pgdg-fedora92-9.2-5.noarch.rpm" - } - } - }, - "9.1" => { - "centos" => { - "6" => { - "i386" => "http://yum.postgresql.org/9.1/redhat/rhel-6-i386/pgdg-centos91-9.1-4.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.1/redhat/rhel-5-x86_64/pgdg-centos91-9.1-4.noarch.rpm" - }, - "5" => { - "i386" => "http://yum.postgresql.org/9.1/redhat/rhel-5-i386/pgdg-centos91-9.1-4.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.1/redhat/rhel-5-x86_64/pgdg-centos91-9.1-4.noarch.rpm" - }, - "4" => { - "i386" => "http://yum.postgresql.org/9.1/redhat/rhel-4-i386/pgdg-centos91-9.1-4.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.1/redhat/rhel-4-x86_64/pgdg-centos91-9.1-4.noarch.rpm" - } - }, - "redhat" => { - "6" => { - "i386" => "http://yum.postgresql.org/9.1/redhat/rhel-6-i386/pgdg-redhat91-9.1-5.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.1/redhat/rhel-6-x86_64/pgdg-redhat91-9.1-5.noarch.rpm" - }, - "5" => { - "i386" => "http://yum.postgresql.org/9.1/redhat/rhel-5-i386/pgdg-redhat91-9.1-5.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.1/redhat/rhel-5-x86_64/pgdg-redhat91-9.1-5.noarch.rpm" - }, - "4" => { - "i386" => "http://yum.postgresql.org/9.1/redhat/rhel-4-i386/pgdg-redhat-9.1-4.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.1/redhat/rhel-4-x86_64/pgdg-redhat-9.1-4.noarch.rpm" - } - }, - "scientific" => { - "6" => { - "i386" => "http://yum.postgresql.org/9.1/redhat/rhel-6-i386/pgdg-sl91-9.1-6.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.1/redhat/rhel-6-x86_64/pgdg-sl91-9.1-6.noarch.rpm" - }, - "5" => { - "i386" => "http://yum.postgresql.org/9.1/redhat/rhel-5-i386/pgdg-sl91-9.1-6.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.1/redhat/rhel-5-x86_64/pgdg-sl91-9.1-6.noarch.rpm" - } - }, - "fedora" => { - "16" => { - "i386" => "http://yum.postgresql.org/9.1/fedora/fedora-16-i386/pgdg-fedora91-9.1-4.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.1/fedora/fedora-16-x86_64/pgdg-fedora91-9.1-4.noarch.rpm" - }, - "15" => { - "i386" => "http://yum.postgresql.org/9.1/fedora/fedora-15-i386/pgdg-fedora91-9.1-4.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.1/fedora/fedora-15-x86_64/pgdg-fedora91-9.1-4.noarch.rpm" - }, - "14" => { - "i386" => "http://yum.postgresql.org/9.1/fedora/fedora-14-i386/pgdg-fedora91-9.1-4.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.1/fedora/fedora-14-x86_64/pgdg-fedora-9.1-2.noarch.rpm" - } - } - }, - "9.0" => { - "centos" => { - "6" => { - "i386" => "http://yum.postgresql.org/9.0/redhat/rhel-6-i386/pgdg-centos90-9.0-5.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.0/redhat/rhel-6-x86_64/pgdg-centos90-9.0-5.noarch.rpm" - }, - "5" => { - "i386" => "http://yum.postgresql.org/9.0/redhat/rhel-5-i386/pgdg-centos90-9.0-5.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.0/redhat/rhel-5-x86_64/pgdg-centos90-9.0-5.noarch.rpm" - }, - "4" => { - "i386" => "http://yum.postgresql.org/9.0/redhat/rhel-4-i386/pgdg-centos90-9.0-5.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.0/redhat/rhel-4-x86_64/pgdg-centos90-9.0-5.noarch.rpm" - } - }, - "redhat" => { - "6" => { - "i386" => "http://yum.postgresql.org/9.0/redhat/rhel-6-i386/pgdg-redhat90-9.0-5.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.0/redhat/rhel-6-x86_64/pgdg-redhat90-9.0-5.noarch.rpm" - }, - "5" => { - "i386" => "http://yum.postgresql.org/9.0/redhat/rhel-5-i386/pgdg-redhat90-9.0-5.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.0/redhat/rhel-5-x86_64/pgdg-redhat90-9.0-5.noarch.rpm" - }, - "4" => { - "i386" => "http://yum.postgresql.org/9.0/redhat/rhel-4-i386/pgdg-redhat90-9.0-5.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.0/redhat/rhel-4-x86_64/pgdg-redhat90-9.0-5.noarch.rpm" - } - }, - "scientific" => { - "6" => { - "i386" => "http://yum.postgresql.org/9.0/redhat/rhel-6-i386/pgdg-sl90-9.0-6.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.0/redhat/rhel-6-x86_64/pgdg-sl90-9.0-6.noarch.rpm" - }, - "5" => { - "i386" => "http://yum.postgresql.org/9.0/redhat/rhel-5-i386/pgdg-sl90-9.0-6.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.0/redhat/rhel-5-x86_64/pgdg-sl90-9.0-6.noarch.rpm" - } - }, - "fedora" => { - "15" => { - "i386" => "http://yum.postgresql.org/9.0/fedora/fedora-15-i386/pgdg-fedora90-9.0-5.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.0/fedora/fedora-15-x86_64/pgdg-fedora90-9.0-5.noarch.rpm" - }, - "14" => { - "i386" => "http://yum.postgresql.org/9.0/fedora/fedora-14-i386/pgdg-fedora90-9.0-5.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/9.0/fedora/fedora-14-x86_64/pgdg-fedora90-9.0-5.noarch.rpm" - } - } - }, - "8.4" => { - "centos" => { - "6" => { - "i386" => "http://yum.postgresql.org/8.4/redhat/rhel-6-i386/pgdg-centos-8.4-3.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/8.4/redhat/rhel-6-x86_64/pgdg-centos-8.4-3.noarch.rpm" - }, - "5" => { - "i386" => "http://yum.postgresql.org/8.4/redhat/rhel-5-i386/pgdg-centos-8.4-3.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/8.4/redhat/rhel-5-x86_64/pgdg-centos-8.4-3.noarch.rpm" - }, - "4" => { - "i386" => "http://yum.postgresql.org/8.4/redhat/rhel-4-i386/pgdg-centos-8.4-3.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/8.4/redhat/rhel-4-x86_64/pgdg-centos-8.4-3.noarch.rpm" - } - }, - "redhat" => { - "6" => { - "i386" => "http://yum.postgresql.org/8.4/redhat/rhel-6-i386/pgdg-redhat-8.4-3.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/8.4/redhat/rhel-6-x86_64/pgdg-redhat-8.4-3.noarch.rpm" - }, - "5" => { - "i386" => "http://yum.postgresql.org/8.4/redhat/rhel-5-i386/pgdg-redhat-8.4-3.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/8.4/redhat/rhel-5-x86_64/pgdg-redhat-8.4-3.noarch.rpm" - }, - "4" => { - "i386" => "http://yum.postgresql.org/8.4/redhat/rhel-4-i386/pgdg-redhat-8.4-3.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/8.4/redhat/rhel-4-x86_64/pgdg-redhat-8.4-3.noarch.rpm" - } - }, - "scientific" => { - "6" => { - "i386" => "http://yum.postgresql.org/8.4/redhat/rhel-6-i386/pgdg-sl84-8.4-4.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/8.4/redhat/rhel-6-x86_64/pgdg-sl84-8.4-4.noarch.rpm" - }, - "5" => { - "i386" => "http://yum.postgresql.org/8.4/redhat/rhel-5-i386/pgdg-sl-8.4-4.noarch.rpm", - "x86_64" => "http://yum.postgresql.org/8.4/redhat/rhel-5-x86_64/pgdg-sl-8.4-4.noarch.rpm" - } - }, - "fedora" => { - "14" => { - "i386" => "http://yum.postgresql.org/8.4/fedora/fedora-14-i386/", - "x86_64" => "http://yum.postgresql.org/8.4/fedora/fedora-14-x86_64/" - }, - "13" => { - "i386" => "http://yum.postgresql.org/8.4/fedora/fedora-13-i386/", - "x86_64" => "http://yum.postgresql.org/8.4/fedora/fedora-13-x86_64/" - }, - "12" => { - "i386" => "http://yum.postgresql.org/8.4/fedora/fedora-12-i386/", - "x86_64" => "http://yum.postgresql.org/8.4/fedora/fedora-12-x86_64/" - }, - "8" => { - "i386" => "http://yum.postgresql.org/8.4/fedora/fedora-8-i386/", - "x86_64" => "http://yum.postgresql.org/8.4/fedora/fedora-8-x86_64/" - }, - "7" => { - "i386" => "http://yum.postgresql.org/8.4/fedora/fedora-7-i386/", - "x86_64" => "http://yum.postgresql.org/8.4/fedora/fedora-7-x86_64/" - } - } - }, -}; +default['postgresql']['initdb_locale'] = 'UTF-8' diff --git a/cookbooks/postgresql/attributes/yum_pgdg_packages.rb b/cookbooks/postgresql/attributes/yum_pgdg_packages.rb new file mode 100644 index 0000000..04f8155 --- /dev/null +++ b/cookbooks/postgresql/attributes/yum_pgdg_packages.rb @@ -0,0 +1,452 @@ +# The PostgreSQL RPM Building Project built repository RPMs for easy +# access to the PGDG yum repositories. Links to RPMs for installation +# on the supported version/platform combinations are listed at +# http://yum.postgresql.org/repopackages.php, and the links for +# PostgreSQL 9.2, 9.3 and 9.4 are captured below. +# +default['postgresql']['pgdg']['repo_rpm_url'] = { + "9.4" => { + "redhat" => { + "7" => { + "x86_64" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-7-x86_64/", + "package" => "pgdg-redhat94-9.4-1.noarch.rpm" + } + }, + "6" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-6-i386/", + "package" => "pgdg-redhat94-9.4-1.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-6-x86_64/", + "package" => "pgdg-redhat94-9.4-1.noarch.rpm" + } + }, + "5" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-5-i386/", + "package" => "pgdg-redhat94-9.4-1.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-5-x86_64/", + "package" => "pgdg-redhat94-9.4-1.noarch.rpm" + } + } + }, + "centos" => { + "7" => { + "x86_64" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-7-x86_64/", + "package" => "pgdg-centos94-9.4-1.noarch.rpm" + } + }, + "6" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-6-i386/", + "package" => "pgdg-centos94-9.4-1.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-6-x86_64/", + "package" => "pgdg-centos94-9.4-1.noarch.rpm" + } + }, + "5" => { + "x86_64" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-5-x86_64/", + "package" => "pgdg-centos94-9.4-1.noarch.rpm" + }, + "i386" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-5-i386/", + "package" => "pgdg-centos94-9.4-1.noarch.rpm" + } + } + }, + "fedora" => { + "22" => { + "x86_64" => { + "url" => "http://yum.postgresql.org/9.4/fedora/fedora-22-x86_64/", + "package" => "pgdg-fedora94-9.4-3.noarch.rpm" + } + }, + "21" => { + "x86_64" => { + "url" => "http://yum.postgresql.org/9.4/fedora/fedora-21-x86_64/", + "package" => "pgdg-fedora94-9.4-2.noarch.rpm" + }, + "i386" => { + "url" => "http://yum.postgresql.org/9.4/fedora/fedora-21-i686/", + "package" => "pgdg-fedora94-9.4-2.noarch.rpm" + } + }, + "20" => { + "x86_64" => { + "url" => "http://yum.postgresql.org/9.4/fedora/fedora-20-x86_64/", + "package" => "pgdg-fedora94-9.4-1.noarch.rpm" + }, + "i386" => { + "url" => "http://yum.postgresql.org/9.4/fedora/fedora-20-i686/", + "package" => "pgdg-fedora94-9.4-1.noarch.rpm" + } + } + }, + "amazon" => { + "2015" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-6-i386/", + "package" => "pgdg-ami201503-94-9.4-1.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-6-x86_64/", + "package" => "pgdg-ami201503-94-9.4-1.noarch.rpm" + } + } + }, + "scientific" => { + "7" => { + "x86_64" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-7-x86_64/", + "package" => "pgdg-sl94-9.4-1.noarch.rpm" + } + }, + "6" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-6-i386/", + "package" => "pgdg-sl94-9.4-1.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-6-x86_64/", + "package" => "pgdg-sl94-9.4-1.noarch.rpm" + } + }, + "5" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-5-i386/", + "package" => "pgdg-sl94-9.4-1.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-5-x86_64/", + "package" => "pgdg-sl94-9.4-1.noarch.rpm" + } + } + }, + "oracle" => { + "7" => { + "x86_64" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-7-x86_64/", + "package" => "pgdg-oraclelinux94-9.4-1.noarch.rpm" + } + }, + "6" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-6-i386/", + "package" => "pgdg-oraclelinux94-9.4-1.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.4/redhat/rhel-6-x86_64/", + "package" => "pgdg-oraclelinux94-9.4-1.noarch.rpm" + } + } + } + }, + "9.3" => { + "amazon" => { + "2015" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-6-i386/", + "package" => "pgdg-redhat93-9.3-1.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/", + "package" => "pgdg-redhat93-9.3-1.noarch.rpm" + } + }, + "2014" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-6-i386/", + "package" => "pgdg-redhat93-9.3-1.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/", + "package" => "pgdg-redhat93-9.3-1.noarch.rpm" + } + }, + "2013" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-6-i386/", + "package" => "pgdg-redhat93-9.3-1.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/", + "package" => "pgdg-redhat93-9.3-1.noarch.rpm" + } + } + }, + "centos" => { + "7" => { + "x86_64" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-7-x86_64/", + "package" => "pgdg-centos93-9.3-1.noarch.rpm" + } + }, + "6" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-6-i386/", + "package" => "pgdg-centos93-9.3-1.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/", + "package" => "pgdg-centos93-9.3-1.noarch.rpm" + } + }, + "5" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-5-i386/", + "package" => "pgdg-centos93-9.3-1.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-5-x86_64/", + "package" => "pgdg-centos93-9.3-1.noarch.rpm" + } + } + }, + "redhat" => { + "7" => { + "x86_64" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-7-x86_64/", + "package" => "pgdg-redhat93-9.3-1.noarch.rpm" + } + }, + "6" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-6-i386/", + "package" => "pgdg-redhat93-9.3-1.noarch.rpm", + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/", + "package" => "pgdg-redhat93-9.3-1.noarch.rpm" + } + }, + "5" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-5-i386/", + "package" => "pgdg-redhat93-9.3-1.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-5-x86_64/", + "package" => "pgdg-redhat93-9.3-1.noarch.rpm" + } + } + }, + "oracle" => { + "6" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-6-i386/", + "package" => "pgdg-redhat93-9.3-1.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/", + "package" => "pgdg-redhat93-9.3-1.noarch.rpm" + } + }, + "5" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-5-i386/", + "package" => "pgdg-redhat93-9.3-1.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-5-x86_64/", + "package" => "pgdg-redhat93-9.3-1.noarch.rpm" + } + } + }, + "scientific" => { + "6" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-6-i386/", + "package" => "pgdg-sl93-9.3-1.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/", + "package" => "pgdg-sl93-9.3-1.noarch.rpm" + } + }, + "5" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-5-i386/", + "package" => "pgdg-sl93-9.3-1.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.3/redhat/rhel-5-x86_64/", + "package" => "pgdg-sl93-9.3-1.noarch.rpm" + } + } + }, + "fedora" => { + "20" => { + "x86_64" => { + "url" => "http://yum.postgresql.org/9.3/fedora/fedora-20-x86_64/", + "pakcage" => "pgdg-fedora93-9.3-1.noarch.rpm" + } + }, + "19" => { + "x86_64" => { + "url" => "http://yum.postgresql.org/9.3/fedora/fedora-19-x86_64/", + "pakcage" => "pgdg-fedora93-9.3-1.noarch.rpm" + } + }, + "18" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.3/fedora/fedora-18-i386/", + "package" => "pgdg-fedora93-9.3-1.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.3/fedora/fedora-18-x86_64/", + "package" => "pgdg-fedora93-9.3-1.noarch.rpm" + } + }, + "17" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.3/fedora/fedora-17-i386/", + "package" => "pgdg-fedora93-9.3-1.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.3/fedora/fedora-17-x86_64/", + "package" => "pgdg-fedora93-9.3-1.noarch.rpm" + } + } + } + }, + "9.2" => { + "centos" => { + "6" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.2/redhat/rhel-6-i386/", + "package" => "pgdg-centos92-9.2-7.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.2/redhat/rhel-6-x86_64/", + "package" => "pgdg-centos92-9.2-7.noarch.rpm" + } + }, + "5" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.2/redhat/rhel-5-i386/", + "package" => "pgdg-centos92-9.2-7.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.2/redhat/rhel-5-x86_64/", + "package" => "pgdg-centos92-9.2-7.noarch.rpm" + } + } + }, + "redhat" => { + "6" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.2/redhat/rhel-6-i386/", + "package" => "pgdg-redhat92-9.2-7.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.2/redhat/rhel-6-x86_64/", + "package" => "pgdg-redhat92-9.2-7.noarch.rpm" + } + }, + "5" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.2/redhat/rhel-5-i386/", + "package" => "pgdg-redhat92-9.2-7.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.2/redhat/rhel-5-x86_64/", + "package" => "pgdg-redhat92-9.2-7.noarch.rpm" + } + } + }, + "oracle" => { + "6" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.2/redhat/rhel-6-i386/", + "package" => "pgdg-redhat92-9.2-7.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.2/redhat/rhel-6-x86_64/", + "package" => "pgdg-redhat92-9.2-7.noarch.rpm" + } + }, + "5" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.2/redhat/rhel-5-i386/", + "package" => "pgdg-redhat92-9.2-7.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.2/redhat/rhel-5-x86_64/", + "package" => "pgdg-redhat92-9.2-7.noarch.rpm" + } + } + }, + "scientific" => { + "6" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.2/redhat/rhel-6-i386/", + "package" => "pgdg-sl92-9.2-8.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.2/redhat/rhel-6-x86_64/", + "package" => "pgdg-sl92-9.2-8.noarch.rpm" + } + }, + "5" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.2/redhat/rhel-5-i386/", + "package" => "pgdg-sl92-9.2-8.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.2/redhat/rhel-5-x86_64/", + "package" => "pgdg-sl92-9.2-8.noarch.rpm" + } + } + }, + "fedora" => { + "19" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.2/fedora/fedora-19-i386/", + "package" => "pgdg-fedora92-9.2-6.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.2/fedora/fedora-19-x86_64/", + "package" => "pgdg-fedora92-9.2-6.noarch.rpm" + } + }, + "18" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.2/fedora/fedora-18-i386/", + "package" => "pgdg-fedora92-9.2-6.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.2/fedora/fedora-18-x86_64/", + "package" => "pgdg-fedora92-9.2-6.noarch.rpm" + } + }, + "17" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.2/fedora/fedora-17-i386/", + "package" => "pgdg-fedora92-9.2-6.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.2/fedora/fedora-17-x86_64/", + "package" => "pgdg-fedora92-9.2-5.noarch.rpm" + } + }, + "16" => { + "i386" => { + "url" => "http://yum.postgresql.org/9.2/fedora/fedora-16-i386/", + "package" => "pgdg-fedora92-9.2-5.noarch.rpm" + }, + "x86_64" => { + "url" => "http://yum.postgresql.org/9.2/fedora/fedora-16-x86_64/", + "package" => "pgdg-fedora92-9.2-5.noarch.rpm" + } + } + } + } +} diff --git a/cookbooks/postgresql/files/default/tests/minitest/apt_pgdg_postgresql_test.rb b/cookbooks/postgresql/files/default/tests/minitest/apt_pgdg_postgresql_test.rb index 41f1fcb..551bc6a 100644 --- a/cookbooks/postgresql/files/default/tests/minitest/apt_pgdg_postgresql_test.rb +++ b/cookbooks/postgresql/files/default/tests/minitest/apt_pgdg_postgresql_test.rb @@ -28,12 +28,12 @@ describe 'postgresql::apt_pgdg_postgresql' do file("/etc/apt/sources.list.d/apt.postgresql.org.list").must_exist end - it 'installs postgresql-client-9.3' do - package("postgresql-client-9.3").must_be_installed + it 'installs postgresql-client-9.4' do + package("postgresql-client-9.4").must_be_installed end - it 'makes psql version 9.3 available' do + it 'makes psql version 9.4 available' do psql = shell_out("psql --version") - assert psql.stdout.include?("psql (PostgreSQL) 9.3") + assert psql.stdout.include?("psql (PostgreSQL) 9.4") end end diff --git a/cookbooks/postgresql/files/default/tests/minitest/server_test.rb b/cookbooks/postgresql/files/default/tests/minitest/server_test.rb index 51c3a21..ea50064 100644 --- a/cookbooks/postgresql/files/default/tests/minitest/server_test.rb +++ b/cookbooks/postgresql/files/default/tests/minitest/server_test.rb @@ -30,6 +30,7 @@ describe 'postgresql::server' do end it 'can connect to postgresql' do + Gem.clear_paths require 'pg' conn = PG::Connection.new( :host => 'localhost', diff --git a/cookbooks/postgresql/libraries/default.rb b/cookbooks/postgresql/libraries/default.rb index 176ff72..24b0e1b 100644 --- a/cookbooks/postgresql/libraries/default.rb +++ b/cookbooks/postgresql/libraries/default.rb @@ -348,30 +348,6 @@ def extension_installed?(pg_ext) end end -###################################### -# Function to build information needed to install RPM for PGDG yum repository, -# since PGDG supports several versions of PostgreSQL, platforms, platform versions -# and architectures. -# Links to RPMs for installation are in an attribute so that new versions/platforms -# can be more easily added. (See attributes/default.rb) -def pgdgrepo_rpm_info - repo_rpm_url = node['postgresql']['pgdg']['repo_rpm_url']. - fetch(node['postgresql']['version']). # e.g., fetch for "9.1" - fetch(node['platform']). # e.g., fetch for "centos" - fetch(node['platform_version'].to_f.to_i.to_s). # e.g., fetch for "5" (truncated "5.7") - fetch(node['kernel']['machine']) # e.g., fetch for "i386" or "x86_64" - - # Extract the filename portion from the URL for the PGDG repository RPM. - # E.g., repo_rpm_filename = "pgdg-centos92-9.2-6.noarch.rpm" - repo_rpm_filename = File.basename(repo_rpm_url) - - # Extract the package name from the URL for the PGDG repository RPM. - # E.g., repo_rpm_package = "pgdg-centos92" - repo_rpm_package = repo_rpm_filename.split(/-/,3)[0..1].join('-') - - return [ repo_rpm_url, repo_rpm_filename, repo_rpm_package ] -end - # End the Opscode::PostgresqlHelpers module end end diff --git a/cookbooks/postgresql/metadata.json b/cookbooks/postgresql/metadata.json index 5989b72..0af3c80 100644 --- a/cookbooks/postgresql/metadata.json +++ b/cookbooks/postgresql/metadata.json @@ -1,15 +1,16 @@ { "name": "postgresql", "description": "Installs and configures postgresql for clients or servers", - "long_description": "Description\n===========\n\nInstalls and configures PostgreSQL as a client or a server.\n\nRequirements\n============\n\n## Platforms\n\n* Debian, Ubuntu\n* Red Hat/CentOS/Scientific (6.0+ required) - \"EL6-family\"\n* Fedora\n* SUSE\n\nTested on:\n\n* Ubuntu 10.04, 11.10, 12.04, 14.04, 14.10\n* Red Hat 6.1, Scientific 6.1, CentOS 6.3\n\n## Cookbooks\n\nRequires Opscode's `openssl` cookbook for secure password generation.\n\nRequires a C compiler and development headers in order to build the\n`pg` RubyGem to provide Ruby bindings in the `ruby` recipe.\n\nOpscode's `build-essential` cookbook provides this functionality on\nDebian, Ubuntu, and EL6-family.\n\nWhile not required, Opscode's `database` cookbook contains resources\nand providers that can interact with a PostgreSQL database. This\ncookbook is a dependency of database.\n\nAttributes\n==========\n\nThe following attributes are set based on the platform, see the\n`attributes/default.rb` file for default values.\n\n* `node['postgresql']['version']` - version of postgresql to manage\n* `node['postgresql']['dir']` - home directory of where postgresql\n data and configuration lives.\n\n* `node['postgresql']['client']['packages']` - An array of package names\n that should be installed on \"client\" systems.\n* `node['postgresql']['server']['packages']` - An array of package names\n that should be installed on \"server\" systems.\n* `node['postgresql']['server']['config_change_notify']` - Type of\n notification triggered when a config file changes.\n* `node['postgresql']['contrib']['packages']` - An array of package names\n that could be installed on \"server\" systems for useful sysadmin tools.\n\n* `node['postgresql']['enable_pgdg_apt']` - Whether to enable the apt repo\n by the PostgreSQL Global Development Group, which contains newer versions\n of PostgreSQL.\n\n* `node['postgresql']['enable_pgdg_yum']` - Whether to enable the yum repo\n by the PostgreSQL Global Development Group, which contains newer versions\n of PostgreSQL.\n\n* `node['postgresql']['initdb_locale']` - Sets the default locale for the\n database cluster. If this attribute is not specified, the locale is\n inherited from the environment that initdb runs in. Sometimes you must\n have a system locale that is not what you want for your database cluster,\n and this attribute addresses that scenario. Valid only for EL-family\n distros (RedHat/Centos/etc.).\n\nThe following attributes are generated in\n`recipe[postgresql::server]`.\n\n* `node['postgresql']['password']['postgres']` - randomly generated\n password by the `openssl` cookbook's library.\n (TODO: This is broken, as it disables the password.)\n\nConfiguration\n-------------\n\nThe `postgresql.conf` and `pg_hba.conf` files are dynamically\ngenerated from attributes. Each key in `node['postgresql']['config']`\nis a postgresql configuration directive, and will be rendered in the\nconfig file. For example, the attribute:\n\n node['postgresql']['config']['listen_addresses'] = 'localhost'\n\nWill result in the following line in the `postgresql.conf` file:\n\n listen_addresses = 'localhost'\n\nThe attributes file contains default values for Debian and RHEL\nplatform families (per the `node['platform_family']`). These defaults\nhave disparity between the platforms because they were originally\nextracted from the postgresql.conf files in the previous version of\nthis cookbook, which differed in their default config. The resulting\nconfiguration files will be the same as before, but the content will\nbe dynamically rendered from the attributes. The helpful commentary\nwill no longer be present. You should consult the PostgreSQL\ndocumentation for specific configuration details.\n\nSee __Recipes__ `config_initdb` and `config_pgtune` below to\nauto-generate many postgresql.conf settings.\n\nFor values that are \"on\" or \"off\", they should be specified as literal\n`true` or `false`. String values will be used with single quotes. Any\nconfiguration option set to the literal `nil` will be skipped\nentirely. All other values (e.g., numeric literals) will be used as\nis. So for example:\n\n node.default['postgresql']['config']['logging_collector'] = true\n node.default['postgresql']['config']['datestyle'] = 'iso, mdy'\n node.default['postgresql']['config']['ident_file'] = nil\n node.default['postgresql']['config']['port'] = 5432\n\nWill result in the following config lines:\n\n logging_collector = 'on'\n datestyle = 'iso,mdy'\n port = 5432\n\n(no line printed for `ident_file` as it is `nil`)\n\nNote that the `unix_socket_directory` configuration was renamed to\n`unix_socket_directories` in Postgres 9.3 so make sure to use the\n`node['postgresql']['unix_socket_directories']` attribute instead of\n`node['postgresql']['unix_socket_directory']`.\n\nThe `pg_hba.conf` file is dynamically generated from the\n`node['postgresql']['pg_hba']` attribute. This attribute must be an\narray of hashes, each hash containing the authorization data. As it is\nan array, you can append to it in your own recipes. The hash keys in\nthe array must be symbols. Each hash will be written as a line in\n`pg_hba.conf`. For example, this entry from\n`node['postgresql']['pg_hba']`:\n\n [{:comment => '# Optional comment',\n :type => 'local', :db => 'all', :user => 'postgres', :addr => nil, :method => 'md5'}]\n\nWill result in the following line in `pg_hba.conf`:\n\n # Optional comment\n local all postgres md5\n\nUse `nil` if the CIDR-ADDRESS should be empty (as above).\nDon't provide a comment if none is desired in the `pg_hba.conf` file.\n\nNote that the following authorization rule is supplied automatically by\nthe cookbook template. The cookbook needs this to execute SQL in the\nPostgreSQL server without supplying the clear-text password (which isn't\nknown by the cookbook). Therefore, your `node['postgresql']['pg_hba']`\nattributes don't need to specify this authorization rule:\n\n # \"local\" is for Unix domain socket connections only\n local all all ident\n\n(By the way, the template uses `peer` instead of `ident` for PostgreSQL-9.1\nand above, which has the same effect.)\n\nRecipes\n=======\n\ndefault\n-------\n\nIncludes the client recipe.\n\nclient\n------\n\nInstalls the packages defined in the\n`node['postgresql']['client']['packages']` attribute.\n\nruby\n----\n\n**NOTE** This recipe may not currently work when installing Chef with\n the\n [\"Omnibus\" full stack installer](http://opscode.com/chef/install) on\n some platforms due to an incompatibility with OpenSSL. See\n [COOK-1406](http://tickets.opscode.com/browse/COOK-1406). You can\n build from source into the Chef omnibus installation to work around\n this issue.\n\nInstall the `pg` gem under Chef's Ruby environment so it can be used\nin other recipes. The build-essential packages and postgresql client\npackages will be installed during the compile phase, so that the\nnative extensions of `pg` can be compiled.\n\nserver\n------\n\nIncludes the `server_debian` or `server_redhat` recipe to get the\nappropriate server packages installed and service managed. Also\nmanages the configuration for the server:\n\n* generates a strong default password (via `openssl`) for `postgres`\n (TODO: This is broken, as it disables the password.)\n* sets the password for postgres\n* manages the `postgresql.conf` file.\n* manages the `pg_hba.conf` file.\n\nserver\\_debian\n--------------\n\nInstalls the postgresql server packages and sets up the service. You\nshould include the `postgresql::server` recipe, which will include\nthis on Debian platforms.\n\nserver\\_redhat\n--------------\n\nManages the postgres user and group (with UID/GID 26, per RHEL package\nconventions), installs the postgresql server packages, initializes the\ndatabase, and manages the postgresql service. You should include the\n`postgresql::server` recipe, which will include this on RHEL/Fedora\nplatforms.\n\nconfig\\_initdb\n--------------\n\nTakes locale and timezone settings from the system configuration.\nThis recipe creates `node.default['postgresql']['config']` attributes\nthat conform to the system's locale and timezone. In addition, this\nrecipe creates the same error reporting and logging settings that\n`initdb` provided: a rotation of 7 days of log files named\npostgresql-Mon.log, etc.\n\nThe default attributes created by this recipe are easy to override with\nnormal attributes because of Chef attribute precedence. For example,\nsuppose a DBA wanted to keep log files indefinitely, rolling over daily\nor when growing to 10MB. The Chef installation could include the\n`postgresql::config_initdb` recipe for the locale and timezone settings,\nbut customize the logging settings with these node JSON attributes:\n\n \"postgresql\": {\n \"config\": {\n \"log_rotation_age\": \"1d\",\n \"log_rotation_size\": \"10MB\",\n \"log_filename\": \"postgresql-%Y-%m-%d_%H%M%S.log\"\n }\n }\n\nCredits: This `postgresql::config_initdb` recipe is based on algorithms\nin the [source code](http://doxygen.postgresql.org/initdb_8c_source.html)\nfor the PostgreSQL `initdb` utility.\n\nconfig\\_pgtune\n--------------\n\nPerformance tuning.\nTakes the wimpy default postgresql.conf and expands the database server\nto be as powerful as the hardware it's being deployed on. This recipe\ncreates a baseline configuration of `node.default['postgresql']['config']`\nattributes in the right general range for a dedicated Postgresql system.\nMost installations won't need additional performance tuning.\n\nThe only decision you need to make is to choose a `db_type` from the\nfollowing database workloads. (See the recipe code comments for more\ndetailed descriptions.)\n\n * \"dw\" -- Data Warehouse\n * \"oltp\" -- Online Transaction Processing\n * \"web\" -- Web Application\n * \"mixed\" -- Mixed DW and OLTP characteristics\n * \"desktop\" -- Not a dedicated database\n\nThis recipe uses a performance model with three input parameters.\nThese node attributes are completely optional, but it is obviously\nimportant to choose the `db_type` correctly:\n\n * `node['postgresql']['config_pgtune']['db_type']` --\n Specifies database type from the list of five choices above.\n If not specified, the default is \"mixed\".\n\n * `node['postgresql']['config_pgtune']['max_connections']` --\n Specifies maximum number of connections expected.\n If not specified, it depends on database type:\n \"web\":200, \"oltp\":300, \"dw\":20, \"mixed\":80, \"desktop\":5\n\n * `node['postgresql']['config_pgtune']['total_memory']` --\n Specifies total system memory in kB. (E.g., \"49416564kB\".)\n If not specified, it will be taken from Ohai automatic attributes.\n This could be used to tune a system that isn't a dedicated database.\n\nThe default attributes created by this recipe are easy to override with\nnormal attributes because of Chef attribute precedence. For example, if\nyou are running application benchmarks to try different buffer cache\nsizes, you would experiment with this node JSON attribute:\n\n \"postgresql\": {\n \"config\": {\n \"shared_buffers\": \"3GB\"\n }\n }\n\nNote that the recipe uses `max_connections` in its computations. If\nyou want to override that setting, you should specify\n`node['postgresql']['config_pgtune']['max_connections']` instead of\n`node['postgresql']['config']['max_connections']`.\n\nCredits: This `postgresql::config_pgtune` recipe is based on the\n[pgtune python script](https://github.com/gregs1104/pgtune)\ndeveloped by\n[Greg Smith](http://notemagnet.blogspot.com/2008/11/automating-initial-postgresqlconf.html)\nand\n[other pgsql-hackers](http://www.postgresql.org/message-id/491C6CDC.8090506@agliodbs.com).\n\ncontrib\n-------\n\nInstalls the packages defined in the\n`node['postgresql']['contrib']['packages']` attribute. The contrib\ndirectory of the PostgreSQL distribution includes porting tools,\nanalysis utilities, and plug-in features that database engineers often\nrequire. Some (like `pgbench`) are executable. Others (like\n`pg_buffercache`) would need to be installed into the database.\n\nAlso installs any contrib module extensions defined in the\n`node['postgresql']['contrib']['extensions']` attribute. These will be\navailable in any subsequently created databases in the cluster, because\nthey will be installed into the `template1` database using the\n`CREATE EXTENSION` command. For example, it is often necessary/helpful\nfor problem troubleshooting and maintenance planning to install the\nviews and functions in these [standard instrumentation extensions]\n(http://www.postgresql.org/message-id/flat/4DC32600.6080900@pgexperts.com#4DD3D6C6.5060006@2ndquadrant.com):\n\n node['postgresql']['contrib']['extensions'] = [\n \"pageinspect\",\n \"pg_buffercache\",\n \"pg_freespacemap\",\n \"pgrowlocks\",\n \"pg_stat_statements\",\n \"pgstattuple\"\n ]\n\nNote that the `pg_stat_statements` view only works if `postgresql.conf`\nloads its shared library, which can be done with this node attribute:\n\n node['postgresql']['config']['shared_preload_libraries'] = 'pg_stat_statements'\n\nIf using `shared_preload_libraries` in combination with the `contrib` recipe,\nmake sure that the `contrib` recipe is called before the `server` recipe (to\nensure the dependencies are installed and setup in order).\n\napt\\_pgdg\\_postgresql\n----------------------\n\nEnables the PostgreSQL Global Development Group yum repository\nmaintained by Devrim Gündüz for updated PostgreSQL packages.\n(The PGDG is the groups that develops PostgreSQL.)\nAutomatically included if the `node['postgresql']['enable_pgdg_apt']`\nattribute is true. Also set the\n`node['postgresql']['client']['packages']` and\n`node['postgresql']['server]['packages']` to the list of packages to\nuse from this repository, and set the `node['postgresql']['version']`\nattribute to the version to use (e.g., \"9.2\").\n\nyum\\_pgdg\\_postgresql\n---------------------\n\nEnables the PostgreSQL Global Development Group yum repository\nmaintained by Devrim Gündüz for updated PostgreSQL packages.\n(The PGDG is the groups that develops PostgreSQL.)\nAutomatically included if the `node['postgresql']['enable_pgdg_yum']`\nattribute is true. Also use `override_attributes` to set a number of\nvalues that will need to have embedded version numbers. For example:\n\n node['postgresql']['enable_pgdg_yum'] = true\n node['postgresql']['version'] = \"9.2\"\n node['postgresql']['dir'] = \"/var/lib/pgsql/9.2/data\"\n node['postgresql']['config']['data_directory'] = node['postgresql']['dir']\n node['postgresql']['client']['packages'] = [\"postgresql92\", \"postgresql92-devel\"]\n node['postgresql']['server']['packages'] = [\"postgresql92-server\"]\n node['postgresql']['server']['service_name'] = \"postgresql-9.2\"\n node['postgresql']['contrib']['packages'] = [\"postgresql92-contrib\"]\n\nYou may set `node['postgresql']['pgdg']['repo_rpm_url']` attributes\nto pick up recent [PGDG repo packages](http://yum.postgresql.org/repopackages.php).\n\nResources/Providers\n===================\n\nSee the [database](http://community.opscode.com/cookbooks/database)\nfor resources and providers that can be used for managing PostgreSQL\nusers and databases.\n\nUsage\n=====\n\nOn systems that need to connect to a PostgreSQL database, add to a run\nlist `recipe[postgresql]` or `recipe[postgresql::client]`.\n\nOn systems that should be PostgreSQL servers, use\n`recipe[postgresql::server]` on a run list. This recipe does set a\npassword for the `postgres` user.\nIf you're using `chef server`, if the attribute\n`node['postgresql']['password']['postgres']` is not found,\nthe recipe generates a random password and performs a node.save.\n(TODO: This is broken, as it disables the password.)\nIf you're using `chef-solo`, you'll need\nto set the attribute `node['postgresql']['password']['postgres']` in\nyour node's `json_attribs` file or in a role.\n\nOn Debian family systems, SSL will be enabled, as the packages on\nDebian/Ubuntu also generate the SSL certificates. If you use another\nplatform and wish to use SSL in postgresql, then generate your SSL\ncertificates and distribute them in your own cookbook, and set the\n`node['postgresql']['config']['ssl']` attribute to true in your\nrole/cookboook/node.\n\nOn server systems, the postgres server is restarted when a configuration\nfile changes. This can be changed to reload only by setting the\nfollowing attribute:\n\n node['postgresql']['server']['config_change_notify'] = :reload\n\nChef Solo Note\n==============\n\nThe following node attribute is stored on the Chef Server when using\n`chef-client`. Because `chef-solo` does not connect to a server or\nsave the node object at all, to have the password persist across\n`chef-solo` runs, you must specify them in the `json_attribs` file\nused. For Example:\n\n {\n \"postgresql\": {\n \"password\": {\n \"postgres\": \"iloverandompasswordsbutthiswilldo\"\n }\n },\n \"run_list\": [\"recipe[postgresql::server]\"]\n }\n\nThat should actually be the \"encrypted password\" instead of cleartext,\nso you should generate it as an md5 hash using the PostgreSQL algorithm.\n\n* You could copy the md5-hashed password from an existing postgres\ndatabase if you have `postgres` access and want to use the same password:
\n`select * from pg_shadow where usename='postgres';`\n* You can run this from any postgres database session to use a new password:
\n`select 'md5'||md5('iloverandompasswordsbutthiswilldo'||'postgres');`\n* You can run this from a linux commandline:
\n`echo -n 'iloverandompasswordsbutthiswilldo''postgres' | openssl md5 | sed -e 's/.* /md5/'`\n\nLicense and Author\n==================\n\n- Author:: Joshua Timberman ()\n- Author:: Lamont Granquist ()\n- Author:: Chris Roberts ()\n- Author:: David Crane ()\n- Author:: Aaron Baer ()\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", + "long_description": "Description\n===========\n\nInstalls and configures PostgreSQL as a client or a server.\n\nRequirements\n============\n\n## Platforms\n\n* Debian, Ubuntu\n* Red Hat/CentOS/Scientific (6.0+ required) - \"EL6-family\"\n* Fedora\n* SUSE\n\nTested on:\n\n* Ubuntu 12.04, 14.04, 14.10\n* Red Hat 6.1, Scientific 6.1, CentOS 6.3, 7.0, OpenSuse\n\n## Cookbooks\n\nRequires Opscode's `openssl` cookbook for secure password generation.\n\nRequires a C compiler and development headers in order to build the\n`pg` RubyGem to provide Ruby bindings in the `ruby` recipe.\n\nOpscode's `build-essential` cookbook provides this functionality on\nDebian, Ubuntu, and EL6-family.\n\nWhile not required, Opscode's `database` cookbook contains resources\nand providers that can interact with a PostgreSQL database. This\ncookbook is a dependency of database.\n\nAttributes\n==========\n\nThe following attributes are set based on the platform, see the\n`attributes/default.rb` file for default values.\n\n* `node['postgresql']['version']` - version of postgresql to manage\n* `node['postgresql']['dir']` - home directory of where postgresql\n data and configuration lives.\n\n* `node['postgresql']['client']['packages']` - An array of package names\n that should be installed on \"client\" systems.\n* `node['postgresql']['server']['packages']` - An array of package names\n that should be installed on \"server\" systems.\n* `node['postgresql']['server']['config_change_notify']` - Type of\n notification triggered when a config file changes.\n* `node['postgresql']['contrib']['packages']` - An array of package names\n that could be installed on \"server\" systems for useful sysadmin tools.\n\n* `node['postgresql']['enable_pgdg_apt']` - Whether to enable the apt repo\n by the PostgreSQL Global Development Group, which contains newer versions\n of PostgreSQL.\n\n* `node['postgresql']['enable_pgdg_yum']` - Whether to enable the yum repo\n by the PostgreSQL Global Development Group, which contains newer versions\n of PostgreSQL.\n\n* `node['postgresql']['initdb_locale']` - Sets the default locale for the\n database cluster. If this attribute is not specified, the locale is\n inherited from the environment that initdb runs in. Sometimes you must\n have a system locale that is not what you want for your database cluster,\n and this attribute addresses that scenario. Valid only for EL-family\n distros (RedHat/Centos/etc.).\n\nThe following attributes are generated in\n`recipe[postgresql::server]`.\n\nConfiguration\n-------------\n\nThe `postgresql.conf` and `pg_hba.conf` files are dynamically\ngenerated from attributes. Each key in `node['postgresql']['config']`\nis a postgresql configuration directive, and will be rendered in the\nconfig file. For example, the attribute:\n\n node['postgresql']['config']['listen_addresses'] = 'localhost'\n\nWill result in the following line in the `postgresql.conf` file:\n\n listen_addresses = 'localhost'\n\nThe attributes file contains default values for Debian and RHEL\nplatform families (per the `node['platform_family']`). These defaults\nhave disparity between the platforms because they were originally\nextracted from the postgresql.conf files in the previous version of\nthis cookbook, which differed in their default config. The resulting\nconfiguration files will be the same as before, but the content will\nbe dynamically rendered from the attributes. The helpful commentary\nwill no longer be present. You should consult the PostgreSQL\ndocumentation for specific configuration details.\n\nSee __Recipes__ `config_initdb` and `config_pgtune` below to\nauto-generate many postgresql.conf settings.\n\nFor values that are \"on\" or \"off\", they should be specified as literal\n`true` or `false`. String values will be used with single quotes. Any\nconfiguration option set to the literal `nil` will be skipped\nentirely. All other values (e.g., numeric literals) will be used as\nis. So for example:\n\n node.default['postgresql']['config']['logging_collector'] = true\n node.default['postgresql']['config']['datestyle'] = 'iso, mdy'\n node.default['postgresql']['config']['ident_file'] = nil\n node.default['postgresql']['config']['port'] = 5432\n\nWill result in the following config lines:\n\n logging_collector = 'on'\n datestyle = 'iso,mdy'\n port = 5432\n\n(no line printed for `ident_file` as it is `nil`)\n\nNote that the `unix_socket_directory` configuration was renamed to\n`unix_socket_directories` in Postgres 9.3 so make sure to use the\n`node['postgresql']['unix_socket_directories']` attribute instead of\n`node['postgresql']['unix_socket_directory']`.\n\nThe `pg_hba.conf` file is dynamically generated from the\n`node['postgresql']['pg_hba']` attribute. This attribute must be an\narray of hashes, each hash containing the authorization data. As it is\nan array, you can append to it in your own recipes. The hash keys in\nthe array must be symbols. Each hash will be written as a line in\n`pg_hba.conf`. For example, this entry from\n`node['postgresql']['pg_hba']`:\n\n [{:comment => '# Optional comment',\n :type => 'local', :db => 'all', :user => 'postgres', :addr => nil, :method => 'md5'}]\n\nWill result in the following line in `pg_hba.conf`:\n\n # Optional comment\n local all postgres md5\n\nUse `nil` if the CIDR-ADDRESS should be empty (as above).\nDon't provide a comment if none is desired in the `pg_hba.conf` file.\n\nNote that the following authorization rule is supplied automatically by\nthe cookbook template. The cookbook needs this to execute SQL in the\nPostgreSQL server without supplying the clear-text password (which isn't\nknown by the cookbook). Therefore, your `node['postgresql']['pg_hba']`\nattributes don't need to specify this authorization rule:\n\n # \"local\" is for Unix domain socket connections only\n local all all ident\n\n(By the way, the template uses `peer` instead of `ident` for PostgreSQL-9.1\nand above, which has the same effect.)\n\nRecipes\n=======\n\ndefault\n-------\n\nIncludes the client recipe.\n\nclient\n------\n\nInstalls the packages defined in the\n`node['postgresql']['client']['packages']` attribute.\n\nruby\n----\n\nInstall the `pg` gem under Chef's Ruby environment so it can be used\nin other recipes. The build-essential packages and postgresql client\npackages will be installed during the compile phase, so that the\nnative extensions of `pg` can be compiled.\n\nserver\n------\n\nIncludes the `server_debian` or `server_redhat` recipe to get the\nappropriate server packages installed and service managed. Also\nmanages the configuration for the server:\n\n* generates a strong default password (via `openssl`) for `postgres`\n* sets the password for postgres\n* manages the `postgresql.conf` file.\n* manages the `pg_hba.conf` file.\n\nserver\\_debian\n--------------\n\nInstalls the postgresql server packages and sets up the service. You\nshould include the `postgresql::server` recipe, which will include\nthis on Debian platforms.\n\nserver\\_redhat\n--------------\n\nManages the postgres user and group (with UID/GID 26, per RHEL package\nconventions), installs the postgresql server packages, initializes the\ndatabase, and manages the postgresql service. You should include the\n`postgresql::server` recipe, which will include this on RHEL/Fedora\nplatforms.\n\nconfig\\_initdb\n--------------\n\nTakes locale and timezone settings from the system configuration.\nThis recipe creates `node.default['postgresql']['config']` attributes\nthat conform to the system's locale and timezone. In addition, this\nrecipe creates the same error reporting and logging settings that\n`initdb` provided: a rotation of 7 days of log files named\npostgresql-Mon.log, etc.\n\nThe default attributes created by this recipe are easy to override with\nnormal attributes because of Chef attribute precedence. For example,\nsuppose a DBA wanted to keep log files indefinitely, rolling over daily\nor when growing to 10MB. The Chef installation could include the\n`postgresql::config_initdb` recipe for the locale and timezone settings,\nbut customize the logging settings with these node JSON attributes:\n\n \"postgresql\": {\n \"config\": {\n \"log_rotation_age\": \"1d\",\n \"log_rotation_size\": \"10MB\",\n \"log_filename\": \"postgresql-%Y-%m-%d_%H%M%S.log\"\n }\n }\n\nCredits: This `postgresql::config_initdb` recipe is based on algorithms\nin the [source code](http://doxygen.postgresql.org/initdb_8c_source.html)\nfor the PostgreSQL `initdb` utility.\n\nconfig\\_pgtune\n--------------\n\nPerformance tuning.\nTakes the wimpy default postgresql.conf and expands the database server\nto be as powerful as the hardware it's being deployed on. This recipe\ncreates a baseline configuration of `node.default['postgresql']['config']`\nattributes in the right general range for a dedicated Postgresql system.\nMost installations won't need additional performance tuning.\n\nThe only decision you need to make is to choose a `db_type` from the\nfollowing database workloads. (See the recipe code comments for more\ndetailed descriptions.)\n\n * \"dw\" -- Data Warehouse\n * \"oltp\" -- Online Transaction Processing\n * \"web\" -- Web Application\n * \"mixed\" -- Mixed DW and OLTP characteristics\n * \"desktop\" -- Not a dedicated database\n\nThis recipe uses a performance model with three input parameters.\nThese node attributes are completely optional, but it is obviously\nimportant to choose the `db_type` correctly:\n\n * `node['postgresql']['config_pgtune']['db_type']` --\n Specifies database type from the list of five choices above.\n If not specified, the default is \"mixed\".\n\n * `node['postgresql']['config_pgtune']['max_connections']` --\n Specifies maximum number of connections expected.\n If not specified, it depends on database type:\n \"web\":200, \"oltp\":300, \"dw\":20, \"mixed\":80, \"desktop\":5\n\n * `node['postgresql']['config_pgtune']['total_memory']` --\n Specifies total system memory in kB. (E.g., \"49416564kB\".)\n If not specified, it will be taken from Ohai automatic attributes.\n This could be used to tune a system that isn't a dedicated database.\n\nThe default attributes created by this recipe are easy to override with\nnormal attributes because of Chef attribute precedence. For example, if\nyou are running application benchmarks to try different buffer cache\nsizes, you would experiment with this node JSON attribute:\n\n \"postgresql\": {\n \"config\": {\n \"shared_buffers\": \"3GB\"\n }\n }\n\nNote that the recipe uses `max_connections` in its computations. If\nyou want to override that setting, you should specify\n`node['postgresql']['config_pgtune']['max_connections']` instead of\n`node['postgresql']['config']['max_connections']`.\n\nCredits: This `postgresql::config_pgtune` recipe is based on the\n[pgtune python script](https://github.com/gregs1104/pgtune)\ndeveloped by\n[Greg Smith](http://notemagnet.blogspot.com/2008/11/automating-initial-postgresqlconf.html)\nand\n[other pgsql-hackers](http://www.postgresql.org/message-id/491C6CDC.8090506@agliodbs.com).\n\ncontrib\n-------\n\nInstalls the packages defined in the\n`node['postgresql']['contrib']['packages']` attribute. The contrib\ndirectory of the PostgreSQL distribution includes porting tools,\nanalysis utilities, and plug-in features that database engineers often\nrequire. Some (like `pgbench`) are executable. Others (like\n`pg_buffercache`) would need to be installed into the database.\n\nAlso installs any contrib module extensions defined in the\n`node['postgresql']['contrib']['extensions']` attribute. These will be\navailable in any subsequently created databases in the cluster, because\nthey will be installed into the `template1` database using the\n`CREATE EXTENSION` command. For example, it is often necessary/helpful\nfor problem troubleshooting and maintenance planning to install the\nviews and functions in these [standard instrumentation extensions]\n(http://www.postgresql.org/message-id/flat/4DC32600.6080900@pgexperts.com#4DD3D6C6.5060006@2ndquadrant.com):\n\n node['postgresql']['contrib']['extensions'] = [\n \"pageinspect\",\n \"pg_buffercache\",\n \"pg_freespacemap\",\n \"pgrowlocks\",\n \"pg_stat_statements\",\n \"pgstattuple\"\n ]\n\nNote that the `pg_stat_statements` view only works if `postgresql.conf`\nloads its shared library, which can be done with this node attribute:\n\n node['postgresql']['config']['shared_preload_libraries'] = 'pg_stat_statements'\n\nIf using `shared_preload_libraries` in combination with the `contrib` recipe,\nmake sure that the `contrib` recipe is called before the `server` recipe (to\nensure the dependencies are installed and setup in order).\n\napt\\_pgdg\\_postgresql\n----------------------\n\nEnables the PostgreSQL Global Development Group yum repository\nmaintained by Devrim Gündüz for updated PostgreSQL packages.\n(The PGDG is the groups that develops PostgreSQL.)\nAutomatically included if the `node['postgresql']['enable_pgdg_apt']`\nattribute is true. Also set the\n`node['postgresql']['client']['packages']` and\n`node['postgresql']['server]['packages']` to the list of packages to\nuse from this repository, and set the `node['postgresql']['version']`\nattribute to the version to use (e.g., \"9.2\").\n\nyum\\_pgdg\\_postgresql\n---------------------\n\nEnables the PostgreSQL Global Development Group yum repository\nmaintained by Devrim Gündüz for updated PostgreSQL packages.\n(The PGDG is the groups that develops PostgreSQL.)\nAutomatically included if the `node['postgresql']['enable_pgdg_yum']`\nattribute is true. Also use `override_attributes` to set a number of\nvalues that will need to have embedded version numbers. For example:\n\n node['postgresql']['enable_pgdg_yum'] = true\n node['postgresql']['version'] = \"9.2\"\n node['postgresql']['dir'] = \"/var/lib/pgsql/9.2/data\"\n node['postgresql']['config']['data_directory'] = node['postgresql']['dir']\n node['postgresql']['client']['packages'] = [\"postgresql92\", \"postgresql92-devel\"]\n node['postgresql']['server']['packages'] = [\"postgresql92-server\"]\n node['postgresql']['server']['service_name'] = \"postgresql-9.2\"\n node['postgresql']['contrib']['packages'] = [\"postgresql92-contrib\"]\n\nYou may set `node['postgresql']['pgdg']['repo_rpm_url']` attributes\nto pick up recent [PGDG repo packages](http://yum.postgresql.org/repopackages.php).\n\nResources/Providers\n===================\n\nSee the [database](http://community.opscode.com/cookbooks/database)\nfor resources and providers that can be used for managing PostgreSQL\nusers and databases.\n\nUsage\n=====\n\nOn systems that need to connect to a PostgreSQL database, add to a run\nlist `recipe[postgresql]` or `recipe[postgresql::client]`.\n\nOn systems that should be PostgreSQL servers, use\n`recipe[postgresql::server]` on a run list. This recipe does set a\npassword for the `postgres` user.\nIf you're using `chef server`, if the attribute\n`node['postgresql']['password']['postgres']` is not found,\nthe recipe generates a random password and performs a node.save.\n(TODO: This is broken, as it disables the password.)\nIf you're using `chef-solo`, you'll need\nto set the attribute `node['postgresql']['password']['postgres']` in\nyour node's `json_attribs` file or in a role.\n\nOn Debian family systems, SSL will be enabled, as the packages on\nDebian/Ubuntu also generate the SSL certificates. If you use another\nplatform and wish to use SSL in postgresql, then generate your SSL\ncertificates and distribute them in your own cookbook, and set the\n`node['postgresql']['config']['ssl']` attribute to true in your\nrole/cookboook/node.\n\nOn server systems, the postgres server is restarted when a configuration\nfile changes. This can be changed to reload only by setting the\nfollowing attribute:\n\n node['postgresql']['server']['config_change_notify'] = :reload\n\nChef Solo Note\n==============\n\nThe following node attribute is stored on the Chef Server when using\n`chef-client`. Because `chef-solo` does not connect to a server or\nsave the node object at all, to have the password persist across\n`chef-solo` runs, you must specify them in the `json_attribs` file\nused. For Example:\n\n {\n \"postgresql\": {\n \"password\": {\n \"postgres\": \"iloverandompasswordsbutthiswilldo\"\n }\n },\n \"run_list\": [\"recipe[postgresql::server]\"]\n }\n\nThat should actually be the \"encrypted password\" instead of cleartext,\nso you should generate it as an md5 hash using the PostgreSQL algorithm.\n\n* You could copy the md5-hashed password from an existing postgres\ndatabase if you have `postgres` access and want to use the same password:
\n`select * from pg_shadow where usename='postgres';`\n* You can run this from any postgres database session to use a new password:
\n`select 'md5'||md5('iloverandompasswordsbutthiswilldo'||'postgres');`\n* You can run this from a linux commandline:
\n`echo -n 'iloverandompasswordsbutthiswilldo''postgres' | openssl md5 | sed -e 's/.* /md5/'`\n\nLicense and Author\n==================\n\n- Author:: Joshua Timberman ()\n- Author:: Lamont Granquist ()\n- Author:: Chris Roberts ()\n- Author:: David Crane ()\n- Author:: Aaron Baer ()\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": "Heavy Water Operations, LLC", - "maintainer_email": "support@hw-ops.com", + "maintainer_email": "helpdesk@heavywater.io", "license": "Apache 2.0", "platforms": { "ubuntu": "< 14.10", "debian": ">= 0.0.0", "fedora": ">= 0.0.0", "suse": ">= 0.0.0", + "opensuse": ">= 0.0.0", "amazon": ">= 0.0.0", "redhat": "~> 6.0", "centos": "~> 6.0", @@ -19,7 +20,7 @@ "dependencies": { "apt": ">= 1.9.0", "build-essential": ">= 0.0.0", - "openssl": "~> 4.0.0" + "openssl": "~> 4.0" }, "recommendations": { @@ -50,7 +51,7 @@ "postgresql::server_redhat": "Installs postgresql server packages, redhat family style", "postgresql::server_debian": "Installs postgresql server packages, debian family style" }, - "version": "3.4.20", + "version": "4.0.0", "source_url": "", "issues_url": "" } diff --git a/cookbooks/postgresql/metadata.rb b/cookbooks/postgresql/metadata.rb index 6a43ddc..30a4ae0 100644 --- a/cookbooks/postgresql/metadata.rb +++ b/cookbooks/postgresql/metadata.rb @@ -1,10 +1,10 @@ name "postgresql" maintainer "Heavy Water Operations, LLC" -maintainer_email "support@hw-ops.com" +maintainer_email "helpdesk@heavywater.io" 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 "3.4.20" +version "4.0.0" recipe "postgresql", "Includes postgresql::client" recipe "postgresql::ruby", "Installs pg gem for Ruby bindings" recipe "postgresql::client", "Installs postgresql client package(s)" @@ -15,7 +15,7 @@ recipe "postgresql::server_debian", "Installs postgresql server packa supports "ubuntu", "< 14.10" -%w{debian fedora suse amazon}.each do |os| +%w{debian fedora suse opensuse amazon}.each do |os| supports os end @@ -25,4 +25,4 @@ end depends "apt", ">= 1.9.0" depends "build-essential" -depends "openssl", "~> 4.0.0" +depends "openssl", "~> 4.0" diff --git a/cookbooks/postgresql/recipes/ca_certificates.rb b/cookbooks/postgresql/recipes/ca_certificates.rb new file mode 100644 index 0000000..f187281 --- /dev/null +++ b/cookbooks/postgresql/recipes/ca_certificates.rb @@ -0,0 +1,6 @@ +# some older linux distributions have expired certificate bundles +# for pgdg repositories. Upgrading this package before trying to +# install postgresql is necessary. +package "ca-certificates" do + action :upgrade +end diff --git a/cookbooks/postgresql/recipes/client.rb b/cookbooks/postgresql/recipes/client.rb index 5a94780..20d6774 100644 --- a/cookbooks/postgresql/recipes/client.rb +++ b/cookbooks/postgresql/recipes/client.rb @@ -15,18 +15,23 @@ # limitations under the License. # -if platform_family?('debian') && node['postgresql']['version'].to_f > 9.3 - node.default['postgresql']['enable_pgdg_apt'] = true +include_recipe "postgresql::ca_certificates" + +case node['platform_family'] +when 'debian' + if node['postgresql']['version'].to_f > 9.3 + node.set['postgresql']['enable_pgdg_apt'] = true + end + + if node['postgresql']['enable_pgdg_apt'] + include_recipe 'postgresql::apt_pgdg_postgresql' + end +when 'rhel' + if node['postgresql']['enable_pgdg_yum'] + include_recipe 'postgresql::yum_pgdg_postgresql' + end end -if(node['postgresql']['enable_pgdg_apt']) and platform_family?('debian') - include_recipe 'postgresql::apt_pgdg_postgresql' -end - -if(node['postgresql']['enable_pgdg_yum']) and platform_family?('rhel') - include_recipe 'postgresql::yum_pgdg_postgresql' -end - -node['postgresql']['client']['packages'].each do |pg_pack| - package pg_pack +node['postgresql']['client']['packages'].each do |pkg| + package pkg end diff --git a/cookbooks/postgresql/recipes/ruby.rb b/cookbooks/postgresql/recipes/ruby.rb index cf93356..68c9c71 100644 --- a/cookbooks/postgresql/recipes/ruby.rb +++ b/cookbooks/postgresql/recipes/ruby.rb @@ -31,24 +31,50 @@ rescue LoadError node.set['build-essential']['compile_time'] = true include_recipe "build-essential" - include_recipe "postgresql::client" if node['postgresql']['enable_pgdg_yum'] - repo_rpm_url, repo_rpm_filename, repo_rpm_package = pgdgrepo_rpm_info + package "ca-certificates" do + action :nothing + end.run_action(:upgrade) + include_recipe "postgresql::yum_pgdg_postgresql" - resources("remote_file[#{Chef::Config[:file_cache_path]}/#{repo_rpm_filename}]").run_action(:create) - resources("package[#{repo_rpm_package}]").run_action(:install) + + rpm_platform = node['platform'] + rpm_platform_version = node['platform_version'].to_f.to_i.to_s + arch = node['kernel']['machine'] + + resources("remote_file[#{Chef::Config[:file_cache_path]}/#{node[:postgresql][:pgdg][:repo_rpm_url][node[:postgresql][:version]][rpm_platform][rpm_platform_version][arch][:package]}]").run_action(:create) + resources("package[#{node[:postgresql][:pgdg][:repo_rpm_url][node[:postgresql][:version]][rpm_platform][rpm_platform_version][arch][:package]}]").run_action(:install) + ENV['PATH'] = "/usr/pgsql-#{node['postgresql']['version']}/bin:#{ENV['PATH']}" + + node['postgresql']['client']['packages'].each do |pkg| + package pkg do + action :nothing + end.run_action(:install) + end + end if node['postgresql']['enable_pgdg_apt'] include_recipe "postgresql::apt_pgdg_postgresql" resources("file[remove deprecated Pitti PPA apt repository]").run_action(:delete) resources("apt_repository[apt.postgresql.org]").run_action(:add) + + node['postgresql']['client']['packages'].each do |pkg| + package pkg do + action :nothing + end.run_action(:install) + end + end - node['postgresql']['client']['packages'].each do |pg_pack| - resources("package[#{pg_pack}]").run_action(:install) + include_recipe "postgresql::client" + + node['postgresql']['client']['packages'].each do |pkg| + package pkg do + action :nothing + end.run_action(:install) end begin diff --git a/cookbooks/postgresql/recipes/server.rb b/cookbooks/postgresql/recipes/server.rb index 2a9a1b5..211d170 100644 --- a/cookbooks/postgresql/recipes/server.rb +++ b/cookbooks/postgresql/recipes/server.rb @@ -15,7 +15,9 @@ # limitations under the License. # -::Chef::Recipe.send(:include, Opscode::OpenSSL::Password) +include_recipe "postgresql::ca_certificates" + +::Chef::Recipe.send(:include, OpenSSLCookbook::RandomPassword) include_recipe "postgresql::client" @@ -42,7 +44,7 @@ else # useful if it weren't saved as clear text in Chef Server for later # retrieval. unless node.key?('postgresql') && node['postgresql'].key?('password') && node['postgresql']['password'].key?('postgres') - node.set_unless['postgresql']['password']['postgres'] = secure_password + node.set_unless['postgresql']['password']['postgres'] = random_password(length: 20, mode: :base64) node.save end end @@ -50,10 +52,16 @@ end # Include the right "family" recipe for installing the server # since they do things slightly differently. case node['platform_family'] -when "rhel", "fedora", "suse" +when "rhel", "fedora" + node.set['postgresql']['dir'] = "/var/lib/pgsql/#{node['postgresql']['version']}/data" + node.set['postgresql']['config']['data_directory'] = "/var/lib/pgsql/#{node['postgresql']['version']}/data" include_recipe "postgresql::server_redhat" when "debian" + node.set['postgresql']['config']['data_directory'] = "/var/lib/postgresql/#{node['postgresql']['version']}/main" include_recipe "postgresql::server_debian" +when 'suse' + node.set['postgresql']['config']['data_directory'] = node['postgresql']['dir'] + include_recipe "postgresql::server_redhat" end # Versions prior to 9.2 do not have a config file option to set the SSL @@ -81,7 +89,7 @@ end bash "assign-postgres-password" do user 'postgres' code <<-EOH - echo "ALTER ROLE postgres ENCRYPTED PASSWORD '#{node['postgresql']['password']['postgres']}';" | psql -p #{node['postgresql']['config']['port']} + echo "ALTER ROLE postgres ENCRYPTED PASSWORD \'#{node['postgresql']['password']['postgres']}\';" | psql -p #{node['postgresql']['config']['port']} EOH action :run not_if "ls #{node['postgresql']['config']['data_directory']}/recovery.conf" diff --git a/cookbooks/postgresql/recipes/server_conf.rb b/cookbooks/postgresql/recipes/server_conf.rb index 68a6b1f..39af1a6 100644 --- a/cookbooks/postgresql/recipes/server_conf.rb +++ b/cookbooks/postgresql/recipes/server_conf.rb @@ -17,6 +17,28 @@ change_notify = node['postgresql']['server']['config_change_notify'] +# There are some configuration items which depend on correctly evaluating the intended version being installed +if node['platform_family'] == 'debian' + + node.set['postgresql']['config']['hba_file'] = "/etc/postgresql/#{node['postgresql']['version']}/main/pg_hba.conf" + node.set['postgresql']['config']['ident_file'] = "/etc/postgresql/#{node['postgresql']['version']}/main/pg_ident.conf" + node.set['postgresql']['config']['external_pid_file'] = "/var/run/postgresql/#{node['postgresql']['version']}-main.pid" + + if node['postgresql']['version'].to_f < 9.3 + node.set['postgresql']['config']['unix_socket_directory'] = '/var/run/postgresql' + else + node.set['postgresql']['config']['unix_socket_directories'] = '/var/run/postgresql' + end + + node.set['postgresql']['config']['max_fsm_pages'] = 153600 if node['postgresql']['version'].to_f < 8.4 + + if node['postgresql']['config']['ssl'] + node.set['postgresql']['config']['ssl_cert_file'] = '/etc/ssl/certs/ssl-cert-snakeoil.pem' if node['postgresql']['version'].to_f >= 9.2 + node.set['postgresql']['config']['ssl_key_file'] = '/etc/ssl/private/ssl-cert-snakeoil.key'if node['postgresql']['version'].to_f >= 9.2 + end + +end + template "#{node['postgresql']['dir']}/postgresql.conf" do source "postgresql.conf.erb" owner "postgres" diff --git a/cookbooks/postgresql/recipes/server_redhat.rb b/cookbooks/postgresql/recipes/server_redhat.rb index 0795b6f..1c0834c 100644 --- a/cookbooks/postgresql/recipes/server_redhat.rb +++ b/cookbooks/postgresql/recipes/server_redhat.rb @@ -18,9 +18,10 @@ include_recipe "postgresql::client" svc_name = node['postgresql']['server']['service_name'] -dir = node['postgresql']['dir'] initdb_locale = node['postgresql']['initdb_locale'] +shortver = node['postgresql']['version'].split('.').join + # Create a group and user like the package will. # Otherwise the templates fail. @@ -38,7 +39,7 @@ user "postgres" do supports :manage_home => false end -directory dir do +directory node['postgresql']['config']['data_directory'] do owner "postgres" group "postgres" recursive true @@ -51,11 +52,24 @@ node['postgresql']['server']['packages'].each do |pg_pack| end -# Starting with Fedora 16, the pgsql sysconfig files are no longer used. +# If using PGDG, add symlinks so that downstream commands all work +if node['postgresql']['enable_pgdg_yum'] == true + [ + "postgresql#{shortver}-setup", + "postgresql#{shortver}-check-db-dir" + ].each do |cmd| + + link "/usr/bin/#{cmd}" do + to "/usr/pgsql-#{node['postgresql']['version']}/bin/#{cmd}" + end + + end +end + # The systemd unit file does not support 'initdb' or 'upgrade' actions. # Use the postgresql-setup script instead. -unless platform_family?("fedora") and node['platform_version'].to_i >= 16 +unless node['postgresql']['server']['init_package'] == 'systemd' directory "/etc/sysconfig/pgsql" do mode "0644" @@ -71,30 +85,38 @@ unless platform_family?("fedora") and node['platform_version'].to_i >= 16 end -if platform_family?("fedora") and node['platform_version'].to_i >= 16 +if node['postgresql']['server']['init_package'] == 'systemd' - execute "postgresql-setup initdb #{svc_name}" do - not_if { ::FileTest.exist?(File.join(dir, "PG_VERSION")) } + case node['platform_family'] + when 'suse' + execute "initdb -d #{node['postgresql']['dir']}" do + user 'postgres' + not_if { ::File.exist?("#{node['postgresql']['config']['data_directory']}/PG_VERSION") } + end + else + execute "#{node['postgresql']['setup_script']} initdb #{svc_name}" do + not_if { ::File.exist?("#{node['postgresql']['config']['data_directory']}/PG_VERSION") } + end end -elsif platform?("redhat") and node['platform_version'].to_i >= 7 - - execute "postgresql#{node['postgresql']['version'].split('.').join}-setup initdb #{svc_name}" do - not_if { ::FileTest.exist?(File.join(dir, "PG_VERSION")) } - end - -else !platform_family?("suse") +elsif (!platform_family?("suse") && node['postgresql']['version'].to_f <= 9.3) execute "/sbin/service #{svc_name} initdb #{initdb_locale}" do - not_if { ::FileTest.exist?(File.join(dir, "PG_VERSION")) } + not_if { ::File.exist?("#{node['postgresql']['config']['data_directory']}/PG_VERSION") } + end + +else + + execute "/sbin/service #{svc_name} initdb" do + not_if { ::File.exist?("#{node['postgresql']['config']['data_directory']}/PG_VERSION") } end end -include_recipe "postgresql::server_conf" - service "postgresql" do service_name svc_name supports :restart => true, :status => true, :reload => true action [:enable, :start] end + +include_recipe "postgresql::server_conf" diff --git a/cookbooks/postgresql/recipes/yum_pgdg_postgresql.rb b/cookbooks/postgresql/recipes/yum_pgdg_postgresql.rb index fcbc54c..97faeb8 100644 --- a/cookbooks/postgresql/recipes/yum_pgdg_postgresql.rb +++ b/cookbooks/postgresql/recipes/yum_pgdg_postgresql.rb @@ -15,31 +15,22 @@ # limitations under the License. # -####### -# Load the pgdgrepo_rpm_info method from libraries/default.rb -::Chef::Recipe.send(:include, Opscode::PostgresqlHelpers) - ###################################### -# Install the "PostgreSQL RPM Building Project - Yum Repository" through -# the repo_rpm_url determined with pgdgrepo_rpm_info method from -# libraries/default.rb. The /etc/yum.repos.d/pgdg-*.repo -# will provide postgresql9X packages, but you may need to exclude -# postgresql packages from the repository of the distro in order to use -# PGDG repository properly. Conflicts will arise if postgresql9X does -# appear in your distro's repo and you want a more recent patch level. +# Install the "PostgreSQL RPM Building Project - Yum Repository" -repo_rpm_url, repo_rpm_filename, repo_rpm_package = pgdgrepo_rpm_info +rpm_platform = node['platform'] +rpm_platform_version = node['platform_version'].to_f.to_i.to_s +arch = node['kernel']['machine'] # Download the PGDG repository RPM as a local file -remote_file "#{Chef::Config[:file_cache_path]}/#{repo_rpm_filename}" do - source repo_rpm_url +remote_file "#{Chef::Config[:file_cache_path]}/#{node[:postgresql][:pgdg][:repo_rpm_url][node[:postgresql][:version]][rpm_platform][rpm_platform_version][arch][:package]}" do + source "#{node[:postgresql][:pgdg][:repo_rpm_url][node[:postgresql][:version]][rpm_platform][rpm_platform_version][arch][:url]}#{node[:postgresql][:pgdg][:repo_rpm_url][node[:postgresql][:version]][rpm_platform][rpm_platform_version][arch][:package]}" mode "0644" end # Install the PGDG repository RPM from the local file -# E.g., /etc/yum.repos.d/pgdg-91-centos.repo -package repo_rpm_package do +package "#{node[:postgresql][:pgdg][:repo_rpm_url][node[:postgresql][:version]][rpm_platform][rpm_platform_version][arch][:package]}" do provider Chef::Provider::Package::Rpm - source "#{Chef::Config[:file_cache_path]}/#{repo_rpm_filename}" + source "#{Chef::Config[:file_cache_path]}/#{node[:postgresql][:pgdg][:repo_rpm_url][node[:postgresql][:version]][rpm_platform][rpm_platform_version][arch][:package]}" action :install end diff --git a/cookbooks/redis/.gitignore b/cookbooks/redis/.gitignore deleted file mode 100644 index bf6420b..0000000 --- a/cookbooks/redis/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -*.tgz -*.tar.gz -vendor/bundle -.bundle -.DS_Store -build/* -tmp/ -*.lock -.kitchen/* diff --git a/cookbooks/redis/test/.chef/knife.rb b/cookbooks/redis/test/.chef/knife.rb deleted file mode 100644 index a0fd5a0..0000000 --- a/cookbooks/redis/test/.chef/knife.rb +++ /dev/null @@ -1,2 +0,0 @@ -cache_type "BasicFile" -cache_options(path: "#{ENV["HOME"]}/.chef/checksums") diff --git a/cookbooks/rsyslog/.kitchen.busted.yml b/cookbooks/rsyslog/.kitchen.busted.yml deleted file mode 100644 index 0e42128..0000000 --- a/cookbooks/rsyslog/.kitchen.busted.yml +++ /dev/null @@ -1,86 +0,0 @@ ---- -driver_plugin: vagrant -driver_plugin: digitalocean -driver_config: - digitalocean_client_id: <%= ENV['DIGITAL_OCEAN_CLIENT_ID'] %> - digitalocean_api_key: <%= ENV['DIGITAL_OCEAN_API_KEY'] %> - aws_access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> - aws_secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> - aws_ssh_key_id: <%= ENV['AWS_KEYPAIR_NAME'] %> - ssh_key: <%= ENV['AWS_PRIVATE_KEY_PATH'] %> - rackspace_username: <%= ENV['RACKSPACE_USERNAME'] %> - rackspace_api_key: <%= ENV['RACKSPACE_API_KEY'] %> - require_chef_omnibus: latest - -platforms: -# - name: omnios-r151006c -# driver_plugin: ec2 -# driver_config: -# image_id: ami-35eb835c -# username: root - -- name: centos-5.8 - driver_plugin: digitalocean - driver_config: - image_id: 1601 - flavor_id: 63 - region_id: 4 - ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> - -- name: centos-6.4 - driver_plugin: digitalocean - driver_config: - image_id: 562354 - flavor_id: 63 - region_id: 4 - ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> - -# - name: amazon-2013.09 -# driver_plugin: ec2 -# driver_config: -# image_id: ami-3be4bc52 -# username: ec2-user - -- name: ubuntu-1004 - driver_plugin: digitalocean - driver_config: - image_id: 14097 - flavor_id: 63 - region_id: 4 - ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> - run_list: - - recipe[apt] - -- name: ubuntu-1204 - driver_plugin: digitalocean - driver_config: - image_id: 1505447 - flavor_id: 63 - region_id: 4 - ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> - run_list: - - recipe[apt] - -suites: - - name: default - run_list: - - recipe[rsyslog::default] - - name: relp - run_list: - - recipe[rsyslog::default] - attributes: - rsyslog: - use_relp: true - # CentOS and OmniOS do not support relp - excludes: - - centos-5.8 - - omnios-r151006c - - name: client - run_list: - - recipe[rsyslog::client] - attributes: - rsyslog: - server_ip: 10.0.0.50 - - name: server - run_list: - - recipe[rsyslog::server] \ No newline at end of file diff --git a/cookbooks/rsyslog/.kitchen.cloud.yml b/cookbooks/rsyslog/.kitchen.cloud.yml deleted file mode 100644 index 44825bd..0000000 --- a/cookbooks/rsyslog/.kitchen.cloud.yml +++ /dev/null @@ -1,92 +0,0 @@ ---- -driver_config: - digitalocean_client_id: <%= ENV['DIGITAL_OCEAN_CLIENT_ID'] %> - digitalocean_api_key: <%= ENV['DIGITAL_OCEAN_API_KEY'] %> - aws_access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> - aws_secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> - aws_ssh_key_id: <%= ENV['AWS_KEYPAIR_NAME'] %> - -provisioner: - name: chef_zero - require_chef_omnibus: latest - -platforms: -- name: centos-5.8 - driver_plugin: digitalocean - driver_config: - image_id: 1601 - flavor_id: 63 - region_id: 4 - ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> - ssh_key: <%= ENV['DIGITAL_OCEAN_SSH_KEY_PATH'] %> - -- name: centos-6.4 - driver_plugin: digitalocean - driver_config: - image_id: 562354 - flavor_id: 63 - region_id: 4 - ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> - ssh_key: <%= ENV['DIGITAL_OCEAN_SSH_KEY_PATH'] %> - -# - name: amazon-2013.09 -# driver_plugin: ec2 -# driver_config: -# image_id: ami-3be4bc52 -# username: ec2-user -# ssh_key: <%= ENV['EC2_SSH_KEY_PATH'] %> - -- name: fedora-19 - driver_plugin: digitalocean - driver_config: - image_id: 696598 - flavor_id: 63 - region_id: 4 - ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> - ssh_key: <%= ENV['DIGITAL_OCEAN_SSH_KEY_PATH'] %> - -- name: ubuntu-1004 - driver_plugin: digitalocean - driver_config: - image_id: 14097 - flavor_id: 63 - region_id: 4 - ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> - ssh_key: <%= ENV['DIGITAL_OCEAN_SSH_KEY_PATH'] %> - run_list: - - recipe[apt] - -- name: ubuntu-1204 - driver_plugin: digitalocean - driver_config: - image_id: 1505447 - flavor_id: 63 - region_id: 4 - ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> - ssh_key: <%= ENV['DIGITAL_OCEAN_SSH_KEY_PATH'] %> - run_list: - - recipe[apt] - -suites: - - name: default - run_list: - - recipe[rsyslog::default] - - name: relp - run_list: - - recipe[rsyslog::default] - attributes: - rsyslog: - use_relp: true - # CentOS and OmniOS do not support relp - excludes: - - centos-5.8 - - omnios-r151006c - - name: client - run_list: - - recipe[rsyslog::client] - attributes: - rsyslog: - server_ip: 10.0.0.50 - - name: server - run_list: - - recipe[rsyslog::server] diff --git a/cookbooks/rsyslog/.kitchen.yml b/cookbooks/rsyslog/.kitchen.yml deleted file mode 100644 index 7ede9ca..0000000 --- a/cookbooks/rsyslog/.kitchen.yml +++ /dev/null @@ -1,44 +0,0 @@ -driver: - name: vagrant - -provisioner: - name: chef_zero - -platforms: - - name: centos-5.10 - - name: centos-6.5 - - name: centos-7.0 - - name: debian-6.0.10 - - name: debian-7.7 - - name: fedora-20 - - name: fedora-21 - - name: ubuntu-10.04 - - name: ubuntu-12.04 - - name: ubuntu-14.04 - -suites: - - name: default - run_list: - - recipe[rsyslog::default] - - name: relp - run_list: - - recipe[rsyslog::default] - attributes: - rsyslog: - use_relp: true - # CentOS and OmniOS do not support relp - excludes: - - centos-5.10 - - omnios-r151006c - - name: client - run_list: - - recipe[rsyslog_test::client] - attributes: - rsyslog: - server_ip: 10.0.0.50 - - name: server - run_list: - - recipe[rsyslog_test::server] - - name: input_file_provider - run_list: - - recipe[rsyslog_test::input_file_provider] diff --git a/cookbooks/rsyslog/.rubocop.yml b/cookbooks/rsyslog/.rubocop.yml deleted file mode 100644 index 095b019..0000000 --- a/cookbooks/rsyslog/.rubocop.yml +++ /dev/null @@ -1,17 +0,0 @@ -AllCops: - Exclude: - - vendor/**/* - - Guardfile - -AlignParameters: - Enabled: false -Encoding: - Enabled: false -HashSyntax: - Enabled: false -LineLength: - Enabled: false -MethodLength: - Max: 30 -SingleSpaceBeforeFirstArg: - Enabled: false diff --git a/cookbooks/rsyslog/.travis.yml b/cookbooks/rsyslog/.travis.yml deleted file mode 100644 index 3834d06..0000000 --- a/cookbooks/rsyslog/.travis.yml +++ /dev/null @@ -1,75 +0,0 @@ -language: ruby -bundler_args: --without kitchen_vagrant --without development -rvm: -- 2.1.1 -before_install: -- echo -n $DO_KEY_CHUNK_{0..30} >> ~/.ssh/id_do.base64 -- cat ~/.ssh/id_do.base64 | tr -d ' ' | base64 --decode > ~/.ssh/id_do.pem -- echo -n $EC2_KEY_CHUNK_{0..30} >> ~/.ssh/id_ec2.base64 -- cat ~/.ssh/id_ec2.base64 | tr -d ' ' | base64 --decode > ~/.ssh/id_ec2.pem -script: -- bundle exec rake travis -after_script: -- bundle exec kitchen destroy -env: - global: - - secure: VTMb359XIsFfszhrq1znF2ANHITta2gyrOloF5GXEColSH1+XB1XikcTyTVeeloHLcLAjmID2LZSbTrhfXu7gT25uKk6AKFCYFo47kIqbvjR/2hChxsZPZJLspEOKl2HyPZvA8QGBJxbTVOVXs46wt1kOui8Hqr3nLbYlKRxnjs= - - secure: bLz73tc0pbS3htWCk6O3dxMfAxQys7RCwvXtc+z9vyLry+nXmHMNBj2irLoyi6ESKdN25LvvbGYtxevwr3e3MtyUNFXhrED4DqYZ6h2PWFY7x7V9ALXdmBXpWSXiycnE9aKbWA01QMSwta8mPHRk7viscXUDX1gab93fQbKG24w= - - secure: FMBQGoAQ3voqsse/tVJHITraljEmpLb+Nz5SDWQsUWmt2aE9yREOjlaoYOHlXY6O+1TwY+Houdb8MVn9oLv4G8nEPzo1f7fS6ddhIZCFZFo6ISGyd4FTw+Ym3401n+dzGFYuZ3JS0oLCZeO5Svvww6mI9eghz6tdXHkODUsUJI0= - - secure: jjI+SZKkwG5ckifd8hgi4gFVj/mOGj4eWK/Y0fpuwu4ycxj5pg2Fa2JgqJXJrmdd4DJMiN1FAPuEftSxErq/6v2doP7knmN+7QoCwsDTsVHlAAHvitL450/PO0dkr9+AY6EnKBu/ablppnNnCxsQqjuxXXfgT1lRVKHFgp4+J9E= - - secure: T2LMLomotIluZ4o/RWxQu4MYuXhHeHkaaHHjvJ1kLdbGcc7HsO0oHSuzHdtZNgPEfHjIUOpj8U5RbMZCCwKNJPJqHlQ3HykmzmNU669NAyTaxCfXDMfdoz3un4vx13FVB0SvX3YgU9J3FQ5P6oEXJynVHoGwlV2QVZ/Hhe0oA6k= - - secure: NrL2uUpo5B39ldZXgL/nmO+DsgciVhxq3WYbX817e54/wUBBJ3KZhk995G7WpnGDaW6EGtJMfpgnIMnqpEyeknW/oi0PTe0mcYd1x1zaijZNRZ97irkb0vHcpdJOyqVpPVyFV8G/ltItRCxhotzLAu5btq0MKD93V/hAcsWD4SQ= - - secure: K1Qjt6eF7ai3362EzShsWWGSq2xG22zj4idjOf1k8pJHrJ/7g/gMaN/bDpqYkksi7R/uD8dbqMTU6l/MBjRV2jzJ7kbG359OxVzXJoFUSxKkJX8TbLoX1P/dyt82XdVyU/j6SprNkhxy2/4uYvbF31ZAsEmiegdkqDbhBxBgmBA= - - secure: DBNraE+2aj4WTBkFbGtSIsxfl0stIAuRDH4ToDMEA6S54zvAIlFYdzjRcYRSOznk9HSk9lRIF/E4Q0RiF6WqZfp7uoHBbhKMNh+SD/anQ4lTyWhxKVTs/2onbr02aP9ztM/GIq3HqvZoLKrMFp2xBj88yOzblz8DZlkNMDPve24= - - secure: KUJpq3781JaY06GVy16L9dx8zFoOANN7I5Ar3juRoKzQztgSuKsqOhFlmZZpj1xX1IJsXEYkFYCvXB72bEBIvwGQnp4TV3LJPGvB1eePrNlheu0mXcxYQSSuAzXN1cg1ok5pgx/zSQovbChEVbQBRyYNnnRkJ41PaUmG8pWaM/I= - - secure: TN+FOCJkYo5tIGp35yqbYadTyIFK10TPqNMCpsfDNK/FXTRjp7GyqhUpTVlYvtDWaOwjqQLjart+ShTnZ8SOrk19znFDZm6PGk/2zVXirtU2zvvJMqqslxrMiVXMUE1ldH4d6U7cFT1ODuvWoUv41uKnbpygGZ+0Z8DMSSRX/x0= - - secure: RkynljZ2W5q4iqvsVkG+pepauzjUZomgf/4JTeRJiekGtvcrFnq+S0YJg9J7Ey9Iry8mHb034lS5OnIHyj8NaCL0vqDJEMVblasM1pVuLc65gv7rAP+5q5pHpwYVhUuerypGJFYKTd9ynhKkTvHOV6CYcqzOEsJGls8+vgvTfwU= - - secure: RsiAYfDJFsqEkJidJEzM4BGaqUwxy2avPSw1y4yh6XXWbgbOdx/eqSPf9ewHwIXPUYdR84sbZkn6PeYWUwTEtN7k1DrE2RXDjapDW8Oxh1U3s/pCvSnh2u0e3DhgD1DBnzN8foB1MV0kseilmx0vMEyDAj8ElhYoV+wvTO1Loxc= - - secure: Equh+0TdmCt1SjnYVJbDtNPBhK5P3/XuCyvU/tgRaGrIsf5gvCfq3tNNlkrdelmJK0UvGICoCKsOTcZDpbQ3jteoBoI3+NFrwVTe10OQ5XRc+/U8duYhS0D6UKzFMWYxWAdZtfmyWOJ5xYrNaV4JRdJgTSTjXk0gOSsPluSK0IY= - - secure: WEZJ1Z51wjYZfhP11tLxWuVZu6N4ZXyoTAb9AFgMzOaULvMOZusXF6o+aZSCr07rUnjlQAg2rE+E800FRUqO3UkL18kxALvtwKmAlyxVT85NcuWbMuaSNMeZwvqGVKJuNNSe3huU9uHePbsUt4trVKA9O1n3Bb4dRJl9wmdcgoU= - - secure: bGtuK+n8hVIibGxOIE/eOCRJHlgaqp2X9KObcBNFCTxKleRm2fDnCPEMVHQJqrX+jlqMGjzGygTnZ8wA1/ZdBwjOOqi3/jaUZ25+r0owaUjS1zaTudTBC61Qcmx+N7bXc3ku8fMWo6WcByTqnqU0oQseoli75KyIRoubIIgwgcM= - - secure: AMYMIfIGAJbPqSRv4ocdsxRWwDr81Wp7hiYjgpzUMFh3SzixKzjgtQ72T9S26PnvhkFjk0QvGixb26IXS8vU0ZtFBtLblUpKvXSd4EafvQ1x/fdN5WFaBlMs01iT4jVMH+wjnSJssuyw+nC5+5/HqeONdZcRm3Hj8uqE/24Qih0= - - secure: UrmjQ1/1OCENKLDezDbh6x4/6P37ybFlyb/gz6vzm2sIpvWeL+1+SvF92xYeeAhCYAtoXU9nAvcMgwqeJIi9P2q7aoTqv9VoK+lq7L1cPqpAjcqJCAdSAH/bYzARu4I0vDbZUhTaZC8+lw9xfl701WHWasyNgcYG3HFULsWQuwI= - - secure: cRhO5SJ0cInh1yYxDKcfymI3dt3PGfPJXCan+QzLoLg7VbJ3zfRKBhjjN2NjdcLxgHUNk5//paooOPoiiOMzwo2GdEDFJjtzL7TC6sQUxP6zN1RAiAIPqjHpuCKv3IQ4hLgTiRaH92I8lpIvst7hEHmPYS6+ItEgJug+tyluaX0= - - secure: LXJ150pAwEHLSMGGxSXs5pA49SwPYsV4Phsi7+ZqZ93uAprO8yw8Pxmhaaz9Y0BSLYVzTtdJI5VbW3XDzwo2tJeMfDz1Oxzqsi5kAXt8DTQRxoVX8FeMyVNLe8TbrI6cGnJrO37u+MrsFz9BI4+TsPoLYcc6Y/zqB2FFan5RMGM= - - secure: ewFdUlqrLoFrBoSx/ikqDgTsASXPZDNjn/nHsC2nv0A5VJDHZb98AwLOnKAFUwxmOkbq4LKoPR1ltQ4KigjpFIIYrkHfRv6izo08cgyd98QVKZSdBJfNjHTe+blwVgh3t/yODxJMPmhE5/lPIC3UnwmGW933UszvkozyPkyE0ag= - - secure: Dt4Kdi/KiydSYcgCUfGQkrFJ4NBNqtNrc1Xi4gdwl+xSpEKEDFFwrGkCaTdWCzB9SKH8Cy+KoNQiToMEp6SFFZGzEAYlN0zITqObyADocmZieEpV44nj+DBneI9h89aGP6XSTYXOwIDluuchR4sD6I5eHUuD3cHTHPbzI7sm3N8= - - secure: BBs+tpDN6MQv3BlnANh/nGzqWCzRwAKmFf8M0/XgidrqXHBxsgAXmAd+jdXQlqBs7bRjT3gNp3xGf3mIRW2gV9+6YNTiFFp8YGxFRxSd7A4x7obcb8HFIyBIqQ9ZgA7R0u3dsbgtAnRclK3+9ZHoZ41e1Qd/8S0PGsry4iTMAgc= - - secure: I3SG0cro9MmyHAASsWqachUWE0kshWtxRcBVgjJHZdvP1RBT2q5KD7p46o7yKP3PD9Kv2qt6DfpSTJJhXA2leIhzUMzRu7fpPu/Llc5k+Ik74tWXdYQMJ4tf5nEtq+A/D8odKax1HuM5L7xpz53Yn3M4Haf2udDm+owk9y/tRHs= - - secure: eNeHY7wbsS8GVhONSEq1crZMdo1fdW30ezoI9xJ4LvZJmYdcMvyR590r2LoV9OZXhYTQaJM+ldWW3rluPFm0oUNoPFdbl0+KuJsTldVhVp7BEQ3rwmoFfUIS+lxWM9qH/iNkOY7A+P9InBbFPbg7WUJ+OaqrQEo7t8muwJxlodc= - - secure: OfngkucaRoVa73QoGIheD7o5DzvWgU27p7wNIsW9bSoiwraOo81E9WiZdFbtwBQXRBy/hIw3TZHrg/BqSAx6HxnubK29IhsxoJ5lkz1Nl5/yxkT/+mqecfji8zu2p1UMnV5+SGUG7df+XWrVcvCJvO4NJyRI1cTIeI79TbOvcBw= - - secure: Fjc0htSGbmkDNFZvt2s89qMlsWGBtHDjewLQDxDX+TpRNk7lc6N43U1TZ7b3G1kzX6gmsST8syplhdo8EfxqBy5thgsNyu9So8CI5/LidOneauBVH8usHIUc7DvXlIxttsC9syjIresfseBrim+aI1HzENMpcWHHcn3UIdQ8yLQ= - - secure: dFD+09BCGyZNe44kZgTF+1rIYLFJQlpx47FctopcXM6Wl/moxVJF8c7e5iaLq34J4L0SvCUHHAF7WyxUjJYgUmxT4GrdET0vDtqqurz5TWxZ+daiJQhA6trcgo/WRQxhEO8qmxgJ6x4kNDyKfhqwVs40R3ThkhEGpNGgQ3jTtoI= - - secure: ch66LvlMlLDSteEkFAykn8dYEd9dEugMiCw/cncUDE6XU8eXusbNtXaCds3kb/rAYHHpGD2IDr+ZjvnoxRdRdh+d/EOBm/9iy0ii26O8iLZdLXqpqxFqiC3rtaoN4fYe1GqAZ03QNYja+XTbNEqUIxb3aozABZLY+wtcGgvtRhE= - - secure: XtH3hwnTIVZmigTJTsNH6flmEsb7Pm2XjzPvLcCNnV6qtwCvR3cgOPiu0Vs+p5s3QGIN8SNnN+mxUEDgcfnKMn2skUalSBgFKVaQg9NiE956dUkytnTDb0KxGoMFJBzMUhEKwSWl3p5+32M0APtzwqQOSP7sYiT+u4ICz5s4aK0= - - secure: J309x5rZal7gJt7qJqFTsj4/y8vF7k4qEpd5KWMs6vjf+hDlmFVyBu3zIDo6NgFAsSazGswwK0SwzAhY20DBcvppwdvCwt2/3wz1ob/fWhNxbEVW0afBGPBXSy/XG38Ag/xZpCRfAnOI9aFzkdKPOsYw6852Vk6exEU73Vxl8OY= - - secure: Bg9S9uiL9Wn5mDIq4BZRAGjWfNJu/b1Ksj8AmobljuASQmRaPvRHrRDJNzOI+TuPb56+ihWSmijGx+sagUyxwSXTmo3wk409rCXU9uaJxQU8nVIrw6nlf5js/j+BgKNtHnYNlcGl6sopYRRS4U0wHLJEZI3Gbvw039VpcStEjEU= - - secure: O7hct2KQBJyBGaHDeA6koGfmRvziI21rIa3cLXYzYK9MfSr5WbYDPI87HnxSxwaBP+Thl0tWxmgEbtVaTmkb2OdhW0JYXqVfLTt1Vbd411/O1xLSkP1INSSNSWJpD9K2/U8nLE3aZcedj/Cosi8GMjhl7wUP07/zTCzYxpnGp4o= - - secure: RNKtHWZEHCLm/2/iqwRUH/iiX9NDxgvHyg4oWnf/Y6oZXM6LEjGRURkouH1dexzZi35ssKdkbnfW/OD/N8jAxyt6KqlvWEPLLMJrrx/TCufdy5SljMH9PfHBSdxZn+U8qeVnufmdPPA3AoxhPabhF8voYaroWAq+oWpNh9sj+3c= - - secure: dkbJ4IGwBa2Z6LVsTyukSaACuHEV6QKyXuO1CHaxI8LRwrZbRee0RTdF4fom83IUn+DQ5LqCnMI2xk4NUVOeMCaY4LthC7f/ImgIxMGCnAq74OxnxCm0CnUhb3E1spPLCa4hgjyBMxp81w/M6ga/qKAIUDLqvqHlbG+Ezf8L+yE= - - secure: g4vz9hPqJhXTbe/zJWsoQ1Rh+Ay+PC7BPkbmqYX2VJPWSsesGQgnY5TrZzEzhiKgKfOkNTItaJs4do5F28XmLOFT+WSOgQGOdg171eS5J1Nq+403hSjOoe5hAdrHbexO5YRMlyjiBeMGP2x+VLIH0ZUeVFsH1Ojc5QfyuzlNxhY= - - secure: IqJosVHlfo49EextXiSrvXtHRgZVyHpqDn0yZIerA6ldaDeNFsai7XT2l5/OsSNYVKM91xm6mWEzhb3uofGnFtCq7pfj4n96kK3zeSx1j0ZtHiiLU4VKQB6qtJuBr0CtNa3XOgKmVYi/xbwIGcRbHSUk45k9jxtPF2ZdbseLb2k= - - secure: cO7k9EiMjXqsELLLqESR8cdU3CJIyO14baXGBzhcxV8B4NEJ1w+mCW5xC8xkOPx0W1uw5kF+ieKNHTb9FuAl+13mztZfEneq5+KzQxhCVC4VLFk37z+YN4XsTtjOpoc+Sejxf7Rk+i2b6iQFgDOnpa2ujy/Kch0TyjjWoDk7z1A= - - secure: CvOZnuItfTL4pQdwh0SYV+J1xGxR5uPChnRqq8sHCIv44ltq0ZiZSu6R+8/SScWN162xW7KlxZYtOJn3obKeIAAiH7OZGOGhsl+li59W0j0ldGEGGAkruaQB8Q29z6sq8HR65fR7hJ/7elo410HgIsMUM5QD9xn5wPePHNTIuv0= - - secure: YY3DZiMltINKWUmnxR5wfzHwPGYzKp6HqHv0fydB4ekKMnxupc5Aegg3Iq9PBGZQ6cAjJprqZX8gJskD5wkPk/NutQ3gUSvpVbHleQmL+blJ1UtE9b7dJqKFDlE12q0KyCydx9hkKMK8G5OLVb/qYsqvrsbqVS2pemGYKL1ztJM= - - secure: NO0zNB/mDzx/qdN9o+jBt+AvVM1ChX5OOdA2s2czrEEZCWYPQUge+p2oNlbkl4+Cc8+N6Np2dUlFZkxIUQ/eDoQv0BVADqzhNvgZn7q1YZCAFtIVT8KJDr3+Ly1YqL9uCHk7hW6rBl+VVYatyo7XyugHneT0RzmQpYY3RKMiSaI= - - secure: KL8bAfL5Q8c5/yMUD8jGuTg52cfYTJPPExI67j8iWfz9WyohyV4wJgRw4G0s4MZP75WXZg74fk5Jhs/jbk3Q8lBtk6a9P8SHZuC7Rh/yHUmVRzYaKTr/yRaFnIBsC/mnvV6JNX5NXfSrmntGs8KA7lWGZeRLpWSOEoT0YgPRn9w= - - secure: U25VWQKe2pFluApjzrA27rHrQTB0SWU/kjnUUXPDxcyqkM5YStNeVb8g3DjT4zR3OIsNsUXCxWHVEMlzP6HQjk+dgIsrlwDi07r7NHAOXFj8m9fCrComKNUZdg79KtHWed2kiB4hrMH51oV7A0fXff51kZiKD0IoH0ySQfPQSBo= - - secure: OSyoiFqPN7IBfIXR1wi64Y8wJf4ZlGOaWYBxWNviKhtuZYyYsb1CnI+zN5kozXr5w83mDxOWnzKS1p6HHMzZD1v+3uJCWRjoLYlUDuOWRJ8OY5kqZsH5LbQ/2Qdl2YuC0YOvZwzfK7CboFLndt/V5bIcVLcQBB5dcDvfqiFW5T0= - - secure: EVdYNRFPFdH5JpULFcS4G9UcPLNwRAy0lL4xD3jVDVbfTt1XC9+GOGa/AsKx3MPFDuSGBCUkbvaq/SxrjL0Fh63X8T6jOeLzWj97qBaAg5Ih7ADSRsdfJ0spQ5K5lI/YbqlumQN+pJg+hkrO0puR7T745Et/WwTfASICr8/ZURU= - - secure: LHf2QsgQZdYiMJM325FLP7wq1eTr3jjMcNlIN6HYwF/zvGwOoqNfYgJqUZXKv45rD2eOeDfXAc2LD6cF6LN5hD+3yzvhybLPCqK4hLWvGnVxSJO2pYn0kdZdTsLMrUTCrQ7X22eFW/wk9ZM/JaefjNwJV2XN+83b+cnMiil0GZ4= - - secure: cNkBHL5W8Ca+X0gLBpHnfiWsas5SKXxbHJm1YKq8Olo/8XUk/90zZvFWSET+a7pwDOzOXVujlE/JfXA5gZVKpbG3JlVt2ntMa5JTaTVVt8GNWkW8slu5niJFdJdpL3EikhX8sgz69q+QFJTBmsDfeJzsUe01VZHsdDCIs/wsPLg= - - secure: bTRB05t28cpSCAxhqXcbDUbrx4QDnDoHQpnhjynwIq+9QuV6IMx65O6+CSL8T61z6BuPVDkvUpLQ8W74rpwtCa91XaSNuiNVciMIaq+yk8FV2gCRzzw55o79IuAFjns/JxGWLV717WR7bGxjU4zR6ybgZzuBgJMXqJSk4iNH62I= - - secure: iBqO1O6827L3eAYrm/X9hN8vsF4Gt+JVZ7kLkm1RGVLAWnQpMYODGl+xQS4WxmY+kaWtHAI8PBhM/WXQ/26d4Iljg/JPvJRH1JSB/+0bLCp+OAfpgEUajbB/6zj6RGNZnU//MyA6h6M/RUW9rES4KHvzQFAtODSyTNFojmEdqTk= - - secure: K0sT+IGy2ncdrfNcPJ5rnwT3oYB1KWK330t6msKlGi6gTwId1z4gDx+iz0ttbP7jCGbQrqj+H+ZTypV+HploVyMAcxFA/tFJsPdMjUmPC/wO2kmP1PCON4OO4+0y4OEA7AX3eBnGTXLJBtqoWb2HCeldA1gQsuM0C0WQ0sz/2lo= - - secure: jAfN1DSUxORr/9LauKKjxeflwufkG3dNOPxwAMX2mUjpV8nfP9N57D+oFsPh4vZYT7kvt2LKAVcn1mMxkXEDb9YOE4UCIB+F5fYqInJGACFUK+VNeM0sbUtkj1cNvd/V/C/cmxG1MbEyIfBy12I8Ezz2+pKpA150QYYaxyOcccQ= - - secure: MGJGwkNaElc8YxEtY2L2iV20srBejwmVqAyKMgfH2GUOEoyZ4ID5va2jAd3TZoteUN5f1wEHVNhBGfT6poYEKcoT09Sl5c81YO8Ws7oKxaSlIUwRwo4Tem+c6WQIkyqSfHaW4pl+nzv2eWBzp/EPQvbRrh6dWbDZYf8S0QqmomU= - - secure: T0osUxN/iHJ4iX/JPhC2dO+OS98SCF2vXCEpszO4LzaC7Cy2ftbzXkN3gcDc4CrbrIdwP/J2dYmBiETlrm6n8eaLNIOPuIJEigSATL4Dke66fQF3DLeSZOC10Ggu72OsIO5RJWQJxYkRjQzaK61553goRAHsIwceO63inKFaFi4= - - secure: DY27wvyRDVQ46WeQjqs7ANuUobazrUU3NT8OdSXXSN5NxBZQK17QmbOuvaCQHKOvuv3YXtKQAl/s7ztgBIH6zTDGVmaCfgJOAX3d5SAvCCHKw9/43Wh7W4ZJ1VprFU9gp1C3wLb45T1kT3rCk2IxCCZxyvepm+43w+hJFFOzFSA= - - secure: TrYhk5FHxgP4O19w56ZtatlJgFtIeBL9Ucco5KGZBvI7ynZm7Bd0k7k2qQ0Nw46FPhCRwTtqK46nx8sRn9jPmkqXGcoYgztDfI9EgD7B79lp7M4897wAa6ditKUDSL+SXG6bgngK5sZCVw749QdJX9F+NPmog5X54QNTBP27XUI= - - secure: SB5cNAQjM1WdYTl8Xe0oib+7S8lp6g0pyRIL1RhStOMjZ2rPS7eFfNUeUw8M1AA11zXXFfsBWCtf+kHI7CK7q4QC2W2129CTTxxgqHpC9hjMlOvddVsbN8vfqCHCWFnjinhvYsKdu6xM6mW6IxIQ1SjShra/u6kyfyKBWrkRvXI= - - secure: H2PPPnH66DD05RdHg8srecBrO/s21MOAqdvFgEhItzMeEmAmTYubCdFIMO4uwyA/bNJiHF0u4g7RYTpsEmW3GNbZ6DGBv2Ltqf/vBP6sTce1LxYTRMsCoYpurTQSODj11+9XU33ml+kH5uNR/CcSSOmco2I5vyBv4qKElsID8CY= - - secure: JWEwbpLg/4KevMApf+z6URboREh56AU5oqZQ7pS9JQG6MffNp1HTcu4R+rxvhM2g28kE/gSxJaEo+pgPCpsggycRC0/ZH2TDOl+WwiPRCjEhqYKkoEDxx4Ot5OP0jwahMTGT/33ihWlnl5DrgjAmvpbSlJsULGV97nYg0llDXb0= - - secure: WUDHKVsOgBFkxNOtifMT3jNOPfR8D7DpyFBWCjwrdIU6DLDFg92/2a7tq1CGCk7uWYUJFgdbCLnJPA304L6AzWKcycvZvgDKzkcmz0iNxpGMOfQPM57UeqQAYpgv+/4wnHzbn85ZXh2gzPsEBvJWaNjE2VftedKkqDXHe5Dg9L0= - - secure: eYgi6mgnI4qkcgi4c7vkR1vaZPcY67U4PeYVcJ0g3Ri1gP0l73D44M6QGpnUrmTdkULjj6ZVOWq2d6i+D8bLGN5R5kj90GzxVhxstVG86ZT7ottipvKez5G7cm1udDzXEK463EX+w4ITTY4Zp4tCS00o4ce+kxR/3ntiGBUYR2Y= - - secure: HOd08Pxhi4thM6PpyIk1PcFsjHKFziWT1VNaC+hhT2p0YIaEeOIL94OcrmYC9cm+Nv4Mns+QNwqazHUc8xyciYo7yVxGPVSxu+qc1GSXtnbEC3KCxjBoae2VEWaVJgZyv3Z525jHXdPKvURMA/+MF39ALRpReUiByi4Q2+rHoBg= diff --git a/cookbooks/rsyslog/Berksfile b/cookbooks/rsyslog/Berksfile deleted file mode 100644 index 90e07ca..0000000 --- a/cookbooks/rsyslog/Berksfile +++ /dev/null @@ -1,7 +0,0 @@ -source 'https://supermarket.getchef.com' -metadata - -group :integration do - cookbook 'apt', '~> 2.0' - cookbook 'rsyslog_test', path: 'test/fixtures/rsyslog_test' -end diff --git a/cookbooks/rsyslog/CHANGELOG.md b/cookbooks/rsyslog/CHANGELOG.md index 963f497..c718777 100644 --- a/cookbooks/rsyslog/CHANGELOG.md +++ b/cookbooks/rsyslog/CHANGELOG.md @@ -2,7 +2,33 @@ rsyslog Cookbook CHANGELOG ========================== This file is used to list changes made in each version of the rsyslog cookbook. +v.2.2.0 (2015-10-05) +---------- +- Add why-run support to the file_input LWRP +- Added support for rsyslog under systemd on Ubuntu 15.04+ +- Added new attribute node['rsyslog']['custom_remote']. See readme for additional information +- Added source_url and issues_url metadata for Supermarket +- Fixed 49-relp.conf to honor logs_to_forward so it didn't just forward everything +- Updated contributing and testing docs +- Set the minimum supported Chef release to 11.0 +- Added maintainers.toml and maintainers.md files +- Added Amazon Linux, Oracle, and Scientific Linux to the metadata +- Removed all pre-Ruby 1.9 hash rockets +- Updated development dependencies in the +- Fix a bad example attribute in the readme +- Updated Travis CI config to test on all modern Ruby releases + +v.2.1.0 (2015-07-22) +---------- +- Fixed minor markdown errors in the readme +- Allow the server to listen on both TCP and UDP. For both set node['rsyslog']['protocol'] to 'udptcp' +- Move the include for /etc/rsyslog.d/ to the very end of the rsyslog.conf config +- Added the ability to bind to a specific IP when running the server on UDP with node['rsyslog']['bind'] +- Sync the comments in the rsyslog.conf file with the latest upstream rsyslog release +- Change emerg to log to :omusrmsg:* vs. * on modern rsyslog releases to avoid deprecation warnings + v.2.0.0 (2015-05-18) +-------------------- Note: This version includes several breaking changes for Ubuntu users. Be sure to take care when deploying these changes to production systems. - 49-relp.conf now properly uses the list of servers discovered in the client recipe diff --git a/cookbooks/rsyslog/CONTRIBUTING.md b/cookbooks/rsyslog/CONTRIBUTING.md deleted file mode 100644 index d876116..0000000 --- a/cookbooks/rsyslog/CONTRIBUTING.md +++ /dev/null @@ -1,196 +0,0 @@ -# Contributing to Chef Cookbooks - -We are glad you want to contribute to Chef Cookbooks! The first -step is the desire to improve the project. If you're new to the Chef -community, please read -[How to become a contributor](https://supermarket.getchef.com/become-a-contributor) -on the Supermarket website for more information. - -## Quick-contribute - -* Create an account on the [Supermarket](http://supermarket.getchef.com) -* Sign our contributor agreement (CLA)[online](https://supermarket.getchef.com/ccla-signatures/new) -* Visit the Github page for the project. -* Fork the repository -* Create a feature branch for your change. -* Create a Pull Request for your change. - -We regularly review contributions and will get back to you if we have -any suggestions or concerns. - -## The Apache License and the CLA/CCLA - -Licensing is very important to open source projects, it helps ensure -the software continues to be available under the terms that the author -desired. Chef uses the Apache 2.0 license to strike a balance between -open contribution and allowing you to use the software however you -would like to. - -The license tells you what rights you have that are provided by the -copyright holder. It is important that the contributor fully -understands what rights they are licensing and agrees to them. -Sometimes the copyright holder isn't the contributor, most often when -the contributor is doing work for a company. - -To make a good faith effort to ensure these criteria are met, Chef -Software Inc requires a Contributor License Agreement (CLA) or a Corporate -Contributor License Agreement (CCLA) for all contributions. This is -without exception due to some matters not being related to copyright -and to avoid having to continually check with our lawyers about small -patches. - -It only takes a few minutes to complete a CLA, and you retain the -copyright to your contribution. - -You can complete our contributor agreement (CLA) -[online](https://supermarket.getchef.com/ccla-signatures/new) If -you're contributing on behalf of your employer, have your employer -fill out our -[Corporate CLA](https://supermarket.getchef.com/ccla-signatures/new) -instead. - -## Using git - -You can get a quick copy of the repository for this cookbook by -running `git clone git://github.com/opscode-coobkooks/COOKBOOKNAME.git`. - -For collaboration purposes, it is best if you create a Github account -and fork the repository to your own account. Once you do this you will -be able to push your changes to your Github repository for others to -see and use. - -If you have another repository in your GitHub account named the same -as the cookbook, we suggest you suffix the repository with -cookbook. - -### Branches and Commits - -Create a _topic branch_ and a pull request on Github. 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. - -If your branch has multiple commits, please quash them into a -single commit. If the PR is addressing an issue in the Github issue -tracker, please reference it in the summary line. - - [#42] - platform_family and style - - * use platform_family for platform checking - * update notifies syntax to "resource_type[resource_name]" instead of - resources() lookup - * #40 - delete config files dropped off by packages in conf.d - * dropped debian 4 support because all other platforms have the same - values, and it is older than "old stable" debian release - -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. - -### More information - -Additional help with git is available on the -[Working with Git](http://wiki.opscode.com/display/chef/Working+with+Git) -wiki page. - -## Functional and Unit Tests - -This cookbook is set up to run tests under -[Kitchen-ci's test-kitchen](https://github.com/test-kitchen/test-kitchen). -It uses Serverspec or Bats to perform integration tests after the node -has been converged. - -Test kitchen should run completely without exception using the default -[baseboxes provided by Chef](https://github.com/opscode/bento). -Because Test Kitchen creates VirtualBox machines and runs through -every configuration in the Kitchenfile, 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 the #chef-hacking IRC channel. - -## Code Review - -Chef regularly reviews code contributions and provides suggestions -for improvement in the code itself or the implementation. - -Depending on the project, these tickets are then merged within a week -or two, depending on the current release cycle. - -## Release Cycle - -The versioning for Chef Cookbook projects is X.Y.Z. - -* X is a major release, which may not be fully compatible with prior - major releases -* Y is a minor release, which adds both new features and bug fixes -* Z is a patch release, which adds just bug fixes - -Releases of Chef's cookbooks are usually announced on the Chef user -mailing list. Releases of several cookbooks may be batched together -and announced on the [Chef Blog](http://www.getchef.com/blog). - -## Working with the community - -These resources will help you learn more about Chef and connect to -other members of the Chef community: - -* [chef](http://lists.opscode.com/sympa/info/chef) and - [chef-dev](http://lists.opscode.com/sympa/info/chef-dev) mailing - lists -* #chef and #chef-hacking IRC channels on irc.freenode.net -* [Community Cookbook site](http://community.opscode.com) -* [Chef wiki](http://wiki.opscode.com/display/chef) -* Chef, Inc [product page](http://www.getchef.com/chef) - -## 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.opscode.com/sympa/info/chef-dev) -or the [#chef-hacking IRC channel](http://community.opscode.com/chat/chef-hacking). -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). - - git commit -m 'Updated pool resource to correctly delete.' - -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, Chef -Software, Inc 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. -Opscode will update the CHANGELOG.md when releasing a new version of -the cookbook. diff --git a/cookbooks/rsyslog/Guardfile b/cookbooks/rsyslog/Guardfile deleted file mode 100644 index 11dc1de..0000000 --- a/cookbooks/rsyslog/Guardfile +++ /dev/null @@ -1,35 +0,0 @@ -# A sample Guardfile -# More info at https://github.com/guard/guard#readme - -# guard 'kitchen' do -# watch(%r{test/.+}) -# watch(%r{^recipes/(.+)\.rb$}) -# watch(%r{^attributes/(.+)\.rb$}) -# watch(%r{^files/(.+)}) -# watch(%r{^templates/(.+)}) -# watch(%r{^providers/(.+)\.rb}) -# watch(%r{^resources/(.+)\.rb}) -# end - -guard 'foodcritic', cookbook_paths: '.', all_on_start: false do - watch(%r{attributes/.+\.rb$}) - watch(%r{providers/.+\.rb$}) - watch(%r{recipes/.+\.rb$}) - watch(%r{resources/.+\.rb$}) - watch('metadata.rb') -end - -guard 'rubocop', all_on_start: false do - watch(%r{attributes/.+\.rb$}) - watch(%r{providers/.+\.rb$}) - watch(%r{recipes/.+\.rb$}) - watch(%r{resources/.+\.rb$}) - watch('metadata.rb') -end - -guard :rspec, cmd: 'bundle exec rspec', all_on_start: false, notification: false do - watch(%r{^libraries/(.+)\.rb$}) - watch(%r{^spec/(.+)_spec\.rb$}) - watch(%r{^(recipes)/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } - watch('spec/spec_helper.rb') { 'spec' } -end diff --git a/cookbooks/rsyslog/README.md b/cookbooks/rsyslog/README.md index f7cc337..7dedf03 100644 --- a/cookbooks/rsyslog/README.md +++ b/cookbooks/rsyslog/README.md @@ -1,20 +1,26 @@ rsyslog Cookbook ================ -[![Build Status](https://secure.travis-ci.org/opscode-cookbooks/rsyslog.png?branch=master)](http://travis-ci.org/opscode-cookbooks/rsyslog) +[![Build Status](https://travis-ci.org/chef-cookbooks/rsyslog.svg?branch=master)](http://travis-ci.org/chef-cookbooks/rsyslog) +[![Cookbook Version](https://img.shields.io/cookbook/v/rsyslog.svg)](https://supermarket.chef.io/cookbooks/rsyslog) Installs and configures rsyslog to replace sysklogd for client and/or server use. By default, the service will be configured to log to files on local disk. See the Recipes and Examples sections for other uses. Requirements ------------ -### Platforms -Tested on: -- Ubuntu 10.04+ -- Red Hat / CentOS 5+ +#### Platforms +- Debian/Ubuntu +- RHEL/CentOS/Scientific/Amazon/Oracle - Fedora 20+ - OmniOS r151006c -### Other +#### Chef +- Chef 11+ + +#### Cookbooks +- none + +#### Other To use the `recipe[rsyslog::client]` recipe, you'll need to set up the `rsyslog.server_search` or `rsyslog.server_ip` attributes. See the __Recipes__ and __Examples__ sections below. @@ -27,9 +33,10 @@ See `attributes/default.rb` for default values. * `node['rsyslog']['server']` - Determined automatically and set to true on the server. * `node['rsyslog']['server_ip']` - If not defined then search will be used to determine rsyslog server. Default is `nil`. This can be a string or an array. * `node['rsyslog']['server_search']` - Specify the criteria for the server search operation. Default is `role:loghost`. -* `node['rsyslog']['protocol']` - Specify whether to use `udp` or `tcp` for remote loghost. Default is `tcp`. +* `node['rsyslog']['protocol']` - Specify whether to use `udp` or `tcp` for remote loghost. Default is `tcp`. To use both specify both in a string e.g. 'udptcp'. +* `node['rsyslog']['bind']` - Specify the address to which the server should be listening; only use with `node['rsyslog']['protocol'] = 'udp'` because the feature does not work with the `tcp` protocol ([more info](http://www.rsyslog.com/doc/master/configuration/modules/imtcp.html#caveats-known-bugs)). * `node['rsyslog']['port']` - Specify the port which rsyslog should connect to a remote loghost. -* `node['rsyslog']['remote_logs']` - Specify wether to send all logs to a remote server (client option). Default is `true`. +* `node['rsyslog']['remote_logs']` - Specify whether to send all logs to a remote server (client option). Default is `true`. * `node['rsyslog']['per_host_dir']` - "PerHost" directories for template statements in `35-server-per-host.conf`. Default value is the previous cookbook version's value, to preserve compatibility. See __server__ recipe below. * `node['rsyslog']['priv_seperation']` - Whether to use privilege separation or not. * `node['rsyslog']['priv_user']` - User to run as when using privilege separation. Defult is `node['rsyslog']['user']` @@ -46,6 +53,7 @@ See `attributes/default.rb` for default values. * `node['rsyslog']['default_log_dir']` - log directory used in `50-default.conf` template, defaults to `/var/log` * `node['rsyslog']['default_facility_logs']` - Hash containing log facilities and destinations used in `50-default.conf` template. * `node['rsyslog']['default_file_template']` - The name of a pre-defined log format template (ie - RSYSLOG_FileFormat), used for local log files. +* `node['rsyslog']['default_remote_template']` - The name of a pre-defined log format template (ie - RSYSLOG_FileFormat), used for sending to remote servers. * `node['rsyslog']['rate_limit_interval']` - Value of the $SystemLogRateLimitInterval configuration directive in `/etc/rsyslog.conf`. Default is nil, leaving it to the platform default. * `node['rsyslog']['rate_limit_burst']` - Value of the $SystemLogRateLimitBurst configuration directive in `/etc/rsyslog.conf`. Default is nil, leaving it to the platform default. * `node['rsyslog']['action_queue_max_disk_space']` - Max amount of disk space the disk-assisted queue is allowed to use ([more info](http://www.rsyslog.com/doc/queues.html)). @@ -56,6 +64,7 @@ See `attributes/default.rb` for default values. * `node['rsyslog']['tls_auth_mode']` - Value for `$InputTCPServerStreamDriverAuthMode`/`$ActionSendStreamDriverAuthMode`, determines whether client certs are validated. Defaults to `anon` (no validation). * `node['rsyslog']['use_local_ipv4']` - Whether or not to make use the remote local IPv4 address on cloud systems when searching for servers (where available). Default is 'false'. * `node['rsyslog']['allow_non_local']` - Whether or not to allow non-local messages. If 'false', incoming messages are only allowed from 127.0.0.1. Default is 'false'. +* `node['rsyslog']['custom_remote']` - Array of hashes for configuring custom remote server targets * `node['rsyslog']['additional_directives']` - Hash of additional directives and their values to place in the main rsyslog config file Recipes @@ -68,6 +77,26 @@ Includes `recipe[rsyslog]`. Uses `node['rsyslog']['server_ip']` or Chef search (in that precedence order) to determine the remote syslog server's IP address. If search is used, the search query will look for the first `ipaddress` returned from the criteria specified in `node['rsyslog']['server_search']`. +You can use `node['rsyslog']['custom_config']` to define custom entries for sending logs to remote servers. +Available attributes: +``` + 'server': Ip/hostname of remote syslog server (Required) + 'port': Port to send logs to + 'logs': Syslog log facilities to send (auth, authpriv, daemon, etc) + 'protocol': Can be tcp or udp + 'remote_template': Rsyslog template used for the messages +``` + +Example: + +```ruby +node['rsyslog']['custom_remote'] = [{ 'server' => '10.10.4.4', 'port' => '567', 'logs' => 'auth.*,mail.*', 'protocol' => 'udp', 'remote_template' => 'RSYSLOG_SyslogProtocol23Format'}, + { 'server' => '10.0.0.3', 'port' => '555', 'logs' => 'authpriv,daemon.*' } ] +``` + +The server key is required; if other keys are left out, the default global values will be used (eg `node['rsyslog']['port']` will be used if 'port' is omitted) + + If the node itself is a rsyslog server ie it has `rsyslog.server` set to true then the configuration is skipped. If the node had an `/etc/rsyslog.d/35-server-per-host.conf` file previously configured, this file gets removed to prevent duplicate logging. @@ -109,8 +138,8 @@ Resources file_input ---------- -Configures a (text file input -monitor)[http://www.rsyslog.com/doc/imfile.html] to push a log file into +Configures a [text file input +monitor](http://www.rsyslog.com/doc/imfile.html) to push a log file into rsyslog. Attributes: @@ -183,7 +212,7 @@ name "facility_log_example" run_list("recipe[rsyslog::default]") default_attributes( "rsyslog" => { - "facility_logs" => { + "default_facility_logs" => { '*.info;mail.none;authpriv.none;cron.none' => "/var/log/messages", 'authpriv' => '/var/log/secure', 'mail.*' => '-/var/log/maillog', @@ -199,7 +228,7 @@ This section details "quick development" steps. For a detailed explanation, see 1. Clone this repository from GitHub: - $ git clone git@github.com:opscode-cookbooks/rsyslog.git + $ git clone git@github.com:chef-cookbooks/rsyslog.git 2. Create a git branch diff --git a/cookbooks/rsyslog/TESTING.md b/cookbooks/rsyslog/TESTING.md deleted file mode 100644 index 5b20bb8..0000000 --- a/cookbooks/rsyslog/TESTING.md +++ /dev/null @@ -1,187 +0,0 @@ -TESTING doc -======================== - -Bundler -------- -A ruby environment with Bundler installed is a prerequisite for using -the testing harness shipped with this cookbook. At the time of this -writing, it works with Ruby 2.0 and Bundler 1.5.3. All programs -involved, with the exception of Vagrant, can be installed by cd'ing -into the parent directory of this cookbook and running "bundle install" - -Rakefile --------- -The Rakefile ships with a number of tasks, each of which can be ran -individually, or in groups. Typing "rake" by itself will perform style -checks with Rubocop and Foodcritic, ChefSpec with rspec, and -integration with Test Kitchen using the Vagrant driver by -default.Alternatively, integration tests can be ran with Test Kitchen -cloud drivers. - -``` -$ rake -T -rake integration:cloud # Run Test Kitchen with cloud plugins -rake integration:vagrant # Run Test Kitchen with Vagrant -rake spec # Run ChefSpec examples -rake style # Run all style checks -rake style:chef # Lint Chef cookbooks -rake style:ruby # Run Ruby style checks -rake travis # Run all tests on Travis -``` - -Style Testing -------------- -Ruby style tests can be performed by Rubocop by issuing either -``` -bundle exec rubocop -``` -or -``` -rake style:ruby -``` - -Chef style tests can be performed with Foodcritic by issuing either -``` -bundle exec foodcritic -``` -or -``` -rake style:chef -``` - -Spec Testing -------------- -Unit testing is done by running Rspec examples. Rspec will test any -libraries, then test recipes using ChefSpec. This works by compiling a -recipe (but not converging it), and allowing the user to make -assertions about the resource_collection. - -Integration Testing -------------------- -Integration testing is performed by Test Kitchen. Test Kitchen will -use either the Vagrant driver or various cloud drivers to instantiate -machines and apply cookbooks. After a successful converge, tests are -uploaded and ran out of band of Chef. Tests should be designed to -ensure that a recipe has accomplished its goal. - -Integration Testing using Vagrant ---------------------------------- -Integration tests can be performed on a local workstation using -Virtualbox or VMWare. Detailed instructions for setting this up can be -found at the [Bento](https://github.com/opscode/bento) project web site. - -Integration tests using Vagrant can be performed with either -``` -bundle exec kitchen test -``` -or -``` -rake integration:vagrant -``` - -Integration Testing using Cloud providers ------------------------------------------ -Integration tests can be performed on cloud providers using -Test Kitchen plugins. This cookbook ships a ```.kitchen.cloud.yml``` -that references environmental variables present in the shell that -```kitchen test``` is ran from. These usually contain authentication -tokens for driving IaaS APIs, as well as the paths to ssh private keys -needed for Test Kitchen log into them after they've been created. - -Examples of environment variables being set in ```~/.bash_profile```: -``` -# digital_ocean -export DIGITAL_OCEAN_CLIENT_ID='your_bits_here' -export DIGITAL_OCEAN_API_KEY='your_bits_here' -export DIGITAL_OCEAN_SSH_KEY_IDS='your_bits_here' - -# aws -export AWS_ACCESS_KEY_ID='your_bits_here' -export AWS_SECRET_ACCESS_KEY='your_bits_here' -export AWS_KEYPAIR_NAME='your_bits_here' - -# joyent -export SDC_CLI_ACCOUNT='your_bits_here' -export SDC_CLI_IDENTITY='your_bits_here' -export SDC_CLI_KEY_ID='your_bits_here' -``` - -Integration tests using cloud drivers can be performed with either -``` -export KITCHEN_YAML=.kitchen.cloud.yml -bundle exec kitchen test -``` -or -``` -rake integration:cloud -``` - -Digital Ocean Hint ------------------- -At the time of this writing, you cannot find the numerical values -needed for your SSH_KEY_IDS from the GUI. Instead, you will need to -access the API from the command line. - - curl -L 'https://api.digitalocean.com/ssh_keys/?client_id=your_bits_here&api_key=your_bits_here' - -Words about .travis.yml ------------------------ -In order for Travis to perform integration tests on public cloud -providers, two major things need to happen. First, the environment -variables referenced by ```.kitchen.cloud.yml``` need to be made -available. Second, the private half of the ssh keys needed to log into -machines need to be dropped off on the machine. - -The first part is straight forward. The travis gem can encrypt -environment variables against the public key on the Travis repository -and add them to the .travis.yml. - -``` -gem install travis -travis encrypt AWS_ACCESS_KEY_ID='your_bits_here' --add -travis encrypt AWS_SECRET_ACCESS_'your_bits_here' --add -travis encrypt AWS_KEYPAIR_NAME='your_bits_here' --add -travis encrypt EC2_SSH_KEY_PATH='~/.ssh/id_ec2.pem' --add - -travis encrypt DIGITAL_OCEAN_CLIENT_ID='your_bits_here' --add -travis encrypt DIGITAL_OCEAN_API_KEY='your_bits_here' --add -travis encrypt DIGITAL_OCEAN_SSH_KEY_IDS='your_bits_here' --add -travis encrypt DIGITAL_OCEAN_SSH_KEY_PATH='~/.ssh/id_do.pem' --add -``` - -The second part is a little more complicated. Travis ENV variables are -restricted to 90 bytes, and will not fit an entire SSH key. This can -be worked around by breaking them up into 90 byte chunks, stashing -them into ENV variables, then digging them out in the -```before_install``` section of .travis.yml - -Here is an AWK script to do the encoding. -``` -base64 ~/.ssh/travisci_cook_digitalocean.pem | \ -awk '{ - j=0; - for( i=1; i> ~/.ssh/id_do.base64 -- cat ~/.ssh/id_do.base64 | tr -d ' ' | base64 --decode > ~/.ssh/id_do.pem - - echo -n $EC2_KEY_CHUNK_{0..30} >> ~/.ssh/id_ec2.base64 - - cat ~/.ssh/id_ec2.base64 | tr -d ' ' | base64 --decode > ~/.ssh/id_ec2.pem -``` - diff --git a/cookbooks/rsyslog/attributes/default.rb b/cookbooks/rsyslog/attributes/default.rb index 6ecd45f..1bfe703 100644 --- a/cookbooks/rsyslog/attributes/default.rb +++ b/cookbooks/rsyslog/attributes/default.rb @@ -2,7 +2,7 @@ # Cookbook Name:: rsyslog # Attributes:: default # -# Copyright 2009-2014, Chef Software, Inc. +# Copyright 2009-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. @@ -24,6 +24,7 @@ default['rsyslog']['server'] = false default['rsyslog']['use_relp'] = false default['rsyslog']['relp_port'] = 20_514 default['rsyslog']['protocol'] = 'tcp' +default['rsyslog']['bind'] = '*' default['rsyslog']['port'] = 514 default['rsyslog']['server_ip'] = nil default['rsyslog']['server_search'] = 'role:loghost' @@ -36,7 +37,7 @@ default['rsyslog']['repeated_msg_reduction'] = 'on' default['rsyslog']['logs_to_forward'] = '*.*' default['rsyslog']['enable_imklog'] = true default['rsyslog']['config_prefix'] = '/etc' -default['rsyslog']['default_file_template'] = nil +default['rsyslog']['default_file_template'] = nil default['rsyslog']['default_remote_template'] = nil default['rsyslog']['rate_limit_interval'] = nil default['rsyslog']['rate_limit_burst'] = nil @@ -48,6 +49,7 @@ default['rsyslog']['tls_key_file'] = nil default['rsyslog']['tls_auth_mode'] = 'anon' default['rsyslog']['use_local_ipv4'] = false default['rsyslog']['allow_non_local'] = false +default['rsyslog']['custom_remote'] = [{}] default['rsyslog']['additional_directives'] = {} # The most likely platform-specific attributes @@ -69,7 +71,7 @@ when 'rhel', 'fedora' 'authpriv.*' => "#{node['rsyslog']['default_log_dir']}/secure", 'mail.*' => "-#{node['rsyslog']['default_log_dir']}/maillog", 'cron.*' => "#{node['rsyslog']['default_log_dir']}/cron", - '*.emerg' => '*', + '*.emerg' => ':omusrmsg:*', 'uucp,news.crit' => "#{node['rsyslog']['default_log_dir']}/spooler", 'local7.*' => "#{node['rsyslog']['default_log_dir']}/boot.log" } @@ -95,10 +97,15 @@ else 'news.notice' => "-#{node['rsyslog']['default_log_dir']}/news/news.notice", '*.=debug;auth,authpriv.none;news.none;mail.none' => "-#{node['rsyslog']['default_log_dir']}/debug", '*.=info;*.=notice;*.=warn;auth,authpriv.none;cron,daemon.none;mail,news.none' => "-#{node['rsyslog']['default_log_dir']}/messages", - '*.emerg' => '*' + '*.emerg' => ':omusrmsg:*' } end +# rsyslog 3/4 do not support the new :omusrmsg:* format and need * instead +if (node['platform'] == 'ubuntu' && node['platform_version'].to_i < 12) || (node['platform_family'] == 'rhel' && node['platform_version'].to_i < 6) + default['rsyslog']['default_facility_logs']['*.emerg'] = '*' +end + # platform specific attributes case node['platform'] when 'ubuntu' diff --git a/cookbooks/rsyslog/libraries/helpers.rb b/cookbooks/rsyslog/libraries/helpers.rb index 51dd4b4..176a6d8 100644 --- a/cookbooks/rsyslog/libraries/helpers.rb +++ b/cookbooks/rsyslog/libraries/helpers.rb @@ -1,15 +1,22 @@ module RsyslogCookbook # helpers for the various service providers on Ubuntu systems module Helpers - def declare_rsyslog_service - if node['platform'] == 'ubuntu' && node['platform_version'].to_f >= 12.04 + def find_provider + if Chef::VersionConstraint.new('>= 15.04').include?(node['platform_version']) + service_provider = Chef::Provider::Service::Systemd + elsif Chef::VersionConstraint.new('>= 12.04').include?(node['platform_version']) service_provider = Chef::Provider::Service::Upstart else service_provider = nil end + service_provider + end + + def declare_rsyslog_service + service_provider = 'ubuntu' == node['platform'] ? find_provider : nil service node['rsyslog']['service_name'] do - supports :restart => true, :status => true + supports restart: true, status: true action [:enable, :start] provider service_provider end diff --git a/cookbooks/rsyslog/metadata.json b/cookbooks/rsyslog/metadata.json index cc27e33..058e4b1 100644 --- a/cookbooks/rsyslog/metadata.json +++ b/cookbooks/rsyslog/metadata.json @@ -1,375 +1 @@ -{ - "name": "rsyslog", - "description": "Installs and configures rsyslog", - "long_description": "rsyslog Cookbook\n================\n[![Build Status](https://secure.travis-ci.org/opscode-cookbooks/rsyslog.png?branch=master)](http://travis-ci.org/opscode-cookbooks/rsyslog)\n\nInstalls and configures rsyslog to replace sysklogd for client and/or server use. By default, the service will be configured to log to files on local disk. See the Recipes and Examples sections for other uses.\n\n\nRequirements\n------------\n### Platforms\nTested on:\n- Ubuntu 10.04+\n- Red Hat / CentOS 5+\n- Fedora 20+\n- OmniOS r151006c\n\n### Other\nTo use the `recipe[rsyslog::client]` recipe, you'll need to set up the `rsyslog.server_search` or `rsyslog.server_ip` attributes. See the __Recipes__ and __Examples__ sections below.\n\n\nAttributes\n----------\nSee `attributes/default.rb` for default values.\n\n* `node['rsyslog']['log_dir']` - If the node is an rsyslog server, this specifies the directory where the logs should be stored.\n* `node['rsyslog']['working_dir']` - The temporary working directory where messages are buffered\n* `node['rsyslog']['server']` - Determined automatically and set to true on the server.\n* `node['rsyslog']['server_ip']` - If not defined then search will be used to determine rsyslog server. Default is `nil`. This can be a string or an array.\n* `node['rsyslog']['server_search']` - Specify the criteria for the server search operation. Default is `role:loghost`.\n* `node['rsyslog']['protocol']` - Specify whether to use `udp` or `tcp` for remote loghost. Default is `tcp`.\n* `node['rsyslog']['port']` - Specify the port which rsyslog should connect to a remote loghost.\n* `node['rsyslog']['remote_logs']` - Specify wether to send all logs to a remote server (client option). Default is `true`.\n* `node['rsyslog']['per_host_dir']` - \"PerHost\" directories for template statements in `35-server-per-host.conf`. Default value is the previous cookbook version's value, to preserve compatibility. See __server__ recipe below.\n* `node['rsyslog']['priv_seperation']` - Whether to use privilege separation or not.\n* `node['rsyslog']['priv_user']` - User to run as when using privilege separation. Defult is `node['rsyslog']['user']`\n* `node['rsyslog']['priv_group']` - Group to run as when using privilege separation. Defult is `node['rsyslog']['group']`\n* `node['rsyslog']['max_message_size']` - Specify the maximum allowed message size. Default is 2k.\n* `node['rsyslog']['user']` - Who should own the configuration files and directories\n* `node['rsyslog']['group']` - Who should group-own the configuration files and directories\n* `node['rsyslog']['defaults_file']` - The full path to the defaults/sysconfig file for the service.\n* `node['rsyslog']['service_name']` - The platform-specific name of the service\n* `node['rsyslog']['preserve_fqdn']` - Value of the `$PreserveFQDN` configuration directive in `/etc/rsyslog.conf`. Default is 'off' for compatibility purposes.\n* `node['rsyslog']['high_precision_timestamps']` - Enable high precision timestamps, instead of the \"old style\" format. Default is 'false'.\n* `node['rsyslog']['repeated_msg_reduction']` - Value of `$RepeatedMsgReduction` configuration directive in `/etc/rsyslog.conf`. Default is 'on'\n* `node['rsyslog']['logs_to_forward']` - Specifies what logs should be sent to the remote rsyslog server. Default is all ( \\*.\\* ).\n* `node['rsyslog']['default_log_dir']` - log directory used in `50-default.conf` template, defaults to `/var/log`\n* `node['rsyslog']['default_facility_logs']` - Hash containing log facilities and destinations used in `50-default.conf` template.\n* `node['rsyslog']['default_file_template']` - The name of a pre-defined log format template (ie - RSYSLOG_FileFormat), used for local log files.\n* `node['rsyslog']['rate_limit_interval']` - Value of the $SystemLogRateLimitInterval configuration directive in `/etc/rsyslog.conf`. Default is nil, leaving it to the platform default.\n* `node['rsyslog']['rate_limit_burst']` - Value of the $SystemLogRateLimitBurst configuration directive in `/etc/rsyslog.conf`. Default is nil, leaving it to the platform default.\n* `node['rsyslog']['action_queue_max_disk_space']` - Max amount of disk space the disk-assisted queue is allowed to use ([more info](http://www.rsyslog.com/doc/queues.html)).\n* `node['rsyslog']['enable_tls']` - Whether or not to enable TLS encryption. When enabled, forces protocol to `tcp`. Default is `false`.\n* `node['rsyslog']['tls_ca_file']` - Path to TLS CA file. Required for both server and clients.\n* `node['rsyslog']['tls_certificate_file']` - Path to TLS certificate file. Required for server, optional for clients.\n* `node['rsyslog']['tls_key_file']` - Path to TLS key file. Required for server, optional for clients.\n* `node['rsyslog']['tls_auth_mode']` - Value for `$InputTCPServerStreamDriverAuthMode`/`$ActionSendStreamDriverAuthMode`, determines whether client certs are validated. Defaults to `anon` (no validation).\n* `node['rsyslog']['use_local_ipv4']` - Whether or not to make use the remote local IPv4 address on cloud systems when searching for servers (where available). Default is 'false'.\n* `node['rsyslog']['allow_non_local']` - Whether or not to allow non-local messages. If 'false', incoming messages are only allowed from 127.0.0.1. Default is 'false'.\n* `node['rsyslog']['additional_directives']` - Hash of additional directives and their values to place in the main rsyslog config file\n\nRecipes\n-------\n### default\nInstalls the rsyslog package, manages the rsyslog service and sets up basic configuration for a standalone machine.\n\n### client\nIncludes `recipe[rsyslog]`.\n\nUses `node['rsyslog']['server_ip']` or Chef search (in that precedence order) to determine the remote syslog server's IP address. If search is used, the search query will look for the first `ipaddress` returned from the criteria specified in `node['rsyslog']['server_search']`.\n\nIf the node itself is a rsyslog server ie it has `rsyslog.server` set to true then the configuration is skipped.\n\nIf the node had an `/etc/rsyslog.d/35-server-per-host.conf` file previously configured, this file gets removed to prevent duplicate logging.\n\nAny previous logs are not cleaned up from the `log_dir`.\n\n### server\nConfigures the node to be a rsyslog server. The chosen rsyslog server node should be defined in the `server_ip` attribute or resolvable by the specified search criteria specified in `node['rsyslog']['server_search]` (so that nodes making use of the `client` recipe can find the server to log to).\n\nThis recipe will create the logs in `node['rsyslog']['log_dir']`, and the configuration is in `/etc/rsyslog.d/server.conf`. This recipe also removes any previous configuration to a remote server by removing the `/etc/rsyslog.d/remote.conf` file.\n\nThe cron job used in the previous version of this cookbook is removed, but it does not remove any existing cron job from your system (so it doesn't break anything unexpectedly). We recommend setting up logrotate for the logfiles instead.\n\nThe `log_dir` will be concatenated with `per_host_dir` to store the logs for each client. Modify the attribute to have a value that is allowed by rsyslogs template matching values, see the rsyslog documentation for this.\n\nDirectory structure:\n\n```erb\n<%= @log_dir %>/<%= @per_host_dir %>/\"logfile\"\n```\n\nFor example for the system with hostname `www`:\n\n```text\n/srv/rsyslog/2011/11/19/www/messages\n```\n\nFor example, to change this to just the hostname, set the attribute `node['rsyslog']['per_host_dir']` via a role:\n\n```ruby\n\"rsyslog\" => { \"per_host_dir\" => \"%HOSTNAME%\" }\n```\n\nAt this time, the server can only listen on UDP *or* TCP.\n\nResources\n=========\n\nfile_input\n----------\n\nConfigures a (text file input\nmonitor)[http://www.rsyslog.com/doc/imfile.html] to push a log file into\nrsyslog.\n\nAttributes:\n* `name`: name of the resource, also used for the syslog tag. Required.\n* `file`: file path for input file to monitor. Required.\n* `priority`: config order priority. Defaults to `99`.\n* `severity`: syslog severity. Must be one of `emergency`, `alert`,\n`critical`, `error`, `warning`, `notice`, `info` or `debug`. If\nundefined, rsyslog interprets this as `notice`.\n* `facility`: syslog facility. Must be one of `auth`, `authpriv`,\n`daemon`, `cron`, `ftp`, `lpr`, `kern`, `mail`, `news`, `syslog`,\n`user`, `uucp`, `local0`, ... , `local7`. If undefined, rsyslog\ninterprets this as `local0`.\n* `cookbook`: cookbook containing the template. Defaults to `rsyslog`.\n* `source`: template file source. Defaults to `file-input.conf.erb`\n\n\nUsage\n=====\nUse `recipe[rsyslog]` to install and start rsyslog as a basic configured service for standalone systems.\n\nUse `recipe[rsyslog::client]` to have nodes log to a remote server (which is found via the `server_ip` attribute or by the recipe's search call -- see __client__)\n\nUse `recipe[rsyslog::server]` to set up a rsyslog server. It will listen on `node['rsyslog']['port']` protocol `node['rsyslog']['protocol']`.\n\nIf you set up a different kind of centralized loghost (syslog-ng, graylog2, logstash, etc), you can still send log messages to it as long as the port and protocol match up with the server software. See __Examples__\n\nUse `rsyslog_file_input` within your recipes to forward log files to\nyour remote syslog server.\n\n\n### Examples\nA `base` role (e.g., roles/base.rb), applied to all nodes so they are syslog clients:\n\n```ruby\nname \"base\"\ndescription \"Base role applied to all nodes\nrun_list(\"recipe[rsyslog::client]\")\n```\n\nThen, a role for the loghost (should only be one):\n\n```ruby\nname \"loghost\"\ndescription \"Central syslog server\"\nrun_list(\"recipe[rsyslog::server]\")\n```\n\nBy default this will set up the clients search for a node with the `loghost` role to talk to the server on TCP port 514. Change the `protocol` and `port` rsyslog attributes to modify this.\n\nIf you want to specify another syslog compatible server with a role other than loghost, simply fill free to use the `server_ip` attribute or the `server_search` attribute.\n\nExample role that sets the per host directory:\n\n```ruby\nname \"loghost\"\ndescription \"Central syslog server\"\nrun_list(\"recipe[rsyslog::server]\")\ndefault_attributes(\n \"rsyslog\" => { \"per_host_dir\" => \"%HOSTNAME%\" }\n)\n```\n\nDefault rsyslog options are rendered for RHEL family platforms, in `/etc/rsyslog.d/50-default.conf`\nwith other platforms using a configuration like Debian family defaults. You can override these\nlog facilities and destinations using the `rsyslog['default_facility_logs']` hash.\n\n```ruby\nname \"facility_log_example\"\nrun_list(\"recipe[rsyslog::default]\")\ndefault_attributes(\n \"rsyslog\" => {\n \"facility_logs\" => {\n '*.info;mail.none;authpriv.none;cron.none' => \"/var/log/messages\",\n 'authpriv' => '/var/log/secure',\n 'mail.*' => '-/var/log/maillog',\n '*.emerg' => '*'\n }\n }\n)\n```\n\nDevelopment\n-----------\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:opscode-cookbooks/rsyslog.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 appropriately\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\nLicense & Authors\n-----------------\n- Author:: Joshua Timberman ()\n- Author:: Denis Barishev ()\n- Author:: Tim Smith ()\n\n```text\nCopyright:: 2009-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", - "maintainer": "Chef Software, Inc.", - "maintainer_email": "cookbooks@chef.io", - "license": "Apache 2.0", - "platforms": { - "ubuntu": ">= 10.04", - "debian": ">= 5.0", - "redhat": ">= 5.0", - "centos": ">= 5.0", - "fedora": ">= 20.0" - }, - "dependencies": { - - }, - "recommendations": { - - }, - "suggestions": { - - }, - "conflicting": { - - }, - "providing": { - - }, - "replacing": { - - }, - "attributes": { - "rsyslog": { - "display_name": "Rsyslog", - "description": "Hash of Rsyslog attributes", - "type": "hash", - "choice": [ - - ], - "calculated": false, - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/log_dir": { - "display_name": "Rsyslog Log Directory", - "description": "Filesystem location of logs from clients", - "default": "/srv/rsyslog", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/server": { - "display_name": "Rsyslog Server?", - "description": "Is this node an rsyslog server?", - "default": "false", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/server_ip": { - "display_name": "Rsyslog Server IP Address", - "description": "Set rsyslog server ip address explicitly", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/server_search": { - "display_name": "Rsyslog Server Search Criteria", - "description": "Set the search criteria for rsyslog server resolving", - "default": "role:loghost", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/protocol": { - "display_name": "Rsyslog Protocol", - "description": "Set which network protocol to use for rsyslog", - "default": "tcp", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/port": { - "display_name": "Rsyslog Port", - "description": "Port that Rsyslog listens for incoming connections", - "default": "514", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/remote_logs": { - "display_name": "Remote Logs", - "description": "Specifies whether redirect all log from client to server", - "default": "true", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/user": { - "display_name": "User", - "description": "The owner of Rsyslog config files and directories", - "default": "root", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/group": { - "display_name": "Group", - "description": "The group-owner of Rsyslog config files and directories", - "default": "adm", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/service_name": { - "display_name": "Service name", - "description": "The name of the service for the platform", - "default": "rsyslog", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/max_message_size": { - "display_name": "Maximum Rsyslog message size", - "description": "Specifies the maximum size of allowable Rsyslog messages", - "default": "2k", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/preserve_fqdn": { - "display_name": "Preserve FQDN", - "description": "Specifies if the short or full host name will be used. The default off setting is more compatible.", - "default": "off", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/repeated_msg_reduction": { - "display_name": "Filter duplicated messages", - "description": "Specifies whether or not repeated messages should be reduced.", - "default": "on", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/priv_seperation": { - "display_name": "Privilege separation", - "description": "Whether or not to make use of Rsyslog privilege separation", - "default": "false", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/default_file_template": { - "display_name": "Default file log format template", - "description": "The name of a pre-defined log format template (ie - `RSYSLOG_FileFormat`), used for local log files.", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/default_remote_template": { - "display_name": "Default remote log format template", - "description": "The name of a pre-defined log format template (ie - `RSYSLOG_SyslogProtocol23Format`), used for remote log forwarding.", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/enable_tls": { - "display_name": "Enable TLS", - "description": "Whether or not to enable TLS encryption. When enabled, forces protocol to \"tcp\"", - "default": "false", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/tls_ca_file": { - "display_name": "TLS CA file", - "description": "Path to TLS CA file. Required for both server and clients.", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/tls_certificate_file": { - "display_name": "TLS certificate file", - "description": "Path to TLS certificate file. Required for server, optional for clients.", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/tls_key_file": { - "display_name": "TLS key file", - "description": "Path to TLS key file. Required for server, optional for clients.", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/tls_auth_mode": { - "display_name": "TLS auth mode", - "description": "Value for \"$InputTCPServerStreamDriverAuthMode\"/\"$ActionSendStreamDriverAuthMode\", determines whether client certs are validated.", - "default": "anon", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/use_local_ipv4": { - "display_name": "Try to use local IPv4 address", - "description": "Whether or not to make use the remote local IPv4 address on cloud systems when searching for servers (where available).", - "default": "false", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - }, - "rsyslog/allow_non_local": { - "display_name": "Allow non-local messages", - "description": "Allow processing of messages coming any IP, not just 127.0.0.1", - "default": "false", - "choice": [ - - ], - "calculated": false, - "type": "string", - "required": "optional", - "recipes": [ - - ] - } - }, - "groupings": { - - }, - "recipes": { - "rsyslog": "Installs rsyslog", - "rsyslog::client": "Sets up a client to log to a remote rsyslog server", - "rsyslog::server": "Sets up an rsyslog server" - }, - "version": "2.0.0", - "source_url": "", - "issues_url": "" -} +{"name":"rsyslog","version":"2.2.0","description":"Installs and configures rsyslog","long_description":"rsyslog Cookbook\n================\n[![Build Status](https://travis-ci.org/chef-cookbooks/rsyslog.svg?branch=master)](http://travis-ci.org/chef-cookbooks/rsyslog)\n[![Cookbook Version](https://img.shields.io/cookbook/v/rsyslog.svg)](https://supermarket.chef.io/cookbooks/rsyslog)\n\nInstalls and configures rsyslog to replace sysklogd for client and/or server use. By default, the service will be configured to log to files on local disk. See the Recipes and Examples sections for other uses.\n\n\nRequirements\n------------\n#### Platforms\n- Debian/Ubuntu\n- RHEL/CentOS/Scientific/Amazon/Oracle\n- Fedora 20+\n- OmniOS r151006c\n\n#### Chef\n- Chef 11+\n\n#### Cookbooks\n- none\n\n#### Other\nTo use the `recipe[rsyslog::client]` recipe, you'll need to set up the `rsyslog.server_search` or `rsyslog.server_ip` attributes. See the __Recipes__ and __Examples__ sections below.\n\n\nAttributes\n----------\nSee `attributes/default.rb` for default values.\n\n* `node['rsyslog']['log_dir']` - If the node is an rsyslog server, this specifies the directory where the logs should be stored.\n* `node['rsyslog']['working_dir']` - The temporary working directory where messages are buffered\n* `node['rsyslog']['server']` - Determined automatically and set to true on the server.\n* `node['rsyslog']['server_ip']` - If not defined then search will be used to determine rsyslog server. Default is `nil`. This can be a string or an array.\n* `node['rsyslog']['server_search']` - Specify the criteria for the server search operation. Default is `role:loghost`.\n* `node['rsyslog']['protocol']` - Specify whether to use `udp` or `tcp` for remote loghost. Default is `tcp`. To use both specify both in a string e.g. 'udptcp'.\n* `node['rsyslog']['bind']` - Specify the address to which the server should be listening; only use with `node['rsyslog']['protocol'] = 'udp'` because the feature does not work with the `tcp` protocol ([more info](http://www.rsyslog.com/doc/master/configuration/modules/imtcp.html#caveats-known-bugs)).\n* `node['rsyslog']['port']` - Specify the port which rsyslog should connect to a remote loghost.\n* `node['rsyslog']['remote_logs']` - Specify whether to send all logs to a remote server (client option). Default is `true`.\n* `node['rsyslog']['per_host_dir']` - \"PerHost\" directories for template statements in `35-server-per-host.conf`. Default value is the previous cookbook version's value, to preserve compatibility. See __server__ recipe below.\n* `node['rsyslog']['priv_seperation']` - Whether to use privilege separation or not.\n* `node['rsyslog']['priv_user']` - User to run as when using privilege separation. Defult is `node['rsyslog']['user']`\n* `node['rsyslog']['priv_group']` - Group to run as when using privilege separation. Defult is `node['rsyslog']['group']`\n* `node['rsyslog']['max_message_size']` - Specify the maximum allowed message size. Default is 2k.\n* `node['rsyslog']['user']` - Who should own the configuration files and directories\n* `node['rsyslog']['group']` - Who should group-own the configuration files and directories\n* `node['rsyslog']['defaults_file']` - The full path to the defaults/sysconfig file for the service.\n* `node['rsyslog']['service_name']` - The platform-specific name of the service\n* `node['rsyslog']['preserve_fqdn']` - Value of the `$PreserveFQDN` configuration directive in `/etc/rsyslog.conf`. Default is 'off' for compatibility purposes.\n* `node['rsyslog']['high_precision_timestamps']` - Enable high precision timestamps, instead of the \"old style\" format. Default is 'false'.\n* `node['rsyslog']['repeated_msg_reduction']` - Value of `$RepeatedMsgReduction` configuration directive in `/etc/rsyslog.conf`. Default is 'on'\n* `node['rsyslog']['logs_to_forward']` - Specifies what logs should be sent to the remote rsyslog server. Default is all ( \\*.\\* ).\n* `node['rsyslog']['default_log_dir']` - log directory used in `50-default.conf` template, defaults to `/var/log`\n* `node['rsyslog']['default_facility_logs']` - Hash containing log facilities and destinations used in `50-default.conf` template.\n* `node['rsyslog']['default_file_template']` - The name of a pre-defined log format template (ie - RSYSLOG_FileFormat), used for local log files.\n* `node['rsyslog']['default_remote_template']` - The name of a pre-defined log format template (ie - RSYSLOG_FileFormat), used for sending to remote servers.\n* `node['rsyslog']['rate_limit_interval']` - Value of the $SystemLogRateLimitInterval configuration directive in `/etc/rsyslog.conf`. Default is nil, leaving it to the platform default.\n* `node['rsyslog']['rate_limit_burst']` - Value of the $SystemLogRateLimitBurst configuration directive in `/etc/rsyslog.conf`. Default is nil, leaving it to the platform default.\n* `node['rsyslog']['action_queue_max_disk_space']` - Max amount of disk space the disk-assisted queue is allowed to use ([more info](http://www.rsyslog.com/doc/queues.html)).\n* `node['rsyslog']['enable_tls']` - Whether or not to enable TLS encryption. When enabled, forces protocol to `tcp`. Default is `false`.\n* `node['rsyslog']['tls_ca_file']` - Path to TLS CA file. Required for both server and clients.\n* `node['rsyslog']['tls_certificate_file']` - Path to TLS certificate file. Required for server, optional for clients.\n* `node['rsyslog']['tls_key_file']` - Path to TLS key file. Required for server, optional for clients.\n* `node['rsyslog']['tls_auth_mode']` - Value for `$InputTCPServerStreamDriverAuthMode`/`$ActionSendStreamDriverAuthMode`, determines whether client certs are validated. Defaults to `anon` (no validation).\n* `node['rsyslog']['use_local_ipv4']` - Whether or not to make use the remote local IPv4 address on cloud systems when searching for servers (where available). Default is 'false'.\n* `node['rsyslog']['allow_non_local']` - Whether or not to allow non-local messages. If 'false', incoming messages are only allowed from 127.0.0.1. Default is 'false'.\n* `node['rsyslog']['custom_remote']` - Array of hashes for configuring custom remote server targets\n* `node['rsyslog']['additional_directives']` - Hash of additional directives and their values to place in the main rsyslog config file\n\nRecipes\n-------\n### default\nInstalls the rsyslog package, manages the rsyslog service and sets up basic configuration for a standalone machine.\n\n### client\nIncludes `recipe[rsyslog]`.\n\nUses `node['rsyslog']['server_ip']` or Chef search (in that precedence order) to determine the remote syslog server's IP address. If search is used, the search query will look for the first `ipaddress` returned from the criteria specified in `node['rsyslog']['server_search']`.\n\nYou can use `node['rsyslog']['custom_config']` to define custom entries for sending logs to remote servers.\nAvailable attributes:\n```\n 'server': Ip/hostname of remote syslog server (Required)\n 'port': Port to send logs to\n 'logs': Syslog log facilities to send (auth, authpriv, daemon, etc)\n 'protocol': Can be tcp or udp\n 'remote_template': Rsyslog template used for the messages\n```\n\nExample:\n\n```ruby\nnode['rsyslog']['custom_remote'] = [{ 'server' => '10.10.4.4', 'port' => '567', 'logs' => 'auth.*,mail.*', 'protocol' => 'udp', 'remote_template' => 'RSYSLOG_SyslogProtocol23Format'},\n { 'server' => '10.0.0.3', 'port' => '555', 'logs' => 'authpriv,daemon.*' } ]\n```\n\nThe server key is required; if other keys are left out, the default global values will be used (eg `node['rsyslog']['port']` will be used if 'port' is omitted)\n\n\nIf the node itself is a rsyslog server ie it has `rsyslog.server` set to true then the configuration is skipped.\n\nIf the node had an `/etc/rsyslog.d/35-server-per-host.conf` file previously configured, this file gets removed to prevent duplicate logging.\n\nAny previous logs are not cleaned up from the `log_dir`.\n\n### server\nConfigures the node to be a rsyslog server. The chosen rsyslog server node should be defined in the `server_ip` attribute or resolvable by the specified search criteria specified in `node['rsyslog']['server_search]` (so that nodes making use of the `client` recipe can find the server to log to).\n\nThis recipe will create the logs in `node['rsyslog']['log_dir']`, and the configuration is in `/etc/rsyslog.d/server.conf`. This recipe also removes any previous configuration to a remote server by removing the `/etc/rsyslog.d/remote.conf` file.\n\nThe cron job used in the previous version of this cookbook is removed, but it does not remove any existing cron job from your system (so it doesn't break anything unexpectedly). We recommend setting up logrotate for the logfiles instead.\n\nThe `log_dir` will be concatenated with `per_host_dir` to store the logs for each client. Modify the attribute to have a value that is allowed by rsyslogs template matching values, see the rsyslog documentation for this.\n\nDirectory structure:\n\n```erb\n<%= @log_dir %>/<%= @per_host_dir %>/\"logfile\"\n```\n\nFor example for the system with hostname `www`:\n\n```text\n/srv/rsyslog/2011/11/19/www/messages\n```\n\nFor example, to change this to just the hostname, set the attribute `node['rsyslog']['per_host_dir']` via a role:\n\n```ruby\n\"rsyslog\" => { \"per_host_dir\" => \"%HOSTNAME%\" }\n```\n\nAt this time, the server can only listen on UDP *or* TCP.\n\nResources\n=========\n\nfile_input\n----------\n\nConfigures a [text file input\nmonitor](http://www.rsyslog.com/doc/imfile.html) to push a log file into\nrsyslog.\n\nAttributes:\n* `name`: name of the resource, also used for the syslog tag. Required.\n* `file`: file path for input file to monitor. Required.\n* `priority`: config order priority. Defaults to `99`.\n* `severity`: syslog severity. Must be one of `emergency`, `alert`,\n`critical`, `error`, `warning`, `notice`, `info` or `debug`. If\nundefined, rsyslog interprets this as `notice`.\n* `facility`: syslog facility. Must be one of `auth`, `authpriv`,\n`daemon`, `cron`, `ftp`, `lpr`, `kern`, `mail`, `news`, `syslog`,\n`user`, `uucp`, `local0`, ... , `local7`. If undefined, rsyslog\ninterprets this as `local0`.\n* `cookbook`: cookbook containing the template. Defaults to `rsyslog`.\n* `source`: template file source. Defaults to `file-input.conf.erb`\n\n\nUsage\n=====\nUse `recipe[rsyslog]` to install and start rsyslog as a basic configured service for standalone systems.\n\nUse `recipe[rsyslog::client]` to have nodes log to a remote server (which is found via the `server_ip` attribute or by the recipe's search call -- see __client__)\n\nUse `recipe[rsyslog::server]` to set up a rsyslog server. It will listen on `node['rsyslog']['port']` protocol `node['rsyslog']['protocol']`.\n\nIf you set up a different kind of centralized loghost (syslog-ng, graylog2, logstash, etc), you can still send log messages to it as long as the port and protocol match up with the server software. See __Examples__\n\nUse `rsyslog_file_input` within your recipes to forward log files to\nyour remote syslog server.\n\n\n### Examples\nA `base` role (e.g., roles/base.rb), applied to all nodes so they are syslog clients:\n\n```ruby\nname \"base\"\ndescription \"Base role applied to all nodes\nrun_list(\"recipe[rsyslog::client]\")\n```\n\nThen, a role for the loghost (should only be one):\n\n```ruby\nname \"loghost\"\ndescription \"Central syslog server\"\nrun_list(\"recipe[rsyslog::server]\")\n```\n\nBy default this will set up the clients search for a node with the `loghost` role to talk to the server on TCP port 514. Change the `protocol` and `port` rsyslog attributes to modify this.\n\nIf you want to specify another syslog compatible server with a role other than loghost, simply fill free to use the `server_ip` attribute or the `server_search` attribute.\n\nExample role that sets the per host directory:\n\n```ruby\nname \"loghost\"\ndescription \"Central syslog server\"\nrun_list(\"recipe[rsyslog::server]\")\ndefault_attributes(\n \"rsyslog\" => { \"per_host_dir\" => \"%HOSTNAME%\" }\n)\n```\n\nDefault rsyslog options are rendered for RHEL family platforms, in `/etc/rsyslog.d/50-default.conf`\nwith other platforms using a configuration like Debian family defaults. You can override these\nlog facilities and destinations using the `rsyslog['default_facility_logs']` hash.\n\n```ruby\nname \"facility_log_example\"\nrun_list(\"recipe[rsyslog::default]\")\ndefault_attributes(\n \"rsyslog\" => {\n \"default_facility_logs\" => {\n '*.info;mail.none;authpriv.none;cron.none' => \"/var/log/messages\",\n 'authpriv' => '/var/log/secure',\n 'mail.*' => '-/var/log/maillog',\n '*.emerg' => '*'\n }\n }\n)\n```\n\nDevelopment\n-----------\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/rsyslog.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 appropriately\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\nLicense & Authors\n-----------------\n- Author:: Joshua Timberman ()\n- Author:: Denis Barishev ()\n- Author:: Tim Smith ()\n\n```text\nCopyright:: 2009-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","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache 2.0","platforms":{"ubuntu":">= 10.04","debian":">= 5.0","redhat":">= 5.0","centos":">= 5.0","fedora":">= 20.0","scientific":">= 0.0.0","amazon":">= 0.0.0","oracle":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{"rsyslog":{"display_name":"Rsyslog","description":"Hash of Rsyslog attributes","type":"hash"},"rsyslog/log_dir":{"display_name":"Rsyslog Log Directory","description":"Filesystem location of logs from clients","default":"/srv/rsyslog"},"rsyslog/server":{"display_name":"Rsyslog Server?","description":"Is this node an rsyslog server?","default":"false"},"rsyslog/server_ip":{"display_name":"Rsyslog Server IP Address","description":"Set rsyslog server ip address explicitly"},"rsyslog/server_search":{"display_name":"Rsyslog Server Search Criteria","description":"Set the search criteria for rsyslog server resolving","default":"role:loghost"},"rsyslog/protocol":{"display_name":"Rsyslog Protocol","description":"Set which network protocol to use for rsyslog","default":"tcp"},"rsyslog/port":{"display_name":"Rsyslog Port","description":"Port that Rsyslog listens for incoming connections","default":"514"},"rsyslog/remote_logs":{"display_name":"Remote Logs","description":"Specifies whether redirect all log from client to server","default":"true"},"rsyslog/user":{"display_name":"User","description":"The owner of Rsyslog config files and directories","default":"root"},"rsyslog/group":{"display_name":"Group","description":"The group-owner of Rsyslog config files and directories","default":"adm"},"rsyslog/service_name":{"display_name":"Service name","description":"The name of the service for the platform","default":"rsyslog"},"rsyslog/max_message_size":{"display_name":"Maximum Rsyslog message size","description":"Specifies the maximum size of allowable Rsyslog messages","default":"2k"},"rsyslog/preserve_fqdn":{"display_name":"Preserve FQDN","description":"Specifies if the short or full host name will be used. The default off setting is more compatible.","default":"off"},"rsyslog/repeated_msg_reduction":{"display_name":"Filter duplicated messages","description":"Specifies whether or not repeated messages should be reduced.","default":"on"},"rsyslog/priv_seperation":{"display_name":"Privilege separation","description":"Whether or not to make use of Rsyslog privilege separation","default":"false"},"rsyslog/default_file_template":{"display_name":"Default file log format template","description":"The name of a pre-defined log format template (ie - `RSYSLOG_FileFormat`), used for local log files."},"rsyslog/default_remote_template":{"display_name":"Default remote log format template","description":"The name of a pre-defined log format template (ie - `RSYSLOG_SyslogProtocol23Format`), used for remote log forwarding."},"rsyslog/enable_tls":{"display_name":"Enable TLS","description":"Whether or not to enable TLS encryption. When enabled, forces protocol to \"tcp\"","default":"false"},"rsyslog/tls_ca_file":{"display_name":"TLS CA file","description":"Path to TLS CA file. Required for both server and clients."},"rsyslog/tls_certificate_file":{"display_name":"TLS certificate file","description":"Path to TLS certificate file. Required for server, optional for clients."},"rsyslog/tls_key_file":{"display_name":"TLS key file","description":"Path to TLS key file. Required for server, optional for clients."},"rsyslog/tls_auth_mode":{"display_name":"TLS auth mode","description":"Value for \"$InputTCPServerStreamDriverAuthMode\"/\"$ActionSendStreamDriverAuthMode\", determines whether client certs are validated.","default":"anon"},"rsyslog/use_local_ipv4":{"display_name":"Try to use local IPv4 address","description":"Whether or not to make use the remote local IPv4 address on cloud systems when searching for servers (where available).","default":"false"},"rsyslog/allow_non_local":{"display_name":"Allow non-local messages","description":"Allow processing of messages coming any IP, not just 127.0.0.1","default":"false"}},"groupings":{},"recipes":{"rsyslog":"Installs rsyslog","rsyslog::client":"Sets up a client to log to a remote rsyslog server","rsyslog::server":"Sets up an rsyslog server"},"source_url":"https://github.com/chef-cookbooks/rsyslog","issues_url":"https://github.com/chef-cookbooks/rsyslog/issues"} \ No newline at end of file diff --git a/cookbooks/rsyslog/metadata.rb b/cookbooks/rsyslog/metadata.rb deleted file mode 100644 index 6f33e5e..0000000 --- a/cookbooks/rsyslog/metadata.rb +++ /dev/null @@ -1,131 +0,0 @@ -name 'rsyslog' -maintainer 'Chef Software, Inc.' -maintainer_email 'cookbooks@chef.io' -license 'Apache 2.0' -description 'Installs and configures rsyslog' -long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) -version '2.0.0' - -recipe 'rsyslog', 'Installs rsyslog' -recipe 'rsyslog::client', 'Sets up a client to log to a remote rsyslog server' -recipe 'rsyslog::server', 'Sets up an rsyslog server' - -supports 'ubuntu', '>= 10.04' -supports 'debian', '>= 5.0' -supports 'redhat', '>= 5.0' -supports 'centos', '>= 5.0' -supports 'fedora', '>= 20.0' - -attribute 'rsyslog', - :display_name => 'Rsyslog', - :description => 'Hash of Rsyslog attributes', - :type => 'hash' - -attribute 'rsyslog/log_dir', - :display_name => 'Rsyslog Log Directory', - :description => 'Filesystem location of logs from clients', - :default => '/srv/rsyslog' - -attribute 'rsyslog/server', - :display_name => 'Rsyslog Server?', - :description => 'Is this node an rsyslog server?', - :default => 'false' - -attribute 'rsyslog/server_ip', - :display_name => 'Rsyslog Server IP Address', - :description => 'Set rsyslog server ip address explicitly' - -attribute 'rsyslog/server_search', - :display_name => 'Rsyslog Server Search Criteria', - :description => 'Set the search criteria for rsyslog server resolving', - :default => 'role:loghost' - -attribute 'rsyslog/protocol', - :display_name => 'Rsyslog Protocol', - :description => 'Set which network protocol to use for rsyslog', - :default => 'tcp' - -attribute 'rsyslog/port', - :display_name => 'Rsyslog Port', - :description => 'Port that Rsyslog listens for incoming connections', - :default => '514' - -attribute 'rsyslog/remote_logs', - :display_name => 'Remote Logs', - :description => 'Specifies whether redirect all log from client to server', - :default => 'true' - -attribute 'rsyslog/user', - :display_name => 'User', - :description => 'The owner of Rsyslog config files and directories', - :default => 'root' - -attribute 'rsyslog/group', - :display_name => 'Group', - :description => 'The group-owner of Rsyslog config files and directories', - :default => 'adm' - -attribute 'rsyslog/service_name', - :display_name => 'Service name', - :description => 'The name of the service for the platform', - :default => 'rsyslog' - -attribute 'rsyslog/max_message_size', - :display_name => 'Maximum Rsyslog message size', - :description => 'Specifies the maximum size of allowable Rsyslog messages', - :default => '2k' - -attribute 'rsyslog/preserve_fqdn', - :display_name => 'Preserve FQDN', - :description => 'Specifies if the short or full host name will be used. The default off setting is more compatible.', - :default => 'off' - -attribute 'rsyslog/repeated_msg_reduction', - :display_name => 'Filter duplicated messages', - :description => 'Specifies whether or not repeated messages should be reduced.', - :default => 'on' - -attribute 'rsyslog/priv_seperation', - :display_name => 'Privilege separation', - :description => 'Whether or not to make use of Rsyslog privilege separation', - :default => 'false' - -attribute 'rsyslog/default_file_template', - :display_name => 'Default file log format template', - :description => 'The name of a pre-defined log format template (ie - `RSYSLOG_FileFormat`), used for local log files.' - -attribute 'rsyslog/default_remote_template', - :display_name => 'Default remote log format template', - :description => 'The name of a pre-defined log format template (ie - `RSYSLOG_SyslogProtocol23Format`), used for remote log forwarding.' - -attribute 'rsyslog/enable_tls', - :display_name => 'Enable TLS', - :description => 'Whether or not to enable TLS encryption. When enabled, forces protocol to "tcp"', - :default => 'false' - -attribute 'rsyslog/tls_ca_file', - :display_name => 'TLS CA file', - :description => 'Path to TLS CA file. Required for both server and clients.' - -attribute 'rsyslog/tls_certificate_file', - :display_name => 'TLS certificate file', - :description => 'Path to TLS certificate file. Required for server, optional for clients.' - -attribute 'rsyslog/tls_key_file', - :display_name => 'TLS key file', - :description => 'Path to TLS key file. Required for server, optional for clients.' - -attribute 'rsyslog/tls_auth_mode', - :display_name => 'TLS auth mode', - :description => 'Value for "$InputTCPServerStreamDriverAuthMode"/"$ActionSendStreamDriverAuthMode", determines whether client certs are validated.', - :default => 'anon' - -attribute 'rsyslog/use_local_ipv4', - :display_name => 'Try to use local IPv4 address', - :description => 'Whether or not to make use the remote local IPv4 address on cloud systems when searching for servers (where available).', - :default => 'false' - -attribute 'rsyslog/allow_non_local', - :display_name => 'Allow non-local messages', - :description => 'Allow processing of messages coming any IP, not just 127.0.0.1', - :default => 'false' diff --git a/cookbooks/rsyslog/providers/file_input.rb b/cookbooks/rsyslog/providers/file_input.rb index 6e17bd3..a5b6543 100644 --- a/cookbooks/rsyslog/providers/file_input.rb +++ b/cookbooks/rsyslog/providers/file_input.rb @@ -1,7 +1,7 @@ # Cookbook Name:: rsyslog # Provider:: file_input # -# Copyright 2012, Joseph Holsten +# Copyright 2012-2015, Joseph Holsten # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -16,6 +16,11 @@ # limitations under the License. # +# support whyrun +def whyrun_supported? + true +end + use_inline_resources include RsyslogCookbook::Helpers diff --git a/cookbooks/rsyslog/recipes/client.rb b/cookbooks/rsyslog/recipes/client.rb index 2add130..4cc55e6 100644 --- a/cookbooks/rsyslog/recipes/client.rb +++ b/cookbooks/rsyslog/recipes/client.rb @@ -2,7 +2,7 @@ # Cookbook Name:: rsyslog # Recipe:: client # -# Copyright 2009-2014, Chef Software, Inc. +# Copyright 2009-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. @@ -33,7 +33,7 @@ end # normal Chef, we leverage the search query. if Chef::Config[:solo] && !chef_solo_search_installed? if node['rsyslog']['server_ip'] - rsyslog_servers = Array(node['rsyslog']['server_ip']) + server_ips = Array(node['rsyslog']['server_ip']) else Chef::Application.fatal!("Chef Solo does not support search. You must set node['rsyslog']['server_ip'] or use the chef-solo-search cookbook!") end @@ -47,7 +47,22 @@ else end ipaddress end - rsyslog_servers = Array(node['rsyslog']['server_ip']) + Array(results) + server_ips = Array(node['rsyslog']['server_ip']) + Array(results) +end + +rsyslog_servers = [] + +server_ips.each do |ip| + rsyslog_servers << { 'server' => ip, 'port' => node['rsyslog']['port'], 'logs' => node['rsyslog']['logs_to_forward'], 'protocol' => node['rsyslog']['protocol'], 'remote_template' => node['rsyslog']['default_remote_template'] } +end + +unless node['rsyslog']['custom_remote'].first.empty? + node['rsyslog']['custom_remote'].each do |server| + if server['server'].nil? + Chef::Application.fatal!('Found a custom_remote server with no IP. Check your custom_remote attribute definition!') + end + end + rsyslog_servers += node['rsyslog']['custom_remote'] end if rsyslog_servers.empty? @@ -61,7 +76,7 @@ template "#{node['rsyslog']['config_prefix']}/rsyslog.d/49-remote.conf" do owner 'root' group 'root' mode '0644' - variables(:servers => rsyslog_servers) + variables(servers: rsyslog_servers) notifies :restart, "service[#{node['rsyslog']['service_name']}]" only_if { node['rsyslog']['remote_logs'] } end diff --git a/cookbooks/rsyslog/recipes/default.rb b/cookbooks/rsyslog/recipes/default.rb index d0fe51a..c35b194 100644 --- a/cookbooks/rsyslog/recipes/default.rb +++ b/cookbooks/rsyslog/recipes/default.rb @@ -2,7 +2,7 @@ # Cookbook Name:: rsyslog # Recipe:: default # -# Copyright 2009-2014, Chef Software, Inc. +# Copyright 2009-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. @@ -33,7 +33,7 @@ directory "#{node['rsyslog']['config_prefix']}/rsyslog.d" do mode '0755' end -directory node['rsyslog']['working_dir'] do +directory node['rsyslog']['working_dir'] do owner node['rsyslog']['user'] group node['rsyslog']['group'] mode '0700' diff --git a/cookbooks/rsyslog/recipes/server.rb b/cookbooks/rsyslog/recipes/server.rb index c1034d2..ec1391a 100644 --- a/cookbooks/rsyslog/recipes/server.rb +++ b/cookbooks/rsyslog/recipes/server.rb @@ -2,7 +2,7 @@ # Cookbook Name:: rsyslog # Recipe:: server # -# Copyright 2009-2014, Chef Software, Inc. +# Copyright 2009-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. diff --git a/cookbooks/rsyslog/resources/file_input.rb b/cookbooks/rsyslog/resources/file_input.rb index aca6539..05a4d8b 100644 --- a/cookbooks/rsyslog/resources/file_input.rb +++ b/cookbooks/rsyslog/resources/file_input.rb @@ -19,10 +19,10 @@ actions :create default_action :create -attribute :name, :kind_of => String, :name_attribute => true, :required => true -attribute :file, :kind_of => String, :required => true -attribute :priority, :kind_of => Integer, :default => 99 -attribute :severity, :kind_of => String -attribute :facility, :kind_of => String -attribute :cookbook, :kind_of => String, :default => 'rsyslog' -attribute :source, :kind_of => String, :default => 'file-input.conf.erb' +attribute :name, kind_of: String, name_attribute: true, required: true +attribute :file, kind_of: String, required: true +attribute :priority, kind_of: Integer, default: 99 +attribute :severity, kind_of: String +attribute :facility, kind_of: String +attribute :cookbook, kind_of: String, default: 'rsyslog' +attribute :source, kind_of: String, default: 'file-input.conf.erb' diff --git a/cookbooks/rsyslog/templates/default/49-relp.conf.erb b/cookbooks/rsyslog/templates/default/49-relp.conf.erb index f96d923..22167bf 100644 --- a/cookbooks/rsyslog/templates/default/49-relp.conf.erb +++ b/cookbooks/rsyslog/templates/default/49-relp.conf.erb @@ -6,5 +6,5 @@ $ActionResumeRetryCount -1 # infinite retries on insert failure $ActionQueueSaveOnShutdown on # save in-memory data if rsyslog shuts down <% @servers.each do |server| -%> -*.* :omrelp:<%= "#{server}:#{node['rsyslog']['relp_port']}" %><%= node['rsyslog']['default_remote_template'] ? ';' + node['rsyslog']['default_remote_template'] : nil %> +<%= node['rsyslog']['logs_to_forward'] %> :omrelp:<%= "#{server}:#{node['rsyslog']['relp_port']}" %><%= node['rsyslog']['default_remote_template'] ? ';' + node['rsyslog']['default_remote_template'] : nil %> <% end -%> diff --git a/cookbooks/rsyslog/templates/default/49-remote.conf.erb b/cookbooks/rsyslog/templates/default/49-remote.conf.erb index 154a16f..dc3bcb5 100644 --- a/cookbooks/rsyslog/templates/default/49-remote.conf.erb +++ b/cookbooks/rsyslog/templates/default/49-remote.conf.erb @@ -19,10 +19,12 @@ $ActionSendStreamDriverAuthMode <%= node['rsyslog']['tls_auth_mode'] %> <% end -%> <% @servers.each do |server| -%> -<% case node['rsyslog']['protocol'] -%> -<% when "tcp" -%> -<%= node['rsyslog']['logs_to_forward'] %> @@<%= server %>:<%= node['rsyslog']['port'] %><%= node["rsyslog"]["default_remote_template"] ? ';' + node["rsyslog"]["default_remote_template"] : nil %> -<% when "udp" -%> -<%= node['rsyslog']['logs_to_forward'] %> @<%= server %>:<%= node['rsyslog']['port'] %><%= node["rsyslog"]["default_remote_template"] ? ';' + node["rsyslog"]["default_remote_template"] : nil %> +<% case server['protocol'] -%> +<% when "tcp" -%> +<%= server['logs'] ? server['logs'] : node['rsyslog']['logs_to_forward'] %> @@<%= server['server'] %>:<%= server['port'] ? server['port'] : node['rsyslog']['port'] %><%= server['remote_template'] ? ';' + server['remote_template'] : nil %> +<% when "udp" -%> +<%= server['logs'] ? server['logs'] : node['rsyslog']['logs_to_forward'] %> @<%= server['server'] %>:<%= server['port'] ? server['port'] : node['rsyslog']['port'] %><%= server['remote_template'] ? ';' + server['remote_template'] : nil %> +<% else -%> +<%= server['logs'] ? server['logs'] : node['rsyslog']['logs_to_forward'] %><%= node['rsyslog']['protocol'] == "tcp" ? " @@" : " @" %><%= server['server'] %>:<%= server['port'] ? server['port'] : node['rsyslog']['port'] %><%= server['remote_template'] ? ';' + server['remote_template'] : nil %> <% end -%> <% end -%> diff --git a/cookbooks/rsyslog/templates/default/rsyslog.conf.erb b/cookbooks/rsyslog/templates/default/rsyslog.conf.erb index 7a0226f..ca64812 100644 --- a/cookbooks/rsyslog/templates/default/rsyslog.conf.erb +++ b/cookbooks/rsyslog/templates/default/rsyslog.conf.erb @@ -1,6 +1,11 @@ -# rsyslog configuration file - Generated by Chef -# For more information see /usr/share/doc/rsyslog-*/rsyslog_conf.html -# If you experience problems, see http://www.rsyslog.com/doc/troubleshoot.html +# Config generated by Chef - manual edits will be overwritten +# +# /etc/rsyslog.conf Configuration file for rsyslog. +# +# For more information see +# /usr/share/doc/rsyslog-doc/html/rsyslog_conf.html +# +# Default logging rules can be found in /etc/rsyslog.d/50-default.conf # # Set max message size # @@ -36,13 +41,14 @@ $InputTCPServerStreamDriverAuthMode <%= node['rsyslog']['tls_auth_mode'] || 'ano $InputTCPServerRun <%= node['rsyslog']['port'] %> # Provide <%= node['rsyslog']['protocol'].upcase %> log reception <% else -%> -<% case node['rsyslog']['protocol'] -%> -<% when "tcp" -%> -$ModLoad imtcp -$InputTCPServerRun <%= node['rsyslog']['port'] %> -<% when "udp" -%> -$ModLoad imudp -$UDPServerRun <%= node['rsyslog']['port'] %> +<% if node['rsyslog']['protocol'] =~ /tcp/ %> + $ModLoad imtcp + $InputTCPServerRun <%= node['rsyslog']['port'] %> +<% end -%> +<% if node['rsyslog']['protocol'] =~ /udp/ %> + $ModLoad imudp + $UDPServerAddress <%= node['rsyslog']['bind'] %> + $UDPServerRun <%= node['rsyslog']['port'] %> <% end -%> <% end -%> <% end -%> @@ -52,13 +58,13 @@ $UDPServerRun <%= node['rsyslog']['port'] %> ########################### <% if node["rsyslog"]["default_file_template"] -%> -# +# # Default log format template -# +# $ActionFileDefaultTemplate <%= node["rsyslog"]["default_file_template"] %> <% elsif !node["rsyslog"]["high_precision_timestamps"] -%> # -# Use default timestamp format. +# Use traditional timestamp format. # To enable high precision timestamps, comment out the following line. # $ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat @@ -97,10 +103,15 @@ $SystemLogRateLimitInterval <%= node['rsyslog']['rate_limit_interval'] %> # $SystemLogRateLimitBurst <%= node['rsyslog']['rate_limit_burst'] %> <% end %> + +# +# Set other directives +# +<% node['rsyslog']['additional_directives'].each_pair do |k,v| %> +$<%= k %> <%= v %> +<% end %> + # # Include all config files in <%= node['rsyslog']['config_prefix'] %>/rsyslog.d/ # $IncludeConfig <%= node['rsyslog']['config_prefix'] %>/rsyslog.d/*.conf -<% node['rsyslog']['additional_directives'].each_pair do |k,v| %> -$<%= k %> <%= v %> -<% end %> diff --git a/cookbooks/runit/CHANGELOG.md b/cookbooks/runit/CHANGELOG.md index c10a8b0..782f47d 100644 --- a/cookbooks/runit/CHANGELOG.md +++ b/cookbooks/runit/CHANGELOG.md @@ -2,6 +2,46 @@ runit Cookbook CHANGELOG ======================== This file is used to list changes made in each version of the runit cookbook. +UNRELEASED +---------- + +v1.7.6 +---------- +* Ensure `supervise/ok` named pipe is properly removed when disabling a service, so that it can be enabled again (#166, #167, #172) +* Restore `restart_on_update` functionality originally added in [#20](https://github.com/hw-cookbooks/runit/pull/20) and lost in the 1.7.0 refactor. +* Update test cookbooks to fix broken tests revealed by restoring `restart_on_update` functionality. Now using socat instead of netcat. + +v1.7.4 (2015-10-13) +---------- +* Ensure the service directory exists so that we will succeed when enabling services (#153) +* Fix regression where env directory contents were being deleted when the `env` attribute is empty. (#144, #158) +* Add `log_dir` attribute, used only when `default_logger` is true. (#135) +* Ensure svlogd configuration is linked into correct path (#83, #135) +* Update README and CHANGELOG for v1.7.0 to warn against known regressions (#144, #157) +* Avoid mutating resource options for Chef 12 compatability (#147, #150, #156) +* Fix regression regarding waiting for the service socket before running (#138, #142) +* Reimplement idempotence checks for `runit_service` resources (#137, #141) +* Enhance ChefSpec unit test coverage with specs that step into the LWRP (#139) +* Deduplicate ServerSpec integration test coverage using example groups (#140) + +v1.7.2 (2015-06-19) +---------- +* Re-add missing runit_service actions start, stop, reload and status + +v1.7.0 (2015-06-18) +---------- + +**NOTE**: With the benefit of hindsight we can say that the changes contained in +this release merit a major version number change. Please be sure to test this +new version for compatibility with your systems before upgrading to version 1.7. + +* Modernize runit_service provider by rewriting pure Ruby as LWRP (#107) +* Modernize integration tests by rewriting Minitest suites as ServerSpec (#107) +* Fix regression in support for alternate sv binary on debian platforms (#92, #123) +* Fix regression in default logger's config location (#117) +* Tighten permissions on environment variable config files from 0644 to 0640 (#125) +* Add `start_down` and `delete_downfile` attributes to support configuring services with default state of 'down' (#105) + v1.6.0 (2015-04-06) -------------------- * Fedora 21 support diff --git a/cookbooks/runit/README.md b/cookbooks/runit/README.md index 9f1fbb8..1322977 100644 --- a/cookbooks/runit/README.md +++ b/cookbooks/runit/README.md @@ -8,15 +8,23 @@ For more information about runit: - http://smarden.org/runit/ +#### A note regarding versions 1.7.0 and 1.7.2 + +With the benefit of hindsight we can say that the changes contained version 1.7.0 merited a major version number change, and that version 1.7.2 contains some still unresolved regressions compared to 1.6.0. Please be sure to test this new version for compatibility with your systems before upgrading to version 1.7. + +See [issue #144](https://github.com/hw-cookbooks/runit/issues/144) for some notes on how these versions behaved unexpectedly in one user's environment. Requirements ------------ -### Platforms +#### Platforms - Debian/Ubuntu - Gentoo - RHEL -### Cookbooks +#### Chef +- Chef 11+ + +#### Cookbooks - packagecloud (for RHEL) Attributes @@ -109,13 +117,18 @@ Many of these parameters are only used in the `:enable` action. compatibility with legacy runit service definition. Default is an empty hash. - **env** - A hash of environment variables with their values as content - used in the service's `env` directory. Default is an empty hash. + used in the service's `env` directory. Default is an empty hash. When + this hash is non-empty, the contents of the runit service's `env` + directory will be managed by Chef in order to conform to the declared + state. - **log** - Whether to start the service's logger with svlogd, requires a template `sv-service_name-log-run.erb` to configure the log's run script. Default is true. - **default_logger** - Whether a default `log/run` script should be set up. If true, the default content of the run script will use `svlogd` to write logs to `/var/log/service_name`. Default is false. +- **log_dir** - The directory where the `svlogd` log service will run. + Used when `default_logger` is `true`. Default is `/var/log/service_name` - **log_size** - The maximum size a log file can grow to before it is automatically rotated. See svlogd(8) for the default value. - **log_num** - The maximum number of log files that will be retained @@ -168,6 +181,10 @@ Many of these parameters are only used in the `:enable` action. - **restart_on_update** - Whether the service should be restarted when the run script is updated. Defaults to `true`. Set to `false` if the service shouldn't be restarted when the run script is updated. +- **start_down** - Set the default state of the runit service to 'down' by creating + `/down` file. Defaults to `false`. Services using `start_down` + will not be notified to restart when their run script is updated. +- **delete_downfile** - Delete previously created `/down` file Unlike previous versions of the cookbook using the `runit_service` definition, the `runit_service` resource can be notified. See __Usage__ examples below. @@ -185,7 +202,7 @@ exec svlogd -tt /var/log/service_name ``` ### Examples -These are example use cases of the `runit_service` resource described above. There are others in the `runit_test` cookbook that is included in the [git repository](https://github.com/chef-cookbooks/runit). +These are example use cases of the `runit_service` resource described above. There are others in the `runit_test` cookbook that is included in the [git repository](https://github.com/hw-cookbooks/runit). **Default Example** @@ -350,8 +367,8 @@ runit_service "memcached" do options({ :memory => node[:memcached][:memory], :port => node[:memcached][:port], - :user => node[:memcached][:user]}.merge(params) - }) + :user => node[:memcached][:user] + }.merge(params)) end ``` @@ -396,16 +413,17 @@ end **More Examples** -For more examples, see the `runit_test` cookbook's `service` recipe in the [git repository](https://github.com/chef-cookbooks/runit). +For more examples, see the `runit_test` cookbook's `service` recipe in the [git repository](https://github.com/hw-cookbooks/runit). License & Authors ----------------- - Author:: Adam Jacob - Author:: Joshua Timberman +- Author:: Sean OMeara ```text -Copyright:: 2008-2013, Chef Software, Inc +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. diff --git a/cookbooks/runit/libraries/helpers.rb b/cookbooks/runit/libraries/helpers.rb index fc47d66..0a40f58 100644 --- a/cookbooks/runit/libraries/helpers.rb +++ b/cookbooks/runit/libraries/helpers.rb @@ -2,8 +2,9 @@ # Cookbook:: runit # Libraries:: helpers # -# Author: Joshua Timberman -# Copyright (c) 2014, Chef Software, Inc. +# Author: Joshua Timberman +# Author: Sean OMeara +# 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. @@ -18,28 +19,180 @@ # limitations under the License. # -require 'chef/mixin/shell_out' -include Chef::Mixin::ShellOut -module Runit +module RunitCookbook module Helpers - def runit_installed? - return true if runit_rpm_installed? || (runit_executable? && runit_sv_works?) + # include Chef::Mixin::ShellOut if it is not already included in the calling class + def self.included(klass) + unless klass.ancestors.include?(Chef::Mixin::ShellOut) + klass.class_eval { include Chef::Mixin::ShellOut } + end end - def runit_executable? - ::File.executable?(node['runit']['executable']) + # Default settings for resource properties. + def parsed_sv_bin + return new_resource.sv_bin if new_resource.sv_bin + '/usr/bin/sv' + end + + def parsed_sv_dir + return new_resource.sv_dir if new_resource.sv_dir + '/etc/sv' + end + + def parsed_service_dir + return new_resource.service_dir if new_resource.service_dir + '/etc/service' + end + + def parsed_lsb_init_dir + return new_resource.lsb_init_dir if new_resource.lsb_init_dir + '/etc/init.d' + end + + # misc helper functions + def inside_docker? + results = `cat /proc/1/cgroup`.strip.split("\n") + results.any? { |val| /docker/ =~ val } + end + + def down_file + "#{sv_dir_name}/down" + end + + def env_dir + "#{sv_dir_name}/env" + end + + def extra_env_files? + files = [] + Dir.glob("#{sv_dir_name}/env/*").each do |f| + files << File.basename(f) + end + return true if files.sort != new_resource.env.keys.sort + false + end + + def zap_extra_env_files + Dir.glob("#{sv_dir_name}/env/*").each do |f| + unless new_resource.env.key?(File.basename(f)) + File.unlink(f) + Chef::Log.info("removing file #{f}") + end + end + end + + def wait_for_service + unless inside_docker? + sleep 1 until ::FileTest.pipe?("#{service_dir_name}/supervise/ok") + + if new_resource.log + sleep 1 until ::FileTest.pipe?("#{service_dir_name}/log/supervise/ok") + end + end end def runit_sv_works? - sv = shell_out("#{node['runit']['sv_bin']} --help") + sv = shell_out("#{sv_bin} --help") sv.exitstatus == 100 && sv.stderr =~ /usage: sv .* command service/ end - def runit_rpm_installed? - shell_out('rpm -qa | grep -q "^runit"').exitstatus == 0 + def runit_send_signal(signal, friendly_name = nil) + friendly_name ||= signal + converge_by("send #{friendly_name} to #{new_resource}") do + shell_out!("#{sv_bin} #{sv_args}#{signal} #{service_dir_name}") + Chef::Log.info("#{new_resource} sent #{friendly_name}") + end + end + + def running? + cmd = shell_out("#{sv_bin} #{sv_args}status #{service_dir_name}") + (cmd.stdout =~ /^run:/ && cmd.exitstatus == 0) + end + + def log_running? + cmd = shell_out("#{sv_bin} #{sv_args}status #{service_dir_name}/log") + (cmd.stdout =~ /^run:/ && cmd.exitstatus == 0) + end + + def enabled? + ::File.exist?("#{service_dir_name}/run") + end + + def log_service_name + "#{new_resource.service_name}/log" + end + + def sv_dir_name + "#{parsed_sv_dir}/#{new_resource.service_name}" + end + + def sv_args + sv_args = '' + sv_args += "-w '#{new_resource.sv_timeout}' " unless new_resource.sv_timeout.nil? + sv_args += '-v ' if new_resource.sv_verbose + sv_args + end + + def sv_bin + parsed_sv_bin + end + + def service_dir_name + "#{new_resource.service_dir}/#{new_resource.service_name}" + end + + def log_dir_name + "#{new_resource.service_dir}/#{new_resource.service_name}/log" + end + + def template_cookbook + new_resource.cookbook.nil? ? new_resource.cookbook_name.to_s : new_resource.cookbook + end + + def default_logger_content + <<-EOS +#!/bin/sh +exec svlogd -tt #{new_resource.log_dir} + EOS + end + + def disable_service + shell_out("#{new_resource.sv_bin} #{sv_args}down #{service_dir_name}") + FileUtils.rm(service_dir_name) + + # per the documentation, a service should be removed from supervision + # within 5 seconds of removing the service dir symlink, so we'll sleep for 6. + # otherwise, runit recreates the 'ok' named pipe too quickly + sleep(6) + # runit will recreate the supervise directory and + # pipes when the service is reenabled + FileUtils.rm("#{sv_dir_name}/supervise/ok") + end + + def start_service + shell_out!("#{new_resource.sv_bin} #{sv_args}start #{service_dir_name}") + end + + def stop_service + shell_out!("#{new_resource.sv_bin} #{sv_args}stop #{service_dir_name}") + end + + def restart_service + shell_out!("#{new_resource.sv_bin} #{sv_args}restart #{service_dir_name}") + end + + def restart_log_service + shell_out!("#{new_resource.sv_bin} #{sv_args}restart #{service_dir_name}/log") + end + + def reload_service + shell_out!("#{new_resource.sv_bin} #{sv_args}force-reload #{service_dir_name}") + end + + def reload_log_service + if log_running? + shell_out!("#{new_resource.sv_bin} #{sv_args}force-reload #{service_dir_name}/log") + end end end end - -Chef::Recipe.send(:include, Runit::Helpers) -Chef::Resource.send(:include, Runit::Helpers) diff --git a/cookbooks/runit/libraries/matchers.rb b/cookbooks/runit/libraries/matchers.rb index c7c6d29..760156e 100644 --- a/cookbooks/runit/libraries/matchers.rb +++ b/cookbooks/runit/libraries/matchers.rb @@ -1,5 +1,7 @@ if defined?(ChefSpec) + ChefSpec.define_matcher(:runit_service) + def start_runit_service(service) ChefSpec::Matchers::ResourceMatcher.new(:runit_service, :start, service) end diff --git a/cookbooks/runit/libraries/provider_runit_service.rb b/cookbooks/runit/libraries/provider_runit_service.rb index 3fefe0f..ab59470 100644 --- a/cookbooks/runit/libraries/provider_runit_service.rb +++ b/cookbooks/runit/libraries/provider_runit_service.rb @@ -2,8 +2,9 @@ # Cookbook Name:: runit # Provider:: service # -# Copyright 2011, Joshua Timberman -# Copyright 2011, Chef Software, Inc. +# Author:: Joshua Timberman +# Author:: Sean OMeara +# 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. @@ -18,533 +19,330 @@ # limitations under the License. # -require 'chef/provider/service' -require 'chef/provider/link' -require 'chef/resource/link' -require 'chef/provider/directory' -require 'chef/resource/directory' -require 'chef/provider/template' -require 'chef/resource/template' -require 'chef/provider/file' -require 'chef/resource/file' -require 'chef/mixin/shell_out' -require 'chef/mixin/language' - class Chef class Provider - class Service - class Runit < Chef::Provider::Service - # refactor this whole thing into a Chef11 LWRP - include Chef::Mixin::ShellOut + class RunitService < Chef::Provider::LWRPBase + unless defined?(VALID_SIGNALS) + # Mapping of valid signals with optional friendly name + VALID_SIGNALS = Mash.new( + :down => nil, + :hup => nil, + :int => nil, + :term => nil, + :kill => nil, + :quit => nil, + :up => nil, + :once => nil, + :cont => nil, + 1 => :usr1, + 2 => :usr2 + ) + end - def initialize(*args) - super - new_resource.supports[:status] = true + use_inline_resources if defined?(use_inline_resources) + + def whyrun_supported? + true + end + + # Mix in helpers from libraries/helpers.rb + include RunitCookbook::Helpers + + # actions + action :create do + ruby_block 'restart_service' do + block do + action_enable + restart_service + end + action :nothing + only_if { new_resource.restart_on_update && !new_resource.start_down } end - def load_current_resource - @current_resource = Chef::Resource::RunitService.new(new_resource.name) - current_resource.service_name(new_resource.service_name) + ruby_block 'restart_log_service' do + block do + action_enable + restart_log_service + end + action :nothing + only_if { new_resource.restart_on_update && !new_resource.start_down } + end - Chef::Log.debug("Checking status of service #{new_resource.service_name}") + # sv_templates + if new_resource.sv_templates - # verify Runit was installed properly - unless ::File.exist?(new_resource.sv_bin) && ::File.executable?(new_resource.sv_bin) - no_runit_message = "Could not locate main runit sv_bin at \"#{new_resource.sv_bin}\". " - no_runit_message << "Did you remember to install runit before declaring a \"runit_service\" resource? " - no_runit_message << "\n\nTry adding the following to the top of your recipe:\n\ninclude_recipe \"runit\"" - fail no_runit_message + directory sv_dir_name do + owner new_resource.owner + group new_resource.group + mode '0755' + recursive true + action :create end - current_resource.running(running?) - current_resource.enabled(enabled?) - current_resource.env(get_current_env) - current_resource - end - - # - # Chef::Provider::Service overrides - # - - def action_create - configure_service # Do this every run, even if service is already enabled and running - Chef::Log.info("#{new_resource} configured") - end - - def action_enable - configure_service # Do this every run, even if service is already enabled and running - Chef::Log.info("#{new_resource} configured") - if current_resource.enabled - Chef::Log.debug("#{new_resource} already enabled - nothing to do") - else - enable_service - Chef::Log.info("#{new_resource} enabled") + template "#{sv_dir_name}/run" do + owner new_resource.owner + group new_resource.group + source "sv-#{new_resource.run_template_name}-run.erb" + cookbook template_cookbook + mode '0755' + variables(options: new_resource.options) + action :create + notifies :run, 'ruby_block[restart_service]', :delayed end - load_new_resource_state - new_resource.enabled(true) - restart_service if new_resource.restart_on_update && run_script.updated_by_last_action? - restart_log_service if new_resource.restart_on_update && log_run_script.updated_by_last_action? - restart_log_service if new_resource.restart_on_update && log_config_file.updated_by_last_action? - end - def configure_service - if new_resource.sv_templates - Chef::Log.debug("Creating sv_dir for #{new_resource.service_name}") - do_action(sv_dir, :create) - Chef::Log.debug("Creating run_script for #{new_resource.service_name}") - do_action(run_script, :create) - - if new_resource.log - Chef::Log.debug("Setting up svlog for #{new_resource.service_name}") - do_action(log_dir, :create) - do_action(log_main_dir, :create) - do_action(default_log_dir, :create) if new_resource.default_logger - do_action(log_run_script, :create) - do_action(log_config_file, :create) - else - Chef::Log.debug("log not specified for #{new_resource.service_name}, continuing") + # log stuff + if new_resource.log + directory "#{sv_dir_name}/log" do + owner new_resource.owner + group new_resource.group + recursive true + action :create end - unless new_resource.env.empty? - Chef::Log.debug("Setting up environment files for #{new_resource.service_name}") - do_action(env_dir, :create) - env_files.each do |file| - file.action.each { |action| do_action(file, action) } + directory "#{sv_dir_name}/log/main" do + owner new_resource.owner + group new_resource.group + mode '0755' + recursive true + action :create + end + + directory new_resource.log_dir do + owner new_resource.owner + group new_resource.group + mode '00755' + recursive true + action :create + end + + template "#{sv_dir_name}/log/config" do + owner new_resource.owner + group new_resource.group + mode '00644' + cookbook 'runit' + source 'log-config.erb' + variables(config: new_resource) + notifies :run, 'ruby_block[restart_log_service]', :delayed + action :create + end + + link "#{new_resource.log_dir}/config" do + to "#{sv_dir_name}/log/config" + end + + if new_resource.default_logger + file "#{sv_dir_name}/log/run" do + content default_logger_content + owner new_resource.owner + group new_resource.group + mode '00755' + action :create + notifies :run, 'ruby_block[restart_log_service]', :delayed end else - Chef::Log.debug("Environment not specified for #{new_resource.service_name}, continuing") - end - - if new_resource.check - Chef::Log.debug("Creating check script for #{new_resource.service_name}") - do_action(check_script, :create) - else - Chef::Log.debug("Check script not specified for #{new_resource.service_name}, continuing") - end - - if new_resource.finish - Chef::Log.debug("Creating finish script for #{new_resource.service_name}") - do_action(finish_script, :create) - else - Chef::Log.debug("Finish script not specified for #{new_resource.service_name}, continuing") - end - - unless new_resource.control.empty? - Chef::Log.debug("Creating control signal scripts for #{new_resource.service_name}") - do_action(control_dir, :create) - control_signal_files.each { |file| do_action(file, :create) } - else - Chef::Log.debug("Control signals not specified for #{new_resource.service_name}, continuing") - end - end - - Chef::Log.debug("Creating lsb_init compatible interface #{new_resource.service_name}") - do_action(lsb_init, :create) - end - - def enable_service - Chef::Log.debug("Creating symlink in service_dir for #{new_resource.service_name}") - do_action(service_link, :create) - - unless inside_docker? - Chef::Log.debug("waiting until named pipe #{service_dir_name}/supervise/ok exists.") - until ::FileTest.pipe?("#{service_dir_name}/supervise/ok") - sleep 1 - Chef::Log.debug('.') - end - - if new_resource.log - Chef::Log.debug("waiting until named pipe #{service_dir_name}/log/supervise/ok exists.") - until ::FileTest.pipe?("#{service_dir_name}/log/supervise/ok") - sleep 1 - Chef::Log.debug('.') + template "#{sv_dir_name}/log/run" do + owner new_resource.owner + group new_resource.group + mode '00755' + source "sv-#{new_resource.log_template_name}-log-run.erb" + cookbook template_cookbook + variables(options: new_resource.options) + action :create + notifies :run, 'ruby_block[restart_log_service]', :delayed end end - else - Chef::Log.debug("skipping */supervise/ok check inside docker") + end - end - def disable_service - shell_out("#{new_resource.sv_bin} #{sv_args}down #{service_dir_name}") - Chef::Log.debug("#{new_resource} down") - FileUtils.rm(service_dir_name) - Chef::Log.debug("#{new_resource} service symlink removed") - end + # environment stuff + directory "#{sv_dir_name}/env" do + owner new_resource.owner + group new_resource.group + mode '00755' + action :create + end - def start_service - shell_out!("#{new_resource.sv_bin} #{sv_args}start #{service_dir_name}") - end - - def stop_service - shell_out!("#{new_resource.sv_bin} #{sv_args}stop #{service_dir_name}") - end - - def restart_service - shell_out!("#{new_resource.sv_bin} #{sv_args}restart #{service_dir_name}") - end - - def restart_log_service - shell_out!("#{new_resource.sv_bin} #{sv_args}restart #{service_dir_name}/log") - end - - def reload_service - shell_out!("#{new_resource.sv_bin} #{sv_args}force-reload #{service_dir_name}") - end - - def reload_log_service - shell_out!("#{new_resource.sv_bin} #{sv_args}force-reload #{service_dir_name}/log") - end - - # - # Addtional Runit-only actions - # - - # only take action if the service is running - [:down, :hup, :int, :term, :kill, :quit].each do |signal| - define_method "action_#{signal}".to_sym do - if current_resource.running - runit_send_signal(signal) - else - Chef::Log.debug("#{new_resource} not running - nothing to do") + new_resource.env.map do |var, value| + file "#{sv_dir_name}/env/#{var}" do + owner new_resource.owner + group new_resource.group + content value + mode 00640 + action :create end end - end - # only take action if service is *not* running - [:up, :once, :cont].each do |signal| - define_method "action_#{signal}".to_sym do - if current_resource.running - Chef::Log.debug("#{new_resource} already running - nothing to do") - else - runit_send_signal(signal) + ruby_block "zap extra env files for #{new_resource.name} service" do + block { zap_extra_env_files } + only_if { extra_env_files? } + not_if { new_resource.env.empty? } + action :run + end + + if new_resource.check + template "#{sv_dir_name}/check" do + owner new_resource.owner + group new_resource.group + mode '00755' + cookbook template_cookbook + source "sv-#{new_resource.check_script_template_name}-check.erb" + variables(options: new_resource.options) + action :create end end - end - def action_usr1 - runit_send_signal(1, :usr1) - end - - def action_usr2 - runit_send_signal(2, :usr2) - end - - private - - def runit_send_signal(signal, friendly_name = nil) - friendly_name ||= signal - converge_by("send #{friendly_name} to #{new_resource}") do - shell_out!("#{new_resource.sv_bin} #{sv_args}#{signal} #{service_dir_name}") - Chef::Log.info("#{new_resource} sent #{friendly_name}") + if new_resource.finish + template "#{sv_dir_name}/finish" do + owner new_resource.owner + group new_resource.group + mode '00755' + source "sv-#{new_resource.finish_script_template_name}-finish.erb" + cookbook template_cookbook + variables(options: new_resource.options) if new_resource.options.respond_to?(:has_key?) + action :create + end end - end - def running? - cmd = shell_out("#{new_resource.sv_bin} #{sv_args}status #{service_dir_name}") - (cmd.stdout =~ /^run:/ && cmd.exitstatus == 0) - end + directory "#{sv_dir_name}/control" do + owner new_resource.owner + group new_resource.group + mode '00755' + action :create + end - def log_running? - cmd = shell_out("#{new_resource.sv_bin} #{sv_args}status #{service_dir_name}/log") - (cmd.stdout =~ /^run:/ && cmd.exitstatus == 0) - end - - def enabled? - ::File.exists?(::File.join(service_dir_name, 'run')) - end - - def log_service_name - ::File.join(new_resource.service_name, 'log') - end - - def sv_dir_name - ::File.join(new_resource.sv_dir, new_resource.service_name) - end - - def sv_args - sv_args = '' - sv_args += "-w '#{new_resource.sv_timeout}' " unless new_resource.sv_timeout.nil? - sv_args += '-v ' if new_resource.sv_verbose - sv_args - end - - def service_dir_name - ::File.join(new_resource.service_dir, new_resource.service_name) - end - - def log_dir_name - ::File.join(new_resource.service_dir, new_resource.service_name, log) - end - - def template_cookbook - new_resource.cookbook.nil? ? new_resource.cookbook_name.to_s : new_resource.cookbook - end - - def default_logger_content - "#!/bin/sh -exec svlogd -tt /var/log/#{new_resource.service_name}" - end - - # - # Helper Resources - # - def do_action(resource, action) - resource.run_action(action) - new_resource.updated_by_last_action(true) if resource.updated_by_last_action? - end - - def sv_dir - @sv_dir ||= - begin - d = Chef::Resource::Directory.new(sv_dir_name, run_context) - d.recursive(true) - d.owner(new_resource.owner) - d.group(new_resource.group) - d.mode(00755) - d + new_resource.control.map do |signal| + template "#{sv_dir_name}/control/#{signal}" do + owner new_resource.owner + group new_resource.group + mode '0755' + source "sv-#{new_resource.control_template_names[signal]}-#{signal}.erb" + cookbook template_cookbook + variables(options: new_resource.options) + action :create end - end + end - def run_script - @run_script ||= - begin - t = Chef::Resource::Template.new(::File.join(sv_dir_name, 'run'), run_context) - t.owner(new_resource.owner) - t.group(new_resource.group) - t.source("sv-#{new_resource.run_template_name}-run.erb") - t.cookbook(template_cookbook) - t.mode(00755) - t.variables(:options => new_resource.options) if new_resource.options.respond_to?(:has_key?) - t + # lsb_init + if node['platform'] == 'debian' + ruby_block "unlink #{parsed_lsb_init_dir}/#{new_resource.service_name}" do + block { ::File.unlink("#{parsed_lsb_init_dir}/#{new_resource.service_name}") } + only_if { ::File.symlink?("#{parsed_lsb_init_dir}/#{new_resource.service_name}") } end - end - def log_dir - @log_dir ||= - begin - d = Chef::Resource::Directory.new(::File.join(sv_dir_name, 'log'), run_context) - d.recursive(true) - d.owner(new_resource.owner) - d.group(new_resource.group) - d.mode(00755) - d - end - end - - def log_main_dir - @log_main_dir ||= - begin - d = Chef::Resource::Directory.new(::File.join(sv_dir_name, 'log', 'main'), run_context) - d.recursive(true) - d.owner(new_resource.owner) - d.group(new_resource.group) - d.mode(00755) - d - end - end - - def default_log_dir - @default_log_dir ||= - begin - d = Chef::Resource::Directory.new(::File.join("/var/log/#{new_resource.service_name}"), run_context) - d.recursive(true) - d.owner(new_resource.owner) - d.group(new_resource.group) - d.mode(00755) - d - end - end - - def log_run_script - @log_run_script ||= - begin - if new_resource.default_logger - f = Chef::Resource::File.new( - ::File.join(sv_dir_name, 'log', 'run'), - run_context - ) - f.content(default_logger_content) - f.owner(new_resource.owner) - f.group(new_resource.group) - f.mode(00755) - f - else - t = Chef::Resource::Template.new( - ::File.join(sv_dir_name, 'log', 'run'), - run_context - ) - t.owner(new_resource.owner) - t.group(new_resource.group) - t.mode(00755) - t.source("sv-#{new_resource.log_template_name}-log-run.erb") - t.cookbook(template_cookbook) - t.variables(:options => new_resource.options) if new_resource.options.respond_to?(:has_key?) - t - end - end - end - - def log_config_file - @log_config_file ||= - begin - t = Chef::Resource::Template.new(::File.join(sv_dir_name, 'log', 'config'), run_context) - t.owner(new_resource.owner) - t.group(new_resource.group) - t.mode(00644) - t.cookbook('runit') - t.source('log-config.erb') - t.variables( - :size => new_resource.log_size, - :num => new_resource.log_num, - :min => new_resource.log_min, - :timeout => new_resource.log_timeout, - :processor => new_resource.log_processor, - :socket => new_resource.log_socket, - :prefix => new_resource.log_prefix, - :append => new_resource.log_config_append + template "#{parsed_lsb_init_dir}/#{new_resource.service_name}" do + owner 'root' + group 'root' + mode '00755' + cookbook 'runit' + source 'init.d.erb' + variables( + name: new_resource.service_name, + sv_bin: new_resource.sv_bin, + init_dir: ::File.join(parsed_lsb_init_dir, '') ) - t + action :create end - end - - def env_dir - @env_dir ||= - begin - d = Chef::Resource::Directory.new(::File.join(sv_dir_name, 'env'), run_context) - d.owner(new_resource.owner) - d.group(new_resource.group) - d.mode(00755) - d + else + link "#{parsed_lsb_init_dir}/#{new_resource.service_name}" do + to sv_bin + action :create end - end - - def env_files - @env_files ||= - begin - create_files = new_resource.env.map do |var, value| - f = Chef::Resource::File.new(::File.join(sv_dir_name, 'env', var), run_context) - f.owner(new_resource.owner) - f.group(new_resource.group) - f.content(value) - f.action(:create) - f - end - extra_env = current_resource.env.reject { |k,_| new_resource.env.key?(k) } - delete_files = extra_env.map do |k,_| - f = Chef::Resource::File.new(::File.join(sv_dir_name, 'env', k), run_context) - f.action(:delete) - f - end - create_files + delete_files - end - end - - def get_current_env - env_dir = ::File.join(sv_dir_name, 'env') - return {} unless ::File.directory? env_dir - files = ::Dir.glob(::File.join(env_dir,'*')) - env = files.reduce({}) do |c,o| - contents = ::IO.read(o).rstrip - c.merge!(::File.basename(o) => contents) end - env + + # Create/Delete service down file + # To prevent unexpected behavior, require users to explicitly set + # delete_downfile to remove any down file that may already exist + df_action = :nothing + if new_resource.start_down + df_action = :create + elsif new_resource.delete_downfile + df_action = :delete + end + + file down_file do + mode 00644 + backup false + content '# File created and managed by chef!' + action df_action + end + end + end + + action :disable do + ruby_block "disable #{new_resource.service_name}" do + block { disable_service } + only_if { enabled? } + end + end + + action :enable do + # FIXME: remove action_create in next major version + action_create + + directory new_resource.service_dir + + link "#{service_dir_name}" do + to sv_dir_name + action :create end - def check_script - @check_script ||= - begin - t = Chef::Resource::Template.new(::File.join(sv_dir_name, 'check'), run_context) - t.owner(new_resource.owner) - t.group(new_resource.group) - t.source("sv-#{new_resource.check_script_template_name}-check.erb") - t.cookbook(template_cookbook) - t.mode(00755) - t.variables(:options => new_resource.options) if new_resource.options.respond_to?(:has_key?) - t - end + ruby_block "wait for #{new_resource.service_name} service socket" do + block do + wait_for_service + end + action :run end + end - def finish_script - @finish_script ||= - begin - t = Chef::Resource::Template.new(::File.join(sv_dir_name, 'finish'), run_context) - t.owner(new_resource.owner) - t.group(new_resource.group) - t.mode(00755) - t.source("sv-#{new_resource.finish_script_template_name}-finish.erb") - t.cookbook(template_cookbook) - t.variables(:options => new_resource.options) if new_resource.options.respond_to?(:has_key?) - t - end + # signals + VALID_SIGNALS.each do |signal, signal_name| + action(signal_name || signal) do + if running? + Chef::Log.info "#{new_resource} signalled (#{(signal_name || signal).to_s.upcase})" + runit_send_signal(signal, signal_name) + else + Chef::Log.debug "#{new_resource} not running - nothing to do" + end end + end - def control_dir - @control_dir ||= - begin - d = Chef::Resource::Directory.new(::File.join(sv_dir_name, 'control'), run_context) - d.owner(new_resource.owner) - d.group(new_resource.group) - d.mode(00755) - d - end - end + action :nothing do + end - def control_signal_files - @control_signal_files ||= - begin - new_resource.control.map do |signal| - t = Chef::Resource::Template.new( - ::File.join(sv_dir_name, 'control', signal), - run_context - ) - t.owner(new_resource.owner) - t.group(new_resource.group) - t.mode(00755) - t.source("sv-#{new_resource.control_template_names[signal]}-#{signal}.erb") - t.cookbook(template_cookbook) - t.variables(:options => new_resource.options) if new_resource.options.respond_to?(:has_key?) - t - end - end - end + action :restart do + restart_service + end - def lsb_init - @lsb_init ||= - begin - initfile = ::File.join(new_resource.lsb_init_dir, new_resource.service_name) - if node['platform'] == 'debian' - ::File.unlink(initfile) if ::File.symlink?(initfile) - t = Chef::Resource::Template.new(initfile, run_context) - t.owner('root') - t.group('root') - t.mode(00755) - t.cookbook('runit') - t.source('init.d.erb') - t.variables(:name => new_resource.service_name) - t - else - l = Chef::Resource::Link.new(initfile, run_context) - l.to(new_resource.sv_bin) - l - end - end + action :start do + if running? + Chef::Log.debug "#{new_resource} already running - nothing to do" + else + start_service + Chef::Log.info "#{new_resource} started" end + end - def service_link - @service_link ||= - begin - l = Chef::Resource::Link.new(::File.join(service_dir_name), run_context) - l.to(sv_dir_name) - l - end + action :stop do + if running? + stop_service + Chef::Log.info "#{new_resource} stopped" + else + Chef::Log.debug "#{new_resource} already stopped - nothing to do" end + end - def inside_docker? - results = `cat /proc/1/cgroup`.strip.split("\n") - results.any?{|val| /docker/ =~ val} + action :reload do + if running? + reload_service + Chef::Log.info "#{new_resource} reloaded" + else + Chef::Log.debug "#{new_resource} not running - nothing to do" end end + + action :status do + running? + end end end end diff --git a/cookbooks/runit/libraries/resource_runit_service.rb b/cookbooks/runit/libraries/resource_runit_service.rb index ec651de..e111f0e 100644 --- a/cookbooks/runit/libraries/resource_runit_service.rb +++ b/cookbooks/runit/libraries/resource_runit_service.rb @@ -29,8 +29,8 @@ class Chef super runit_node = runit_attributes_from_node(run_context) @resource_name = :runit_service - @provider = Chef::Provider::Service::Runit - @supports = { :restart => true, :reload => true, :status => true } + @provider = Chef::Provider::RunitService + @supports = { restart: true, reload: true, status: true } @action = :enable @allowed_actions = [:nothing, :start, :stop, :enable, :disable, :restart, :reload, :status, :once, :hup, :cont, :term, :kill, :up, :down, :usr1, :usr2, :create] @@ -47,6 +47,8 @@ class Chef @log = true @cookbook = nil @check = false + @start_down = false + @delete_downfile = false @finish = false @owner = nil @group = nil @@ -63,6 +65,7 @@ class Chef @sv_templates = true @sv_timeout = nil @sv_verbose = false + @log_dir = ::File.join('/var/log/', @service_name) @log_size = nil @log_num = nil @log_min = nil @@ -94,103 +97,114 @@ class Chef end def sv_bin(arg = nil) - set_or_return(:sv_bin, arg, :kind_of => [String]) + set_or_return(:sv_bin, arg, kind_of: [String]) end def sv_dir(arg = nil) - set_or_return(:sv_dir, arg, :kind_of => [String, FalseClass]) + set_or_return(:sv_dir, arg, kind_of: [String, FalseClass]) end def sv_timeout(arg = nil) - set_or_return(:sv_timeout, arg, :kind_of => [Fixnum]) + set_or_return(:sv_timeout, arg, kind_of: [Fixnum]) end def sv_verbose(arg = nil) - set_or_return(:sv_verbose, arg, :kind_of => [TrueClass, FalseClass]) + set_or_return(:sv_verbose, arg, kind_of: [TrueClass, FalseClass]) end def service_dir(arg = nil) - set_or_return(:service_dir, arg, :kind_of => [String]) + set_or_return(:service_dir, arg, kind_of: [String]) end def lsb_init_dir(arg = nil) - set_or_return(:lsb_init_dir, arg, :kind_of => [String]) + set_or_return(:lsb_init_dir, arg, kind_of: [String]) end def control(arg = nil) - set_or_return(:control, arg, :kind_of => [Array]) + set_or_return(:control, arg, kind_of: [Array]) end def options(arg = nil) - @env.empty? ? opts = @options : opts = @options.merge!(:env_dir => ::File.join(@sv_dir, @service_name, 'env')) + default_opts = @env.empty? ? @options : @options.merge(env_dir: ::File.join(@sv_dir, @service_name, 'env')) + + merged_opts = arg.respond_to?(:merge) ? default_opts.merge(arg) : default_opts + set_or_return( :options, - arg, - :kind_of => [Hash], - :default => opts + merged_opts, + kind_of: [Hash], + default: default_opts ) end def env(arg = nil) - set_or_return(:env, arg, :kind_of => [Hash]) + set_or_return(:env, arg, kind_of: [Hash]) end ## set log to current instance value if nothing is passed. def log(arg = @log) - set_or_return(:log, arg, :kind_of => [TrueClass, FalseClass]) + set_or_return(:log, arg, kind_of: [TrueClass, FalseClass]) end def cookbook(arg = nil) - set_or_return(:cookbook, arg, :kind_of => [String]) + set_or_return(:cookbook, arg, kind_of: [String]) end def finish(arg = nil) - set_or_return(:finish, arg, :kind_of => [TrueClass, FalseClass]) + set_or_return(:finish, arg, kind_of: [TrueClass, FalseClass]) end def check(arg = nil) - set_or_return(:check, arg, :kind_of => [TrueClass, FalseClass]) + set_or_return(:check, arg, kind_of: [TrueClass, FalseClass]) + end + + def start_down(arg = nil) + set_or_return(:start_down, arg, kind_of: [TrueClass, FalseClass]) + end + + def delete_downfile(arg = nil) + set_or_return(:delete_downfile, arg, kind_of: [TrueClass, FalseClass]) end def owner(arg = nil) - set_or_return(:owner, arg, :regex => [Chef::Config[:user_valid_regex]]) + set_or_return(:owner, arg, regex: [Chef::Config[:user_valid_regex]]) end def group(arg = nil) - set_or_return(:group, arg, :regex => [Chef::Config[:group_valid_regex]]) + set_or_return(:group, arg, regex: [Chef::Config[:group_valid_regex]]) end def default_logger(arg = nil) - set_or_return(:default_logger, arg, :kind_of => [TrueClass, FalseClass]) + set_or_return(:default_logger, arg, kind_of: [TrueClass, FalseClass]) end def restart_on_update(arg = nil) - set_or_return(:restart_on_update, arg, :kind_of => [TrueClass, FalseClass]) + set_or_return(:restart_on_update, arg, kind_of: [TrueClass, FalseClass]) end def run_template_name(arg = nil) - set_or_return(:run_template_name, arg, :kind_of => [String]) + set_or_return(:run_template_name, arg, kind_of: [String]) end alias_method :template_name, :run_template_name def log_template_name(arg = nil) - set_or_return(:log_template_name, arg, :kind_of => [String]) + set_or_return(:log_template_name, arg, kind_of: [String]) end def check_script_template_name(arg = nil) - set_or_return(:check_script_template_name, arg, :kind_of => [String]) + set_or_return(:check_script_template_name, arg, kind_of: [String]) end def finish_script_template_name(arg = nil) - set_or_return(:finish_script_template_name, arg, :kind_of => [String]) + set_or_return(:finish_script_template_name, arg, kind_of: [String]) end def control_template_names(arg = nil) set_or_return( :control_template_names, arg, - :kind_of => [Hash], - :default => set_control_template_names + kind_of: [Hash], + default: set_control_template_names ) end @@ -202,39 +216,43 @@ class Chef end def sv_templates(arg = nil) - set_or_return(:sv_templates, arg, :kind_of => [TrueClass, FalseClass]) + set_or_return(:sv_templates, arg, kind_of: [TrueClass, FalseClass]) + end + + def log_dir(arg = nil) + set_or_return(:log_dir, arg, kind_of: [String]) end def log_size(arg = nil) - set_or_return(:log_size, arg, :kind_of => [Integer]) + set_or_return(:log_size, arg, kind_of: [Integer]) end def log_num(arg = nil) - set_or_return(:log_num, arg, :kind_of => [Integer]) + set_or_return(:log_num, arg, kind_of: [Integer]) end def log_min(arg = nil) - set_or_return(:log_min, arg, :kind_of => [Integer]) + set_or_return(:log_min, arg, kind_of: [Integer]) end def log_timeout(arg = nil) - set_or_return(:log_timeout, arg, :kind_of => [Integer]) + set_or_return(:log_timeout, arg, kind_of: [Integer]) end def log_processor(arg = nil) - set_or_return(:log_processor, arg, :kind_of => [String]) + set_or_return(:log_processor, arg, kind_of: [String]) end def log_socket(arg = nil) - set_or_return(:log_socket, arg, :kind_of => [String, Hash]) + set_or_return(:log_socket, arg, kind_of: [String, Hash]) end def log_prefix(arg = nil) - set_or_return(:log_prefix, arg, :kind_of => [String]) + set_or_return(:log_prefix, arg, kind_of: [String]) end def log_config_append(arg = nil) - set_or_return(:log_config_append, arg, :kind_of => [String]) + set_or_return(:log_config_append, arg, kind_of: [String]) end def runit_attributes_from_node(run_context) diff --git a/cookbooks/runit/metadata.json b/cookbooks/runit/metadata.json index df7d104..6553a97 100644 --- a/cookbooks/runit/metadata.json +++ b/cookbooks/runit/metadata.json @@ -1,8 +1,7 @@ { "name": "runit", - "version": "1.6.0", "description": "Installs runit and provides runit_service definition", - "long_description": "runit Cookbook\n==============\nInstalls runit and provides the `runit_service` service resource for managing processes (services) under runit.\n\nThis cookbook does not use runit to replace system init, nor are ther plans to do so.\n\nFor more information about runit:\n\n- http://smarden.org/runit/\n\n\nRequirements\n------------\n### Platforms\n- Debian/Ubuntu\n- Gentoo\n- RHEL\n\n### Cookbooks\n- packagecloud (for RHEL)\n\nAttributes\n----------\nSee `attributes/default.rb` for defaults generated per platform.\n\n- `node['runit']['sv_bin']` - Full path to the `sv` binary.\n- `node['runit']['chpst_bin']` - Full path to the `chpst` binary.\n- `node['runit']['service_dir']` - Full path to the default \"services\" directory where enabled services are linked.\n- `node['runit']['sv_dir']` - Full path to the directory where service lives, which gets linked to `service_dir`.\n- `node['runit']['lsb_init_dir']` - Full path to the directory where the LSB-compliant init script interface will be created.\n- `node['runit']['start']` - Command to start the runsvdir service\n- `node['runit']['stop]` - Command to stop the runsvdir service\n- `node['runit']['reload']` - Command to reload the runsvdir service\n\n### Optional Attributes for RHEL systems\n\n- `node['runit']['prefer_local_yum']` - If `true`, assumes that a `runit` package is available on an already configured local yum repository. By default, the recipe installs the `runit` package from a Package Cloud repository (see below). This is set to the value of `node['runit']['use_package_from_yum']` for backwards compatibility, but otherwise defaults to `false`.\n\nRecipes\n-------\n### default\nThe default recipe installs runit and starts `runsvdir` to supervise the services in runit's service directory (e.g., `/etc/service`).\n\nOn RHEL-family systems, it will install the runit RPM using [Ian Meyer's Package Cloud repository](https://packagecloud.io/imeyer/runit) for runit. This replaces the previous functionality where the RPM was build using his [runit RPM SPEC](https://github.com/imeyer/runit-rpm). However, if the attribute `node['runit']['prefer_local_yum']` is set to `true`, the packagecloud repository creation will be skipped and it is assumed that a `runit` package is available on an otherwise configured (outside this cookbook) local repository.\n\nOn Debian family systems, the runit packages are maintained by the runit author, Gerrit Pape, and the recipe will use that for installation.\n\nOn Gentoo, the runit ebuild package is installed.\n\nResource/Provider\n-----------------\nThis cookbook has a resource, `runit_service`, for managing services under runit. This service subclasses the Chef `service` resource.\n\n**This resource replaces the runit_service definition. See the CHANGELOG.md file in this cookbook for breaking change information and any actions you may need to take to update cookbooks using runit_service.**\n\n### Actions\n- **enable** - enables the service, creating the required run scripts and symlinks. This is the default action.\n- **start** - starts the service with `sv start`\n- **stop** - stops the service with `sv stop`\n- **disable** - stops the service with `sv down` and removes the service symlink\n- **create** - create the service directory, but don't enable the service with symlink\n- **restart** - restarts the service with `sv restart`\n- **reload** - reloads the service with `sv force-reload`\n- **once** - starts the service with `sv once`.\n- **hup** - sends the `HUP` signal to the service with `sv hup`\n- **cont** - sends the `CONT` signal to the service\n- **term** - sends the `TERM` signal to the service\n- **kill** - sends the `KILL` signal to the service\n- **up** - starts the service with `sv up`\n- **down** - downs the service with `sv down`\n- **usr1** - sends the `USR1` signal to the service with `sv 1`\n- **usr2** - sends the `USR2` signal to the service with `sv 2`\n\nService management actions are taken with runit's \"`sv`\" program.\n\nRead the `sv(8)` [man page](http://smarden.org/runit/sv.8.html) for more information on the `sv` program.\n\n### Parameter Attributes\n\nThe first three parameters, `sv_dir`, `service_dir`, and `sv_bin` will attempt to use the corresponding node attributes, and fall back to hardcoded default values that match the settings used on Debian platform systems.\n\nMany of these parameters are only used in the `:enable` action.\n\n- **sv_dir** - The base \"service directory\" for the services managed by\n the resource. By default, this will attempt to use the\n `node['runit']['sv_dir']` attribute, and falls back to `/etc/sv`.\n- **service_dir** - The directory where services are symlinked to be\n supervised by `runsvdir`. By default, this will attempt to use the\n `node['runit']['service_dir']` attribute, and falls back to\n `/etc/service`.\n- **lsb_init_dir** - The directory where an LSB-compliant init script\n interface will be created. By default, this will attempt to use the\n `node['runit']['lsb_init_dir']` attribute, and falls back to\n `/etc/init.d`.\n- **sv_bin** - The path to the `sv` program binary. This will attempt\n to use the `node['runit']['sv_bin']` attribute, and falls back to\n `/usr/bin/sv`.\n- **service_name** - *Name attribute*. The name of the service. This\n will be used in the directory of the managed service in the\n `sv_dir` and `service_dir`.\n- **sv_timeout** - Override the default `sv` timeout of 7 seconds.\n- **sv_verbose** - Whether to enable `sv` verbose mode. Default is\n `false`.\n- **sv_templates** - If true, the `:enable` action will create the\n service directory with the appropriate templates. Default is\n `true`. Set this to `false` if the service has a package that\n provides its own service directory. See __Usage__ examples.\n- **options** - Options passed as variables to templates, for\n compatibility with legacy runit service definition. Default is an\n empty hash.\n- **env** - A hash of environment variables with their values as content\n used in the service's `env` directory. Default is an empty hash.\n- **log** - Whether to start the service's logger with svlogd, requires\n a template `sv-service_name-log-run.erb` to configure the log's run\n script. Default is true.\n- **default_logger** - Whether a default `log/run` script should be set\n up. If true, the default content of the run script will use\n `svlogd` to write logs to `/var/log/service_name`. Default is false.\n- **log_size** - The maximum size a log file can grow to before it is\n automatically rotated. See svlogd(8) for the default value.\n- **log_num** - The maximum number of log files that will be retained\n after rotation. See svlogd(8) for the default value.\n- **log_min** - The minimum number of log files that will be retained\n after rotation (if svlogd cannot create a new file and the minimum\n has not been reached, it will block). Default is no minimum.\n- **log_timeout** - The maximum age a log file can get to before it is\n automatically rotated, whether it has reached `log_size` or not.\n Default is no timeout.\n- **log_processor** - A string containing a path to a program that\n rotated log files will be fed through. See the **PROCESSOR** section\n of svlogd(8) for details. Default is no processor.\n- **log_socket** - An string containing an IP:port pair identifying a UDP\n socket that log lines will be copied to. Default is none.\n- **log_prefix** - A string that will be prepended to each line as it\n is logged. Default is no prefix.\n- **log_config_append** - A string containing optional additional lines to add\n to the log service configuration. See svlogd(8) for more details.\n- **cookbook** - A cookbook where templates are located instead of\n where the resource is used. Applies for all the templates in the\n `enable` action.\n- **check** - whether the service has a check script, requires a\n template `sv-service_name-check.erb`\n- **finish** - whether the service has a finish script, requires a\n template `sv-service_name-finish.erb`\n- **control** - An array of signals to customize control of the service,\n see [runsv man page](http://smarden.org/runit/runsv.8.html) on how\n to use this. This requires that each template be created with the\n name `sv-service_name-signal.erb`.\n- **owner** - user that should own the templates created to enable the\n service\n- **group** - group that should own the templates created to enable the\n service\n- **run_template_name** - alternate filename of the run run script to\n use replacing `service_name`.\n- **log_template_name** - alternate filename of the log run script to\n use replacing `service_name`.\n- **check_script_template_name** - alternate filename of the check\n script to use, replacing `service_name`.\n- **finish_script_template_name** - alternate filename of the finish\n script to use, replacing `service_name`.\n- **control_template_names** - a hash of control signals (see *control*\n above) and their alternate template name(s) replacing\n `service_name`.\n- **status_command** - The command used to check the status of the\n service to see if it is enabled/running (if it's running, it's\n enabled). This hardcodes the location of the sv program to\n `/usr/bin/sv` due to the aforementioned cookbook load order.\n- **restart_on_update** - Whether the service should be restarted when\n the run script is updated. Defaults to `true`. Set to `false` if\n the service shouldn't be restarted when the run script is updated.\n\nUnlike previous versions of the cookbook using the `runit_service` definition, the `runit_service` resource can be notified. See __Usage__ examples below.\n\n\nUsage\n-----\nTo get runit installed on supported platforms, use `recipe[runit]`. Once it is installed, use the `runit_service` resource to set up services to be managed by runit.\n\nIn order to use the `runit_service` resource in your cookbook(s), each service managed will also need to have `sv-service_name-run.erb` and `sv-service_name-log-run.erb` templates created. If the `log` parameter is false, the log run script isn't created. If the `log` parameter is true, and `default_logger` is also true, the log run\nscript will be created with the default content:\n\n```bash\n#!/bin/sh\nexec svlogd -tt /var/log/service_name\n```\n\n### Examples\nThese are example use cases of the `runit_service` resource described above. There are others in the `runit_test` cookbook that is included in the [git repository](https://github.com/chef-cookbooks/runit).\n\n**Default Example**\n\nThis example uses all the defaults in the `:enable` action to set up the service.\n\nWe'll set up `chef-client` to run as a service under runit, such as is done in the `chef-client` cookbook. This example will be more simple than in that cookbook. First, create the required run template, `chef-client/templates/default/sv-chef-client-run.erb`.\n\n```bash\n#!/bin/sh\nexec 2>&1\nexec /usr/bin/env chef-client -i 1800 -s 30\n```\n\nThen create the required log/run template, `chef-client/templates/default/sv-chef-client-log-run.erb`.\n\n```bash\n#!/bin/sh\nexec svlogd -tt ./main\n```\n\n__Note__ This will cause output of the running process to go to `/etc/sv/chef-client/log/main/current`. Some people may not like this, see the following example. This is preserved for compatibility reasons.\n\nFinally, set up the service in the recipe with:\n\n```ruby\nrunit_service \"chef-client\"\n```\n\n**Default Logger Example**\n\nTo use a default logger with svlogd which will log to `/var/log/chef-client/current`, instead, use the `default_logger` option.\n\n```ruby\nrunit_service \"chef-client\" do\n default_logger true\nend\n```\n\n**No Log Service**\n\nIf there isn't an appendant log service, set `log` to false, and the log/run script won't be created.\n\n```ruby\nrunit_service \"no-svlog\" do\n log false\nend\n```\n\n**Check Script**\n\nTo create a service that has a check script in its service directory, set the `check` parameter to `true`, and create a `sv-checker-check.erb` template.\n\n```ruby\nrunit_service \"checker\" do\n check true\nend\n```\n\nThis will create `/etc/sv/checker/check`.\n\n**Finish Script**\n\nTo create a service that has a finish script in its service directory, set the `finish` parameter to `true`, and create a `sv-finisher-finish.erb` template.\n\n```ruby\nrunit_service \"finisher\" do\n finish true\nend\n```\n\nThis will create `/etc/sv/finisher/finish`.\n\n**Alternate service directory**\n\nIf the service directory for the managed service isn't the `sv_dir` (`/etc/sv`), then specify it:\n\n```ruby\nrunit_service \"custom_service\" do\n sv_dir \"/etc/custom_service/runit\"\nend\n```\n\n**No Service Directory**\n\nIf the service to manage has a package that provides its service directory, such as `git-daemon` on Debian systems, set `sv_templates` to false.\n\n```ruby\npackage \"git-daemon-run\"\n\nrunit_service \"git-daemon\" do\n sv_templates false\nend\n```\n\nThis will create the service symlink in `/etc/service`, but it will not manage any templates in the service directory.\n\n**User Controlled Services**\n\nTo set up services controlled by a non-privileged user, we follow the recommended configuration in the [runit documentation](http://smarden.org/runit/faq.html#user) (Is it possible to allow a user other than root to control a service?).\n\nSuppose the user's name is floyd, and floyd wants to run floyds-app. Assuming that the floyd user and group are already managed with Chef, create a `runsvdir-floyd` runit_service.\n\n```ruby\nrunit_service \"runsvdir-floyd\"\n```\n\nCreate the `sv-runsvdir-floyd-log-run.erb` template, or add `log false`. Also create the `sv-runsvdir-floyd-run.erb` with the following content:\n\n```bash\n#!/bin/sh\nexec 2>&1\nexec chpst -ufloyd runsvdir /home/floyd/service\n```\n\nNext, create the `runit_service` resource for floyd's app:\n\n```ruby\nrunit_service \"floyds-app\" do\n sv_dir \"/home/floyd/sv\"\n service_dir \"/home/floyd/service\"\n owner \"floyd\"\n group \"floyd\"\nend\n```\n\nAnd now floyd can manage the service with sv:\n\n```text\n$ id\nuid=1000(floyd) gid=1001(floyd) groups=1001(floyd)\n$ sv stop /home/floyd/service/floyds-app/\nok: down: /home/floyd/service/floyds-app/: 0s, normally up\n$ sv start /home/floyd/service/floyds-app/\nok: run: /home/floyd/service/floyds-app/: (pid 5287) 0s\n$ sv status /home/floyd/service/floyds-app/\nrun: /home/floyd/service/floyds-app/: (pid 5287) 13s; run: log: (pid 4691) 726s\n```\n\n**Options**\n\nNext, let's set up memcached under runit with some additional options using the `options` parameter. First, the `memcached/templates/default/sv-memcached-run.erb` template:\n\n```bash\n#!/bin/sh\nexec 2>&1\nexec chpst -u <%= @options[:user] %> /usr/bin/memcached -v -m <%= @options[:memory] %> -p <%= @options[:port] %>\n```\n\nNote that the script uses `chpst` (which comes with runit) to set the user option, then starts memcached on the specified memory and port (see below).\n\nThe log/run template, `memcached/templates/default/sv-memcached-log-run.erb`:\n\n```bash\n#!/bin/sh\nexec svlogd -tt ./main\n```\n\nFinally, the `runit_service` in our recipe:\n\n```ruby\nrunit_service \"memcached\" do\n options({\n :memory => node[:memcached][:memory],\n :port => node[:memcached][:port],\n :user => node[:memcached][:user]}.merge(params)\n })\nend\n```\n\nThis is where the user, port and memory options used in the run template are used.\n\n**Notifying Runit Services**\n\nIn previous versions of this cookbook where the definition was used, it created a `service` resource that could be notified. With the `runit_service` resource, recipes need to use the full resource name.\n\nFor example:\n\n```ruby\nrunit_service \"my-service\"\n\ntemplate \"/etc/my-service.conf\" do\n notifies :restart, \"runit_service[my-service]\"\nend\n```\n\nBecause the resource implements actions for various commands that `sv` can send to the service, any of those actions could be used for notification. For example, `chef-client` supports triggering a Chef run with a USR1 signal.\n\n```ruby\ntemplate \"/tmp/chef-notifier\" do\n notifies :usr1, \"runit_service[chef-client]\"\nend\n```\n\nFor older implementations of services that used `runit_service` as a definition, but may support alternate service styles, use a conditional, such as based on an attribute:\n\n```ruby\nservice_to_notify = case node['nginx']['init_style']\n when \"runit\"\n \"runit_service[nginx]\"\n else\n \"service[nginx]\"\n end\n\ntemplate \"/etc/nginx/nginx.conf\" do\n notifies :restart, service_to_notify\nend\n```\n\n**More Examples**\n\nFor more examples, see the `runit_test` cookbook's `service` recipe in the [git repository](https://github.com/chef-cookbooks/runit).\n\n\nLicense & Authors\n-----------------\n- Author:: Adam Jacob \n- Author:: Joshua Timberman \n\n```text\nCopyright:: 2008-2013, 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", + "long_description": "runit Cookbook\n==============\nInstalls runit and provides the `runit_service` service resource for managing processes (services) under runit.\n\nThis cookbook does not use runit to replace system init, nor are ther plans to do so.\n\nFor more information about runit:\n\n- http://smarden.org/runit/\n\n#### A note regarding versions 1.7.0 and 1.7.2\n\nWith the benefit of hindsight we can say that the changes contained version 1.7.0 merited a major version number change, and that version 1.7.2 contains some still unresolved regressions compared to 1.6.0. Please be sure to test this new version for compatibility with your systems before upgrading to version 1.7.\n\nSee [issue #144](https://github.com/hw-cookbooks/runit/issues/144) for some notes on how these versions behaved unexpectedly in one user's environment.\n\nRequirements\n------------\n#### Platforms\n- Debian/Ubuntu\n- Gentoo\n- RHEL\n\n#### Chef\n- Chef 11+\n\n#### Cookbooks\n- packagecloud (for RHEL)\n\nAttributes\n----------\nSee `attributes/default.rb` for defaults generated per platform.\n\n- `node['runit']['sv_bin']` - Full path to the `sv` binary.\n- `node['runit']['chpst_bin']` - Full path to the `chpst` binary.\n- `node['runit']['service_dir']` - Full path to the default \"services\" directory where enabled services are linked.\n- `node['runit']['sv_dir']` - Full path to the directory where service lives, which gets linked to `service_dir`.\n- `node['runit']['lsb_init_dir']` - Full path to the directory where the LSB-compliant init script interface will be created.\n- `node['runit']['start']` - Command to start the runsvdir service\n- `node['runit']['stop]` - Command to stop the runsvdir service\n- `node['runit']['reload']` - Command to reload the runsvdir service\n\n### Optional Attributes for RHEL systems\n\n- `node['runit']['prefer_local_yum']` - If `true`, assumes that a `runit` package is available on an already configured local yum repository. By default, the recipe installs the `runit` package from a Package Cloud repository (see below). This is set to the value of `node['runit']['use_package_from_yum']` for backwards compatibility, but otherwise defaults to `false`.\n\nRecipes\n-------\n### default\nThe default recipe installs runit and starts `runsvdir` to supervise the services in runit's service directory (e.g., `/etc/service`).\n\nOn RHEL-family systems, it will install the runit RPM using [Ian Meyer's Package Cloud repository](https://packagecloud.io/imeyer/runit) for runit. This replaces the previous functionality where the RPM was build using his [runit RPM SPEC](https://github.com/imeyer/runit-rpm). However, if the attribute `node['runit']['prefer_local_yum']` is set to `true`, the packagecloud repository creation will be skipped and it is assumed that a `runit` package is available on an otherwise configured (outside this cookbook) local repository.\n\nOn Debian family systems, the runit packages are maintained by the runit author, Gerrit Pape, and the recipe will use that for installation.\n\nOn Gentoo, the runit ebuild package is installed.\n\nResource/Provider\n-----------------\nThis cookbook has a resource, `runit_service`, for managing services under runit. This service subclasses the Chef `service` resource.\n\n**This resource replaces the runit_service definition. See the CHANGELOG.md file in this cookbook for breaking change information and any actions you may need to take to update cookbooks using runit_service.**\n\n### Actions\n- **enable** - enables the service, creating the required run scripts and symlinks. This is the default action.\n- **start** - starts the service with `sv start`\n- **stop** - stops the service with `sv stop`\n- **disable** - stops the service with `sv down` and removes the service symlink\n- **create** - create the service directory, but don't enable the service with symlink\n- **restart** - restarts the service with `sv restart`\n- **reload** - reloads the service with `sv force-reload`\n- **once** - starts the service with `sv once`.\n- **hup** - sends the `HUP` signal to the service with `sv hup`\n- **cont** - sends the `CONT` signal to the service\n- **term** - sends the `TERM` signal to the service\n- **kill** - sends the `KILL` signal to the service\n- **up** - starts the service with `sv up`\n- **down** - downs the service with `sv down`\n- **usr1** - sends the `USR1` signal to the service with `sv 1`\n- **usr2** - sends the `USR2` signal to the service with `sv 2`\n\nService management actions are taken with runit's \"`sv`\" program.\n\nRead the `sv(8)` [man page](http://smarden.org/runit/sv.8.html) for more information on the `sv` program.\n\n### Parameter Attributes\n\nThe first three parameters, `sv_dir`, `service_dir`, and `sv_bin` will attempt to use the corresponding node attributes, and fall back to hardcoded default values that match the settings used on Debian platform systems.\n\nMany of these parameters are only used in the `:enable` action.\n\n- **sv_dir** - The base \"service directory\" for the services managed by\n the resource. By default, this will attempt to use the\n `node['runit']['sv_dir']` attribute, and falls back to `/etc/sv`.\n- **service_dir** - The directory where services are symlinked to be\n supervised by `runsvdir`. By default, this will attempt to use the\n `node['runit']['service_dir']` attribute, and falls back to\n `/etc/service`.\n- **lsb_init_dir** - The directory where an LSB-compliant init script\n interface will be created. By default, this will attempt to use the\n `node['runit']['lsb_init_dir']` attribute, and falls back to\n `/etc/init.d`.\n- **sv_bin** - The path to the `sv` program binary. This will attempt\n to use the `node['runit']['sv_bin']` attribute, and falls back to\n `/usr/bin/sv`.\n- **service_name** - *Name attribute*. The name of the service. This\n will be used in the directory of the managed service in the\n `sv_dir` and `service_dir`.\n- **sv_timeout** - Override the default `sv` timeout of 7 seconds.\n- **sv_verbose** - Whether to enable `sv` verbose mode. Default is\n `false`.\n- **sv_templates** - If true, the `:enable` action will create the\n service directory with the appropriate templates. Default is\n `true`. Set this to `false` if the service has a package that\n provides its own service directory. See __Usage__ examples.\n- **options** - Options passed as variables to templates, for\n compatibility with legacy runit service definition. Default is an\n empty hash.\n- **env** - A hash of environment variables with their values as content\n used in the service's `env` directory. Default is an empty hash. When\n this hash is non-empty, the contents of the runit service's `env`\n directory will be managed by Chef in order to conform to the declared\n state.\n- **log** - Whether to start the service's logger with svlogd, requires\n a template `sv-service_name-log-run.erb` to configure the log's run\n script. Default is true.\n- **default_logger** - Whether a default `log/run` script should be set\n up. If true, the default content of the run script will use\n `svlogd` to write logs to `/var/log/service_name`. Default is false.\n- **log_dir** - The directory where the `svlogd` log service will run.\n Used when `default_logger` is `true`. Default is `/var/log/service_name`\n- **log_size** - The maximum size a log file can grow to before it is\n automatically rotated. See svlogd(8) for the default value.\n- **log_num** - The maximum number of log files that will be retained\n after rotation. See svlogd(8) for the default value.\n- **log_min** - The minimum number of log files that will be retained\n after rotation (if svlogd cannot create a new file and the minimum\n has not been reached, it will block). Default is no minimum.\n- **log_timeout** - The maximum age a log file can get to before it is\n automatically rotated, whether it has reached `log_size` or not.\n Default is no timeout.\n- **log_processor** - A string containing a path to a program that\n rotated log files will be fed through. See the **PROCESSOR** section\n of svlogd(8) for details. Default is no processor.\n- **log_socket** - An string containing an IP:port pair identifying a UDP\n socket that log lines will be copied to. Default is none.\n- **log_prefix** - A string that will be prepended to each line as it\n is logged. Default is no prefix.\n- **log_config_append** - A string containing optional additional lines to add\n to the log service configuration. See svlogd(8) for more details.\n- **cookbook** - A cookbook where templates are located instead of\n where the resource is used. Applies for all the templates in the\n `enable` action.\n- **check** - whether the service has a check script, requires a\n template `sv-service_name-check.erb`\n- **finish** - whether the service has a finish script, requires a\n template `sv-service_name-finish.erb`\n- **control** - An array of signals to customize control of the service,\n see [runsv man page](http://smarden.org/runit/runsv.8.html) on how\n to use this. This requires that each template be created with the\n name `sv-service_name-signal.erb`.\n- **owner** - user that should own the templates created to enable the\n service\n- **group** - group that should own the templates created to enable the\n service\n- **run_template_name** - alternate filename of the run run script to\n use replacing `service_name`.\n- **log_template_name** - alternate filename of the log run script to\n use replacing `service_name`.\n- **check_script_template_name** - alternate filename of the check\n script to use, replacing `service_name`.\n- **finish_script_template_name** - alternate filename of the finish\n script to use, replacing `service_name`.\n- **control_template_names** - a hash of control signals (see *control*\n above) and their alternate template name(s) replacing\n `service_name`.\n- **status_command** - The command used to check the status of the\n service to see if it is enabled/running (if it's running, it's\n enabled). This hardcodes the location of the sv program to\n `/usr/bin/sv` due to the aforementioned cookbook load order.\n- **restart_on_update** - Whether the service should be restarted when\n the run script is updated. Defaults to `true`. Set to `false` if\n the service shouldn't be restarted when the run script is updated.\n- **start_down** - Set the default state of the runit service to 'down' by creating\n `/down` file. Defaults to `false`. Services using `start_down`\n will not be notified to restart when their run script is updated.\n- **delete_downfile** - Delete previously created `/down` file\n\nUnlike previous versions of the cookbook using the `runit_service` definition, the `runit_service` resource can be notified. See __Usage__ examples below.\n\n\nUsage\n-----\nTo get runit installed on supported platforms, use `recipe[runit]`. Once it is installed, use the `runit_service` resource to set up services to be managed by runit.\n\nIn order to use the `runit_service` resource in your cookbook(s), each service managed will also need to have `sv-service_name-run.erb` and `sv-service_name-log-run.erb` templates created. If the `log` parameter is false, the log run script isn't created. If the `log` parameter is true, and `default_logger` is also true, the log run\nscript will be created with the default content:\n\n```bash\n#!/bin/sh\nexec svlogd -tt /var/log/service_name\n```\n\n### Examples\nThese are example use cases of the `runit_service` resource described above. There are others in the `runit_test` cookbook that is included in the [git repository](https://github.com/hw-cookbooks/runit).\n\n**Default Example**\n\nThis example uses all the defaults in the `:enable` action to set up the service.\n\nWe'll set up `chef-client` to run as a service under runit, such as is done in the `chef-client` cookbook. This example will be more simple than in that cookbook. First, create the required run template, `chef-client/templates/default/sv-chef-client-run.erb`.\n\n```bash\n#!/bin/sh\nexec 2>&1\nexec /usr/bin/env chef-client -i 1800 -s 30\n```\n\nThen create the required log/run template, `chef-client/templates/default/sv-chef-client-log-run.erb`.\n\n```bash\n#!/bin/sh\nexec svlogd -tt ./main\n```\n\n__Note__ This will cause output of the running process to go to `/etc/sv/chef-client/log/main/current`. Some people may not like this, see the following example. This is preserved for compatibility reasons.\n\nFinally, set up the service in the recipe with:\n\n```ruby\nrunit_service \"chef-client\"\n```\n\n**Default Logger Example**\n\nTo use a default logger with svlogd which will log to `/var/log/chef-client/current`, instead, use the `default_logger` option.\n\n```ruby\nrunit_service \"chef-client\" do\n default_logger true\nend\n```\n\n**No Log Service**\n\nIf there isn't an appendant log service, set `log` to false, and the log/run script won't be created.\n\n```ruby\nrunit_service \"no-svlog\" do\n log false\nend\n```\n\n**Check Script**\n\nTo create a service that has a check script in its service directory, set the `check` parameter to `true`, and create a `sv-checker-check.erb` template.\n\n```ruby\nrunit_service \"checker\" do\n check true\nend\n```\n\nThis will create `/etc/sv/checker/check`.\n\n**Finish Script**\n\nTo create a service that has a finish script in its service directory, set the `finish` parameter to `true`, and create a `sv-finisher-finish.erb` template.\n\n```ruby\nrunit_service \"finisher\" do\n finish true\nend\n```\n\nThis will create `/etc/sv/finisher/finish`.\n\n**Alternate service directory**\n\nIf the service directory for the managed service isn't the `sv_dir` (`/etc/sv`), then specify it:\n\n```ruby\nrunit_service \"custom_service\" do\n sv_dir \"/etc/custom_service/runit\"\nend\n```\n\n**No Service Directory**\n\nIf the service to manage has a package that provides its service directory, such as `git-daemon` on Debian systems, set `sv_templates` to false.\n\n```ruby\npackage \"git-daemon-run\"\n\nrunit_service \"git-daemon\" do\n sv_templates false\nend\n```\n\nThis will create the service symlink in `/etc/service`, but it will not manage any templates in the service directory.\n\n**User Controlled Services**\n\nTo set up services controlled by a non-privileged user, we follow the recommended configuration in the [runit documentation](http://smarden.org/runit/faq.html#user) (Is it possible to allow a user other than root to control a service?).\n\nSuppose the user's name is floyd, and floyd wants to run floyds-app. Assuming that the floyd user and group are already managed with Chef, create a `runsvdir-floyd` runit_service.\n\n```ruby\nrunit_service \"runsvdir-floyd\"\n```\n\nCreate the `sv-runsvdir-floyd-log-run.erb` template, or add `log false`. Also create the `sv-runsvdir-floyd-run.erb` with the following content:\n\n```bash\n#!/bin/sh\nexec 2>&1\nexec chpst -ufloyd runsvdir /home/floyd/service\n```\n\nNext, create the `runit_service` resource for floyd's app:\n\n```ruby\nrunit_service \"floyds-app\" do\n sv_dir \"/home/floyd/sv\"\n service_dir \"/home/floyd/service\"\n owner \"floyd\"\n group \"floyd\"\nend\n```\n\nAnd now floyd can manage the service with sv:\n\n```text\n$ id\nuid=1000(floyd) gid=1001(floyd) groups=1001(floyd)\n$ sv stop /home/floyd/service/floyds-app/\nok: down: /home/floyd/service/floyds-app/: 0s, normally up\n$ sv start /home/floyd/service/floyds-app/\nok: run: /home/floyd/service/floyds-app/: (pid 5287) 0s\n$ sv status /home/floyd/service/floyds-app/\nrun: /home/floyd/service/floyds-app/: (pid 5287) 13s; run: log: (pid 4691) 726s\n```\n\n**Options**\n\nNext, let's set up memcached under runit with some additional options using the `options` parameter. First, the `memcached/templates/default/sv-memcached-run.erb` template:\n\n```bash\n#!/bin/sh\nexec 2>&1\nexec chpst -u <%= @options[:user] %> /usr/bin/memcached -v -m <%= @options[:memory] %> -p <%= @options[:port] %>\n```\n\nNote that the script uses `chpst` (which comes with runit) to set the user option, then starts memcached on the specified memory and port (see below).\n\nThe log/run template, `memcached/templates/default/sv-memcached-log-run.erb`:\n\n```bash\n#!/bin/sh\nexec svlogd -tt ./main\n```\n\nFinally, the `runit_service` in our recipe:\n\n```ruby\nrunit_service \"memcached\" do\n options({\n :memory => node[:memcached][:memory],\n :port => node[:memcached][:port],\n :user => node[:memcached][:user]\n }.merge(params))\nend\n```\n\nThis is where the user, port and memory options used in the run template are used.\n\n**Notifying Runit Services**\n\nIn previous versions of this cookbook where the definition was used, it created a `service` resource that could be notified. With the `runit_service` resource, recipes need to use the full resource name.\n\nFor example:\n\n```ruby\nrunit_service \"my-service\"\n\ntemplate \"/etc/my-service.conf\" do\n notifies :restart, \"runit_service[my-service]\"\nend\n```\n\nBecause the resource implements actions for various commands that `sv` can send to the service, any of those actions could be used for notification. For example, `chef-client` supports triggering a Chef run with a USR1 signal.\n\n```ruby\ntemplate \"/tmp/chef-notifier\" do\n notifies :usr1, \"runit_service[chef-client]\"\nend\n```\n\nFor older implementations of services that used `runit_service` as a definition, but may support alternate service styles, use a conditional, such as based on an attribute:\n\n```ruby\nservice_to_notify = case node['nginx']['init_style']\n when \"runit\"\n \"runit_service[nginx]\"\n else\n \"service[nginx]\"\n end\n\ntemplate \"/etc/nginx/nginx.conf\" do\n notifies :restart, service_to_notify\nend\n```\n\n**More Examples**\n\nFor more examples, see the `runit_test` cookbook's `service` recipe in the [git repository](https://github.com/hw-cookbooks/runit).\n\n\nLicense & Authors\n-----------------\n- Author:: Adam Jacob \n- Author:: Joshua Timberman \n- Author:: Sean OMeara \n\n```text\nCopyright:: 2008-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": "Heavy Water Operations, LLC.", "maintainer_email": "support@hw-ops.com", "license": "Apache 2.0", @@ -21,20 +20,30 @@ "packagecloud": ">= 0.0.0" }, "recommendations": { + }, "suggestions": { + }, "conflicting": { + }, "providing": { + }, "replacing": { + }, "attributes": { + }, "groupings": { + }, "recipes": { "runit": "Installs and configures runit" - } -} \ No newline at end of file + }, + "version": "1.7.6", + "source_url": "", + "issues_url": "" +} diff --git a/cookbooks/runit/metadata.rb b/cookbooks/runit/metadata.rb new file mode 100644 index 0000000..65bb21d --- /dev/null +++ b/cookbooks/runit/metadata.rb @@ -0,0 +1,15 @@ +name 'runit' +maintainer 'Heavy Water Operations, LLC.' +maintainer_email 'support@hw-ops.com' +license 'Apache 2.0' +description 'Installs runit and provides runit_service definition' +long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) +version '1.7.6' + +recipe 'runit', 'Installs and configures runit' + +%w(ubuntu debian gentoo centos redhat amazon scientific oracle enterpriseenterprise).each do |os| + supports os +end + +depends 'packagecloud' diff --git a/cookbooks/runit/recipes/default.rb b/cookbooks/runit/recipes/default.rb index c3439f8..2c18881 100644 --- a/cookbooks/runit/recipes/default.rb +++ b/cookbooks/runit/recipes/default.rb @@ -42,6 +42,12 @@ when 'rhel', 'fedora' packagecloud_repo 'imeyer/runit' unless node['runit']['prefer_local_yum'] package 'runit' + if node['platform_version'].to_i == 7 + service 'runsvdir-start' do + action [:start, :enable] + end + end + when 'debian', 'gentoo' if platform?('gentoo') @@ -59,7 +65,7 @@ when 'debian', 'gentoo' action :install response_file 'runit.seed' if platform?('ubuntu', 'debian') notifies value_for_platform( - 'debian' => { '4.0' => :run, 'default' => :nothing }, + 'debian' => { '4.0' => :run, 'default' => :nothing }, 'ubuntu' => { 'default' => :nothing, '9.04' => :run, diff --git a/cookbooks/runit/templates/debian/init.d.erb b/cookbooks/runit/templates/debian/init.d.erb index 48b5367..491d53f 100644 --- a/cookbooks/runit/templates/debian/init.d.erb +++ b/cookbooks/runit/templates/debian/init.d.erb @@ -13,8 +13,8 @@ PATH=/sbin:/usr/sbin:/bin:/usr/bin DESC="runit-managed <%= @name %>" NAME=<%= @name %> -RUNIT=/usr/bin/sv -SCRIPTNAME=/etc/init.d/$NAME +RUNIT=<%= @sv_bin %> +SCRIPTNAME=<%= @init_dir %>$NAME # Exit if runit is not installed [ -x $RUNIT ] || exit 0 diff --git a/cookbooks/runit/templates/default/log-config.erb b/cookbooks/runit/templates/default/log-config.erb index 6e33db1..68322b6 100644 --- a/cookbooks/runit/templates/default/log-config.erb +++ b/cookbooks/runit/templates/default/log-config.erb @@ -1,24 +1,24 @@ -<% if @size -%> -s<%= @size %> +<% if @config.log_size -%> +s<%= @config.log_size %> <% end -%> -<% if @num -%> -n<%= @num %> +<% if @config.log_num -%> +n<%= @config.log_num %> <% end -%> -<% if @min -%> -N<%= @min %> +<% if @config.log_min -%> +N<%= @config.log_min %> <% end -%> -<% if @timeout -%> -t<%= @timeout %> +<% if @config.log_timeout -%> +t<%= @config.log_timeout %> <% end -%> -<% if @processor -%> -!<%= @processor %> +<% if @config.log_processor -%> +!<%= @config.log_processor %> <% end -%> -<% if @socket -%> -u<%= @socket %> +<% if @config.log_socket -%> +u<%= @config.log_socket %> <% end -%> -<% if @prefix -%> -p<%= @prefix %> +<% if @config.log_prefix -%> +p<%= @config.log_prefix %> <% end -%> -<% if @append -%> -<%= @append %> +<% if @config.log_config_append -%> +<%= @config.log_config_append %> <% end -%> diff --git a/cookbooks/selinux/CHANGELOG.md b/cookbooks/selinux/CHANGELOG.md new file mode 100644 index 0000000..0e43d7f --- /dev/null +++ b/cookbooks/selinux/CHANGELOG.md @@ -0,0 +1,52 @@ +selinux Cookbook CHANGELOG +========================== + +v0.9.0 (2015-02-22) +------------------- +- Initial Debian / Ubuntu support +- Various bug fixes + +v0.8.0 (2014-04-23) +------------------- +- [COOK-4528] - Fix selinux directory permissions +- [COOK-4562] - Basic support for Ubuntu/Debian + + +v0.7.2 (2014-03-24) +------------------- +handling minimal installs + + +v0.7.0 (2014-02-27) +------------------- +[COOK-4218] Support setting SELinux boolean values + + +v0.6.2 +------ +- Fixing bug introduced in 0.6.0 +- adding basic test-kitchen coverage + + +v0.6.0 +------ +- [COOK-760] - selinux enforce/permit/disable based on attribute + + +v0.5.6 +------ +- [COOK-2124] - enforcing recipe fails if selinux is disabled + +v0.5.4 +------ +- [COOK-1277] - disabled recipe fails on systems w/o selinux installed + +v0.5.2 +------ +- [COOK-789] - fix dangling commas causing syntax error on some rubies + +v0.5.0 +------ +- [COOK-678] - add the selinux cookbook to the repository +- Use main selinux config file (/etc/selinux/config) +- Use getenforce instead of selinuxenabled for enforcing and permissive diff --git a/cookbooks/selinux/README.md b/cookbooks/selinux/README.md new file mode 100644 index 0000000..11e8961 --- /dev/null +++ b/cookbooks/selinux/README.md @@ -0,0 +1,144 @@ +Description +=========== + +Provides recipes for manipulating SELinux policy enforcement state. + +Requirements +============ + +RHEL family distribution or other Linux system that uses SELinux. + +## Platform: + +Tested on RHEL 5.8, 6.3 + +Node Attributes +=============== + +* `node['selinux']['state']` - The SELinux policy enforcement state. + The state to set by default, to match the default SELinux state on + RHEL. Can be "enforcing", "permissive", "disabled" + +* `node['selinux']['booleans']` - A hash of SELinux boolean names and the + values they should be set to. Values can be off, false, or 0 to disable; + or on, true, or 1 to enable. + +Resources/Providers +=================== + +## selinux\_state + +The `selinux_state` LWRP is used to manage the SELinux state on the +system. It does this by using the `setenforce` command and rendering +the `/etc/selinux/config` file from a template. + +### Actions + +* `:nothing` - default action, does nothing +* `:enforcing` - Sets SELinux to enforcing. +* `:disabled` - Sets SELinux to disabled. +* `:permissive` - Sets SELinux to permissive. + +### Attributes + +The LWRP has no user-settable resource attributes. + +### Examples + +Simply set SELinux to enforcing or permissive: + + selinux_state "SELinux Enforcing" do + action :enforcing + end + + selinux_state "SELinux Permissive" do + action :permissive + end + +The action here is based on the value of the +`node['selinux']['state']` attribute, which we convert to lower-case +and make a symbol to pass to the action. + + selinux_state "SELinux #{node['selinux']['state'].capitalize}" do + action node['selinux']['state'].downcase.to_sym + end + +Recipes +======= + +All the recipes now leverage the LWRP described above. + +## default + +The default recipe will use the attribute `node['selinux']['state']` +in the `selinux_state` LWRP's action. By default, this will be `:enforcing`. + +## enforcing + +This recipe will use `:enforcing` as the `selinux_state` action. + +## permissive + +This recipe will use `:permissive` as the `selinux_state` action. + +## disabled + +This recipe will use `:disabled` as the `selinux_state` action. + +Usage +===== + +By default, this cookbook will have SELinux enforcing by default, as +the default recipe uses the `node['selinux']['state']` attribute, +which is "enforcing." This is in line with the policy of enforcing by +default on RHEL family distributions. + +This has complicated considerations when changing the default +configuration of their systems, whether it is with automated +configuration management or manually. Often, third party help forums +and support sites recommend setting SELinux to "permissive." This +cookbook can help with that, in two ways. + +You can simply set the attribute in a role applied to the node: + + name "base" + description "Base role applied to all nodes." + default_attributes( + "selinux" => { + "state" => "permissive" + } + ) + +Or, you can apply the recipe to the run list (e.g., in a role): + + name "base" + description "Base role applied to all nodes." + run_list( + "recipe[selinux::permissive]", + ) + +Roadmap +======= + +Add LWRP/Libraries for manipulating security contexts for files and +services managed by Chef. + +License and Author +================== + +- Author:: Sean OMeara () +- Author:: Joshua Timberman () + +Copyright:: 2011-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. diff --git a/cookbooks/selinux/attributes/default.rb b/cookbooks/selinux/attributes/default.rb new file mode 100644 index 0000000..68d07f3 --- /dev/null +++ b/cookbooks/selinux/attributes/default.rb @@ -0,0 +1,2 @@ +default['selinux']['state'] = 'enforcing' +default['selinux']['booleans'] = {} diff --git a/cookbooks/selinux/libraries/selinux_service_helpers.rb b/cookbooks/selinux/libraries/selinux_service_helpers.rb new file mode 100644 index 0000000..1c2e568 --- /dev/null +++ b/cookbooks/selinux/libraries/selinux_service_helpers.rb @@ -0,0 +1,13 @@ +module SELinuxServiceHelpers + def self.selinux_bool(bool) + if ['on', 'true', '1', true, 1].include? bool + 'on' + elsif ['off', 'false', '0', false, 0].include? bool + 'off' + else + Chef::Log.warn "Not a valid boolean value: #{bool}" + nil + end + end +end + diff --git a/cookbooks/selinux/metadata.json b/cookbooks/selinux/metadata.json new file mode 100644 index 0000000..f956ff1 --- /dev/null +++ b/cookbooks/selinux/metadata.json @@ -0,0 +1,54 @@ +{ + "name": "selinux", + "version": "0.9.0", + "description": "Manages SELinux policy state via LWRP or recipes.", + "long_description": "Description\n===========\n\nProvides recipes for manipulating SELinux policy enforcement state.\n\nRequirements\n============\n\nRHEL family distribution or other Linux system that uses SELinux.\n\n## Platform:\n\nTested on RHEL 5.8, 6.3\n\nNode Attributes\n===============\n\n* `node['selinux']['state']` - The SELinux policy enforcement state.\n The state to set by default, to match the default SELinux state on\n RHEL. Can be \"enforcing\", \"permissive\", \"disabled\"\n\n* `node['selinux']['booleans']` - A hash of SELinux boolean names and the\n values they should be set to. Values can be off, false, or 0 to disable;\n or on, true, or 1 to enable.\n\nResources/Providers\n===================\n\n## selinux\\_state\n\nThe `selinux_state` LWRP is used to manage the SELinux state on the\nsystem. It does this by using the `setenforce` command and rendering\nthe `/etc/selinux/config` file from a template.\n\n### Actions\n\n* `:nothing` - default action, does nothing\n* `:enforcing` - Sets SELinux to enforcing.\n* `:disabled` - Sets SELinux to disabled.\n* `:permissive` - Sets SELinux to permissive.\n\n### Attributes\n\nThe LWRP has no user-settable resource attributes.\n\n### Examples\n\nSimply set SELinux to enforcing or permissive:\n\n selinux_state \"SELinux Enforcing\" do\n action :enforcing\n end\n\n selinux_state \"SELinux Permissive\" do\n action :permissive\n end\n\nThe action here is based on the value of the\n`node['selinux']['state']` attribute, which we convert to lower-case\nand make a symbol to pass to the action.\n\n selinux_state \"SELinux #{node['selinux']['state'].capitalize}\" do\n action node['selinux']['state'].downcase.to_sym\n end\n\nRecipes\n=======\n\nAll the recipes now leverage the LWRP described above.\n\n## default\n\nThe default recipe will use the attribute `node['selinux']['state']`\nin the `selinux_state` LWRP's action. By default, this will be `:enforcing`.\n\n## enforcing\n\nThis recipe will use `:enforcing` as the `selinux_state` action.\n\n## permissive\n\nThis recipe will use `:permissive` as the `selinux_state` action.\n\n## disabled\n\nThis recipe will use `:disabled` as the `selinux_state` action.\n\nUsage\n=====\n\nBy default, this cookbook will have SELinux enforcing by default, as\nthe default recipe uses the `node['selinux']['state']` attribute,\nwhich is \"enforcing.\" This is in line with the policy of enforcing by\ndefault on RHEL family distributions.\n\nThis has complicated considerations when changing the default\nconfiguration of their systems, whether it is with automated\nconfiguration management or manually. Often, third party help forums\nand support sites recommend setting SELinux to \"permissive.\" This\ncookbook can help with that, in two ways.\n\nYou can simply set the attribute in a role applied to the node:\n\n name \"base\"\n description \"Base role applied to all nodes.\"\n default_attributes(\n \"selinux\" => {\n \"state\" => \"permissive\"\n }\n )\n\nOr, you can apply the recipe to the run list (e.g., in a role):\n\n name \"base\"\n description \"Base role applied to all nodes.\"\n run_list(\n \"recipe[selinux::permissive]\",\n )\n\nRoadmap\n=======\n\nAdd LWRP/Libraries for manipulating security contexts for files and\nservices managed by Chef.\n\nLicense and Author\n==================\n\n- Author:: Sean OMeara ()\n- Author:: Joshua Timberman ()\n\nCopyright:: 2011-2012, 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", + "maintainer": "Sam Kottler", + "maintainer_email": "shk@linux.com", + "license": "Apache", + "platforms": { + "redhat": ">= 0.0.0", + "centos": ">= 0.0.0", + "scientific": ">= 0.0.0", + "oracle": ">= 0.0.0", + "amazon": ">= 0.0.0", + "ubuntu": ">= 0.0.0", + "debian": ">= 0.0.0" + }, + "dependencies": { + }, + "recommendations": { + }, + "suggestions": { + }, + "conflicting": { + }, + "providing": { + }, + "replacing": { + }, + "attributes": { + "selinux/state": { + "display_name": "SELinux State", + "description": "The SELinux policy enforcement state.", + "choices": [ + "enforcing", + "permissive", + "disabled" + ], + "recipes": [ + "selinux::default" + ], + "type": "string", + "default": "enforcing" + } + }, + "groupings": { + }, + "recipes": { + "selinux": "Use LWRP with state attribute to manage SELinux state.", + "selinux::enforcing": "Use :enforcing as the action for the selinux_state.", + "selinux::permissive": "Use :permissive as the action for the selinux_state.", + "selinux::disabled": "Use :disabled as the action for the selinux_state." + } +} \ No newline at end of file diff --git a/cookbooks/selinux/providers/state.rb b/cookbooks/selinux/providers/state.rb new file mode 100644 index 0000000..c61556a --- /dev/null +++ b/cookbooks/selinux/providers/state.rb @@ -0,0 +1,75 @@ +# +# Cookbook Name:: selinux +# Provider:: default +# +# Copyright 2011, 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' +include Chef::Mixin::ShellOut + +def whyrun_supported? + true +end + +action :enforcing do + unless @current_resource.state == "enforcing" + execute "selinux-enforcing" do + not_if "getenforce | grep -qx 'Enforcing'" + command "setenforce 1" + end + se_template = render_selinux_template("enforcing") + end +end + +action :disabled do + unless @current_resource.state == "disabled" + execute "selinux-disabled" do + only_if "selinuxenabled" + command "setenforce 0" + end + se_template = render_selinux_template("disabled") + end +end + +action :permissive do + unless @current_resource.state == "permissive" || @current_resource.state == "disabled" + execute "selinux-permissive" do + not_if "getenforce | egrep -qx 'Permissive|Disabled'" + command "setenforce 0" + end + se_template = render_selinux_template("permissive") + end +end + +def load_current_resource + @current_resource = Chef::Resource::SelinuxState.new(new_resource.name) + s = shell_out("getenforce") + @current_resource.state(s.stdout.chomp.downcase) +end + +def render_selinux_template(state) + template "#{state} selinux config" do + path "/etc/selinux/config" + source "sysconfig/selinux.erb" + cookbook "selinux" + if state == 'permissive' + not_if "getenforce | grep -qx 'Disabled'" + end + variables( + :selinux => state, + :selinuxtype => "targeted" + ) + end +end diff --git a/cookbooks/selinux/recipes/_common.rb b/cookbooks/selinux/recipes/_common.rb new file mode 100644 index 0000000..c8a1c7e --- /dev/null +++ b/cookbooks/selinux/recipes/_common.rb @@ -0,0 +1,17 @@ + +case node[:platform_family] +when %r(debian|ubuntu) + package 'selinux-utils' +when 'rhel', 'fedora' + package 'libselinux-utils' +else + # implement support for your platform here! + raise "#{node[:platform_family]} not supported!" +end + +directory '/etc/selinux' do + owner 'root' + group 'root' + mode '0755' + action :create +end diff --git a/cookbooks/selinux/recipes/default.rb b/cookbooks/selinux/recipes/default.rb new file mode 100644 index 0000000..7feb0e5 --- /dev/null +++ b/cookbooks/selinux/recipes/default.rb @@ -0,0 +1,34 @@ +# +# Cookbook Name:: selinux +# Recipe:: default +# +# Copyright 2011, 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 'selinux::_common' + +selinux_state "SELinux #{node['selinux']['state'].capitalize}" do + action node['selinux']['state'].downcase.to_sym +end + +node['selinux']['booleans'].each do |boolean, value| + value = SELinuxServiceHelpers.selinux_bool(value) + unless value.nil? + script "boolean_#{boolean}" do + interpreter "bash" + code "setsebool -P #{boolean} #{value}" + not_if "getsebool #{boolean} |egrep -q \" #{value}\"$" + end + end +end diff --git a/cookbooks/selinux/recipes/disabled.rb b/cookbooks/selinux/recipes/disabled.rb new file mode 100644 index 0000000..904051a --- /dev/null +++ b/cookbooks/selinux/recipes/disabled.rb @@ -0,0 +1,25 @@ +# +# Author:: Sean OMeara () +# Cookbook Name:: selinux +# Recipe:: disabled +# +# Copyright 2011, 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 'selinux::_common' + +selinux_state "SELinux Disabled" do + action :disabled +end diff --git a/cookbooks/selinux/recipes/enforcing.rb b/cookbooks/selinux/recipes/enforcing.rb new file mode 100644 index 0000000..d1be09e --- /dev/null +++ b/cookbooks/selinux/recipes/enforcing.rb @@ -0,0 +1,25 @@ +# +# Author:: Sean OMeara () +# Cookbook Name:: selinux +# Recipe:: enforcing +# +# Copyright 2011, 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 'selinux::_common' + +selinux_state "SELinux Enforcing" do + action :enforcing +end diff --git a/cookbooks/selinux/recipes/permissive.rb b/cookbooks/selinux/recipes/permissive.rb new file mode 100644 index 0000000..6010be3 --- /dev/null +++ b/cookbooks/selinux/recipes/permissive.rb @@ -0,0 +1,25 @@ +# +# Author:: Sean OMeara () +# Cookbook Name:: selinux +# Recipe:: permissive +# +# Copyright 2011, 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 'selinux::_common' + +selinux_state "SELinux Permissive" do + action :permissive +end diff --git a/cookbooks/selinux/resources/state.rb b/cookbooks/selinux/resources/state.rb new file mode 100644 index 0000000..eb7debf --- /dev/null +++ b/cookbooks/selinux/resources/state.rb @@ -0,0 +1,22 @@ +# +# Cookbook Name:: selinux +# Resource:: default +# +# Copyright 2011, 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_action :nothing +actions :enforcing, :disabled, :permissive + +attribute :state, :default => nil diff --git a/cookbooks/selinux/templates/default/sysconfig/selinux.erb b/cookbooks/selinux/templates/default/sysconfig/selinux.erb new file mode 100644 index 0000000..2b393f0 --- /dev/null +++ b/cookbooks/selinux/templates/default/sysconfig/selinux.erb @@ -0,0 +1,11 @@ +# This file controls the state of SELinux on the system. +# SELINUX= can take one of these three values: +# enforcing - SELinux security policy is enforced. +# permissive - SELinux prints warnings instead of enforcing. +# disabled - SELinux is fully disabled. +SELINUX=<%= @selinux %> +# SELINUXTYPE= type of policy in use. Possible values are: +# targeted - Only targeted network daemons are protected. +# strict - Full SELinux protection. +SELINUXTYPE=<%= @selinuxtype %> + diff --git a/cookbooks/7-zip/CHANGELOG.md b/cookbooks/seven_zip/CHANGELOG.md similarity index 61% rename from cookbooks/7-zip/CHANGELOG.md rename to cookbooks/seven_zip/CHANGELOG.md index 183bcf7..4270da1 100644 --- a/cookbooks/7-zip/CHANGELOG.md +++ b/cookbooks/seven_zip/CHANGELOG.md @@ -1,6 +1,6 @@ -7-zip Cookbook CHANGELOG +seven_zip Cookbook CHANGELOG ======================== -This file is used to list changes made in each version of the 7-zip cookbook. +This file is used to list changes made in each version of the seven_zip cookbook. v1.0.2 diff --git a/cookbooks/apt/CONTRIBUTING b/cookbooks/seven_zip/CONTRIBUTING similarity index 87% rename from cookbooks/apt/CONTRIBUTING rename to cookbooks/seven_zip/CONTRIBUTING index e781c97..89ac873 100644 --- a/cookbooks/apt/CONTRIBUTING +++ b/cookbooks/seven_zip/CONTRIBUTING @@ -1,6 +1,6 @@ If you would like to contribute, please open a ticket in JIRA: -* http://tickets.chef.io +* http://tickets.opscode.com Create the ticket in the COOK project and use the cookbook name as the component. @@ -8,12 +8,12 @@ component. For all code contributions, we ask that contributors sign a contributor license agreement (CLA). Instructions may be found here: -* http://wiki.chef.io/display/chef/How+to+Contribute +* http://wiki.opscode.com/display/chef/How+to+Contribute When contributing changes to individual cookbooks, please do not modify the version number in the metadata.rb. Also 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. Chef Software will +cookbook may be merged and released in the same versions. Opscode will handle the version updates during the release process. You are welcome to correct typos or otherwise make updates to documentation in the README. diff --git a/cookbooks/apt/LICENSE b/cookbooks/seven_zip/LICENSE similarity index 100% rename from cookbooks/apt/LICENSE rename to cookbooks/seven_zip/LICENSE diff --git a/cookbooks/7-zip/README.md b/cookbooks/seven_zip/README.md similarity index 84% rename from cookbooks/7-zip/README.md rename to cookbooks/seven_zip/README.md index 4bfd6be..6aba5ad 100644 --- a/cookbooks/7-zip/README.md +++ b/cookbooks/seven_zip/README.md @@ -1,4 +1,4 @@ -7-zip Cookbook +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). @@ -20,13 +20,13 @@ Requirements Attributes ---------- -- `node['7-zip']['home']` - location to install 7-zip files to. default is `%SYSTEMDRIVE%\7-zip` +- `node['seven_zip']['home']` - location to install 7-zip files to. default is `%SYSTEMDRIVE%\7-zip` Usage ----- ### default -Downloads and installs 7-zip to the location specified by `node['7-zip']['home']`. Also ensures `node['7-zip']['home']` is in the system path. +Downloads and installs 7-zip to the location specified by `node['seven_zip']['home']`. Also ensures `node['seven_zip']['home']` is in the system path. License & Authors diff --git a/cookbooks/7-zip/attributes/default.rb b/cookbooks/seven_zip/attributes/default.rb similarity index 54% rename from cookbooks/7-zip/attributes/default.rb rename to cookbooks/seven_zip/attributes/default.rb index adc1903..31a36fa 100644 --- a/cookbooks/7-zip/attributes/default.rb +++ b/cookbooks/seven_zip/attributes/default.rb @@ -1,6 +1,6 @@ # # Author:: Seth Chisamore () -# Cookbook Name:: 7-zip +# Cookbook Name:: seven_zip # Attribute:: default # # Copyright:: Copyright (c) 2011 Opscode, Inc. @@ -19,13 +19,13 @@ # if kernel['machine'] =~ /x86_64/ - default['7-zip']['url'] = "http://downloads.sourceforge.net/sevenzip/7z922-x64.msi" - default['7-zip']['checksum'] = "f09bf515289eea45185a4cc673e3bbc18ce608c55b4cf96e77833435c9cdf3dc" - default['7-zip']['package_name'] = "7-Zip 9.22 (x64 edition)" + default['seven_zip']['url'] = "http://www.7-zip.org/a/7z920-x64.msi" + default['seven_zip']['checksum'] = "62df458bc521001cd9a947643a84810ecbaa5a16b5c8e87d80df8e34c4a16fe2" + default['seven_zip']['package_name'] = "7z920-x64.msi" else - default['7-zip']['url'] = "http://downloads.sourceforge.net/sevenzip/7z922.msi" - default['7-zip']['checksum'] = "86df264d22c3dd3ab80cb55a118da2d41bdd95c2db2cd09a6bbdf48f069e3d7a" - default['7-zip']['package_name'] = "7-Zip 9.22" + default['seven_zip']['url'] = "http://www.7-zip.org/a/7z920.msi" + default['seven_zip']['checksum'] = "fe4807b4698ec89f82de7d85d32deaa4c772fc871537e31fb0fccf4473455cb8" + default['seven_zip']['package_name'] = "7z920.msi" end -default['7-zip']['home'] = "#{ENV['SYSTEMDRIVE']}\\7-zip" +default['seven_zip']['home'] = "#{ENV['SYSTEMDRIVE']}\\7-zip" diff --git a/cookbooks/seven_zip/metadata.json b/cookbooks/seven_zip/metadata.json new file mode 100644 index 0000000..5540f6a --- /dev/null +++ b/cookbooks/seven_zip/metadata.json @@ -0,0 +1,41 @@ +{ + "name": "seven_zip", + "description": "Installs/Configures the 7-zip file archiver", + "long_description": "seven_zip Cookbook\n==============\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).\n\n\nRequirements\n------------\n### Platform\n- Windows XP\n- Windows Vista\n- Windows Server 2003 R2\n- Windows 7\n- Windows Server 2008 (R1, R2)\n- Windows 8\n- Windows Server 2012\n\n### Cookbooks\n- windows\n\n\nAttributes\n----------\n- `node['seven_zip']['home']` - location to install 7-zip files to. default is `%SYSTEMDRIVE%\\7-zip`\n\n\nUsage\n-----\n### default\nDownloads and installs 7-zip to the location specified by `node['seven_zip']['home']`. Also ensures `node['seven_zip']['home']` is in the system path.\n\n\nLicense & Authors\n-----------------\n- Author:: Seth Chisamore ()\n\n```text\nCopyright:: 2011, Opscode, 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": "Opscode, Inc.", + "maintainer_email": "cookbooks@opscode.com", + "license": "Apache 2.0", + "platforms": { + "windows": ">= 0.0.0" + }, + "dependencies": { + "windows": ">= 1.2.2" + }, + "recommendations": { + + }, + "suggestions": { + + }, + "conflicting": { + + }, + "providing": { + + }, + "replacing": { + + }, + "attributes": { + + }, + "groupings": { + + }, + "recipes": { + + }, + "version": "1.0.4", + "source_url": "", + "issues_url": "" +} diff --git a/cookbooks/7-zip/metadata.rb b/cookbooks/seven_zip/metadata.rb similarity index 85% rename from cookbooks/7-zip/metadata.rb rename to cookbooks/seven_zip/metadata.rb index fa83e9f..2c5305d 100644 --- a/cookbooks/7-zip/metadata.rb +++ b/cookbooks/seven_zip/metadata.rb @@ -1,10 +1,10 @@ -name "7-zip" +name "seven_zip" maintainer "Opscode, Inc." maintainer_email "cookbooks@opscode.com" license "Apache 2.0" description "Installs/Configures the 7-zip file archiver" long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) -version "1.0.2" +version "1.0.4" supports "windows" depends "windows", ">= 1.2.2" diff --git a/cookbooks/seven_zip/providers/archive.rb b/cookbooks/seven_zip/providers/archive.rb new file mode 100644 index 0000000..2b5653c --- /dev/null +++ b/cookbooks/seven_zip/providers/archive.rb @@ -0,0 +1,48 @@ +# +# Author:: Shawn Neal () +# Cookbook Name:: seven_zip +# Provider:: archive +# +# Copyright:: 2013, 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' + +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.exists?(@new_resource.path) + local_source = cached_file(@new_resource.source, @new_resource.checksum) + cmd = "#{seven_zip_exe} x" + cmd << " -y" if @new_resource.overwrite + cmd << " -o#{win_friendly_path(@new_resource.path)}" + cmd << " #{local_source}" + Chef::Log.debug(cmd) + shell_out!(cmd) + end +end + + +def seven_zip_exe() + Chef::Log.debug("seven zip home: #{node['seven_zip']['home']}") + win_friendly_path(::File.join(node['seven_zip']['home'], '7z.exe')) +end diff --git a/cookbooks/7-zip/recipes/default.rb b/cookbooks/seven_zip/recipes/default.rb similarity index 73% rename from cookbooks/7-zip/recipes/default.rb rename to cookbooks/seven_zip/recipes/default.rb index 155cbb6..299f556 100644 --- a/cookbooks/7-zip/recipes/default.rb +++ b/cookbooks/seven_zip/recipes/default.rb @@ -1,6 +1,6 @@ # # Author:: Seth Chisamore () -# Cookbook Name:: 7-zip +# Cookbook Name:: seven_zip # Recipe:: default # # Copyright 2011, Opscode, Inc. @@ -18,14 +18,14 @@ # limitations under the License. # -windows_package node['7-zip']['package_name'] do - source node['7-zip']['url'] - checksum node['7-zip']['checksum'] - options "INSTALLDIR=\"#{node['7-zip']['home']}\"" +windows_package node['seven_zip']['package_name'] do + source node['seven_zip']['url'] + checksum node['seven_zip']['checksum'] + options "INSTALLDIR=\"#{node['seven_zip']['home']}\"" action :install end # update path -windows_path node['7-zip']['home'] do +windows_path "#{node['seven_zip']['home']}" do action :add end diff --git a/cookbooks/seven_zip/resources/archive.rb b/cookbooks/seven_zip/resources/archive.rb new file mode 100644 index 0000000..cc36eed --- /dev/null +++ b/cookbooks/seven_zip/resources/archive.rb @@ -0,0 +1,28 @@ +# +# Author:: Shawn Neal () +# Cookbook Name:: seven_zip +# Resource:: archive +# +# Copyright:: 2013, 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 diff --git a/cookbooks/smf/metadata.json b/cookbooks/smf/metadata.json index c18edb3..d5aba81 100644 --- a/cookbooks/smf/metadata.json +++ b/cookbooks/smf/metadata.json @@ -12,21 +12,37 @@ "rbac": ">= 1.0.1" }, "recommendations": { + }, "suggestions": { "resource-control": ">= 0.0.0" }, "conflicting": { + }, "providing": { + }, "replacing": { + }, "attributes": { + }, "groupings": { + }, "recipes": { + }, - "version": "2.2.7" -} \ No newline at end of file + "version": "2.2.8", + "source_url": "", + "issues_url": "", + "privacy": false, + "chef_versions": [ + + ], + "ohai_versions": [ + + ] +} diff --git a/cookbooks/smf/metadata.rb b/cookbooks/smf/metadata.rb index 9019fa5..94a4751 100644 --- a/cookbooks/smf/metadata.rb +++ b/cookbooks/smf/metadata.rb @@ -4,7 +4,7 @@ maintainer_email 'sax@livinginthepast.org' license 'MIT' description 'A light weight resource provider (LWRP) for SMF (Service Management Facility)' long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) -version '2.2.7' +version '2.2.8' supports 'smartos' diff --git a/cookbooks/smf/resources/default.rb b/cookbooks/smf/resources/default.rb index e5dc0f0..6224e19 100644 --- a/cookbooks/smf/resources/default.rb +++ b/cookbooks/smf/resources/default.rb @@ -36,7 +36,7 @@ attribute :duration, kind_of: String, default: 'contract', regex: '(contract|wai attribute :ignore, kind_of: [Array, NilClass], default: nil attribute :fmri, kind_of: String, default: nil -attribute :stability, kind_of: String, equal_to: %(Standard Stable Evolving Unstable External Obsolete), +attribute :stability, kind_of: String, equal_to: %w(Standard Stable Evolving Unstable External Obsolete), default: 'Evolving' attribute :property_groups, kind_of: Hash, default: {} diff --git a/cookbooks/sudo/CHANGELOG.md b/cookbooks/sudo/CHANGELOG.md index 6cfa2b6..4f3bce2 100644 --- a/cookbooks/sudo/CHANGELOG.md +++ b/cookbooks/sudo/CHANGELOG.md @@ -1,119 +1,116 @@ -v2.7.1 (2014-09-18) -------------------- -- [#53] - removed doublespace from sudoer.erb template +# sudo Cookbook CHANGELOG +This file is used to list changes made in each version of the sudo cookbook. -v2.7.0 (2014-08-08) -------------------- +## v2.9.0 (2016-02-07) +- Updated the provider to avoid writing out config files with periods in the filename when a user has a period in their name as these are skipped by the sudo package. A sudo config for invalid.user will write out a config named invalid_user now. + +## v2.8.0 (2016-02-04) +- Added a new attribute to the recipe and provider for adding SETENV to sudoer config +- Updated development deps to the latest version +- Setup test kitchen to run in Travis with kitchen-docker +- Expanded the kitchen.yml config to include additional platforms +- Renamed the test recipe from fake to test +- Updated the testing and contributing docs to the latest +- Added maintainers.toml and maitainers.md +- Added a chefignore file to limit which files get uploaded to the chef server +- Added long_description to the metadata.rb +- Added source_url and issues_url for Supermarket to the metadata.rb +- Resolved all Rubocop warnings +- Updated the Chefspec to the 4.x format +- Removed kitchen cloud testing configs and gem deps +- Removed the Guardfile and the gem deps + +## v2.7.2 (2015-07-10) +- Adding support for keep_env +- misc cleanup + +## v2.7.1 (2014-09-18) +- [#53] - removed double space from sudoer.erb template + +## v2.7.0 (2014-08-08) - [#44] Add basic ChefSpec matchers -v2.6.0 (2014-05-15) -------------------- +## v2.6.0 (2014-05-15) - [COOK-4612] Add support for the command alias (Cmnd_Alias) directive - [COOK-4637] - handle duplicate resources in LWRP - -v2.5.2 (2014-02-27) -------------------- +## v2.5.2 (2014-02-27) Bumping version for toolchain sanity - -v2.5.0 (2014-02-27) -------------------- +## v2.5.0 (2014-02-27) Bumping to 2.5.0 - -v2.4.2 (2014-02-27) -------------------- +## v2.4.2 (2014-02-27) [COOK-4350] - Fix issue with "Defaults" line in sudoer.erb - -v2.4.0 (2014-02-18) -------------------- +## v2.4.0 (2014-02-18) ### Bug -- **[COOK-4225](https://tickets.opscode.com/browse/COOK-4225)** - Mac OS X: /etc/sudoers: syntax error when include_sudoers_d is true +- **[COOK-4225](https://tickets.chef.io/browse/COOK-4225)** - Mac OS X: /etc/sudoers: syntax error when include_sudoers_d is true ### Improvement -- **[COOK-4014](https://tickets.opscode.com/browse/COOK-4014)** - It should be possible to remove the 'sysadmin' group setting from /etc/sudoers -- **[COOK-3643](https://tickets.opscode.com/browse/COOK-3643)** - FreeBSD support for sudo cookbook +- **[COOK-4014](https://tickets.chef.io/browse/COOK-4014)** - It should be possible to remove the 'sysadmin' group setting from /etc/sudoers +- **[COOK-3643](https://tickets.chef.io/browse/COOK-3643)** - FreeBSD support for sudo cookbook ### New Feature -- **[COOK-3409](https://tickets.opscode.com/browse/COOK-3409)** - enhance sudo lwrp's default template to allow defining default user parameters +- **[COOK-3409](https://tickets.chef.io/browse/COOK-3409)** - enhance sudo lwrp's default template to allow defining default user parameters - -v2.3.0 ------- +## v2.3.0 ### Improvement -- **[COOK-3843](https://tickets.opscode.com/browse/COOK-3843)** - Make cookbook 'sudo' compatible with Mac OS X +- **[COOK-3843](https://tickets.chef.io/browse/COOK-3843)** - Make cookbook 'sudo' compatible with Mac OS X - -v2.2.2 ------- +## v2.2.2 ### Improvement -- **[COOK-3653](https://tickets.opscode.com/browse/COOK-3653)** - Change template attribute to kind_of String -- **[COOK-3572](https://tickets.opscode.com/browse/COOK-3572)** - Add Test Kitchen, Specs, and Travis CI +- **[COOK-3653](https://tickets.chef.io/browse/COOK-3653)** - Change template attribute to kind_of String +- **[COOK-3572](https://tickets.chef.io/browse/COOK-3572)** - Add Test Kitchen, Specs, and Travis CI ### Bug -- **[COOK-3610](https://tickets.opscode.com/browse/COOK-3610)** - Document "Runas" attribute not described in the LWRP Attributes section -- **[COOK-3431](https://tickets.opscode.com/browse/COOK-3431)** - Validate correctly with `visudo` +- **[COOK-3610](https://tickets.chef.io/browse/COOK-3610)** - Document "Runas" attribute not described in the LWRP Attributes section +- **[COOK-3431](https://tickets.chef.io/browse/COOK-3431)** - Validate correctly with `visudo` - -v2.2.0 ------- +## v2.2.0 ### New Feature -- **[COOK-3056](https://tickets.opscode.com/browse/COOK-3056)** - Allow custom sudoers config prefix +- **[COOK-3056](https://tickets.chef.io/browse/COOK-3056)** - Allow custom sudoers config prefix -v2.1.4 ------- +## v2.1.4 This is a bugfix for 11.6.0 compatibility, as we're not monkey-patching Erubis::Context. ### Bug - [COOK-3399]: Remove node attribute in comment of sudoers templates -v2.1.2 ------- +## v2.1.2 ### Bug - [COOK-2388]: Chef::ShellOut is deprecated, please use Mixlib::ShellOut - [COOK-2814]: Incorrect syntax in README example -v2.1.0 ------- -* [COOK-2388] - Chef::ShellOut is deprecated, please use Mixlib::ShellOut -* [COOK-2427] - unable to install users cookbook in chef 11 -* [COOK-2814] - Incorrect syntax in README example +## v2.1.0 +- [COOK-2388] - Chef::ShellOut is deprecated, please use Mixlib::ShellOut +- [COOK-2427] - unable to install users cookbook in chef 11 +- [COOK-2814] - Incorrect syntax in README example -v2.0.4 ------- -* [COOK-2078] - syntax highlighting README on GitHub flavored markdown -* [COOK-2119] - LWRP template doesn't support multiple commands in a single block. +## v2.0.4 +- [COOK-2078] - syntax highlighting README on GitHub flavored markdown +- [COOK-2119] - LWRP template doesn't support multiple commands in a single block. -v2.0.2 ------- -* [COOK-2109] - lwrp uses incorrect action on underlying file resource. +## v2.0.2 +- [COOK-2109] - lwrp uses incorrect action on underlying file resource. -v2.0.0 ------- +## v2.0.0 This is a major release because the LWRP's "nopasswd" attribute is changed from true to false, to match the passwordless attribute in the attributes file. This requires a change to people's LWRP use. +- [COOK-2085] - Incorrect default value in the sudo LWRP's nopasswd attribute -* [COOK-2085] - Incorrect default value in the sudo LWRP's nopasswd attribute +## v1.3.0 +- [COOK-1892] - Revamp sudo cookbook and LWRP +- [COOK-2022] - add an attribute for setting /etc/sudoers Defaults -v1.3.0 ------- -* [COOK-1892] - Revamp sudo cookbook and LWRP -* [COOK-2022] - add an attribute for setting /etc/sudoers Defaults +## v1.2.2 +- [COOK-1628] - set host in sudo lwrp -v1.2.2 ------- -* [COOK-1628] - set host in sudo lwrp +## v1.2.0 +- [COOK-1314] - default package action is now :install instead of :upgrade +- [COOK-1549] - Preserve SSH agent credentials upon sudo using an attribute -v1.2.0 ------- -* [COOK-1314] - default package action is now :install instead of :upgrade -* [COOK-1549] - Preserve SSH agent credentials upon sudo using an attribute +## v1.1.0 +- [COOK-350] - LWRP to manage sudo files via include dir (/etc/sudoers.d) -v1.1.0 ------- -* [COOK-350] - LWRP to manage sudo files via includedir (/etc/sudoers.d) - -v1.0.2 ------- -* [COOK-903] - freebsd support +## v1.0.2 +- [COOK-903] - freebsd support diff --git a/cookbooks/sudo/CONTRIBUTING.md b/cookbooks/sudo/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/sudo/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/sudo/MAINTAINERS.md b/cookbooks/sudo/MAINTAINERS.md new file mode 100644 index 0000000..c6a51ae --- /dev/null +++ b/cookbooks/sudo/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 +* [Tim Smith](https://github.com/tas50) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Sean OMeara](https://github.com/someara) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) diff --git a/cookbooks/sudo/README.md b/cookbooks/sudo/README.md index e79c208..f609b7d 100644 --- a/cookbooks/sudo/README.md +++ b/cookbooks/sudo/README.md @@ -1,30 +1,34 @@ -sudo cookbook -============= -[![Build Status](https://secure.travis-ci.org/opscode-cookbooks/sudo.png?branch=master)](http://travis-ci.org/opscode-cookbooks/sudo) +# sudo cookbook +[![Build Status](https://travis-ci.org/chef-cookbooks/sudo.svg?branch=master)](http://travis-ci.org/chef-cookbooks/sudo) [![Cookbook Version](https://img.shields.io/cookbook/v/sudo.svg)](https://supermarket.chef.io/cookbooks/sudo) The Chef `sudo` cookbook installs the `sudo` package and configures the `/etc/sudoers` file. It also exposes an LWRP for adding and managing sudoers. +## Requirements +### Platforms +- Debian/Ubuntu +- RHEL/CentOS/Scientific/Amazon/Oracle +- FreeBSD +- Mac OS X -Requirements ------------- -The platform has a package named `sudo` and the `sudoers` file is `/etc/sudoers`. +### Chef +- Chef 11+ +### Cookbooks +- None -Attributes ----------- +## Attributes - `node['authorization']['sudo']['groups']` - groups to enable sudo access (default: `[ "sysadmin" ]`) - `node['authorization']['sudo']['users']` - users to enable sudo access (default: `[]`) - `node['authorization']['sudo']['passwordless']` - use passwordless sudo (default: `false`) -- `node['authorization']['sudo']['include_sudoers_d']` - include and manager `/etc/sudoers.d` (default: `false`) +- `node['authorization']['sudo']['include_sudoers_d']` - include and manage `/etc/sudoers.d` (default: `false`) - `node['authorization']['sudo']['agent_forwarding']` - preserve `SSH_AUTH_SOCK` when sudoing (default: `false`) - `node['authorization']['sudo']['sudoers_defaults']` - Array of `Defaults` entries to configure in `/etc/sudoers` +- `node['authorization']['sudo']['setenv']` - Whether to permit preserving of environment with `sudo -E` (default: `false`) - -Usage ------ -#### Attributes +## Usage +### Attributes To use attributes for defining sudoers, set the attributes above on the node (or role) itself: ```json @@ -56,24 +60,23 @@ default_attributes( **Note that the template for the sudoers file has the group "sysadmin" with ALL:ALL permission, though the group by default does not exist.** -#### Sudoers Defaults +### Sudoers Defaults +Configure a node attribute, `node['authorization']['sudo']['sudoers_defaults']` as an array of `Defaults` entries to configure in `/etc/sudoers`. A list of examples for common platforms is listed below: -Configure a node attribute, -`node['authorization']['sudo']['sudoers_defaults']` as an array of -`Defaults` entries to configure in `/etc/sudoers`. A list of examples -for common platforms is listed below: +_Debian_ -*Debian* ```ruby node.default['authorization']['sudo']['sudoers_defaults'] = ['env_reset'] ``` -*Ubuntu 10.04* +_Ubuntu 10.04_ + ```ruby node.default['authorization']['sudo']['sudoers_defaults'] = ['env_reset'] ``` -*Ubuntu 12.04* +_Ubuntu 12.04_ + ```ruby node.default['authorization']['sudo']['sudoers_defaults'] = [ 'env_reset', @@ -81,7 +84,8 @@ node.default['authorization']['sudo']['sudoers_defaults'] = [ ] ``` -*FreeBSD* +_FreeBSD_ + ```ruby node.default['authorization']['sudo']['sudoers_defaults'] = [ 'env_reset', @@ -89,8 +93,7 @@ node.default['authorization']['sudo']['sudoers_defaults'] = [ ] ``` -*RHEL family 5.x* -The version of sudo in RHEL 5 may not support `+=`, as used in `env_keep`, so its a single string. +_RHEL family 5.x_ The version of sudo in RHEL 5 may not support `+=`, as used in `env_keep`, so its a single string. ```ruby node.default['authorization']['sudo']['sudoers_defaults'] = [ @@ -105,7 +108,8 @@ node.default['authorization']['sudo']['sudoers_defaults'] = [ ] ``` -*RHEL family 6.x* +_RHEL family 6.x_ + ```ruby node.default['authorization']['sudo']['sudoers_defaults'] = [ '!visiblepw', @@ -121,7 +125,8 @@ node.default['authorization']['sudo']['sudoers_defaults'] = [ ] ``` -*Mac OS X* +_Mac OS X_ + ```ruby node.default['authorization']['sudo']['sudoers_defaults'] = [ 'env_reset', @@ -139,13 +144,12 @@ node.default['authorization']['sudo']['sudoers_defaults'] = [ ] ``` -#### LWRP +### LWRP **Note** Sudo version 1.7.2 or newer is required to use the sudo LWRP as it relies on the "#includedir" directive introduced in version 1.7.2. The recipe does not enforce installing the version. To use this LWRP, set `node['authorization']['sudo']['include_sudoers_d']` to `true`. There are two ways for rendering a sudoer-fragment using this LWRP: - - 1. Using the built-in template - 2. Using a custom, cookbook-level template +1. Using the built-in template +2. Using a custom, cookbook-level template Both methods will create the `/etc/sudoers.d/#{username}` file with the correct permissions. @@ -177,7 +181,7 @@ In either case, the following file would be generated in `/etc/sudoers.d/tomcat` %tomcat ALL=(app_user) /etc/init.d/tomcat restart ``` -##### LWRP Attributes +#### LWRP Attributes @@ -238,6 +242,24 @@ case it is not already + + + + + + + + + + + + + + + + + + @@ -249,50 +271,49 @@ case it is not already **If you use the template attribute, all other attributes will be ignored except for the variables attribute.** - -Development ------------ +## Development This section details "quick development" steps. For a detailed explanation, see [[Contributing.md]]. +- Clone this repository from GitHub: -1. Clone this repository from GitHub: + ``` + $ git clone git@github.com:chef-cookbooks/sudo.git + ``` - $ git clone git@github.com:opscode-cookbooks/sudo.git +- Create a git branch -2. Create a git branch + ``` + $ git checkout -b my_bug_fix + ``` - $ git checkout -b my_bug_fix +- Install dependencies: -3. Install dependencies: + ``` + $ bundle install + ``` - $ 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` +- Make your changes/patches/fixes, committing appropiately +- **Write tests** +- 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 + - 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:** Bryan W. Berry [bryan.berry@gmail.com](mailto:bryan.berry@gmail.com) +**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io)) -License and Authors -------------------- -- Author:: Bryan W. Berry -- Author:: Adam Jacob -- Author:: Seth Chisamore -- Author:: Seth Vargo - -```text -Copyright 2009-2012, Opscode, Inc. +**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 diff --git a/cookbooks/sudo/attributes/default.rb b/cookbooks/sudo/attributes/default.rb index 6b7ce50..d1bd74b 100644 --- a/cookbooks/sudo/attributes/default.rb +++ b/cookbooks/sudo/attributes/default.rb @@ -2,7 +2,7 @@ # Cookbook Name:: sudo # Attribute File:: default # -# Copyright 2008-2013, Opscode, Inc. +# 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. @@ -20,16 +20,19 @@ default['authorization']['sudo']['groups'] = ['sysadmin'] default['authorization']['sudo']['users'] = [] default['authorization']['sudo']['passwordless'] = false +default['authorization']['sudo']['setenv'] = false default['authorization']['sudo']['include_sudoers_d'] = false default['authorization']['sudo']['agent_forwarding'] = false default['authorization']['sudo']['sudoers_defaults'] = ['!lecture,tty_tickets,!fqdn'] default['authorization']['sudo']['command_aliases'] = [] +default['authorization']['sudo']['env_keep_add'] = [] +default['authorization']['sudo']['env_keep_subtract'] = [] -case node['platform_family'] -when 'smartos' - default['authorization']['sudo']['prefix'] = '/opt/local/etc' -when 'freebsd' - default['authorization']['sudo']['prefix'] = '/usr/local/etc' -else - default['authorization']['sudo']['prefix'] = '/etc' -end +default['authorization']['sudo']['prefix'] = case node['platform_family'] + when 'smartos' + '/opt/local/etc' + when 'freebsd' + '/usr/local/etc' + else + '/etc' + end diff --git a/cookbooks/sudo/metadata.json b/cookbooks/sudo/metadata.json index c911bc8..75479c1 100644 --- a/cookbooks/sudo/metadata.json +++ b/cookbooks/sudo/metadata.json @@ -1,71 +1 @@ -{ - "name": "sudo", - "version": "2.7.1", - "description": "Installs sudo and configures /etc/sudoers", - "long_description": "", - "maintainer": "Opscode, Inc.", - "maintainer_email": "cookbooks@opscode.com", - "license": "Apache 2.0", - "platforms": { - "redhat": ">= 0.0.0", - "centos": ">= 0.0.0", - "fedora": ">= 0.0.0", - "ubuntu": ">= 0.0.0", - "debian": ">= 0.0.0", - "freebsd": ">= 0.0.0", - "mac_os_x": ">= 0.0.0" - }, - "dependencies": { - }, - "recommendations": { - }, - "suggestions": { - }, - "conflicting": { - }, - "providing": { - }, - "replacing": { - }, - "attributes": { - "authorization": { - "display_name": "Authorization", - "description": "Hash of Authorization attributes", - "type": "hash" - }, - "authorization/sudo": { - "display_name": "Authorization Sudoers", - "description": "Hash of Authorization/Sudo attributes", - "type": "hash" - }, - "authorization/sudo/users": { - "display_name": "Sudo Users", - "description": "Users who are allowed sudo ALL", - "type": "array", - "default": "" - }, - "authorization/sudo/groups": { - "display_name": "Sudo Groups", - "description": "Groups who are allowed sudo ALL", - "type": "array", - "default": "" - }, - "authorization/sudo/passwordless": { - "display_name": "Passwordless Sudo", - "description": "", - "type": "string", - "default": "false" - }, - "authorization/sudo/include_sudoers_d": { - "display_name": "Include sudoers.d", - "description": "Whether to create the sudoers.d includedir", - "type": "string", - "default": "false" - } - }, - "groupings": { - }, - "recipes": { - "sudo": "Installs sudo and configures /etc/sudoers" - } -} \ No newline at end of file +{"name":"sudo","version":"2.9.0","description":"Installs sudo and configures /etc/sudoers","long_description":"# sudo cookbook\n[![Build Status](https://travis-ci.org/chef-cookbooks/sudo.svg?branch=master)](http://travis-ci.org/chef-cookbooks/sudo) [![Cookbook Version](https://img.shields.io/cookbook/v/sudo.svg)](https://supermarket.chef.io/cookbooks/sudo)\n\nThe Chef `sudo` cookbook installs the `sudo` package and configures the `/etc/sudoers` file.\n\nIt also exposes an LWRP for adding and managing sudoers.\n\n## Requirements\n### Platforms\n- Debian/Ubuntu\n- RHEL/CentOS/Scientific/Amazon/Oracle\n- FreeBSD\n- Mac OS X\n\n### Chef\n- Chef 11+\n\n### Cookbooks\n- None\n\n## Attributes\n- `node['authorization']['sudo']['groups']` - groups to enable sudo access (default: `[ \"sysadmin\" ]`)\n- `node['authorization']['sudo']['users']` - users to enable sudo access (default: `[]`)\n- `node['authorization']['sudo']['passwordless']` - use passwordless sudo (default: `false`)\n- `node['authorization']['sudo']['include_sudoers_d']` - include and manage `/etc/sudoers.d` (default: `false`)\n- `node['authorization']['sudo']['agent_forwarding']` - preserve `SSH_AUTH_SOCK` when sudoing (default: `false`)\n- `node['authorization']['sudo']['sudoers_defaults']` - Array of `Defaults` entries to configure in `/etc/sudoers`\n- `node['authorization']['sudo']['setenv']` - Whether to permit preserving of environment with `sudo -E` (default: `false`)\n\n## Usage\n### Attributes\nTo use attributes for defining sudoers, set the attributes above on the node (or role) itself:\n\n```json\n{\n \"default_attributes\": {\n \"authorization\": {\n \"sudo\": {\n \"groups\": [\"admin\", \"wheel\", \"sysadmin\"],\n \"users\": [\"jerry\", \"greg\"],\n \"passwordless\": \"true\"\n }\n }\n }\n}\n```\n\n```ruby\n# roles/example.rb\ndefault_attributes(\n \"authorization\" => {\n \"sudo\" => {\n \"groups\" => [\"admin\", \"wheel\", \"sysadmin\"],\n \"users\" => [\"jerry\", \"greg\"],\n \"passwordless\" => true\n }\n }\n)\n```\n\n**Note that the template for the sudoers file has the group \"sysadmin\" with ALL:ALL permission, though the group by default does not exist.**\n\n### Sudoers Defaults\nConfigure a node attribute, `node['authorization']['sudo']['sudoers_defaults']` as an array of `Defaults` entries to configure in `/etc/sudoers`. A list of examples for common platforms is listed below:\n\n_Debian_\n\n```ruby\nnode.default['authorization']['sudo']['sudoers_defaults'] = ['env_reset']\n```\n\n_Ubuntu 10.04_\n\n```ruby\nnode.default['authorization']['sudo']['sudoers_defaults'] = ['env_reset']\n```\n\n_Ubuntu 12.04_\n\n```ruby\nnode.default['authorization']['sudo']['sudoers_defaults'] = [\n 'env_reset',\n 'secure_path=\"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"'\n]\n```\n\n_FreeBSD_\n\n```ruby\nnode.default['authorization']['sudo']['sudoers_defaults'] = [\n 'env_reset',\n 'secure_path=\"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"'\n]\n```\n\n_RHEL family 5.x_ The version of sudo in RHEL 5 may not support `+=`, as used in `env_keep`, so its a single string.\n\n```ruby\nnode.default['authorization']['sudo']['sudoers_defaults'] = [\n '!visiblepw',\n 'env_reset',\n 'env_keep = \"COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR \\\n LS_COLORS MAIL PS1 PS2 QTDIR USERNAME \\\n LANG LC_ADDRESS LC_CTYPE LC_COLLATE LC_IDENTIFICATION \\\n LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC \\\n LC_PAPER LC_TELEPHONE LC_TIME LC_ALL LANGUAGE LINGUAS \\\n _XKB_CHARSET XAUTHORITY\"'\n]\n```\n\n_RHEL family 6.x_\n\n```ruby\nnode.default['authorization']['sudo']['sudoers_defaults'] = [\n '!visiblepw',\n 'env_reset',\n 'env_keep = \"COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR LS_COLORS\"',\n 'env_keep += \"MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE\"',\n 'env_keep += \"LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES\"',\n 'env_keep += \"LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE\"',\n 'env_keep += \"LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY\"',\n 'env_keep += \"HOME\"',\n 'always_set_home',\n 'secure_path = /sbin:/bin:/usr/sbin:/usr/bin'\n]\n```\n\n_Mac OS X_\n\n```ruby\nnode.default['authorization']['sudo']['sudoers_defaults'] = [\n 'env_reset',\n 'env_keep += \"BLOCKSIZE\"',\n 'env_keep += \"COLORFGBG COLORTERM\"',\n 'env_keep += \"__CF_USER_TEXT_ENCODING\"',\n 'env_keep += \"CHARSET LANG LANGUAGE LC_ALL LC_COLLATE LC_CTYPE\"',\n 'env_keep += \"LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME\"',\n 'env_keep += \"LINES COLUMNS\"',\n 'env_keep += \"LSCOLORS\"',\n 'env_keep += \"TZ\"',\n 'env_keep += \"DISPLAY XAUTHORIZATION XAUTHORITY\"',\n 'env_keep += \"EDITOR VISUAL\"',\n 'env_keep += \"HOME MAIL\"'\n]\n```\n\n### LWRP\n**Note** Sudo version 1.7.2 or newer is required to use the sudo LWRP as it relies on the \"#includedir\" directive introduced in version 1.7.2. The recipe does not enforce installing the version. To use this LWRP, set `node['authorization']['sudo']['include_sudoers_d']` to `true`.\n\nThere are two ways for rendering a sudoer-fragment using this LWRP:\n1. Using the built-in template\n2. Using a custom, cookbook-level template\n\nBoth methods will create the `/etc/sudoers.d/#{username}` file with the correct permissions.\n\nThe LWRP also performs **fragment validation**. If a sudoer-fragment is not valid, the Chef run will throw an exception and fail. This ensures that your sudoers file is always valid and cannot become corrupt (from this cookbook).\n\nExample using the built-in template:\n\n```ruby\nsudo 'tomcat' do\n user \"%tomcat\" # or a username\n runas 'app_user' # or 'app_user:tomcat'\n commands ['/etc/init.d/tomcat restart']\nend\n```\n\n```ruby\nsudo 'tomcat' do\n template 'my_tomcat.erb' # local cookbook template\n variables :cmds => ['/etc/init.d/tomcat restart']\nend\n```\n\nIn either case, the following file would be generated in `/etc/sudoers.d/tomcat`\n\n```bash\n# This file is managed by Chef for node.example.com\n# Do NOT modify this file directly.\n\n%tomcat ALL=(app_user) /etc/init.d/tomcat restart\n```\n\n#### LWRP Attributes\n
['!requiretty','env_reset']
setenvwhether to permit the preserving of environment with `sudo -E`true
env_keep_addarray of strings to add to env_keep['HOME', 'MY_ENV_VAR MY_OTHER_ENV_VAR']
env_keep_subtractarray of strings to remove from env_keep['DISPLAY', 'MY_SECURE_ENV_VAR']
variables the variables to pass to the custom template
\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 \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
namename of the `/etc/sudoers.d` filerestart-tomcatcurrent resource name
commandsarray of commands this sudoer can execute['/etc/init.d/tomcat restart']['ALL']
groupgroup to provide sudo privileges to, except `%` is prepended to the name in\ncase it is not already%admin
nopasswdsupply a password to invoke sudotruefalse
runasUser the command(s) can be run asrootALL
templatethe erb template to render instead of the defaultrestart-tomcat.erb
useruser to provide sudo privileges totomcat
defaultsarray of defaults this user has['!requiretty','env_reset']
setenvwhether to permit the preserving of environment with `sudo -E`true
env_keep_addarray of strings to add to env_keep['HOME', 'MY_ENV_VAR MY_OTHER_ENV_VAR']
env_keep_subtractarray of strings to remove from env_keep['DISPLAY', 'MY_SECURE_ENV_VAR']
variablesthe variables to pass to the custom template:commands => ['/etc/init.d/tomcat restart']
\n\n**If you use the template attribute, all other attributes will be ignored except for the variables attribute.**\n\n## Development\nThis section details \"quick development\" steps. For a detailed explanation, see [[Contributing.md]].\n- Clone this repository from GitHub:\n\n ```\n $ git clone git@github.com:chef-cookbooks/sudo.git\n ```\n\n- Create a git branch\n\n ```\n $ git checkout -b my_bug_fix\n ```\n\n- Install dependencies:\n\n ```\n $ bundle install\n ```\n\n- Make your changes/patches/fixes, committing appropiately\n- **Write tests**\n- 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\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## License & Authors\n**Author:** Bryan W. Berry [bryan.berry@gmail.com](mailto:bryan.berry@gmail.com)\n\n**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io))\n\n**Copyright:** 2008-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":{"redhat":">= 0.0.0","centos":">= 0.0.0","fedora":">= 0.0.0","ubuntu":">= 0.0.0","debian":">= 0.0.0","freebsd":">= 0.0.0","mac_os_x":">= 0.0.0","oracle":">= 0.0.0","scientific":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{"authorization":{"display_name":"Authorization","description":"Hash of Authorization attributes","type":"hash"},"authorization/sudo":{"display_name":"Authorization Sudoers","description":"Hash of Authorization/Sudo attributes","type":"hash"},"authorization/sudo/users":{"display_name":"Sudo Users","description":"Users who are allowed sudo ALL","type":"array","default":""},"authorization/sudo/groups":{"display_name":"Sudo Groups","description":"Groups who are allowed sudo ALL","type":"array","default":""},"authorization/sudo/passwordless":{"display_name":"Passwordless Sudo","description":"","type":"string","default":"false"},"authorization/sudo/include_sudoers_d":{"display_name":"Include sudoers.d","description":"Whether to create the sudoers.d includedir","type":"string","default":"false"},"authorization/sudo/setenv":{"display_name":"SetEnv Sudo","description":"Whether to permit the preserving of environment via sudo -E","type":"string","default":"false"}},"groupings":{},"recipes":{"sudo":"Installs sudo and configures /etc/sudoers"}} \ No newline at end of file diff --git a/cookbooks/sudo/metadata.rb b/cookbooks/sudo/metadata.rb deleted file mode 100644 index e455678..0000000 --- a/cookbooks/sudo/metadata.rb +++ /dev/null @@ -1,46 +0,0 @@ -name 'sudo' -maintainer 'Opscode, Inc.' -maintainer_email 'cookbooks@opscode.com' -license 'Apache 2.0' -description 'Installs sudo and configures /etc/sudoers' -version '2.7.1' - -recipe 'sudo', 'Installs sudo and configures /etc/sudoers' - -%w(redhat centos fedora ubuntu debian freebsd mac_os_x).each do |os| - supports os -end - -attribute 'authorization', - :display_name => 'Authorization', - :description => 'Hash of Authorization attributes', - :type => 'hash' - -attribute 'authorization/sudo', - :display_name => 'Authorization Sudoers', - :description => 'Hash of Authorization/Sudo attributes', - :type => 'hash' - -attribute 'authorization/sudo/users', - :display_name => 'Sudo Users', - :description => 'Users who are allowed sudo ALL', - :type => 'array', - :default => '' - -attribute 'authorization/sudo/groups', - :display_name => 'Sudo Groups', - :description => 'Groups who are allowed sudo ALL', - :type => 'array', - :default => '' - -attribute 'authorization/sudo/passwordless', - :display_name => 'Passwordless Sudo', - :description => '', - :type => 'string', - :default => 'false' - -attribute 'authorization/sudo/include_sudoers_d', - :display_name => 'Include sudoers.d', - :description => 'Whether to create the sudoers.d includedir', - :type => 'string', - :default => 'false' diff --git a/cookbooks/sudo/providers/default.rb b/cookbooks/sudo/providers/default.rb index be68133..32cea31 100644 --- a/cookbooks/sudo/providers/default.rb +++ b/cookbooks/sudo/providers/default.rb @@ -26,12 +26,12 @@ def whyrun_supported? end # Ensure that the inputs are valid (we cannot just use the resource for this) -def check_inputs(user, group, foreign_template, foreign_vars) +def check_inputs(user, group, foreign_template, _foreign_vars) # if group, user, and template are nil, throw an exception if user.nil? && group.nil? && foreign_template.nil? - fail 'You must provide a user, group, or template!' + raise 'You must provide a user, group, or template!' elsif !user.nil? && !group.nil? && !template.nil? - fail 'You cannot specify user, group, and template!' + raise 'You cannot specify user, group, and template!' end end @@ -66,31 +66,34 @@ def render_sudoer if new_resource.template Chef::Log.debug('Template attribute provided, all other attributes ignored.') - resource = template "#{node['authorization']['sudo']['prefix']}/sudoers.d/#{new_resource.name}" do - source new_resource.template - owner 'root' - group node['root_group'] - mode '0440' - variables new_resource.variables - action :nothing + resource = template "#{node['authorization']['sudo']['prefix']}/sudoers.d/#{sudo_filename}" do + source new_resource.template + owner 'root' + group node['root_group'] + mode '0440' + variables new_resource.variables + action :nothing end else sudoer = new_resource.user || "%#{new_resource.group}".squeeze('%') - resource = template "#{node['authorization']['sudo']['prefix']}/sudoers.d/#{new_resource.name}" do - source 'sudoer.erb' - cookbook 'sudo' - owner 'root' - group node['root_group'] - mode '0440' - variables :sudoer => sudoer, - :host => new_resource.host, - :runas => new_resource.runas, - :nopasswd => new_resource.nopasswd, - :commands => new_resource.commands, - :command_aliases => new_resource.command_aliases, - :defaults => new_resource.defaults - action :nothing + resource = template "#{node['authorization']['sudo']['prefix']}/sudoers.d/#{sudo_filename}" do + source 'sudoer.erb' + cookbook 'sudo' + owner 'root' + group node['root_group'] + mode '0440' + variables sudoer: sudoer, + host: new_resource.host, + runas: new_resource.runas, + nopasswd: new_resource.nopasswd, + commands: new_resource.commands, + command_aliases: new_resource.command_aliases, + defaults: new_resource.defaults, + setenv: new_resource.setenv, + env_keep_add: new_resource.env_keep_add, + env_keep_subtract: new_resource.env_keep_subtract + action :nothing end end @@ -107,7 +110,7 @@ end action :install do target = "#{node['authorization']['sudo']['prefix']}/sudoers.d/" - unless ::File.exists?(target) + unless ::File.exist?(target) sudoers_dir = directory target sudoers_dir.run_action(:create) end @@ -126,6 +129,12 @@ end private +# acording to the sudo man pages sudo will ignore files in an include dir that have a `.` or `~` +# It is quite common for users to have a `.` in their login, so we will convert this to `__` +def sudo_filename + new_resource.name.gsub(/\./, '__') +end + # Capture a template to a string def capture(template) context = {} diff --git a/cookbooks/sudo/recipes/default.rb b/cookbooks/sudo/recipes/default.rb index afb3574..1e51f8d 100644 --- a/cookbooks/sudo/recipes/default.rb +++ b/cookbooks/sudo/recipes/default.rb @@ -2,7 +2,7 @@ # Cookbook Name:: sudo # Recipe:: default # -# Copyright 2008-2013, Opscode, Inc. +# 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. @@ -25,31 +25,34 @@ end if node['authorization']['sudo']['include_sudoers_d'] directory "#{prefix}/sudoers.d" do - mode '0755' - owner 'root' - group node['root_group'] + mode '0755' + owner 'root' + group node['root_group'] end cookbook_file "#{prefix}/sudoers.d/README" do - source 'README' - mode '0440' - owner 'root' - group node['root_group'] + source 'README' + mode '0440' + owner 'root' + group node['root_group'] end end template "#{prefix}/sudoers" do source 'sudoers.erb' - mode '0440' - owner 'root' - group node['root_group'] + mode '0440' + owner 'root' + group node['root_group'] variables( - :sudoers_groups => node['authorization']['sudo']['groups'], - :sudoers_users => node['authorization']['sudo']['users'], - :passwordless => node['authorization']['sudo']['passwordless'], - :include_sudoers_d => node['authorization']['sudo']['include_sudoers_d'], - :agent_forwarding => node['authorization']['sudo']['agent_forwarding'], - :sudoers_defaults => node['authorization']['sudo']['sudoers_defaults'], - :command_aliases => node['authorization']['sudo']['command_aliases'] + sudoers_groups: node['authorization']['sudo']['groups'], + sudoers_users: node['authorization']['sudo']['users'], + passwordless: node['authorization']['sudo']['passwordless'], + setenv: node['authorization']['sudo']['setenv'], + include_sudoers_d: node['authorization']['sudo']['include_sudoers_d'], + agent_forwarding: node['authorization']['sudo']['agent_forwarding'], + sudoers_defaults: node['authorization']['sudo']['sudoers_defaults'], + command_aliases: node['authorization']['sudo']['command_aliases'], + env_keep_add: node['authorization']['sudo']['env_keep_add'], + env_keep_subtract: node['authorization']['sudo']['env_keep_subtract'] ) end diff --git a/cookbooks/sudo/resources/default.rb b/cookbooks/sudo/resources/default.rb index 1b18858..1086216 100644 --- a/cookbooks/sudo/resources/default.rb +++ b/cookbooks/sudo/resources/default.rb @@ -20,23 +20,26 @@ actions :install, :remove default_action :install -attribute :user, :kind_of => String, :default => nil -attribute :group, :kind_of => String, :default => nil -attribute :commands, :kind_of => Array, :default => ['ALL'] -attribute :host, :kind_of => String, :default => 'ALL' -attribute :runas, :kind_of => String, :default => 'ALL' -attribute :nopasswd, :equal_to => [true, false], :default => false -attribute :template, :kind_of => String, :default => nil -attribute :variables, :kind_of => Hash, :default => nil -attribute :defaults, :kind_of => Array, :default => [] -attribute :command_aliases, :kind_of => Array, :default => [] +attribute :user, kind_of: String, default: nil +attribute :group, kind_of: String, default: nil +attribute :commands, kind_of: Array, default: ['ALL'] +attribute :host, kind_of: String, default: 'ALL' +attribute :runas, kind_of: String, default: 'ALL' +attribute :nopasswd, equal_to: [true, false], default: false +attribute :template, kind_of: String, default: nil +attribute :variables, kind_of: Hash, default: nil +attribute :defaults, kind_of: Array, default: [] +attribute :command_aliases, kind_of: Array, default: [] +attribute :setenv, equal_to: [true, false], default: false +attribute :env_keep_add, kind_of: Array, default: [] +attribute :env_keep_subtract, kind_of: Array, default: [] # Set default for the supports attribute in initializer since it is # a 'reserved' attribute name def initialize(*args) super @action = :install - @supports = { :report => true, :exception => true } + @supports = { report: true, exception: true } end state_attrs :commands, @@ -47,4 +50,6 @@ state_attrs :commands, :template, :user, :variables, - :command_aliases + :command_aliases, + :env_keep_add, + :env_keep_subtract diff --git a/cookbooks/sudo/templates/default/sudoer.erb b/cookbooks/sudo/templates/default/sudoer.erb index 2f6fd21..dbd9dc8 100644 --- a/cookbooks/sudo/templates/default/sudoer.erb +++ b/cookbooks/sudo/templates/default/sudoer.erb @@ -5,8 +5,16 @@ Cmnd_Alias <%= a[:name].upcase %> = <%= a[:command_list].join(', ') %> <% end -%> +<% @env_keep_add.each do |env_keep| -%> +Defaults env_keep += "<%= env_keep %>" +<% end -%> + +<% @env_keep_subtract.each do |env_keep| -%> +Defaults env_keep -= "<%= env_keep %>" +<% end -%> + <% @commands.each do |command| -%> -<%= @sudoer %> <%= @host %>=(<%= @runas %>) <%= 'NOPASSWD:' if @nopasswd %><%= command %> +<%= @sudoer %> <%= @host %>=(<%= @runas %>) <%= 'NOPASSWD:' if @nopasswd %><%= 'SETENV:' if @setenv %><%= command %> <% end -%> <% unless @defaults.empty? %> diff --git a/cookbooks/sudo/templates/default/sudoers.erb b/cookbooks/sudo/templates/default/sudoers.erb index 19be1ef..c18126e 100644 --- a/cookbooks/sudo/templates/default/sudoers.erb +++ b/cookbooks/sudo/templates/default/sudoers.erb @@ -16,12 +16,13 @@ Cmnd_Alias <%= a[:name].upcase %> = <%= a[:command_list].join(', ') %> <% end -%> <% @sudoers_users.each do |user| -%> -<%= user %> ALL=(ALL) <%= "NOPASSWD:" if @passwordless %>ALL +<%= user %> ALL=(ALL) <%= "NOPASSWD:" if @passwordless %><%= "SETENV:" if @setenv %>ALL <% end -%> <% @sudoers_groups.each do |group| -%> # Members of the group '<%= group %>' may gain root privileges -%<%= group %> ALL=(ALL) <%= "NOPASSWD:" if @passwordless %>ALL +%<%= group %> ALL=(ALL) <%= "NOPASSWD:" if @passwordless %><%= "SETENV:" if @setenv %>ALL <% end -%> +# This is not a comment; see sudoers(5) for more information on "#include" directives <%= "#includedir #{node['authorization']['sudo']['prefix']}/sudoers.d" if @include_sudoers_d %> diff --git a/cookbooks/sudo/templates/mac_os_x/sudoers.erb b/cookbooks/sudo/templates/mac_os_x/sudoers.erb index c83e4ee..851c92e 100644 --- a/cookbooks/sudo/templates/mac_os_x/sudoers.erb +++ b/cookbooks/sudo/templates/mac_os_x/sudoers.erb @@ -12,12 +12,12 @@ Defaults env_keep+=SSH_AUTH_SOCK root ALL=(ALL) ALL %admin ALL=(ALL) ALL <% @sudoers_users.each do |user| -%> -<%= user %> ALL=(ALL) <%= "NOPASSWD:" if @passwordless %>ALL +<%= user %> ALL=(ALL) <%= "NOPASSWD:" if @passwordless %><%= "SETENV:" if @setenv %>ALL <% end -%> <% @sudoers_groups.each do |group| -%> # Members of the group '<%= group %>' may gain root privileges -%<%= group %> ALL=(ALL) <%= "NOPASSWD:" if @passwordless %>ALL +%<%= group %> ALL=(ALL) <%= "NOPASSWD:" if @passwordless %><%= "SETENV:" if @setenv %>ALL <% end -%> <%= "#includedir #{node['authorization']['sudo']['prefix']}/sudoers.d" if @include_sudoers_d %> diff --git a/cookbooks/tar/CHANGELOG.md b/cookbooks/tar/CHANGELOG.md new file mode 100644 index 0000000..d586b0b --- /dev/null +++ b/cookbooks/tar/CHANGELOG.md @@ -0,0 +1,75 @@ +# Tar Cookbook Changelog + +## v0.7.0 (2015-07-08) + +* Add adoption notice +* Use `file_cache_path` instead of `file_backup_path` for downloaded artifact + storage +* Fix links to Chef documentation in README + +## v0.6.0 (2014-12-03) + +* Allow either string or array for tar flags + +## v0.5.0 (2014-07-28) + +* Add support for more attributes of `remote_file` +* Escape downloaded file names + +## v0.4.0 (2014-06-13) + +* Add `archive_name` option for when the file name is different from the + package name + +## v0.3.4 (2014-06-05) + +* Define ChefSpec::Runner method for tar_extract + +## v0.3.3 (2014-06-03) + +* Add ChefSpec matchers + +## v0.3.2 (2014-05-05) + +* Add checksum to remote file downloads + +## v0.3.1 (2014-04-04) + +* Correct "notifies" definition in tar_extract's remote_file + +## v0.3.0 (2014-03-21) + +* Add `:extract_local` action + +## v0.2.0 (2013-12-31) + +* Make `tar_extract` only run if needed +* Fix missing space in command line prefix +* Ensure `file_backup_path` exists on initial chef-client run +* Only add headers if needed + +## v0.1.0 (2013-11-26) + +* Allow custom HTTP headers when downloading files +* Allow the type of tar compression +* Improve resource notifications + +## v0.0.4 (2013-10-02) + +* Remove conditional download requests in favor of built-in functionality in Chef >= 11.6.0. +* Fix readme example +* Foodcritic fixes + +## v0.0.3 (2013-01-30) + +* Conditional requests for downloads +* Allow extract if non-root user +* Formatting fixes + +## v0.0.2 (2012-10-13) + +* Add `tar_extract` LWRP + +## v0.0.1 (2011-09-15) + +Initial release diff --git a/cookbooks/tar/README.md b/cookbooks/tar/README.md new file mode 100644 index 0000000..863919c --- /dev/null +++ b/cookbooks/tar/README.md @@ -0,0 +1,101 @@ +*This cookbook is no longer actively maintained and is up for adoption. If you +would like to take over development, go to https://supermarket.chef.io/cookbooks/tar, +click the "Adopt me!" button, and you could be the new maintainer of this cookbook!* + +DESCRIPTION +=========== + +Installs tar and two resources for managing remote tar files. +`tar_package` handles remote source package compilation. +`tar_extract` handles retrieving remote tar files and extracting +them locally. + +LICENSE AND AUTHOR +================== + +Author:: Nathan L Smith () +Author:: George Miranda () +Author:: Mark Van de Vyver () + +Copyright 2011, Cramer Development, Inc. +Copyright 2011, Opscode, Inc. +Copyright 2013, TAQTIQA 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. + +Resources/Providers +=================== + +A `tar_package` LWRP provides an easy way to download remote files and compile and install them. This only works for the most basic Autoconf programs that can do `./configure && make && make install`. + +A `tar_extract` LWRP provides an easy way to download remote tar files and extract them to a local directory. + +# Actions + +`tar_package` +- :install: Installs the package + +`tar_extract` +- :extract: Extracts the tar file from a url +- :extract_local: Extracts the tar file from a local file path + +# Attribute Parameters + +`tar_package` +- source: name attribute. The source remote URL. +- prefix: Directory to be used as the `--prefix` configure flag. +- source\_directory: Directory to which source files are download. +- creates: A file this command creates - if the file exists, the command will not be run. +- configure\_flags: Array of additional flags to be passed to `./configure`. +- archive\_name: Specify a different name for the downloaded archive. Use it if the directory name inside the tar file is different than the name defined in the URL. +Additionally, `tar_package` supports most `remote_file` [attributes](https://docs.chef.io/chef/resources.html#remote-file). + +`tar_extract` +- source: name attribute. The source remote URL. +- target\_dir: Directory to extract into, e.g. tar xzf -C (target_dir) +- download\_dir: Directory to which tarball is downloaded (defaults to chef cache which requires root `group` and `user`). +- creates: A file this command creates - if the file exists, the command will not be run. +- compress_char: Flag for compression type, such as `z` for `gzip`. `man tar` for options. +- tar\_flags: Array of additional flags to be passed to tar xzf command. +- group: Group name or group ID to extract the archive under. If set to non-root group, point to a `download_dir` the group has permission to access. +- user: User name or user ID to extract the archive under. If set to non-root user, point to a `download_dir` the user has permission to access. +Additionally, `tar_extract` supports most `remote_file` [attributes](https://docs.chef.io/chef/resources.html#remote-file). + +# Example + + tar_package 'http://pgfoundry.org/frs/download.php/1446/pgpool-3.4.1.tar.gz' do + prefix '/usr/local' + creates '/usr/local/bin/pgpool' + end + +This will download, compile, and install the package from the given URL and install it into /usr/local. + + tar_extract 'http://dev.mycoderepo.com/artifacts/mycode-1.2.3.tar.gz' do + target_dir '/opt/myapp/mycode' + creates '/opt/myapp/mycode/lib' + tar_flags [ '-P', '--strip-components 1' ] + end + +This will download the tarball to cache, extract the contents to /opt/myapp/mycode, use the file '/opt/myapp/mycode/lib' to determine idempotency, and pass both '-P' and '--strip-components 1' flags to the tar xzf command. + + tar_extract '/tmp/mycode-1.2.3.tar.gz' do + action :extract_local + target_dir '/opt/myapp/mycode' + creates '/opt/myapp/mycode/lib' + end + +This will extract the contents of /tmp/mycode-1.2.3.tar.gz to /opt/myapp/mycode and use the file '/opt/myapp/mycode/lib' to determine idempotency. + +# ChefSpec Matchers + +ChefSpec matchers are defined for tar_package and tar_extract. diff --git a/cookbooks/tar/libraries/matchers.rb b/cookbooks/tar/libraries/matchers.rb new file mode 100644 index 0000000..5a293cc --- /dev/null +++ b/cookbooks/tar/libraries/matchers.rb @@ -0,0 +1,15 @@ +if defined?(ChefSpec) + ChefSpec.define_matcher :tar_extract + + def install_tar_package(source) + ChefSpec::Matchers::ResourceMatcher.new(:tar_package, :install, source) + end + + def extract_tar_extract(source) + ChefSpec::Matchers::ResourceMatcher.new(:tar_extract, :extract, source) + end + + def extract_local_tar_extract(source) + ChefSpec::Matchers::ResourceMatcher.new(:tar_extract, :extract_local, source) + end +end diff --git a/cookbooks/tar/metadata.json b/cookbooks/tar/metadata.json new file mode 100644 index 0000000..752547a --- /dev/null +++ b/cookbooks/tar/metadata.json @@ -0,0 +1,41 @@ +{ + "name": "tar", + "description": "Installs tar and two LWRPs to manage remote tar packages", + "long_description": "*This cookbook is no longer actively maintained and is up for adoption. If you\nwould like to take over development, go to https://supermarket.chef.io/cookbooks/tar,\nclick the \"Adopt me!\" button, and you could be the new maintainer of this cookbook!*\n\nDESCRIPTION\n===========\n\nInstalls tar and two resources for managing remote tar files.\n`tar_package` handles remote source package compilation.\n`tar_extract` handles retrieving remote tar files and extracting\nthem locally.\n\nLICENSE AND AUTHOR\n==================\n\nAuthor:: Nathan L Smith ()\nAuthor:: George Miranda ()\nAuthor:: Mark Van de Vyver ()\n\nCopyright 2011, Cramer Development, Inc.\nCopyright 2011, Opscode, Inc.\nCopyright 2013, TAQTIQA 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\nResources/Providers\n===================\n\nA `tar_package` LWRP provides an easy way to download remote files and compile and install them. This only works for the most basic Autoconf programs that can do `./configure && make && make install`.\n\nA `tar_extract` LWRP provides an easy way to download remote tar files and extract them to a local directory.\n\n# Actions\n\n`tar_package`\n- :install: Installs the package\n\n`tar_extract`\n- :extract: Extracts the tar file from a url\n- :extract_local: Extracts the tar file from a local file path\n\n# Attribute Parameters\n\n`tar_package`\n- source: name attribute. The source remote URL.\n- prefix: Directory to be used as the `--prefix` configure flag.\n- source\\_directory: Directory to which source files are download.\n- creates: A file this command creates - if the file exists, the command will not be run.\n- configure\\_flags: Array of additional flags to be passed to `./configure`.\n- archive\\_name: Specify a different name for the downloaded archive. Use it if the directory name inside the tar file is different than the name defined in the URL.\nAdditionally, `tar_package` supports most `remote_file` [attributes](https://docs.chef.io/chef/resources.html#remote-file).\n\n`tar_extract`\n- source: name attribute. The source remote URL.\n- target\\_dir: Directory to extract into, e.g. tar xzf -C (target_dir)\n- download\\_dir: Directory to which tarball is downloaded (defaults to chef cache which requires root `group` and `user`).\n- creates: A file this command creates - if the file exists, the command will not be run.\n- compress_char: Flag for compression type, such as `z` for `gzip`. `man tar` for options.\n- tar\\_flags: Array of additional flags to be passed to tar xzf command.\n- group: Group name or group ID to extract the archive under. If set to non-root group, point to a `download_dir` the group has permission to access.\n- user: User name or user ID to extract the archive under. If set to non-root user, point to a `download_dir` the user has permission to access.\nAdditionally, `tar_extract` supports most `remote_file` [attributes](https://docs.chef.io/chef/resources.html#remote-file).\n\n# Example\n\n tar_package 'http://pgfoundry.org/frs/download.php/1446/pgpool-3.4.1.tar.gz' do\n prefix '/usr/local'\n creates '/usr/local/bin/pgpool'\n end\n\nThis will download, compile, and install the package from the given URL and install it into /usr/local.\n\n tar_extract 'http://dev.mycoderepo.com/artifacts/mycode-1.2.3.tar.gz' do\n target_dir '/opt/myapp/mycode'\n creates '/opt/myapp/mycode/lib'\n tar_flags [ '-P', '--strip-components 1' ]\n end\n\nThis will download the tarball to cache, extract the contents to /opt/myapp/mycode, use the file '/opt/myapp/mycode/lib' to determine idempotency, and pass both '-P' and '--strip-components 1' flags to the tar xzf command.\n\n tar_extract '/tmp/mycode-1.2.3.tar.gz' do\n action :extract_local\n target_dir '/opt/myapp/mycode'\n creates '/opt/myapp/mycode/lib'\n end\n\nThis will extract the contents of /tmp/mycode-1.2.3.tar.gz to /opt/myapp/mycode and use the file '/opt/myapp/mycode/lib' to determine idempotency.\n\n# ChefSpec Matchers\n\nChefSpec matchers are defined for tar_package and tar_extract.\n", + "maintainer": "Cramer Development, Inc.", + "maintainer_email": "sysadmin@cramerdev.com", + "license": "Apache 2.0", + "platforms": { + + }, + "dependencies": { + + }, + "recommendations": { + + }, + "suggestions": { + + }, + "conflicting": { + + }, + "providing": { + + }, + "replacing": { + + }, + "attributes": { + + }, + "groupings": { + + }, + "recipes": { + + }, + "version": "0.7.0", + "source_url": "", + "issues_url": "" +} diff --git a/cookbooks/tar/metadata.rb b/cookbooks/tar/metadata.rb new file mode 100644 index 0000000..aa1d09c --- /dev/null +++ b/cookbooks/tar/metadata.rb @@ -0,0 +1,7 @@ +name "tar" +maintainer "Cramer Development, Inc." +maintainer_email "sysadmin@cramerdev.com" +license "Apache 2.0" +description "Installs tar and two LWRPs to manage remote tar packages" +long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) +version "0.7.0" diff --git a/cookbooks/tar/providers/extract.rb b/cookbooks/tar/providers/extract.rb new file mode 100644 index 0000000..1e48417 --- /dev/null +++ b/cookbooks/tar/providers/extract.rb @@ -0,0 +1,86 @@ +# +# Cookbook Name:: tar +# Provider:: extract +# +# Author:: Nathan L Smith () +# Author:: George Miranda () +# Author:: Mark Van de Vyver () +# +# Copyright 2011, Cramer Development, Inc. +# Copyright 2012, Opscode, Inc. +# Copyright 2013, TAQTIQA 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 'shellwords' + +use_inline_resources if defined?(use_inline_resources) + +def whyrun_supported? + true +end + +action :extract do + version = Chef::Version.new(Chef::VERSION[/^(\d+\.\d+\.\d+)/, 1]) + r = new_resource + basename = ::File.basename(r.name) + local_archive = "#{r.download_dir}/#{basename}" + + directory r.download_dir do + recursive true + end + + remote_file basename do + source r.name + checksum r.checksum + path local_archive + backup false + action :create + group r.group + owner r.user + mode r.mode + notifies :run, "execute[extract #{local_archive}]" + if version.major > 11 || (version.major == 11 && version.minor >= 6) + unless r.headers.nil? + headers r.headers + end + use_etag r.use_etag + use_last_modified r.use_last_modified + atomic_update r.atomic_update + force_unlink r.force_unlink + manage_symlink_source r.manage_symlink_source + end + end + + extract_tar(local_archive, new_resource) +end + +action :extract_local do + extract_tar(new_resource.name, new_resource) +end + +def extract_tar(local_archive, r) + execute "extract #{local_archive}" do + if r.tar_flags.kind_of?(String) + flags = r.tar_flags + else + flags = r.tar_flags.join(' ') + end + command "tar xf#{r.compress_char} #{local_archive.shellescape} #{flags}" + cwd r.target_dir + creates r.creates + group r.group + user r.user + action (r.creates || r.not_if.any? || r.only_if.any? ? :run : :nothing) + end +end diff --git a/cookbooks/tar/providers/package.rb b/cookbooks/tar/providers/package.rb new file mode 100644 index 0000000..1141c46 --- /dev/null +++ b/cookbooks/tar/providers/package.rb @@ -0,0 +1,65 @@ +# +# Cookbook Name:: tar +# Provider:: package +# +# Author:: Nathan L Smith () +# +# Copyright 2011, Cramer Development, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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_inline_resources if defined?(use_inline_resources) + +def whyrun_supported? + true +end + +action :install do + version = Chef::Version.new(Chef::VERSION[/^(\d+\.\d+\.\d+)/, 1]) + r = new_resource + basename = r.archive_name || ::File.basename(r.name) + dirname = basename.chomp('.tar.gz') # Assuming .tar.gz + src_dir = r.source_directory + + remote_file basename do + source r.name + path "#{src_dir}/#{basename}" + backup false + action :create_if_missing + if version.major > 11 || (version.major == 11 && version.minor >= 6) + unless r.headers.nil? + headers r.headers + end + use_etag r.use_etag + use_last_modified r.use_last_modified + atomic_update r.atomic_update + force_unlink r.force_unlink + manage_symlink_source r.manage_symlink_source + end + end + + execute "extract #{basename}" do + command "tar xfz #{basename}" + cwd src_dir + creates "#{src_dir}/#{dirname}" + end + + execute "compile & install #{dirname}" do + flags = [r.prefix ? "--prefix=#{r.prefix}" : nil, *r.configure_flags].compact.join(' ') + command "./configure --quiet #{flags} && make --quiet && make --quiet install" + cwd "#{src_dir}/#{dirname}" + creates r.creates + end +end + diff --git a/cookbooks/tar/recipes/default.rb b/cookbooks/tar/recipes/default.rb new file mode 100644 index 0000000..8d8e2dc --- /dev/null +++ b/cookbooks/tar/recipes/default.rb @@ -0,0 +1,22 @@ +# +# Cookbook Name:: tar +# Recipe:: default +# +# Author:: Nathan L Smith () +# +# Copyright 2011, Cramer Development, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 'tar' diff --git a/cookbooks/tar/resources/extract.rb b/cookbooks/tar/resources/extract.rb new file mode 100644 index 0000000..51d8f0e --- /dev/null +++ b/cookbooks/tar/resources/extract.rb @@ -0,0 +1,49 @@ +# +# Cookbook Name:: tar +# Resource:: extract +# +# Author:: Nathan L Smith () +# Author:: George Miranda () +# Author:: Mark Van de Vyver () +# +# Copyright 2011, Cramer Development, Inc. +# Copyright 2012, Opscode, Inc. +# Copyright 2013, TAQTIQA 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. +# + +actions :extract, :extract_local + +attribute :source, :kind_of => String, :name_attribute => true +attribute :checksum, :kind_of => String +attribute :download_dir, :kind_of => String, :default => Chef::Config[:file_cache_path] +attribute :group, :kind_of => String, :default => 'root' +attribute :mode, :kind_of => String, :default => '0755' +attribute :target_dir, :kind_of => String +attribute :creates, :kind_of => String +attribute :compress_char, :kind_of => String, :default => 'z' +attribute :tar_flags, :kind_of => [String, Array], :default => Array.new +attribute :user, :kind_of => String, :default => 'root' + +version = Chef::Version.new(Chef::VERSION[/^(\d+\.\d+\.\d+)/, 1]) +if version.major > 11 || (version.major == 11 && version.minor >= 6) + attribute :headers, :kind_of => Hash, :default => nil + attribute :use_etag, :kind_of => [TrueClass, FalseClass], :default => true + attribute :use_last_modified, :kind_of => [TrueClass, FalseClass], :default => true + attribute :atomic_update, :kind_of => [TrueClass, FalseClass], :default => true + attribute :force_unlink, :kind_of => [TrueClass, FalseClass], :default => false + attribute :manage_symlink_source, :kind_of => [TrueClass, FalseClass], :default => nil +end + +default_action :extract diff --git a/cookbooks/tar/resources/package.rb b/cookbooks/tar/resources/package.rb new file mode 100644 index 0000000..8a68386 --- /dev/null +++ b/cookbooks/tar/resources/package.rb @@ -0,0 +1,42 @@ +# +# Cookbook Name:: tar +# Resource:: package +# +# Author:: Nathan L Smith () +# +# Copyright 2011, Cramer Development, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 :install + +attribute :source, :kind_of => String, :name_attribute => true +attribute :headers, :kind_of => Hash, :default => {} +attribute :prefix, :kind_of => String +attribute :source_directory, :kind_of => String, :default => '/usr/local/src' +attribute :creates, :kind_of => String +attribute :configure_flags, :kind_of => Array, :default => [] +attribute :archive_name, :kind_of => String + +version = Chef::Version.new(Chef::VERSION[/^(\d+\.\d+\.\d+)/, 1]) +if version.major > 11 || (version.major == 11 && version.minor >= 6) + attribute :headers, :kind_of => Hash, :default => nil + attribute :use_etag, :kind_of => [TrueClass, FalseClass], :default => true + attribute :use_last_modified, :kind_of => [TrueClass, FalseClass], :default => true + attribute :atomic_update, :kind_of => [TrueClass, FalseClass], :default => true + attribute :force_unlink, :kind_of => [TrueClass, FalseClass], :default => false + attribute :manage_symlink_source, :kind_of => [TrueClass, FalseClass], :default => nil +end + +default_action :install diff --git a/cookbooks/ufw/CHANGELOG.md b/cookbooks/ufw/CHANGELOG.md index 8386ebf..6fc7246 100644 --- a/cookbooks/ufw/CHANGELOG.md +++ b/cookbooks/ufw/CHANGELOG.md @@ -1,30 +1,32 @@ -ufw Cookbook CHANGELOG -====================== +# ufw Cookbook CHANGELOG This file is used to list changes made in each version of the ufw cookbook. +## v1.0.0 (12-14-2015) +- Update to use / require the Firewall v2.0.0+ cookbook, which requires Chef 12 +- Updated all Opscode references to Chef Software Inc. +- Updated testing, contributing, and maintainers docs +- Added source_url and issues_url metadata for supermarket +- Resolved all rubocop warnings and add the standard Chef rubocop file +- Added travis and supermarket version badges to the readme +- Added requirements section to the readme +- Added a chefignore file +- Added a Rakefile for simplified testing +- Added a basic converge chefspec -v0.7.4 ------- +## v0.7.4 No change. Version bump for toolchain - -v0.7.2 ------- +## v0.7.2 Updating metadata to depend on firewall >= 0.9 - -v0.7.0 ------- +## v0.7.0 [COOK-3592] - allow source ports to be defined as a range in ufw - -v0.6.4 ------- +## v0.6.4 ### Bug -- **[COOK-3316](https://tickets.opscode.com/browse/COOK-3316)** - Fix README.md example +- **[COOK-3316](https://tickets.chef.io/browse/COOK-3316)** - Fix README.md example -v0.6.2 ------- +## v0.6.2 ### Bug - [COOK-2487]: when setting a node attribute you must specify the precedence - [COOK-2982]: ufw cookbook has foodcritic failures diff --git a/cookbooks/ufw/CONTRIBUTING.md b/cookbooks/ufw/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/ufw/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/ufw/MAINTAINERS.md b/cookbooks/ufw/MAINTAINERS.md new file mode 100644 index 0000000..c6a51ae --- /dev/null +++ b/cookbooks/ufw/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 +* [Tim Smith](https://github.com/tas50) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Sean OMeara](https://github.com/someara) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) diff --git a/cookbooks/ufw/README.md b/cookbooks/ufw/README.md index a11f57a..4ce402d 100644 --- a/cookbooks/ufw/README.md +++ b/cookbooks/ufw/README.md @@ -1,136 +1,151 @@ -Description -=========== +# Description +[![Build Status](https://travis-ci.org/chef-cookbooks/ufw.svg?branch=master)](http://travis-ci.org/chef-cookbooks/ufw) [![Cookbook Version](https://img.shields.io/cookbook/v/ufw.svg)](https://supermarket.chef.io/cookbooks/ufw) + Configures Uncomplicated Firewall (ufw) on Ubuntu. Including the `ufw` recipe in a run list means the firewall will be enabled and will deny everything except SSH and ICMP ping by default. Rules may be added to the node by adding them to the `['firewall']['rules']` attributes in roles or on the node directly. The `firewall` cookbook has an LWRP that may be used to apply rules directly from other recipes as well. There is no need to explicitly remove rules, they are reevaluated on changes and reset. Rules are applied in the order of the run list, unless ordering is explictly added. -Requirements -============ -Tested with Ubuntu 10.04 and 11.04. +## Requirements +### Platforms +- Ubuntu + +### Chef +- Chef 12+ + +Since this cookbook has an open-ended dependency on 'firewall', users of Chef11 or earlier should pin 'firewall' to '~>0.9' via the caller's metadata. Otherwise 'poise' v2+ will be invoked which is Chef12+ only. + +### Cookbooks +- firewall 2.0+ + +## Recipes +###default -Recipes -======= -default -------- The `default` recipe looks for the list of firewall rules to apply from the `['firewall']['rules']` attribute added to roles and on the node itself. The list of rules is then applied to the node in the order specified. -disable -------- +###disable + The `disable` recipe is used if there is a need to disable the existing firewall, perhaps for testing. It disables the ufw firewall even if other ufw recipes attempt to enable it. If you remove this recipe, the firewall does not get automatically re-enabled. You will need clear the value of the `['firewall']['state']` to force a recalculation of the firewall rules. This can be done with `knife node edit`. -databag -------- +###databag + The `databag` recipe looks in the `firewall` data bag for to apply firewall rules based on inspecting the runlist for roles and recipe names for keys that map to the data bag items and are applied in the the order specified. The `databag` recipe calls the `default` recipe after the `['firewall']['rules']` attribute is set to appy the rules, so you may mix roles with databag items if you want (roles apply first, then data bag contents). -recipes -------- +###recipes + The `recipes` recipe applies firewall rules based on inspecting the runlist for recipes that have node[]['firewall']['rules'] attributes. These are appended to node['firewall']['rules'] and applied to the node. Cookbooks may define attributes for recipes like so: -# attributes/default.rb for test cookbook - default['test']['firewall']['rules'] = [ - {"test"=> { - "port"=> "27901", - "protocol"=> "udp" - } - } - ] - default['test::awesome']['firewall']['rules'] = [ - {"awesome"=> { - "port"=> "99427", - "protocol"=> "udp" - } - }, - {"awesome2"=> { - "port"=> "99428" - } - } - ] +### attributes/default.rb for test cookbook + +``` +default['test']['firewall']['rules'] = [ + {"test"=> { + "port"=> "27901", + "protocol"=> "udp" + } + } +] +default['test::awesome']['firewall']['rules'] = [ + {"awesome"=> { + "port"=> "99427", + "protocol"=> "udp" + } + }, + {"awesome2"=> { + "port"=> "99428" + } + } +] +``` Note that the 'test::awesome' rules are only applied if that specific recipe is in the runlist. Recipe-applied firewall rules are applied after any rules defined in role attributes. -securitylevel -------------- -The `securitylevel` recipe is used if there are any node['firewall']['securitylevel'] settings that need to be enforced. It is a reference implementation with nothing configured. +### -Attributes -========== +securitylevel The `securitylevel` recipe is used if there are any node['firewall']['securitylevel'] settings that need to be enforced. It is a reference implementation with nothing configured. + +## Attributes Roles and the node may have the `['firewall']['rules']` attribute set. This attribute is a list of hashes, the key will be rule name, the value will be the hash of parameters. Application order is based on run list. -# Example Role - name "fw_example" - description "Firewall rules for Examples" - override_attributes( - "firewall" => { - "rules" => [ - {"tftp" => {}}, - {"http" => { - "port" => "80" - } - }, - {"block tomcat from 192.168.1.0/24" => { - "port" => "8080", - "source" => "192.168.1.0/24", - "action" => "deny" - } - }, - {"Allow access to udp 1.2.3.4 port 5469 from 1.2.3.5 port 5469" => { - "protocol" => "udp", - "port" => "5469", - "source" => "1.2.3.4", - "destination" => "1.2.3.5", - "dest_port" => "5469" - } - }, - {"allow to tcp ports 8000-8010 from 192.168.1.0/24" => { - "port_range" => "8000..8010", - "source" => "192.168.1.0/24", - "protocol" => "tcp" //protocol is mandatory when using port ranges - } - } - ] - } - ) +### Example Role -Data Bags -========= -The `firewall` data bag may be used with the `databag` recipe. It will contain items that map to role names (eg. the 'apache' role will map to the 'apache' item in the 'firewall' data bag). Either roles or recipes may be keys (role[webserver] is 'webserver', recipe[apache2] is 'apache2'). If you have recipe-specific firewall rules, you will need to replace the '::' with '__' (double underscores) (eg. recipe[apache2::mod_ssl] is 'apache2__mod_ssl' in the data bag item). +``` +name "fw_example" +description "Firewall rules for Examples" +override_attributes( + "firewall" => { + "rules" => [ + {"tftp" => {}}, + {"http" => { + "port" => "80" + } + }, + {"block tomcat from 192.168.1.0/24" => { + "port" => "8080", + "source" => "192.168.1.0/24", + "action" => "deny" + } + }, + {"Allow access to udp 1.2.3.4 port 5469 from 1.2.3.5 port 5469" => { + "protocol" => "udp", + "port" => "5469", + "source" => "1.2.3.4", + "destination" => "1.2.3.5", + "dest_port" => "5469" + } + }, + {"allow to tcp ports 8000-8010 from 192.168.1.0/24" => { + "port_range" => "8000..8010", + "source" => "192.168.1.0/24", + "protocol" => "tcp" //protocol is mandatory when using port ranges + } + } + ] + } + ) +``` + +## Data Bags +The `firewall` data bag may be used with the `databag` recipe. It will contain items that map to role names (eg. the 'apache' role will map to the 'apache' item in the 'firewall' data bag). Either roles or recipes may be keys (role[webserver] is 'webserver', recipe[apache2] is 'apache2'). If you have recipe-specific firewall rules, you will need to replace the '::' with '**' (double underscores) (eg. recipe[apache2::mod_ssl] is 'apache2**mod_ssl' in the data bag item). The items in the data bag will contain a 'rules' array of hashes to apply to the `['firewall']['rules']` attribute. - % knife data bag create firewall - % knife data bag from file firewall examples/data_bags/firewall/apache2.json - % knife data bag from file firewall examples/data_bags/firewall/apache2__mod_ssl.json +``` +% knife data bag create firewall +% knife data bag from file firewall examples/data_bags/firewall/apache2.json +% knife data bag from file firewall examples/data_bags/firewall/apache2__mod_ssl.json +``` -# Example 'firewall' data bag item +### Example 'firewall' data bag item - { - "id": "apache2", - "rules": [ - {"http": { - "port": "80" - }}, - {"block http from 192.168.1.0/24": { - "port": "80", - "source": "192.168.1.0/24", - "action": "deny" - }} - ] - } +``` +{ + "id": "apache2", + "rules": [ + {"http": { + "port": "80" + }}, + {"block http from 192.168.1.0/24": { + "port": "80", + "source": "192.168.1.0/24", + "action": "deny" + }} + ] +} +``` -Resources/Providers -=================== +## Resources/Providers The `firewall` cookbook provides the `firewall` and `firewall_rule` LWRPs, for which there is a ufw provider. -License and Author -================== -Author:: Matt Ray () +## License & Authors +**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io)) -Copyright:: 2011 Opscode, Inc. +**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 @@ -142,3 +157,4 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 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/ufw/attributes/default.rb b/cookbooks/ufw/attributes/default.rb index b8e079d..3f2e6d4 100644 --- a/cookbooks/ufw/attributes/default.rb +++ b/cookbooks/ufw/attributes/default.rb @@ -1,2 +1,2 @@ default['firewall']['rules'] = [] -default['firewall']['securitylevel'] = "" +default['firewall']['securitylevel'] = '' diff --git a/cookbooks/ufw/metadata.json b/cookbooks/ufw/metadata.json index 7f9b26c..eb0fdf0 100644 --- a/cookbooks/ufw/metadata.json +++ b/cookbooks/ufw/metadata.json @@ -1,40 +1 @@ -{ - "name": "ufw", - "version": "0.7.4", - "description": "Installs/Configures ufw", - "long_description": "Description\n===========\nConfigures Uncomplicated Firewall (ufw) on Ubuntu. Including the `ufw` recipe in a run list means the firewall will be enabled and will deny everything except SSH and ICMP ping by default.\n\nRules may be added to the node by adding them to the `['firewall']['rules']` attributes in roles or on the node directly. The `firewall` cookbook has an LWRP that may be used to apply rules directly from other recipes as well. There is no need to explicitly remove rules, they are reevaluated on changes and reset. Rules are applied in the order of the run list, unless ordering is explictly added.\n\nRequirements\n============\nTested with Ubuntu 10.04 and 11.04.\n\nRecipes\n=======\ndefault\n-------\nThe `default` recipe looks for the list of firewall rules to apply from the `['firewall']['rules']` attribute added to roles and on the node itself. The list of rules is then applied to the node in the order specified.\n\ndisable\n-------\nThe `disable` recipe is used if there is a need to disable the existing firewall, perhaps for testing. It disables the ufw firewall even if other ufw recipes attempt to enable it.\n\nIf you remove this recipe, the firewall does not get automatically re-enabled. You will need clear the value of the `['firewall']['state']` to force a recalculation of the firewall rules. This can be done with `knife node edit`.\n\ndatabag\n-------\nThe `databag` recipe looks in the `firewall` data bag for to apply firewall rules based on inspecting the runlist for roles and recipe names for keys that map to the data bag items and are applied in the the order specified.\n\nThe `databag` recipe calls the `default` recipe after the `['firewall']['rules']` attribute is set to appy the rules, so you may mix roles with databag items if you want (roles apply first, then data bag contents).\n\nrecipes\n-------\nThe `recipes` recipe applies firewall rules based on inspecting the runlist for recipes that have node[]['firewall']['rules'] attributes. These are appended to node['firewall']['rules'] and applied to the node. Cookbooks may define attributes for recipes like so:\n\n# attributes/default.rb for test cookbook\n default['test']['firewall']['rules'] = [\n {\"test\"=> {\n \"port\"=> \"27901\",\n \"protocol\"=> \"udp\"\n }\n }\n ]\n default['test::awesome']['firewall']['rules'] = [\n {\"awesome\"=> {\n \"port\"=> \"99427\",\n \"protocol\"=> \"udp\"\n }\n },\n {\"awesome2\"=> {\n \"port\"=> \"99428\"\n }\n }\n ]\n\nNote that the 'test::awesome' rules are only applied if that specific recipe is in the runlist. Recipe-applied firewall rules are applied after any rules defined in role attributes.\n\nsecuritylevel\n-------------\nThe `securitylevel` recipe is used if there are any node['firewall']['securitylevel'] settings that need to be enforced. It is a reference implementation with nothing configured.\n\nAttributes\n==========\nRoles and the node may have the `['firewall']['rules']` attribute set. This attribute is a list of hashes, the key will be rule name, the value will be the hash of parameters. Application order is based on run list.\n\n# Example Role\n name \"fw_example\"\n description \"Firewall rules for Examples\"\n override_attributes(\n \"firewall\" => {\n \"rules\" => [\n {\"tftp\" => {}},\n {\"http\" => {\n \"port\" => \"80\"\n }\n },\n {\"block tomcat from 192.168.1.0/24\" => {\n \"port\" => \"8080\",\n \"source\" => \"192.168.1.0/24\",\n \"action\" => \"deny\"\n }\n },\n {\"Allow access to udp 1.2.3.4 port 5469 from 1.2.3.5 port 5469\" => {\n \"protocol\" => \"udp\",\n \"port\" => \"5469\",\n \"source\" => \"1.2.3.4\",\n \"destination\" => \"1.2.3.5\",\n \"dest_port\" => \"5469\"\n }\n },\n {\"allow to tcp ports 8000-8010 from 192.168.1.0/24\" => {\n \"port_range\" => \"8000..8010\",\n \"source\" => \"192.168.1.0/24\",\n \"protocol\" => \"tcp\" //protocol is mandatory when using port ranges\n }\n }\n ]\n }\n )\n\nData Bags\n=========\nThe `firewall` data bag may be used with the `databag` recipe. It will contain items that map to role names (eg. the 'apache' role will map to the 'apache' item in the 'firewall' data bag). Either roles or recipes may be keys (role[webserver] is 'webserver', recipe[apache2] is 'apache2'). If you have recipe-specific firewall rules, you will need to replace the '::' with '__' (double underscores) (eg. recipe[apache2::mod_ssl] is 'apache2__mod_ssl' in the data bag item).\n\nThe items in the data bag will contain a 'rules' array of hashes to apply to the `['firewall']['rules']` attribute.\n\n % knife data bag create firewall\n % knife data bag from file firewall examples/data_bags/firewall/apache2.json\n % knife data bag from file firewall examples/data_bags/firewall/apache2__mod_ssl.json\n\n# Example 'firewall' data bag item\n\n {\n \"id\": \"apache2\",\n \"rules\": [\n {\"http\": {\n \"port\": \"80\"\n }},\n {\"block http from 192.168.1.0/24\": {\n \"port\": \"80\",\n \"source\": \"192.168.1.0/24\",\n \"action\": \"deny\"\n }}\n ]\n }\n\nResources/Providers\n===================\nThe `firewall` cookbook provides the `firewall` and `firewall_rule` LWRPs, for which there is a ufw provider.\n\nLicense and Author\n==================\nAuthor:: Matt Ray ()\n\nCopyright:: 2011 Opscode, 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", - "maintainer": "Opscode, Inc.", - "maintainer_email": "matt@opscode.com", - "license": "Apache 2.0", - "platforms": { - "ubuntu": ">= 0.0.0" - }, - "dependencies": { - "firewall": ">= 0.9.0" - }, - "recommendations": { - }, - "suggestions": { - }, - "conflicting": { - }, - "providing": { - }, - "replacing": { - }, - "attributes": { - "firewall/rules": { - "display_name": "List of firewall rules for the node.", - "description": "List of firewall rules for the node. Possibly set by node, roles or data bags.", - "type": "array" - }, - "firewall/securitylevel": { - "display_name": "Security level of the node.", - "description": "Security level of the node, may be set by node, roles or environment." - } - }, - "groupings": { - }, - "recipes": { - } -} \ No newline at end of file +{"name":"ufw","version":"1.0.0","description":"Installs and configures Uncomplicated Firewall (ufw)","long_description":"# Description\n[![Build Status](https://travis-ci.org/chef-cookbooks/ufw.svg?branch=master)](http://travis-ci.org/chef-cookbooks/ufw) [![Cookbook Version](https://img.shields.io/cookbook/v/ufw.svg)](https://supermarket.chef.io/cookbooks/ufw)\n\nConfigures Uncomplicated Firewall (ufw) on Ubuntu. Including the `ufw` recipe in a run list means the firewall will be enabled and will deny everything except SSH and ICMP ping by default.\n\nRules may be added to the node by adding them to the `['firewall']['rules']` attributes in roles or on the node directly. The `firewall` cookbook has an LWRP that may be used to apply rules directly from other recipes as well. There is no need to explicitly remove rules, they are reevaluated on changes and reset. Rules are applied in the order of the run list, unless ordering is explictly added.\n\n## Requirements\n### Platforms\n- Ubuntu\n\n### Chef\n- Chef 12+\n\nSince this cookbook has an open-ended dependency on 'firewall', users of Chef11 or earlier should pin 'firewall' to '~>0.9' via the caller's metadata. Otherwise 'poise' v2+ will be invoked which is Chef12+ only.\n\n### Cookbooks\n- firewall 2.0+\n\n## Recipes\n###default\n\nThe `default` recipe looks for the list of firewall rules to apply from the `['firewall']['rules']` attribute added to roles and on the node itself. The list of rules is then applied to the node in the order specified.\n\n###disable\n\nThe `disable` recipe is used if there is a need to disable the existing firewall, perhaps for testing. It disables the ufw firewall even if other ufw recipes attempt to enable it.\n\nIf you remove this recipe, the firewall does not get automatically re-enabled. You will need clear the value of the `['firewall']['state']` to force a recalculation of the firewall rules. This can be done with `knife node edit`.\n\n###databag\n\nThe `databag` recipe looks in the `firewall` data bag for to apply firewall rules based on inspecting the runlist for roles and recipe names for keys that map to the data bag items and are applied in the the order specified.\n\nThe `databag` recipe calls the `default` recipe after the `['firewall']['rules']` attribute is set to appy the rules, so you may mix roles with databag items if you want (roles apply first, then data bag contents).\n\n###recipes\n\nThe `recipes` recipe applies firewall rules based on inspecting the runlist for recipes that have node[]['firewall']['rules'] attributes. These are appended to node['firewall']['rules'] and applied to the node. Cookbooks may define attributes for recipes like so:\n\n### attributes/default.rb for test cookbook\n\n```\ndefault['test']['firewall']['rules'] = [\n {\"test\"=> {\n \"port\"=> \"27901\",\n \"protocol\"=> \"udp\"\n }\n }\n]\ndefault['test::awesome']['firewall']['rules'] = [\n {\"awesome\"=> {\n \"port\"=> \"99427\",\n \"protocol\"=> \"udp\"\n }\n },\n {\"awesome2\"=> {\n \"port\"=> \"99428\"\n }\n }\n]\n```\n\nNote that the 'test::awesome' rules are only applied if that specific recipe is in the runlist. Recipe-applied firewall rules are applied after any rules defined in role attributes.\n\n###\n\nsecuritylevel The `securitylevel` recipe is used if there are any node['firewall']['securitylevel'] settings that need to be enforced. It is a reference implementation with nothing configured.\n\n## Attributes\nRoles and the node may have the `['firewall']['rules']` attribute set. This attribute is a list of hashes, the key will be rule name, the value will be the hash of parameters. Application order is based on run list.\n\n### Example Role\n\n```\nname \"fw_example\"\ndescription \"Firewall rules for Examples\"\noverride_attributes(\n \"firewall\" => {\n \"rules\" => [\n {\"tftp\" => {}},\n {\"http\" => {\n \"port\" => \"80\"\n }\n },\n {\"block tomcat from 192.168.1.0/24\" => {\n \"port\" => \"8080\",\n \"source\" => \"192.168.1.0/24\",\n \"action\" => \"deny\"\n }\n },\n {\"Allow access to udp 1.2.3.4 port 5469 from 1.2.3.5 port 5469\" => {\n \"protocol\" => \"udp\",\n \"port\" => \"5469\",\n \"source\" => \"1.2.3.4\",\n \"destination\" => \"1.2.3.5\",\n \"dest_port\" => \"5469\"\n }\n },\n {\"allow to tcp ports 8000-8010 from 192.168.1.0/24\" => {\n \"port_range\" => \"8000..8010\",\n \"source\" => \"192.168.1.0/24\",\n \"protocol\" => \"tcp\" //protocol is mandatory when using port ranges\n }\n }\n ]\n }\n )\n```\n\n## Data Bags\nThe `firewall` data bag may be used with the `databag` recipe. It will contain items that map to role names (eg. the 'apache' role will map to the 'apache' item in the 'firewall' data bag). Either roles or recipes may be keys (role[webserver] is 'webserver', recipe[apache2] is 'apache2'). If you have recipe-specific firewall rules, you will need to replace the '::' with '**' (double underscores) (eg. recipe[apache2::mod_ssl] is 'apache2**mod_ssl' in the data bag item).\n\nThe items in the data bag will contain a 'rules' array of hashes to apply to the `['firewall']['rules']` attribute.\n\n```\n% knife data bag create firewall\n% knife data bag from file firewall examples/data_bags/firewall/apache2.json\n% knife data bag from file firewall examples/data_bags/firewall/apache2__mod_ssl.json\n```\n\n### Example 'firewall' data bag item\n\n```\n{\n \"id\": \"apache2\",\n \"rules\": [\n {\"http\": {\n \"port\": \"80\"\n }},\n {\"block http from 192.168.1.0/24\": {\n \"port\": \"80\",\n \"source\": \"192.168.1.0/24\",\n \"action\": \"deny\"\n }}\n ]\n}\n```\n\n## Resources/Providers\nThe `firewall` cookbook provides the `firewall` and `firewall_rule` LWRPs, for which there is a ufw provider.\n\n## License & Authors\n**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io))\n\n**Copyright:** 2011-2015, 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"},"dependencies":{"firewall":">= 2.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{"firewall/rules":{"display_name":"List of firewall rules for the node.","description":"List of firewall rules for the node. Possibly set by node, roles or data bags.","type":"array"},"firewall/securitylevel":{"display_name":"Security level of the node.","description":"Security level of the node, may be set by node, roles or environment."}},"groupings":{},"recipes":{}} \ No newline at end of file diff --git a/cookbooks/ufw/metadata.rb b/cookbooks/ufw/metadata.rb deleted file mode 100644 index 93c2e9e..0000000 --- a/cookbooks/ufw/metadata.rb +++ /dev/null @@ -1,21 +0,0 @@ -name "ufw" -maintainer "Opscode, Inc." -maintainer_email "matt@opscode.com" -license "Apache 2.0" -description "Installs/Configures ufw" -long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) -version "0.7.4" -depends "firewall", ">= 0.9" - -%w{ ubuntu }.each do |os| - supports os -end - -attribute "firewall/rules", - :display_name => "List of firewall rules for the node.", - :description => "List of firewall rules for the node. Possibly set by node, roles or data bags.", - :type => "array" - -attribute "firewall/securitylevel", - :display_name => "Security level of the node.", - :description => "Security level of the node, may be set by node, roles or environment." diff --git a/cookbooks/ufw/recipes/databag.rb b/cookbooks/ufw/recipes/databag.rb index 0a643ec..66bcad0 100644 --- a/cookbooks/ufw/recipes/databag.rb +++ b/cookbooks/ufw/recipes/databag.rb @@ -1,9 +1,9 @@ # -# Author:: Matt Ray +# Author:: Matt Ray # Cookbook Name:: ufw # Recipe:: databag # -# Copyright 2011, Opscode, Inc +# 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. @@ -18,12 +18,12 @@ # limitations under the License. # -#flatten the run_list to just the names of the roles and recipes in order +# flatten the run_list to just the names of the roles and recipes in order def run_list_names(run_list) names = [] run_list.each do |entry| Chef::Log.debug "ufw::databag:run_list_names+name: #{entry.name}" - if entry.name.index('::') #cookbook::recipe + if entry.name.index('::') # cookbook::recipe names.push(entry.name.sub('::', '__')) else names.push(entry.name) @@ -34,7 +34,7 @@ def run_list_names(run_list) end end Chef::Log.debug "ufw::databag:run_list_names+names: #{names}" - return names + names end rlist = run_list_names(node.run_list) @@ -46,13 +46,13 @@ Chef::Log.debug "ufw::databag:firewall:#{fw_db}" rlist.each do |entry| Chef::Log.debug "ufw::databag: \"#{entry}\"" - if fw_db.member?(entry) - #add the list of firewall rules to the current list - item = data_bag_item('firewall', entry) - rules = item['rules'] - node.set['firewall']['rules'].concat(rules) unless rules.nil? - end + next unless fw_db.member?(entry) + + # add the list of firewall rules to the current list + item = data_bag_item('firewall', entry) + rules = item['rules'] + node.set['firewall']['rules'].concat(rules) unless rules.nil? end -#now go apply the rules -include_recipe "ufw::default" +# now go apply the rules +include_recipe 'ufw::default' diff --git a/cookbooks/ufw/recipes/default.rb b/cookbooks/ufw/recipes/default.rb index 5c4981d..4e3c0d9 100644 --- a/cookbooks/ufw/recipes/default.rb +++ b/cookbooks/ufw/recipes/default.rb @@ -1,9 +1,9 @@ # -# Author:: Matt Ray +# Author:: Matt Ray # Cookbook Name:: ufw # Recipe:: default # -# Copyright 2011, Opscode, Inc +# 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. @@ -18,32 +18,32 @@ # limitations under the License. # -package "ufw" +package 'ufw' old_state = node['firewall']['state'] new_state = node['firewall']['rules'].to_s Chef::Log.debug "Old firewall state:#{old_state}" Chef::Log.debug "New firewall state:#{new_state}" -#check to see if the firewall rules changed. -#the rules are always changed the first run +# check to see if the firewall rules changed. +# the rules are always changed the first run if old_state == new_state - Chef::Log.info "Firewall rules unchanged." + Chef::Log.info 'Firewall rules unchanged.' else - Chef::Log.info "Firewall rules updated." + Chef::Log.info 'Firewall rules updated.' node.set['firewall']['state'] = new_state - #drop rules and re-enable - execute "ufw --force reset" + # drop rules and re-enable + execute 'ufw --force reset' - firewall "ufw" do - action :enable + firewall 'ufw' do + action :install end - #leave this on by default - firewall_rule "ssh" do + # leave this on by default + firewall_rule 'ssh' do port 22 - action :allow + action :create end node['firewall']['rules'].each do |rule_mash| @@ -64,8 +64,8 @@ else Chef::Log.debug "ufw:rule:dest_port #{params['dest_port']}" if params['dest_port'] Chef::Log.debug "ufw:rule:position #{params['position']}" if params['position'] act = params['action'] - act ||= "allow" - raise "ufw: port_range was specified to firewall_rule without protocol" if params['port_range'] && !params['protocol'] + act ||= 'create' + fail 'ufw: port_range was specified to firewall_rule without protocol' if params['port_range'] && !params['protocol'] Chef::Log.debug "ufw:rule:action :#{act}" firewall_rule rule do name params['name'] if params['name'] @@ -74,10 +74,10 @@ else interface params['interface'] if params['interface'] logging params['logging'].to_sym if params['logging'] port params['port'].to_i if params['port'] - if params['port_range'] - ends = params['port_range'].split('..').map{|d| Integer(d)} - port_range ends[0]..ends[1] - end + if params['port_range'] + ends = params['port_range'].split('..').map { |d| Integer(d) } + port_range ends[0]..ends[1] + end source params['source'] if params['source'] destination params['destination'] if params['destination'] dest_port params['dest_port'].to_i if params['dest_port'] diff --git a/cookbooks/ufw/recipes/disable.rb b/cookbooks/ufw/recipes/disable.rb index 132b696..6718bc6 100644 --- a/cookbooks/ufw/recipes/disable.rb +++ b/cookbooks/ufw/recipes/disable.rb @@ -1,9 +1,9 @@ # -# Author:: Matt Ray +# Author:: Matt Ray # Cookbook Name:: ufw # Recipe:: disable # -# Copyright 2011, Opscode, Inc +# 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. @@ -18,6 +18,6 @@ # limitations under the License. # -firewall "ufw" do +firewall 'ufw' do action :disable end diff --git a/cookbooks/ufw/recipes/recipes.rb b/cookbooks/ufw/recipes/recipes.rb index d35188b..dd03425 100644 --- a/cookbooks/ufw/recipes/recipes.rb +++ b/cookbooks/ufw/recipes/recipes.rb @@ -1,9 +1,9 @@ # -# Author:: Matt Ray +# Author:: Matt Ray # Cookbook Name:: ufw # Recipe:: recipes # -# Copyright 2011, Opscode, Inc +# 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. @@ -23,19 +23,19 @@ node.expand!.recipes.each do |recipe| Chef::Log.debug "ufw::recipes: #{recipe}" cookbook = recipe.split('::')[0] - #get the cookbook attributes if there are any - if recipe != cookbook and node[cookbook] and node[cookbook]['firewall'] and node[cookbook]['firewall']['rules'] + # get the cookbook attributes if there are any + if recipe != cookbook && node[cookbook] && node[cookbook]['firewall'] && node[cookbook]['firewall']['rules'] rules = node[cookbook]['firewall']['rules'] Chef::Log.debug "ufw::recipes:#{cookbook}:rules #{rules}" node.set['firewall']['rules'].concat(rules) unless rules.nil? end - #get the recipe attributes if there are any - if node[recipe] and node[recipe]['firewall'] and node[recipe]['firewall']['rules'] - rules = node[recipe]['firewall']['rules'] - Chef::Log.debug "ufw::recipes:#{recipe}:rules #{rules}" - node.set['firewall']['rules'].concat(rules) unless rules.nil? - end + # get the recipe attributes if there are any + next unless node[recipe] && node[recipe]['firewall'] && node[recipe]['firewall']['rules'] + + rules = node[recipe]['firewall']['rules'] + Chef::Log.debug "ufw::recipes:#{recipe}:rules #{rules}" + node.set['firewall']['rules'].concat(rules) unless rules.nil? end -#now go apply the rules -include_recipe "ufw::default" +# now go apply the rules +include_recipe 'ufw::default' diff --git a/cookbooks/ufw/recipes/securitylevel.rb b/cookbooks/ufw/recipes/securitylevel.rb index c642574..bfc2ad2 100644 --- a/cookbooks/ufw/recipes/securitylevel.rb +++ b/cookbooks/ufw/recipes/securitylevel.rb @@ -1,9 +1,9 @@ # -# Author:: Matt Ray +# Author:: Matt Ray # Cookbook Name:: ufw # Recipe:: securitylevel # -# Copyright 2011, Opscode, Inc +# 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. @@ -22,20 +22,20 @@ securitylevel = node['firewall']['securitylevel'] Chef::Log.info "ufw::securitylevel:#{securitylevel}" -#verify that only 1 "color" security group is applied" -count = node.expand!.roles.count {|role| role =~ /SecurityLevel-(Red|Green|Yellow)/ } +# verify that only 1 "color" security group is applied" +count = node.expand!.roles.count { |role| role =~ /SecurityLevel-(Red|Green|Yellow)/ } if count > 1 - raise Chef::Exceptions::AmbiguousRunlistSpecification, "conflicting SecurityLevel-'color' roles, only 1 may be applied." + fail Chef::Exceptions::AmbiguousRunlistSpecification, "conflicting SecurityLevel-'color' roles, only 1 may be applied." end case securitylevel when 'red' - #put special stuff for red here + # put special stuff for red here when 'yellow' - #put special stuff for red here + # put special stuff for red here when 'green' - #put special stuff for red here + # put special stuff for red here end -#now go apply the rules -include_recipe "ufw::default" +# now go apply the rules +include_recipe 'ufw::default' diff --git a/cookbooks/users/CHANGELOG.md b/cookbooks/users/CHANGELOG.md index f812933..14f0a03 100644 --- a/cookbooks/users/CHANGELOG.md +++ b/cookbooks/users/CHANGELOG.md @@ -1,77 +1,81 @@ -users Cookbook CHANGELOG -======================== +# users Cookbook CHANGELOG This file is used to list changes made in each version of the users cookbook. -v1.8.2 (2015-03-18) -------------------- +## 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 https://github.com/bbatsov/rubocop/issues/2608 +- 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.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) -------------------- +## 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 +- [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) -------------------- +## 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 ------- +## 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 ------- +## v1.5.2 ### Bug - **[COOK-3215](https://tickets.opscode.com/browse/COOK-3215)** - Make `group_id` optional -v1.5.0 ------- +## v1.5.0 - [COOK-2427] - Mistakenly released instead of sudo :-). -v1.4.0 ------- +## 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 ------- +## v1.3.0 - [COOK-1842] - allow specifying private SSH keys - [COOK-2021] - Empty default recipe for including users LWRPs -v1.2.0 ------- +## 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 ------- +## v1.1.4 - [COOK-1396] - removed users get recreated - [COOK-1433] - resolve foodcritic warnings - [COOK-1583] - set passwords for users -v1.1.2 ------- +## v1.1.2 - [COOK-1076] - authorized_keys template not found in another cookbook -v1.1.0 ------- +## 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/MAINTAINERS.md b/cookbooks/users/MAINTAINERS.md new file mode 100644 index 0000000..c6a51ae --- /dev/null +++ b/cookbooks/users/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 +* [Tim Smith](https://github.com/tas50) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Sean OMeara](https://github.com/someara) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) diff --git a/cookbooks/users/README.md b/cookbooks/users/README.md index 8fef5b4..9a866a6 100644 --- a/cookbooks/users/README.md +++ b/cookbooks/users/README.md @@ -1,35 +1,181 @@ -users Cookbook -============== -![Build Status](https://travis-ci.org/opscode-cookbooks/users.svg?branch=master) +# 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) -Creates users from a databag search. +Manages OS users from databags. +## Scope -Requirements ------------- -### Platforms -- Debian, Ubuntu -- CentOS, Red Hat, Fedora -- FreeBSD +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. -A data bag populated with user objects must exist. The default data -bag in this recipe is `users`. See USAGE. +## Requirements +A data bag populated with user objects must exist. The default data bag in this recipe is `users`. See USAGE. -Usage ------ -To include just the LWRPs in your cookbook, use: +### Chef -```ruby -include_recipe "users" +- Chef 11+ + +### Platform Support + +The following platforms have been tested with Test Kitchen: + +- Debian / Ubuntu and derivatives +- RHEL and derivatives +- Fedora +- FreeBSD / OpenBSD +- Mac OS X + +### Cookbook Dependencies +- 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: + +```ruby +users_manage 'GROUPNAME' do + group_id GROUPID + action [:remove, :create] + data_bag 'DATABAG_NAME' +end +``` + +Example: + +```ruby +users_manage 'testgroup' do + group_id 3000 + action [:remove, :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" +} +``` + +### 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 .ssh/authorized_keys +* `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 [:remove, :create] +end +``` + +Removes, then creates the `testgroup` group, and users defined in the `test_home_dir` databag. + +```ruby +users_manage 'testgroup' do + group_id 3000 + action [:remove, :create] + data_bag 'test_home_dir' +end +``` + +Removes, then 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 [:remove, :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 + +`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 [ :remove, :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. This may become an attribute at a later date. + +## 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 @@ -38,7 +184,7 @@ $ knife data bag create users Create a user in the data_bag/users/ directory. -When using an [Omnibus ruby](http://tickets.opscode.com/browse/CHEF-2848), one can specify an optional password hash. This will be used as the user's password. +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. @@ -48,14 +194,14 @@ $ 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. -```javascript +```json { "id": "bofh", - "ssh_keys": "ssh-rsa AAAAB3Nz...yhCw== bofh", + "ssh_keys": "ssh-rsa AAAAB3Nz...yhCw== bofh" } ``` -```javascript +```json { "id": "bofh", "password": "$1$d...HgH0", @@ -66,12 +212,7 @@ Note: The ssh_keys attribute below can be either a String or an Array. However, "groups": [ "sysadmin", "dba", "devops" ], "uid": 2001, "shell": "\/bin\/bash", - "comment": "BOFH", - "nagios": { - "pager": "8005551212@txt.att.net", - "email": "bofh@example.com" - }, - "openid": "bofh.myopenid.com" + "comment": "BOFH" } ``` @@ -113,32 +254,23 @@ And then change the action to "remove": } ``` -* Note only user bags with the "action : remove" and a search-able "group" attribute will be purged by the :remove action. - -The sysadmins recipe makes use of the `users_manage` Lightweight Resource Provider (LWRP), and looks like this: - -```ruby -users_manage "sysadmin" do - group_id 2300 - action [ :remove, :create ] -end -``` - -Note this LWRP 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 LWRP is `:create` only. +- 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 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` +- 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: @@ -150,35 +282,26 @@ users_manage "postmaster" do end ``` -The latest version of 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: +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 default search, and Unix group is sysadmin. - -The recipe, by default, will also create the sysadmin group. If you're using the chef sudo cookbook, they'll have sudo access in the default site-cookbooks template. They won't have passwords though, so the sudo cookbook's template needs to be adjusted so the sysadmin group has NOPASSWD. - -The sysadmin group will be created with GID 2300. This may become an attribute at a later date. +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. - -Chef Solo ---------- +## Chef Solo As of version 1.4.0, this cookbook might work with Chef Solo when using [chef-solo-search by edelight](https://github.com/edelight/chef-solo-search). That cookbook is not a dependency of this one as Chef solo doesn't support dependency resolution using cookbook metadata - all cookbooks must be provided to the node manually when using Chef Solo. +## License & Authors +**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io)) -License & Authors ------------------ -- Author:: Joshua Timberman () -- Author:: Seth Chisamore () - -```text -Copyright:: 2009-2015, Chef Software, Inc +**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 diff --git a/cookbooks/users/libraries/helpers.rb b/cookbooks/users/libraries/helpers.rb index ae46a6d..e0a358b 100644 --- a/cookbooks/users/libraries/helpers.rb +++ b/cookbooks/users/libraries/helpers.rb @@ -7,13 +7,11 @@ module Users # # @return [String] def fs_type(mount) - begin - # Doesn't support macosx - stat = Mixlib::ShellOut.new("stat -f -L -c %T #{mount} 2>&1").run_command - stat.stdout.chomp - rescue - 'none' - end + # 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. @@ -22,6 +20,14 @@ module Users def fs_remote?(mount) fs_type(mount) == 'nfs' ? true : 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 end end diff --git a/cookbooks/users/metadata.json b/cookbooks/users/metadata.json index d62a9d2..deac531 100644 --- a/cookbooks/users/metadata.json +++ b/cookbooks/users/metadata.json @@ -1,40 +1 @@ -{ - "name": "users", - "version": "1.8.2", - "description": "Creates users from a databag search", - "long_description": "users Cookbook\n==============\n![Build Status](https://travis-ci.org/opscode-cookbooks/users.svg?branch=master)\n\nCreates users from a databag search.\n\n\nRequirements\n------------\n### Platforms\n- Debian, Ubuntu\n- CentOS, Red Hat, Fedora\n- FreeBSD\n\nA data bag populated with user objects must exist. The default data\nbag in this recipe is `users`. See USAGE.\n\n\nUsage\n-----\nTo include just the LWRPs in your cookbook, use:\n\n```ruby\ninclude_recipe \"users\"\n```\n\nOtherwise, this cookbook is specific for setting up `sysadmin` group and users with the sysadmins recipe for now.\n\n```ruby\ninclude_recipe \"users::sysadmins\"\n```\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\nWhen using an [Omnibus ruby](http://tickets.opscode.com/browse/CHEF-2848), one can specify an optional password hash. This 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```javascript\n{\n \"id\": \"bofh\",\n \"ssh_keys\": \"ssh-rsa AAAAB3Nz...yhCw== bofh\",\n}\n```\n\n```javascript\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 \"nagios\": {\n \"pager\": \"8005551212@txt.att.net\",\n \"email\": \"bofh@example.com\"\n },\n \"openid\": \"bofh.myopenid.com\"\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\nThe sysadmins recipe makes use of the `users_manage` Lightweight Resource Provider (LWRP), and looks like this:\n\n```ruby\nusers_manage \"sysadmin\" do\n group_id 2300\n action [ :remove, :create ]\nend\n```\n\nNote this LWRP 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 LWRP is `:create` only.\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 - data_bag `mail`\n * You want to search for a different group attribute named\n `postmaster`. You may change the search_group attribute. This\n attribute defaults to the LWRP resource name.\n - search_group `postmaster`\n * You want to add the users to a security group other than the\n lightweight resource name. You may change the group_name attribute.\n This attribute also defaults to the LWRP resource name.\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\nThe latest version of 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:\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. The default search, and Unix group is sysadmin.\n\nThe recipe, by default, will also create the sysadmin group. If you're using the chef sudo cookbook, they'll have sudo access in the default site-cookbooks template. They won't have passwords though, so the sudo cookbook's template needs to be adjusted so the sysadmin group has NOPASSWD.\n\nThe sysadmin group will be created with GID 2300. This may become an attribute at a later date.\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\nChef Solo\n---------\nAs of version 1.4.0, this cookbook might work with Chef Solo when using [chef-solo-search by edelight](https://github.com/edelight/chef-solo-search). That cookbook is not a dependency of this one as Chef solo doesn't support dependency resolution using cookbook metadata - all cookbooks must be provided to the node manually when using Chef Solo.\n\n\nLicense & Authors\n-----------------\n- Author:: Joshua Timberman ()\n- Author:: Seth Chisamore ()\n\n```text\nCopyright:: 2009-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", - "source_url": "https://github.com/opscode-cookbooks/users", - "issues_url": "https://github.com/opscode-cookbooks/users/issues", - "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" - }, - "dependencies": { - }, - "recommendations": { - }, - "suggestions": { - }, - "conflicting": { - }, - "providing": { - }, - "replacing": { - }, - "attributes": { - }, - "groupings": { - }, - "recipes": { - "users": "Empty recipe for including LWRPs", - "users::sysadmins": "Create and manage sysadmin group" - } -} \ No newline at end of file +{"name":"users","version":"2.0.3","description":"Creates users from a databag search","long_description":"# users Cookbook\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\nA data bag populated with user objects must exist. The default data bag in this recipe is `users`. See USAGE.\n\n### Chef\n\n- Chef 11+\n\n### Platform Support\n\nThe following platforms have been tested with Test Kitchen:\n\n- Debian / Ubuntu and derivatives\n- RHEL and derivatives \n- Fedora \n- FreeBSD / OpenBSD\n- Mac OS X\n\n### Cookbook Dependencies\n- none\n\n## Usage\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:\n\n```ruby\nusers_manage 'GROUPNAME' do\n group_id GROUPID\n action [:remove, :create]\n data_bag 'DATABAG_NAME'\nend\n```\n\nExample:\n\n```ruby\nusers_manage 'testgroup' do\n group_id 3000\n action [:remove, :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\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 .ssh/authorized_keys\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\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 [:remove, :create]\nend\n```\n\nRemoves, then creates 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 [:remove, :create]\n data_bag 'test_home_dir'\nend\n```\n\nRemoves, then creates 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 [:remove, :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`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 [ :remove, :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. This may become an attribute at a later date.\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- You want to search a different data bag specific to a role such as\n- mail. You may change the data_bag searched.\n - data_bag `mail`\n\n- You want to search for a different group attribute named\n- `postmaster`. You may change the search_group attribute. This\n- attribute defaults to the LWRP resource name.\n - search_group `postmaster`\n\n- You want to add the users to a security group other than the\n- lightweight resource name. You may change the group_name attribute.\n- This attribute also defaults to the LWRP resource name.\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## Chef Solo\nAs of version 1.4.0, this cookbook might work with Chef Solo when using [chef-solo-search by edelight](https://github.com/edelight/chef-solo-search). That cookbook is not a dependency of this one as Chef solo doesn't support dependency resolution using cookbook metadata - all cookbooks must be provided to the node manually when using Chef Solo.\n\n## License & Authors\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","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"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{"users::default":"Empty recipe for including LWRPs","users::sysadmins":"Create and manage sysadmin group"}} \ No newline at end of file diff --git a/cookbooks/users/providers/manage.rb b/cookbooks/users/providers/manage.rb index 2132549..775d496 100644 --- a/cookbooks/users/providers/manage.rb +++ b/cookbooks/users/providers/manage.rb @@ -3,7 +3,7 @@ # Provider:: manage # # Copyright 2011, Eric G. Wolfe -# Copyright 2009-2011, Chef Software, Inc. +# Copyright 2009-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. @@ -18,92 +18,93 @@ # limitations under the License. # -use_inline_resources if defined?(use_inline_resources) +use_inline_resources def whyrun_supported? true end -def initialize(*args) - super - @action = :create -end - def chef_solo_search_installed? - klass = ::Search::const_get('Helper') + klass = ::Search.const_get('Helper') return klass.is_a?(Class) rescue NameError return false end +def search_missing? + Chef::Config[:solo] && !(Chef::Config[:local_mode] || chef_solo_search_installed?) +end + action :remove do - if Chef::Config[:solo] and not chef_solo_search_installed? - Chef::Log.warn("This recipe uses search. Chef Solo does not support search unless you install the chef-solo-search cookbook.") + if search_missing? + Chef::Log.warn('This recipe uses search. Chef Solo does not support search unless you install the chef-solo-search cookbook.') else 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 end action :create do - security_group = Array.new + users_groups = {} + users_groups[new_resource.group_name] = [] - if Chef::Config[:solo] and not chef_solo_search_installed? - Chef::Log.warn("This recipe uses search. Chef Solo does not support search unless you install the chef-solo-search cookbook.") + if search_missing? + Chef::Log.warn('This recipe uses search. Chef Solo does not support search unless you install the chef-solo-search cookbook.') else search(new_resource.data_bag, "groups:#{new_resource.search_group} AND NOT action:remove") do |u| u['username'] ||= u['id'] - security_group << u['username'] + u['groups'].each do |g| + users_groups[g] = [] unless users_groups.key?(g) + users_groups[g] << u['username'] + end - if node['apache'] and node['apache']['allowed_openids'] + if node['apache'] && node['apache']['allowed_openids'] Array(u['openid']).compact.each do |oid| node.default['apache']['allowed_openids'] << oid unless node['apache']['allowed_openids'].include?(oid) end end - # Set home_basedir based on platform_family + # Platform specific checks + # Set home_basedir + # Set shell on FreeBSD + home_basedir = '/home' + case node['platform_family'] when 'mac_os_x' home_basedir = '/Users' - when 'debian', 'rhel', 'fedora', 'arch', 'suse', 'freebsd' - home_basedir = '/home' + when 'freebsd' + # Check if we need to prepend shell with /usr/local/? + u['shell'] = (!File.exist?(u['shell']) && File.exist?("/usr/local#{u['shell']}") ? "/usr/local#{u['shell']}" : '/bin/sh') end # Set home to location in data bag, # or a reasonable default ($home_basedir/$user). - if u['home'] - home_dir = u['home'] - else - home_dir = "#{home_basedir}/#{u['username']}" - end + 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. - if u['gid'] and u['gid'].kind_of?(Numeric) - group u['username'] do - gid u['gid'] - end + group u['username'] do + gid validate_id(u['gid']) + 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 u['uid'] - if u['gid'] - gid u['gid'] - end + uid validate_id(u['uid']) + gid validate_id(u['gid']) if u['gid'] shell u['shell'] comment u['comment'] password u['password'] if u['password'] - if home_dir == "/dev/null" - supports :manage_home => false - else - supports :manage_home => true - end + supports manage_home: manage_home home home_dir action u['action'] if u['action'] end @@ -112,65 +113,72 @@ action :create do Chef::Log.debug("Managing home files for #{u['username']}") directory "#{home_dir}/.ssh" do - owner u['username'] - group u['gid'] || u['username'] - mode "0700" + 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 - if u['ssh_keys'] - template "#{home_dir}/.ssh/authorized_keys" do - source "authorized_keys.erb" - cookbook new_resource.cookbook - owner u['username'] - group u['gid'] || u['username'] - mode "0600" - variables :ssh_keys => u['ssh_keys'] - 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' + variables ssh_keys: u['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" + 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" + source 'private_key.erb' cookbook new_resource.cookbook - owner u['id'] - group u['gid'] || u['id'] - mode "0400" - variables :private_key => u['ssh_private_key'] + 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" + 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" + source 'public_key.pub.erb' cookbook new_resource.cookbook - owner u['id'] - group u['gid'] || u['id'] - mode "0400" - variables :public_key => u['ssh_public_key'] + 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 end group new_resource.group_name do - if new_resource.group_id - gid new_resource.group_id - end - members security_group + gid new_resource.group_id if new_resource.group_id + members users_groups[new_resource.group_name] end end private -def manage_home_files?(home_dir, user) +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" + if home_dir == '/dev/null' false elsif fs_remote?(home_dir) new_resource.manage_nfs_home_dirs ? true : false diff --git a/cookbooks/users/recipes/default.rb b/cookbooks/users/recipes/default.rb index 7c4e78d..9908546 100644 --- a/cookbooks/users/recipes/default.rb +++ b/cookbooks/users/recipes/default.rb @@ -2,7 +2,7 @@ # Cookbook Name:: users # Recipe:: default # -# Copyright 2009-2012, Chef Software, Inc. +# Copyright 2009-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. diff --git a/cookbooks/users/recipes/sysadmins.rb b/cookbooks/users/recipes/sysadmins.rb index 8e65053..c017b10 100644 --- a/cookbooks/users/recipes/sysadmins.rb +++ b/cookbooks/users/recipes/sysadmins.rb @@ -3,7 +3,7 @@ # Recipe:: sysadmins # # Copyright 2011, Eric G. Wolfe -# Copyright 2009-2011, Chef Software, Inc. +# Copyright 2009-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. @@ -20,7 +20,7 @@ # Searches data bag "users" for groups attribute "sysadmin". # Places returned users in Unix group "sysadmin" with GID 2300. -users_manage "sysadmin" do +users_manage 'sysadmin' do group_id 2300 - action [ :remove, :create ] + action [:remove, :create] end diff --git a/cookbooks/users/resources/manage.rb b/cookbooks/users/resources/manage.rb index a74c84b..9763696 100644 --- a/cookbooks/users/resources/manage.rb +++ b/cookbooks/users/resources/manage.rb @@ -19,6 +19,7 @@ # Data bag user object needs an "action": "remove" tag to actually be removed by the action. actions :create, :remove +default_action :create state_attrs :cookbook, :data_bag, @@ -31,14 +32,9 @@ state_attrs :cookbook, # :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 -attribute :data_bag, :kind_of => String, :default => "users" -attribute :search_group, :kind_of => String, :name_attribute => true -attribute :group_name, :kind_of => String, :name_attribute => true -attribute :group_id, :kind_of => Integer -attribute :cookbook, :kind_of => String, :default => "users" -attribute :manage_nfs_home_dirs, :kind_of => [TrueClass, FalseClass], :default => true - -def initialize(*args) - super - @action = :create -end +attribute :data_bag, kind_of: String, default: 'users' +attribute :search_group, kind_of: String, name_attribute: true +attribute :group_name, kind_of: String, name_attribute: true +attribute :group_id, kind_of: Integer +attribute :cookbook, kind_of: String, default: 'users' +attribute :manage_nfs_home_dirs, kind_of: [TrueClass, FalseClass], default: true diff --git a/cookbooks/users/templates/default/authorized_keys.erb b/cookbooks/users/templates/default/authorized_keys.erb index bd969f1..f656d5f 100644 --- a/cookbooks/users/templates/default/authorized_keys.erb +++ b/cookbooks/users/templates/default/authorized_keys.erb @@ -1,4 +1,4 @@ -# Generated by Chef for <%= node['fqdn'] %> +# Generated by Chef # Local modifications will be overwritten. <% Array(@ssh_keys).each do |key| %> diff --git a/cookbooks/windows/CHANGELOG.md b/cookbooks/windows/CHANGELOG.md index a352183..1fa57ef 100644 --- a/cookbooks/windows/CHANGELOG.md +++ b/cookbooks/windows/CHANGELOG.md @@ -1,320 +1,362 @@ -windows Cookbook CHANGELOG -======================= -This file is used to list changes made in each version of the windows cookbook. - -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 +windows Cookbook CHANGELOG +======================= +This file is used to list changes made in each version of the windows cookbook. + +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/README.md b/cookbooks/windows/README.md index 3559281..64cb14e 100644 --- a/cookbooks/windows/README.md +++ b/cookbooks/windows/README.md @@ -1,749 +1,890 @@ -Windows Cookbook -================ -Provides a set of Windows-specific primitives (Chef resources) meant to aid in the creation of cookbooks/recipes targeting the Windows platform. - - -Requirements -------------- -Version 1.3.0+ of this cookbook requires Chef 0.10.10+. - - -### Platforms -* Windows XP -* Windows Vista -* Windows Server 2003 R2 -* Windows 7 -* Windows Server 2008 (R1, R2) - -The `windows_task` LWRP requires Windows Server 2008 due to its API usage. - -### Cookbooks -The following cookbooks provided by Chef Software are required as noted: - -* chef_handler (`windows::reboot_handler` leverages the chef_handler LWRP) - -Attributes ----------- -* `node['windows']['allow_pending_reboots']` - used to configure the `WindowsRebootHandler` (via the `windows::reboot_handler` recipe) to act on pending reboots. default is true (ie act on pending reboots). The value of this attribute only has an effect if the `windows::reboot_handler` is in a node's run list. -* `node['windows']['allow_reboot_on_failure']` - used to register the `WindowsRebootHandler` (via the `windows::reboot_handler` recipe) as an exception handler too to act on reboots not only at the end of successful Chef runs, but even at the end of failed runs. default is false (ie reboot only after successful runs). The value of this attribute only has an effect if the `windows::reboot_handler` is in a node's run list. - - -Resource/Provider ------------------ -### windows_auto_run -#### Actions -- :create: Create an item to be run at login -- :remove: Remove an item that was previously setup to run at login - -#### Attribute Parameters -- :name: Name attribute. The name of the value to be stored in the registry -- :program: The program to be run at login -- :args: The arguments for the program - -#### Examples -Run BGInfo at login - -```ruby -windows_auto_run 'BGINFO' do - program 'C:/Sysinternals/bginfo.exe' - args '\'C:/Sysinternals/Config.bgi\' /NOLICPROMPT /TIMER:0' - not_if { Registry.value_exists?(AUTO_RUN_KEY, 'BGINFO') } - action :create -end -``` - -### windows_batch -(Chef 11.6.0 includes a built-in [batch](http://docs.chef.io/resource_batch.html) resource, so use that in preference to `windows_batch` if possible.) - -Execute a batch script using the cmd.exe interpreter (much like the script resources for bash, csh, powershell, perl, python and ruby). A temporary file is created and executed like other script resources, rather than run inline. By their nature, Script resources are not idempotent, as they are completely up to the user's imagination. Use the `not_if` or `only_if` meta parameters to guard the resource for idempotence. - -#### Actions -- :run: run the batch file - -#### Attribute Parameters -- command: name attribute. Name of the command to execute. -- code: quoted string of code to execute. -- creates: a file this command creates - if the file exists, the command will not be run. -- cwd: current working directory to run the command from. -- flags: command line flags to pass to the interpreter when invoking. -- user: A user name or user ID that we should change to before running this command. -- group: A group name or group ID that we should change to before running this command. - -#### Examples -```ruby -windows_batch 'unzip_and_move_ruby' do - code <<-EOH - 7z.exe x #{Chef::Config[:file_cache_path]}/ruby-1.8.7-p352-i386-mingw32.7z -oC:\\source -r -y - xcopy C:\\source\\ruby-1.8.7-p352-i386-mingw32 C:\\ruby /e /y - EOH -end -``` - -```ruby -windows_batch 'echo some env vars' do - code <<-EOH - echo %TEMP% - echo %SYSTEMDRIVE% - echo %PATH% - echo %WINDIR% - EOH -end -``` - -### windows_feature -Windows Roles and Features can be thought of as built-in operating system packages that ship with the OS. A server role is a set of software programs that, when they are installed and properly configured, lets a computer perform a specific function for multiple users or other computers within a network. A Role can have multiple Role Services that provide functionality to the Role. Role services are software programs that provide the functionality of a role. Features are software programs that, although they are not directly parts of roles, can support or augment the functionality of one or more roles, or improve the functionality of the server, regardless of which roles are installed. Collectively we refer to all of these attributes as 'features'. - -This resource allows you to manage these 'features' in an unattended, idempotent way. - -There are two providers for the `windows_features` which map into Microsoft's two major tools for managing roles/features: [Deployment Image Servicing and Management (DISM)](http://msdn.microsoft.com/en-us/library/dd371719%28v=vs.85%29.aspx) and [Servermanagercmd](http://technet.microsoft.com/en-us/library/ee344834%28WS.10%29.aspx) (The CLI for Server Manager). As Servermanagercmd is deprecated, Chef will set the default provider to `Chef::Provider::WindowsFeature::DISM` if DISM is present on the system being configured. The default provider will fall back to `Chef::Provider::WindowsFeature::ServerManagerCmd`. - -For more information on Roles, Role Services and Features see the [Microsoft TechNet article on the topic](http://technet.microsoft.com/en-us/library/cc754923.aspx). For a complete list of all features that are available on a node type either of the following commands at a command prompt: - -```text -dism /online /Get-Features -servermanagercmd -query -``` - -#### Actions -- :install: install a Windows role/feature -- :remove: remove a Windows role/feature - -#### Attribute Parameters -- feature_name: name of the feature/role to install. The same feature may have different names depending on the provider used (ie DHCPServer vs DHCP; DNS-Server-Full-Role vs DNS). -- all: Boolean. Optional. Default: false. DISM provider only. Forces all dependencies to be installed. -- source: String. Optional. DISM provider only. Uses local repository for feature install. - -#### Providers -- **Chef::Provider::WindowsFeature::DISM**: Uses Deployment Image Servicing and Management (DISM) to manage roles/features. -- **Chef::Provider::WindowsFeature::ServerManagerCmd**: Uses Server Manager to manage roles/features. -- **Chef::Provider::WindowsFeaturePowershell**: Uses Powershell to manage roles/features. (see [COOK-3714](https://tickets.chef.io/browse/COOK-3714) - -#### Examples -Enable the node as a DHCP Server - -```ruby -windows_feature 'DHCPServer' do - action :install -end -``` - -Enable TFTP - -```ruby -windows_feature 'TFTP' do - action :install -end -``` - -Enable .Net 3.5.1 on Server 2012 using repository files on DVD and -install all dependencies - -```ruby -windows_feature "NetFx3" do - action :install - all true - source "d:\sources\sxs" -end -``` - -Disable Telnet client/server - -```ruby -%w[TelnetServer TelnetClient].each do |feature| - windows_feature feature do - action :remove - end -end -``` - -### windows_font -Installs a font. - -Font files should be included in the cookbooks - -#### Actions -- :install: install a font to the system fonts directory. - -#### Attribute Parameters -- file: The name of the font file name to install. It should exist in the files/default directory of the cookbook you're calling windows_font from. Defaults to the resource name. - -#### Examples - -```ruby -windows_font 'Code New Roman.otf' -``` - -### windows_package -Manage Windows application packages in an unattended, idempotent way. - -The following application installers are currently supported: - -* MSI packages -* InstallShield -* Wise InstallMaster -* Inno Setup -* Nullsoft Scriptable Install System - -If the proper installer type is not passed into the resource's installer_type attribute, the provider will do it's best to identify the type by introspecting the installation package. If the installation type cannot be properly identified the `:custom` value can be passed into the installer_type attribute along with the proper flags for silent/quiet installation (using the `options` attribute..see example below). - -__PLEASE NOTE__ - For proper idempotence the resource's `package_name` should be the same as the 'DisplayName' registry value in the uninstallation data that is created during package installation. The easiest way to definitively find the proper 'DisplayName' value is to install the package on a machine and search for the uninstall information under the following registry keys: - -* `HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall` -* `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Uninstall` -* `HKEY_LOCAL_MACHINE\Software\Wow6464Node\Microsoft\Windows\CurrentVersion\Uninstall` - -For maximum flexibility the `source` attribute supports both remote and local installation packages. - -#### Actions -- :install: install a package -- :remove: remove a package. The remove action is completely hit or miss as many application uninstallers do not support a full silent/quiet mode. - -#### Attribute Parameters -- package_name: name attribute. The 'DisplayName' of the application installation package. -- source: The source of the windows installer. This can either be a URI or a local path. -- installer_type: They type of windows installation package. valid values are: :msi, :inno, :nsis, :wise, :installshield, :custom. If this value is not provided, the provider will do it's best to identify the installer type through introspection of the file. -- checksum: useful if source is remote, the SHA-256 checksum of the file--if the local file matches the checksum, Chef will not download it -- options: Additional options to pass the underlying installation command -- timeout: set a timeout for the package download (default 600 seconds) -- version: The version number of this package, as indicated by the 'DisplayVersion' value in one of the 'Uninstall' registry keys. If the given version number does equal the 'DisplayVersion' in the registry, the package will be installed. -- success_codes: set an array of possible successful installation - return codes. Previously this was hardcoded, but certain MSIs may - have a different return code, e.g. 3010 for reboot required. Must be - an array, and defaults to `[0, 42, 127]`. - -#### Examples - -Install PuTTY (InnoSetup installer) -```ruby -windows_package 'PuTTY version 0.60' do - source 'http://the.earth.li/~sgtatham/putty/latest/x86/putty-0.60-installer.exe' - installer_type :inno - action :install -end -``` - -Install 7-Zip (MSI installer) -```ruby -windows_package '7-Zip 9.20 (x64 edition)' do - source 'http://downloads.sourceforge.net/sevenzip/7z920-x64.msi' - action :install -end -``` - -Install Notepad++ (Y U No Emacs?) using a local installer -```ruby -windows_package 'Notepad++' do - source 'c:/installation_files/npp.5.9.2.Installer.exe' - action :install -end -``` - -Install VLC for that Xvid (NSIS installer) -```ruby -windows_package 'VLC media player 1.1.10' do - source 'http://superb-sea2.dl.sourceforge.net/project/vlc/1.1.10/win32/vlc-1.1.10-win32.exe' - action :install -end -``` - -Install Firefox as custom installer and manually set the silent install flags -```ruby -windows_package 'Mozilla Firefox 5.0 (x86 en-US)' do - source 'http://archive.mozilla.org/pub/mozilla.org/mozilla.org/firefox/releases/5.0/win32/en-US/Firefox%20Setup%205.0.exe' - options '-ms' - installer_type :custom - action :install -end -``` - -Google Chrome FTW (MSI installer) -```ruby -windows_package 'Google Chrome' do - source 'https://dl-ssl.google.com/tag/s/appguid%3D%7B8A69D345-D564-463C-AFF1-A69D9E530F96%7D%26iid%3D%7B806F36C0-CB54-4A84-A3F3-0CF8A86575E0%7D%26lang%3Den%26browser%3D3%26usagestats%3D0%26appname%3DGoogle%2520Chrome%26needsadmin%3Dfalse/edgedl/chrome/install/GoogleChromeStandaloneEnterprise.msi' - action :install -end -``` - -Remove Google Chrome -```ruby -windows_package 'Google Chrome' do - action :remove -end -``` - -Remove 7-Zip -```ruby -windows_package '7-Zip 9.20 (x64 edition)' do - action :remove -end -``` - -### windows_printer_port - -Create and delete TCP/IPv4 printer ports. - -#### Actions -- :create: Create a TCIP/IPv4 printer port. This is the default action. -- :delete: Delete a TCIP/IPv4 printer port - -#### Attribute Parameters -- :ipv4_address: Name attribute. Required. IPv4 address, e.g. '10.0.24.34' -- :port_name: Port name. Optional. Defaults to 'IP_' + :ipv4_address -- :port_number: Port number. Optional. Defaults to 9100. -- :port_description: Port description. Optional. -- :snmp_enabled: Boolean. Optional. Defaults to false. -- :port_protocol: Port protocol, 1 (RAW), or 2 (LPR). Optional. Defaults to 1. - -#### Examples - -Create a TCP/IP printer port named 'IP_10.4.64.37' with all defaults -```ruby -windows_printer_port '10.4.64.37' do -end -``` - -Delete a printer port -```ruby -windows_printer_port '10.4.64.37' do - action :delete -end -``` - -Delete a port with a custom port_name -```ruby -windows_printer_port '10.4.64.38' do - port_name 'My awesome port' - action :delete -end -``` - -Create a port with more options -```ruby -windows_printer_port '10.4.64.39' do - port_name 'My awesome port' - snmp_enabled true - port_protocol 2 -end -``` - -### windows_printer - -Create Windows printer. Note that this doesn't currently install a printer -driver. You must already have the driver installed on the system. - -The Windows Printer LWRP will automatically create a TCP/IP printer port for you using the `ipv4_address` property. If you want more granular control over the printer port, just create it using the `windows_printer_port` LWRP before creating the printer. - -#### Actions -- :create: Create a new printer -- :delete: Delete a new printer - -#### Attribute Parameters -- :device_id: Name attribute. Required. Printer queue name, e.g. 'HP LJ 5200 in fifth floor copy room' -- :comment: Optional string describing the printer queue. -- :default: Boolean. Optional. Defaults to false. Note that Windows sets the first printer defined to the default printer regardless of this setting. -- :driver_name: String. Required. Exact name of printer driver. Note that the printer driver must already be installed on the node. -- :location: Printer location, e.g. 'Fifth floor copy room', or 'US/NYC/Floor42/Room4207' -- :shared: Boolean. Defaults to false. -- :share_name: Printer share name. -- :ipv4_address: Printer IPv4 address, e.g. '10.4.64.23'. You don't have to be able to ping the IP addresss to set it. Required. - -An error of "Set-WmiInstance : Generic failure" is most likely due to the printer driver name not matching or not being installed. - -#### Examples - -Create a printer -```ruby -windows_printer 'HP LaserJet 5th Floor' do - driver_name 'HP LaserJet 4100 Series PCL6' - ipv4_address '10.4.64.38' -end -``` - -Delete a printer. Note: this doesn't delete the associated printer port. See `windows_printer_port` above for how to delete the port. -```ruby -windows_printer 'HP LaserJet 5th Floor' do - action :delete -end -``` - -### windows_reboot -Sets required data in the node's run_state to notify `WindowsRebootHandler` a reboot is requested. If Chef run completes successfully a reboot will occur if the `WindowsRebootHandler` is properly registered as a report handler. As an action of `:request` will cause a node to reboot every Chef run, this resource is usually notified by other resources...ie restart node after a package is installed (see example below). - -#### Actions -- :request: requests a reboot at completion of successful Cher run. requires `WindowsRebootHandler` to be registered as a report handler. -- :cancel: remove reboot request from node.run_state. this will cancel *ALL* previously requested reboots as this is a binary state. - -#### Attribute Parameters -- :timeout: Name attribute. timeout delay in seconds to wait before proceeding with the requested reboot. default is 60 seconds -- :reason: comment on the reason for the reboot. default is 'Chef Software Chef initiated reboot' - -#### Examples -If the package installs, schedule a reboot at end of chef run -```ruby -windows_reboot 60 do - reason 'cause chef said so' - action :nothing -end - -windows_package 'some_package' do - action :install - notifies :request, 'windows_reboot[60]' -end -``` - -Cancel the previously requested reboot -```ruby -windows_reboot 60 do - action :cancel -end -``` - -### windows_registry -(Chef 11.6.0 includes a built-in [registry_key](http://docs.chef.io/resource_registry_key.html) resource, so use that in preference to `windows_registry` if possible.) - -Creates and modifies Windows registry keys. - -*Change in v1.3.0: The Win32 classes use `::Win32` to avoid namespace conflict with `Chef::Win32` (introduced in Chef 0.10.10).* - -#### Actions -- :create: create a new registry key with the provided values. -- :modify: modify an existing registry key with the provided values. -- :force_modify: modify an existing registry key with the provided values. ensures the value is actually set by checking multiple times. useful for fighting race conditions where two processes are trying to set the same registry key. This will be updated in the near future to use 'RegNotifyChangeKeyValue' which is exposed by the WinAPI and allows a process to register for notification on a registry key change. -- :remove: removes a value from an existing registry key - -#### Attribute Parameters -- key_name: name attribute. The registry key to create/modify. -- values: hash of the values to set under the registry key. The individual hash items will become respective 'Value name' => 'Value data' items in the registry key. -- type: Type of key to create, defaults to REG_SZ. Must be a symbol, see the overview below for valid values. - -#### Registry key types -- :binary: REG_BINARY -- :string: REG_SZ -- :multi_string: REG_MULTI_SZ -- :expand_string: REG_EXPAND_SZ -- :dword: REG_DWORD -- :dword_big_endian: REG_DWORD_BIG_ENDIAN -- :qword: REG_QWORD - -#### Examples - -Make the local windows proxy match the one set for Chef -```ruby -proxy = URI.parse(Chef::Config[:http_proxy]) -windows_registry 'HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings' do - values 'ProxyEnable' => 1, 'ProxyServer' => "#{proxy.host}:#{proxy.port}", 'ProxyOverride' => '' -end -``` - -Enable Remote Desktop and poke the firewall hole -```ruby -windows_registry 'HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server' do - values 'FdenyTSConnections' => 0 -end -``` - -Delete an item from the registry -```ruby -windows_registry 'HKCU\Software\Test' do - #Key is the name of the value that you want to delete the value is always empty - values 'ValueToDelete' => '' - action :remove -end -``` - -Add a REG_MULTI_SZ value to the registry -```ruby -windows_registry 'HKCU\Software\Test' do - values 'MultiString' => ['line 1', 'line 2', 'line 3'] - type :multi_string -end -``` - -#### Library Methods - -```ruby -Registry.value_exists?('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run','BGINFO') -Registry.key_exists?('HKLM\SOFTWARE\Microsoft') -BgInfo = Registry.get_value('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run','BGINFO') -``` - -### windows_path -#### Actions -- :add: Add an item to the system path -- :remove: Remove an item from the system path - -#### Attribute Parameters -- :path: Name attribute. The name of the value to add to the system path - -#### Examples - -Add Sysinternals to the system path -```ruby -windows_path 'C:\Sysinternals' do - action :add -end -``` - -Remove 7-Zip from the system path -```ruby -windows_path 'C:\7-Zip' do - action :remove -end -``` - -### windows_task -Creates, deletes or runs a Windows scheduled task. Requires Windows -Server 2008 due to API usage. - -#### Actions -- :create: creates a task -- :delete: deletes a task -- :run: runs a task -- :change: changes the un/pw or command of a task -- :enable: enable a task -- :disable: disable a task - -#### Attribute Parameters -- name: name attribute, The task name. -- command: The command the task will run. -- cwd: The directory the task will be run from. -- user: The user to run the task as. (requires password) -- password: The user's password. (requires user) -- run_level: Run with limited or highest privileges. -- frequency: Frequency with which to run the task. (hourly, daily, ect.) -- frequency_modifier: Multiple for frequency. (15 minutes, 2 days) -- start_day: Specifies the first date on which the task runs. Optional string (MM/DD/YYYY) -- start_time: Specifies the start time to run the task. Optional string (HH:mm) - -#### Examples - -Run Chef every 15 minutes -```ruby -windows_task 'Chef client' do - user 'Administrator' - password '$ecR3t' - cwd 'C:\chef\bin' - command 'chef-client -L C:\tmp\' - run_level :highest - frequency :minute - frequency_modifier 15 -end -``` - -Update Chef Client task with new password and log location -```ruby -windows_task 'Chef client' do - user 'Administrator' - password 'N3wPassW0Rd' - cwd 'C:\chef\bin' - command 'chef-client -L C:\chef\logs\' - action :change -end -``` - -Delete a taks named 'old task' -```ruby -windows_task 'old task' do - action :delete -end -``` - -Enable a task named 'Chef client' -```ruby -windows_task 'Chef client' do - action :enable -end -``` - -Disable a task named 'Chef client' -```ruby -windows_task 'Chef client' do - action :disable -end -``` - -### 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) - -#### Attribute Parameters -- 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 -``` - -Exception/Report Handlers -------------------------- -### WindowsRebootHandler -Required reboots are a necessary evil of configuring and managing Windows nodes. This report handler (ie fires at the end of Chef runs) acts on requested (Chef initiated) or pending (as determined by the OS per configuration action we performed) reboots. The `allow_pending_reboots` initialization argument should be set to false if you do not want the handler to automatically reboot a node if it has been determined a reboot is pending. Reboots can still be requested explicitly via the `windows_reboot` LWRP. - -### Initialization Arguments -- `allow_pending_reboots`: indicator on whether the handler should act on a the Window's 'pending reboot' state. default is true -- `timeout`: timeout delay in seconds to wait before proceeding with the reboot. default is 60 seconds -- `reason`: comment on the reason for the reboot. default is 'Chef Software Chef initiated reboot' - - -Windows ChefSpec Matchers -------------------------- -The Windows cookbook includes custom [ChefSpec](https://github.com/sethvargo/chefspec) matchers you can use to test your own cookbooks that consume Windows cookbook LWRPs. - -###Example Matcher Usage -```ruby -expect(chef_run).to install_windows_package('Node.js').with( - source: 'http://nodejs.org/dist/v0.10.26/x64/node-v0.10.26-x64.msi') -``` - -###Windows Cookbook Matchers -* install_windows_package -* remove_windows_package -* install_windows_feature -* remove_windows_feature -* delete_windows_feature -* create_windows_task -* delete_windows_task -* run_windows_task -* change_windows_task -* add_windows_path -* remove_windows_path -* run_windows_batch -* set_windows_pagefile -* unzip_windows_zipfile_to -* zip_windows_zipfile_to -* create_windows_shortcut -* create_windows_auto_run -* remove_windows_auto_run -* create_windows_printer -* delete_windows_printer -* create_windows_printer_port -* delete_windows_printer_port -* request_windows_reboot -* cancel_windows_reboot -* create_windows_shortcut - - -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' -``` - -### default -Convenience recipe that installs supporting gems for many of the resources/providers that ship with this cookbook. - -*Change in v1.3.0: Uses chef_gem instead of gem_package to ensure gem installation in Chef 0.10.10.* - -### reboot_handler -Leverages the `chef_handler` LWRP to register the `WindowsRebootHandler` report handler that ships as part of this cookbook. By default this handler is set to automatically act on pending reboots. If you would like to change this behavior override `node['windows']['allow_pending_reboots']` and set the value to false. For example: - -```ruby -name 'base' -description 'base role' -override_attributes( - 'windows' => { - 'allow_pending_reboots' => false - } -) -``` - -This will still allow a reboot to be explicitly requested via the `windows_reboot` LWRP. - -By default, the handler will only be registered as a report handler, meaning that it will only fire at the end of successful Chef runs. If the run fails, pending or requested reboots will be ignored. This can lead to a situation where some package was installed and notified a reboot request via the `windows_reboot` LWRP, and then the run fails for some unrelated reason, and the reboot request gets dropped because the resource that notified the reboot request will already be up-to-date at the next run and will not request a reboot again, and thus the requested reboot will never be performed. To change this behavior and register the handler as an exception handler that fires at the end of failed runs too, override `node['windows']['allow_reboot_on_failure']` and set the value to true. - - -License & Authors ------------------ -- Author:: Seth Chisamore () -- Author:: Doug MacEachern () -- Author:: Paul Morton () -- Author:: Doug Ireton () - -```text -Copyright 2011-2013, 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. -``` +Windows Cookbook +================ +[![Build Status](https://travis-ci.org/chef-cookbooks/windows.svg?branch=master)](http://travis-ci.org/chef-cookbooks/windows) +[![Cookbook Version](https://img.shields.io/cookbook/v/windows.svg)](https://supermarket.chef.io/cookbooks/windows) + +Provides a set of Windows-specific primitives (Chef resources) meant to aid in the creation of cookbooks/recipes targeting the Windows platform. + + +Requirements +------------ +#### Platforms +* Windows Vista +* Windows 7 +* Windows Server 2008 (R1, R2) +* Windows 8, 8.1 +* Windows Server 2012 (R1, R2) + +#### Chef +- Chef 11+ + +#### Cookbooks +* chef_handler (`windows::reboot_handler` leverages the chef_handler LWRP) + + +Attributes +---------- +* `node['windows']['allow_pending_reboots']` - used to configure the `WindowsRebootHandler` (via the `windows::reboot_handler` recipe) to act on pending reboots. default is true (ie act on pending reboots). The value of this attribute only has an effect if the `windows::reboot_handler` is in a node's run list. +* `node['windows']['allow_reboot_on_failure']` - used to register the `WindowsRebootHandler` (via the `windows::reboot_handler` recipe) as an exception handler too to act on reboots not only at the end of successful Chef runs, but even at the end of failed runs. default is false (ie reboot only after successful runs). The value of this attribute only has an effect if the `windows::reboot_handler` is in a node's run list. + + +Resource/Provider +----------------- +### windows_auto_run +#### Actions +- `:create` - Create an item to be run at login +- `:remove` - Remove an item that was previously setup to run at login + +#### Attribute Parameters +- `name` - Name attribute. The name of the value to be stored in the registry +- `program` - The program to be run at login +- `args` - The arguments for the program + +#### Examples +Run BGInfo at login + +```ruby +windows_auto_run 'BGINFO' do + program 'C:/Sysinternals/bginfo.exe' + args '\'C:/Sysinternals/Config.bgi\' /NOLICPROMPT /TIMER:0' + not_if { Registry.value_exists?(AUTO_RUN_KEY, 'BGINFO') } + action :create +end +``` + +### windows_batch +This resource is now deprecated and will be removed in a future version of this cookbook. Chef >= 11.6.0 includes a built-in [batch](http://docs.chef.io/resource_batch.html) resource. + +Execute a batch script using the cmd.exe interpreter (much like the script resources for bash, csh, powershell, perl, python and ruby). A temporary file is created and executed like other script resources, rather than run inline. By their nature, Script resources are not idempotent, as they are completely up to the user's imagination. Use the `not_if` or `only_if` meta parameters to guard the resource for idempotence. + +#### Actions +- `:run` - run the batch file + +#### Attribute Parameters +- `command` - name attribute. Name of the command to execute. +- `code` - quoted string of code to execute. +- `creates` - a file this command creates - if the file exists, the command will not be run. +- `cwd` - current working directory to run the command from. +- `flags` - command line flags to pass to the interpreter when invoking. +- `user` - A user name or user ID that we should change to before running this command. +- `group` - A group name or group ID that we should change to before running this command. + +#### Examples +```ruby +windows_batch 'unzip_and_move_ruby' do + code <<-EOH + 7z.exe x #{Chef::Config[:file_cache_path]}/ruby-1.8.7-p352-i386-mingw32.7z -oC:\\source -r -y + xcopy C:\\source\\ruby-1.8.7-p352-i386-mingw32 C:\\ruby /e /y + EOH +end +``` + +```ruby +windows_batch 'echo some env vars' do + code <<-EOH + echo %TEMP% + echo %SYSTEMDRIVE% + echo %PATH% + echo %WINDIR% + EOH +end +``` + +### windows_certificate + +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. + +#### Attribute Parameters +- `source` - name attribute. The source file (for create and acl_add), thumprint (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 maniplate. One of MY (default : personal store), CA (trusted intermediate store) or ROOT (trusted root store). +- `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 certicates 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. + +#### Attribute Parameters +- `cert_name` - name attribute. The thumprint(hash) or subject that identifies the certicate 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). +- `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 (default : personal store), CA (trusted intermediate store) or ROOT (trusted root store). + +#### 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_feature +Windows Roles and Features can be thought of as built-in operating system packages that ship with the OS. A server role is a set of software programs that, when they are installed and properly configured, lets a computer perform a specific function for multiple users or other computers within a network. A Role can have multiple Role Services that provide functionality to the Role. Role services are software programs that provide the functionality of a role. Features are software programs that, although they are not directly parts of roles, can support or augment the functionality of one or more roles, or improve the functionality of the server, regardless of which roles are installed. Collectively we refer to all of these attributes as 'features'. + +This resource allows you to manage these 'features' in an unattended, idempotent way. + +There are two providers for the `windows_features` which map into Microsoft's two major tools for managing roles/features: [Deployment Image Servicing and Management (DISM)](http://msdn.microsoft.com/en-us/library/dd371719%28v=vs.85%29.aspx) and [Servermanagercmd](http://technet.microsoft.com/en-us/library/ee344834%28WS.10%29.aspx) (The CLI for Server Manager). As Servermanagercmd is deprecated, Chef will set the default provider to `Chef::Provider::WindowsFeature::DISM` if DISM is present on the system being configured. The default provider will fall back to `Chef::Provider::WindowsFeature::ServerManagerCmd`. + +For more information on Roles, Role Services and Features see the [Microsoft TechNet article on the topic](http://technet.microsoft.com/en-us/library/cc754923.aspx). For a complete list of all features that are available on a node type either of the following commands at a command prompt: + +```text +dism /online /Get-Features +servermanagercmd -query +``` + +#### Actions +- `:install` - install a Windows role/feature +- `:remove` - remove a Windows role/feature + +#### Attribute Parameters +- `feature_name` - name of the feature/role to install. The same feature may have different names depending on the provider used (ie DHCPServer vs DHCP; DNS-Server-Full-Role vs DNS). +- `all` - Boolean. Optional. Default: false. DISM provider only. Forces all dependencies to be installed. +- `source` - String. Optional. DISM provider only. Uses local repository for feature install. + +#### Providers +- **Chef::Provider::WindowsFeature::DISM**: Uses Deployment Image Servicing and Management (DISM) to manage roles/features. +- **Chef::Provider::WindowsFeature::ServerManagerCmd**: Uses Server Manager to manage roles/features. +- **Chef::Provider::WindowsFeaturePowershell**: Uses Powershell to manage roles/features. (see [COOK-3714](https://tickets.chef.io/browse/COOK-3714) + +#### Examples +Enable the node as a DHCP Server + +```ruby +windows_feature 'DHCPServer' do + action :install +end +``` + +Enable TFTP + +```ruby +windows_feature 'TFTP' do + action :install +end +``` + +Enable .Net 3.5.1 on Server 2012 using repository files on DVD and +install all dependencies + +```ruby +windows_feature "NetFx3" do + action :install + all true + source "d:\sources\sxs" +end +``` + +Disable Telnet client/server + +```ruby +%w[TelnetServer TelnetClient].each do |feature| + windows_feature feature do + action :remove + end +end +``` + +Add SMTP Feature with powershell provider + +```ruby +windows_feature "smtp-server" do + action :install + all true + provider :windows_feature_powershell +end +``` + +### windows_font +Installs a font. + +Font files should be included in the cookbooks + +#### Actions +- `:install` - install a font to the system fonts directory. + +#### Attribute Parameters +- `file` - The name of the font file name to install. It should exist in the files/default directory of the cookbook you're calling windows_font from. Defaults to the resource name. + +#### Examples + +```ruby +windows_font 'Code New Roman.otf' +``` + +### 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. + +#### Attribute Parameters +- `url` - the name of the url to be created/deleted. +- `user` - the name (domain\user) of the user or group to be granted permission to the URL. Mandatory for create. Only one user or group can be granted permission so this replaces any previously defined entry. + +#### Examples + +```ruby +windows_http_acl 'http://+:50051/' do + user 'pc\\fred' +end +``` + +```ruby +windows_http_acl 'http://+:50051/' do + action :delete +end +``` + +### windows_package +Manage Windows application packages in an unattended, idempotent way. + +The following application installers are currently supported: + +* MSI packages +* InstallShield +* Wise InstallMaster +* Inno Setup +* Nullsoft Scriptable Install System + +If the proper installer type is not passed into the resource's installer_type attribute, the provider will do it's best to identify the type by introspecting the installation package. If the installation type cannot be properly identified the `:custom` value can be passed into the installer_type attribute along with the proper flags for silent/quiet installation (using the `options` attribute..see example below). + +__PLEASE NOTE__ - For proper idempotence the resource's `package_name` should be the same as the 'DisplayName' registry value in the uninstallation data that is created during package installation. The easiest way to definitively find the proper 'DisplayName' value is to install the package on a machine and search for the uninstall information under the following registry keys: + +* `HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall` +* `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Uninstall` +* `HKEY_LOCAL_MACHINE\Software\Wow6464Node\Microsoft\Windows\CurrentVersion\Uninstall` + +For maximum flexibility the `source` attribute supports both remote and local installation packages. + +#### Actions +- `:install` - install a package +- `:remove` - remove a package. The remove action is completely hit or miss as many application uninstallers do not support a full silent/quiet mode. + +#### Attribute Parameters +- `package_name` - name attribute. The 'DisplayName' of the application installation package. +- `source` - The source of the windows installer. This can either be a URI or a local path. +- `installer_type` - They type of windows installation package. Valid values include :msi, :inno, :nsis, :wise, :installshield, :custom. If this value is not provided, the provider will do it's best to identify the installer type through introspection of the file. +- `checksum` - useful if source is remote, the SHA-256 checksum of the file--if the local file matches the checksum, Chef will not download it +- `options` - Additional options to pass the underlying installation command +- `timeout` - set a timeout for the package download (default 600 seconds) +- `version` - The version number of this package, as indicated by the 'DisplayVersion' value in one of the 'Uninstall' registry keys. If the given version number does equal the 'DisplayVersion' in the registry, the package will be installed. +- `success_codes` - set an array of possible successful installation + return codes. Previously this was hardcoded, but certain MSIs may + have a different return code, e.g. 3010 for reboot required. Must be + an array, and defaults to `[0, 42, 127]`. + +#### Examples + +Install PuTTY (InnoSetup installer) +```ruby +windows_package 'PuTTY version 0.60' do + source 'http://the.earth.li/~sgtatham/putty/latest/x86/putty-0.60-installer.exe' + installer_type :inno + action :install +end +``` + +Install 7-Zip (MSI installer) +```ruby +windows_package '7-Zip 9.20 (x64 edition)' do + source 'http://downloads.sourceforge.net/sevenzip/7z920-x64.msi' + action :install +end +``` + +Install Notepad++ (Y U No Emacs?) using a local installer +```ruby +windows_package 'Notepad++' do + source 'c:/installation_files/npp.5.9.2.Installer.exe' + action :install +end +``` + +Install VLC for that Xvid (NSIS installer) +```ruby +windows_package 'VLC media player 1.1.10' do + source 'http://superb-sea2.dl.sourceforge.net/project/vlc/1.1.10/win32/vlc-1.1.10-win32.exe' + action :install +end +``` + +Install Firefox as custom installer and manually set the silent install flags +```ruby +windows_package 'Mozilla Firefox 5.0 (x86 en-US)' do + source 'http://archive.mozilla.org/pub/mozilla.org/mozilla.org/firefox/releases/5.0/win32/en-US/Firefox%20Setup%205.0.exe' + options '-ms' + installer_type :custom + action :install +end +``` + +Google Chrome FTW (MSI installer) +```ruby +windows_package 'Google Chrome' do + source 'https://dl-ssl.google.com/tag/s/appguid%3D%7B8A69D345-D564-463C-AFF1-A69D9E530F96%7D%26iid%3D%7B806F36C0-CB54-4A84-A3F3-0CF8A86575E0%7D%26lang%3Den%26browser%3D3%26usagestats%3D0%26appname%3DGoogle%2520Chrome%26needsadmin%3Dfalse/edgedl/chrome/install/GoogleChromeStandaloneEnterprise.msi' + action :install +end +``` + +Remove Google Chrome +```ruby +windows_package 'Google Chrome' do + action :remove +end +``` + +Remove 7-Zip +```ruby +windows_package '7-Zip 9.20 (x64 edition)' do + action :remove +end +``` + +### windows_printer_port + +Create and delete TCP/IPv4 printer ports. + +#### Actions +- `:create` - Create a TCIP/IPv4 printer port. This is the default action. +- `:delete` - Delete a TCIP/IPv4 printer port + +#### Attribute Parameters +- `ipv4_address` - Name attribute. Required. IPv4 address, e.g. '10.0.24.34' +- `port_name` - Port name. Optional. Defaults to 'IP_' + `ipv4_address` +- `port_number` - Port number. Optional. Defaults to 9100. +- `port_description` - Port description. Optional. +- `snmp_enabled` - Boolean. Optional. Defaults to false. +- `port_protocol` - Port protocol, 1 (RAW), or 2 (LPR). Optional. Defaults to 1. + +#### Examples + +Create a TCP/IP printer port named 'IP_10.4.64.37' with all defaults +```ruby +windows_printer_port '10.4.64.37' do + action :create +end +``` + +Delete a printer port +```ruby +windows_printer_port '10.4.64.37' do + action :delete +end +``` + +Delete a port with a custom port_name +```ruby +windows_printer_port '10.4.64.38' do + port_name 'My awesome port' + action :delete +end +``` + +Create a port with more options +```ruby +windows_printer_port '10.4.64.39' do + port_name 'My awesome port' + snmp_enabled true + port_protocol 2 +end +``` + +### windows_printer + +Create Windows printer. Note that this doesn't currently install a printer +driver. You must already have the driver installed on the system. + +The Windows Printer LWRP will automatically create a TCP/IP printer port for you using the `ipv4_address` property. If you want more granular control over the printer port, just create it using the `windows_printer_port` LWRP before creating the printer. + +#### Actions +- `:create` - Create a new printer +- `:delete` - Delete a new printer + +#### Attribute Parameters +- `device_id` - Name attribute. Required. Printer queue name, e.g. 'HP LJ 5200 in fifth floor copy room' +- `comment` - Optional string describing the printer queue. +- `default` - Boolean. Optional. Defaults to false. Note that Windows sets the first printer defined to the default printer regardless of this setting. +- `driver_name` - String. Required. Exact name of printer driver. Note that the printer driver must already be installed on the node. +- `location` - Printer location, e.g. 'Fifth floor copy room', or 'US/NYC/Floor42/Room4207' +- `shared` - Boolean. Defaults to false. +- `share_name` - Printer share name. +- `ipv4_address` - Printer IPv4 address, e.g. '10.4.64.23'. You don't have to be able to ping the IP addresss to set it. Required. + +An error of "Set-WmiInstance : Generic failure" is most likely due to the printer driver name not matching or not being installed. + +#### Examples + +Create a printer +```ruby +windows_printer 'HP LaserJet 5th Floor' do + driver_name 'HP LaserJet 4100 Series PCL6' + ipv4_address '10.4.64.38' +end +``` + +Delete a printer. Note: this doesn't delete the associated printer port. See `windows_printer_port` above for how to delete the port. +```ruby +windows_printer 'HP LaserJet 5th Floor' do + action :delete +end +``` + +### windows_reboot +This resource is now deprecated and will be removed in a future version of this cookbook. Chef >= 12.0.0 includes a built-in [reboot](http://docs.chef.io/resource_reboot.html) resource. + +Sets required data in the node's run_state to notify `WindowsRebootHandler` a reboot is requested. If Chef run completes successfully a reboot will occur if the `WindowsRebootHandler` is properly registered as a report handler. As an action of `:request` will cause a node to reboot every Chef run, this resource is usually notified by other resources...ie restart node after a package is installed (see example below). + +#### Actions +- `:request` - requests a reboot at completion of successful Cher run. requires `WindowsRebootHandler` to be registered as a report handler. +- `:cancel` - remove reboot request from node.run_state. this will cancel *ALL* previously requested reboots as this is a binary state. + +#### Attribute Parameters +- `timeout` - Name attribute. timeout delay in seconds to wait before proceeding with the requested reboot. default is 60 seconds +- `reason` - comment on the reason for the reboot. default is 'Chef Software Chef initiated reboot' + +#### Examples +If the package installs, schedule a reboot at end of chef run +```ruby +windows_reboot 60 do + reason 'cause chef said so' + action :nothing +end + +windows_package 'some_package' do + action :install + notifies :request, 'windows_reboot[60]' +end +``` + +Cancel the previously requested reboot +```ruby +windows_reboot 60 do + action :cancel +end +``` + +### windows_registry +This resource is now deprecated and will be removed in a future version of this cookbook. Chef >= 11.6.0 includes a built-in [registry_key](http://docs.chef.io/resource_registry_key.html) resource. + +Creates and modifies Windows registry keys. + +*Change in v1.3.0: The Win32 classes use `::Win32` to avoid namespace conflict with `Chef::Win32` (introduced in Chef 0.10.10).* + +#### Actions +- `:create` - create a new registry key with the provided values. +- `:modify` - modify an existing registry key with the provided values. +- `:force_modify` - modify an existing registry key with the provided values. ensures the value is actually set by checking multiple times. useful for fighting race conditions where two processes are trying to set the same registry key. This will be updated in the near future to use 'RegNotifyChangeKeyValue' which is exposed by the WinAPI and allows a process to register for notification on a registry key change. +- `:remove` - removes a value from an existing registry key + +#### Attribute Parameters +- `key_name` - name attribute. The registry key to create/modify. +- `values` - hash of the values to set under the registry key. The individual hash items will become respective 'Value name' => 'Value data' items in the registry key. +- `type` - Type of key to create, defaults to REG_SZ. Must be a symbol, see the overview below for valid values. + +#### Registry key types +- `:binary` - REG_BINARY +- `:string` - REG_SZ +- `:multi_string` - REG_MULTI_SZ +- `:expand_string` - REG_EXPAND_SZ +- `:dword` - REG_DWORD +- `:dword_big_endian` - REG_DWORD_BIG_ENDIAN +- `:qword` - REG_QWORD + +#### Examples + +Make the local windows proxy match the one set for Chef +```ruby +proxy = URI.parse(Chef::Config[:http_proxy]) +windows_registry 'HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings' do + values 'ProxyEnable' => 1, 'ProxyServer' => "#{proxy.host}:#{proxy.port}", 'ProxyOverride' => '' +end +``` + +Enable Remote Desktop and poke the firewall hole +```ruby +windows_registry 'HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server' do + values 'FdenyTSConnections' => 0 +end +``` + +Delete an item from the registry +```ruby +windows_registry 'HKCU\Software\Test' do + #Key is the name of the value that you want to delete the value is always empty + values 'ValueToDelete' => '' + action :remove +end +``` + +Add a REG_MULTI_SZ value to the registry +```ruby +windows_registry 'HKCU\Software\Test' do + values 'MultiString' => ['line 1', 'line 2', 'line 3'] + type :multi_string +end +``` + +### windows_shortcut +Creates and modifies Windows shortcuts. + +#### Actions +- `:create` - create or modify a windows shortcut + +#### Attribute Parameters +- `name` - name attribute. The shortcut to create/modify. +- `target` - what the shortcut links to +- `arguments` - arguments to pass to the target when the shortcut is executed +- `description` - description of the shortcut +- `cwd` - Working directory to use when the target is executed +- `iconlocation` - Icon to use, in the format of ```"path, index"``` where index is which icon in that file to use (See [WshShortcut.IconLocation](https://msdn.microsoft.com/en-us/library/3s9bx7at.aspx)) + +#### Examples + +Add a shortcut all users desktop: +```ruby +require 'win32ole' +all_users_desktop = WIN32OLE.new("WScript.Shell").SpecialFolders("AllUsersDesktop") + +windows_shortcut "#{all_users_desktop}/Notepad.lnk" do + target "C:\\WINDOWS\\notepad.exe" + description "Launch Notepad" + iconlocation "C:\\windows\\notepad.exe, 0" +end +``` + +#### Library Methods + +```ruby +Registry.value_exists?('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run','BGINFO') +Registry.key_exists?('HKLM\SOFTWARE\Microsoft') +BgInfo = Registry.get_value('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run','BGINFO') +``` + +### windows_path +#### Actions +- `:add` - Add an item to the system path +- `:remove` - Remove an item from the system path + +#### Attribute Parameters +- `path` - Name attribute. The name of the value to add to the system path + +#### Examples + +Add Sysinternals to the system path +```ruby +windows_path 'C:\Sysinternals' do + action :add +end +``` + +Remove 7-Zip from the system path +```ruby +windows_path 'C:\7-Zip' do + action :remove +end +``` + +### windows_task +Creates, deletes or runs a Windows scheduled task. Requires Windows +Server 2008 due to API usage. + +#### Actions +- `:create` - creates a task (or updates existing if user or command has changed) +- `:delete` - deletes a task +- `:run` - runs a task +- `:end` - ends a task +- `:change` - changes the un/pw or command of a task +- `:enable` - enable a task +- `:disable` - disable a task + +#### Attribute Parameters +- `task_name` - name attribute, The task name. ("Task Name" or "/Task Name") +- `force` - When used with create, will update the task. +- `command` - The command the task will run. +- `cwd` - The directory the task will be run from. +- `user` - The user to run the task as. (defaults to 'SYSTEM') +- `password` - The user's password. (requires user) +- `run_level` - Run with `:limited` or `:highest` privileges. +- `frequency` - Frequency with which to run the task. (default is :hourly. Other valid values include :minute, :hourly, :daily, :weekly, :monthly, :once, :on_logon, :onstart, :on_idle) \*:once requires start_time +- `frequency_modifier` - Multiple for frequency. (15 minutes, 2 days) +- `start_day` - Specifies the first date on which the task runs. Optional string (MM/DD/YYYY) +- `start_time` - Specifies the start time to run the task. Optional string (HH:mm) +- `interactive_enabled` - (Allow task to run interactively or non-interactively. Requires user and password.) +- `day` - For monthly or weekly tasks, the day(s) on which the task runs. (MON - SUN, *, 1 - 31) + +#### Examples + +Create a `chef-client` task with TaskPath `\` running every 15 minutes +```ruby +windows_task 'chef-client' do + user 'Administrator' + password '$ecR3t' + cwd 'C:\\chef\\bin' + command 'chef-client -L C:\\tmp\\' + run_level :highest + frequency :minute + frequency_modifier 15 +end +``` + +Update `chef-client` task with new password and log location +```ruby +windows_task 'chef-client' do + user 'Administrator' + password 'N3wPassW0Rd' + cwd 'C:\\chef\\bin' + command 'chef-client -L C:\\chef\\logs\\' + action :change +end +``` + +Delete a taks named `old task` +```ruby +windows_task 'old task' do + action :delete +end +``` + +Enable a task named `chef-client` +```ruby +windows_task 'chef-client' do + action :enable +end +``` + +Disable a task named `ProgramDataUpdater` with TaskPath `\Microsoft\Windows\Application Experience\` +```ruby +windows_task '\Microsoft\Windows\Application Experience\ProgramDataUpdater' do + action :disable +end +``` + +### 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) + +#### Attribute Parameters +- `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 +``` + +Exception/Report Handlers +------------------------- +### WindowsRebootHandler +Required reboots are a necessary evil of configuring and managing Windows nodes. This report handler (ie fires at the end of Chef runs) acts on requested (Chef initiated) or pending (as determined by the OS per configuration action we performed) reboots. The `allow_pending_reboots` initialization argument should be set to false if you do not want the handler to automatically reboot a node if it has been determined a reboot is pending. Reboots can still be requested explicitly via the `windows_reboot` LWRP. + +### Initialization Arguments +- `allow_pending_reboots` - indicator on whether the handler should act on a the Window's 'pending reboot' state. default is true +- `timeout` - timeout delay in seconds to wait before proceeding with the reboot. default is 60 seconds +- `reason` - comment on the reason for the reboot. default is 'Chef Software Chef initiated reboot' + + +Windows ChefSpec Matchers +------------------------- +The Windows cookbook includes custom [ChefSpec](https://github.com/sethvargo/chefspec) matchers you can use to test your own cookbooks that consume Windows cookbook LWRPs. + +###Example Matcher Usage +```ruby +expect(chef_run).to install_windows_package('Node.js').with( + source: 'http://nodejs.org/dist/v0.10.26/x64/node-v0.10.26-x64.msi') +``` + +###Windows Cookbook Matchers +* install_windows_package +* remove_windows_package +* install_windows_feature +* remove_windows_feature +* delete_windows_feature +* create_windows_task +* delete_windows_task +* run_windows_task +* change_windows_task +* add_windows_path +* remove_windows_path +* run_windows_batch +* set_windows_pagefile +* unzip_windows_zipfile_to +* zip_windows_zipfile_to +* create_windows_shortcut +* create_windows_auto_run +* remove_windows_auto_run +* create_windows_printer +* delete_windows_printer +* create_windows_printer_port +* delete_windows_printer_port +* request_windows_reboot +* cancel_windows_reboot +* create_windows_shortcut + + +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' +``` + +### default +Convenience recipe that installs supporting gems for many of the resources/providers that ship with this cookbook. + +### reboot_handler +Leverages the `chef_handler` LWRP to register the `WindowsRebootHandler` report handler that ships as part of this cookbook. By default this handler is set to automatically act on pending reboots. If you would like to change this behavior override `node['windows']['allow_pending_reboots']` and set the value to false. For example: + +```ruby +name 'base' +description 'base role' +override_attributes( + 'windows' => { + 'allow_pending_reboots' => false + } +) +``` + +This will still allow a reboot to be explicitly requested via the `windows_reboot` LWRP. + +By default, the handler will only be registered as a report handler, meaning that it will only fire at the end of successful Chef runs. If the run fails, pending or requested reboots will be ignored. This can lead to a situation where some package was installed and notified a reboot request via the `windows_reboot` LWRP, and then the run fails for some unrelated reason, and the reboot request gets dropped because the resource that notified the reboot request will already be up-to-date at the next run and will not request a reboot again, and thus the requested reboot will never be performed. To change this behavior and register the handler as an exception handler that fires at the end of failed runs too, override `node['windows']['allow_reboot_on_failure']` and set the value to true. + + +License & Authors +----------------- +- Author:: Seth Chisamore () +- Author:: Doug MacEachern () +- Author:: Paul Morton () +- Author:: Doug Ireton () + +```text +Copyright 2011-2015, 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/attributes/default.rb b/cookbooks/windows/attributes/default.rb index f76f65c..0d043c2 100644 --- a/cookbooks/windows/attributes/default.rb +++ b/cookbooks/windows/attributes/default.rb @@ -1,24 +1,24 @@ -# -# Author:: Seth Chisamore () -# Cookbook Name:: windows -# Attribute:: default -# -# Copyright 2011, 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['windows']['allow_pending_reboots'] = true -default['windows']['allow_reboot_on_failure'] = false -default['windows']['rubyzipversion'] = nil -default['windows']['reboot_timeout'] = 60 +# +# Author:: Seth Chisamore () +# Cookbook Name:: windows +# Attribute:: default +# +# 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. +# + +default['windows']['allow_pending_reboots'] = true +default['windows']['allow_reboot_on_failure'] = false +default['windows']['rubyzipversion'] = nil +default['windows']['reboot_timeout'] = 60 diff --git a/cookbooks/windows/files/default/handlers/windows_reboot_handler.rb b/cookbooks/windows/files/default/handlers/windows_reboot_handler.rb index 95382ec..874b751 100644 --- a/cookbooks/windows/files/default/handlers/windows_reboot_handler.rb +++ b/cookbooks/windows/files/default/handlers/windows_reboot_handler.rb @@ -1,76 +1,83 @@ -# -# Author:: Seth Chisamore () -# Copyright:: Copyright (c) 2011 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 WindowsRebootHandler < Chef::Handler - include Chef::Mixin::ShellOut - - def initialize(allow_pending_reboots = true, timeout = 60, reason = "Chef Software Chef initiated reboot") - @allow_pending_reboots = allow_pending_reboots - @timeout = timeout - @reason = reason - end - - def report - log_message, reboot = begin - if reboot_requested? - ["chef_handler[#{self.class}] requested reboot will occur in #{timeout} seconds", true] - elsif reboot_pending? - if @allow_pending_reboots - ["chef_handler[#{self.class}] reboot pending - automatic reboot will occur in #{timeout} seconds", true] - else - ["chef_handler[#{self.class}] reboot pending but handler not configured to act on pending reboots - please reboot node manually", false] - end - else - ["chef_handler[#{self.class}] no reboot requested or pending", false] - end - end - - Chef::Log.warn(log_message) - shell_out!("shutdown /r /t #{timeout} /c \"#{reason}\"") if reboot - end - - private - # reboot cause CHEF says so: - # reboot explicitly requested in our cookbook code - def reboot_requested? - node.run_state[:reboot_requested] == true - end - - # reboot cause WIN says so: - # reboot pending because of some configuration action we performed - def reboot_pending? - # Any files listed here means reboot needed - (Registry.key_exists?('HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations') && - Registry.get_value('HKLM\SYSTEM\CurrentControlSet\Control\Session Manager','PendingFileRenameOperations').any?) || - # 1 for any value means reboot pending - # "9306cdfc-c4a1-4a22-9996-848cb67eddc3"=1 - (Registry.key_exists?('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired') && - Registry.get_values('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired').select{|v| v[2] == 1 }.any?) || - # 1 or 2 for 'Flags' value means reboot pending - (Registry.key_exists?('HKLM\SOFTWARE\Microsoft\Updates\UpdateExeVolatile') && - [1,2].include?(Registry::get_value('HKLM\SOFTWARE\Microsoft\Updates\UpdateExeVolatile','Flags'))) - end - - def timeout - node.run_state[:reboot_timeout] || node['windows']['reboot_timeout'] || @timeout - end - - def reason - node.run_state[:reboot_reason] || @reason - end -end +# +# Author:: Seth Chisamore () +# Copyright:: Copyright (c) 2011 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 WindowsRebootHandler < Chef::Handler + include Chef::Mixin::ShellOut + + def initialize(allow_pending_reboots = true, timeout = 60, reason = 'Chef client run') + @allow_pending_reboots = allow_pending_reboots + @timeout = timeout + @reason = reason + end + + def report + log_message, reboot = begin + if reboot_requested? + ["chef_handler[#{self.class}] requested reboot will occur in #{timeout} seconds", true] + elsif reboot_pending? + if @allow_pending_reboots + ["chef_handler[#{self.class}] reboot pending - automatic reboot will occur in #{timeout} seconds", true] + else + ["chef_handler[#{self.class}] reboot pending but handler not configured to act on pending reboots - please reboot node manually", false] + end + else + ["chef_handler[#{self.class}] no reboot requested or pending", false] + end + end + + Chef::Log.warn(log_message) + shell_out!("shutdown /r /t #{timeout} /c \"#{reason}\"") if reboot + end + + private + + # reboot cause CHEF says so: + # reboot explicitly requested in our cookbook code + def reboot_requested? + node.run_state[:reboot_requested] == true + end + + if Chef::VERSION > '11.12' + include Chef::DSL::RebootPending + else + # reboot cause WIN says so: + # reboot pending because of some configuration action we performed + def reboot_pending? + # this key will only exit if the system need a reboot to update some file currently in use + # see http://technet.microsoft.com/en-us/library/cc960241.aspx + Registry.value_exists?('HKLM\SYSTEM\CurrentControlSet\Control\Session Manager', 'PendingFileRenameOperations') || + # 1 for any value means reboot pending + # "9306cdfc-c4a1-4a22-9996-848cb67eddc3"=1 + (Registry.key_exists?('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired') && + Registry.get_values('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired').select { |v| v[2] == 1 }.any?) || + # this key will only exit if the system is pending a reboot + ::Registry.key_exists?('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending') || + # 1, 2 or 3 for 'Flags' value means reboot pending + (Registry.key_exists?('HKLM\SOFTWARE\Microsoft\Updates\UpdateExeVolatile') && + [1, 2, 3].include?(Registry.get_value('HKLM\SOFTWARE\Microsoft\Updates\UpdateExeVolatile', 'Flags'))) + end + end + + def timeout + node.run_state[:reboot_timeout] || node['windows']['reboot_timeout'] || @timeout + end + + def reason + node.run_state[:reboot_reason] || @reason + end +end diff --git a/cookbooks/windows/libraries/feature_base.rb b/cookbooks/windows/libraries/feature_base.rb index a25c56f..2ed8fb2 100644 --- a/cookbooks/windows/libraries/feature_base.rb +++ b/cookbooks/windows/libraries/feature_base.rb @@ -1,59 +1,57 @@ -class Chef - class Provider - class WindowsFeature - module Base - - def action_install - unless installed? - install_feature(@new_resource.feature_name) - @new_resource.updated_by_last_action(true) - Chef::Log.info("#{@new_resource} installed feature") - else - Chef::Log.debug("#{@new_resource} is already installed - nothing to do") - end - end - - def action_remove - if installed? - remove_feature(@new_resource.feature_name) - @new_resource.updated_by_last_action(true) - Chef::Log.info("#{@new_resource} removed") - else - Chef::Log.debug("#{@new_resource} feature does not exist - nothing to do") - end - end - - def action_delete - if available? - delete_feature(@new_resource.feature_name) - @new_resource.updated_by_last_action(true) - Chef::Log.info("#{@new_resource} deleted") - else - Chef::Log.debug("#{@new_resource} feature is not installed - nothing to do") - end - end - - def install_feature(name) - raise Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :install" - end - - def remove_feature(name) - raise Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :remove" - end - - def delete_feature(name) - raise Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :delete" - end - - def installed? - raise Chef::Exceptions::Override, "You must override installed? in #{self.to_s}" - end - - def available? - raise Chef::Exceptions::Override, "You must override available? in #{self.to_s}" - end - end - end - end -end - +class Chef + class Provider + class WindowsFeature + module Base + def action_install + unless installed? + install_feature(@new_resource.feature_name) + @new_resource.updated_by_last_action(true) + Chef::Log.info("#{@new_resource} installed feature") + else + Chef::Log.debug("#{@new_resource} is already installed - nothing to do") + end + end + + def action_remove + if installed? + remove_feature(@new_resource.feature_name) + @new_resource.updated_by_last_action(true) + Chef::Log.info("#{@new_resource} removed") + else + Chef::Log.debug("#{@new_resource} feature does not exist - nothing to do") + end + end + + def action_delete + if available? + delete_feature(@new_resource.feature_name) + @new_resource.updated_by_last_action(true) + Chef::Log.info("#{@new_resource} deleted") + else + Chef::Log.debug("#{@new_resource} feature is not installed - nothing to do") + end + end + + def install_feature(_name) + fail Chef::Exceptions::UnsupportedAction, "#{self} does not support :install" + end + + def remove_feature(_name) + fail Chef::Exceptions::UnsupportedAction, "#{self} does not support :remove" + end + + def delete_feature(_name) + fail Chef::Exceptions::UnsupportedAction, "#{self} does not support :delete" + end + + def installed? + fail Chef::Exceptions::Override, "You must override installed? in #{self}" + end + + def available? + fail Chef::Exceptions::Override, "You must override available? in #{self}" + end + end + end + end +end diff --git a/cookbooks/windows/libraries/matchers.rb b/cookbooks/windows/libraries/matchers.rb index 6aeb516..b39b4fc 100644 --- a/cookbooks/windows/libraries/matchers.rb +++ b/cookbooks/windows/libraries/matchers.rb @@ -1,465 +1,452 @@ -if defined?(ChefSpec) - chefspec_version = Gem.loaded_specs["chefspec"].version - if chefspec_version < Gem::Version.new('4.1.0') - define_method = ChefSpec::Runner.method(:define_runner_method) - else - define_method = ChefSpec.method(:define_matcher) - end - - define_method.call :windows_package - define_method.call :windows_feature - define_method.call :windows_task - define_method.call :windows_path - define_method.call :windows_batch - define_method.call :windows_pagefile - define_method.call :windows_zipfile - define_method.call :windows_shortcut - define_method.call :windows_auto_run - define_method.call :windows_printer - define_method.call :windows_printer_port - define_method.call :windows_reboot - # - # Assert that a +windows_package+ resource exists in the Chef run with the - # action +:install+. Given a Chef Recipe that installs "Node.js" as a - # +windows_package+: - # - # windows_package 'Node.js' do - # source 'http://nodejs.org/dist/v0.10.26/x64/node-v0.10.26-x64.msi' - # action :install - # end - # - # The Examples section demonstrates the different ways to test a - # +windows_package+ resource with ChefSpec. - # - # @example Assert that a +windows_package+ was installed - # expect(chef_run).to install_windows_package('Node.js') - # - # @example Assert that a +windows_package+ was _not_ installed - # expect(chef_run).to_not install_windows_package('7-zip') - # - # - # @param [String, Regex] resource_name - # the name of the resource to match - # - # @return [ChefSpec::Matchers::ResourceMatcher] - # - def install_windows_package(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_package, :install, resource_name) - end - - # - # Assert that a +windows_package+ resource exists in the Chef run with the - # action +:remove+. Given a Chef Recipe that removes "Node.js" as a - # +windows_package+: - # - # windows_package 'Node.js' do - # action :remove - # end - # - # The Examples section demonstrates the different ways to test a - # +windows_package+ resource with ChefSpec. - # - # @example Assert that a +windows_package+ was installed - # expect(chef_run).to remove_windows_package('Node.js') - # - # @example Assert that a +windows_package+ was _not_ removed - # expect(chef_run).to_not remove_windows_package('7-zip') - # - # - # @param [String, Regex] resource_name - # the name of the resource to match - # - # @return [ChefSpec::Matchers::ResourceMatcher] - # - def remove_windows_package(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_package, :remove, resource_name) - end - - - - # - # Assert that a +windows_feature+ resource exists in the Chef run with the - # action +:install+. Given a Chef Recipe that installs "NetFX3" as a - # +windows_feature+: - # - # windows_feature 'NetFX3' do - # action :install - # end - # - # The Examples section demonstrates the different ways to test a - # +windows_feature+ resource with ChefSpec. - # - # @example Assert that a +windows_feature+ was installed - # expect(chef_run).to install_windows_feature('NetFX3') - # - # @example Assert that a +windows_feature+ was _not_ installed - # expect(chef_run).to_not install_windows_feature('NetFX3') - # - # - # @param [String, Regex] resource_name - # the name of the resource to match - # - # @return [ChefSpec::Matchers::ResourceMatcher] - # - def install_windows_feature(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_feature, :install, resource_name) - end - - # - # Assert that a +windows_feature+ resource exists in the Chef run with the - # action +:remove+. Given a Chef Recipe that removes "NetFX3" as a - # +windows_feature+: - # - # windows_feature 'NetFX3' do - # action :remove - # end - # - # The Examples section demonstrates the different ways to test a - # +windows_feature+ resource with ChefSpec. - # - # @example Assert that a +windows_feature+ was removed - # expect(chef_run).to remove_windows_feature('NetFX3') - # - # - # @param [String, Regex] resource_name - # the name of the resource to match - # - # @return [ChefSpec::Matchers::ResourceMatcher] - # - def remove_windows_feature(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_feature, :remove, resource_name) - end - - # - # Assert that a +windows_feature+ resource exists in the Chef run with the - # action +:delete+. Given a Chef Recipe that deletes "NetFX3" as a - # +windows_feature+: - # - # windows_feature 'NetFX3' do - # action :delete - # end - # - # The Examples section demonstrates the different ways to test a - # +windows_feature+ resource with ChefSpec. - # - # @example Assert that a +windows_feature+ was deleted - # expect(chef_run).to delete_windows_feature('NetFX3') - # - # - # @param [String, Regex] resource_name - # the name of the resource to match - # - # @return [ChefSpec::Matchers::ResourceMatcher] - # - def delete_windows_feature(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_feature, :delete, resource_name) - end - - - - # - # Assert that a +windows_task+ resource exists in the Chef run with the - # action +:create+. Given a Chef Recipe that creates "mytask" as a - # +windows_task+: - # - # windows_task 'mytask' do - # command 'mybatch.bat' - # action :create - # end - # - # The Examples section demonstrates the different ways to test a - # +windows_task+ resource with ChefSpec. - # - # @example Assert that a +windows_task+ was created - # expect(chef_run).to create_windows_task('mytask') - # - # - # @param [String, Regex] resource_name - # the name of the resource to match - # - # @return [ChefSpec::Matchers::ResourceMatcher] - # - def create_windows_task(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_task, :create, resource_name) - end - - # - # Assert that a +windows_task+ resource exists in the Chef run with the - # action +:delete+. Given a Chef Recipe that deletes "mytask" as a - # +windows_task+: - # - # windows_task 'mytask' do - # action :delete - # end - # - # The Examples section demonstrates the different ways to test a - # +windows_task+ resource with ChefSpec. - # - # @example Assert that a +windows_task+ was deleted - # expect(chef_run).to delete_windows_task('mytask') - # - # - # @param [String, Regex] resource_name - # the name of the resource to match - # - # @return [ChefSpec::Matchers::ResourceMatcher] - # - def delete_windows_task(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_task, :delete, resource_name) - end - - # - # Assert that a +windows_task+ resource exists in the Chef run with the - # action +:run+. Given a Chef Recipe that runs "mytask" as a - # +windows_task+: - # - # windows_task 'mytask' do - # action :run - # end - # - # The Examples section demonstrates the different ways to test a - # +windows_task+ resource with ChefSpec. - # - # @example Assert that a +windows_task+ was run - # expect(chef_run).to run_windows_task('mytask') - # - # - # @param [String, Regex] resource_name - # the name of the resource to match - # - # @return [ChefSpec::Matchers::ResourceMatcher] - # - def run_windows_task(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_task, :run, resource_name) - end - - # - # Assert that a +windows_task+ resource exists in the Chef run with the - # action +:change+. Given a Chef Recipe that changes "mytask" as a - # +windows_task+: - # - # windows_task 'mytask' do - # action :change - # end - # - # The Examples section demonstrates the different ways to test a - # +windows_task+ resource with ChefSpec. - # - # @example Assert that a +windows_task+ was changed - # expect(chef_run).to change_windows_task('mytask') - # - # - # @param [String, Regex] resource_name - # the name of the resource to match - # - # @return [ChefSpec::Matchers::ResourceMatcher] - # - def change_windows_task(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_task, :change, resource_name) - end - - - - # - # Assert that a +windows_path+ resource exists in the Chef run with the - # action +:add+. Given a Chef Recipe that adds "C:\7-Zip" to the Windows - # PATH env var - # - # windows_path 'C:\7-Zip' do - # action :add - # end - # - # The Examples section demonstrates the different ways to test a - # +windows_path+ resource with ChefSpec. - # - # @example Assert that a +windows_path+ was added - # expect(chef_run).to add_windows_path('C:\7-Zip') - # - # - # @param [String, Regex] resource_name - # the name of the resource to match - # - # @return [ChefSpec::Matchers::ResourceMatcher] - # - def add_windows_path(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_path, :add, resource_name) - end - - # - # Assert that a +windows_path+ resource exists in the Chef run with the - # action +:remove+. Given a Chef Recipe that removes "C:\7-Zip" from the - # Windows PATH env var - # - # windows_path 'C:\7-Zip' do - # action :remove - # end - # - # The Examples section demonstrates the different ways to test a - # +windows_path+ resource with ChefSpec. - # - # @example Assert that a +windows_path+ was removed - # expect(chef_run).to remove_windows_path('C:\7-Zip') - # - # - # @param [String, Regex] resource_name - # the name of the resource to match - # - # @return [ChefSpec::Matchers::ResourceMatcher] - # - def remove_windows_path(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_path, :remove, resource_name) - end - - - - # - # Assert that a +windows_batch+ resource exists in the Chef run with the - # action +:run+. Given a Chef Recipe that runs a batch script - # - # windows_batch "unzip_and_move_ruby" do - # code <<-EOH - # 7z.exe x #{Chef::Config[:file_cache_path]}/ruby-1.8.7-p352-i386-mingw32.7z - # -oC:\\source -r -y - # xcopy C:\\source\\ruby-1.8.7-p352-i386-mingw32 C:\\ruby /e /y - # EOH - # end - # - # The Examples section demonstrates the different ways to test a - # +windows_path+ resource with ChefSpec. - # - # @example Assert that a +windows_path+ was removed - # expect(chef_run).to run_windows_batch('unzip_and_move_ruby') - # - # - # @param [String, Regex] resource_name - # the name of the resource to match - # - # @return [ChefSpec::Matchers::ResourceMatcher] - # - def run_windows_batch(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_batch, :run, resource_name) - end - - - - # - # Assert that a +windows_pagefile+ resource exists in the Chef run with the - # action +:set+. Given a Chef Recipe that sets a pagefile - # - # windows_pagefile "pagefile" do - # system_managed true - # initial_size 1024 - # maximum_size 4096 - # end - # - # The Examples section demonstrates the different ways to test a - # +windows_pagefile+ resource with ChefSpec. - # - # @example Assert that a +windows_pagefile+ was set - # expect(chef_run).to set_windows_pagefile('pagefile').with( - # initial_size: 1024) - # - # - # @param [String, Regex] resource_name - # the name of the resource to match - # - # @return [ChefSpec::Matchers::ResourceMatcher] - # - def set_windows_pagefile(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_pagefile, :set, resource_name) - end - - - - # - # Assert that a +windows_zipfile+ resource exists in the Chef run with the - # action +:unzip+. Given a Chef Recipe that extracts "SysinternalsSuite.zip" - # to c:/bin - # - # windows_zipfile "c:/bin" do - # source "http://download.sysinternals.com/Files/SysinternalsSuite.zip" - # action :unzip - # not_if {::File.exists?("c:/bin/PsExec.exe")} - # end - # - # The Examples section demonstrates the different ways to test a - # +windows_zipfile+ resource with ChefSpec. - # - # @example Assert that a +windows_zipfile+ was unzipped - # expect(chef_run).to unzip_windows_zipfile_to('c:/bin') - # - # - # @param [String, Regex] resource_name - # the name of the resource to match - # - # @return [ChefSpec::Matchers::ResourceMatcher] - # - def unzip_windows_zipfile_to(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_zipfile, :unzip, resource_name) - end - - # - # Assert that a +windows_zipfile+ resource exists in the Chef run with the - # action +:zip+. Given a Chef Recipe that zips "c:/src" - # to c:/code.zip - # - # windows_zipfile "c:/code.zip" do - # source "c:/src" - # action :zip - # end - # - # The Examples section demonstrates the different ways to test a - # +windows_zipfile+ resource with ChefSpec. - # - # @example Assert that a +windows_zipfile+ was zipped - # expect(chef_run).to zip_windows_zipfile_to('c:/code.zip') - # - # - # @param [String, Regex] resource_name - # the name of the resource to match - # - # @return [ChefSpec::Matchers::ResourceMatcher] - # - def zip_windows_zipfile_to(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_zipfile, :zip, resource_name) - end - - - # All the other less commonly used LWRPs - def create_windows_shortcut(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_shortcut, :create, resource_name) - end - - def create_windows_auto_run(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_auto_run, :create, resource_name) - end - - def remove_windows_auto_run(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_auto_run, :remove, resource_name) - end - - def create_windows_printer(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_printer, :create, resource_name) - end - - def delete_windows_printer(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_printer, :delete, resource_name) - end - - def create_windows_printer_port(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_printer_port, :create, resource_name) - end - - def delete_windows_printer_port(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_printer_port, :delete, resource_name) - end - - def request_windows_reboot(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_reboot, :request, resource_name) - end - - def cancel_windows_reboot(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:windows_reboot, :cancel, resource_name) - end - -end +if defined?(ChefSpec) + chefspec_version = Gem.loaded_specs['chefspec'].version + if chefspec_version < Gem::Version.new('4.1.0') + define_method = ChefSpec::Runner.method(:define_runner_method) + else + define_method = ChefSpec.method(:define_matcher) + end + + define_method.call :windows_package + define_method.call :windows_feature + define_method.call :windows_task + define_method.call :windows_path + define_method.call :windows_batch + define_method.call :windows_pagefile + define_method.call :windows_zipfile + define_method.call :windows_shortcut + define_method.call :windows_auto_run + define_method.call :windows_printer + define_method.call :windows_printer_port + define_method.call :windows_reboot + # + # Assert that a +windows_package+ resource exists in the Chef run with the + # action +:install+. Given a Chef Recipe that installs "Node.js" as a + # +windows_package+: + # + # windows_package 'Node.js' do + # source 'http://nodejs.org/dist/v0.10.26/x64/node-v0.10.26-x64.msi' + # action :install + # end + # + # The Examples section demonstrates the different ways to test a + # +windows_package+ resource with ChefSpec. + # + # @example Assert that a +windows_package+ was installed + # expect(chef_run).to install_windows_package('Node.js') + # + # @example Assert that a +windows_package+ was _not_ installed + # expect(chef_run).to_not install_windows_package('7-zip') + # + # + # @param [String, Regex] resource_name + # the name of the resource to match + # + # @return [ChefSpec::Matchers::ResourceMatcher] + # + def install_windows_package(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_package, :install, resource_name) + end + + # + # Assert that a +windows_package+ resource exists in the Chef run with the + # action +:remove+. Given a Chef Recipe that removes "Node.js" as a + # +windows_package+: + # + # windows_package 'Node.js' do + # action :remove + # end + # + # The Examples section demonstrates the different ways to test a + # +windows_package+ resource with ChefSpec. + # + # @example Assert that a +windows_package+ was installed + # expect(chef_run).to remove_windows_package('Node.js') + # + # @example Assert that a +windows_package+ was _not_ removed + # expect(chef_run).to_not remove_windows_package('7-zip') + # + # + # @param [String, Regex] resource_name + # the name of the resource to match + # + # @return [ChefSpec::Matchers::ResourceMatcher] + # + def remove_windows_package(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_package, :remove, resource_name) + end + + # + # Assert that a +windows_feature+ resource exists in the Chef run with the + # action +:install+. Given a Chef Recipe that installs "NetFX3" as a + # +windows_feature+: + # + # windows_feature 'NetFX3' do + # action :install + # end + # + # The Examples section demonstrates the different ways to test a + # +windows_feature+ resource with ChefSpec. + # + # @example Assert that a +windows_feature+ was installed + # expect(chef_run).to install_windows_feature('NetFX3') + # + # @example Assert that a +windows_feature+ was _not_ installed + # expect(chef_run).to_not install_windows_feature('NetFX3') + # + # + # @param [String, Regex] resource_name + # the name of the resource to match + # + # @return [ChefSpec::Matchers::ResourceMatcher] + # + def install_windows_feature(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_feature, :install, resource_name) + end + + # + # Assert that a +windows_feature+ resource exists in the Chef run with the + # action +:remove+. Given a Chef Recipe that removes "NetFX3" as a + # +windows_feature+: + # + # windows_feature 'NetFX3' do + # action :remove + # end + # + # The Examples section demonstrates the different ways to test a + # +windows_feature+ resource with ChefSpec. + # + # @example Assert that a +windows_feature+ was removed + # expect(chef_run).to remove_windows_feature('NetFX3') + # + # + # @param [String, Regex] resource_name + # the name of the resource to match + # + # @return [ChefSpec::Matchers::ResourceMatcher] + # + def remove_windows_feature(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_feature, :remove, resource_name) + end + + # + # Assert that a +windows_feature+ resource exists in the Chef run with the + # action +:delete+. Given a Chef Recipe that deletes "NetFX3" as a + # +windows_feature+: + # + # windows_feature 'NetFX3' do + # action :delete + # end + # + # The Examples section demonstrates the different ways to test a + # +windows_feature+ resource with ChefSpec. + # + # @example Assert that a +windows_feature+ was deleted + # expect(chef_run).to delete_windows_feature('NetFX3') + # + # + # @param [String, Regex] resource_name + # the name of the resource to match + # + # @return [ChefSpec::Matchers::ResourceMatcher] + # + def delete_windows_feature(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_feature, :delete, resource_name) + end + + # + # Assert that a +windows_task+ resource exists in the Chef run with the + # action +:create+. Given a Chef Recipe that creates "mytask" as a + # +windows_task+: + # + # windows_task 'mytask' do + # command 'mybatch.bat' + # action :create + # end + # + # The Examples section demonstrates the different ways to test a + # +windows_task+ resource with ChefSpec. + # + # @example Assert that a +windows_task+ was created + # expect(chef_run).to create_windows_task('mytask') + # + # + # @param [String, Regex] resource_name + # the name of the resource to match + # + # @return [ChefSpec::Matchers::ResourceMatcher] + # + def create_windows_task(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_task, :create, resource_name) + end + + # + # Assert that a +windows_task+ resource exists in the Chef run with the + # action +:delete+. Given a Chef Recipe that deletes "mytask" as a + # +windows_task+: + # + # windows_task 'mytask' do + # action :delete + # end + # + # The Examples section demonstrates the different ways to test a + # +windows_task+ resource with ChefSpec. + # + # @example Assert that a +windows_task+ was deleted + # expect(chef_run).to delete_windows_task('mytask') + # + # + # @param [String, Regex] resource_name + # the name of the resource to match + # + # @return [ChefSpec::Matchers::ResourceMatcher] + # + def delete_windows_task(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_task, :delete, resource_name) + end + + # + # Assert that a +windows_task+ resource exists in the Chef run with the + # action +:run+. Given a Chef Recipe that runs "mytask" as a + # +windows_task+: + # + # windows_task 'mytask' do + # action :run + # end + # + # The Examples section demonstrates the different ways to test a + # +windows_task+ resource with ChefSpec. + # + # @example Assert that a +windows_task+ was run + # expect(chef_run).to run_windows_task('mytask') + # + # + # @param [String, Regex] resource_name + # the name of the resource to match + # + # @return [ChefSpec::Matchers::ResourceMatcher] + # + def run_windows_task(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_task, :run, resource_name) + end + + # + # Assert that a +windows_task+ resource exists in the Chef run with the + # action +:change+. Given a Chef Recipe that changes "mytask" as a + # +windows_task+: + # + # windows_task 'mytask' do + # action :change + # end + # + # The Examples section demonstrates the different ways to test a + # +windows_task+ resource with ChefSpec. + # + # @example Assert that a +windows_task+ was changed + # expect(chef_run).to change_windows_task('mytask') + # + # + # @param [String, Regex] resource_name + # the name of the resource to match + # + # @return [ChefSpec::Matchers::ResourceMatcher] + # + def change_windows_task(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_task, :change, resource_name) + end + + # + # Assert that a +windows_path+ resource exists in the Chef run with the + # action +:add+. Given a Chef Recipe that adds "C:\7-Zip" to the Windows + # PATH env var + # + # windows_path 'C:\7-Zip' do + # action :add + # end + # + # The Examples section demonstrates the different ways to test a + # +windows_path+ resource with ChefSpec. + # + # @example Assert that a +windows_path+ was added + # expect(chef_run).to add_windows_path('C:\7-Zip') + # + # + # @param [String, Regex] resource_name + # the name of the resource to match + # + # @return [ChefSpec::Matchers::ResourceMatcher] + # + def add_windows_path(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_path, :add, resource_name) + end + + # + # Assert that a +windows_path+ resource exists in the Chef run with the + # action +:remove+. Given a Chef Recipe that removes "C:\7-Zip" from the + # Windows PATH env var + # + # windows_path 'C:\7-Zip' do + # action :remove + # end + # + # The Examples section demonstrates the different ways to test a + # +windows_path+ resource with ChefSpec. + # + # @example Assert that a +windows_path+ was removed + # expect(chef_run).to remove_windows_path('C:\7-Zip') + # + # + # @param [String, Regex] resource_name + # the name of the resource to match + # + # @return [ChefSpec::Matchers::ResourceMatcher] + # + def remove_windows_path(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_path, :remove, resource_name) + end + + # + # Assert that a +windows_batch+ resource exists in the Chef run with the + # action +:run+. Given a Chef Recipe that runs a batch script + # + # windows_batch "unzip_and_move_ruby" do + # code <<-EOH + # 7z.exe x #{Chef::Config[:file_cache_path]}/ruby-1.8.7-p352-i386-mingw32.7z + # -oC:\\source -r -y + # xcopy C:\\source\\ruby-1.8.7-p352-i386-mingw32 C:\\ruby /e /y + # EOH + # end + # + # The Examples section demonstrates the different ways to test a + # +windows_path+ resource with ChefSpec. + # + # @example Assert that a +windows_path+ was removed + # expect(chef_run).to run_windows_batch('unzip_and_move_ruby') + # + # + # @param [String, Regex] resource_name + # the name of the resource to match + # + # @return [ChefSpec::Matchers::ResourceMatcher] + # + def run_windows_batch(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_batch, :run, resource_name) + end + + # + # Assert that a +windows_pagefile+ resource exists in the Chef run with the + # action +:set+. Given a Chef Recipe that sets a pagefile + # + # windows_pagefile "pagefile" do + # system_managed true + # initial_size 1024 + # maximum_size 4096 + # end + # + # The Examples section demonstrates the different ways to test a + # +windows_pagefile+ resource with ChefSpec. + # + # @example Assert that a +windows_pagefile+ was set + # expect(chef_run).to set_windows_pagefile('pagefile').with( + # initial_size: 1024) + # + # + # @param [String, Regex] resource_name + # the name of the resource to match + # + # @return [ChefSpec::Matchers::ResourceMatcher] + # + def set_windows_pagefile(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_pagefile, :set, resource_name) + end + + # + # Assert that a +windows_zipfile+ resource exists in the Chef run with the + # action +:unzip+. Given a Chef Recipe that extracts "SysinternalsSuite.zip" + # to c:/bin + # + # windows_zipfile "c:/bin" do + # source "http://download.sysinternals.com/Files/SysinternalsSuite.zip" + # action :unzip + # not_if {::File.exists?("c:/bin/PsExec.exe")} + # end + # + # The Examples section demonstrates the different ways to test a + # +windows_zipfile+ resource with ChefSpec. + # + # @example Assert that a +windows_zipfile+ was unzipped + # expect(chef_run).to unzip_windows_zipfile_to('c:/bin') + # + # + # @param [String, Regex] resource_name + # the name of the resource to match + # + # @return [ChefSpec::Matchers::ResourceMatcher] + # + def unzip_windows_zipfile_to(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_zipfile, :unzip, resource_name) + end + + # + # Assert that a +windows_zipfile+ resource exists in the Chef run with the + # action +:zip+. Given a Chef Recipe that zips "c:/src" + # to c:/code.zip + # + # windows_zipfile "c:/code.zip" do + # source "c:/src" + # action :zip + # end + # + # The Examples section demonstrates the different ways to test a + # +windows_zipfile+ resource with ChefSpec. + # + # @example Assert that a +windows_zipfile+ was zipped + # expect(chef_run).to zip_windows_zipfile_to('c:/code.zip') + # + # + # @param [String, Regex] resource_name + # the name of the resource to match + # + # @return [ChefSpec::Matchers::ResourceMatcher] + # + def zip_windows_zipfile_to(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_zipfile, :zip, resource_name) + end + + # All the other less commonly used LWRPs + def create_windows_shortcut(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_shortcut, :create, resource_name) + end + + def create_windows_auto_run(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_auto_run, :create, resource_name) + end + + def remove_windows_auto_run(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_auto_run, :remove, resource_name) + end + + def create_windows_printer(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_printer, :create, resource_name) + end + + def delete_windows_printer(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_printer, :delete, resource_name) + end + + def create_windows_printer_port(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_printer_port, :create, resource_name) + end + + def delete_windows_printer_port(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_printer_port, :delete, resource_name) + end + + def request_windows_reboot(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_reboot, :request, resource_name) + end + + def cancel_windows_reboot(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:windows_reboot, :cancel, resource_name) + end + +end diff --git a/cookbooks/windows/libraries/powershell_helper.rb b/cookbooks/windows/libraries/powershell_helper.rb index 0e42574..aba93a3 100644 --- a/cookbooks/windows/libraries/powershell_helper.rb +++ b/cookbooks/windows/libraries/powershell_helper.rb @@ -1,59 +1,53 @@ -# -# Author:: Seth Chisamore () -# Cookbook Name:: windows -# Library:: helper -# -# Copyright:: 2011, 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 - begin - 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 - if cmd.stdout =~ /^(\d+)/ - $1.to_i - else - nil - end - end - rescue Errno::ENOENT - nil - end - end - end -end +# +# Author:: Seth Chisamore () +# Cookbook Name:: windows +# Library:: helper +# +# 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. +# + +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/powershell_out.rb b/cookbooks/windows/libraries/powershell_out.rb index 9edeb57..ffd5c9e 100644 --- a/cookbooks/windows/libraries/powershell_out.rb +++ b/cookbooks/windows/libraries/powershell_out.rb @@ -1,79 +1,92 @@ -class Chef - module Mixin - module PowershellOut - include Chef::Mixin::ShellOut - - begin - include Chef::Mixin::WindowsArchitectureHelper - rescue - # nothing to do, as the include will happen when windows_architecture_helper.rb - # is loaded. This is for ease of removal of that library when either - # powershell_out is core chef or powershell cookbook depends upon version - # of chef that has Chef::Mixin::WindowsArchitectureHelper in core chef - end - - def powershell_out(*command_args) - script = command_args.first - options = command_args.last.is_a?(Hash) ? command_args.last : nil - - run_command(script, options) - end - - def powershell_out!(*command_args) - cmd = powershell_out(*command_args) - cmd.error! - cmd - end - - private - def run_command(script, options) - if options && options[:architecture] - architecture = options[:architecture] - options.delete(:architecture) - else - architecture = node_windows_architecture(node) - end - - disable_redirection = wow64_architecture_override_required?(node, architecture) - - if disable_redirection - original_redirection_state = disable_wow64_file_redirection(node) - end - - command = build_command(script) - - if options - cmd = shell_out(command, options) - else - cmd = shell_out(command) - end - - if disable_redirection - restore_wow64_file_redirection(node, original_redirection_state) - end - - cmd - end - - def build_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 RemoteSigned", - # 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" - ] - - command = "powershell.exe #{flags.join(' ')} -Command \"#{script}\"" - command - end - end - end -end + +# +# WARNING +# +# THIS CODE HAS BEEN MOVED TO CORE CHEF. DO NOT SUMBIT PULL REQUESTS AGAINST THIS +# CODE. IT WILL BE REMOVED IN THE FUTURE. +# + +unless defined? Chef::Mixin::PowershellOut + class Chef + module Mixin + module PowershellOut + include Chef::Mixin::ShellOut + + begin + include Chef::Mixin::WindowsArchitectureHelper + rescue + # nothing to do, as the include will happen when windows_architecture_helper.rb + # is loaded. This is for ease of removal of that library when either + # powershell_out is core chef or powershell cookbook depends upon version + # of chef that has Chef::Mixin::WindowsArchitectureHelper in core chef + end + + def powershell_out(*command_args) + Chef::Log.warn 'The powershell_out library in the windows cookbook is deprecated.' + Chef::Log.warn 'Please upgrade to Chef 12.4.0 or later where it is built-in to core chef.' + script = command_args.first + options = command_args.last.is_a?(Hash) ? command_args.last : nil + + run_command(script, options) + end + + def powershell_out!(*command_args) + cmd = powershell_out(*command_args) + cmd.error! + cmd + end + + private + + def run_command(script, options) + if options && options[:architecture] + architecture = options[:architecture] + options.delete(:architecture) + else + architecture = node_windows_architecture(node) + end + + disable_redirection = wow64_architecture_override_required?(node, architecture) + + if disable_redirection + original_redirection_state = disable_wow64_file_redirection(node) + end + + command = build_command(script) + + if options + cmd = shell_out(command, options) + else + cmd = shell_out(command) + end + + if disable_redirection + restore_wow64_file_redirection(node, original_redirection_state) + end + + cmd + end + + def build_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 RemoteSigned', + # 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' + ] + + command = "powershell.exe #{flags.join(' ')} -Command \"#{script}\"" + command + end + end + end + end +end diff --git a/cookbooks/windows/libraries/registry_helper.rb b/cookbooks/windows/libraries/registry_helper.rb index a63df45..531d4a2 100644 --- a/cookbooks/windows/libraries/registry_helper.rb +++ b/cookbooks/windows/libraries/registry_helper.rb @@ -1,364 +1,355 @@ -# -# Author:: Doug MacEachern () -# Author:: Seth Chisamore () -# Author:: Paul Morton () -# Cookbook Name:: windows -# Provider:: registry -# -# Copyright:: 2010, VMware, Inc. -# Copyright:: 2011, Chef Software, Inc. -# Copyright:: 2011, 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 = ENV['PROCESSOR_ARCHITEW6432'] == 'AMD64' ? 0x0100 : 0x0200 - - 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}") - return 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}") - return 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}") - - if !key_exists?(path,true) - create_key(path) - end - - 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 - if cur_val != val - Chef::Log.debug("setting #{key}=#{val}") - - if type.nil? - type = :string - end - - 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 - end - return changed_something - end - return 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 { |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 - - 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 - return 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) - begin - 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}") - return sid - rescue - return nil - end - end - - def hive_loaded?(path) - hive = get_hive(path) - reg_path = path.split("\\") - hive_name = reg_path.shift - user_hive = path[0] - - if is_user_hive?(hive) - return key_exists?("#{hive_name}\\#{user_hive}") - else - return true - end - end - - def is_user_hive?(hive) - if hive == ::Win32::Registry::HKEY_USERS - return true - else - return true - end - 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 is_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 - - return 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 is_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) - if profile_path != nil - ntuser_dat = "#{profile_path}\\NTUSER.DAT" - if ::File.exists?(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 - - return 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 - extend Windows::RegistryHelper -end +# +# Author:: Doug MacEachern () +# Author:: Seth Chisamore () +# Author:: Paul Morton () +# Cookbook Name:: windows +# Provider:: registry +# +# Copyright:: 2010, VMware, Inc. +# Copyright:: 2011-2015, Chef Software, Inc. +# Copyright:: 2011, 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 = ENV['PROCESSOR_ARCHITEW6432'] == 'AMD64' ? 0x0100 : 0x0200 + + 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}") + return sid + rescue + return 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) + if hive == ::Win32::Registry::HKEY_USERS + return true + else + return true + end + 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 + + extend Windows::RegistryHelper +end diff --git a/cookbooks/windows/libraries/version.rb b/cookbooks/windows/libraries/version.rb index 5dc802f..685aca8 100644 --- a/cookbooks/windows/libraries/version.rb +++ b/cookbooks/windows/libraries/version.rb @@ -1,207 +1,207 @@ -# -# Author:: Seth Chisamore () -# Cookbook Name:: windows -# Library:: version -# -# Copyright:: 2011, 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' - require 'Win32API' -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.freeze unless defined?(VER_SUITE_BACKOFFICE) - # Windows Server 2003, Web Edition is installed. - VER_SUITE_BLADE = 0x00000400.freeze unless defined?(VER_SUITE_BLADE) - # Windows Server 2003, Compute Cluster Edition is installed. - VER_SUITE_COMPUTE_SERVER = 0x00004000.freeze unless defined?(VER_SUITE_COMPUTE_SERVER) - # Windows Server 2008 Datacenter, Windows Server 2003, Datacenter Edition, or Windows 2000 Datacenter Server is installed. - VER_SUITE_DATACENTER = 0x00000080.freeze 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.freeze unless defined?(VER_SUITE_ENTERPRISE) - # Windows XP Embedded is installed. - VER_SUITE_EMBEDDEDNT = 0x00000040.freeze unless defined?(VER_SUITE_EMBEDDEDNT) - # Windows Vista Home Premium, Windows Vista Home Basic, or Windows XP Home Edition is installed. - VER_SUITE_PERSONAL = 0x00000200.freeze 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.freeze 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.freeze 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.freeze unless defined?(VER_SUITE_SMALLBUSINESS_RESTRICTED) - # Windows Storage Server 2003 R2 or Windows Storage Server 2003is installed. - VER_SUITE_STORAGE_SERVER = 0x00002000.freeze unless defined?(VER_SUITE_STORAGE_SERVER) - # 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.freeze unless defined?(VER_SUITE_TERMINAL) - # Windows Home Server is installed. - VER_SUITE_WH_SERVER = 0x00008000.freeze 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.freeze 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.freeze 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.freeze unless defined?(VER_NT_WORKSTATION) - - # GetSystemMetrics - # The build number if the system is Windows Server 2003 R2; otherwise, 0. - SM_SERVERR2 = 89.freeze unless defined?(SM_SERVERR2) - - # 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{|v| v.to_i } - end - - WIN_VERSIONS = { - "Windows Server 2012 R2" => {:major => 6, :minor => 3, :callable => lambda{ @product_type != VER_NT_WORKSTATION }}, - "Windows 8" => {:major => 6, :minor => 2, :callable => lambda{ @product_type == VER_NT_WORKSTATION }}, - "Windows Server 2012" => {:major => 6, :minor => 2, :callable => lambda{ @product_type != VER_NT_WORKSTATION }}, - "Windows 7" => {:major => 6, :minor => 1, :callable => lambda{ @product_type == VER_NT_WORKSTATION }}, - "Windows Server 2008 R2" => {:major => 6, :minor => 1, :callable => lambda{ @product_type != VER_NT_WORKSTATION }}, - "Windows Server 2008" => {:major => 6, :minor => 0, :callable => lambda{ @product_type != VER_NT_WORKSTATION }}, - "Windows Vista" => {:major => 6, :minor => 0, :callable => lambda{ @product_type == VER_NT_WORKSTATION }}, - "Windows Server 2003 R2" => {:major => 5, :minor => 2, :callable => lambda{ Win32API.new('user32', 'GetSystemMetrics', 'I', 'I').call(SM_SERVERR2) != 0 }}, - "Windows Home Server" => {:major => 5, :minor => 2, :callable => lambda{ (@product_suite & VER_SUITE_WH_SERVER) == VER_SUITE_WH_SERVER }}, - "Windows Server 2003" => {:major => 5, :minor => 2, :callable => lambda{ Win32API.new('user32', 'GetSystemMetrics', 'I', 'I').call(SM_SERVERR2) == 0 }}, - "Windows XP" => {:major => 5, :minor => 1}, - "Windows 2000" => {:major => 5, :minor => 0} - }.freeze unless defined?(WIN_VERSIONS) - - marketing_names = Array.new - - # 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 self.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 - # Win32API call to GetSystemMetrics(SM_SERVERR2) - # returns: The build number if the system is Windows Server 2003 R2; otherwise, 0. - def sm_serverr2 - @sm_serverr2 ||= Win32API.new('user32', 'GetSystemMetrics', 'I', 'I').call(SM_SERVERR2) - end - - # 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 +# +# Author:: Seth Chisamore () +# Cookbook Name:: windows +# Library:: version +# +# 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. +# + +if RUBY_PLATFORM =~ /mswin|mingw32|windows/ + require_relative 'wmi_helper' + require 'Win32API' +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 2003, Web Edition is installed. + VER_SUITE_BLADE = 0x00000400 unless defined?(VER_SUITE_BLADE) + # Windows Server 2003, Compute Cluster Edition is installed. + VER_SUITE_COMPUTE_SERVER = 0x00004000 unless defined?(VER_SUITE_COMPUTE_SERVER) + # 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) + # Windows Storage Server 2003 R2 or Windows Storage Server 2003is installed. + VER_SUITE_STORAGE_SERVER = 0x00002000 unless defined?(VER_SUITE_STORAGE_SERVER) + # 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) + + # GetSystemMetrics + # The build number if the system is Windows Server 2003 R2; otherwise, 0. + SM_SERVERR2 = 89 unless defined?(SM_SERVERR2) + + # 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/ + fail 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 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 Server 2003 R2' => { major: 5, minor: 2, callable: -> { Win32API.new('user32', 'GetSystemMetrics', 'I', 'I').call(SM_SERVERR2) != 0 } }, + 'Windows Home Server' => { major: 5, minor: 2, callable: -> { (@product_suite & VER_SUITE_WH_SERVER) == VER_SUITE_WH_SERVER } }, + 'Windows Server 2003' => { major: 5, minor: 2, callable: -> { Win32API.new('user32', 'GetSystemMetrics', 'I', 'I').call(SM_SERVERR2) == 0 } }, + '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 + + # Win32API call to GetSystemMetrics(SM_SERVERR2) + # returns: The build number if the system is Windows Server 2003 R2; otherwise, 0. + def sm_serverr2 + @sm_serverr2 ||= Win32API.new('user32', 'GetSystemMetrics', 'I', 'I').call(SM_SERVERR2) + end + + # 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/windows_architecture_helper.rb b/cookbooks/windows/libraries/windows_architecture_helper.rb index e2c2213..c8fc736 100644 --- a/cookbooks/windows/libraries/windows_architecture_helper.rb +++ b/cookbooks/windows/libraries/windows_architecture_helper.rb @@ -1,87 +1,86 @@ -# Try to include from core chef, if error then monkey patch it in. - -begin - include Chef::Mixin::WindowsArchitectureHelper -rescue - Chef::Log.debug("Chef::Mixin::WindowsArchitectureHelper not in core version, Monkey patching in.") - - require 'chef/exceptions' - require 'win32/api' if Chef::Platform.windows? - - class Chef - module Mixin - module WindowsArchitectureHelper - - def node_windows_architecture(node) - node['kernel']['machine'].to_sym - end - - def wow64_architecture_override_required?(node, desired_architecture) - is_i386_windows_process? && - node_windows_architecture(node) == :x86_64 && - desired_architecture == :x86_64 - end - - def node_supports_windows_architecture?(node, desired_architecture) - assert_valid_windows_architecture!(desired_architecture) - return (node_windows_architecture(node) == :x86_64 || - desired_architecture == :i386) ? true : false - end - - def valid_windows_architecture?(architecture) - return (architecture == :x86_64) || (architecture == :i386) - end - - def assert_valid_windows_architecture!(architecture) - if ! valid_windows_architecture?(architecture) - raise Chef::Exceptions::Win32ArchitectureIncorrect, - "The specified architecture was not valid. It must be one of :i386 or :x86_64" - end - end - - def is_i386_windows_process? - Chef::Platform.windows? && 'X86'.casecmp(ENV['PROCESSOR_ARCHITECTURE']) == 0 - end - - def disable_wow64_file_redirection(node) - original_redirection_state = ['0'].pack('P') - - if ((node_windows_architecture(node) == :x86_64) && ::Chef::Platform.windows?) - win32_wow_64_disable_wow_64_fs_redirection = - ::Win32::API.new('Wow64DisableWow64FsRedirection', 'P', 'L', 'kernel32') - - succeeded = win32_wow_64_disable_wow_64_fs_redirection.call(original_redirection_state) - - if succeeded == 0 - raise Win32APIError "Failed to disable Wow64 file redirection" - end - - end - - original_redirection_state - end - - def restore_wow64_file_redirection(node, original_redirection_state) - if ( (node_windows_architecture(node) == :x86_64) && ::Chef::Platform.windows?) - win32_wow_64_revert_wow_64_fs_redirection = - ::Win32::API.new('Wow64RevertWow64FsRedirection', 'P', 'L', 'kernel32') - - succeeded = win32_wow_64_revert_wow_64_fs_redirection.call(original_redirection_state) - - if succeeded == 0 - raise Win32APIError "Failed to revert Wow64 file redirection" - end - end - end - end - end - end -end - -# Making sure this library is available to Chef::Mixin::PowershellOut -# Required for clients that don't have Chef::Mixin::WindowsArchitectureHelper in -# core chef. -if ::Chef::Platform.windows? - require_relative 'powershell_out' - Chef::Mixin::PowershellOut.send(:include, Chef::Mixin::WindowsArchitectureHelper) -end +# Try to include from core chef, if error then monkey patch it in. + +begin + include Chef::Mixin::WindowsArchitectureHelper +rescue + Chef::Log.debug('Chef::Mixin::WindowsArchitectureHelper not in core version, Monkey patching in.') + + require 'chef/exceptions' + require 'win32/api' if Chef::Platform.windows? + + class Chef + module Mixin + module WindowsArchitectureHelper + def node_windows_architecture(node) + node['kernel']['machine'].to_sym + end + + def wow64_architecture_override_required?(node, desired_architecture) + i386_windows_process? && + node_windows_architecture(node) == :x86_64 && + desired_architecture == :x86_64 + end + + def node_supports_windows_architecture?(node, desired_architecture) + assert_valid_windows_architecture!(desired_architecture) + (node_windows_architecture(node) == :x86_64 || + desired_architecture == :i386) ? true : false + end + + def valid_windows_architecture?(architecture) + (architecture == :x86_64) || (architecture == :i386) + end + + def assert_valid_windows_architecture!(architecture) + unless valid_windows_architecture?(architecture) + raise Chef::Exceptions::Win32ArchitectureIncorrect, + 'The specified architecture was not valid. It must be one of :i386 or :x86_64' + end + end + + def i386_windows_process? + Chef::Platform.windows? && 'X86'.casecmp(ENV['PROCESSOR_ARCHITECTURE']) == 0 + end + + def disable_wow64_file_redirection(node) + original_redirection_state = ['0'].pack('P') + + if (node_windows_architecture(node) == :x86_64) && ::Chef::Platform.windows? + win32_wow_64_disable_wow_64_fs_redirection = + ::Win32::API.new('Wow64DisableWow64FsRedirection', 'P', 'L', 'kernel32') + + succeeded = win32_wow_64_disable_wow_64_fs_redirection.call(original_redirection_state) + + if succeeded == 0 + raise Win32APIError 'Failed to disable Wow64 file redirection' + end + + end + + original_redirection_state + end + + def restore_wow64_file_redirection(node, original_redirection_state) + if (node_windows_architecture(node) == :x86_64) && ::Chef::Platform.windows? + win32_wow_64_revert_wow_64_fs_redirection = + ::Win32::API.new('Wow64RevertWow64FsRedirection', 'P', 'L', 'kernel32') + + succeeded = win32_wow_64_revert_wow_64_fs_redirection.call(original_redirection_state) + + if succeeded == 0 + raise Win32APIError 'Failed to revert Wow64 file redirection' + end + end + end + end + end + end +end + +# Making sure this library is available to Chef::Mixin::PowershellOut +# Required for clients that don't have Chef::Mixin::WindowsArchitectureHelper in +# core chef. +if ::Chef::Platform.windows? + require_relative 'powershell_out' + Chef::Mixin::PowershellOut.send(:include, Chef::Mixin::WindowsArchitectureHelper) +end diff --git a/cookbooks/windows/libraries/windows_helper.rb b/cookbooks/windows/libraries/windows_helper.rb index f19cf62..75d8566 100644 --- a/cookbooks/windows/libraries/windows_helper.rb +++ b/cookbooks/windows/libraries/windows_helper.rb @@ -1,148 +1,168 @@ -# -# Author:: Seth Chisamore () -# Cookbook Name:: windows -# Library:: helper -# -# Copyright:: 2011, 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 'Win32API' if Chef::Platform.windows? -require 'chef/exceptions' - -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) - ExpandEnvironmentStrings = Win32API.new('kernel32', 'ExpandEnvironmentStrings', ['P', 'P', 'L'], 'L') if Chef::Platform.windows? - - # returns windows friendly version of the provided path, - # ensures backslashes are used everywhere - def win_friendly_path(path) - 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.exists?("#{ENV['WINDIR']}\\sysnative\\#{cmd}") - "#{ENV['WINDIR']}\\sysnative\\#{cmd}" - elsif ::File.exists?("#{ENV['WINDIR']}\\system32\\#{cmd}") - "#{ENV['WINDIR']}\\system32\\#{cmd}" - else - cmd - end - end - - # Create a feature provider dependent value object. - # mainly created becasue Windows Feature names are - # different based on whether dism.exe or servicemanagercmd.exe - # is used for installation - def value_for_feature_provider(provider_hash) - p = Chef::Platform.find_provider_for_node(node, :windows_feature) - key = p.to_s.downcase.split('::').last - provider_hash[key] || provider_hash[key.to_sym] - end - - # singleton instance of the Windows Version checker - def win_version - @win_version ||= Windows::Version.new - 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 =~ ::URI::ABS_URI && %w[ftp http https].include?(URI.parse(source).scheme) - uri = ::URI.parse(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}") - r = Chef::Resource::RemoteFile.new(cache_file_path, run_context) - r.source(source) - r.backup(false) - r.checksum(checksum) if checksum - r.run_action(:create) - else - cache_file_path = source - end - - windows_path ? win_friendly_path(cache_file_path) : cache_file_path - end - end - - # Expands the environment variables - def expand_env_vars(path) - # We pick 32k because that is the largest it could be: - # http://msdn.microsoft.com/en-us/library/windows/desktop/ms724265%28v=vs.85%29.aspx - buf = 0.chr * 32 * 1024 # 32k - if ExpandEnvironmentStrings.call(path.dup, buf, buf.length) == 0 - raise Chef::Exceptions::Win32APIError, "Failed calling ExpandEnvironmentStrings (received 0)" - end - buf.strip - end - - def is_package_installed?(package_name) - 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 - - 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 = k["DisplayName"] rescue nil - version = k["DisplayVersion"] rescue "NO VERSION" - uninstall_string = k["UninstallString"] rescue nil - 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) +# +# Author:: Seth Chisamore () +# Cookbook Name:: windows +# Library:: helper +# +# 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. + +require 'uri' +require 'Win32API' if Chef::Platform.windows? +require 'chef/exceptions' + +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) + ExpandEnvironmentStrings = Win32API.new('kernel32', 'ExpandEnvironmentStrings', %w(P P L), 'L') if Chef::Platform.windows? && !defined?(ExpandEnvironmentStrings) + + # returns windows friendly version of the provided path, + # ensures backslashes are used everywhere + def win_friendly_path(path) + 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 + + # Create a feature provider dependent value object. + # mainly created becasue Windows Feature names are + # different based on whether dism.exe or servicemanagercmd.exe + # is used for installation + def value_for_feature_provider(provider_hash) + p = Chef::Platform.find_provider_for_node(node, :windows_feature) + key = p.to_s.downcase.split('::').last + provider_hash[key] || provider_hash[key.to_sym] + 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 =~ /^(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}") + r = Chef::Resource::RemoteFile.new(cache_file_path, run_context) + r.source(source) + r.backup(false) + r.checksum(checksum) if checksum + r.run_action(:create) + else + cache_file_path = source + end + + windows_path ? win_friendly_path(cache_file_path) : cache_file_path + end + end + + # Expands the environment variables + def expand_env_vars(path) + # We pick 32k because that is the largest it could be: + # http://msdn.microsoft.com/en-us/library/windows/desktop/ms724265%28v=vs.85%29.aspx + buf = 0.chr * 32 * 1024 # 32k + if ExpandEnvironmentStrings.call(path.dup, buf, buf.length) == 0 + fail Chef::Exceptions::Win32APIError, 'Failed calling ExpandEnvironmentStrings (received 0)' + end + buf.strip + end + + def is_package_installed?(package_name) # rubocop:disable Style/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 + + 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_package.rb b/cookbooks/windows/libraries/windows_package.rb index cfa26a1..f8700f9 100644 --- a/cookbooks/windows/libraries/windows_package.rb +++ b/cookbooks/windows/libraries/windows_package.rb @@ -1,224 +1,226 @@ -require 'chef/resource/lwrp_base' -require 'chef/provider/lwrp_base' - -if RUBY_PLATFORM =~ /mswin|mingw32|windows/ - require 'win32/registry' -end - -require 'chef/mixin/shell_out' -require 'chef/mixin/language' -class Chef - class Provider - class WindowsCookbookPackage < Chef::Provider::LWRPBase - include Chef::Mixin::ShellOut - include Windows::Helper - - # the logic in all action methods mirror that of - # the Chef::Provider::Package which will make - # refactoring into core chef easy - - action :install do - # If we specified a version, and it's not the current version, move to the specified version - if @new_resource.version != nil && @new_resource.version != @current_resource.version - install_version = @new_resource.version - # If it's not installed at all, install it - elsif @current_resource.version == nil - install_version = candidate_version - end - - if install_version - Chef::Log.info("Installing #{@new_resource} version #{install_version}") - status = install_package(@new_resource.package_name, install_version) - if status - new_resource.updated_by_last_action(true) - end - end - end - - action :upgrade do - if @current_resource.version != candidate_version - orig_version = @current_resource.version || "uninstalled" - Chef::Log.info("Upgrading #{@new_resource} version from #{orig_version} to #{candidate_version}") - status = upgrade_package(@new_resource.package_name, candidate_version) - if status - new_resource.updated_by_last_action(true) - end - end - end - - action :remove do - if removing_package? - Chef::Log.info("Removing #{@new_resource}") - remove_package(@current_resource.package_name, @new_resource.version) - new_resource.updated_by_last_action(true) - else - end - end - - def removing_package? - if @current_resource.version.nil? - false # nothing to remove - elsif @new_resource.version.nil? - true # remove any version of a package - elsif @new_resource.version == @current_resource.version - true # remove the version we have - else - false # we don't have the version we want to remove - end - end - - def expand_options(options) - options ? " #{options}" : "" - end - - # these methods are the required overrides of - # a provider that extends from Chef::Provider::Package - # so refactoring into core Chef should be easy - - def load_current_resource - @current_resource = Chef::Resource::WindowsPackage.new(@new_resource.name) - @current_resource.package_name(@new_resource.package_name) - @current_resource.version(nil) - - unless current_installed_version.nil? - @current_resource.version(current_installed_version) - end - - @current_resource - end - - def current_installed_version - @current_installed_version ||= begin - if installed_packages.include?(@new_resource.package_name) - installed_packages[@new_resource.package_name][:version] - end - end - end - - def candidate_version - @candidate_version ||= begin - @new_resource.version || 'latest' - end - end - - def install_package(name,version) - Chef::Log.debug("Processing #{@new_resource} as a #{installer_type} installer.") - install_args = [cached_file(@new_resource.source, @new_resource.checksum), expand_options(unattended_installation_flags), expand_options(@new_resource.options)] - Chef::Log.info("Starting installation...this could take awhile.") - Chef::Log.debug "Install command: #{ sprintf(install_command_template, *install_args) }" - shell_out!(sprintf(install_command_template, *install_args), {:timeout => @new_resource.timeout, :returns => @new_resource.success_codes}) - end - - def remove_package(name, version) - uninstall_string = installed_packages[@new_resource.package_name][:uninstall_string] - Chef::Log.info("Registry provided uninstall string for #{@new_resource} is '#{uninstall_string}'") - uninstall_command = begin - if uninstall_string =~ /msiexec/i - "#{uninstall_string} /qn" - else - uninstall_string.gsub!('"','') - "start \"\" /wait /d\"#{::File.dirname(uninstall_string)}\" #{::File.basename(uninstall_string)}#{expand_options(@new_resource.options)} /S & exit %%%%ERRORLEVEL%%%%" - end - end - Chef::Log.info("Removing #{@new_resource} with uninstall command '#{uninstall_command}'") - shell_out!(uninstall_command, {:returns => @new_resource.success_codes}) - end - - private - - def install_command_template - case installer_type - when :msi - "msiexec%2$s \"%1$s\"%3$s" - else - "start \"\" /wait \"%1$s\"%2$s%3$s & exit %%%%ERRORLEVEL%%%%" - end - end - - - # http://unattended.sourceforge.net/installers.php - def unattended_installation_flags - case installer_type - when :msi - # this is no-ui - "/qn /i" - when :installshield - "/s /sms" - when :nsis - "/S /NCRC" - when :inno - #"/sp- /silent /norestart" - "/verysilent /norestart" - when :wise - "/s" - else - end - end - - def installer_type - @installer_type || begin - if @new_resource.installer_type - @new_resource.installer_type - else - basename = ::File.basename(cached_file(@new_resource.source, @new_resource.checksum)) - if basename.split(".").last.downcase == "msi" # Microsoft MSI - :msi - else - # search the binary file for installer type - contents = ::Kernel.open(::File.expand_path(cached_file(@new_resource.source)), "rb") {|io| io.read } # TODO limit data read in - case contents - when /inno/i # Inno Setup - :inno - when /wise/i # Wise InstallMaster - :wise - when /nsis/i # Nullsoft Scriptable Install System - :nsis - else - # if file is named 'setup.exe' assume installshield - if basename == "setup.exe" - :installshield - else - raise Chef::Exceptions::AttributeNotFound, "installer_type could not be determined, please set manually" - end - end - end - end - end - end - end - end -end - - -class Chef - class Resource - class WindowsCookbookPackage < Chef::Resource::LWRPBase - if Gem::Version.new(Chef::VERSION) >= Gem::Version.new('12') - provides :windows_package, os: "windows" - end - actions :install, :remove - - default_action :install - - attribute :package_name, :kind_of => String, :name_attribute => true - attribute :source, :kind_of => String, :required => true - attribute :version, :kind_of => String - attribute :options, :kind_of => String - attribute :installer_type, :kind_of => Symbol, :default => nil, :equal_to => [:msi, :inno, :nsis, :wise, :installshield, :custom] - attribute :checksum, :kind_of => String - attribute :timeout, :kind_of => Integer, :default => 600 - attribute :success_codes, :kind_of => Array, :default => [0, 42, 127] - - self.resource_name = 'windows_package' - def initialize(*args) - super - @provider = Chef::Provider::WindowsCookbookPackage - end - end - end -end - -if Gem::Version.new(Chef::VERSION) < Gem::Version.new('12') - Chef::Resource.send(:remove_const, :WindowsPackage) if defined? Chef::Resource::WindowsPackage - Chef::Resource.const_set("WindowsPackage", Chef::Resource::WindowsCookbookPackage) -end +require 'chef/resource/lwrp_base' +require 'chef/provider/lwrp_base' + +require 'win32/registry' if RUBY_PLATFORM =~ /mswin|mingw32|windows/ + +require 'chef/mixin/shell_out' +require 'chef/mixin/language' +class Chef + class Provider + class WindowsCookbookPackage < Chef::Provider::LWRPBase + include Chef::Mixin::ShellOut + include Windows::Helper + + # the logic in all action methods mirror that of + # the Chef::Provider::Package which will make + # refactoring into core chef easy + + action :install do + # If we specified a version, and it's not the current version, move to the specified version + if !@new_resource.version.nil? && @new_resource.version != @current_resource.version + install_version = @new_resource.version + # If it's not installed at all, install it + elsif @current_resource.version.nil? + install_version = candidate_version + end + + if install_version + Chef::Log.info("Installing #{@new_resource} version #{install_version}") + status = install_package(@new_resource.package_name, install_version) + new_resource.updated_by_last_action(true) if status + end + end + + action :upgrade do + if @current_resource.version != candidate_version + orig_version = @current_resource.version || 'uninstalled' + Chef::Log.info("Upgrading #{@new_resource} version from #{orig_version} to #{candidate_version}") + status = upgrade_package(@new_resource.package_name, candidate_version) + new_resource.updated_by_last_action(true) if status + end + end + + action :remove do + if removing_package? + Chef::Log.info("Removing #{@new_resource}") + remove_package(@current_resource.package_name, @new_resource.version) + new_resource.updated_by_last_action(true) + end + end + + def removing_package? + if @current_resource.version.nil? + false # nothing to remove + elsif @new_resource.version.nil? + true # remove any version of a package + elsif @new_resource.version == @current_resource.version + true # remove the version we have + else + false # we don't have the version we want to remove + end + end + + def expand_options(options) + options ? " #{options}" : '' + end + + # these methods are the required overrides of + # a provider that extends from Chef::Provider::Package + # so refactoring into core Chef should be easy + + def load_current_resource + @current_resource = Chef::Resource::WindowsPackage.new(@new_resource.name) + @current_resource.package_name(@new_resource.package_name) + @current_resource.version(nil) + + unless current_installed_version.nil? + @current_resource.version(current_installed_version) + end + + @current_resource + end + + def current_installed_version + @current_installed_version ||= begin + if installed_packages.include?(@new_resource.package_name) + installed_packages[@new_resource.package_name][:version] + end + end + end + + def candidate_version + @candidate_version ||= begin + @new_resource.version || 'latest' + end + end + + def install_package(_name, _version) + Chef::Log.debug("Processing #{@new_resource} as a #{installer_type} installer.") + install_args = [cached_file(@new_resource.source, @new_resource.checksum), expand_options(unattended_installation_flags), expand_options(@new_resource.options)] + Chef::Log.info('Starting installation...this could take awhile.') + Chef::Log.debug "Install command: #{sprintf(install_command_template, *install_args)}" + shell_out!(sprintf(install_command_template, *install_args), timeout: @new_resource.timeout, returns: @new_resource.success_codes) + end + + def remove_package(_name, _version) + uninstall_string = installed_packages[@new_resource.package_name][:uninstall_string] + Chef::Log.info("Registry provided uninstall string for #{@new_resource} is '#{uninstall_string}'") + uninstall_command = begin + if uninstall_string =~ /msiexec/i + "#{uninstall_string} /qn" + else + uninstall_string.delete!('"') + "start \"\" /wait /d\"#{::File.dirname(uninstall_string)}\" #{::File.basename(uninstall_string)}#{expand_options(@new_resource.options)} /S & exit %%%%ERRORLEVEL%%%%" + end + end + Chef::Log.info("Removing #{@new_resource} with uninstall command '#{uninstall_command}'") + shell_out!(uninstall_command, { returns: @new_resource.success_codes }) + end + + private + + def install_command_template + case installer_type + when :msi + "msiexec%2$s \"%1$s\"%3$s" + else + "start \"\" /wait \"%1$s\"%2$s%3$s & exit %%%%ERRORLEVEL%%%%" + end + end + + # http://unattended.sourceforge.net/installers.php + def unattended_installation_flags + case installer_type + when :msi + # this is no-ui + '/qn /i' + when :installshield + '/s /sms' + when :nsis + '/S /NCRC' + when :inno + # "/sp- /silent /norestart" + '/verysilent /norestart' + when :wise + '/s' + end + end + + def installer_type + @installer_type || begin + if @new_resource.installer_type + @new_resource.installer_type + else + basename = ::File.basename(cached_file(@new_resource.source, @new_resource.checksum)) + if basename.split('.').last.downcase == 'msi' # Microsoft MSI + :msi + else + # search the binary file for installer type + contents = ::Kernel.open(::File.expand_path(cached_file(@new_resource.source)), 'rb', &:read) # TODO: limit data read in + case contents + when /inno/i # Inno Setup + :inno + when /wise/i # Wise InstallMaster + :wise + when /nsis/i # Nullsoft Scriptable Install System + :nsis + else + # if file is named 'setup.exe' assume installshield + if basename == 'setup.exe' + :installshield + else + fail Chef::Exceptions::AttributeNotFound, 'installer_type could not be determined, please set manually' + end + end + end + end + end + end + end + end +end + +class Chef + class Resource + class WindowsCookbookPackage < Chef::Resource::LWRPBase + if Gem::Version.new(Chef::VERSION) >= Gem::Version.new('12.4.0') + provides :windows_package, os: 'windows', override: true + elsif Gem::Version.new(Chef::VERSION) >= Gem::Version.new('12') + provides :windows_package, os: 'windows' + end + actions :install, :remove + + default_action :install + + attribute :package_name, kind_of: String, name_attribute: true + attribute :source, kind_of: String, required: true + attribute :version, kind_of: String + attribute :options, kind_of: String + attribute :installer_type, kind_of: Symbol, default: nil, equal_to: [:msi, :inno, :nsis, :wise, :installshield, :custom] + attribute :checksum, kind_of: String + attribute :timeout, kind_of: Integer, default: 600 + attribute :success_codes, kind_of: Array, default: [0, 42, 127] + + self.resource_name = 'windows_package' + def initialize(*args) + super + @provider = Chef::Provider::WindowsCookbookPackage + end + end + end +end + +if Gem::Version.new(Chef::VERSION) < Gem::Version.new('12') + # this wires up the cookbook version of the windows_package resource as Chef::Resource::WindowsPackage, + # which is kinda hella janky + Chef::Resource.send(:remove_const, :WindowsPackage) if defined? Chef::Resource::WindowsPackage + Chef::Resource.const_set('WindowsPackage', Chef::Resource::WindowsCookbookPackage) +else + if Chef.respond_to?(:set_resource_priority_array) + # this wires up the dynamic resource resolver to favor the cookbook version of windows_package over + # the internal version (but the internal Chef::Resource::WindowsPackage is still the internal version + # and a wrapper cookbook can override this e.g. for users that want to use the windows cookbook but + # want the internal windows_package resource) + Chef.set_resource_priority_array(:windows_package, [Chef::Resource::WindowsCookbookPackage], platform: 'windows') + end +end diff --git a/cookbooks/windows/libraries/windows_privileged.rb b/cookbooks/windows/libraries/windows_privileged.rb index f868835..50b1e4a 100644 --- a/cookbooks/windows/libraries/windows_privileged.rb +++ b/cookbooks/windows/libraries/windows_privileged.rb @@ -1,94 +1,103 @@ -# -# Author:: Doug MacEachern -# Author:: Paul Morton () -# Cookbook Name:: windows -# Library:: windows_privileged -# -# Copyright:: 2010, VMware, Inc. -# Copyright:: 2011, 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 'windows/error' - require 'windows/registry' - require 'windows/process' - require 'windows/security' -end - -#helpers for Windows API calls that require privilege adjustments -class Chef - class WindowsPrivileged - if RUBY_PLATFORM =~ /mswin|mingw32|windows/ - include Windows::Error - include Windows::Registry - include Windows::Process - include Windows::Security - end - #File -> Load Hive... in regedit.exe - def reg_load_key(name, file) - 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) - run(SE_BACKUP_NAME, SE_RESTORE_NAME) do - rc = RegUnLoadKey(HKEY_USERS, name.to_s) - if rc != ERROR_SUCCESS - raise get_last_error(rc) - end - end - end - - def run(*privileges) - token = [0].pack('L') - - unless OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, token) - raise get_last_error - end - token = token.unpack('L')[0] - - 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) - 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 - end -end +# +# Author:: Doug MacEachern +# Author:: Paul Morton () +# Cookbook Name:: windows +# Library:: windows_privileged +# +# Copyright:: 2010, VMware, Inc. +# Copyright:: 2011, 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 + fail 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) + fail 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) + fail get_last_error + end + token = token.unpack('L')[0] + + privileges.each do |name| + unless adjust_privilege(token, name, SE_PRIVILEGE_ENABLED) + fail 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 index e65c41a..171a7d2 100644 --- a/cookbooks/windows/libraries/wmi_helper.rb +++ b/cookbooks/windows/libraries/wmi_helper.rb @@ -1,32 +1,32 @@ -# -# Author:: Adam Edwards () -# -# Copyright:: 2014, 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 +# +# Author:: Adam Edwards () +# +# Copyright:: 2014-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. +# + +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 index 617ddea..5fb7396 100644 --- a/cookbooks/windows/metadata.json +++ b/cookbooks/windows/metadata.json @@ -1,31 +1 @@ -{ - "name": "windows", - "version": "1.36.6", - "description": "Provides a set of useful Windows-specific primitives.", - "long_description": "Windows Cookbook\n================\nProvides a set of Windows-specific primitives (Chef resources) meant to aid in the creation of cookbooks/recipes targeting the Windows platform.\n\n\nRequirements\n-------------\nVersion 1.3.0+ of this cookbook requires Chef 0.10.10+.\n\n\n### Platforms\n* Windows XP\n* Windows Vista\n* Windows Server 2003 R2\n* Windows 7\n* Windows Server 2008 (R1, R2)\n\nThe `windows_task` LWRP requires Windows Server 2008 due to its API usage.\n\n### Cookbooks\nThe following cookbooks provided by Chef Software are required as noted:\n\n* chef_handler (`windows::reboot_handler` leverages the chef_handler LWRP)\n\nAttributes\n----------\n* `node['windows']['allow_pending_reboots']` - used to configure the `WindowsRebootHandler` (via the `windows::reboot_handler` recipe) to act on pending reboots. default is true (ie act on pending reboots). The value of this attribute only has an effect if the `windows::reboot_handler` is in a node's run list.\n* `node['windows']['allow_reboot_on_failure']` - used to register the `WindowsRebootHandler` (via the `windows::reboot_handler` recipe) as an exception handler too to act on reboots not only at the end of successful Chef runs, but even at the end of failed runs. default is false (ie reboot only after successful runs). The value of this attribute only has an effect if the `windows::reboot_handler` is in a node's run list.\n\n\nResource/Provider\n-----------------\n### windows_auto_run\n#### Actions\n- :create: Create an item to be run at login\n- :remove: Remove an item that was previously setup to run at login\n\n#### Attribute Parameters\n- :name: Name attribute. The name of the value to be stored in the registry\n- :program: The program to be run at login\n- :args: The arguments for the program\n\n#### Examples\nRun BGInfo at login\n\n```ruby\nwindows_auto_run 'BGINFO' do\n program 'C:/Sysinternals/bginfo.exe'\n args '\\'C:/Sysinternals/Config.bgi\\' /NOLICPROMPT /TIMER:0'\n not_if { Registry.value_exists?(AUTO_RUN_KEY, 'BGINFO') }\n action :create\nend\n```\n\n### windows_batch\n(Chef 11.6.0 includes a built-in [batch](http://docs.chef.io/resource_batch.html) resource, so use that in preference to `windows_batch` if possible.)\n\nExecute a batch script using the cmd.exe interpreter (much like the script resources for bash, csh, powershell, perl, python and ruby). A temporary file is created and executed like other script resources, rather than run inline. By their nature, Script resources are not idempotent, as they are completely up to the user's imagination. Use the `not_if` or `only_if` meta parameters to guard the resource for idempotence.\n\n#### Actions\n- :run: run the batch file\n\n#### Attribute Parameters\n- command: name attribute. Name of the command to execute.\n- code: quoted string of code to execute.\n- creates: a file this command creates - if the file exists, the command will not be run.\n- cwd: current working directory to run the command from.\n- flags: command line flags to pass to the interpreter when invoking.\n- user: A user name or user ID that we should change to before running this command.\n- group: A group name or group ID that we should change to before running this command.\n\n#### Examples\n```ruby\nwindows_batch 'unzip_and_move_ruby' do\n code <<-EOH\n 7z.exe x #{Chef::Config[:file_cache_path]}/ruby-1.8.7-p352-i386-mingw32.7z -oC:\\\\source -r -y\n xcopy C:\\\\source\\\\ruby-1.8.7-p352-i386-mingw32 C:\\\\ruby /e /y\n EOH\nend\n```\n\n```ruby\nwindows_batch 'echo some env vars' do\n code <<-EOH\n echo %TEMP%\n echo %SYSTEMDRIVE%\n echo %PATH%\n echo %WINDIR%\n EOH\nend\n```\n\n### windows_feature\nWindows Roles and Features can be thought of as built-in operating system packages that ship with the OS. A server role is a set of software programs that, when they are installed and properly configured, lets a computer perform a specific function for multiple users or other computers within a network. A Role can have multiple Role Services that provide functionality to the Role. Role services are software programs that provide the functionality of a role. Features are software programs that, although they are not directly parts of roles, can support or augment the functionality of one or more roles, or improve the functionality of the server, regardless of which roles are installed. Collectively we refer to all of these attributes as 'features'.\n\nThis resource allows you to manage these 'features' in an unattended, idempotent way.\n\nThere are two providers for the `windows_features` which map into Microsoft's two major tools for managing roles/features: [Deployment Image Servicing and Management (DISM)](http://msdn.microsoft.com/en-us/library/dd371719%28v=vs.85%29.aspx) and [Servermanagercmd](http://technet.microsoft.com/en-us/library/ee344834%28WS.10%29.aspx) (The CLI for Server Manager). As Servermanagercmd is deprecated, Chef will set the default provider to `Chef::Provider::WindowsFeature::DISM` if DISM is present on the system being configured. The default provider will fall back to `Chef::Provider::WindowsFeature::ServerManagerCmd`.\n\nFor more information on Roles, Role Services and Features see the [Microsoft TechNet article on the topic](http://technet.microsoft.com/en-us/library/cc754923.aspx). For a complete list of all features that are available on a node type either of the following commands at a command prompt:\n\n```text\ndism /online /Get-Features\nservermanagercmd -query\n```\n\n#### Actions\n- :install: install a Windows role/feature\n- :remove: remove a Windows role/feature\n\n#### Attribute Parameters\n- feature_name: name of the feature/role to install. The same feature may have different names depending on the provider used (ie DHCPServer vs DHCP; DNS-Server-Full-Role vs DNS).\n- all: Boolean. Optional. Default: false. DISM provider only. Forces all dependencies to be installed.\n- source: String. Optional. DISM provider only. Uses local repository for feature install.\n\n#### Providers\n- **Chef::Provider::WindowsFeature::DISM**: Uses Deployment Image Servicing and Management (DISM) to manage roles/features.\n- **Chef::Provider::WindowsFeature::ServerManagerCmd**: Uses Server Manager to manage roles/features.\n- **Chef::Provider::WindowsFeaturePowershell**: Uses Powershell to manage roles/features. (see [COOK-3714](https://tickets.chef.io/browse/COOK-3714)\n\n#### Examples\nEnable the node as a DHCP Server\n\n```ruby\nwindows_feature 'DHCPServer' do\n action :install\nend\n```\n\nEnable TFTP\n\n```ruby\nwindows_feature 'TFTP' do\n action :install\nend\n```\n\nEnable .Net 3.5.1 on Server 2012 using repository files on DVD and\ninstall all dependencies\n\n```ruby\nwindows_feature \"NetFx3\" do\n action :install\n all true\n source \"d:\\sources\\sxs\"\nend\n```\n\nDisable Telnet client/server\n\n```ruby\n%w[TelnetServer TelnetClient].each do |feature|\n windows_feature feature do\n action :remove\n end\nend\n```\n\n### windows_font\nInstalls a font.\n\nFont files should be included in the cookbooks\n\n#### Actions\n- :install: install a font to the system fonts directory.\n\n#### Attribute Parameters\n- file: The name of the font file name to install. It should exist in the files/default directory of the cookbook you're calling windows_font from. Defaults to the resource name.\n\n#### Examples\n\n```ruby\nwindows_font 'Code New Roman.otf'\n```\n\n### windows_package\nManage Windows application packages in an unattended, idempotent way.\n\nThe following application installers are currently supported:\n\n* MSI packages\n* InstallShield\n* Wise InstallMaster\n* Inno Setup\n* Nullsoft Scriptable Install System\n\nIf the proper installer type is not passed into the resource's installer_type attribute, the provider will do it's best to identify the type by introspecting the installation package. If the installation type cannot be properly identified the `:custom` value can be passed into the installer_type attribute along with the proper flags for silent/quiet installation (using the `options` attribute..see example below).\n\n__PLEASE NOTE__ - For proper idempotence the resource's `package_name` should be the same as the 'DisplayName' registry value in the uninstallation data that is created during package installation. The easiest way to definitively find the proper 'DisplayName' value is to install the package on a machine and search for the uninstall information under the following registry keys:\n\n* `HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall`\n* `HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall`\n* `HKEY_LOCAL_MACHINE\\Software\\Wow6464Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall`\n\nFor maximum flexibility the `source` attribute supports both remote and local installation packages.\n\n#### Actions\n- :install: install a package\n- :remove: remove a package. The remove action is completely hit or miss as many application uninstallers do not support a full silent/quiet mode.\n\n#### Attribute Parameters\n- package_name: name attribute. The 'DisplayName' of the application installation package.\n- source: The source of the windows installer. This can either be a URI or a local path.\n- installer_type: They type of windows installation package. valid values are: :msi, :inno, :nsis, :wise, :installshield, :custom. If this value is not provided, the provider will do it's best to identify the installer type through introspection of the file.\n- checksum: useful if source is remote, the SHA-256 checksum of the file--if the local file matches the checksum, Chef will not download it\n- options: Additional options to pass the underlying installation command\n- timeout: set a timeout for the package download (default 600 seconds)\n- version: The version number of this package, as indicated by the 'DisplayVersion' value in one of the 'Uninstall' registry keys. If the given version number does equal the 'DisplayVersion' in the registry, the package will be installed.\n- success_codes: set an array of possible successful installation\n return codes. Previously this was hardcoded, but certain MSIs may\n have a different return code, e.g. 3010 for reboot required. Must be\n an array, and defaults to `[0, 42, 127]`.\n\n#### Examples\n\nInstall PuTTY (InnoSetup installer)\n```ruby\nwindows_package 'PuTTY version 0.60' do\n source 'http://the.earth.li/~sgtatham/putty/latest/x86/putty-0.60-installer.exe'\n installer_type :inno\n action :install\nend\n```\n\nInstall 7-Zip (MSI installer)\n```ruby\nwindows_package '7-Zip 9.20 (x64 edition)' do\n source 'http://downloads.sourceforge.net/sevenzip/7z920-x64.msi'\n action :install\nend\n```\n\nInstall Notepad++ (Y U No Emacs?) using a local installer\n```ruby\nwindows_package 'Notepad++' do\n source 'c:/installation_files/npp.5.9.2.Installer.exe'\n action :install\nend\n```\n\nInstall VLC for that Xvid (NSIS installer)\n```ruby\nwindows_package 'VLC media player 1.1.10' do\n source 'http://superb-sea2.dl.sourceforge.net/project/vlc/1.1.10/win32/vlc-1.1.10-win32.exe'\n action :install\nend\n```\n\nInstall Firefox as custom installer and manually set the silent install flags\n```ruby\nwindows_package 'Mozilla Firefox 5.0 (x86 en-US)' do\n source 'http://archive.mozilla.org/pub/mozilla.org/mozilla.org/firefox/releases/5.0/win32/en-US/Firefox%20Setup%205.0.exe'\n options '-ms'\n installer_type :custom\n action :install\nend\n```\n\nGoogle Chrome FTW (MSI installer)\n```ruby\nwindows_package 'Google Chrome' do\n source 'https://dl-ssl.google.com/tag/s/appguid%3D%7B8A69D345-D564-463C-AFF1-A69D9E530F96%7D%26iid%3D%7B806F36C0-CB54-4A84-A3F3-0CF8A86575E0%7D%26lang%3Den%26browser%3D3%26usagestats%3D0%26appname%3DGoogle%2520Chrome%26needsadmin%3Dfalse/edgedl/chrome/install/GoogleChromeStandaloneEnterprise.msi'\n action :install\nend\n```\n\nRemove Google Chrome\n```ruby\nwindows_package 'Google Chrome' do\n action :remove\nend\n```\n\nRemove 7-Zip\n```ruby\nwindows_package '7-Zip 9.20 (x64 edition)' do\n action :remove\nend\n```\n\n### windows_printer_port\n\nCreate and delete TCP/IPv4 printer ports.\n\n#### Actions\n- :create: Create a TCIP/IPv4 printer port. This is the default action.\n- :delete: Delete a TCIP/IPv4 printer port\n\n#### Attribute Parameters\n- :ipv4_address: Name attribute. Required. IPv4 address, e.g. '10.0.24.34'\n- :port_name: Port name. Optional. Defaults to 'IP_' + :ipv4_address\n- :port_number: Port number. Optional. Defaults to 9100.\n- :port_description: Port description. Optional.\n- :snmp_enabled: Boolean. Optional. Defaults to false.\n- :port_protocol: Port protocol, 1 (RAW), or 2 (LPR). Optional. Defaults to 1.\n\n#### Examples\n\nCreate a TCP/IP printer port named 'IP_10.4.64.37' with all defaults\n```ruby\nwindows_printer_port '10.4.64.37' do\nend\n```\n\nDelete a printer port\n```ruby\nwindows_printer_port '10.4.64.37' do\n action :delete\nend\n```\n\nDelete a port with a custom port_name\n```ruby\nwindows_printer_port '10.4.64.38' do\n port_name 'My awesome port'\n action :delete\nend\n```\n\nCreate a port with more options\n```ruby\nwindows_printer_port '10.4.64.39' do\n port_name 'My awesome port'\n snmp_enabled true\n port_protocol 2\nend\n```\n\n### windows_printer\n\nCreate Windows printer. Note that this doesn't currently install a printer\ndriver. You must already have the driver installed on the system.\n\nThe Windows Printer LWRP will automatically create a TCP/IP printer port for you using the `ipv4_address` property. If you want more granular control over the printer port, just create it using the `windows_printer_port` LWRP before creating the printer.\n\n#### Actions\n- :create: Create a new printer\n- :delete: Delete a new printer\n\n#### Attribute Parameters\n- :device_id: Name attribute. Required. Printer queue name, e.g. 'HP LJ 5200 in fifth floor copy room'\n- :comment: Optional string describing the printer queue.\n- :default: Boolean. Optional. Defaults to false. Note that Windows sets the first printer defined to the default printer regardless of this setting.\n- :driver_name: String. Required. Exact name of printer driver. Note that the printer driver must already be installed on the node.\n- :location: Printer location, e.g. 'Fifth floor copy room', or 'US/NYC/Floor42/Room4207'\n- :shared: Boolean. Defaults to false.\n- :share_name: Printer share name.\n- :ipv4_address: Printer IPv4 address, e.g. '10.4.64.23'. You don't have to be able to ping the IP addresss to set it. Required.\n\nAn error of \"Set-WmiInstance : Generic failure\" is most likely due to the printer driver name not matching or not being installed.\n\n#### Examples\n\nCreate a printer\n```ruby\nwindows_printer 'HP LaserJet 5th Floor' do\n driver_name 'HP LaserJet 4100 Series PCL6'\n ipv4_address '10.4.64.38'\nend\n```\n\nDelete a printer. Note: this doesn't delete the associated printer port. See `windows_printer_port` above for how to delete the port.\n```ruby\nwindows_printer 'HP LaserJet 5th Floor' do\n action :delete\nend\n```\n\n### windows_reboot\nSets required data in the node's run_state to notify `WindowsRebootHandler` a reboot is requested. If Chef run completes successfully a reboot will occur if the `WindowsRebootHandler` is properly registered as a report handler. As an action of `:request` will cause a node to reboot every Chef run, this resource is usually notified by other resources...ie restart node after a package is installed (see example below).\n\n#### Actions\n- :request: requests a reboot at completion of successful Cher run. requires `WindowsRebootHandler` to be registered as a report handler.\n- :cancel: remove reboot request from node.run_state. this will cancel *ALL* previously requested reboots as this is a binary state.\n\n#### Attribute Parameters\n- :timeout: Name attribute. timeout delay in seconds to wait before proceeding with the requested reboot. default is 60 seconds\n- :reason: comment on the reason for the reboot. default is 'Chef Software Chef initiated reboot'\n\n#### Examples\nIf the package installs, schedule a reboot at end of chef run\n```ruby\nwindows_reboot 60 do\n reason 'cause chef said so'\n action :nothing\nend\n\nwindows_package 'some_package' do\n action :install\n notifies :request, 'windows_reboot[60]'\nend\n```\n\nCancel the previously requested reboot\n```ruby\nwindows_reboot 60 do\n action :cancel\nend\n```\n\n### windows_registry\n(Chef 11.6.0 includes a built-in [registry_key](http://docs.chef.io/resource_registry_key.html) resource, so use that in preference to `windows_registry` if possible.)\n\nCreates and modifies Windows registry keys.\n\n*Change in v1.3.0: The Win32 classes use `::Win32` to avoid namespace conflict with `Chef::Win32` (introduced in Chef 0.10.10).*\n\n#### Actions\n- :create: create a new registry key with the provided values.\n- :modify: modify an existing registry key with the provided values.\n- :force_modify: modify an existing registry key with the provided values. ensures the value is actually set by checking multiple times. useful for fighting race conditions where two processes are trying to set the same registry key. This will be updated in the near future to use 'RegNotifyChangeKeyValue' which is exposed by the WinAPI and allows a process to register for notification on a registry key change.\n- :remove: removes a value from an existing registry key\n\n#### Attribute Parameters\n- key_name: name attribute. The registry key to create/modify.\n- values: hash of the values to set under the registry key. The individual hash items will become respective 'Value name' => 'Value data' items in the registry key.\n- type: Type of key to create, defaults to REG_SZ. Must be a symbol, see the overview below for valid values.\n\n#### Registry key types\n- :binary: REG_BINARY\n- :string: REG_SZ\n- :multi_string: REG_MULTI_SZ\n- :expand_string: REG_EXPAND_SZ\n- :dword: REG_DWORD\n- :dword_big_endian: REG_DWORD_BIG_ENDIAN\n- :qword: REG_QWORD\n\n#### Examples\n\nMake the local windows proxy match the one set for Chef\n```ruby\nproxy = URI.parse(Chef::Config[:http_proxy])\nwindows_registry 'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings' do\n values 'ProxyEnable' => 1, 'ProxyServer' => \"#{proxy.host}:#{proxy.port}\", 'ProxyOverride' => ''\nend\n```\n\nEnable Remote Desktop and poke the firewall hole\n```ruby\nwindows_registry 'HKLM\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server' do\n values 'FdenyTSConnections' => 0\nend\n```\n\nDelete an item from the registry\n```ruby\nwindows_registry 'HKCU\\Software\\Test' do\n #Key is the name of the value that you want to delete the value is always empty\n values 'ValueToDelete' => ''\n action :remove\nend\n```\n\nAdd a REG_MULTI_SZ value to the registry\n```ruby\nwindows_registry 'HKCU\\Software\\Test' do\n values 'MultiString' => ['line 1', 'line 2', 'line 3']\n type :multi_string\nend\n```\n\n#### Library Methods\n\n```ruby\nRegistry.value_exists?('HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run','BGINFO')\nRegistry.key_exists?('HKLM\\SOFTWARE\\Microsoft')\nBgInfo = Registry.get_value('HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run','BGINFO')\n```\n\n### windows_path\n#### Actions\n- :add: Add an item to the system path\n- :remove: Remove an item from the system path\n\n#### Attribute Parameters\n- :path: Name attribute. The name of the value to add to the system path\n\n#### Examples\n\nAdd Sysinternals to the system path\n```ruby\nwindows_path 'C:\\Sysinternals' do\n action :add\nend\n```\n\nRemove 7-Zip from the system path\n```ruby\nwindows_path 'C:\\7-Zip' do\n action :remove\nend\n```\n\n### windows_task\nCreates, deletes or runs a Windows scheduled task. Requires Windows\nServer 2008 due to API usage.\n\n#### Actions\n- :create: creates a task\n- :delete: deletes a task\n- :run: runs a task\n- :change: changes the un/pw or command of a task\n- :enable: enable a task\n- :disable: disable a task\n\n#### Attribute Parameters\n- name: name attribute, The task name.\n- command: The command the task will run.\n- cwd: The directory the task will be run from.\n- user: The user to run the task as. (requires password)\n- password: The user's password. (requires user)\n- run_level: Run with limited or highest privileges.\n- frequency: Frequency with which to run the task. (hourly, daily, ect.)\n- frequency_modifier: Multiple for frequency. (15 minutes, 2 days)\n- start_day: Specifies the first date on which the task runs. Optional string (MM/DD/YYYY)\n- start_time: Specifies the start time to run the task. Optional string (HH:mm)\n\n#### Examples\n\nRun Chef every 15 minutes\n```ruby\nwindows_task 'Chef client' do\n user 'Administrator'\n password '$ecR3t'\n cwd 'C:\\chef\\bin'\n command 'chef-client -L C:\\tmp\\'\n run_level :highest\n frequency :minute\n frequency_modifier 15\nend\n```\n\nUpdate Chef Client task with new password and log location\n```ruby\nwindows_task 'Chef client' do\n user 'Administrator'\n password 'N3wPassW0Rd'\n cwd 'C:\\chef\\bin'\n command 'chef-client -L C:\\chef\\logs\\'\n action :change\nend\n```\n\nDelete a taks named 'old task'\n```ruby\nwindows_task 'old task' do\n action :delete\nend\n```\n\nEnable a task named 'Chef client'\n```ruby\nwindows_task 'Chef client' do\n action :enable\nend\n```\n\nDisable a task named 'Chef client'\n```ruby\nwindows_task 'Chef client' do\n action :disable\nend\n```\n\n### windows_zipfile\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- :unzip: unzip a compressed file\n- :zip: zip a directory (recursively)\n\n#### Attribute Parameters\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```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```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```ruby\nwindows_zipfile 'c:/foo/baz/the_codez.zip' do\n source 'c:/the_codez'\n action :zip\nend\n```\n\nLibraries\n-------------------------\n### WindowsHelper\n\nHelper that allows you to use helpful functions in windows\n\n#### installed_packages\nReturns a hash of all DisplayNames installed\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- `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```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```\nDo something if a package is installed\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\nException/Report Handlers\n-------------------------\n### WindowsRebootHandler\nRequired reboots are a necessary evil of configuring and managing Windows nodes. This report handler (ie fires at the end of Chef runs) acts on requested (Chef initiated) or pending (as determined by the OS per configuration action we performed) reboots. The `allow_pending_reboots` initialization argument should be set to false if you do not want the handler to automatically reboot a node if it has been determined a reboot is pending. Reboots can still be requested explicitly via the `windows_reboot` LWRP.\n\n### Initialization Arguments\n- `allow_pending_reboots`: indicator on whether the handler should act on a the Window's 'pending reboot' state. default is true\n- `timeout`: timeout delay in seconds to wait before proceeding with the reboot. default is 60 seconds\n- `reason`: comment on the reason for the reboot. default is 'Chef Software Chef initiated reboot'\n\n\nWindows ChefSpec Matchers\n-------------------------\nThe Windows cookbook includes custom [ChefSpec](https://github.com/sethvargo/chefspec) matchers you can use to test your own cookbooks that consume Windows cookbook LWRPs.\n\n###Example Matcher Usage\n```ruby\nexpect(chef_run).to install_windows_package('Node.js').with(\n source: 'http://nodejs.org/dist/v0.10.26/x64/node-v0.10.26-x64.msi')\n```\n\n###Windows Cookbook Matchers\n* install_windows_package\n* remove_windows_package\n* install_windows_feature\n* remove_windows_feature\n* delete_windows_feature\n* create_windows_task\n* delete_windows_task\n* run_windows_task\n* change_windows_task\n* add_windows_path\n* remove_windows_path\n* run_windows_batch\n* set_windows_pagefile\n* unzip_windows_zipfile_to\n* zip_windows_zipfile_to\n* create_windows_shortcut\n* create_windows_auto_run\n* remove_windows_auto_run\n* create_windows_printer\n* delete_windows_printer\n* create_windows_printer_port\n* delete_windows_printer_port\n* request_windows_reboot\n* cancel_windows_reboot\n* create_windows_shortcut\n\n\nUsage\n-----\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### default\nConvenience recipe that installs supporting gems for many of the resources/providers that ship with this cookbook.\n\n*Change in v1.3.0: Uses chef_gem instead of gem_package to ensure gem installation in Chef 0.10.10.*\n\n### reboot_handler\nLeverages the `chef_handler` LWRP to register the `WindowsRebootHandler` report handler that ships as part of this cookbook. By default this handler is set to automatically act on pending reboots. If you would like to change this behavior override `node['windows']['allow_pending_reboots']` and set the value to false. For example:\n\n```ruby\nname 'base'\ndescription 'base role'\noverride_attributes(\n 'windows' => {\n 'allow_pending_reboots' => false\n }\n)\n```\n\nThis will still allow a reboot to be explicitly requested via the `windows_reboot` LWRP.\n\nBy default, the handler will only be registered as a report handler, meaning that it will only fire at the end of successful Chef runs. If the run fails, pending or requested reboots will be ignored. This can lead to a situation where some package was installed and notified a reboot request via the `windows_reboot` LWRP, and then the run fails for some unrelated reason, and the reboot request gets dropped because the resource that notified the reboot request will already be up-to-date at the next run and will not request a reboot again, and thus the requested reboot will never be performed. To change this behavior and register the handler as an exception handler that fires at the end of failed runs too, override `node['windows']['allow_reboot_on_failure']` and set the value to true.\n\n\nLicense & Authors\n-----------------\n- Author:: Seth Chisamore ()\n- Author:: Doug MacEachern ()\n- Author:: Paul Morton ()\n- Author:: Doug Ireton ()\n\n```text\nCopyright 2011-2013, 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": { - "chef_handler": ">= 0.0.0" - }, - "recommendations": { - }, - "suggestions": { - }, - "conflicting": { - }, - "providing": { - }, - "replacing": { - }, - "attributes": { - }, - "groupings": { - }, - "recipes": { - } -} \ No newline at end of file +{"name":"windows","version":"1.38.4","description":"Provides a set of useful Windows-specific primitives.","long_description":"Windows Cookbook\n================\n[![Build Status](https://travis-ci.org/chef-cookbooks/windows.svg?branch=master)](http://travis-ci.org/chef-cookbooks/windows)\n[![Cookbook Version](https://img.shields.io/cookbook/v/windows.svg)](https://supermarket.chef.io/cookbooks/windows)\n\nProvides a set of Windows-specific primitives (Chef resources) meant to aid in the creation of cookbooks/recipes targeting the Windows platform.\n\n\nRequirements\n------------\n#### Platforms\n* Windows Vista\n* Windows 7\n* Windows Server 2008 (R1, R2)\n* Windows 8, 8.1\n* Windows Server 2012 (R1, R2)\n\n#### Chef\n- Chef 11+\n\n#### Cookbooks\n* chef_handler (`windows::reboot_handler` leverages the chef_handler LWRP)\n\n\nAttributes\n----------\n* `node['windows']['allow_pending_reboots']` - used to configure the `WindowsRebootHandler` (via the `windows::reboot_handler` recipe) to act on pending reboots. default is true (ie act on pending reboots). The value of this attribute only has an effect if the `windows::reboot_handler` is in a node's run list.\n* `node['windows']['allow_reboot_on_failure']` - used to register the `WindowsRebootHandler` (via the `windows::reboot_handler` recipe) as an exception handler too to act on reboots not only at the end of successful Chef runs, but even at the end of failed runs. default is false (ie reboot only after successful runs). The value of this attribute only has an effect if the `windows::reboot_handler` is in a node's run list.\n\n\nResource/Provider\n-----------------\n### windows_auto_run\n#### Actions\n- `:create` - Create an item to be run at login\n- `:remove` - Remove an item that was previously setup to run at login\n\n#### Attribute Parameters\n- `name` - Name attribute. The name of the value to be stored in the registry\n- `program` - The program to be run at login\n- `args` - The arguments for the program\n\n#### Examples\nRun BGInfo at login\n\n```ruby\nwindows_auto_run 'BGINFO' do\n program 'C:/Sysinternals/bginfo.exe'\n args '\\'C:/Sysinternals/Config.bgi\\' /NOLICPROMPT /TIMER:0'\n not_if { Registry.value_exists?(AUTO_RUN_KEY, 'BGINFO') }\n action :create\nend\n```\n\n### windows_batch\nThis resource is now deprecated and will be removed in a future version of this cookbook. Chef >= 11.6.0 includes a built-in [batch](http://docs.chef.io/resource_batch.html) resource.\n\nExecute a batch script using the cmd.exe interpreter (much like the script resources for bash, csh, powershell, perl, python and ruby). A temporary file is created and executed like other script resources, rather than run inline. By their nature, Script resources are not idempotent, as they are completely up to the user's imagination. Use the `not_if` or `only_if` meta parameters to guard the resource for idempotence.\n\n#### Actions\n- `:run` - run the batch file\n\n#### Attribute Parameters\n- `command` - name attribute. Name of the command to execute.\n- `code` - quoted string of code to execute.\n- `creates` - a file this command creates - if the file exists, the command will not be run.\n- `cwd` - current working directory to run the command from.\n- `flags` - command line flags to pass to the interpreter when invoking.\n- `user` - A user name or user ID that we should change to before running this command.\n- `group` - A group name or group ID that we should change to before running this command.\n\n#### Examples\n```ruby\nwindows_batch 'unzip_and_move_ruby' do\n code <<-EOH\n 7z.exe x #{Chef::Config[:file_cache_path]}/ruby-1.8.7-p352-i386-mingw32.7z -oC:\\\\source -r -y\n xcopy C:\\\\source\\\\ruby-1.8.7-p352-i386-mingw32 C:\\\\ruby /e /y\n EOH\nend\n```\n\n```ruby\nwindows_batch 'echo some env vars' do\n code <<-EOH\n echo %TEMP%\n echo %SYSTEMDRIVE%\n echo %PATH%\n echo %WINDIR%\n EOH\nend\n```\n\n### windows_certificate\n\nInstalls a certificate into the Windows certificate store from a file, and grants read-only access to the private key for designated accounts.\nDue 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- `: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\n#### Attribute Parameters\n- `source` - name attribute. The source file (for create and acl_add), thumprint (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 maniplate. One of MY (default : personal store), CA (trusted intermediate store) or ROOT (trusted root store).\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```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\tpfx_password\t\"password\"\n\tprivate_key_acl\t[\"acme\\fred\", \"pc\\jane\"]\nend\n```\n\n```ruby\n# Add cert to trusted intermediate store\nwindows_certificate \"c:/test/mycert.cer\" do\n\tstore_name\t\"CA\"\nend\n```\n\n```ruby\n# Remove all certicates matching the subject\nwindows_certificate \"me.acme.com\" do\n\taction :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- `:create` - creates or updates a binding.\n- `:delete` - deletes a binding.\n\n#### Attribute Parameters\n- `cert_name` - name attribute. The thumprint(hash) or subject that identifies the certicate 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).\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 MY (default : personal store), CA (trusted intermediate store) or ROOT (trusted root store).\n\n#### Examples\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\tcert_name\t\"d234567890a23f567c901e345bc8901d34567890\"\n\tname_kind\t:hash\n\tstore_name\t\"CA\"\n\tport\t\t4334\nend\n```\n\n### windows_feature\nWindows Roles and Features can be thought of as built-in operating system packages that ship with the OS. A server role is a set of software programs that, when they are installed and properly configured, lets a computer perform a specific function for multiple users or other computers within a network. A Role can have multiple Role Services that provide functionality to the Role. Role services are software programs that provide the functionality of a role. Features are software programs that, although they are not directly parts of roles, can support or augment the functionality of one or more roles, or improve the functionality of the server, regardless of which roles are installed. Collectively we refer to all of these attributes as 'features'.\n\nThis resource allows you to manage these 'features' in an unattended, idempotent way.\n\nThere are two providers for the `windows_features` which map into Microsoft's two major tools for managing roles/features: [Deployment Image Servicing and Management (DISM)](http://msdn.microsoft.com/en-us/library/dd371719%28v=vs.85%29.aspx) and [Servermanagercmd](http://technet.microsoft.com/en-us/library/ee344834%28WS.10%29.aspx) (The CLI for Server Manager). As Servermanagercmd is deprecated, Chef will set the default provider to `Chef::Provider::WindowsFeature::DISM` if DISM is present on the system being configured. The default provider will fall back to `Chef::Provider::WindowsFeature::ServerManagerCmd`.\n\nFor more information on Roles, Role Services and Features see the [Microsoft TechNet article on the topic](http://technet.microsoft.com/en-us/library/cc754923.aspx). For a complete list of all features that are available on a node type either of the following commands at a command prompt:\n\n```text\ndism /online /Get-Features\nservermanagercmd -query\n```\n\n#### Actions\n- `:install` - install a Windows role/feature\n- `:remove` - remove a Windows role/feature\n\n#### Attribute Parameters\n- `feature_name` - name of the feature/role to install. The same feature may have different names depending on the provider used (ie DHCPServer vs DHCP; DNS-Server-Full-Role vs DNS).\n- `all` - Boolean. Optional. Default: false. DISM provider only. Forces all dependencies to be installed.\n- `source` - String. Optional. DISM provider only. Uses local repository for feature install.\n\n#### Providers\n- **Chef::Provider::WindowsFeature::DISM**: Uses Deployment Image Servicing and Management (DISM) to manage roles/features.\n- **Chef::Provider::WindowsFeature::ServerManagerCmd**: Uses Server Manager to manage roles/features.\n- **Chef::Provider::WindowsFeaturePowershell**: Uses Powershell to manage roles/features. (see [COOK-3714](https://tickets.chef.io/browse/COOK-3714)\n\n#### Examples\nEnable the node as a DHCP Server\n\n```ruby\nwindows_feature 'DHCPServer' do\n action :install\nend\n```\n\nEnable TFTP\n\n```ruby\nwindows_feature 'TFTP' do\n action :install\nend\n```\n\nEnable .Net 3.5.1 on Server 2012 using repository files on DVD and\ninstall all dependencies\n\n```ruby\nwindows_feature \"NetFx3\" do\n action :install\n all true\n source \"d:\\sources\\sxs\"\nend\n```\n\nDisable Telnet client/server\n\n```ruby\n%w[TelnetServer TelnetClient].each do |feature|\n windows_feature feature do\n action :remove\n end\nend\n```\n\nAdd SMTP Feature with powershell provider\n\n```ruby\nwindows_feature \"smtp-server\" do\n action :install\n all true\n provider :windows_feature_powershell\nend\n```\n\n### windows_font\nInstalls a font.\n\nFont files should be included in the cookbooks\n\n#### Actions\n- `:install` - install a font to the system fonts directory.\n\n#### Attribute Parameters\n- `file` - The name of the font file name to install. It should exist in the files/default directory of the cookbook you're calling windows_font from. Defaults to the resource name.\n\n#### Examples\n\n```ruby\nwindows_font 'Code New Roman.otf'\n```\n\n### windows_http_acl\nSets the Access Control List for an http URL to grant non-admin accounts permission to open HTTP endpoints.\n\n#### Actions\n- `:create` - creates or updates the ACL for a URL.\n- `:delete` - deletes the ACL from a URL.\n\n#### Attribute Parameters\n- `url` - the name of the url to be created/deleted.\n- `user` - the name (domain\\user) of the user or group to be granted permission to the URL. Mandatory for create. Only one user or group can be granted permission so this replaces any previously defined entry.\n\n#### Examples\n\n```ruby\nwindows_http_acl 'http://+:50051/' do\n\tuser 'pc\\\\fred'\nend\n```\n\n```ruby\nwindows_http_acl 'http://+:50051/' do\n\taction :delete\nend\n```\n\n### windows_package\nManage Windows application packages in an unattended, idempotent way.\n\nThe following application installers are currently supported:\n\n* MSI packages\n* InstallShield\n* Wise InstallMaster\n* Inno Setup\n* Nullsoft Scriptable Install System\n\nIf the proper installer type is not passed into the resource's installer_type attribute, the provider will do it's best to identify the type by introspecting the installation package. If the installation type cannot be properly identified the `:custom` value can be passed into the installer_type attribute along with the proper flags for silent/quiet installation (using the `options` attribute..see example below).\n\n__PLEASE NOTE__ - For proper idempotence the resource's `package_name` should be the same as the 'DisplayName' registry value in the uninstallation data that is created during package installation. The easiest way to definitively find the proper 'DisplayName' value is to install the package on a machine and search for the uninstall information under the following registry keys:\n\n* `HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall`\n* `HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall`\n* `HKEY_LOCAL_MACHINE\\Software\\Wow6464Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall`\n\nFor maximum flexibility the `source` attribute supports both remote and local installation packages.\n\n#### Actions\n- `:install` - install a package\n- `:remove` - remove a package. The remove action is completely hit or miss as many application uninstallers do not support a full silent/quiet mode.\n\n#### Attribute Parameters\n- `package_name` - name attribute. The 'DisplayName' of the application installation package.\n- `source` - The source of the windows installer. This can either be a URI or a local path.\n- `installer_type` - They type of windows installation package. Valid values include :msi, :inno, :nsis, :wise, :installshield, :custom. If this value is not provided, the provider will do it's best to identify the installer type through introspection of the file.\n- `checksum` - useful if source is remote, the SHA-256 checksum of the file--if the local file matches the checksum, Chef will not download it\n- `options` - Additional options to pass the underlying installation command\n- `timeout` - set a timeout for the package download (default 600 seconds)\n- `version` - The version number of this package, as indicated by the 'DisplayVersion' value in one of the 'Uninstall' registry keys. If the given version number does equal the 'DisplayVersion' in the registry, the package will be installed.\n- `success_codes` - set an array of possible successful installation\n return codes. Previously this was hardcoded, but certain MSIs may\n have a different return code, e.g. 3010 for reboot required. Must be\n an array, and defaults to `[0, 42, 127]`.\n\n#### Examples\n\nInstall PuTTY (InnoSetup installer)\n```ruby\nwindows_package 'PuTTY version 0.60' do\n source 'http://the.earth.li/~sgtatham/putty/latest/x86/putty-0.60-installer.exe'\n installer_type :inno\n action :install\nend\n```\n\nInstall 7-Zip (MSI installer)\n```ruby\nwindows_package '7-Zip 9.20 (x64 edition)' do\n source 'http://downloads.sourceforge.net/sevenzip/7z920-x64.msi'\n action :install\nend\n```\n\nInstall Notepad++ (Y U No Emacs?) using a local installer\n```ruby\nwindows_package 'Notepad++' do\n source 'c:/installation_files/npp.5.9.2.Installer.exe'\n action :install\nend\n```\n\nInstall VLC for that Xvid (NSIS installer)\n```ruby\nwindows_package 'VLC media player 1.1.10' do\n source 'http://superb-sea2.dl.sourceforge.net/project/vlc/1.1.10/win32/vlc-1.1.10-win32.exe'\n action :install\nend\n```\n\nInstall Firefox as custom installer and manually set the silent install flags\n```ruby\nwindows_package 'Mozilla Firefox 5.0 (x86 en-US)' do\n source 'http://archive.mozilla.org/pub/mozilla.org/mozilla.org/firefox/releases/5.0/win32/en-US/Firefox%20Setup%205.0.exe'\n options '-ms'\n installer_type :custom\n action :install\nend\n```\n\nGoogle Chrome FTW (MSI installer)\n```ruby\nwindows_package 'Google Chrome' do\n source 'https://dl-ssl.google.com/tag/s/appguid%3D%7B8A69D345-D564-463C-AFF1-A69D9E530F96%7D%26iid%3D%7B806F36C0-CB54-4A84-A3F3-0CF8A86575E0%7D%26lang%3Den%26browser%3D3%26usagestats%3D0%26appname%3DGoogle%2520Chrome%26needsadmin%3Dfalse/edgedl/chrome/install/GoogleChromeStandaloneEnterprise.msi'\n action :install\nend\n```\n\nRemove Google Chrome\n```ruby\nwindows_package 'Google Chrome' do\n action :remove\nend\n```\n\nRemove 7-Zip\n```ruby\nwindows_package '7-Zip 9.20 (x64 edition)' do\n action :remove\nend\n```\n\n### windows_printer_port\n\nCreate and delete TCP/IPv4 printer ports.\n\n#### Actions\n- `:create` - Create a TCIP/IPv4 printer port. This is the default action.\n- `:delete` - Delete a TCIP/IPv4 printer port\n\n#### Attribute Parameters\n- `ipv4_address` - Name attribute. Required. IPv4 address, e.g. '10.0.24.34'\n- `port_name` - Port name. Optional. Defaults to 'IP_' + `ipv4_address`\n- `port_number` - Port number. Optional. Defaults to 9100.\n- `port_description` - Port description. Optional.\n- `snmp_enabled` - Boolean. Optional. Defaults to false.\n- `port_protocol` - Port protocol, 1 (RAW), or 2 (LPR). Optional. Defaults to 1.\n\n#### Examples\n\nCreate a TCP/IP printer port named 'IP_10.4.64.37' with all defaults\n```ruby\nwindows_printer_port '10.4.64.37' do\n action :create\nend\n```\n\nDelete a printer port\n```ruby\nwindows_printer_port '10.4.64.37' do\n action :delete\nend\n```\n\nDelete a port with a custom port_name\n```ruby\nwindows_printer_port '10.4.64.38' do\n port_name 'My awesome port'\n action :delete\nend\n```\n\nCreate a port with more options\n```ruby\nwindows_printer_port '10.4.64.39' do\n port_name 'My awesome port'\n snmp_enabled true\n port_protocol 2\nend\n```\n\n### windows_printer\n\nCreate Windows printer. Note that this doesn't currently install a printer\ndriver. You must already have the driver installed on the system.\n\nThe Windows Printer LWRP will automatically create a TCP/IP printer port for you using the `ipv4_address` property. If you want more granular control over the printer port, just create it using the `windows_printer_port` LWRP before creating the printer.\n\n#### Actions\n- `:create` - Create a new printer\n- `:delete` - Delete a new printer\n\n#### Attribute Parameters\n- `device_id` - Name attribute. Required. Printer queue name, e.g. 'HP LJ 5200 in fifth floor copy room'\n- `comment` - Optional string describing the printer queue.\n- `default` - Boolean. Optional. Defaults to false. Note that Windows sets the first printer defined to the default printer regardless of this setting.\n- `driver_name` - String. Required. Exact name of printer driver. Note that the printer driver must already be installed on the node.\n- `location` - Printer location, e.g. 'Fifth floor copy room', or 'US/NYC/Floor42/Room4207'\n- `shared` - Boolean. Defaults to false.\n- `share_name` - Printer share name.\n- `ipv4_address` - Printer IPv4 address, e.g. '10.4.64.23'. You don't have to be able to ping the IP addresss to set it. Required.\n\nAn error of \"Set-WmiInstance : Generic failure\" is most likely due to the printer driver name not matching or not being installed.\n\n#### Examples\n\nCreate a printer\n```ruby\nwindows_printer 'HP LaserJet 5th Floor' do\n driver_name 'HP LaserJet 4100 Series PCL6'\n ipv4_address '10.4.64.38'\nend\n```\n\nDelete a printer. Note: this doesn't delete the associated printer port. See `windows_printer_port` above for how to delete the port.\n```ruby\nwindows_printer 'HP LaserJet 5th Floor' do\n action :delete\nend\n```\n\n### windows_reboot\nThis resource is now deprecated and will be removed in a future version of this cookbook. Chef >= 12.0.0 includes a built-in [reboot](http://docs.chef.io/resource_reboot.html) resource.\n\nSets required data in the node's run_state to notify `WindowsRebootHandler` a reboot is requested. If Chef run completes successfully a reboot will occur if the `WindowsRebootHandler` is properly registered as a report handler. As an action of `:request` will cause a node to reboot every Chef run, this resource is usually notified by other resources...ie restart node after a package is installed (see example below).\n\n#### Actions\n- `:request` - requests a reboot at completion of successful Cher run. requires `WindowsRebootHandler` to be registered as a report handler.\n- `:cancel` - remove reboot request from node.run_state. this will cancel *ALL* previously requested reboots as this is a binary state.\n\n#### Attribute Parameters\n- `timeout` - Name attribute. timeout delay in seconds to wait before proceeding with the requested reboot. default is 60 seconds\n- `reason` - comment on the reason for the reboot. default is 'Chef Software Chef initiated reboot'\n\n#### Examples\nIf the package installs, schedule a reboot at end of chef run\n```ruby\nwindows_reboot 60 do\n reason 'cause chef said so'\n action :nothing\nend\n\nwindows_package 'some_package' do\n action :install\n notifies :request, 'windows_reboot[60]'\nend\n```\n\nCancel the previously requested reboot\n```ruby\nwindows_reboot 60 do\n action :cancel\nend\n```\n\n### windows_registry\nThis resource is now deprecated and will be removed in a future version of this cookbook. Chef >= 11.6.0 includes a built-in [registry_key](http://docs.chef.io/resource_registry_key.html) resource.\n\nCreates and modifies Windows registry keys.\n\n*Change in v1.3.0: The Win32 classes use `::Win32` to avoid namespace conflict with `Chef::Win32` (introduced in Chef 0.10.10).*\n\n#### Actions\n- `:create` - create a new registry key with the provided values.\n- `:modify` - modify an existing registry key with the provided values.\n- `:force_modify` - modify an existing registry key with the provided values. ensures the value is actually set by checking multiple times. useful for fighting race conditions where two processes are trying to set the same registry key. This will be updated in the near future to use 'RegNotifyChangeKeyValue' which is exposed by the WinAPI and allows a process to register for notification on a registry key change.\n- `:remove` - removes a value from an existing registry key\n\n#### Attribute Parameters\n- `key_name` - name attribute. The registry key to create/modify.\n- `values` - hash of the values to set under the registry key. The individual hash items will become respective 'Value name' => 'Value data' items in the registry key.\n- `type` - Type of key to create, defaults to REG_SZ. Must be a symbol, see the overview below for valid values.\n\n#### Registry key types\n- `:binary` - REG_BINARY\n- `:string` - REG_SZ\n- `:multi_string` - REG_MULTI_SZ\n- `:expand_string` - REG_EXPAND_SZ\n- `:dword` - REG_DWORD\n- `:dword_big_endian` - REG_DWORD_BIG_ENDIAN\n- `:qword` - REG_QWORD\n\n#### Examples\n\nMake the local windows proxy match the one set for Chef\n```ruby\nproxy = URI.parse(Chef::Config[:http_proxy])\nwindows_registry 'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings' do\n values 'ProxyEnable' => 1, 'ProxyServer' => \"#{proxy.host}:#{proxy.port}\", 'ProxyOverride' => ''\nend\n```\n\nEnable Remote Desktop and poke the firewall hole\n```ruby\nwindows_registry 'HKLM\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server' do\n values 'FdenyTSConnections' => 0\nend\n```\n\nDelete an item from the registry\n```ruby\nwindows_registry 'HKCU\\Software\\Test' do\n #Key is the name of the value that you want to delete the value is always empty\n values 'ValueToDelete' => ''\n action :remove\nend\n```\n\nAdd a REG_MULTI_SZ value to the registry\n```ruby\nwindows_registry 'HKCU\\Software\\Test' do\n values 'MultiString' => ['line 1', 'line 2', 'line 3']\n type :multi_string\nend\n```\n\n### windows_shortcut\nCreates and modifies Windows shortcuts.\n\n#### Actions\n- `:create` - create or modify a windows shortcut\n\n#### Attribute Parameters\n- `name` - name attribute. The shortcut to create/modify.\n- `target` - what the shortcut links to\n- `arguments` - arguments to pass to the target when the shortcut is executed\n- `description` - description of the shortcut\n- `cwd` - Working directory to use when the target is executed\n- `iconlocation` - Icon to use, in the format of ```\"path, index\"``` where index is which icon in that file to use (See [WshShortcut.IconLocation](https://msdn.microsoft.com/en-us/library/3s9bx7at.aspx))\n\n#### Examples\n\nAdd a shortcut all users desktop:\n```ruby\nrequire 'win32ole'\nall_users_desktop = WIN32OLE.new(\"WScript.Shell\").SpecialFolders(\"AllUsersDesktop\")\n\nwindows_shortcut \"#{all_users_desktop}/Notepad.lnk\" do\n target \"C:\\\\WINDOWS\\\\notepad.exe\"\n description \"Launch Notepad\"\n iconlocation \"C:\\\\windows\\\\notepad.exe, 0\"\nend\n```\n\n#### Library Methods\n\n```ruby\nRegistry.value_exists?('HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run','BGINFO')\nRegistry.key_exists?('HKLM\\SOFTWARE\\Microsoft')\nBgInfo = Registry.get_value('HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run','BGINFO')\n```\n\n### windows_path\n#### Actions\n- `:add` - Add an item to the system path\n- `:remove` - Remove an item from the system path\n\n#### Attribute Parameters\n- `path` - Name attribute. The name of the value to add to the system path\n\n#### Examples\n\nAdd Sysinternals to the system path\n```ruby\nwindows_path 'C:\\Sysinternals' do\n action :add\nend\n```\n\nRemove 7-Zip from the system path\n```ruby\nwindows_path 'C:\\7-Zip' do\n action :remove\nend\n```\n\n### windows_task\nCreates, deletes or runs a Windows scheduled task. Requires Windows\nServer 2008 due to API usage.\n\n#### Actions\n- `:create` - creates a task (or updates existing if user or command has changed)\n- `:delete` - deletes a task\n- `:run` - runs a task\n- `:end` - ends a task\n- `:change` - changes the un/pw or command of a task\n- `:enable` - enable a task\n- `:disable` - disable a task\n\n#### Attribute Parameters\n- `task_name` - name attribute, The task name. (\"Task Name\" or \"/Task Name\")\n- `force` - When used with create, will update the task.\n- `command` - The command the task will run.\n- `cwd` - The directory the task will be run from.\n- `user` - The user to run the task as. (defaults to 'SYSTEM')\n- `password` - The user's password. (requires user)\n- `run_level` - Run with `:limited` or `:highest` privileges.\n- `frequency` - Frequency with which to run the task. (default is :hourly. Other valid values include :minute, :hourly, :daily, :weekly, :monthly, :once, :on_logon, :onstart, :on_idle) \\*:once requires start_time\n- `frequency_modifier` - Multiple for frequency. (15 minutes, 2 days)\n- `start_day` - Specifies the first date on which the task runs. Optional string (MM/DD/YYYY)\n- `start_time` - Specifies the start time to run the task. Optional string (HH:mm)\n- `interactive_enabled` - (Allow task to run interactively or non-interactively. Requires user and password.)\n- `day` - For monthly or weekly tasks, the day(s) on which the task runs. (MON - SUN, *, 1 - 31)\n\n#### Examples\n\nCreate a `chef-client` task with TaskPath `\\` running every 15 minutes\n```ruby\nwindows_task 'chef-client' do\n user 'Administrator'\n password '$ecR3t'\n cwd 'C:\\\\chef\\\\bin'\n command 'chef-client -L C:\\\\tmp\\\\'\n run_level :highest\n frequency :minute\n frequency_modifier 15\nend\n```\n\nUpdate `chef-client` task with new password and log location\n```ruby\nwindows_task 'chef-client' do\n user 'Administrator'\n password 'N3wPassW0Rd'\n cwd 'C:\\\\chef\\\\bin'\n command 'chef-client -L C:\\\\chef\\\\logs\\\\'\n action :change\nend\n```\n\nDelete a taks named `old task`\n```ruby\nwindows_task 'old task' do\n action :delete\nend\n```\n\nEnable a task named `chef-client`\n```ruby\nwindows_task 'chef-client' do\n action :enable\nend\n```\n\nDisable a task named `ProgramDataUpdater` with TaskPath `\\Microsoft\\Windows\\Application Experience\\`\n```ruby\nwindows_task '\\Microsoft\\Windows\\Application Experience\\ProgramDataUpdater' do\n action :disable\nend\n```\n\n### windows_zipfile\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- `:unzip` - unzip a compressed file\n- `:zip` - zip a directory (recursively)\n\n#### Attribute Parameters\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```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```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```ruby\nwindows_zipfile 'c:/foo/baz/the_codez.zip' do\n source 'c:/the_codez'\n action :zip\nend\n```\n\nLibraries\n-------------------------\n### WindowsHelper\n\nHelper that allows you to use helpful functions in windows\n\n#### installed_packages\nReturns a hash of all DisplayNames installed\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- `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```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```\nDo something if a package is installed\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\nException/Report Handlers\n-------------------------\n### WindowsRebootHandler\nRequired reboots are a necessary evil of configuring and managing Windows nodes. This report handler (ie fires at the end of Chef runs) acts on requested (Chef initiated) or pending (as determined by the OS per configuration action we performed) reboots. The `allow_pending_reboots` initialization argument should be set to false if you do not want the handler to automatically reboot a node if it has been determined a reboot is pending. Reboots can still be requested explicitly via the `windows_reboot` LWRP.\n\n### Initialization Arguments\n- `allow_pending_reboots` - indicator on whether the handler should act on a the Window's 'pending reboot' state. default is true\n- `timeout` - timeout delay in seconds to wait before proceeding with the reboot. default is 60 seconds\n- `reason` - comment on the reason for the reboot. default is 'Chef Software Chef initiated reboot'\n\n\nWindows ChefSpec Matchers\n-------------------------\nThe Windows cookbook includes custom [ChefSpec](https://github.com/sethvargo/chefspec) matchers you can use to test your own cookbooks that consume Windows cookbook LWRPs.\n\n###Example Matcher Usage\n```ruby\nexpect(chef_run).to install_windows_package('Node.js').with(\n source: 'http://nodejs.org/dist/v0.10.26/x64/node-v0.10.26-x64.msi')\n```\n\n###Windows Cookbook Matchers\n* install_windows_package\n* remove_windows_package\n* install_windows_feature\n* remove_windows_feature\n* delete_windows_feature\n* create_windows_task\n* delete_windows_task\n* run_windows_task\n* change_windows_task\n* add_windows_path\n* remove_windows_path\n* run_windows_batch\n* set_windows_pagefile\n* unzip_windows_zipfile_to\n* zip_windows_zipfile_to\n* create_windows_shortcut\n* create_windows_auto_run\n* remove_windows_auto_run\n* create_windows_printer\n* delete_windows_printer\n* create_windows_printer_port\n* delete_windows_printer_port\n* request_windows_reboot\n* cancel_windows_reboot\n* create_windows_shortcut\n\n\nUsage\n-----\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### default\nConvenience recipe that installs supporting gems for many of the resources/providers that ship with this cookbook.\n\n### reboot_handler\nLeverages the `chef_handler` LWRP to register the `WindowsRebootHandler` report handler that ships as part of this cookbook. By default this handler is set to automatically act on pending reboots. If you would like to change this behavior override `node['windows']['allow_pending_reboots']` and set the value to false. For example:\n\n```ruby\nname 'base'\ndescription 'base role'\noverride_attributes(\n 'windows' => {\n 'allow_pending_reboots' => false\n }\n)\n```\n\nThis will still allow a reboot to be explicitly requested via the `windows_reboot` LWRP.\n\nBy default, the handler will only be registered as a report handler, meaning that it will only fire at the end of successful Chef runs. If the run fails, pending or requested reboots will be ignored. This can lead to a situation where some package was installed and notified a reboot request via the `windows_reboot` LWRP, and then the run fails for some unrelated reason, and the reboot request gets dropped because the resource that notified the reboot request will already be up-to-date at the next run and will not request a reboot again, and thus the requested reboot will never be performed. To change this behavior and register the handler as an exception handler that fires at the end of failed runs too, override `node['windows']['allow_reboot_on_failure']` and set the value to true.\n\n\nLicense & Authors\n-----------------\n- Author:: Seth Chisamore ()\n- Author:: Doug MacEachern ()\n- Author:: Paul Morton ()\n- Author:: Doug Ireton ()\n\n```text\nCopyright 2011-2015, 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":{"chef_handler":">= 0.0.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file diff --git a/cookbooks/windows/providers/auto_run.rb b/cookbooks/windows/providers/auto_run.rb index e9c9cad..fad5e02 100644 --- a/cookbooks/windows/providers/auto_run.rb +++ b/cookbooks/windows/providers/auto_run.rb @@ -1,33 +1,33 @@ -# -# Author:: Paul Morton () -# Cookbook Name:: windows -# Provider:: auto_run -# -# Copyright:: 2011, 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. -# -use_inline_resources if defined?(use_inline_resources) - -action :create do - windows_registry 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run' do - values new_resource.name => "\"#{new_resource.program}\" #{new_resource.args}" - end -end - -action :remove do - windows_registry 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run' do - values new_resource.name => '' - action :remove - end -end +# +# Author:: Paul Morton () +# Cookbook Name:: windows +# Provider:: auto_run +# +# Copyright:: 2011, 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. +# +use_inline_resources if defined?(use_inline_resources) + +action :create do + windows_registry 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run' do + values new_resource.name => "\"#{new_resource.program}\" #{new_resource.args}" + end +end + +action :remove do + windows_registry 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run' do + values new_resource.name => '' + action :remove + end +end diff --git a/cookbooks/windows/providers/batch.rb b/cookbooks/windows/providers/batch.rb index 47e5b60..6e5ffef 100644 --- a/cookbooks/windows/providers/batch.rb +++ b/cookbooks/windows/providers/batch.rb @@ -1,63 +1,64 @@ -# -# Author:: Seth Chisamore () -# Cookbook Name:: windws -# Provider:: batch -# -# Copyright:: 2011, 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. -# -use_inline_resources if defined?(use_inline_resources) - -require 'tempfile' -require 'chef/resource/execute' - -action :run do - begin - script_file.puts(@new_resource.code) - script_file.close - set_owner_and_group - - # cwd hax...shell_out on windows needs to support proper 'cwd' - # follow CHEF-2357 for more - cwd = @new_resource.cwd ? "cd \"#{@new_resource.cwd}\" & " : "" - - r = Chef::Resource::Execute.new(@new_resource.name, run_context) - r.user(@new_resource.user) - r.group(@new_resource.group) - r.command("#{cwd}call \"#{script_file.path}\" #{@new_resource.flags}") - r.creates(@new_resource.creates) - r.returns(@new_resource.returns) - r.run_action(:run) - - @new_resource.updated_by_last_action(r.updated_by_last_action?) - ensure - unlink_script_file - end -end - -private -def set_owner_and_group - # FileUtils itself implements a no-op if +user+ or +group+ are nil - # You can prove this by running FileUtils.chown(nil,nil,'/tmp/file') - # as an unprivileged user. - FileUtils.chown(@new_resource.user, @new_resource.group, script_file.path) -end - -def script_file - @script_file ||= Tempfile.open(['chef-script', '.bat']) -end - -def unlink_script_file - @script_file && @script_file.close! -end +# +# Author:: Seth Chisamore () +# Cookbook Name:: windws +# Provider:: batch +# +# 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. +# +use_inline_resources if defined?(use_inline_resources) + +require 'tempfile' +require 'chef/resource/execute' + +action :run do + begin + script_file.puts(@new_resource.code) + script_file.close + set_owner_and_group + + # cwd hax...shell_out on windows needs to support proper 'cwd' + # follow CHEF-2357 for more + cwd = @new_resource.cwd ? "cd \"#{@new_resource.cwd}\" & " : '' + + r = Chef::Resource::Execute.new(@new_resource.name, run_context) + r.user(@new_resource.user) + r.group(@new_resource.group) + r.command("#{cwd}call \"#{script_file.path}\" #{@new_resource.flags}") + r.creates(@new_resource.creates) + r.returns(@new_resource.returns) + r.run_action(:run) + + @new_resource.updated_by_last_action(r.updated_by_last_action?) + ensure + unlink_script_file + end +end + +private + +def set_owner_and_group + # FileUtils itself implements a no-op if +user+ or +group+ are nil + # You can prove this by running FileUtils.chown(nil,nil,'/tmp/file') + # as an unprivileged user. + FileUtils.chown(@new_resource.user, @new_resource.group, script_file.path) +end + +def script_file + @script_file ||= Tempfile.open(['chef-script', '.bat']) +end + +def unlink_script_file + @script_file && @script_file.close! +end diff --git a/cookbooks/windows/providers/certificate.rb b/cookbooks/windows/providers/certificate.rb new file mode 100644 index 0000000..5730b56 --- /dev/null +++ b/cookbooks/windows/providers/certificate.rb @@ -0,0 +1,178 @@ +# +# Author:: Richard Lavey (richard.lavey@calastone.com) +# Cookbook Name:: windows +# Provider:: certificate +# +# 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 certutil +# https://technet.microsoft.com/en-gb/library/cc732443.aspx + +include Windows::Helper + +# Support whyrun +def whyrun_supported? + true +end + +use_inline_resources + +action :create do + hash = '$cert.GetCertHashString()' + code_script = cert_script(true) << + within_store_script { |store| store + '.Add($cert)' } << + acl_script(hash) + + guard_script = cert_script(false) << + cert_exists_script(hash) + + powershell_script @new_resource.name do + guard_interpreter :powershell_script + convert_boolean_return true + code code_script + not_if guard_script + 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 @new_resource.name do + guard_interpreter :powershell_script + convert_boolean_return true + code code_script + only_if guard_script + end +end + +action :delete do + # do we have a hash or a subject? + # TODO: It's a bit annoying to know the thumbprint of a cert you want to remove when you already + # have the file. Support reading the hash directly from the file if provided. + if @new_resource.source.match(/^[a-fA-F0-9]{40}$/) + search = "Thumbprint -eq '#{@new_resource.source}'" + else + search = "Subject -like '*#{@new_resource.source.sub(/\*/, '`*')}*'" # escape any * in the source + end + cert_command = "Get-ChildItem Cert:\\#{@location}\\#{@new_resource.store_name} | where { $_.#{search} }" + + code_script = within_store_script do |store| + <<-EOH +foreach ($c in #{cert_command}) +{ + #{store}.Remove($c) +} +EOH + end + guard_script = "@(#{cert_command}).Count -gt 0\n" + + powershell_script @new_resource.name do + guard_interpreter :powershell_script + convert_boolean_return true + code code_script + only_if guard_script + end +end + +def load_current_resource + # Currently we don't read out the cert acl here and converge it in a very Chef-y way. + # We also don't read if the private key is available or populate "exists". This means + # that if you converged a cert without persisting the private key once, we won't do it + # again, even if you have a cert with the keys now. + # TODO: Make this more Chef-y and follow a more state-based patten of convergence. + @current_resource = Chef::Resource::WindowsCertificate.new(@new_resource.name) + # TODO: Change to allow source to be read from the cookbook. It makes testing + # and loading certs from the cookbook much easier. + @current_resource.source(@new_resource.source) + @current_resource.pfx_password(@new_resource.pfx_password) + @current_resource.private_key_acl(@new_resource.private_key_acl) + @current_resource.store_name(@new_resource.store_name) + @current_resource.user_store(@new_resource.user_store) + @location = @current_resource.user_store ? 'CurrentUser' : 'LocalMachine' +end + +private + +def cert_script(persist) + cert_script = '$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2' + file = win_friendly_path(@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:\\#{@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]::#{@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.length == 0 + # 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:\\#{@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 diff --git a/cookbooks/windows/providers/certificate_binding.rb b/cookbooks/windows/providers/certificate_binding.rb new file mode 100644 index 0000000..341ab4e --- /dev/null +++ b/cookbooks/windows/providers/certificate_binding.rb @@ -0,0 +1,133 @@ +# +# Author:: Richard Lavey (richard.lavey@calastone.com) +# Cookbook Name:: windows +# Provider:: certificate_binding +# +# 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 https://msdn.microsoft.com/en-us/library/windows/desktop/cc307236%28v=vs.85%29.aspx for netsh info + +include Chef::Mixin::ShellOut +include Chef::Mixin::PowershellOut +include Windows::Helper + +# Support whyrun +def whyrun_supported? + true +end + +action :create do + hash = @new_resource.name_kind == :subject ? getHashFromSubject : @new_resource.cert_name + + if @current_resource.exists + needsChange = (hash.casecmp(@current_hash) != 0) + + if needsChange + converge_by("Changing #{@current_resource.address}:#{@current_resource.port}") do + deleteBinding + setBinding hash + end + else + Chef::Log.debug("#{@current_resource.address}:#{@current_resource.port} already bound to #{hash} - nothing to do") + end + else + converge_by("Binding #{@current_resource.address}:#{@current_resource.port}") do + setBinding hash + end + end +end + +action :delete do + if @current_resource.exists + converge_by("Deleting #{@current_resource.address}:#{@current_resource.port}") do + deleteBinding + end + else + Chef::Log.debug("#{@current_resource.address}:#{@current_resource.port} not bound - nothing to do") + end +end + +def load_current_resource + @current_resource = Chef::Resource::WindowsCertificateBinding.new(@new_resource.name) + @current_resource.cert_name(@new_resource.cert_name) + @current_resource.name_kind(@new_resource.name_kind) + @current_resource.address(@new_resource.address) + @current_resource.port(@new_resource.port) + @current_resource.store_name(@new_resource.store_name) + + @command = locate_sysnative_cmd('netsh.exe') + getCurrentHash +end + +private + +def getCurrentHash + cmd = shell_out("#{@command} http show sslcert ipport=#{@current_resource.address}:#{@current_resource.port}") + Chef::Log.debug "netsh reports: #{cmd.stdout}" + + if cmd.exitstatus == 0 + m = cmd.stdout.scan(/Certificate Hash\s+:\s?([A-Fa-f0-9]{40})/) + if m.length == 0 + fail "Failed to extract hash from command output #{cmd.stdout}" + else + @current_hash = m[0][0] + @current_resource.exists = true + end + else + @current_resource.exists = false + end +end + +def setBinding(hash) + cmd = "#{@command} http add sslcert" + cmd << " ipport=#{@current_resource.address}:#{@current_resource.port}" + cmd << " certhash=#{hash}" + cmd << " appid=#{@current_resource.app_id}" + cmd << " certstorename=#{@current_resource.store_name}" + checkHash hash + + shell_out!(cmd) +end + +def deleteBinding + shell_out!("#{@command} http delete sslcert ipport=#{@current_resource.address}:#{@current_resource.port}") +end + +def checkHash(hash) + p = powershell_out!("Test-Path \"cert:\\LocalMachine\\#{@current_resource.store_name}\\#{hash}\"") + + unless p.stderr.empty? && p.stdout =~ /True/i + fail "A Cert with hash of #{hash} doesn't exist in keystore LocalMachine\\#{@current_resource.store_name}" + end + nil +end + +def getHashFromSubject + # escape wildcard subject name (*.acme.com) + subject = @current_resource.cert_name.sub(/\*/, '`*') + ps_script = "& { gci cert:\\localmachine\\#{@current_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) + + if !p.stderr.nil? && p.stderr.length > 0 + fail "#{ps_script} failed with #{p.stderr}" + elsif p.stdout.nil? || p.stdout.length == 0 + fail "Couldn't find thumbprint for subject #{@current_resource.cert_name}" + end + + p.stdout.strip +end diff --git a/cookbooks/windows/providers/feature_dism.rb b/cookbooks/windows/providers/feature_dism.rb index 84fdbcf..a0c1cb6 100644 --- a/cookbooks/windows/providers/feature_dism.rb +++ b/cookbooks/windows/providers/feature_dism.rb @@ -1,64 +1,65 @@ -# -# Author:: Seth Chisamore () -# Cookbook Name:: windows -# Provider:: feature_dism -# -# Copyright:: 2011, 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::Provider::WindowsFeature::Base -include Chef::Mixin::ShellOut -include Windows::Helper - -def install_feature(name) - addsource = @new_resource.source ? "/LimitAccess /Source:\"#{@new_resource.source}\"" : "" - addall = @new_resource.all ? "/All" : "" - shell_out!("#{dism} /online /enable-feature /featurename:#{@new_resource.feature_name} /norestart #{addsource} #{addall}", {:returns => [0,42,127,3010]}) -end - -def remove_feature(name) - shell_out!("#{dism} /online /disable-feature /featurename:#{@new_resource.feature_name} /norestart", {:returns => [0,42,127,3010]}) -end - -def delete_feature(name) - if win_version.major_version >= 6 and win_version.minor_version >=2 - shell_out!("#{dism} /online /disable-feature /featurename:#{@new_resource.feature_name} /Remove /norestart", {:returns => [0,42,127,3010]}) - else - raise Chef::Exceptions::UnsupportedAction, "#{self.to_s} :delete action not support on #{win_version.sku}" - end -end - -def installed? - @installed ||= begin - cmd = shell_out("#{dism} /online /Get-Features", {:returns => [0,42,127]}) - cmd.stderr.empty? && (cmd.stdout =~ /^Feature Name : #{@new_resource.feature_name}.?$\n^State : Enabled.?$/i) - end -end - -def available? - @available ||= begin - cmd = shell_out("#{dism} /online /Get-Features", {:returns => [0,42,127]}) - cmd.stderr.empty? && (cmd.stdout !~ /^Feature Name : #{@new_resource.feature_name}.?$\n^State : .* with payload removed.?$/i) - end -end - -private -# account for File System Redirector -# http://msdn.microsoft.com/en-us/library/aa384187(v=vs.85).aspx -def dism - @dism ||= begin - locate_sysnative_cmd("dism.exe") - end -end +# +# Author:: Seth Chisamore () +# Cookbook Name:: windows +# Provider:: feature_dism +# +# 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. +# + +include Chef::Provider::WindowsFeature::Base +include Chef::Mixin::ShellOut +include Windows::Helper + +def install_feature(_name) + addsource = @new_resource.source ? "/LimitAccess /Source:\"#{@new_resource.source}\"" : '' + addall = @new_resource.all ? '/All' : '' + shell_out!("#{dism} /online /enable-feature /featurename:#{@new_resource.feature_name} /norestart #{addsource} #{addall}", returns: [0, 42, 127, 3010]) +end + +def remove_feature(_name) + shell_out!("#{dism} /online /disable-feature /featurename:#{@new_resource.feature_name} /norestart", returns: [0, 42, 127, 3010]) +end + +def delete_feature(_name) + if win_version.major_version >= 6 && win_version.minor_version >= 2 + shell_out!("#{dism} /online /disable-feature /featurename:#{@new_resource.feature_name} /Remove /norestart", returns: [0, 42, 127, 3010]) + else + fail Chef::Exceptions::UnsupportedAction, "#{self} :delete action not support on #{win_version.sku}" + end +end + +def installed? + @installed ||= begin + cmd = shell_out("#{dism} /online /Get-Features", returns: [0, 42, 127]) + cmd.stderr.empty? && (cmd.stdout =~ /^Feature Name : #{@new_resource.feature_name}.?$\n^State : Enabled.?$/i) + end +end + +def available? + @available ||= begin + cmd = shell_out("#{dism} /online /Get-Features", returns: [0, 42, 127]) + cmd.stderr.empty? && (cmd.stdout !~ /^Feature Name : #{@new_resource.feature_name}.?$\n^State : .* with payload removed.?$/i) + end +end + +private + +# account for File System Redirector +# http://msdn.microsoft.com/en-us/library/aa384187(v=vs.85).aspx +def dism + @dism ||= begin + locate_sysnative_cmd('dism.exe') + end +end diff --git a/cookbooks/windows/providers/feature_powershell.rb b/cookbooks/windows/providers/feature_powershell.rb index 44cd96c..e7cd867 100644 --- a/cookbooks/windows/providers/feature_powershell.rb +++ b/cookbooks/windows/providers/feature_powershell.rb @@ -1,38 +1,38 @@ -# -# Author:: Greg Zapp () -# Cookbook Name:: windows -# Provider:: feature_powershell -# - -include Chef::Provider::WindowsFeature::Base -include Chef::Mixin::PowershellOut -include Windows::Helper - -def install_feature(name) - cmd = powershell_out("Install-WindowsFeature #{@new_resource.feature_name}") - Chef::Log.info(cmd.stdout) -end - -def remove_feature(name) - cmd = powershell_out("Uninstall-WindowsFeature #{@new_resource.feature_name}") - Chef::Log.info(cmd.stdout) -end - -def delete_feature(name) - cmd = powershell_out("Uninstall-WindowsFeature #{@new_resource.feature_name} -Remove") - Chef::Log.info(cmd.stdout) -end - -def installed? - @installed ||= begin - cmd = powershell_out("Get-WindowsFeature #{@new_resource.feature_name} | Select Installed | % { Write-Host $_.Installed }") - cmd.stderr.empty? && cmd.stdout =~ /True/i - end -end - -def available? - @available ||= begin - cmd = powershell_out("Get-WindowsFeature #{@new_resource.feature_name}") - cmd.stderr.empty? && cmd.stdout !~ /Removed/i - end -end +# +# Author:: Greg Zapp () +# Cookbook Name:: windows +# Provider:: feature_powershell +# + +include Chef::Provider::WindowsFeature::Base +include Chef::Mixin::PowershellOut +include Windows::Helper + +def install_feature(_name) + cmd = powershell_out("Install-WindowsFeature #{@new_resource.feature_name}") + Chef::Log.info(cmd.stdout) +end + +def remove_feature(_name) + cmd = powershell_out("Uninstall-WindowsFeature #{@new_resource.feature_name}") + Chef::Log.info(cmd.stdout) +end + +def delete_feature(_name) + cmd = powershell_out("Uninstall-WindowsFeature #{@new_resource.feature_name} -Remove") + Chef::Log.info(cmd.stdout) +end + +def installed? + @installed ||= begin + cmd = powershell_out("Get-WindowsFeature #{@new_resource.feature_name} | Select Installed | % { Write-Host $_.Installed }") + cmd.stderr.empty? && cmd.stdout =~ /True/i + end +end + +def available? + @available ||= begin + cmd = powershell_out("Get-WindowsFeature #{@new_resource.feature_name}") + cmd.stderr.empty? && cmd.stdout !~ /Removed/i + end +end diff --git a/cookbooks/windows/providers/feature_servermanagercmd.rb b/cookbooks/windows/providers/feature_servermanagercmd.rb index 59cc3a7..75e25c2 100644 --- a/cookbooks/windows/providers/feature_servermanagercmd.rb +++ b/cookbooks/windows/providers/feature_servermanagercmd.rb @@ -1,61 +1,61 @@ -# -# Author:: Seth Chisamore () -# Cookbook Name:: windows -# Provider:: feature_servermanagercmd -# -# Copyright:: 2011, 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::Provider::WindowsFeature::Base -include Chef::Mixin::ShellOut -include Windows::Helper - -# Exit codes are listed at http://technet.microsoft.com/en-us/library/cc749128(v=ws.10).aspx - -def check_reboot(result, feature) - if result.exitstatus == 3010 # successful, but needs reboot - node.run_state[:reboot_requested] = true - Chef::Log.warn("Require reboot to install #{feature}") - elsif result.exitstatus == 1001 # failure, but needs reboot before we can do anything else - node.run_state[:reboot_requested] = true - Chef::Log.warn("Failed installing #{feature} and need to reboot") - end - result.error! # throw for any other bad results. The above results will also get raised, and should cause a reboot via the handler. -end - -def install_feature(name) - check_reboot(shell_out("#{servermanagercmd} -install #{@new_resource.feature_name}", {:returns => [0,42,127,1003,3010]}), @new_resource.feature_name) -end - -def remove_feature(name) - check_reboot(shell_out("#{servermanagercmd} -remove #{@new_resource.feature_name}", {:returns => [0,42,127,1003,3010]}), @new_resource.feature_name) -end - -def installed? - @installed ||= begin - cmd = shell_out("#{servermanagercmd} -query", {:returns => [0,42,127,1003]}) - cmd.stderr.empty? && (cmd.stdout =~ /^\s*?\[X\]\s.+?\s\[#{@new_resource.feature_name}\]\s*$/i) - end -end - -private - -# account for File System Redirector -# http://msdn.microsoft.com/en-us/library/aa384187(v=vs.85).aspx -def servermanagercmd - @servermanagercmd ||= begin - locate_sysnative_cmd("servermanagercmd.exe") - end -end +# +# Author:: Seth Chisamore () +# Cookbook Name:: windows +# Provider:: feature_servermanagercmd +# +# 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. +# + +include Chef::Provider::WindowsFeature::Base +include Chef::Mixin::ShellOut +include Windows::Helper + +# Exit codes are listed at http://technet.microsoft.com/en-us/library/cc749128(v=ws.10).aspx + +def check_reboot(result, feature) + if result.exitstatus == 3010 # successful, but needs reboot + node.run_state[:reboot_requested] = true + Chef::Log.warn("Require reboot to install #{feature}") + elsif result.exitstatus == 1001 # failure, but needs reboot before we can do anything else + node.run_state[:reboot_requested] = true + Chef::Log.warn("Failed installing #{feature} and need to reboot") + end + result.error! # throw for any other bad results. The above results will also get raised, and should cause a reboot via the handler. +end + +def install_feature(_name) + check_reboot(shell_out("#{servermanagercmd} -install #{@new_resource.feature_name}", returns: [0, 42, 127, 1003, 3010]), @new_resource.feature_name) +end + +def remove_feature(_name) + check_reboot(shell_out("#{servermanagercmd} -remove #{@new_resource.feature_name}", returns: [0, 42, 127, 1003, 3010]), @new_resource.feature_name) +end + +def installed? + @installed ||= begin + cmd = shell_out("#{servermanagercmd} -query", returns: [0, 42, 127, 1003]) + cmd.stderr.empty? && (cmd.stdout =~ /^\s*?\[X\]\s.+?\s\[#{@new_resource.feature_name}\]\s*$/i) + end +end + +private + +# account for File System Redirector +# http://msdn.microsoft.com/en-us/library/aa384187(v=vs.85).aspx +def servermanagercmd + @servermanagercmd ||= begin + locate_sysnative_cmd('servermanagercmd.exe') + end +end diff --git a/cookbooks/windows/providers/font.rb b/cookbooks/windows/providers/font.rb index 1a1e473..e185062 100644 --- a/cookbooks/windows/providers/font.rb +++ b/cookbooks/windows/providers/font.rb @@ -1,69 +1,69 @@ -# -# Author:: Sander Botman -# Cookbook Name:: windows -# Provider:: font -# -# Copyright:: 2014, Schuberg Philis BV. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT 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 - -def load_current_resource - require 'win32ole' - fonts_dir = WIN32OLE.new("WScript.Shell").SpecialFolders("Fonts") - @current_resource = Chef::Resource::WindowsFont.new(@new_resource.name) - @current_resource.file(win_friendly_path(::File.join(fonts_dir, @new_resource.file))) - @current_resource -end - -# Check to see if the font is installed -# -# === Returns -# :: If the font is installed -# :: If the font is not instaled -def font_exists? - ::File.exists?(@current_resource.file) -end - -def get_cookbook_font - r = Chef::Resource::CookbookFile.new(@new_resource.file, run_context) - r.path(win_friendly_path(::File.join(ENV['TEMP'], @new_resource.file))) - r.cookbook(cookbook_name.to_s) - r.run_action(:create) -end - -def del_cookbook_font - r = Chef::Resource::File.new(::File.join(ENV['TEMP'], @new_resource.file), run_context) - r.run_action(:delete) -end - -def install_font - require 'win32ole' - fonts_dir = WIN32OLE.new("WScript.Shell").SpecialFolders("Fonts") - folder = WIN32OLE.new("Shell.Application").Namespace(fonts_dir) - folder.CopyHere(win_friendly_path(::File.join(ENV['TEMP'], @new_resource.file))) - Chef::Log.debug("Installing font: #{@new_resource.file}") -end - -def action_install - unless font_exists? - get_cookbook_font - install_font - del_cookbook_font - new_resource.updated_by_last_action(true) - else - Chef::Log.debug("Not installing font: #{@new_resource.file}, font already installed.") - new_resource.updated_by_last_action(false) - end -end +# +# Author:: Sander Botman +# Cookbook Name:: windows +# Provider:: font +# +# Copyright:: 2014, Schuberg Philis BV. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 + +def load_current_resource + require 'win32ole' + fonts_dir = WIN32OLE.new('WScript.Shell').SpecialFolders('Fonts') + @current_resource = Chef::Resource::WindowsFont.new(@new_resource.name) + @current_resource.file(win_friendly_path(::File.join(fonts_dir, @new_resource.file))) + @current_resource +end + +# Check to see if the font is installed +# +# === Returns +# :: If the font is installed +# :: If the font is not instaled +def font_exists? + ::File.exist?(@current_resource.file) +end + +def get_cookbook_font + r = Chef::Resource::CookbookFile.new(@new_resource.file, run_context) + r.path(win_friendly_path(::File.join(ENV['TEMP'], @new_resource.file))) + r.cookbook(cookbook_name.to_s) + r.run_action(:create) +end + +def del_cookbook_font + r = Chef::Resource::File.new(::File.join(ENV['TEMP'], @new_resource.file), run_context) + r.run_action(:delete) +end + +def install_font + require 'win32ole' + fonts_dir = WIN32OLE.new('WScript.Shell').SpecialFolders('Fonts') + folder = WIN32OLE.new('Shell.Application').Namespace(fonts_dir) + folder.CopyHere(win_friendly_path(::File.join(ENV['TEMP'], @new_resource.file))) + Chef::Log.debug("Installing font: #{@new_resource.file}") +end + +def action_install + unless font_exists? + get_cookbook_font + install_font + del_cookbook_font + new_resource.updated_by_last_action(true) + else + Chef::Log.debug("Not installing font: #{@new_resource.file}, font already installed.") + new_resource.updated_by_last_action(false) + end +end diff --git a/cookbooks/windows/providers/http_acl.rb b/cookbooks/windows/providers/http_acl.rb new file mode 100644 index 0000000..6487bab --- /dev/null +++ b/cookbooks/windows/providers/http_acl.rb @@ -0,0 +1,91 @@ +# +# Author:: Richard Lavey (richard.lavey@calastone.com) +# Cookbook Name:: windows +# Provider:: http_acl +# +# 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 https://msdn.microsoft.com/en-us/library/windows/desktop/cc307236%28v=vs.85%29.aspx for netsh info + +include Chef::Mixin::ShellOut +include Windows::Helper + +# Support whyrun +def whyrun_supported? + true +end + +action :create do + fail 'No user property set' if @new_resource.user.nil? || @new_resource.user.empty? + + if @current_resource.exists + needsChange = (@current_resource.user.casecmp(@new_resource.user) != 0) + + if needsChange + converge_by("Changing #{@current_resource.url}") do + deleteAcl + setAcl + end + else + Chef::Log.debug("#{@current_resource.url} already set - nothing to do") + end + else + converge_by("Setting #{@current_resource.url}") do + setAcl + end + end +end + +action :delete do + if @current_resource.exists + converge_by("Deleting #{@current_resource.url}") do + deleteAcl + end + else + Chef::Log.debug("#{@current_resource.url} does not exist - nothing to do") + end +end + +def load_current_resource + @current_resource = Chef::Resource::WindowsHttpAcl.new(@new_resource.name) + @current_resource.url(@new_resource.url) + + @command = locate_sysnative_cmd('netsh.exe') + getCurrentAcl +end + +private + +def getCurrentAcl + cmd = shell_out!("#{@command} http show urlacl url=#{@current_resource.url}") + Chef::Log.debug "netsh reports: #{cmd.stdout}" + + m = cmd.stdout.scan(/User:\s*(\S+)/) + if m.length == 0 + @current_resource.exists = false + else + @current_resource.user(m[0][0]) + @current_resource.exists = true + end +end + +def setAcl + shell_out!("#{@command} http add urlacl url=#{@new_resource.url} user=\"#{@new_resource.user}\"") +end + +def deleteAcl + shell_out!("#{@command} http delete urlacl url=#{@new_resource.url}") +end diff --git a/cookbooks/windows/providers/pagefile.rb b/cookbooks/windows/providers/pagefile.rb index 2b41af4..a83ba0b 100644 --- a/cookbooks/windows/providers/pagefile.rb +++ b/cookbooks/windows/providers/pagefile.rb @@ -1,153 +1,149 @@ -# -# Author:: Kevin Moser () -# Cookbook Name:: windows -# Provider:: pagefile -# -# 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. -# - -include Chef::Mixin::ShellOut -include Windows::Helper - -action :set do - pagefile = @new_resource.name - initial_size = @new_resource.initial_size - maximum_size = @new_resource.maximum_size - system_managed = @new_resource.system_managed - automatic_managed = @new_resource.automatic_managed - updated = false - - if automatic_managed - unless automatic_managed? - set_automatic_managed - updated = true - end - else - if automatic_managed? - unset_automatic_managed - updated = true - end - - # Check that the resource is not just trying to unset automatic managed, if it is do nothing more - if (initial_size && maximum_size) || system_managed - unless exists?(pagefile) - create(pagefile) - end - - if system_managed - unless max_and_min_set?(pagefile, 0, 0) - set_system_managed(pagefile) - updated = true - end - else - unless max_and_min_set?(pagefile, initial_size, maximum_size) - set_custom_size(pagefile, initial_size, maximum_size) - updated = true - end - end - end - end - - new_resource.updated_by_last_action(updated) -end - -action :delete do - pagefile = @new_resource.name - updated = false - - if exists?(pagefile) - delete(pagefile) - updated = true - end - - new_resource.updated_by_last_action(updated) -end - - -private -def exists?(pagefile) - @exists ||= begin - cmd = shell_out("#{wmic} pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" list /format:list", {:returns => [0]}) - cmd.stderr.empty? && (cmd.stdout =~ /SettingID=#{get_setting_id(pagefile)}/i) - end -end - -def max_and_min_set?(pagefile, min, max) - @max_and_min_set ||= begin - cmd = shell_out("#{wmic} pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" list /format:list", {:returns => [0]}) - cmd.stderr.empty? && (cmd.stdout =~ /InitialSize=#{min}/i) && (cmd.stdout =~ /MaximumSize=#{max}/i) - end -end - -def create(pagefile) - Chef::Log.debug("Creating pagefile #{pagefile}") - cmd = shell_out("#{wmic} pagefileset create name=\"#{win_friendly_path(pagefile)}\"") - check_for_errors(cmd.stderr) -end - -def delete(pagefile) - Chef::Log.debug("Removing pagefile #{pagefile}") - cmd = shell_out("#{wmic} pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" delete") - check_for_errors(cmd.stderr) -end - -def automatic_managed? - @automatic_managed ||= begin - cmd = shell_out("#{wmic} computersystem where name=\"%computername%\" get AutomaticManagedPagefile /format:list") - cmd.stderr.empty? && (cmd.stdout =~ /AutomaticManagedPagefile=TRUE/i) - end -end - -def set_automatic_managed - Chef::Log.debug("Setting pagefile to Automatic Managed") - cmd = shell_out("#{wmic} computersystem where name=\"%computername%\" set AutomaticManagedPagefile=True") - check_for_errors(cmd.stderr) -end - -def unset_automatic_managed - Chef::Log.debug("Setting pagefile to User Managed") - cmd = shell_out("#{wmic} computersystem where name=\"%computername%\" set AutomaticManagedPagefile=False") - check_for_errors(cmd.stderr) -end - -def set_custom_size(pagefile, min, max) - Chef::Log.debug("Setting #{pagefile} to InitialSize=#{min} & MaximumSize=#{max}") - cmd = shell_out("#{wmic} pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" set InitialSize=#{min},MaximumSize=#{max}", {:returns => [0]}) - check_for_errors(cmd.stderr) -end - -def set_system_managed(pagefile) - Chef::Log.debug("Setting #{pagefile} to System Managed") - cmd = shell_out("#{wmic} pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" set InitialSize=0,MaximumSize=0", {:returns => [0]}) - check_for_errors(cmd.stderr) -end - -def get_setting_id(pagefile) - pagefile = win_friendly_path(pagefile) - pagefile = pagefile.split("\\") - "#{pagefile[1]} @ #{pagefile[0]}" -end - -def check_for_errors(stderr) - unless stderr.empty? - Chef::Log.fatal(stderr) - end -end - -def wmic - @wmic ||= begin - locate_sysnative_cmd("wmic.exe") - end -end +# +# Author:: Kevin Moser () +# Cookbook Name:: windows +# Provider:: pagefile +# +# 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. +# + +include Chef::Mixin::ShellOut +include Windows::Helper + +action :set do + pagefile = @new_resource.name + initial_size = @new_resource.initial_size + maximum_size = @new_resource.maximum_size + system_managed = @new_resource.system_managed + automatic_managed = @new_resource.automatic_managed + updated = false + + if automatic_managed + unless automatic_managed? + set_automatic_managed + updated = true + end + else + if automatic_managed? + unset_automatic_managed + updated = true + end + + # Check that the resource is not just trying to unset automatic managed, if it is do nothing more + if (initial_size && maximum_size) || system_managed + create(pagefile) unless exists?(pagefile) + + if system_managed + unless max_and_min_set?(pagefile, 0, 0) + set_system_managed(pagefile) + updated = true + end + else + unless max_and_min_set?(pagefile, initial_size, maximum_size) + set_custom_size(pagefile, initial_size, maximum_size) + updated = true + end + end + end + end + + new_resource.updated_by_last_action(updated) +end + +action :delete do + pagefile = @new_resource.name + updated = false + + if exists?(pagefile) + delete(pagefile) + updated = true + end + + new_resource.updated_by_last_action(updated) +end + +private + +def exists?(pagefile) + @exists ||= begin + cmd = shell_out("#{wmic} pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" list /format:list", returns: [0]) + cmd.stderr.empty? && (cmd.stdout =~ /SettingID=#{get_setting_id(pagefile)}/i) + end +end + +def max_and_min_set?(pagefile, min, max) + @max_and_min_set ||= begin + cmd = shell_out("#{wmic} pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" list /format:list", returns: [0]) + cmd.stderr.empty? && (cmd.stdout =~ /InitialSize=#{min}/i) && (cmd.stdout =~ /MaximumSize=#{max}/i) + end +end + +def create(pagefile) + Chef::Log.debug("Creating pagefile #{pagefile}") + cmd = shell_out("#{wmic} pagefileset create name=\"#{win_friendly_path(pagefile)}\"") + check_for_errors(cmd.stderr) +end + +def delete(pagefile) + Chef::Log.debug("Removing pagefile #{pagefile}") + cmd = shell_out("#{wmic} pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" delete") + check_for_errors(cmd.stderr) +end + +def automatic_managed? + @automatic_managed ||= begin + cmd = shell_out("#{wmic} computersystem where name=\"%computername%\" get AutomaticManagedPagefile /format:list") + cmd.stderr.empty? && (cmd.stdout =~ /AutomaticManagedPagefile=TRUE/i) + end +end + +def set_automatic_managed + Chef::Log.debug('Setting pagefile to Automatic Managed') + cmd = shell_out("#{wmic} computersystem where name=\"%computername%\" set AutomaticManagedPagefile=True") + check_for_errors(cmd.stderr) +end + +def unset_automatic_managed + Chef::Log.debug('Setting pagefile to User Managed') + cmd = shell_out("#{wmic} computersystem where name=\"%computername%\" set AutomaticManagedPagefile=False") + check_for_errors(cmd.stderr) +end + +def set_custom_size(pagefile, min, max) + Chef::Log.debug("Setting #{pagefile} to InitialSize=#{min} & MaximumSize=#{max}") + cmd = shell_out("#{wmic} pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" set InitialSize=#{min},MaximumSize=#{max}", returns: [0]) + check_for_errors(cmd.stderr) +end + +def set_system_managed(pagefile) + Chef::Log.debug("Setting #{pagefile} to System Managed") + cmd = shell_out("#{wmic} pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" set InitialSize=0,MaximumSize=0", returns: [0]) + check_for_errors(cmd.stderr) +end + +def get_setting_id(pagefile) + pagefile = win_friendly_path(pagefile) + pagefile = pagefile.split('\\') + "#{pagefile[1]} @ #{pagefile[0]}" +end + +def check_for_errors(stderr) + Chef::Log.fatal(stderr) unless stderr.empty? +end + +def wmic + @wmic ||= begin + locate_sysnative_cmd('wmic.exe') + end +end diff --git a/cookbooks/windows/providers/path.rb b/cookbooks/windows/providers/path.rb index 8003c7f..f246dd7 100644 --- a/cookbooks/windows/providers/path.rb +++ b/cookbooks/windows/providers/path.rb @@ -1,52 +1,52 @@ -# -# Author:: Paul Morton () -# Cookbook Name:: windows -# Provider:: path -# -# Copyright:: 2011, 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. -# -use_inline_resources if defined?(use_inline_resources) - -include Windows::Helper - -action :add do - env "path" do - action :modify - delim ::File::PATH_SEPARATOR - value new_resource.path - notifies :run, "ruby_block[fix ruby ENV['PATH']]", :immediately - end - - # The windows Env provider does not correctly expand variables in - # the PATH environment variable. Ruby expects these to be expanded. - # This is a temporary fix for that. - # - # Follow at https://github.com/chef/chef/pull/1876 - # - ruby_block "fix ruby ENV['PATH']" do - block do - ENV['PATH'] = expand_env_vars(ENV['PATH']) - end - action :nothing - end -end - -action :remove do - env "path" do - action :delete - delim ::File::PATH_SEPARATOR - value new_resource.path - end -end +# +# Author:: Paul Morton () +# Cookbook Name:: windows +# Provider:: path +# +# Copyright:: 2011, 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. +# +use_inline_resources if defined?(use_inline_resources) + +include Windows::Helper + +action :add do + env 'path' do + action :modify + delim ::File::PATH_SEPARATOR + value new_resource.path + notifies :run, "ruby_block[fix ruby ENV['PATH']]", :immediately + end + + # The windows Env provider does not correctly expand variables in + # the PATH environment variable. Ruby expects these to be expanded. + # This is a temporary fix for that. + # + # Follow at https://github.com/chef/chef/pull/1876 + # + ruby_block "fix ruby ENV['PATH']" do + block do + ENV['PATH'] = expand_env_vars(ENV['PATH']) + end + action :nothing + end +end + +action :remove do + env 'path' do + action :delete + delim ::File::PATH_SEPARATOR + value new_resource.path + end +end diff --git a/cookbooks/windows/providers/printer.rb b/cookbooks/windows/providers/printer.rb index 3dd976c..5da6730 100644 --- a/cookbooks/windows/providers/printer.rb +++ b/cookbooks/windows/providers/printer.rb @@ -1,101 +1,99 @@ -# -# Author:: Doug Ireton () -# Cookbook Name:: windows -# Provider:: printer -# -# 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. -# -use_inline_resources if defined?(use_inline_resources) - -# Support whyrun -def whyrun_supported? - true -end - -action :create do - if @current_resource.exists - Chef::Log.info "#{ @new_resource } already exists - nothing to do." - else - converge_by("Create #{ @new_resource }") do - create_printer - end - end -end - -action :delete do - if @current_resource.exists - converge_by("Delete #{ @new_resource }") do - delete_printer - end - else - Chef::Log.info "#{ @current_resource } doesn't exist - can't delete." - end -end - -def load_current_resource - @current_resource = Chef::Resource::WindowsPrinter.new(@new_resource.name) - @current_resource.name(@new_resource.name) - - if printer_exists?(@current_resource.name) - # TODO: Set @current_resource printer properties from registry - @current_resource.exists = true - end -end - - -private - -PRINTERS_REG_KEY = 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers\\'.freeze unless defined?(PRINTERS_REG_KEY) - -def printer_exists?(name) - printer_reg_key = PRINTERS_REG_KEY + name - Chef::Log.debug "Checking to see if this reg key exists: '#{ printer_reg_key }'" - Registry.key_exists?(printer_reg_key) -end - -def create_printer - - # Create the printer port first - windows_printer_port new_resource.ipv4_address do - end - - port_name = "IP_#{ new_resource.ipv4_address }" - - powershell_script "Creating printer: #{ new_resource.name }" do - code <<-EOH - - Set-WmiInstance -class Win32_Printer ` - -EnableAllPrivileges ` - -Argument @{ DeviceID = "#{ new_resource.device_id }"; - Comment = "#{ new_resource.comment }"; - Default = "$#{ new_resource.default }"; - DriverName = "#{ new_resource.driver_name }"; - Location = "#{ new_resource.location }"; - PortName = "#{ port_name }"; - Shared = "$#{ new_resource.shared }"; - ShareName = "#{ new_resource.share_name }"; - } - EOH - end -end - -def delete_printer - powershell_script "Deleting printer: #{ new_resource.name }" do - code <<-EOH - $printer = Get-WMIObject -class Win32_Printer -EnableAllPrivileges -Filter "name = '#{ new_resource.name }'" - $printer.Delete() - EOH - end -end +# +# Author:: Doug Ireton () +# Cookbook Name:: windows +# Provider:: printer +# +# 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. +# +use_inline_resources if defined?(use_inline_resources) + +# Support whyrun +def whyrun_supported? + true +end + +action :create do + if @current_resource.exists + Chef::Log.info "#{@new_resource} already exists - nothing to do." + else + converge_by("Create #{@new_resource}") do + create_printer + end + end +end + +action :delete do + if @current_resource.exists + converge_by("Delete #{@new_resource}") do + delete_printer + end + else + Chef::Log.info "#{@current_resource} doesn't exist - can't delete." + end +end + +def load_current_resource + @current_resource = Chef::Resource::WindowsPrinter.new(@new_resource.name) + @current_resource.name(@new_resource.name) + + if printer_exists?(@current_resource.name) + # TODO: Set @current_resource printer properties from registry + @current_resource.exists = true + end +end + +private + +PRINTERS_REG_KEY = 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers\\'.freeze unless defined?(PRINTERS_REG_KEY) + +def printer_exists?(name) + printer_reg_key = PRINTERS_REG_KEY + name + Chef::Log.debug "Checking to see if this reg key exists: '#{printer_reg_key}'" + Registry.key_exists?(printer_reg_key) +end + +def create_printer + # Create the printer port first + windows_printer_port new_resource.ipv4_address do + end + + port_name = "IP_#{new_resource.ipv4_address}" + + powershell_script "Creating printer: #{new_resource.name}" do + code <<-EOH + + Set-WmiInstance -class Win32_Printer ` + -EnableAllPrivileges ` + -Argument @{ DeviceID = "#{new_resource.device_id}"; + Comment = "#{new_resource.comment}"; + Default = "$#{new_resource.default}"; + DriverName = "#{new_resource.driver_name}"; + Location = "#{new_resource.location}"; + PortName = "#{port_name}"; + Shared = "$#{new_resource.shared}"; + ShareName = "#{new_resource.share_name}"; + } + EOH + end +end + +def delete_printer + powershell_script "Deleting printer: #{new_resource.name}" do + code <<-EOH + $printer = Get-WMIObject -class Win32_Printer -EnableAllPrivileges -Filter "name = '#{new_resource.name}'" + $printer.Delete() + EOH + end +end diff --git a/cookbooks/windows/providers/printer_port.rb b/cookbooks/windows/providers/printer_port.rb index d2666ec..1793291 100644 --- a/cookbooks/windows/providers/printer_port.rb +++ b/cookbooks/windows/providers/printer_port.rb @@ -1,103 +1,99 @@ -# -# Author:: Doug Ireton () -# Cookbook Name:: windows -# Provider:: printer_port -# -# 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. -# -use_inline_resources if defined?(use_inline_resources) - -# Support whyrun -def whyrun_supported? - true -end - -action :create do - if @current_resource.exists - Chef::Log.info "#{ @new_resource } already exists - nothing to do." - else - converge_by("Create #{ @new_resource }") do - create_printer_port - end - end -end - -action :delete do - if @current_resource.exists - converge_by("Delete #{ @new_resource }") do - delete_printer_port - end - else - Chef::Log.info "#{ @current_resource } doesn't exist - can't delete." - end -end - -def load_current_resource - @current_resource = Chef::Resource::WindowsPrinterPort.new(@new_resource.name) - @current_resource.name(@new_resource.name) - @current_resource.ipv4_address(@new_resource.ipv4_address) - @current_resource.port_name(@new_resource.port_name || "IP_#{ @new_resource.ipv4_address }") - - if port_exists?(@current_resource.port_name) - # TODO: Set @current_resource port properties from registry - @current_resource.exists = true - end -end - - -private - -PORTS_REG_KEY = 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Monitors\Standard TCP/IP Port\Ports\\'.freeze unless defined?(PORTS_REG_KEY) - -def port_exists?(name) - port_reg_key = PORTS_REG_KEY + name - - Chef::Log.debug "Checking to see if this reg key exists: '#{ port_reg_key }'" - Registry.key_exists?(port_reg_key) -end - - -def create_printer_port - - port_name = new_resource.port_name || "IP_#{ new_resource.ipv4_address }" - - # create the printer port using PowerShell - powershell_script "Creating printer port #{ new_resource.port_name }" do - code <<-EOH - - Set-WmiInstance -class Win32_TCPIPPrinterPort ` - -EnableAllPrivileges ` - -Argument @{ HostAddress = "#{ new_resource.ipv4_address }"; - Name = "#{ port_name }"; - Description = "#{ new_resource.port_description }"; - PortNumber = "#{ new_resource.port_number }"; - Protocol = "#{ new_resource.port_protocol }"; - SNMPEnabled = "$#{ new_resource.snmp_enabled }"; - } - EOH - end -end - -def delete_printer_port - - port_name = new_resource.port_name || "IP_#{ new_resource.ipv4_address }" - - powershell_script "Deleting printer port: #{ new_resource.port_name }" do - code <<-EOH - $port = Get-WMIObject -class Win32_TCPIPPrinterPort -EnableAllPrivileges -Filter "name = '#{ port_name }'" - $port.Delete() - EOH - end -end +# +# Author:: Doug Ireton () +# Cookbook Name:: windows +# Provider:: printer_port +# +# 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. +# +use_inline_resources if defined?(use_inline_resources) + +# Support whyrun +def whyrun_supported? + true +end + +action :create do + if @current_resource.exists + Chef::Log.info "#{@new_resource} already exists - nothing to do." + else + converge_by("Create #{@new_resource}") do + create_printer_port + end + end +end + +action :delete do + if @current_resource.exists + converge_by("Delete #{@new_resource}") do + delete_printer_port + end + else + Chef::Log.info "#{@current_resource} doesn't exist - can't delete." + end +end + +def load_current_resource + @current_resource = Chef::Resource::WindowsPrinterPort.new(@new_resource.name) + @current_resource.name(@new_resource.name) + @current_resource.ipv4_address(@new_resource.ipv4_address) + @current_resource.port_name(@new_resource.port_name || "IP_#{@new_resource.ipv4_address}") + + if port_exists?(@current_resource.port_name) + # TODO: Set @current_resource port properties from registry + @current_resource.exists = true + end +end + +private + +PORTS_REG_KEY = 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Monitors\Standard TCP/IP Port\Ports\\'.freeze unless defined?(PORTS_REG_KEY) + +def port_exists?(name) + port_reg_key = PORTS_REG_KEY + name + + Chef::Log.debug "Checking to see if this reg key exists: '#{port_reg_key}'" + Registry.key_exists?(port_reg_key) +end + +def create_printer_port + port_name = new_resource.port_name || "IP_#{new_resource.ipv4_address}" + + # create the printer port using PowerShell + powershell_script "Creating printer port #{new_resource.port_name}" do + code <<-EOH + + Set-WmiInstance -class Win32_TCPIPPrinterPort ` + -EnableAllPrivileges ` + -Argument @{ HostAddress = "#{new_resource.ipv4_address}"; + Name = "#{port_name}"; + Description = "#{new_resource.port_description}"; + PortNumber = "#{new_resource.port_number}"; + Protocol = "#{new_resource.port_protocol}"; + SNMPEnabled = "$#{new_resource.snmp_enabled}"; + } + EOH + end +end + +def delete_printer_port + port_name = new_resource.port_name || "IP_#{new_resource.ipv4_address}" + + powershell_script "Deleting printer port: #{new_resource.port_name}" do + code <<-EOH + $port = Get-WMIObject -class Win32_TCPIPPrinterPort -EnableAllPrivileges -Filter "name = '#{port_name}'" + $port.Delete() + EOH + end +end diff --git a/cookbooks/windows/providers/reboot.rb b/cookbooks/windows/providers/reboot.rb index c5cf68c6..5da1903 100644 --- a/cookbooks/windows/providers/reboot.rb +++ b/cookbooks/windows/providers/reboot.rb @@ -1,33 +1,33 @@ -# -# Author:: Seth Chisamore () -# Cookbook Name:: windows -# Provider:: reboot -# -# Copyright:: 2011, 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 :request do - node.run_state[:reboot_requested] = true - node.run_state[:reboot_timeout] = @new_resource.timeout - node.run_state[:reboot_reason] = @new_resource.reason - new_resource.updated_by_last_action(true) -end - -action :cancel do - node.run_state.delete(:reboot_requested) - node.run_state.delete(:reboot_timeout) - node.run_state.delete(:reboot_reason) - new_resource.updated_by_last_action(true) -end +# +# Author:: Seth Chisamore () +# Cookbook Name:: windows +# Provider:: reboot +# +# 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. +# + +action :request do + node.run_state[:reboot_requested] = true + node.run_state[:reboot_timeout] = @new_resource.timeout + node.run_state[:reboot_reason] = @new_resource.reason + new_resource.updated_by_last_action(true) +end + +action :cancel do + node.run_state.delete(:reboot_requested) + node.run_state.delete(:reboot_timeout) + node.run_state.delete(:reboot_reason) + new_resource.updated_by_last_action(true) +end diff --git a/cookbooks/windows/providers/registry.rb b/cookbooks/windows/providers/registry.rb index 6ffd498..71637c8 100644 --- a/cookbooks/windows/providers/registry.rb +++ b/cookbooks/windows/providers/registry.rb @@ -1,75 +1,75 @@ -# -# Author:: Doug MacEachern () -# Author:: Seth Chisamore () -# Author:: Paul Morton () -# Cookbook Name:: windows -# Provider:: registry -# -# Copyright:: 2010, VMware, Inc. -# Copyright:: 2011, Chef Software, Inc. -# Copyright:: 2011, 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. -# - -include Windows::RegistryHelper - -action :create do - updated = registry_update(:create) - new_resource.updated_by_last_action(updated) -end - -action :modify do - updated = registry_update(:open) - new_resource.updated_by_last_action(updated) -end - -action :force_modify do - require 'timeout' - Timeout.timeout(120) do - @new_resource.values.each do |value_name, value_data| - i = 1 - until i > 5 do - desired_value_data = value_data - current_value_data = get_value(@new_resource.key_name.dup, value_name.dup) - if current_value_data.to_s == desired_value_data.to_s - Chef::Log.debug("#{@new_resource} value [#{value_name}] desired [#{desired_value_data}] data already set. Check #{i}/5.") - i+=1 - else - Chef::Log.debug("#{@new_resource} value [#{value_name}] current [#{current_value_data}] data not equal to desired [#{desired_value_data}] data. Setting value and restarting check loop.") - begin - updated = registry_update(:open) - new_resource.updated_by_last_action(updated) - rescue Exception - updated = registry_update(:create) - new_resource.updated_by_last_action(updated) - end - i=0 # start count loop over - end - end - end - break - end -end - -action :remove do - delete_value(@new_resource.key_name,@new_resource.values) - new_resource.updated_by_last_action(true) -end - -private -def registry_update(mode) - - Chef::Log.debug("Registry Mode (#{mode})") - updated = set_value(mode,@new_resource.key_name,@new_resource.values,@new_resource.type) -end +# +# Author:: Doug MacEachern () +# Author:: Seth Chisamore () +# Author:: Paul Morton () +# Cookbook Name:: windows +# Provider:: registry +# +# Copyright:: 2010, VMware, Inc. +# Copyright:: 2011-2015, Chef Software, Inc. +# Copyright:: 2011, 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. +# + +include Windows::RegistryHelper + +action :create do + updated = registry_update(:create) + new_resource.updated_by_last_action(updated) +end + +action :modify do + updated = registry_update(:open) + new_resource.updated_by_last_action(updated) +end + +action :force_modify do + require 'timeout' + Timeout.timeout(120) do + @new_resource.values.each do |value_name, value_data| + i = 1 + until i > 5 + desired_value_data = value_data + current_value_data = get_value(@new_resource.key_name.dup, value_name.dup) + if current_value_data.to_s == desired_value_data.to_s + Chef::Log.debug("#{@new_resource} value [#{value_name}] desired [#{desired_value_data}] data already set. Check #{i}/5.") + i += 1 + else + Chef::Log.debug("#{@new_resource} value [#{value_name}] current [#{current_value_data}] data not equal to desired [#{desired_value_data}] data. Setting value and restarting check loop.") + begin + updated = registry_update(:open) + new_resource.updated_by_last_action(updated) + rescue Exception + updated = registry_update(:create) + new_resource.updated_by_last_action(updated) + end + i = 0 # start count loop over + end + end + end + break + end +end + +action :remove do + delete_value(@new_resource.key_name, @new_resource.values) + new_resource.updated_by_last_action(true) +end + +private + +def registry_update(mode) + Chef::Log.debug("Registry Mode (#{mode})") + updated = set_value(mode, @new_resource.key_name, @new_resource.values, @new_resource.type) +end diff --git a/cookbooks/windows/providers/shortcut.rb b/cookbooks/windows/providers/shortcut.rb index 9fd9a88..2b909b3 100644 --- a/cookbooks/windows/providers/shortcut.rb +++ b/cookbooks/windows/providers/shortcut.rb @@ -1,56 +1,58 @@ -# -# Author:: Doug MacEachern -# Cookbook Name:: windows -# Provider:: shortcut -# -# Copyright:: 2010, VMware, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -def load_current_resource - require 'win32ole' - - @link = WIN32OLE.new("WScript.Shell").CreateShortcut(@new_resource.name) - - @current_resource = Chef::Resource::WindowsShortcut.new(@new_resource.name) - @current_resource.name(@new_resource.name) - @current_resource.target(@link.TargetPath) - @current_resource.arguments(@link.Arguments) - @current_resource.description(@link.Description) - @current_resource.cwd(@link.WorkingDirectory) -end - -# Check to see if the shorcut needs any changes -# -# === Returns -# :: If a change is required -# :: If the shorcuts are identical -def compare_shortcut - [:target, :arguments, :description, :cwd].any? do |attr| - !@new_resource.send(attr).nil? && @current_resource.send(attr) != @new_resource.send(attr) - end -end - -def action_create - if compare_shortcut - @link.TargetPath = @new_resource.target if @new_resource.target != nil - @link.Arguments = @new_resource.arguments if @new_resource.arguments != nil - @link.Description = @new_resource.description if @new_resource.description != nil - @link.WorkingDirectory = @new_resource.cwd if @new_resource.cwd != nil - #ignoring: WindowStyle, Hotkey, IconLocation - @link.Save - Chef::Log.info("Added #{@new_resource} shortcut") - new_resource.updated_by_last_action(true) - end -end +# +# Author:: Doug MacEachern +# Cookbook Name:: windows +# Provider:: shortcut +# +# Copyright:: 2010, VMware, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +def load_current_resource + require 'win32ole' + + @link = WIN32OLE.new('WScript.Shell').CreateShortcut(@new_resource.name) + + @current_resource = Chef::Resource::WindowsShortcut.new(@new_resource.name) + @current_resource.name(@new_resource.name) + @current_resource.target(@link.TargetPath) + @current_resource.arguments(@link.Arguments) + @current_resource.description(@link.Description) + @current_resource.cwd(@link.WorkingDirectory) + @current_resource.iconlocation(@link.IconLocation) +end + +# Check to see if the shorcut needs any changes +# +# === Returns +# :: If a change is required +# :: If the shorcuts are identical +def compare_shortcut + [:target, :arguments, :description, :cwd, :iconlocation].any? do |attr| + !@new_resource.send(attr).nil? && @current_resource.send(attr) != @new_resource.send(attr) + end +end + +def action_create + if compare_shortcut + @link.TargetPath = @new_resource.target unless @new_resource.target.nil? + @link.Arguments = @new_resource.arguments unless @new_resource.arguments.nil? + @link.Description = @new_resource.description unless @new_resource.description.nil? + @link.WorkingDirectory = @new_resource.cwd unless @new_resource.cwd.nil? + @link.IconLocation = @new_resource.iconlocation unless @new_resource.iconlocation.nil? + # ignoring: WindowStyle, Hotkey + @link.Save + Chef::Log.info("Added #{@new_resource} shortcut") + new_resource.updated_by_last_action(true) + end +end diff --git a/cookbooks/windows/providers/task.rb b/cookbooks/windows/providers/task.rb index 24a35c0..4ecaa1c 100644 --- a/cookbooks/windows/providers/task.rb +++ b/cookbooks/windows/providers/task.rb @@ -1,167 +1,236 @@ -# -# Author:: Paul Mooring () -# Cookbook Name:: windows -# Provider:: task -# -# Copyright:: 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. -# - -require 'chef/mixin/shell_out' -include Chef::Mixin::ShellOut - -action :create do - if @current_resource.exists - Chef::Log.info "#{@new_resource} task already exists - nothing to do" - else - if @new_resource.user and @new_resource.password.nil? then Chef::Log.debug "#{@new_resource} did not specify a password, creating task without a password" end - use_force = @new_resource.force ? '/F' : '' - cmd = "schtasks /Create #{use_force} /TN \"#{@new_resource.name}\" " - schedule = @new_resource.frequency == :on_logon ? "ONLOGON" : @new_resource.frequency - cmd += "/SC #{schedule} " - cmd += "/MO #{@new_resource.frequency_modifier} " if [:minute, :hourly, :daily, :weekly, :monthly].include?(@new_resource.frequency) - cmd += "/SD \"#{@new_resource.start_day}\" " unless @new_resource.start_day.nil? - cmd += "/ST \"#{@new_resource.start_time}\" " unless @new_resource.start_time.nil? - cmd += "/TR \"#{@new_resource.command}\" " - cmd += "/RU \"#{@new_resource.user}\" " if @new_resource.user - cmd += "/RP \"#{@new_resource.password}\" " if @new_resource.user and @new_resource.password - cmd += "/RL HIGHEST " if @new_resource.run_level == :highest - shell_out!(cmd, {:returns => [0]}) - new_resource.updated_by_last_action true - Chef::Log.info "#{@new_resource} task created" - end -end - -action :run do - if @current_resource.exists - if @current_resource.status == :running - Chef::Log.info "#{@new_resource} task is currently running, skipping run" - else - cmd = "schtasks /Run /TN \"#{@current_resource.name}\"" - shell_out!(cmd, {:returns => [0]}) - new_resource.updated_by_last_action true - Chef::Log.info "#{@new_resource} task ran" - end - else - Chef::Log.debug "#{@new_resource} task doesn't exists - nothing to do" - end -end - -action :change do - if @current_resource.exists - cmd = "schtasks /Change /TN \"#{@current_resource.name}\" " - cmd += "/TR \"#{@new_resource.command}\" " if @new_resource.command - if @new_resource.user && @new_resource.password - cmd += "/RU \"#{@new_resource.user}\" /RP \"#{@new_resource.password}\" " - elsif (@new_resource.user and !@new_resource.password) || (@new_resource.password and !@new_resource.user) - Chef::Log.fatal "#{@new_resource.name}: Can't specify user or password without both!" - end - shell_out!(cmd, {:returns => [0]}) - new_resource.updated_by_last_action true - Chef::Log.info "Change #{@new_resource} task ran" - else - Chef::Log.debug "#{@new_resource} task doesn't exists - nothing to do" - end -end - -action :delete do - if @current_resource.exists - use_force = @new_resource.force ? '/F' : '' - cmd = "schtasks /Delete #{use_force} /TN \"#{@current_resource.name}\"" - shell_out!(cmd, {:returns => [0]}) - new_resource.updated_by_last_action true - Chef::Log.info "#{@new_resource} task deleted" - else - Chef::Log.debug "#{@new_resource} task doesn't exists - nothing to do" - end -end - -action :enable do - if @current_resource.exists - if @current_resource.enabled - Chef::Log.debug "#{@new_resource} already enabled - nothing to do" - else - cmd = "schtasks /Change /TN \"#{@current_resource.name}\" " - cmd += "/ENABLE" - shell_out!(cmd, {:returns => [0]}) - @new_resource.updated_by_last_action true - Chef::Log.info "#{@new_resource} task enabled" - end - else - Chef::Log.fatal "#{@new_resource} task doesn't exist - nothing to do" - raise Errno::ENOENT, "#{@new_resource}: task does not exist, cannot enable" - end -end - -action :disable do - if @current_resource.exists - if @current_resource.enabled - cmd = "schtasks /Change /TN \"#{@current_resource.name}\" " - cmd += "/DISABLE" - shell_out!(cmd, {:returns => [0]}) - @new_resource.updated_by_last_action true - Chef::Log.info "#{@new_resource} task disabled" - else - Chef::Log.debug "#{@new_resource} already disabled - nothing to do" - end - else - Chef::Log.debug "#{@new_resource} task doesn't exist - nothing to do" - end -end - - -def load_current_resource - @current_resource = Chef::Resource::WindowsTask.new(@new_resource.name) - @current_resource.name(@new_resource.name) - - task_hash = load_task_hash(@current_resource.name) - if task_hash[:TaskName] == '\\' + @new_resource.name - @current_resource.exists = true - if task_hash[:Status] == "Running" - @current_resource.status = :running - end - if task_hash[:ScheduledTaskState] == "Enabled" - @current_resource.enabled = true - end - @current_resource.cwd(task_hash[:Folder]) - @current_resource.command(task_hash[:TaskToRun]) - @current_resource.user(task_hash[:RunAsUser]) - end if task_hash.respond_to? :[] -end - -private - -def load_task_hash(task_name) - Chef::Log.debug "looking for existing tasks" - - # we use shell_out here instead of shell_out! because a failure implies that the task does not exist - output = shell_out("schtasks /Query /FO LIST /V /TN \"#{task_name}\"").stdout - if output.empty? - task = false - else - task = Hash.new - - output.split("\n").map! do |line| - line.split(":", 2).map! do |field| - field.strip - end - end.each do |field| - if field.kind_of? Array and field[0].respond_to? :to_sym - task[field[0].gsub(/\s+/,"").to_sym] = field[1] - end - end - end - - task -end +# +# Author:: Paul Mooring () +# Cookbook Name:: windows +# Provider:: task +# +# Copyright:: 2012-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/mixin/shell_out' +include Chef::Mixin::ShellOut + +use_inline_resources + +action :create do + if @current_resource.exists && (!(task_need_update? || @new_resource.force)) + Chef::Log.info "#{@new_resource} task already exists - nothing to do" + else + validate_user_and_password + validate_interactive_setting + validate_create_day + + schedule = @new_resource.frequency == :on_logon ? 'ONLOGON' : @new_resource.frequency + frequency_modifier_allowed = [:minute, :hourly, :daily, :weekly, :monthly] + options = {} + options['F'] = '' if @new_resource.force || task_need_update? + options['SC'] = schedule + options['MO'] = @new_resource.frequency_modifier if frequency_modifier_allowed.include?(@new_resource.frequency) + options['SD'] = @new_resource.start_day unless @new_resource.start_day.nil? + options['ST'] = @new_resource.start_time unless @new_resource.start_time.nil? + options['TR'] = "\"#{@new_resource.command}\" " + options['RU'] = @new_resource.user + options['RP'] = @new_resource.password if use_password? + options['RL'] = 'HIGHEST' if @new_resource.run_level == :highest + options['IT'] = '' if @new_resource.interactive_enabled + options['D'] = @new_resource.day if @new_resource.day + + run_schtasks 'CREATE', options + new_resource.updated_by_last_action true + Chef::Log.info "#{@new_resource} task created" + end +end + +action :run do + if @current_resource.exists + if @current_resource.status == :running + Chef::Log.info "#{@new_resource} task is currently running, skipping run" + else + run_schtasks 'RUN' + new_resource.updated_by_last_action true + Chef::Log.info "#{@new_resource} task ran" + end + else + Chef::Log.debug "#{@new_resource} task doesn't exists - nothing to do" + end +end + +action :change do + if @current_resource.exists + validate_user_and_password + validate_interactive_setting + + options = {} + options['TR'] = "\"#{@new_resource.command}\" " if @new_resource.command + options['RU'] = @new_resource.user if @new_resource.user + options['RP'] = @new_resource.password if @new_resource.password + options['SD'] = @new_resource.start_day unless @new_resource.start_day.nil? + options['ST'] = @new_resource.start_time unless @new_resource.start_time.nil? + options['IT'] = '' if @new_resource.interactive_enabled + + run_schtasks 'CHANGE', options + new_resource.updated_by_last_action true + Chef::Log.info "Change #{@new_resource} task ran" + else + Chef::Log.debug "#{@new_resource} task doesn't exists - nothing to do" + end +end + +action :delete do + if @current_resource.exists + # always need to force deletion + run_schtasks 'DELETE', 'F' => '' + new_resource.updated_by_last_action true + Chef::Log.info "#{@new_resource} task deleted" + else + Chef::Log.debug "#{@new_resource} task doesn't exists - nothing to do" + end +end + +action :end do + if @current_resource.exists + if @current_resource.status != :running + Chef::Log.debug "#{@new_resource} is not running - nothing to do" + else + run_schtasks 'END' + @new_resource.updated_by_last_action true + Chef::Log.info "#{@new_resource} task ended" + end + else + Chef::Log.fatal "#{@new_resource} task doesn't exist - nothing to do" + fail Errno::ENOENT, "#{@new_resource}: task does not exist, cannot end" + end +end + +action :enable do + if @current_resource.exists + if @current_resource.enabled + Chef::Log.debug "#{@new_resource} already enabled - nothing to do" + else + run_schtasks 'CHANGE', 'ENABLE' => '' + @new_resource.updated_by_last_action true + Chef::Log.info "#{@new_resource} task enabled" + end + else + Chef::Log.fatal "#{@new_resource} task doesn't exist - nothing to do" + fail Errno::ENOENT, "#{@new_resource}: task does not exist, cannot enable" + end +end + +action :disable do + if @current_resource.exists + if @current_resource.enabled + run_schtasks 'CHANGE', 'DISABLE' => '' + @new_resource.updated_by_last_action true + Chef::Log.info "#{@new_resource} task disabled" + else + Chef::Log.debug "#{@new_resource} already disabled - nothing to do" + end + else + Chef::Log.debug "#{@new_resource} task doesn't exist - nothing to do" + end +end + +def load_current_resource + @current_resource = Chef::Resource::WindowsTask.new(@new_resource.name) + @current_resource.task_name(@new_resource.task_name) + + pathed_task_name = @new_resource.task_name[0, 1] == '\\' ? @new_resource.task_name : @new_resource.task_name.prepend('\\') + task_hash = load_task_hash(@current_resource.task_name) + if task_hash[:TaskName] == pathed_task_name + @current_resource.exists = true + @current_resource.status = :running if task_hash[:Status] == 'Running' + if task_hash[:ScheduledTaskState] == 'Enabled' + @current_resource.enabled = true + end + @current_resource.cwd(task_hash[:Folder]) + @current_resource.command(task_hash[:TaskToRun]) + @current_resource.user(task_hash[:RunAsUser]) + end if task_hash.respond_to? :[] +end + +private + +def run_schtasks(task_action, options = {}) + cmd = "schtasks /#{task_action} /TN \"#{@new_resource.task_name}\" " + options.keys.each do |option| + cmd += "/#{option} #{options[option]} " + end + Chef::Log.debug('running: ') + Chef::Log.debug(" #{cmd}") + shell_out!(cmd, returns: [0]) +end + +def task_need_update? + # gsub needed as schtasks converts single quotes to double quotes on creation + @current_resource.command != @new_resource.command.tr("'", "\"") || + @current_resource.user != @new_resource.user +end + +def load_task_hash(task_name) + Chef::Log.debug 'looking for existing tasks' + + # we use shell_out here instead of shell_out! because a failure implies that the task does not exist + output = shell_out("schtasks /Query /FO LIST /V /TN \"#{task_name}\"").stdout + if output.empty? + task = false + else + task = {} + + output.split("\n").map! do |line| + line.split(':', 2).map!(&:strip) + end.each do |field| + if field.is_a?(Array) && field[0].respond_to?(:to_sym) + task[field[0].gsub(/\s+/, '').to_sym] = field[1] + end + end + end + + task +end + +SYSTEM_USERS = ['NT AUTHORITY\SYSTEM', 'SYSTEM', 'NT AUTHORITY\LOCALSERVICE', 'NT AUTHORITY\NETWORKSERVICE'] + +def validate_user_and_password + if @new_resource.user && use_password? + if @new_resource.password.nil? + Chef::Log.fatal "#{@new_resource.task_name}: Can't specify a non-system user without a password!" + end + end +end + +def validate_interactive_setting + if @new_resource.interactive_enabled && @new_resource.password.nil? + Chef::Log.fatal "#{new_resource} did not provide a password when attempting to set interactive/non-interactive." + end +end + +def validate_create_day + return unless @new_resource.day + unless [:weekly, :monthly].include?(@new_resource.frequency) + fail 'day attribute is only valid for tasks that run weekly or monthly' + end + if @new_resource.day.is_a? String + days = @new_resource.day.split(',') + days.each do |day| + unless ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun', '*'].include?(day.strip.downcase) + fail 'day attribute invalid. Only valid values are: MON, TUE, WED, THU, FRI, SAT, SUN and *. Multiple values must be separated by a comma.' + end + end + end +end + +def use_password? + @use_password ||= !SYSTEM_USERS.include?(@new_resource.user.upcase) +end diff --git a/cookbooks/windows/providers/zipfile.rb b/cookbooks/windows/providers/zipfile.rb index caa9e9c..b050725 100644 --- a/cookbooks/windows/providers/zipfile.rb +++ b/cookbooks/windows/providers/zipfile.rb @@ -1,93 +1,90 @@ -# -# Author:: Doug MacEachern () -# Author:: Seth Chisamore () -# Cookbook Name:: windows -# Provider:: zipfile -# -# Copyright:: 2010, VMware, Inc. -# Copyright:: 2011, 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 Windows::Helper - -require 'find' - -action :unzip do - ensure_rubyzip_gem_installed - Chef::Log.debug("unzip #{@new_resource.source} => #{@new_resource.path} (overwrite=#{@new_resource.overwrite})") - - Zip::File.open(cached_file(@new_resource.source, @new_resource.checksum)) 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.exists?(path) && !::File.directory?(path) - FileUtils.rm(path) - end - zip.extract(entry, path) - end - end - new_resource.updated_by_last_action(true) -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.exists?(@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.exists?(@new_resource.path) - ::File.unlink(@new_resource.path) - end - # only supporting compression of a single directory (recursively). - if ::File.directory?(@new_resource.source) - 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 - new_resource.updated_by_last_action(true) - else - Chef::Log.info("Single directory must be specified for compression, and #{@new_resource.source} does not meet that criteria.") - end - end -end - -private -def ensure_rubyzip_gem_installed - begin - require 'zip' - rescue LoadError - Chef::Log.info("Missing gem 'rubyzip'...installing now.") - chef_gem "rubyzip" do - version node['windows']['rubyzipversion'] - action :install - end - require 'zip' - end -end +# +# Author:: Doug MacEachern () +# Author:: Seth Chisamore () +# Cookbook Name:: windows +# Provider:: zipfile +# +# Copyright:: 2010, VMware, Inc. +# 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. +# + +include Windows::Helper + +require 'find' + +action :unzip do + ensure_rubyzip_gem_installed + Chef::Log.debug("unzip #{@new_resource.source} => #{@new_resource.path} (overwrite=#{@new_resource.overwrite})") + + Zip::File.open(cached_file(@new_resource.source, @new_resource.checksum)) 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) + end + end + new_resource.updated_by_last_action(true) +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. + ::File.unlink(@new_resource.path) if ::File.exist?(@new_resource.path) + # only supporting compression of a single directory (recursively). + if ::File.directory?(@new_resource.source) + 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 + new_resource.updated_by_last_action(true) + else + Chef::Log.info("Single directory must be specified for compression, and #{@new_resource.source} does not meet that criteria.") + end + end +end + +private + +def ensure_rubyzip_gem_installed + require 'zip' +rescue LoadError + Chef::Log.info("Missing gem 'rubyzip'...installing now.") + chef_gem 'rubyzip' do + version node['windows']['rubyzipversion'] + action :install + end + require 'zip' +end diff --git a/cookbooks/windows/recipes/default.rb b/cookbooks/windows/recipes/default.rb index 87e5096..4ca641e 100644 --- a/cookbooks/windows/recipes/default.rb +++ b/cookbooks/windows/recipes/default.rb @@ -1,34 +1,34 @@ -# -# Author:: Seth Chisamore () -# Cookbook Name:: windows -# Recipe:: default -# -# Copyright:: 2011, 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. -# - -# gems with precompiled binaries -%w{ win32-api win32-service }.each do |win_gem| - chef_gem win_gem do - options '--platform=mswin32' - action :install - end -end - -# the rest -%w{ windows-api windows-pr win32-dir win32-event win32-mutex }.each do |win_gem| - chef_gem win_gem do - action :install - end -end +# +# Author:: Seth Chisamore () +# Cookbook Name:: windows +# Recipe:: default +# +# 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. +# + +# gems with precompiled binaries +%w( win32-api win32-service ).each do |win_gem| + chef_gem win_gem do + options '--platform=mswin32' + action :install + end +end + +# the rest +%w( windows-api windows-pr win32-dir win32-event win32-mutex ).each do |win_gem| + chef_gem win_gem do + action :install + end +end diff --git a/cookbooks/windows/recipes/reboot_handler.rb b/cookbooks/windows/recipes/reboot_handler.rb index ee5de51..9f435b0 100644 --- a/cookbooks/windows/recipes/reboot_handler.rb +++ b/cookbooks/windows/recipes/reboot_handler.rb @@ -1,32 +1,32 @@ -# -# Author:: Seth Chisamore () -# Cookbook Name:: windows -# Recipe:: restart_handler -# -# Copyright:: 2011, 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. -# - -remote_directory node['chef_handler']['handler_path'] do - source 'handlers' - recursive true - action :create -end - -chef_handler 'WindowsRebootHandler' do - source "#{node['chef_handler']['handler_path']}/windows_reboot_handler.rb" - arguments node['windows']['allow_pending_reboots'] - supports :report => true, :exception => node['windows']['allow_reboot_on_failure'] - action :enable -end +# +# Author:: Seth Chisamore () +# Cookbook Name:: windows +# Recipe:: restart_handler +# +# 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. +# + +remote_directory node['chef_handler']['handler_path'] do + source 'handlers' + recursive true + action :create +end + +chef_handler 'WindowsRebootHandler' do + source "#{node['chef_handler']['handler_path']}/windows_reboot_handler.rb" + arguments node['windows']['allow_pending_reboots'] + supports report: true, exception: node['windows']['allow_reboot_on_failure'] + action :enable +end diff --git a/cookbooks/windows/resources/auto_run.rb b/cookbooks/windows/resources/auto_run.rb index 78a7702..ca9beaf 100644 --- a/cookbooks/windows/resources/auto_run.rb +++ b/cookbooks/windows/resources/auto_run.rb @@ -1,30 +1,30 @@ -# -# Author:: Paul Morton () -# Cookbook Name:: windows -# Resource:: auto_run -# -# Copyright:: 2011, 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. -# - -def initialize(name,run_context=nil) - super - @action = :create -end - -actions :create, :remove - -attribute :program, :kind_of => String -attribute :name, :kind_of => String, :name_attribute => true -attribute :args, :kind_of => String, :default => '' +# +# Author:: Paul Morton () +# Cookbook Name:: windows +# Resource:: auto_run +# +# Copyright:: 2011, 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. +# + +def initialize(name, run_context = nil) + super + @action = :create +end + +actions :create, :remove + +attribute :program, kind_of: String +attribute :name, kind_of: String, name_attribute: true +attribute :args, kind_of: String, default: '' diff --git a/cookbooks/windows/resources/batch.rb b/cookbooks/windows/resources/batch.rb index 4b1e6be..8fe73bd 100644 --- a/cookbooks/windows/resources/batch.rb +++ b/cookbooks/windows/resources/batch.rb @@ -1,36 +1,41 @@ -# -# Author:: Seth Chisamore () -# Cookbook Name:: windows -# Resource:: batch -# -# Copyright:: 2011, 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 :run - -attribute :command, :kind_of => String, :name_attribute => true -attribute :cwd, :kind_of => String, :default => nil -attribute :code, :kind_of => String, :default => nil -attribute :user, :kind_of => [ String, Integer ], :default => nil -attribute :group, :kind_of => [ String, Integer ], :default => nil -attribute :creates, :kind_of => [ String ], :default => nil -attribute :flags, :kind_of => [ String ], :default => nil -attribute :returns, :kind_of => [Integer, Array], :default => 0 - -def initialize(name, run_context=nil) - super - @action = :run - @command = name -end +# +# Author:: Seth Chisamore () +# Cookbook Name:: windows +# Resource:: batch +# +# 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. +# + +actions :run + +attribute :command, kind_of: String, name_attribute: true +attribute :cwd, kind_of: String, default: nil +attribute :code, kind_of: String, default: nil +attribute :user, kind_of: [String, Integer], default: nil +attribute :group, kind_of: [String, Integer], default: nil +attribute :creates, kind_of: [String], default: nil +attribute :flags, kind_of: [String], default: nil +attribute :returns, kind_of: [Integer, Array], default: 0 + +def initialize(name, run_context = nil) + super + @action = :run + @command = name + Chef::Log.warn <<-EOF +Please use the batch resource in Chef Client 11 and 12. +windows_batch will be removed in the next major version release +of the Windows cookbook. +EOF +end diff --git a/cookbooks/windows/resources/certificate.rb b/cookbooks/windows/resources/certificate.rb new file mode 100644 index 0000000..943ac1e --- /dev/null +++ b/cookbooks/windows/resources/certificate.rb @@ -0,0 +1,28 @@ +# +# Author:: Richard Lavey (richard.lavey@calastone.com) +# Cookbook Name:: windows +# Resource:: certificate +# +# 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, :acl_add +default_action :create + +attribute :source, kind_of: String, name_attribute: true, required: true +attribute :pfx_password, kind_of: String +attribute :private_key_acl, kind_of: Array +attribute :store_name, kind_of: String, default: 'MY', regex: /^(?:MY|CA|ROOT)$/ +attribute :user_store, kind_of: [TrueClass, FalseClass], default: false diff --git a/cookbooks/windows/resources/certificate_binding.rb b/cookbooks/windows/resources/certificate_binding.rb new file mode 100644 index 0000000..63c97a1 --- /dev/null +++ b/cookbooks/windows/resources/certificate_binding.rb @@ -0,0 +1,31 @@ +# +# Author:: Richard Lavey (richard.lavey@calastone.com) +# Cookbook Name:: windows +# Resource:: certificate_binding +# +# 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 :cert_name, kind_of: String, name_attribute: true, required: true +attribute :name_kind, kind_of: Symbol, equal_to: [:hash, :subject], default: :subject +attribute :address, kind_of: String, default: '0.0.0.0' +attribute :port, kind_of: Integer, default: 443 +attribute :app_id, kind_of: String, default: '{4dc3e181-e14b-4a21-b022-59fc669b0914}' +attribute :store_name, kind_of: String, default: 'MY', regex: /^(?:MY|CA|ROOT)$/ + +attr_accessor :exists diff --git a/cookbooks/windows/resources/feature.rb b/cookbooks/windows/resources/feature.rb index 4adf758..47f7340 100644 --- a/cookbooks/windows/resources/feature.rb +++ b/cookbooks/windows/resources/feature.rb @@ -1,44 +1,47 @@ -# -# Author:: Seth Chisamore () -# Cookbook Name:: windows -# Resource:: feature -# -# Copyright:: 2011, 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 Windows::Helper - -actions :install, :remove, :delete - -attribute :feature_name, :kind_of => String, :name_attribute => true -attribute :source, :kind_of => String -attribute :all, :kind_of => [ TrueClass, FalseClass ], :default => false - -def initialize(name, run_context=nil) - super - @action = :install - @provider = lookup_provider_constant(locate_default_provider) -end - -private -def locate_default_provider - if node['windows'].attribute?(:feature_provider) - "windows_feature_#{node['windows']['feature_provider']}" - elsif ::File.exists?(locate_sysnative_cmd('dism.exe')) - :windows_feature_dism - elsif ::File.exists?(locate_sysnative_cmd('servermanagercmd.exe')) - :windows_feature_servermanagercmd - end -end +# +# Author:: Seth Chisamore () +# Cookbook Name:: windows +# Resource:: feature +# +# 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. +# + +include Windows::Helper + +actions :install, :remove, :delete + +attribute :feature_name, kind_of: String, name_attribute: true +attribute :source, kind_of: String +attribute :all, kind_of: [TrueClass, FalseClass], default: false + +def initialize(name, run_context = nil) + super + @action = :install + @provider = lookup_provider_constant(locate_default_provider) +end + +private + +def locate_default_provider + if node['windows'].attribute?(:feature_provider) + "windows_feature_#{node['windows']['feature_provider']}" + elsif ::File.exist?(locate_sysnative_cmd('dism.exe')) + :windows_feature_dism + elsif ::File.exist?(locate_sysnative_cmd('servermanagercmd.exe')) + :windows_feature_servermanagercmd + else + :windows_feature_powershell + end +end diff --git a/cookbooks/windows/resources/font.rb b/cookbooks/windows/resources/font.rb index 57c73f0..f930db4 100644 --- a/cookbooks/windows/resources/font.rb +++ b/cookbooks/windows/resources/font.rb @@ -1,25 +1,25 @@ -# -# Author:: Sander Botman -# Cookbook Name:: windows -# Resource:: font -# -# Copyright:: 2014, Schuberg Philis BV. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT 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 :install - -default_action :install - -attribute :file, :kind_of => String, :name_attribute => true +# +# Author:: Sander Botman +# Cookbook Name:: windows +# Resource:: font +# +# Copyright:: 2014, Schuberg Philis BV. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 :install + +default_action :install + +attribute :file, kind_of: String, name_attribute: true diff --git a/cookbooks/windows/resources/http_acl.rb b/cookbooks/windows/resources/http_acl.rb new file mode 100644 index 0000000..2a20126 --- /dev/null +++ b/cookbooks/windows/resources/http_acl.rb @@ -0,0 +1,27 @@ +# +# Author:: Richard Lavey (richard.lavey@calastone.com) +# Cookbook Name:: windows +# Resource:: http_acl +# +# 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 :url, kind_of: String, name_attribute: true, required: true +attribute :user, kind_of: String + +attr_accessor :exists diff --git a/cookbooks/windows/resources/pagefile.rb b/cookbooks/windows/resources/pagefile.rb index 4f488dc..d0ca6e3 100644 --- a/cookbooks/windows/resources/pagefile.rb +++ b/cookbooks/windows/resources/pagefile.rb @@ -1,29 +1,29 @@ -# -# Author:: Kevin Moser () -# Cookbook Name:: windows -# Resource:: pagefile -# -# 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. -# - -actions :set, :delete - -attribute :name, :kind_of => String, :name_attribute => true -attribute :system_managed, :kind_of => [TrueClass, FalseClass] -attribute :automatic_managed, :kind_of => [TrueClass, FalseClass], :default => false -attribute :initial_size, :kind_of => Integer -attribute :maximum_size, :kind_of => Integer - -default_action :set +# +# Author:: Kevin Moser () +# Cookbook Name:: windows +# Resource:: pagefile +# +# 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. +# + +actions :set, :delete + +attribute :name, kind_of: String, name_attribute: true +attribute :system_managed, kind_of: [TrueClass, FalseClass] +attribute :automatic_managed, kind_of: [TrueClass, FalseClass], default: false +attribute :initial_size, kind_of: Integer +attribute :maximum_size, kind_of: Integer + +default_action :set diff --git a/cookbooks/windows/resources/path.rb b/cookbooks/windows/resources/path.rb index 84f5523..a496c03 100644 --- a/cookbooks/windows/resources/path.rb +++ b/cookbooks/windows/resources/path.rb @@ -1,28 +1,28 @@ -# -# Author:: Paul Morton () -# Cookbook Name:: windows -# Resource:: path -# -# Copyright:: 2011, 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. -# - -def initialize(name,run_context=nil) - super - @action = :add -end - -actions :add, :remove - -attribute :path, :kind_of => String, :name_attribute => true +# +# Author:: Paul Morton () +# Cookbook Name:: windows +# Resource:: path +# +# Copyright:: 2011, 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. +# + +def initialize(name, run_context = nil) + super + @action = :add +end + +actions :add, :remove + +attribute :path, kind_of: String, name_attribute: true diff --git a/cookbooks/windows/resources/printer.rb b/cookbooks/windows/resources/printer.rb index 5effa33..2555660 100644 --- a/cookbooks/windows/resources/printer.rb +++ b/cookbooks/windows/resources/printer.rb @@ -1,41 +1,41 @@ -# -# Author:: Doug Ireton () -# Cookbook Name:: windows -# Resource:: printer -# -# 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. -# -# See here for more info: -# http://msdn.microsoft.com/en-us/library/windows/desktop/aa394492(v=vs.85).aspx - -require 'resolv' - -actions :create, :delete - -default_action :create - -attribute :device_id, :kind_of => String, :name_attribute => true, - :required => true -attribute :comment, :kind_of => String - -attribute :default, :kind_of => [ TrueClass, FalseClass ], :default => false -attribute :driver_name, :kind_of => String, :required => true -attribute :location, :kind_of => String -attribute :shared, :kind_of => [ TrueClass, FalseClass ], :default => false -attribute :share_name, :kind_of => String - -attribute :ipv4_address, :kind_of => String, :regex => Resolv::IPv4::Regex - -attr_accessor :exists +# +# Author:: Doug Ireton () +# Cookbook Name:: windows +# Resource:: printer +# +# 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. +# +# See here for more info: +# http://msdn.microsoft.com/en-us/library/windows/desktop/aa394492(v=vs.85).aspx + +require 'resolv' + +actions :create, :delete + +default_action :create + +attribute :device_id, kind_of: String, name_attribute: true, + required: true +attribute :comment, kind_of: String + +attribute :default, kind_of: [TrueClass, FalseClass], default: false +attribute :driver_name, kind_of: String, required: true +attribute :location, kind_of: String +attribute :shared, kind_of: [TrueClass, FalseClass], default: false +attribute :share_name, kind_of: String + +attribute :ipv4_address, kind_of: String, regex: Resolv::IPv4::Regex + +attr_accessor :exists diff --git a/cookbooks/windows/resources/printer_port.rb b/cookbooks/windows/resources/printer_port.rb index b79a6fc..70eff93 100644 --- a/cookbooks/windows/resources/printer_port.rb +++ b/cookbooks/windows/resources/printer_port.rb @@ -1,40 +1,40 @@ -# -# Author:: Doug Ireton () -# Cookbook Name:: windows -# Resource:: printer_port -# -# 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. -# -# See here for more info: -# http://msdn.microsoft.com/en-us/library/windows/desktop/aa394492(v=vs.85).aspx - -require 'resolv' - -actions :create, :delete - -default_action :create - -attribute :ipv4_address, :name_attribute => true, :kind_of => String, - :required => true, :regex => Resolv::IPv4::Regex - -attribute :port_name , :kind_of => String -attribute :port_number , :kind_of => Fixnum, :default => 9100 -attribute :port_description, :kind_of => String -attribute :snmp_enabled , :kind_of => [ TrueClass, FalseClass ], - :default => false - -attribute :port_protocol, :kind_of => Fixnum, :default => 1, :equal_to => [1, 2] - -attr_accessor :exists +# +# Author:: Doug Ireton () +# Cookbook Name:: windows +# Resource:: printer_port +# +# 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. +# +# See here for more info: +# http://msdn.microsoft.com/en-us/library/windows/desktop/aa394492(v=vs.85).aspx + +require 'resolv' + +actions :create, :delete + +default_action :create + +attribute :ipv4_address, name_attribute: true, kind_of: String, + required: true, regex: Resolv::IPv4::Regex + +attribute :port_name, kind_of: String +attribute :port_number, kind_of: Fixnum, default: 9100 +attribute :port_description, kind_of: String +attribute :snmp_enabled, kind_of: [TrueClass, FalseClass], + default: false + +attribute :port_protocol, kind_of: Fixnum, default: 1, equal_to: [1, 2] + +attr_accessor :exists diff --git a/cookbooks/windows/resources/reboot.rb b/cookbooks/windows/resources/reboot.rb index 014e201..af1eeb1 100644 --- a/cookbooks/windows/resources/reboot.rb +++ b/cookbooks/windows/resources/reboot.rb @@ -1,29 +1,34 @@ -# -# Author:: Seth Chisamore () -# Cookbook Name:: windows -# Resource:: reboot -# -# Copyright:: 2011, 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 :request, :cancel - -attribute :timeout, :kind_of => Integer, :name_attribute => true -attribute :reason, :kind_of => String, :default => '' - -def initialize(name,run_context=nil) - super - @action = :request -end +# +# Author:: Seth Chisamore () +# Cookbook Name:: windows +# Resource:: reboot +# +# 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. +# + +actions :request, :cancel + +attribute :timeout, kind_of: Integer, name_attribute: true +attribute :reason, kind_of: String, default: 'Chef client run' + +def initialize(name, run_context = nil) + super + @action = :request + Chef::Log.warn <<-EOF +The windows_reboot resource is deprecated. Please use the reboot resource in +Chef Client 12. windows_reboot will be removed in the next major version +release of the Windows cookbook. +EOF +end diff --git a/cookbooks/windows/resources/registry.rb b/cookbooks/windows/resources/registry.rb index ffe6cf2..1d1b3f3 100644 --- a/cookbooks/windows/resources/registry.rb +++ b/cookbooks/windows/resources/registry.rb @@ -1,34 +1,38 @@ -# -# Author:: Doug MacEachern () -# Author:: Seth Chisamore () -# Cookbook Name:: windows -# Resource:: registry -# -# Copyright:: 2010, VMware, Inc. -# Copyright:: 2011, 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 :create, :modify, :force_modify, :remove - -attribute :key_name, :kind_of => String, :name_attribute => true -attribute :values, :kind_of => Hash -attribute :type, :kind_of => Symbol, :default => nil, :equal_to => [:binary, :string, :multi_string, :expand_string, :dword, :dword_big_endian, :qword] - -def initialize(name, run_context=nil) - super - @action = :modify - @key_name = name - Chef::Log.warn("Please use the registry_key resource in Chef Client 11. The windows_registry LWRP is still supported for Chef Client 10, but is deprecated in future versions.") -end +# +# Author:: Doug MacEachern () +# Author:: Seth Chisamore () +# Cookbook Name:: windows +# Resource:: registry +# +# Copyright:: 2010, VMware, Inc. +# 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. +# + +actions :create, :modify, :force_modify, :remove + +attribute :key_name, kind_of: String, name_attribute: true +attribute :values, kind_of: Hash +attribute :type, kind_of: Symbol, default: nil, equal_to: [:binary, :string, :multi_string, :expand_string, :dword, :dword_big_endian, :qword] + +def initialize(name, run_context = nil) + super + @action = :modify + @key_name = name + Chef::Log.warn <<-EOF +Please use the registry_key resource in Chef Client 11 and 12. +windows_registry will be removed in the next major version release +of the Windows cookbook. +EOF +end diff --git a/cookbooks/windows/resources/shortcut.rb b/cookbooks/windows/resources/shortcut.rb index eb6268b..6b8b646 100644 --- a/cookbooks/windows/resources/shortcut.rb +++ b/cookbooks/windows/resources/shortcut.rb @@ -1,35 +1,36 @@ -# -# Author:: Doug MacEachern -# Cookbook Name:: windows -# Resource:: shortcut -# -# Copyright:: 2010, VMware, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT 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 - -default_action :create - -attribute :name, :kind_of => String -attribute :target, :kind_of => String -attribute :arguments, :kind_of => String -attribute :description, :kind_of => String -attribute :cwd, :kind_of => String - -# Covers 0.10.8 and earlier -def initialize(*args) - super - @action = :create -end +# +# Author:: Doug MacEachern +# Cookbook Name:: windows +# Resource:: shortcut +# +# Copyright:: 2010, VMware, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 + +default_action :create + +attribute :name, kind_of: String +attribute :target, kind_of: String +attribute :arguments, kind_of: String +attribute :description, kind_of: String +attribute :cwd, kind_of: String +attribute :iconlocation, kind_of: String + +# Covers 0.10.8 and earlier +def initialize(*args) + super + @action = :create +end diff --git a/cookbooks/windows/resources/task.rb b/cookbooks/windows/resources/task.rb index fa1fab4..81723cb 100644 --- a/cookbooks/windows/resources/task.rb +++ b/cookbooks/windows/resources/task.rb @@ -1,50 +1,52 @@ -# -# Author:: Paul Mooring () -# Cookbook Name:: windows -# Resource:: task -# -# Copyright:: 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. -# - -# Passwords can't be loaded for existing tasks, making :modify both confusing -# and not very useful -actions :create, :delete, :run, :change, :enable, :disable - -attribute :name, :kind_of => String, :name_attribute => true, :regex => [ /\A[^\\\/\:\*\?\<\>\|]+\z/ ] -attribute :command, :kind_of => String -attribute :cwd, :kind_of => String -attribute :user, :kind_of => String, :default => nil -attribute :password, :kind_of => String, :default => nil -attribute :run_level, :equal_to => [:highest, :limited], :default => :limited -attribute :force, :kind_of => [ TrueClass, FalseClass ], :default => false -attribute :frequency_modifier, :kind_of => Integer, :default => 1 -attribute :frequency, :equal_to => [:minute, - :hourly, - :daily, - :weekly, - :monthly, - :once, - :on_logon, - :onstart, - :on_idle], :default => :hourly -attribute :start_day, :kind_of => String, :default => nil -attribute :start_time, :kind_of => String, :default => nil - -attr_accessor :exists, :status, :enabled - -def initialize(name, run_context=nil) - super - @action = :create -end +# +# Author:: Paul Mooring () +# Cookbook Name:: windows +# Resource:: task +# +# Copyright:: 2012-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. +# + +# Passwords can't be loaded for existing tasks, making :modify both confusing +# and not very useful +actions :create, :delete, :run, :end, :change, :enable, :disable + +attribute :task_name, kind_of: String, name_attribute: true, regex: [/\A[^\/\:\*\?\<\>\|]+\z/] +attribute :command, kind_of: String +attribute :cwd, kind_of: String +attribute :user, kind_of: String, default: 'SYSTEM' +attribute :password, kind_of: String, default: nil +attribute :run_level, equal_to: [:highest, :limited], default: :limited +attribute :force, kind_of: [TrueClass, FalseClass], default: false +attribute :interactive_enabled, kind_of: [TrueClass, FalseClass], default: false +attribute :frequency_modifier, kind_of: Integer, default: 1 +attribute :frequency, equal_to: [:minute, + :hourly, + :daily, + :weekly, + :monthly, + :once, + :on_logon, + :onstart, + :on_idle], default: :hourly +attribute :start_day, kind_of: String, default: nil +attribute :start_time, kind_of: String, default: nil +attribute :day, kind_of: [String, Integer], default: nil + +attr_accessor :exists, :status, :enabled + +def initialize(name, run_context = nil) + super + @action = :create +end diff --git a/cookbooks/windows/resources/zipfile.rb b/cookbooks/windows/resources/zipfile.rb index 3a802ae..f1af3b3 100644 --- a/cookbooks/windows/resources/zipfile.rb +++ b/cookbooks/windows/resources/zipfile.rb @@ -1,33 +1,33 @@ -# -# Author:: Doug MacEachern () -# Author:: Seth Chisamore () -# Cookbook Name:: windows -# Resource:: zipfile -# -# Copyright:: 2010, VMware, Inc. -# Copyright:: 2011, 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 :unzip, :zip - -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 - -def initialize(name, run_context=nil) - super - @action = :unzip -end +# +# Author:: Doug MacEachern () +# Author:: Seth Chisamore () +# Cookbook Name:: windows +# Resource:: zipfile +# +# Copyright:: 2010, VMware, Inc. +# 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. +# + +actions :unzip, :zip + +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 + +def initialize(name, run_context = nil) + super + @action = :unzip +end diff --git a/cookbooks/wordpress/CHANGELOG.md b/cookbooks/wordpress/CHANGELOG.md new file mode 100644 index 0000000..69f331b --- /dev/null +++ b/cookbooks/wordpress/CHANGELOG.md @@ -0,0 +1,93 @@ +CHANGELOG + +v3.0.0 (2015-02-24) +------------------- +* Cookbook updated to support the MySQL 6.0 community cookbook +* Added selinux as a dependency to resolve MySQL installation issues on CentOS +* Adjustments made to Nginx/PHP-FPM configuration to work out of the box with CentOS +* Added attribute to allow for additional WordPress configuration options +* Updated bats tests to work when testing WordPress version 4+ and <4 +* Removed testing for Ubuntu 10.04 due to fast approaching EOL and bugs in several cookbooks WordPress depends on. + +v2.1.5 (2014-06-28) +------------------- +* Recipe added to support installation with nginx + +v2.1.2 (2014-04-03) +------------------- +* Fixes issue where `mysql::ruby` recipe was removed in v5 of community cookbook + +v2.1.0 (2014-02-27) +------------------- +[COOK-4354] s/Wordpress/WordPress/g in docs +[COOK-4356] Gets WordPress to be extracted to the proper directory +[COOK-4191] WordPress table_prefix not configured when node['wordpress']['db']['prefix'] is set +[COOK-4192] Add attribute to control WordPress multisite features +[COOK-4366] apache2 port parameter + + +v2.0.0 (2014-02-27) +------------------- +[COOK-4180] leverage the database cookbook + + +v1.3.2 (2014-01-23) +------------------- +* [COOK-4248] - use "no_managed_code" when setting up WordPress Pool on Windows +* [COOK-4170] - Wordpress tarball contains a wordpress subdirectory, causing "extract-wordpress" to execute every run and the WP URL to be http://hostname/wordpress/ + + +v1.3.0 +------ +### Bug +- **[COOK-3478](https://tickets.opscode.com/browse/COOK-3478)** - Windows support for Wordpress + + +v1.2.0 +------ +### New Feature +- **[COOK-3321](https://tickets.opscode.com/browse/COOK-3321)** - Add languages recipe + +### Improvement +- **[COOK-3311](https://tickets.opscode.com/browse/COOK-3311)** - Remove legacy Test Kitchen, Add Travis CI + + +v1.1.0 +------ +- Added Test Kitchen 1.0 + +Bug Fixes: +- [COOK-1393]: wordpress recipe should use mysql::ruby to ensure ruby extension is installed +- [COOK-2984]: wordpress cookbook has foodcritic failures + +Improvements: +- [COOK-2661]: Allow downloads from other repos for wordpress install + +v1.0.0: +------- +- [COOK-1127] - update defaults to latest version +- [COOK-1222] - support installing "latest" version +- [COOK-1271] - Wordpress cookbook generates new password on every chef run + +v0.8.8 +------ +- [COOK-826] - recipe doesn't quote password string + +v0.8.6 +------ +- [COOK-534] - allow server_aliases to overridden by an attribute +- [COOK-799] - fixed disables .htaccess breaking permalink feature +- [COOK-820] - guard node.save with check for chef-solo in our cookbooks + +v0.8.4 +------ +- [COOK-406] - wp-config.php.erb has wrong CRLF encoding +- Dropping explicit support for Red Hat platforms due to issues in php and mysql cookbooks (COOK-603, COOK-672, COOK-816, COOK-679) + +v0.8.2 +------ +- [COOK-435] Don't set the mysql root user password in wordpress cookbook +- [COOK-535] - recursively create the directory +- RHEL/CentOS/Fedora support (yeah!) +- cleaned up node attribute keys +- cleaned up README.md diff --git a/cookbooks/wordpress/README.md b/cookbooks/wordpress/README.md new file mode 100644 index 0000000..1a99f24 --- /dev/null +++ b/cookbooks/wordpress/README.md @@ -0,0 +1,98 @@ +[![Build Status](https://travis-ci.org/brint/wordpress-cookbook.svg?branch=master)](https://travis-ci.org/brint/wordpress-cookbook) +[![Dependency Status](https://gemnasium.com/brint/wordpress-cookbook.svg)](https://gemnasium.com/brint/wordpress-cookbook) + +Description +=========== + +The Chef WordPress cookbook installs and configures WordPress according to the instructions at http://codex.wordpress.org/Installing_WordPress. + +Description +=========== + +This cookbook does not set up the WordPress blog. You will need to do this manually by going to http://hostname/wp-admin/install.php (this URL may be different if you change the attribute values). + +Requirements +============ + +Platform +-------- + +* Ubuntu 12.04, 14.04 +* RHEL/CentOS 5, 6 +* Windows + +Cookbooks +--------- + +* mysql +* mysql_chef_gem +* php +* apache2 +* iis +* windows +* openssl (uses library to generate secure passwords) +* selinux (used to disable selinux for MySQL on RHEL-based systems) + +Attributes +========== + +### WordPress + +* `node['wordpress']['version']` - Version of WordPress to download. Use 'latest' to download most recent version. +* `node['wordpress']['parent_dir']` - Parent directory to where WordPress will be extracted. (Windows Only) +* `node['wordpress']['dir']` - Location to place WordPress files. +* `node['wordpress']['db']['root_password']` - Root password for MySQL (added for support with community cookbook version 6+) +* `node['wordpress']['db']['instance_name']` - Name of the MySQL instance to use with MySQL (community cookbook version 6+) +* `node['wordpress']['db']['name']` - Name of the WordPress MySQL database. +* `node['wordpress']['db']['user']` - Name of the WordPress MySQL user. +* `node['wordpress']['db']['pass']` - Password of the WordPress MySQL user. By default, generated using openssl cookbook. +* `node['wordpress']['db']['prefix']` - Prefix of all MySQL tables created by WordPress. +* `node['wordpress']['db']['host']` - Host of the WordPress MySQL database. +* `node['wordpress']['db']['port']` - Port of the WordPress MySQL database. +* `node['wordpress']['db']['charset']` - [Character set](http://dev.mysql.com/doc/refman/5.7/en/charset-charsets.html) of the WordPress MySQL database tables. Defaults to 'utf8'. +* `node['wordpress']['db']['collate']` - [Collation](http://dev.mysql.com/doc/refman/5.7/en/charset-collation-effect.html) of the WordPress MySQL database tables. +* `node['wordpress']['db']['mysql_version']` - Version of MySQL to install (for supporting community cookbook version 6+) + +* `node['wordpress']['allow_multisite']` - Enable [multisite](http://codex.wordpress.org/Create_A_Network) features (default: false). +* `node['wordpress']['wp_config_options']` - A hash of options to define in wp_config.php, output as key value pairs into a PHP constant e.g. `define( '<%= @key %>', <%= @value %> );`. Note: for values you will need to add single quotes around text but omit them for booleans and numbers. (default: {}). +* `node['wordpress']['config_perms']` - Permissions to set for a site's wp-config.php. +* `node['wordpress']['server_aliases']` - Aliases to use when setting up Virtual Host with Nginx or Apache +* `node['wordpress']['server_port']` - Port to use when setting up the Virtual Host with Nginx or Apache + +* `node['wordpress']['install']['user']` - Install user used for WordPress file permissions and the PHP-FPM user (if applicable) +* `node['wordpress']['install']['group']` - Install group used for WordPress file permissions and the PHP-FPM group (if necessary) + +* `node['wordpress']['parent_dir']` - Parent directory of where WordPress will be installed. This is used in the Windows installation to determine where the .zip will be downloaded to. +* `node['wordpress']['dir']` - Path where WordPress should be installed +* `node['wordpress']['url']` - URL to the zip or tarball installer of WordPress +* `node['wordpress']['server_name']` - Hostname used for setting up the Virtual Host configuration for your WordPress site + +* `node['wordpress']['php_options']` - Additional PHP settings for the installation. + +Usage +===== + +Add the "wordpress" recipe to your node's run list or role, or include the recipe in another cookbook. + +License and Author +================== + +* Author:: Barry Steinglass (barry@opscode.com) +* Author:: Joshua Timberman (joshua@opscode.com) +* Author:: Seth Chisamore (schisamo@opscode.com) +* Author:: Lucas Hansen (lucash@opscode.com) +* Author:: Julian C. Dunn (jdunn@getchef.com) + +Copyright:: 2010-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. diff --git a/cookbooks/wordpress/attributes/default.rb b/cookbooks/wordpress/attributes/default.rb new file mode 100644 index 0000000..c122fa4 --- /dev/null +++ b/cookbooks/wordpress/attributes/default.rb @@ -0,0 +1,103 @@ +# +# Author:: Barry Steinglass () +# Author:: Koseki Kengo () +# Author:: Lucas Hansen () +# Author:: Julian C. Dunn () +# +# Cookbook Name:: wordpress +# Attributes:: wordpress +# +# Copyright 2009-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. +# + +# General settings +default['wordpress']['version'] = 'latest' + +default['wordpress']['db']['root_password'] = 'my_root_password' +default['wordpress']['db']['instance_name'] = 'default' +default['wordpress']['db']['name'] = "wordpressdb" +default['wordpress']['db']['user'] = "wordpressuser" +default['wordpress']['db']['pass'] = nil +default['wordpress']['db']['prefix'] = 'wp_' +default['wordpress']['db']['host'] = 'localhost' +default['wordpress']['db']['port'] = '3306' # Must be a string +default['wordpress']['db']['charset'] = 'utf8' +default['wordpress']['db']['collate'] = '' +case node['platform'] +when 'ubuntu' + case node['platform_version'] + when '10.04' + default['wordpress']['db']['mysql_version'] = '5.1' + else + default['wordpress']['db']['mysql_version'] = '5.5' + end +when 'centos', 'redhat' + if node['platform_version'].to_i < 6 + default['wordpress']['db']['mysql_version'] = '5.0' + elsif node['platform_version'].to_i < 7 + default['wordpress']['db']['mysql_version'] = '5.1' + else + default['wordpress']['db']['mysql_version'] = '5.5' + end +else + default['wordpress']['db']['mysql_version'] = '5.5' +end + +default['wordpress']['allow_multisite'] = false + +default['wordpress']['wp_config_options'] = {} + +default['wordpress']['config_perms'] = 0644 +default['wordpress']['server_aliases'] = [node['fqdn']] +default['wordpress']['server_port'] = '80' + +default['wordpress']['install']['user'] = node['apache']['user'] +default['wordpress']['install']['group'] = node['apache']['group'] + +# Languages +default['wordpress']['languages']['lang'] = '' +default['wordpress']['languages']['version'] = '' +default['wordpress']['languages']['repourl'] = 'http://translate.wordpress.org/projects/wp' +default['wordpress']['languages']['projects'] = ['main', 'admin', 'admin_network', 'continents_cities'] +default['wordpress']['languages']['themes'] = [] +default['wordpress']['languages']['project_pathes'] = { + 'main' => '/', + 'admin' => '/admin/', + 'admin_network' => '/admin/network/', + 'continents_cities' => '/cc/' +} +%w{ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty}.each do |year| + default['wordpress']['languages']['project_pathes']["twenty#{year}"] = "/twenty#{year}/" +end +node['wordpress']['languages']['project_pathes'].each do |project,project_path| + # http://translate.wordpress.org/projects/wp/3.5.x/admin/network/ja/default/export-translations?format=mo + default['wordpress']['languages']['urls'][project] = + node['wordpress']['languages']['repourl'] + '/' + + node['wordpress']['languages']['version'] + project_path + + node['wordpress']['languages']['lang'] + '/default/export-translations?format=mo' +end + +if node['platform'] == 'windows' + default['wordpress']['parent_dir'] = "#{ENV['SystemDrive']}\\inetpub" + default['wordpress']['dir'] = "#{node['wordpress']['parent_dir']}\\wordpress" + default['wordpress']['url'] = "https://wordpress.org/wordpress-#{node['wordpress']['version']}.zip" +else + default['wordpress']['server_name'] = node['fqdn'] + default['wordpress']['parent_dir'] = '/var/www' + default['wordpress']['dir'] = "#{node['wordpress']['parent_dir']}/wordpress" + default['wordpress']['url'] = "https://wordpress.org/wordpress-#{node['wordpress']['version']}.tar.gz" +end + +default['wordpress']['php_options'] = { 'php_admin_value[upload_max_filesize]' => '50M', 'php_admin_value[post_max_size]' => '55M' } diff --git a/cookbooks/wordpress/libraries/helpers.rb b/cookbooks/wordpress/libraries/helpers.rb new file mode 100644 index 0000000..ce6e3fb --- /dev/null +++ b/cookbooks/wordpress/libraries/helpers.rb @@ -0,0 +1,38 @@ +# +# Cookbook Name:: wordpress +# Library:: helpers +# Author:: Yvo van Doorn +# Author:: Julian C. Dunn +# +# 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. +# + +module Wordpress + module Helpers + def is_local_host?(host) + if host == 'localhost' || host == '127.0.0.1' || host == '::1' + true + else + require 'socket' + require 'resolv' + Socket.ip_address_list.map { |a| a.ip_address }.include? Resolv.getaddress host + end + end + + def self.make_db_query(user, pass, query) + %< --user=#{user} --password="#{pass}" --execute="#{query}"> + end + end +end diff --git a/cookbooks/wordpress/metadata.json b/cookbooks/wordpress/metadata.json new file mode 100644 index 0000000..e8ca9f7 --- /dev/null +++ b/cookbooks/wordpress/metadata.json @@ -0,0 +1,126 @@ +{ + "name": "wordpress", + "version": "3.0.0", + "description": "Installs/Configures WordPress", + "long_description": "[![Build Status](https://travis-ci.org/brint/wordpress-cookbook.svg?branch=master)](https://travis-ci.org/brint/wordpress-cookbook)\n[![Dependency Status](https://gemnasium.com/brint/wordpress-cookbook.svg)](https://gemnasium.com/brint/wordpress-cookbook)\n\nDescription\n===========\n\nThe Chef WordPress cookbook installs and configures WordPress according to the instructions at http://codex.wordpress.org/Installing_WordPress.\n\nDescription\n===========\n\nThis cookbook does not set up the WordPress blog. You will need to do this manually by going to http://hostname/wp-admin/install.php (this URL may be different if you change the attribute values).\n\nRequirements\n============\n\nPlatform\n--------\n\n* Ubuntu 12.04, 14.04\n* RHEL/CentOS 5, 6\n* Windows\n\nCookbooks\n---------\n\n* mysql\n* mysql_chef_gem\n* php\n* apache2\n* iis\n* windows\n* openssl (uses library to generate secure passwords)\n* selinux (used to disable selinux for MySQL on RHEL-based systems)\n\nAttributes\n==========\n\n### WordPress\n\n* `node['wordpress']['version']` - Version of WordPress to download. Use 'latest' to download most recent version.\n* `node['wordpress']['parent_dir']` - Parent directory to where WordPress will be extracted. (Windows Only)\n* `node['wordpress']['dir']` - Location to place WordPress files.\n* `node['wordpress']['db']['root_password']` - Root password for MySQL (added for support with community cookbook version 6+)\n* `node['wordpress']['db']['instance_name']` - Name of the MySQL instance to use with MySQL (community cookbook version 6+)\n* `node['wordpress']['db']['name']` - Name of the WordPress MySQL database.\n* `node['wordpress']['db']['user']` - Name of the WordPress MySQL user.\n* `node['wordpress']['db']['pass']` - Password of the WordPress MySQL user. By default, generated using openssl cookbook.\n* `node['wordpress']['db']['prefix']` - Prefix of all MySQL tables created by WordPress.\n* `node['wordpress']['db']['host']` - Host of the WordPress MySQL database.\n* `node['wordpress']['db']['port']` - Port of the WordPress MySQL database.\n* `node['wordpress']['db']['charset']` - [Character set](http://dev.mysql.com/doc/refman/5.7/en/charset-charsets.html) of the WordPress MySQL database tables. Defaults to 'utf8'.\n* `node['wordpress']['db']['collate']` - [Collation](http://dev.mysql.com/doc/refman/5.7/en/charset-collation-effect.html) of the WordPress MySQL database tables.\n* `node['wordpress']['db']['mysql_version']` - Version of MySQL to install (for supporting community cookbook version 6+)\n\n* `node['wordpress']['allow_multisite']` - Enable [multisite](http://codex.wordpress.org/Create_A_Network) features (default: false).\n* `node['wordpress']['wp_config_options']` - A hash of options to define in wp_config.php, output as key value pairs into a PHP constant e.g. `define( '<%= @key %>', <%= @value %> );`. Note: for values you will need to add single quotes around text but omit them for booleans and numbers. (default: {}).\n* `node['wordpress']['config_perms']` - Permissions to set for a site's wp-config.php.\n* `node['wordpress']['server_aliases']` - Aliases to use when setting up Virtual Host with Nginx or Apache\n* `node['wordpress']['server_port']` - Port to use when setting up the Virtual Host with Nginx or Apache\n\n* `node['wordpress']['install']['user']` - Install user used for WordPress file permissions and the PHP-FPM user (if applicable)\n* `node['wordpress']['install']['group']` - Install group used for WordPress file permissions and the PHP-FPM group (if necessary)\n\n* `node['wordpress']['parent_dir']` - Parent directory of where WordPress will be installed. This is used in the Windows installation to determine where the .zip will be downloaded to.\n* `node['wordpress']['dir']` - Path where WordPress should be installed\n* `node['wordpress']['url']` - URL to the zip or tarball installer of WordPress\n* `node['wordpress']['server_name']` - Hostname used for setting up the Virtual Host configuration for your WordPress site\n\n* `node['wordpress']['php_options']` - Additional PHP settings for the installation.\n\nUsage\n=====\n\nAdd the \"wordpress\" recipe to your node's run list or role, or include the recipe in another cookbook.\n\nLicense and Author\n==================\n\n* Author:: Barry Steinglass (barry@opscode.com)\n* Author:: Joshua Timberman (joshua@opscode.com)\n* Author:: Seth Chisamore (schisamo@opscode.com)\n* Author:: Lucas Hansen (lucash@opscode.com)\n* Author:: Julian C. Dunn (jdunn@getchef.com)\n\nCopyright:: 2010-2013, 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", + "maintainer": "Brint O'Hearn", + "maintainer_email": "cookbooks@opscode.com", + "license": "Apache 2.0", + "platforms": { + "debian": ">= 0.0.0", + "ubuntu": ">= 0.0.0", + "windows": ">= 0.0.0", + "centos": ">= 0.0.0", + "redhat": ">= 0.0.0", + "scientific": ">= 0.0.0", + "oracle": ">= 0.0.0" + }, + "dependencies": { + "php": ">= 0.0.0", + "openssl": ">= 0.0.0", + "apache2": ">= 2.0.0", + "database": ">= 1.6.0", + "mysql": ">= 6.0", + "mysql2_chef_gem": "~> 1.0.1", + "build-essential": ">= 0.0.0", + "iis": ">= 1.6.2", + "tar": ">= 0.3.1", + "nginx": "~> 2.7.4", + "php-fpm": "~> 0.6.10", + "selinux": "~> 0.7" + }, + "recommendations": { + }, + "suggestions": { + }, + "conflicting": { + }, + "providing": { + }, + "replacing": { + }, + "attributes": { + "WordPress/version": { + "display_name": "WordPress download version", + "description": "Version of WordPress to download from the WordPress site or 'latest' for the current release.", + "default": "latest" + }, + "WordPress/checksum": { + "display_name": "WordPress tarball checksum", + "description": "Checksum of the tarball for the version specified.", + "default": "" + }, + "WordPress/dir": { + "display_name": "WordPress installation directory", + "description": "Location to place WordPress files.", + "default": "/var/www/wordpress" + }, + "WordPress/db/database": { + "display_name": "WordPress MySQL database", + "description": "WordPress will use this MySQL database to store its data.", + "default": "wordpressdb" + }, + "WordPress/db/user": { + "display_name": "WordPress MySQL user", + "description": "WordPress will connect to MySQL using this user.", + "default": "wordpressuser" + }, + "WordPress/db/password": { + "display_name": "WordPress MySQL password", + "description": "Password for the WordPress MySQL user.", + "default": "randomly generated" + }, + "WordPress/keys/auth": { + "display_name": "WordPress auth key", + "description": "WordPress auth key.", + "default": "randomly generated" + }, + "WordPress/keys/secure_auth": { + "display_name": "WordPress secure auth key", + "description": "WordPress secure auth key.", + "default": "randomly generated" + }, + "WordPress/keys/logged_in": { + "display_name": "WordPress logged-in key", + "description": "WordPress logged-in key.", + "default": "randomly generated" + }, + "WordPress/keys/nonce": { + "display_name": "WordPress nonce key", + "description": "WordPress nonce key.", + "default": "randomly generated" + }, + "WordPress/server_aliases": { + "display_name": "WordPress Server Aliases", + "description": "WordPress Server Aliases", + "default": "FQDN" + }, + "WordPress/languages/lang": { + "display_name": "WordPress WPLANG configulation value", + "description": "WordPress WPLANG configulation value", + "default": "" + }, + "WordPress/languages/version": { + "display_name": "Version of WordPress translation file", + "description": "Version of WordPress translation file", + "default": "" + }, + "WordPress/languages/projects": { + "display_name": "WordPress translation projects", + "description": "WordPress translation projects", + "type": "array", + "default": [ + "main", + "admin", + "admin/network", + "cc" + ] + } + }, + "groupings": { + }, + "recipes": { + "WordPress": "Installs and configures WordPress LAMP stack on a single system", + "WordPress::languages": "Install WordPress translation files" + } +} \ No newline at end of file diff --git a/cookbooks/wordpress/recipes/apache.rb b/cookbooks/wordpress/recipes/apache.rb new file mode 100644 index 0000000..88acc03 --- /dev/null +++ b/cookbooks/wordpress/recipes/apache.rb @@ -0,0 +1,56 @@ +# +# Cookbook Name:: wordpress +# Recipe:: apache +# +# Copyright 2009-2010, 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. +# + +include_recipe "php" + +# On Windows PHP comes with the MySQL Module and we use IIS on Windows +unless platform? "windows" + include_recipe "php::module_mysql" + include_recipe "apache2" + include_recipe "apache2::mod_php5" +end + +include_recipe "wordpress::app" + +if platform?('windows') + + include_recipe 'iis::remove_default_site' + + iis_pool 'WordpressPool' do + no_managed_code true + action :add + end + + iis_site 'Wordpress' do + protocol :http + port 80 + path node['wordpress']['dir'] + application_pool 'WordpressPool' + action [:add,:start] + end +else + web_app "wordpress" do + template "wordpress.conf.erb" + docroot node['wordpress']['dir'] + server_name node['wordpress']['server_name'] + server_aliases node['wordpress']['server_aliases'] + server_port node['wordpress']['server_port'] + enable true + end +end diff --git a/cookbooks/wordpress/recipes/app.rb b/cookbooks/wordpress/recipes/app.rb new file mode 100644 index 0000000..b3d9f41 --- /dev/null +++ b/cookbooks/wordpress/recipes/app.rb @@ -0,0 +1,90 @@ +# +# Cookbook Name:: wordpress +# Recipe:: app +# +# Copyright 2009-2010, 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. +# + +include_recipe "wordpress::database" + +::Chef::Recipe.send(:include, Opscode::OpenSSL::Password) +node.set_unless['wordpress']['keys']['auth'] = secure_password +node.set_unless['wordpress']['keys']['secure_auth'] = secure_password +node.set_unless['wordpress']['keys']['logged_in'] = secure_password +node.set_unless['wordpress']['keys']['nonce'] = secure_password +node.set_unless['wordpress']['salt']['auth'] = secure_password +node.set_unless['wordpress']['salt']['secure_auth'] = secure_password +node.set_unless['wordpress']['salt']['logged_in'] = secure_password +node.set_unless['wordpress']['salt']['nonce'] = secure_password +node.save unless Chef::Config[:solo] + +directory node['wordpress']['dir'] do + action :create + recursive true + if platform_family?('windows') + rights :read, 'Everyone' + else + owner node['wordpress']['install']['user'] + group node['wordpress']['install']['group'] + mode '00755' + end +end + +archive = platform_family?('windows') ? 'wordpress.zip' : 'wordpress.tar.gz' + +if platform_family?('windows') + windows_zipfile node['wordpress']['parent_dir'] do + source node['wordpress']['url'] + action :unzip + not_if {::File.exists?("#{node['wordpress']['dir']}\\index.php")} + end +else + tar_extract node['wordpress']['url'] do + target_dir node['wordpress']['dir'] + creates File.join(node['wordpress']['dir'], 'index.php') + user node['wordpress']['install']['user'] + group node['wordpress']['install']['group'] + tar_flags [ '--strip-components 1' ] + not_if { ::File.exists?("#{node['wordpress']['dir']}/index.php") } + end +end + +template "#{node['wordpress']['dir']}/wp-config.php" do + source 'wp-config.php.erb' + mode node['wordpress']['config_perms'] + variables( + :db_name => node['wordpress']['db']['name'], + :db_user => node['wordpress']['db']['user'], + :db_password => node['wordpress']['db']['pass'], + :db_host => node['wordpress']['db']['host'], + :db_prefix => node['wordpress']['db']['prefix'], + :db_charset => node['wordpress']['db']['charset'], + :db_collate => node['wordpress']['db']['collate'], + :auth_key => node['wordpress']['keys']['auth'], + :secure_auth_key => node['wordpress']['keys']['secure_auth'], + :logged_in_key => node['wordpress']['keys']['logged_in'], + :nonce_key => node['wordpress']['keys']['nonce'], + :auth_salt => node['wordpress']['salt']['auth'], + :secure_auth_salt => node['wordpress']['salt']['secure_auth'], + :logged_in_salt => node['wordpress']['salt']['logged_in'], + :nonce_salt => node['wordpress']['salt']['nonce'], + :lang => node['wordpress']['languages']['lang'], + :allow_multisite => node['wordpress']['allow_multisite'], + :wp_config_options => node['wordpress']['wp_config_options'] + ) + owner node['wordpress']['install']['user'] + group node['wordpress']['install']['group'] + action :create +end diff --git a/cookbooks/wordpress/recipes/database.rb b/cookbooks/wordpress/recipes/database.rb new file mode 100644 index 0000000..6fb074d --- /dev/null +++ b/cookbooks/wordpress/recipes/database.rb @@ -0,0 +1,94 @@ +# +# Cookbook Name:: wordpress +# Recipe:: database +# Author:: Lucas Hansen () +# Author:: Julian C. Dunn () +# Author:: Craig Tracey () +# +# Copyright (C) 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. +# + +unless platform_family?('windows') + mysql_client 'default' do + action :create + end +end + +mysql2_chef_gem 'default' do + action :install +end + +::Chef::Recipe.send(:include, Opscode::OpenSSL::Password) +::Chef::Recipe.send(:include, Wordpress::Helpers) + +node.set_unless['wordpress']['db']['pass'] = secure_password +node.save unless Chef::Config[:solo] + +db = node['wordpress']['db'] + +if is_local_host? db['host'] + + # The following is required for the mysql community cookbook to work properly + include_recipe 'selinux::disabled' if node['platform_family'] == 'rhel' + + mysql_service db['instance_name'] do + port db['port'] + version db['mysql_version'] + initial_root_password db['root_password'] + action [:create, :start] + end + + socket = "/var/run/mysql-#{db['instance_name']}/mysqld.sock" + + if node['platform_family'] == 'debian' + link '/var/run/mysqld/mysqld.sock' do + to socket + not_if 'test -f /var/run/mysqld/mysqld.sock' + end + elsif node['platform_family'] == 'rhel' + link '/var/lib/mysql/mysql.sock' do + to socket + not_if 'test -f /var/lib/mysql/mysql.sock' + end + end + + mysql_connection_info = { + :host => 'localhost', + :username => 'root', + :socket => socket, + :password => db['root_password'] + } + + mysql_database db['name'] do + connection mysql_connection_info + action :create + end + + mysql_database_user db['user'] do + connection mysql_connection_info + password db['pass'] + host db['host'] + database_name db['name'] + action :create + end + + mysql_database_user db['user'] do + connection mysql_connection_info + database_name db['name'] + privileges [:all] + action :grant + end + +end diff --git a/cookbooks/wordpress/recipes/default.rb b/cookbooks/wordpress/recipes/default.rb new file mode 100644 index 0000000..39636ec --- /dev/null +++ b/cookbooks/wordpress/recipes/default.rb @@ -0,0 +1,20 @@ +# +# Cookbook Name:: wordpress +# Recipe:: default +# +# Copyright 2009-2010, 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. +# + +include_recipe "wordpress::apache" diff --git a/cookbooks/wordpress/recipes/languages.rb b/cookbooks/wordpress/recipes/languages.rb new file mode 100644 index 0000000..54a5aac --- /dev/null +++ b/cookbooks/wordpress/recipes/languages.rb @@ -0,0 +1,64 @@ +# +# Cookbook Name:: wordpress +# Recipe:: languages +# Author:: Koseki Kengo +# +# Copyright 2013, 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. +# + +include_recipe "wordpress" + +directory "#{node['wordpress']['dir']}/wp-content/languages" do + owner "root" + group "root" + mode "0755" + action :create + recursive true +end + +unless node['wordpress']['languages']['lang'].to_s.empty? && + node['wordpress']['languages']['version'].to_s.empty? + urls = node['wordpress']['languages']['urls'] + node['wordpress']['languages']['projects'].to_a.each do |project| + next unless urls[project] + + file = "#{node['wordpress']['dir']}/wp-content/languages/" + file += "#{project.tr('_', '-')}-" if project != 'main' + file += "#{node['wordpress']['languages']['lang']}.mo" + + remote_file file do + source urls[project] + owner "root" + group "root" + mode "0644" + action :create_if_missing + end + end + + node['wordpress']['languages']['themes'].to_a.each do |project| + next unless urls[project] + + file = "#{node['wordpress']['dir']}/wp-content/themes/#{project}/languages/" + file += "#{node['wordpress']['languages']['lang']}.mo" + + remote_file file do + source urls[project] + owner "root" + group "root" + mode "0644" + action :create_if_missing + end + end +end diff --git a/cookbooks/wordpress/recipes/nginx.rb b/cookbooks/wordpress/recipes/nginx.rb new file mode 100644 index 0000000..1ab9787 --- /dev/null +++ b/cookbooks/wordpress/recipes/nginx.rb @@ -0,0 +1,63 @@ +# +# Cookbook Name:: wordpress +# Recipe:: nginx +# +# Copyright 2009-2010, 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. +# + +node.set_unless['php-fpm']['pools'] = [] + +include_recipe "php-fpm" + +php_fpm_pool "wordpress" do + listen "127.0.0.1:9001" + user node['wordpress']['install']['user'] + group node['wordpress']['install']['group'] + if node['platform'] == 'ubuntu' and node['platform_version'] == '10.04' + process_manager 'dynamic' + end + listen_owner node['wordpress']['install']['user'] + listen_group node['wordpress']['install']['group'] + php_options node['wordpress']['php_options'] + start_servers 5 +end + +include_recipe "php::module_mysql" + +node.set_unless['nginx']['default_site_enabled'] = false +include_recipe "nginx" + +include_recipe "wordpress::app" + +template "#{node['nginx']['dir']}/sites-enabled/wordpress.conf" do + source "nginx.conf.erb" + variables( + :docroot => node['wordpress']['dir'], + :server_name => node['wordpress']['server_name'], + :server_aliases => node['wordpress']['server_aliases'], + :server_port => node['wordpress']['server_port'] + ) + action :create +end + +# The following block is specifically for OS's like CentOS that include a +# default site as a part of the install. This block will only be triggered if +# node['nginx']['default_site_enable'] is set to false. +if node['platform_family'] == 'rhel' && !node['nginx']['default_site_enabled'] + file File.join(node['nginx']['dir'], 'conf.d', 'default.conf') do + action :delete + notifies :reload, 'service[nginx]' + end +end diff --git a/cookbooks/wordpress/templates/default/nginx.conf.erb b/cookbooks/wordpress/templates/default/nginx.conf.erb new file mode 100644 index 0000000..8b19b5a --- /dev/null +++ b/cookbooks/wordpress/templates/default/nginx.conf.erb @@ -0,0 +1,21 @@ +server { + listen <%= @server_port %>; + server_name <%= @server_name %> <%= @server_aliases.join(" ") %>; + + access_log /var/log/nginx/<%= @server_name %>.access.log; + error_log /var/log/nginx/<%= @server_name %>.error.log; + + root <%= @docroot %>; + index index.php; + + location / { + try_files $uri $uri/ /index.php?$args; + } + + location ~ \.php$ { + try_files $uri =404; + include fastcgi_params; + fastcgi_pass 127.0.0.1:9001; + fastcgi_param SCRIPT_FILENAME <%= @docroot %>$fastcgi_script_name; + } +} diff --git a/cookbooks/wordpress/templates/default/wordpress.conf.erb b/cookbooks/wordpress/templates/default/wordpress.conf.erb new file mode 100644 index 0000000..2fc691b --- /dev/null +++ b/cookbooks/wordpress/templates/default/wordpress.conf.erb @@ -0,0 +1,31 @@ +> + ServerName <%= @params[:server_name] %> + ServerAlias <% @params[:server_aliases].each do |a| %><%= a %> <% end %> + DocumentRoot <%= @params[:docroot] %> + + > + Options FollowSymLinks + AllowOverride FileInfo Options + <% if node['apache']['version'] == '2.4' %> + Require all granted + <% else %> + Order allow,deny + Allow from all + <% end %> + + + + Options FollowSymLinks + AllowOverride None + + + LogLevel info + ErrorLog <%= node['apache']['log_dir'] %>/<%= @params[:name] %>-error.log + CustomLog <%= node['apache']['log_dir'] %>/<%= @params[:name] %>-access.log combined + + RewriteEngine On +<% unless node['apache']['version'] == '2.4' %> + RewriteLog <%= node['apache']['log_dir'] %>/<%= @application_name %>-rewrite.log + RewriteLogLevel 0 +<% end %> + diff --git a/cookbooks/wordpress/templates/default/wp-config.php.erb b/cookbooks/wordpress/templates/default/wp-config.php.erb new file mode 100644 index 0000000..ef157d9 --- /dev/null +++ b/cookbooks/wordpress/templates/default/wp-config.php.erb @@ -0,0 +1,99 @@ +'); + +/** MySQL database username */ +define('DB_USER', '<%= @db_user %>'); + +/** MySQL database password */ +define('DB_PASSWORD', '<%= @db_password %>'); + +/** MySQL hostname */ +define('DB_HOST', '<%= @db_host %>'); + +/** Database Charset to use in creating database tables. */ +define('DB_CHARSET', '<%= @db_charset %>'); + +/** The Database Collate type. Don't change this if in doubt. */ +define('DB_COLLATE', '<%= @db_collate %>'); + +/**#@+ + * Authentication Unique Keys and Salts. + * + * Change these to different unique phrases! + * You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service} + * You can change these at any point in time to invalidate all existing cookies. This will force all users to have to log in again. + * + * @since 2.6.0 + */ +define('AUTH_KEY', '<%= @auth_key %>'); +define('SECURE_AUTH_KEY', '<%= @secure_auth_key %>'); +define('LOGGED_IN_KEY', '<%= @logged_in_key %>'); +define('NONCE_KEY', '<%= @nonce_key %>'); +define('AUTH_SALT', '<%= @auth_salt %>'); +define('SECURE_AUTH_SALT', '<%= @secure_auth_salt %>'); +define('LOGGED_IN_SALT', '<%= @logged_in_salt %>'); +define('NONCE_SALT', '<%= @nonce_salt %>'); + +/**#@-*/ + +/** + * WordPress Database Table prefix. + * + * You can have multiple installations in one database if you give each a unique + * prefix. Only numbers, letters, and underscores please! + */ +$table_prefix = '<%= @db_prefix %>'; + +/** + * WordPress Localized Language, defaults to English. + * + * Change this to localize WordPress. A corresponding MO file for the chosen + * language must be installed to wp-content/languages. For example, install + * de_DE.mo to wp-content/languages and set WPLANG to 'de_DE' to enable German + * language support. + */ +define('WPLANG', '<%= @lang %>'); + +/** + * For developers: WordPress debugging mode. + * + * Change this to true to enable the display of notices during development. + * It is strongly recommended that plugin and theme developers use WP_DEBUG + * in their development environments. + */ +define('WP_DEBUG', false); + +<% if @allow_multisite %> +/* Multisite */ +define( 'WP_ALLOW_MULTISITE', true ); +<% end %> + +<% @wp_config_options.each do |key,value| %> +define( '<%= key %>', <%= value %> ); +<% end %> + +/* That's all, stop editing! Happy blogging. */ + +/** Absolute path to the WordPress directory. */ +if ( !defined('ABSPATH') ) + define('ABSPATH', dirname(__FILE__) . '/'); + +/** Sets up WordPress vars and included files. */ +require_once(ABSPATH . 'wp-settings.php'); diff --git a/cookbooks/xml/CHANGELOG.md b/cookbooks/xml/CHANGELOG.md index 2420032..69caa07 100644 --- a/cookbooks/xml/CHANGELOG.md +++ b/cookbooks/xml/CHANGELOG.md @@ -1,73 +1,81 @@ -v1.2.13 (2014-02-18) --------------------- +# xml Cookbook CHANGELOG +This file is used to list changes made in each version of the xml cookbook. + +## v2.0.0 (2015-12-07) +- The 1.3.1 release pinned the nokogiri gem version to 1.6.2.1 to avoid compilation failure that occured at some point in time. The cookbook also prevented the user from setting the version attribute to a modern nokogiri release. Nokogiri no longer fails to install so there is no longer a reason to pin or gate the versions. This release removes the version attribute and instead installs the latest version, but still allows the user to set the version attribute to pin to a specific version. + +## v1.3.1 (2015-10-12) +- Fixed compile errors on Chef 11 +- Added an empty array of packages for unknown systems to prevent failures on Windows and other operating systems + +## v1.3.0 (2015-10-06) +- Added zlib1g-dev on Ubuntu / Debian to fix compiles +- Add support for OS X +- Add source_url and issues_url to metadata.rb for Supermarket +- Updated readme to reflect that use_system_libraries actually defaults to false +- Use compile_time attribute with chef_gem to avoid deprecation warnings +- Update Chefspec tests to 4.X format +- Add additional platforms to the Kitchen CI config +- Use the standard Rubocop config and resolve all warnings +- Add Ruby 2.1/2.2 to Travis and remove Ruby 1.9.3 +- Update Berksfile to 3.X format +- Update contributing and testing docs +- Update and expand testing dependencies in the Gemfile +- Add maintainers.md and maintainers.toml files +- Add cookbook version badge to the readme +- Add Chef and platform requirements to the readme +- Add Rakfile for simplified testing +- Remove yum and build-essential from the Berksfile since these didn't need to be there +- Update .gitignore and add chefignore to prevent extra files from being uploaded to the Chef server + +## v1.2.13 (2014-02-18) - Reverting compile_time work -v1.2.12 (2014-02-18) --------------------- +## v1.2.12 (2014-02-18) - Fixing last patch to play nicely with Chef Sugar -v1.2.11 (2014-02-18) --------------------- +## v1.2.11 (2014-02-18) - Fixing chef_gem for Chef below 12.1.0 -v1.2.10 (2014-02-17) --------------------- +## v1.2.10 (2014-02-17) - Being explicit about usage of the chef_gem's compile_time property. - Eliminating future deprecation warnings in Chef 12.1.0. -v1.2.9 (2014-12-10) -------------------- +## v1.2.9 (2014-12-10) - Re-release with stove 3.2.2 to get a metadata.rb -v1.2.8 (2014-12-09) -------------------- +## v1.2.8 (2014-12-09) - [#11] Fix warning message from build-essential - [#13] pin nokogiri to a working version -v1.2.6 (2014-06-17) -------------------- +## v1.2.6 (2014-06-17) - [COOK-4468] Only set ENV variable when needed - -v1.2.4 (2014-03-27) -------------------- +## v1.2.4 (2014-03-27) - [COOK-4474] - Bump apt and yum versions in Berksfile, Lock to build-essentials 1.4 - [COOK-4468] - Set NOKOGIRI_USE_SYSTEM_LIBRARIES env variable +## v1.2.2 (2014-02-27) +[COOK-4382] - Fix xml cookbook spec test [COOK-4304] - Set proper packages for SUSE 11 -v1.2.2 (2014-02-27) -------------------- -[COOK-4382] - Fix xml cookbook spec test -[COOK-4304] - Set proper packages for SUSE 11 - - -v1.2.1 ------- +## v1.2.1 ### Improvement - [COOK-4304](https://tickets.chef.io/browse/COOK-4304) - Now sets proper packages for SUSE 11 - -v1.2.0 ------- +## v1.2.0 ### Improvement - **[COOK-3462](https://tickets.chef.io/browse/COOK-3462)** - Allow installing packages during compile time - -v1.1.2 ------- +## v1.1.2 - [COOK-2059] - missing dependency on build-essential -v1.1.0 ------- +## v1.1.0 - [COOK-1826] - support nokogiri chef_gem - [COOK-1902] - add support for archlinux -v1.0.4 ------- +## v1.0.4 - [COOK-1232] - add xslt to xml cookbook -v1.0.2 ------- +## v1.0.2 - [COOK-953] - Add FreeBSD support - [COOK-775] - Add Amazon Linux support - diff --git a/cookbooks/xml/CONTRIBUTING.md b/cookbooks/xml/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/xml/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/xml/MAINTAINERS.md b/cookbooks/xml/MAINTAINERS.md new file mode 100644 index 0000000..c6a51ae --- /dev/null +++ b/cookbooks/xml/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 +* [Tim Smith](https://github.com/tas50) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Sean OMeara](https://github.com/someara) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) diff --git a/cookbooks/xml/README.md b/cookbooks/xml/README.md index 76d7ba1..3d11548 100644 --- a/cookbooks/xml/README.md +++ b/cookbooks/xml/README.md @@ -1,22 +1,28 @@ -XML Cookbook -============ -[![Build Status](https://secure.travis-ci.org/chef-cookbooks/xml.png?branch=master)](http://travis-ci.org/chef-cookbooks/xml) +# XML Cookbook +[![Build Status](https://travis-ci.org/chef-cookbooks/xml.svg?branch=master)](http://travis-ci.org/chef-cookbooks/xml) [![Cookbook Version](http://img.shields.io/cookbook/v/xml.svg)](https://supermarket.chef.io/cookbooks/xml) Installs development package for libxml. +## Requirements +### Platforms +- Debian/Ubuntu +- RHEL/CentOS/Scientific/Amazon/Oracle +- Arch Linux +- Suse +- FreeBSD -Requirements ------------- -Debian, Ubuntu, CentOS, Red Hat, Scientific, Fedora, SUSE, ArchLinux +### Chef +- Chef 11+ -Attributes ----------- +### Cookbooks +- build-essential +- chef-sugar + +## Attributes - `node['xml']['packages']` - Array of package names that should be installed -- `node['xml']['nokogiri']['use_system_libraries']` - Whether to use system libraries for nokogiri (defaults to `true`) +- `node['xml']['nokogiri']['use_system_libraries']` - Whether to use system libraries for nokogiri (defaults to `false`) - -Recipes -------- +## Recipes ### default Installs the development packages for libxml2 and libxslt. @@ -28,16 +34,14 @@ include_recipe 'xml::default' ``` ### ruby -Installs the nokogiri gem into Chef's Ruby environment so it can be used in recipes. +Installs the nokogiri gem into Chef's Ruby environment so it can be used in recipes. If nokogiri is being installed using the system's libxml package your distro must include version 2.6.21 or later. Due to this Debian 7 or earlier / Ubuntu 12.04 or earlier will not work with the system library attribute enabled. +## License & Authors +**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io)) -License & Authors ------------------ -- Author:: Joshua Timberman () - -```text -Copyright 2009-2013, Chef Software, Inc. +**Copyright:** 2009-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 diff --git a/cookbooks/xml/attributes/default.rb b/cookbooks/xml/attributes/default.rb index e9ffd0c..6728d0f 100644 --- a/cookbooks/xml/attributes/default.rb +++ b/cookbooks/xml/attributes/default.rb @@ -1,8 +1,8 @@ # # Cookbook Name:: xml -# Recipe:: default +# Attributes:: default # -# Copyright 2010-2013, Chef Software, Inc. +# Copyright 2009-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. @@ -22,14 +22,15 @@ default['xml']['compiletime'] = false case node['platform_family'] when 'rhel', 'fedora', 'suse' default['xml']['packages'] = %w(libxml2-devel libxslt-devel) -when 'ubuntu', 'debian' - default['xml']['packages'] = %w(libxml2-dev libxslt-dev) +when 'debian' + default['xml']['packages'] = %w(libxml2-dev libxslt-dev zlib1g-dev) when 'freebsd', 'arch' default['xml']['packages'] = %w(libxml2 libxslt) +when 'mac_os_x' + default['xml']['packages'] = %w(libxml2) +else + default['xml']['packages'] = [] end default['xml']['nokogiri']['use_system_libraries'] = false - -# Newest versions will not compile with system libraries -# https://github.com/sparklemotion/nokogiri/issues/1099 -default['xml']['nokogiri']['version'] = '1.6.2.1' +default['xml']['nokogiri']['version'] = nil diff --git a/cookbooks/xml/metadata.json b/cookbooks/xml/metadata.json index 7e7dd17..c83418b 100644 --- a/cookbooks/xml/metadata.json +++ b/cookbooks/xml/metadata.json @@ -1,42 +1 @@ -{ - "name": "xml", - "version": "1.2.13", - "description": "Installs xml", - "long_description": "XML Cookbook\n============\n[![Build Status](https://secure.travis-ci.org/chef-cookbooks/xml.png?branch=master)](http://travis-ci.org/chef-cookbooks/xml)\n\nInstalls development package for libxml.\n\n\nRequirements\n------------\nDebian, Ubuntu, CentOS, Red Hat, Scientific, Fedora, SUSE, ArchLinux\n\nAttributes\n----------\n- `node['xml']['packages']` - Array of package names that should be installed\n- `node['xml']['nokogiri']['use_system_libraries']` - Whether to use system libraries for nokogiri (defaults to `true`)\n\n\nRecipes\n-------\n### default\nInstalls the development packages for libxml2 and libxslt.\n\nFor installing the packages during compile time:\n\n```ruby\nnode.set['xml']['compiletime'] = true\ninclude_recipe 'xml::default'\n```\n\n### ruby\nInstalls the nokogiri gem into Chef's Ruby environment so it can be used in recipes.\n\n\nLicense & Authors\n-----------------\n- Author:: Joshua Timberman ()\n\n```text\nCopyright 2009-2013, 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": { - "amazon": ">= 0.0.0", - "arch": ">= 0.0.0", - "centos": ">= 0.0.0", - "debian": ">= 0.0.0", - "fedora": ">= 0.0.0", - "freebsd": ">= 0.0.0", - "redhat": ">= 0.0.0", - "scientific": ">= 0.0.0", - "suse": ">= 0.0.0", - "ubuntu": ">= 0.0.0" - }, - "dependencies": { - "build-essential": ">= 0.0.0", - "chef-sugar": ">= 0.0.0" - }, - "recommendations": { - }, - "suggestions": { - }, - "conflicting": { - }, - "providing": { - }, - "replacing": { - }, - "attributes": { - }, - "groupings": { - }, - "recipes": { - "xml": "Installs libxml development packages" - } -} \ No newline at end of file +{"name":"xml","version":"2.0.0","description":"Installs xml","long_description":"# XML Cookbook\n[![Build Status](https://travis-ci.org/chef-cookbooks/xml.svg?branch=master)](http://travis-ci.org/chef-cookbooks/xml) [![Cookbook Version](http://img.shields.io/cookbook/v/xml.svg)](https://supermarket.chef.io/cookbooks/xml)\n\nInstalls development package for libxml.\n\n## Requirements\n### Platforms\n- Debian/Ubuntu\n- RHEL/CentOS/Scientific/Amazon/Oracle\n- Arch Linux\n- Suse\n- FreeBSD\n\n### Chef\n- Chef 11+\n\n### Cookbooks\n- build-essential\n- chef-sugar\n\n## Attributes\n- `node['xml']['packages']` - Array of package names that should be installed\n- `node['xml']['nokogiri']['use_system_libraries']` - Whether to use system libraries for nokogiri (defaults to `false`)\n\n## Recipes\n### default\nInstalls the development packages for libxml2 and libxslt.\n\nFor installing the packages during compile time:\n\n```ruby\nnode.set['xml']['compiletime'] = true\ninclude_recipe 'xml::default'\n```\n\n### ruby\nInstalls the nokogiri gem into Chef's Ruby environment so it can be used in recipes. If nokogiri is being installed using the system's libxml package your distro must include version 2.6.21 or later. Due to this Debian 7 or earlier / Ubuntu 12.04 or earlier will not work with the system library attribute enabled.\n\n## License & Authors\n**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io))\n\n**Copyright:** 2009-2015, 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","arch":">= 0.0.0","centos":">= 0.0.0","debian":">= 0.0.0","fedora":">= 0.0.0","freebsd":">= 0.0.0","oracle":">= 0.0.0","redhat":">= 0.0.0","scientific":">= 0.0.0","suse":">= 0.0.0","ubuntu":">= 0.0.0"},"dependencies":{"build-essential":">= 0.0.0","chef-sugar":">= 0.0.0"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{"xml":"Installs libxml development packages"}} \ No newline at end of file diff --git a/cookbooks/xml/recipes/default.rb b/cookbooks/xml/recipes/default.rb index 53ddeb8..0eae8a7 100644 --- a/cookbooks/xml/recipes/default.rb +++ b/cookbooks/xml/recipes/default.rb @@ -2,7 +2,7 @@ # Cookbook Name:: xml # Recipe:: default # -# Copyright 2010-2013, Chef Software, Inc. +# 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. diff --git a/cookbooks/xml/recipes/ruby.rb b/cookbooks/xml/recipes/ruby.rb index 2e114dd..988378b 100644 --- a/cookbooks/xml/recipes/ruby.rb +++ b/cookbooks/xml/recipes/ruby.rb @@ -32,15 +32,11 @@ include_recipe 'build-essential::default' include_recipe 'xml::default' if node['xml']['nokogiri']['use_system_libraries'] - if node['xml']['nokogiri']['version'].nil? || - version(node['xml']['nokogiri']['version']).satisfies?('> 1.6.1') - Chef::Application.fatal!("You must specify a version less than or equal to 1.6.1 of nokogiri to use system libraries. You set: #{node['xml']['nokogiri']['version']}.") - else - ENV['NOKOGIRI_USE_SYSTEM_LIBRARIES'] = node['xml']['nokogiri']['use_system_libraries'].to_s - end + ENV['NOKOGIRI_USE_SYSTEM_LIBRARIES'] = node['xml']['nokogiri']['use_system_libraries'].to_s end chef_gem 'nokogiri' do - version node['xml']['nokogiri']['version'] + version node['xml']['nokogiri']['version'] if node['xml']['nokogiri']['version'] action :install + compile_time true if defined? compile_time end diff --git a/cookbooks/yum-epel/CHANGELOG.md b/cookbooks/yum-epel/CHANGELOG.md index 14e5662..7e57b60 100644 --- a/cookbooks/yum-epel/CHANGELOG.md +++ b/cookbooks/yum-epel/CHANGELOG.md @@ -1,5 +1,38 @@ yum-epel Cookbook CHANGELOG ====================== +This file is used to list changes made in each version of the yum-epel cookbook. + +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) ------------------- @@ -22,42 +55,34 @@ 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/MAINTAINERS.md b/cookbooks/yum-epel/MAINTAINERS.md new file mode 100644 index 0000000..2cf4d2f --- /dev/null +++ b/cookbooks/yum-epel/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 +* [Jennifer Davis](https://github.com/sigje) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Sean OMeara](https://github.com/someara) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) diff --git a/cookbooks/yum-epel/README.md b/cookbooks/yum-epel/README.md index 54eb287..561f382 100644 --- a/cookbooks/yum-epel/README.md +++ b/cookbooks/yum-epel/README.md @@ -1,5 +1,7 @@ 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) The yum-epel cookbook takes over management of the default repositoryids shipped with epel-release. It allows attribute @@ -8,8 +10,16 @@ manipulation of `epel`, `epel-debuginfo`, `epel-source`, `epel-testing`, Requirements ------------ -* Chef 11 or higher -* yum cookbook version 3.0.0 or higher +#### Platforms +* RHEL/CentOS and derivatives +* Fedora + +#### Chef +* Chef 11+ + +#### Cookbooks +* yum version 3.2.0 or higher + Attributes ---------- @@ -143,11 +153,11 @@ include_recipe 'yum-epel' License & Authors ----------------- -- Author:: Sean OMeara () -```text -Copyright:: 2011-2013 Opscode, Inc. +**Author:** Cookbook Engineering Team () +**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 diff --git a/cookbooks/yum-epel/attributes/epel-debuginfo.rb b/cookbooks/yum-epel/attributes/epel-debuginfo.rb index 0e72757..b466e15 100644 --- a/cookbooks/yum-epel/attributes/epel-debuginfo.rb +++ b/cookbooks/yum-epel/attributes/epel-debuginfo.rb @@ -14,11 +14,11 @@ else when 6 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://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6' + default['yum']['epel-debuginfo']['gpgkey'] = 'https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6' when 7 default['yum']['epel-debuginfo']['description'] = 'Extra Packages for Enterprise Linux 7 - $basearch - Debug' default['yum']['epel-debuginfo']['mirrorlist'] = 'https://mirrors.fedoraproject.org/metalink?repo=epel-debug-7&arch=$basearch' - default['yum']['epel-debuginfo']['gpgkey'] = 'http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7' + default['yum']['epel-debuginfo']['gpgkey'] = 'https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7' end end diff --git a/cookbooks/yum-epel/attributes/epel-source.rb b/cookbooks/yum-epel/attributes/epel-source.rb index 1433eed..9b1b344 100644 --- a/cookbooks/yum-epel/attributes/epel-source.rb +++ b/cookbooks/yum-epel/attributes/epel-source.rb @@ -13,12 +13,12 @@ else default['yum']['epel-source']['gpgkey'] = 'http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL' when 6 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://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6' + default['yum']['epel-source']['mirrorlist'] = 'https://mirrors.fedoraproject.org/metalink?repo=epel-source-6&arch=$basearch' + default['yum']['epel-source']['gpgkey'] = 'https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6' when 7 default['yum']['epel-source']['description'] = 'Extra Packages for Enterprise Linux 7 - $basearch - Source' - default['yum']['epel-source']['mirrorlist'] = 'http://mirrors.fedoraproject.org/mirrorlist?repo=epel-source-7&arch=$basearch' - default['yum']['epel-source']['gpgkey'] = 'http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7' + default['yum']['epel-source']['mirrorlist'] = 'https://mirrors.fedoraproject.org/metalink?repo=epel-source-7&arch=$basearch' + default['yum']['epel-source']['gpgkey'] = 'https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7' end end diff --git a/cookbooks/yum-epel/attributes/epel.rb b/cookbooks/yum-epel/attributes/epel.rb index 07dceb6..4a15a4a 100644 --- a/cookbooks/yum-epel/attributes/epel.rb +++ b/cookbooks/yum-epel/attributes/epel.rb @@ -13,12 +13,12 @@ else default['yum']['epel']['gpgkey'] = 'http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL' when 6 default['yum']['epel']['description'] = 'Extra Packages for Enterprise Linux 6 - $basearch' - default['yum']['epel']['mirrorlist'] = 'http://mirrors.fedoraproject.org/mirrorlist?repo=epel-6&arch=$basearch' - default['yum']['epel']['gpgkey'] = 'http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6' + default['yum']['epel']['mirrorlist'] = 'https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch' + default['yum']['epel']['gpgkey'] = 'https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6' when 7 default['yum']['epel']['description'] = 'Extra Packages for Enterprise Linux 7 - $basearch' - default['yum']['epel']['mirrorlist'] = 'http://mirrors.fedoraproject.org/mirrorlist?repo=epel-7&arch=$basearch' - default['yum']['epel']['gpgkey'] = 'http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7' + default['yum']['epel']['mirrorlist'] = 'https://mirrors.fedoraproject.org/metalink?repo=epel-7&arch=$basearch' + default['yum']['epel']['gpgkey'] = 'https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7' end end diff --git a/cookbooks/yum-epel/metadata.json b/cookbooks/yum-epel/metadata.json index f60c0d8..e6ab785 100644 --- a/cookbooks/yum-epel/metadata.json +++ b/cookbooks/yum-epel/metadata.json @@ -1,34 +1 @@ -{ - "name": "yum-epel", - "version": "0.6.0", - "description": "Installs/Configures yum-epel", - "long_description": "", - "maintainer": "Chef", - "maintainer_email": "Sean OMeara ", - "license": "Apache 2.0", - "platforms": { - "redhat": ">= 0.0.0", - "centos": ">= 0.0.0", - "scientific": ">= 0.0.0", - "amazon": ">= 0.0.0" - }, - "dependencies": { - "yum": "~> 3.0" - }, - "recommendations": { - }, - "suggestions": { - }, - "conflicting": { - }, - "providing": { - }, - "replacing": { - }, - "attributes": { - }, - "groupings": { - }, - "recipes": { - } -} \ No newline at end of file +{"name":"yum-epel","version":"0.6.5","description":"Installs and configures the EPEL Yum repository","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"},"dependencies":{"yum":"~> 3.2"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file diff --git a/cookbooks/yum-epel/recipes/default.rb b/cookbooks/yum-epel/recipes/default.rb index 8ed695e..31f3631 100644 --- a/cookbooks/yum-epel/recipes/default.rb +++ b/cookbooks/yum-epel/recipes/default.rb @@ -1,8 +1,9 @@ # -# Author:: Sean OMeara () -# Recipe:: yum-epel::default +# Author:: Sean OMeara () +# Cookbook Name:: yum-epel +# Recipe:: default # -# Copyright 2013, Chef +# 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. @@ -17,45 +18,44 @@ # limitations under the License. node['yum-epel']['repositories'].each do |repo| + next unless node['yum'][repo]['managed'] - if node['yum'][repo]['managed'] - yum_repository repo do - baseurl node['yum'][repo]['baseurl'] - cost node['yum'][repo]['cost'] - description node['yum'][repo]['description'] - enabled node['yum'][repo]['enabled'] - enablegroups node['yum'][repo]['enablegroups'] - exclude node['yum'][repo]['exclude'] - failovermethod node['yum'][repo]['failovermethod'] - fastestmirror_enabled node['yum'][repo]['fastestmirror_enabled'] - gpgcheck node['yum'][repo]['gpgcheck'] - gpgkey node['yum'][repo]['gpgkey'] - http_caching node['yum'][repo]['http_caching'] - include_config node['yum'][repo]['include_config'] - includepkgs node['yum'][repo]['includepkgs'] - keepalive node['yum'][repo]['keepalive'] - max_retries node['yum'][repo]['max_retries'] - metadata_expire node['yum'][repo]['metadata_expire'] - mirror_expire node['yum'][repo]['mirror_expire'] - mirrorlist node['yum'][repo]['mirrorlist'] - mirrorlist_expire node['yum'][repo]['mirrorlist_expire'] - password node['yum'][repo]['password'] - priority node['yum'][repo]['priority'] - proxy node['yum'][repo]['proxy'] - proxy_username node['yum'][repo]['proxy_username'] - proxy_password node['yum'][repo]['proxy_password'] - report_instanceid node['yum'][repo]['report_instanceid'] - repositoryid node['yum'][repo]['repositoryid'] - skip_if_unavailable node['yum'][repo]['skip_if_unavailable'] - source node['yum'][repo]['source'] - sslcacert node['yum'][repo]['sslcacert'] - sslclientcert node['yum'][repo]['sslclientcert'] - sslclientkey node['yum'][repo]['sslclientkey'] - sslverify node['yum'][repo]['sslverify'] - timeout node['yum'][repo]['timeout'] - username node['yum'][repo]['username'] + yum_repository repo do + baseurl node['yum'][repo]['baseurl'] unless node['yum'][repo]['baseurl'].nil? + cost node['yum'][repo]['cost'] unless node['yum'][repo]['cost'].nil? + description node['yum'][repo]['description'] unless node['yum'][repo]['description'].nil? + enabled node['yum'][repo]['enabled'] unless node['yum'][repo]['enabled'].nil? + enablegroups node['yum'][repo]['enablegroups'] unless node['yum'][repo]['enablegroups'].nil? + exclude node['yum'][repo]['exclude'] unless node['yum'][repo]['exclude'].nil? + failovermethod node['yum'][repo]['failovermethod'] unless node['yum'][repo]['failovermethod'].nil? + fastestmirror_enabled node['yum'][repo]['fastestmirror_enabled'] unless node['yum'][repo]['fastestmirror_enabled'].nil? + gpgcheck node['yum'][repo]['gpgcheck'] unless node['yum'][repo]['gpgcheck'].nil? + gpgkey node['yum'][repo]['gpgkey'] unless node['yum'][repo]['gpgkey'].nil? + http_caching node['yum'][repo]['http_caching'] unless node['yum'][repo]['http_caching'].nil? + include_config node['yum'][repo]['include_config'] unless node['yum'][repo]['include_config'].nil? + includepkgs node['yum'][repo]['includepkgs'] unless node['yum'][repo]['includepkgs'].nil? + keepalive node['yum'][repo]['keepalive'] unless node['yum'][repo]['keepalive'].nil? + max_retries node['yum'][repo]['max_retries'] unless node['yum'][repo]['max_retries'].nil? + metadata_expire node['yum'][repo]['metadata_expire'] unless node['yum'][repo]['metadata_expire'].nil? + mirror_expire node['yum'][repo]['mirror_expire'] unless node['yum'][repo]['mirror_expire'].nil? + mirrorlist node['yum'][repo]['mirrorlist'] unless node['yum'][repo]['mirrorlist'].nil? + mirrorlist_expire node['yum'][repo]['mirrorlist_expire'] unless node['yum'][repo]['mirrorlist_expire'].nil? + password node['yum'][repo]['password'] unless node['yum'][repo]['password'].nil? + priority node['yum'][repo]['priority'] unless node['yum'][repo]['priority'].nil? + proxy node['yum'][repo]['proxy'] unless node['yum'][repo]['proxy'].nil? + proxy_username node['yum'][repo]['proxy_username'] unless node['yum'][repo]['proxy_username'].nil? + proxy_password node['yum'][repo]['proxy_password'] unless node['yum'][repo]['proxy_password'].nil? + report_instanceid node['yum'][repo]['report_instanceid'] unless node['yum'][repo]['report_instanceid'].nil? + repositoryid node['yum'][repo]['repositoryid'] unless node['yum'][repo]['repositoryid'].nil? + skip_if_unavailable node['yum'][repo]['skip_if_unavailable'] unless node['yum'][repo]['skip_if_unavailable'].nil? + source node['yum'][repo]['source'] unless node['yum'][repo]['source'].nil? + sslcacert node['yum'][repo]['sslcacert'] unless node['yum'][repo]['sslcacert'].nil? + sslclientcert node['yum'][repo]['sslclientcert'] unless node['yum'][repo]['sslclientcert'].nil? + sslclientkey node['yum'][repo]['sslclientkey'] unless node['yum'][repo]['sslclientkey'].nil? + sslverify node['yum'][repo]['sslverify'] unless node['yum'][repo]['sslverify'].nil? + timeout node['yum'][repo]['timeout'] unless node['yum'][repo]['timeout'].nil? + username node['yum'][repo]['username'] unless node['yum'][repo]['username'].nil? - action :create - end + action :create end end diff --git a/cookbooks/yum-mysql-community/CHANGELOG.md b/cookbooks/yum-mysql-community/CHANGELOG.md index 11fa69f..77d7ed7 100644 --- a/cookbooks/yum-mysql-community/CHANGELOG.md +++ b/cookbooks/yum-mysql-community/CHANGELOG.md @@ -1,7 +1,33 @@ yum-mysql-community Cookbook CHANGELOG -====================== +--------------------------------------- This file is used to list changes made in each version of the yum-mysql-community cookbook. +v0.1.21 (2015-12-01) +-------------------- +- Fixing if/unless logic in recipes + +v0.1.20 (2015-11-30) +-------------------- +- Fixed attributes with a false value not being passed + +v0.1.19 (2015-10-28) +-------------------- +- Fixing Chef 13 nil property deprecation warnings + +v0.1.18 (2015-09-21) +-------------------- +- Added Travis CI config for lint and unit testing +- Added Chef standard Rubocop file and resolved all warnings +- Added Chef standard chefignore and .gitignore files +- Add supported platforms to the metadata +- Added source_url and issues_url to the metadata +- Added long_description to the metadata +- Updated and expanded development dependencies in the Gemfile +- Added contributing, testing, and maintainers docs +- Added platform requirements to the readme +- Added Travis and cookbook version badges to the readme +- Update Chefspec to 4.X format + v0.1.17 (2015-04-06) -------------------- - Updating pubkey link from someara to chef-client github orgs @@ -23,15 +49,15 @@ v0.1.13 (2015-03-12) - #3 corrected typo in public key attribute v0.1.12 (2015-01-20) -------------------- +-------------------- - Minor style updates v0.1.11 (2014-07-21) -------------------- +-------------------- - Adding RHEL-7 support v0.1.10 (2014-07-21) -------------------- +-------------------- - Adding mysql-5.7 and centos 7 support v0.1.8 (2014-06-18) @@ -42,57 +68,15 @@ v0.1.6 (2014-06-16) ------------------- Fixing typo in mysql55-community attributes - v0.1.4 (2014-06-13) ------------------- - updating url to keys in cookbook attributes - v0.1.2 (2014-06-11) ------------------- #1 - Move files/mysql_pubkey.asc to files/default/mysql_pubkey.asc - v0.1.0 (2014-04-30) ------------------- Initial release - -v0.3.6 (2014-04-09) -------------------- -- [COOK-4509] add RHEL7 support to yum-mysql-community 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-mysql-community/CONTRIBUTING.md b/cookbooks/yum-mysql-community/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/cookbooks/yum-mysql-community/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-mysql-community/MAINTAINERS.md b/cookbooks/yum-mysql-community/MAINTAINERS.md new file mode 100644 index 0000000..2cf4d2f --- /dev/null +++ b/cookbooks/yum-mysql-community/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 +* [Jennifer Davis](https://github.com/sigje) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Sean OMeara](https://github.com/someara) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) diff --git a/cookbooks/yum-mysql-community/README.md b/cookbooks/yum-mysql-community/README.md index c642ab1..7bae244 100644 --- a/cookbooks/yum-mysql-community/README.md +++ b/cookbooks/yum-mysql-community/README.md @@ -1,21 +1,24 @@ -yum-mysql-community Cookbook -============ +# yum-mysql-community Cookbook +[![Build Status](https://travis-ci.org/chef-cookbooks/yum-mysql-community.svg?branch=master)](http://travis-ci.org/chef-cookbooks/yum-mysql-community) [![Cookbook Version](https://img.shields.io/cookbook/v/yum-mysql-community.svg)](https://supermarket.chef.io/cookbooks/yum-mysql-community) -The yum-mysql-community cookbook takes over management of the default -repositoryids shipped with epel-release. It allows attribute -manipulation of `mysql-connectors-community`, `mysql56-community`, and -`mysql57-community-dmr`. +The yum-mysql-community cookbook takes over management of the default repository ids shipped with epel-release. It allows attribute manipulation of `mysql-connectors-community`, `mysql56-community`, and `mysql57-community-dmr`. -Requirements ------------- -* Chef 11 or higher -* yum cookbook version 3.0.0 or higher +## Requirements +### Platforms +- RHEL/CentOS and derivatives +- Fedora -Attributes ----------- +### Chef +- Chef 11+ + +### Cookbooks +- yum version 3.0.0 or higher +- yum-epel + +## Attributes The following attributes are set by default -``` ruby +```ruby default['yum']['mysql-connectors-community']['repositoryid'] = 'mysql-connectors-community' default['yum']['mysql-connectors-community']['description'] = 'MySQL Connectors Community' default['yum']['mysql-connectors-community']['baseurl'] = 'http://repo.mysql.com/yum/mysql-connectors-community/el/$releasever/$basearch/' @@ -25,7 +28,7 @@ default['yum']['mysql-connectors-community']['gpgcheck'] = true default['yum']['mysql-connectors-community']['enabled'] = true ``` -``` ruby +```ruby default['yum']['mysql56-community']['repositoryid'] = 'mysql56-community' default['yum']['mysql56-community']['description'] = 'MySQL 5.6 Community Server' default['yum']['mysql56-community']['baseurl'] = 'http://repo.mysql.com/yum/mysql56-community/el/$releasever/$basearch/' @@ -35,7 +38,7 @@ default['yum']['mysql56-community']['gpgcheck'] = true default['yum']['mysql56-community']['enabled'] = true ``` -``` ruby +```ruby default['yum']['mysql57-community-dmr']['repositoryid'] = 'mysql57-community-dmr' default['yum']['mysql57-community-dmr']['description'] = 'MySQL 5.7 Community Server Development Milestone Release' default['yum']['mysql57-community-dmr']['baseurl'] = 'http://repo.mysql.com/yum/mysql56-community/el/$releasever/$basearch/' @@ -45,10 +48,9 @@ default['yum']['mysql57-community-dmr']['gpgcheck'] = true default['yum']['mysql57-community-dmr']['enabled'] = true ``` -Recipes -------- -* mysql55 - Sets up the mysql56-community repository on supported - platforms +## Recipes +- mysql55 - Sets up the mysql56-community repository on supported +- platforms ```ruby yum_repository 'mysql55-community' do @@ -59,8 +61,8 @@ Recipes end ``` -* mysql56 - Sets up the mysql56-community repository on supported - platforms +- mysql56 - Sets up the mysql56-community repository on supported +- platforms ```ruby yum_repository 'mysql56-community' do @@ -71,13 +73,10 @@ Recipes end ``` +- connectors - Sets up the mysql-connectors-community repository on supported +- platforms -* connectors - Sets up the mysql-connectors-community repository on supported - platforms - - -Usage Example -------------- +## Usage Example To disable the epel repository through a Role or Environment definition ``` @@ -92,10 +91,7 @@ default_attributes( ) ``` -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: +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: ``` node.default['yum']['mysql57-community-dmr']['enabled'] = true @@ -103,8 +99,7 @@ node.default['yum']['mysql57-community-dmr']['managed'] = true include_recipe 'mysql57-community-dmr' ``` -More Examples -------------- +## More Examples Point the mysql56-community repositories at an internally hosted server. ``` @@ -116,13 +111,12 @@ node.default['yum']['mysql56-community']['sslverify'] = false include_recipe 'mysql56-community' ``` -License & Authors ------------------ -- Author:: Sean OMeara () +## License & Authors +**Author:** Cookbook Engineering Team ([cookbooks@chef.io](mailto:cookbooks@chef.io)) -```text -Copyright:: 2011-2015, Chef Software, Inc. +**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 diff --git a/cookbooks/yum-mysql-community/metadata.json b/cookbooks/yum-mysql-community/metadata.json index 3bae524..0e996cb 100644 --- a/cookbooks/yum-mysql-community/metadata.json +++ b/cookbooks/yum-mysql-community/metadata.json @@ -1,30 +1 @@ -{ - "name": "yum-mysql-community", - "version": "0.1.17", - "description": "Installs/Configures yum-mysql-community", - "long_description": "", - "maintainer": "Chef Software, Inc", - "maintainer_email": "Sean OMeara ", - "license": "Apache 2.0", - "platforms": { - }, - "dependencies": { - "yum": ">= 3.0" - }, - "recommendations": { - }, - "suggestions": { - }, - "conflicting": { - }, - "providing": { - }, - "replacing": { - }, - "attributes": { - }, - "groupings": { - }, - "recipes": { - } -} \ No newline at end of file +{"name":"yum-mysql-community","version":"0.1.21","description":"Installs/Configures yum-mysql-community","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"},"dependencies":{"yum":">= 3.2"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file diff --git a/cookbooks/yum-mysql-community/recipes/connectors.rb b/cookbooks/yum-mysql-community/recipes/connectors.rb index 6bc02bf..40fc983 100644 --- a/cookbooks/yum-mysql-community/recipes/connectors.rb +++ b/cookbooks/yum-mysql-community/recipes/connectors.rb @@ -2,7 +2,7 @@ # Author:: Sean OMeara () # Recipe:: yum-mysql-community::connectors # -# Copyright 2014, Chef Software, Inc. +# Copyright 2014-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. @@ -17,32 +17,32 @@ # limitations under the License. yum_repository 'mysql-connectors-community' do - description node['yum']['mysql-connectors-community']['description'] - baseurl node['yum']['mysql-connectors-community']['baseurl'] - mirrorlist node['yum']['mysql-connectors-community']['mirrorlist'] - gpgcheck node['yum']['mysql-connectors-community']['gpgcheck'] - gpgkey node['yum']['mysql-connectors-community']['gpgkey'] - enabled node['yum']['mysql-connectors-community']['enabled'] - cost node['yum']['mysql-connectors-community']['cost'] - exclude node['yum']['mysql-connectors-community']['exclude'] - enablegroups node['yum']['mysql-connectors-community']['enablegroups'] - failovermethod node['yum']['mysql-connectors-community']['failovermethod'] - http_caching node['yum']['mysql-connectors-community']['http_caching'] - include_config node['yum']['mysql-connectors-community']['include_config'] - includepkgs node['yum']['mysql-connectors-community']['includepkgs'] - keepalive node['yum']['mysql-connectors-community']['keepalive'] - max_retries node['yum']['mysql-connectors-community']['max_retries'] - metadata_expire node['yum']['mysql-connectors-community']['metadata_expire'] - mirror_expire node['yum']['mysql-connectors-community']['mirror_expire'] - priority node['yum']['mysql-connectors-community']['priority'] - proxy node['yum']['mysql-connectors-community']['proxy'] - proxy_username node['yum']['mysql-connectors-community']['proxy_username'] - proxy_password node['yum']['mysql-connectors-community']['proxy_password'] - repositoryid node['yum']['mysql-connectors-community']['repositoryid'] - sslcacert node['yum']['mysql-connectors-community']['sslcacert'] - sslclientcert node['yum']['mysql-connectors-community']['sslclientcert'] - sslclientkey node['yum']['mysql-connectors-community']['sslclientkey'] - sslverify node['yum']['mysql-connectors-community']['sslverify'] - timeout node['yum']['mysql-connectors-community']['timeout'] + description node['yum']['mysql-connectors-community']['description'] unless node['yum']['mysql-connectors-community']['description'].nil? + baseurl node['yum']['mysql-connectors-community']['baseurl'] unless node['yum']['mysql-connectors-community']['baseurl'].nil? + mirrorlist node['yum']['mysql-connectors-community']['mirrorlist'] unless node['yum']['mysql-connectors-community']['mirrorlist'].nil? + gpgcheck node['yum']['mysql-connectors-community']['gpgcheck'] unless node['yum']['mysql-connectors-community']['gpgcheck'].nil? + gpgkey node['yum']['mysql-connectors-community']['gpgkey'] unless node['yum']['mysql-connectors-community']['gpgkey'].nil? + enabled node['yum']['mysql-connectors-community']['enabled'] unless node['yum']['mysql-connectors-community']['enabled'].nil? + cost node['yum']['mysql-connectors-community']['cost'] unless node['yum']['mysql-connectors-community']['cost'].nil? + exclude node['yum']['mysql-connectors-community']['exclude'] unless node['yum']['mysql-connectors-community']['exclude'].nil? + enablegroups node['yum']['mysql-connectors-community']['enablegroups'] unless node['yum']['mysql-connectors-community']['enablegroups'].nil? + failovermethod node['yum']['mysql-connectors-community']['failovermethod'] unless node['yum']['mysql-connectors-community']['failovermethod'].nil? + http_caching node['yum']['mysql-connectors-community']['http_caching'] unless node['yum']['mysql-connectors-community']['http_caching'].nil? + include_config node['yum']['mysql-connectors-community']['include_config'] unless node['yum']['mysql-connectors-community']['include_config'].nil? + includepkgs node['yum']['mysql-connectors-community']['includepkgs'] unless node['yum']['mysql-connectors-community']['includepkgs'].nil? + keepalive node['yum']['mysql-connectors-community']['keepalive'] unless node['yum']['mysql-connectors-community']['keepalive'].nil? + max_retries node['yum']['mysql-connectors-community']['max_retries'] unless node['yum']['mysql-connectors-community']['max_retries'].nil? + metadata_expire node['yum']['mysql-connectors-community']['metadata_expire'] unless node['yum']['mysql-connectors-community']['metadata_expire'].nil? + mirror_expire node['yum']['mysql-connectors-community']['mirror_expire'] unless node['yum']['mysql-connectors-community']['mirror_expire'].nil? + priority node['yum']['mysql-connectors-community']['priority'] unless node['yum']['mysql-connectors-community']['priority'].nil? + proxy node['yum']['mysql-connectors-community']['proxy'] unless node['yum']['mysql-connectors-community']['proxy'].nil? + proxy_username node['yum']['mysql-connectors-community']['proxy_username'] unless node['yum']['mysql-connectors-community']['proxy_username'].nil? + proxy_password node['yum']['mysql-connectors-community']['proxy_password'] unless node['yum']['mysql-connectors-community']['proxy_password'].nil? + repositoryid node['yum']['mysql-connectors-community']['repositoryid'] unless node['yum']['mysql-connectors-community']['repositoryid'].nil? + sslcacert node['yum']['mysql-connectors-community']['sslcacert'] unless node['yum']['mysql-connectors-community']['sslcacert'].nil? + sslclientcert node['yum']['mysql-connectors-community']['sslclientcert'] unless node['yum']['mysql-connectors-community']['sslclientcert'].nil? + sslclientkey node['yum']['mysql-connectors-community']['sslclientkey'] unless node['yum']['mysql-connectors-community']['sslclientkey'].nil? + sslverify node['yum']['mysql-connectors-community']['sslverify'] unless node['yum']['mysql-connectors-community']['sslverify'].nil? + timeout node['yum']['mysql-connectors-community']['timeout'] unless node['yum']['mysql-connectors-community']['timeout'].nil? action :create end diff --git a/cookbooks/yum-mysql-community/recipes/mysql55.rb b/cookbooks/yum-mysql-community/recipes/mysql55.rb index e675ce3..6b6d46c 100644 --- a/cookbooks/yum-mysql-community/recipes/mysql55.rb +++ b/cookbooks/yum-mysql-community/recipes/mysql55.rb @@ -2,7 +2,7 @@ # Author:: Sean OMeara () # Recipe:: yum-mysql-community::mysql55 # -# Copyright 2014, Chef Software, Inc. +# Copyright 2014-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. @@ -17,32 +17,32 @@ # limitations under the License. yum_repository 'mysql55-community' do - description node['yum']['mysql55-community']['description'] - baseurl node['yum']['mysql55-community']['baseurl'] - mirrorlist node['yum']['mysql55-community']['mirrorlist'] - gpgcheck node['yum']['mysql55-community']['gpgcheck'] - gpgkey node['yum']['mysql55-community']['gpgkey'] - enabled node['yum']['mysql55-community']['enabled'] - cost node['yum']['mysql55-community']['cost'] - exclude node['yum']['mysql55-community']['exclude'] - enablegroups node['yum']['mysql55-community']['enablegroups'] - failovermethod node['yum']['mysql55-community']['failovermethod'] - http_caching node['yum']['mysql55-community']['http_caching'] - include_config node['yum']['mysql55-community']['include_config'] - includepkgs node['yum']['mysql55-community']['includepkgs'] - keepalive node['yum']['mysql55-community']['keepalive'] - max_retries node['yum']['mysql55-community']['max_retries'] - metadata_expire node['yum']['mysql55-community']['metadata_expire'] - mirror_expire node['yum']['mysql55-community']['mirror_expire'] - priority node['yum']['mysql55-community']['priority'] - proxy node['yum']['mysql55-community']['proxy'] - proxy_username node['yum']['mysql55-community']['proxy_username'] - proxy_password node['yum']['mysql55-community']['proxy_password'] - repositoryid node['yum']['mysql55-community']['repositoryid'] - sslcacert node['yum']['mysql55-community']['sslcacert'] - sslclientcert node['yum']['mysql55-community']['sslclientcert'] - sslclientkey node['yum']['mysql55-community']['sslclientkey'] - sslverify node['yum']['mysql55-community']['sslverify'] - timeout node['yum']['mysql55-community']['timeout'] + description node['yum']['mysql55-community']['description'] unless node['yum']['mysql55-community']['description'].nil? + baseurl node['yum']['mysql55-community']['baseurl'] unless node['yum']['mysql55-community']['baseurl'].nil? + mirrorlist node['yum']['mysql55-community']['mirrorlist'] unless node['yum']['mysql55-community']['mirrorlist'].nil? + gpgcheck node['yum']['mysql55-community']['gpgcheck'] unless node['yum']['mysql55-community']['gpgcheck'].nil? + gpgkey node['yum']['mysql55-community']['gpgkey'] unless node['yum']['mysql55-community']['gpgkey'].nil? + enabled node['yum']['mysql55-community']['enabled'] unless node['yum']['mysql55-community']['enabled'].nil? + cost node['yum']['mysql55-community']['cost'] unless node['yum']['mysql55-community']['cost'].nil? + exclude node['yum']['mysql55-community']['exclude'] unless node['yum']['mysql55-community']['exclude'].nil? + enablegroups node['yum']['mysql55-community']['enablegroups'] unless node['yum']['mysql55-community']['enablegroups'].nil? + failovermethod node['yum']['mysql55-community']['failovermethod'] unless node['yum']['mysql55-community']['failovermethod'].nil? + http_caching node['yum']['mysql55-community']['http_caching'] unless node['yum']['mysql55-community']['http_caching'].nil? + include_config node['yum']['mysql55-community']['include_config'] unless node['yum']['mysql55-community']['include_config'].nil? + includepkgs node['yum']['mysql55-community']['includepkgs'] unless node['yum']['mysql55-community']['includepkgs'].nil? + keepalive node['yum']['mysql55-community']['keepalive'] unless node['yum']['mysql55-community']['keepalive'].nil? + max_retries node['yum']['mysql55-community']['max_retries'] unless node['yum']['mysql55-community']['max_retries'].nil? + metadata_expire node['yum']['mysql55-community']['metadata_expire'] unless node['yum']['mysql55-community']['metadata_expire'].nil? + mirror_expire node['yum']['mysql55-community']['mirror_expire'] unless node['yum']['mysql55-community']['mirror_expire'].nil? + priority node['yum']['mysql55-community']['priority'] unless node['yum']['mysql55-community']['priority'].nil? + proxy node['yum']['mysql55-community']['proxy'] unless node['yum']['mysql55-community']['proxy'].nil? + proxy_username node['yum']['mysql55-community']['proxy_username'] unless node['yum']['mysql55-community']['proxy_username'].nil? + proxy_password node['yum']['mysql55-community']['proxy_password'] unless node['yum']['mysql55-community']['proxy_password'].nil? + repositoryid node['yum']['mysql55-community']['repositoryid'] unless node['yum']['mysql55-community']['repositoryid'].nil? + sslcacert node['yum']['mysql55-community']['sslcacert'] unless node['yum']['mysql55-community']['sslcacert'].nil? + sslclientcert node['yum']['mysql55-community']['sslclientcert'] unless node['yum']['mysql55-community']['sslclientcert'].nil? + sslclientkey node['yum']['mysql55-community']['sslclientkey'] unless node['yum']['mysql55-community']['sslclientkey'].nil? + sslverify node['yum']['mysql55-community']['sslverify'] unless node['yum']['mysql55-community']['sslverify'].nil? + timeout node['yum']['mysql55-community']['timeout'] unless node['yum']['mysql55-community']['timeout'].nil? action :create end diff --git a/cookbooks/yum-mysql-community/recipes/mysql56.rb b/cookbooks/yum-mysql-community/recipes/mysql56.rb index 6b6bb33..5adb378 100644 --- a/cookbooks/yum-mysql-community/recipes/mysql56.rb +++ b/cookbooks/yum-mysql-community/recipes/mysql56.rb @@ -2,7 +2,7 @@ # Author:: Sean OMeara () # Recipe:: yum-mysql-community::mysql56-community # -# Copyright 2014, Chef Software, Inc. +# Copyright 2014-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. @@ -17,32 +17,32 @@ # limitations under the License. yum_repository 'mysql56-community' do - description node['yum']['mysql56-community']['description'] - baseurl node['yum']['mysql56-community']['baseurl'] - mirrorlist node['yum']['mysql56-community']['mirrorlist'] - gpgcheck node['yum']['mysql56-community']['gpgcheck'] - gpgkey node['yum']['mysql56-community']['gpgkey'] - enabled node['yum']['mysql56-community']['enabled'] - cost node['yum']['mysql56-community']['cost'] - exclude node['yum']['mysql56-community']['exclude'] - enablegroups node['yum']['mysql56-community']['enablegroups'] - failovermethod node['yum']['mysql56-community']['failovermethod'] - http_caching node['yum']['mysql56-community']['http_caching'] - include_config node['yum']['mysql56-community']['include_config'] - includepkgs node['yum']['mysql56-community']['includepkgs'] - keepalive node['yum']['mysql56-community']['keepalive'] - max_retries node['yum']['mysql56-community']['max_retries'] - metadata_expire node['yum']['mysql56-community']['metadata_expire'] - mirror_expire node['yum']['mysql56-community']['mirror_expire'] - priority node['yum']['mysql56-community']['priority'] - proxy node['yum']['mysql56-community']['proxy'] - proxy_username node['yum']['mysql56-community']['proxy_username'] - proxy_password node['yum']['mysql56-community']['proxy_password'] - repositoryid node['yum']['mysql56-community']['repositoryid'] - sslcacert node['yum']['mysql56-community']['sslcacert'] - sslclientcert node['yum']['mysql56-community']['sslclientcert'] - sslclientkey node['yum']['mysql56-community']['sslclientkey'] - sslverify node['yum']['mysql56-community']['sslverify'] - timeout node['yum']['mysql56-community']['timeout'] + description node['yum']['mysql56-community']['description'] unless node['yum']['mysql56-community']['description'].nil? + baseurl node['yum']['mysql56-community']['baseurl'] unless node['yum']['mysql56-community']['baseurl'].nil? + mirrorlist node['yum']['mysql56-community']['mirrorlist'] unless node['yum']['mysql56-community']['mirrorlist'].nil? + gpgcheck node['yum']['mysql56-community']['gpgcheck'] unless node['yum']['mysql56-community']['gpgcheck'].nil? + gpgkey node['yum']['mysql56-community']['gpgkey'] unless node['yum']['mysql56-community']['gpgkey'].nil? + enabled node['yum']['mysql56-community']['enabled'] unless node['yum']['mysql56-community']['enabled'].nil? + cost node['yum']['mysql56-community']['cost'] unless node['yum']['mysql56-community']['cost'].nil? + exclude node['yum']['mysql56-community']['exclude'] unless node['yum']['mysql56-community']['exclude'].nil? + enablegroups node['yum']['mysql56-community']['enablegroups'] unless node['yum']['mysql56-community']['enablegroups'].nil? + failovermethod node['yum']['mysql56-community']['failovermethod'] unless node['yum']['mysql56-community']['failovermethod'].nil? + http_caching node['yum']['mysql56-community']['http_caching'] unless node['yum']['mysql56-community']['http_caching'].nil? + include_config node['yum']['mysql56-community']['include_config'] unless node['yum']['mysql56-community']['include_config'].nil? + includepkgs node['yum']['mysql56-community']['includepkgs'] unless node['yum']['mysql56-community']['includepkgs'].nil? + keepalive node['yum']['mysql56-community']['keepalive'] unless node['yum']['mysql56-community']['keepalive'].nil? + max_retries node['yum']['mysql56-community']['max_retries'] unless node['yum']['mysql56-community']['max_retries'].nil? + metadata_expire node['yum']['mysql56-community']['metadata_expire'] unless node['yum']['mysql56-community']['metadata_expire'].nil? + mirror_expire node['yum']['mysql56-community']['mirror_expire'] unless node['yum']['mysql56-community']['mirror_expire'].nil? + priority node['yum']['mysql56-community']['priority'] unless node['yum']['mysql56-community']['priority'].nil? + proxy node['yum']['mysql56-community']['proxy'] unless node['yum']['mysql56-community']['proxy'].nil? + proxy_username node['yum']['mysql56-community']['proxy_username'] unless node['yum']['mysql56-community']['proxy_username'].nil? + proxy_password node['yum']['mysql56-community']['proxy_password'] unless node['yum']['mysql56-community']['proxy_password'].nil? + repositoryid node['yum']['mysql56-community']['repositoryid'] unless node['yum']['mysql56-community']['repositoryid'].nil? + sslcacert node['yum']['mysql56-community']['sslcacert'] unless node['yum']['mysql56-community']['sslcacert'].nil? + sslclientcert node['yum']['mysql56-community']['sslclientcert'] unless node['yum']['mysql56-community']['sslclientcert'].nil? + sslclientkey node['yum']['mysql56-community']['sslclientkey'] unless node['yum']['mysql56-community']['sslclientkey'].nil? + sslverify node['yum']['mysql56-community']['sslverify'] unless node['yum']['mysql56-community']['sslverify'].nil? + timeout node['yum']['mysql56-community']['timeout'] unless node['yum']['mysql56-community']['timeout'].nil? action :create end diff --git a/cookbooks/yum-mysql-community/recipes/mysql57.rb b/cookbooks/yum-mysql-community/recipes/mysql57.rb index dafe194..ba617c1 100644 --- a/cookbooks/yum-mysql-community/recipes/mysql57.rb +++ b/cookbooks/yum-mysql-community/recipes/mysql57.rb @@ -2,7 +2,7 @@ # Author:: Sean OMeara () # Recipe:: yum-mysql-community::mysql57-community # -# Copyright 2014, Chef Software, Inc. +# Copyright 2014-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. @@ -17,32 +17,32 @@ # limitations under the License. yum_repository 'mysql57-community' do - description node['yum']['mysql57-community']['description'] - baseurl node['yum']['mysql57-community']['baseurl'] - mirrorlist node['yum']['mysql57-community']['mirrorlist'] - gpgcheck node['yum']['mysql57-community']['gpgcheck'] - gpgkey node['yum']['mysql57-community']['gpgkey'] - enabled node['yum']['mysql57-community']['enabled'] - cost node['yum']['mysql57-community']['cost'] - exclude node['yum']['mysql57-community']['exclude'] - enablegroups node['yum']['mysql57-community']['enablegroups'] - failovermethod node['yum']['mysql57-community']['failovermethod'] - http_caching node['yum']['mysql57-community']['http_caching'] - include_config node['yum']['mysql57-community']['include_config'] - includepkgs node['yum']['mysql57-community']['includepkgs'] - keepalive node['yum']['mysql57-community']['keepalive'] - max_retries node['yum']['mysql57-community']['max_retries'] - metadata_expire node['yum']['mysql57-community']['metadata_expire'] - mirror_expire node['yum']['mysql57-community']['mirror_expire'] - priority node['yum']['mysql57-community']['priority'] - proxy node['yum']['mysql57-community']['proxy'] - proxy_username node['yum']['mysql57-community']['proxy_username'] - proxy_password node['yum']['mysql57-community']['proxy_password'] - repositoryid node['yum']['mysql57-community']['repositoryid'] - sslcacert node['yum']['mysql57-community']['sslcacert'] - sslclientcert node['yum']['mysql57-community']['sslclientcert'] - sslclientkey node['yum']['mysql57-community']['sslclientkey'] - sslverify node['yum']['mysql57-community']['sslverify'] - timeout node['yum']['mysql57-community']['timeout'] + description node['yum']['mysql57-community']['description'] unless node['yum']['mysql57-community']['description'].nil? + baseurl node['yum']['mysql57-community']['baseurl'] unless node['yum']['mysql57-community']['baseurl'].nil? + mirrorlist node['yum']['mysql57-community']['mirrorlist'] unless node['yum']['mysql57-community']['mirrorlist'].nil? + gpgcheck node['yum']['mysql57-community']['gpgcheck'] unless node['yum']['mysql57-community']['gpgcheck'].nil? + gpgkey node['yum']['mysql57-community']['gpgkey'] unless node['yum']['mysql57-community']['gpgkey'].nil? + enabled node['yum']['mysql57-community']['enabled'] unless node['yum']['mysql57-community']['enabled'].nil? + cost node['yum']['mysql57-community']['cost'] unless node['yum']['mysql57-community']['cost'].nil? + exclude node['yum']['mysql57-community']['exclude'] unless node['yum']['mysql57-community']['exclude'].nil? + enablegroups node['yum']['mysql57-community']['enablegroups'] unless node['yum']['mysql57-community']['enablegroups'].nil? + failovermethod node['yum']['mysql57-community']['failovermethod'] unless node['yum']['mysql57-community']['failovermethod'].nil? + http_caching node['yum']['mysql57-community']['http_caching'] unless node['yum']['mysql57-community']['http_caching'].nil? + include_config node['yum']['mysql57-community']['include_config'] unless node['yum']['mysql57-community']['include_config'].nil? + includepkgs node['yum']['mysql57-community']['includepkgs'] unless node['yum']['mysql57-community']['includepkgs'].nil? + keepalive node['yum']['mysql57-community']['keepalive'] unless node['yum']['mysql57-community']['keepalive'].nil? + max_retries node['yum']['mysql57-community']['max_retries'] unless node['yum']['mysql57-community']['max_retries'].nil? + metadata_expire node['yum']['mysql57-community']['metadata_expire'] unless node['yum']['mysql57-community']['metadata_expire'].nil? + mirror_expire node['yum']['mysql57-community']['mirror_expire'] unless node['yum']['mysql57-community']['mirror_expire'].nil? + priority node['yum']['mysql57-community']['priority'] unless node['yum']['mysql57-community']['priority'].nil? + proxy node['yum']['mysql57-community']['proxy'] unless node['yum']['mysql57-community']['proxy'].nil? + proxy_username node['yum']['mysql57-community']['proxy_username'] unless node['yum']['mysql57-community']['proxy_username'].nil? + proxy_password node['yum']['mysql57-community']['proxy_password'] unless node['yum']['mysql57-community']['proxy_password'].nil? + repositoryid node['yum']['mysql57-community']['repositoryid'] unless node['yum']['mysql57-community']['repositoryid'].nil? + sslcacert node['yum']['mysql57-community']['sslcacert'] unless node['yum']['mysql57-community']['sslcacert'].nil? + sslclientcert node['yum']['mysql57-community']['sslclientcert'] unless node['yum']['mysql57-community']['sslclientcert'].nil? + sslclientkey node['yum']['mysql57-community']['sslclientkey'] unless node['yum']['mysql57-community']['sslclientkey'].nil? + sslverify node['yum']['mysql57-community']['sslverify'] unless node['yum']['mysql57-community']['sslverify'].nil? + timeout node['yum']['mysql57-community']['timeout'] unless node['yum']['mysql57-community']['timeout'].nil? action :create end diff --git a/cookbooks/yum/CHANGELOG.md b/cookbooks/yum/CHANGELOG.md index f23bc47..da538bd 100644 --- a/cookbooks/yum/CHANGELOG.md +++ b/cookbooks/yum/CHANGELOG.md @@ -1,104 +1,113 @@ -yum Cookbook CHANGELOG -====================== +# yum Cookbook CHANGELOG This file is used to list changes made in each version of the yum cookbook. -v3.6.1 (2015-06-04) -------------------- +## 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) -------------------- +## 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) -------------------- +## v3.5.4 (2015-04-07) - Changing tolerant config line to stringified integer -v3.5.3 (2015-01-16) -------------------- +## v3.5.3 (2015-01-16) - Adding reposdir to globalconfig template -v3.5.2 (2014-12-24) -------------------- +## v3.5.2 (2014-12-24) - Fixing redhat-release detection for Redhat 7 -v3.5.1 (2014-11-24) -------------------- +## v3.5.1 (2014-11-24) - Reverting management of ca-certificates because EL5 was broken -v3.5.0 (2014-11-24) -------------------- +## v3.5.0 (2014-11-24) - Adding management of ca-certificates package to yum_repository provider -v3.4.1 (2014-10-29) -------------------- +## 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) -------------------- +## v3.4.0 (2014-10-15) - Dynamically generate the new_resource attributes -v3.3.2 (2014-09-11) -------------------- +## v3.3.2 (2014-09-11) - Fix globalconfig resource param for http_caching -v3.3.1 (2014-09-04) -------------------- +## v3.3.1 (2014-09-04) - Fix issue with sslverify if set to false - Add fancy badges -v3.3.0 (2014-09-03) -------------------- +## 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) +- 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.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.2 (2014-06-11) +- #77 - Parameter default to be Trueclass instead of "1" +- #78 - add releasever parameter - -v3.2.0 (2014-04-09) -------------------- +## 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) -------------------- +## 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) -------------------- +## 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.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) -------------------- +## 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 @@ -108,83 +117,51 @@ v3.1.0 (2014-02-13) - Adding full spec coverage - Adding support for custom source template to yum_repository - -v3.0.8 (2014-01-27) -------------------- +## v3.0.8 (2014-01-27) Fixing typo in default.rb. yum_globalconfig now passes proxy attribute correctly. - -v3.0.6 (2014-01-27) -------------------- +## v3.0.6 (2014-01-27) Updating default.rb to consume node['yum']['main']['proxy'] - -v3.0.4 (2013-12-29) -------------------- +## 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 ------- +## 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 -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 ------- +## 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.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 ------- +## v2.4.0 ### Improvement - [COOK-3025] - Allow per-repo proxy definitions - -v2.3.4 ------- +## 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 ------- +## v2.3.2 ### Bug - **[COOK-3145](https://tickets.chef.io/browse/COOK-3145)** - Use correct download URL for epel `key_url` -v2.3.0 ------- +## v2.3.0 ### New Feature - [COOK-2924]: Yum should allow type setting in repo file -v2.2.4 ------- +## 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 ------- +## v2.2.2 ### Improvement - [COOK-2741]: yum::elrepo - [COOK-2946]: update tests, test kitchen support in yum cookbook @@ -194,8 +171,7 @@ v2.2.2 - [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 ------- +## 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 @@ -204,56 +180,44 @@ v2.2.0 - [COOK-2593] - allow integer or string for yum priority - [COOK-2643] - don't use conditional attribute for `yum_key` `remote_file` -v2.1.0 ------- +## v2.1.0 - [COOK-2045] - add remi repository recipe - [COOK-2121] - add `:create` action to `yum_repository` -v2.0.6 ------- +## v2.0.6 - [COOK-2037] - minor style fixes - [COOK-2038] - updated README -v2.0.4 ------- +## v2.0.4 - [COOK-1908] - unable to install repoforge on CentOS 6 32 bit -v2.0.2 ------- +## v2.0.2 - [COOK-1758] - Add default action for repository resource -v2.0.0 ------- +## 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 ------- +## 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 ------- +## v0.8.2 - [COOK-1521] - add :update action to `yum_repository` -v0.8.0 ------- +## 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 ------- +## v0.6.2 - Updated README to remove git diff artifacts. -v0.6.0 ------- +## 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 @@ -261,16 +225,12 @@ v0.6.0 - [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 ------- +## v0.5.2 - [COOK-825] - epel and ius `remote_file` should notify the `rpm_package` to install -v0.5.0 ------- +## v0.5.0 - [COOK-675] - add recipe for handling EPEL repository - [COOK-722] - add recipe for handling IUS repository -v.0.1.2 ------- +## 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/MAINTAINERS.md b/cookbooks/yum/MAINTAINERS.md new file mode 100644 index 0000000..f180113 --- /dev/null +++ b/cookbooks/yum/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 +* [Sean OMeara](https://github.com/someara) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Sean OMeara](https://github.com/someara) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) diff --git a/cookbooks/yum/README.md b/cookbooks/yum/README.md index 6aa9da0..94527cc 100644 --- a/cookbooks/yum/README.md +++ b/cookbooks/yum/README.md @@ -1,43 +1,29 @@ -yum Cookbook -============ +# 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) [![Code Climate](https://codeclimate.com/github/chef-cookbooks/yum/badges/gpa.svg)](https://codeclimate.com/github/chef-cookbooks/yum) -[![Join the chat at https://gitter.im/chef-cookbooks/yum](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/chef-cookbooks/yum?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +The Yum cookbook exposes the `yum_globalconfig` and `yum_repository` resources that allows a user to both control global behavior and make individual Yum repositories available for use. These resources aim to allow the user to configure all options listed in the `yum.conf` man page, found at [http://linux.die.net/man/5/yum.conf](http://linux.die.net/man/5/yum.conf) -[![Cookbook Version](https://img.shields.io/cookbook/v/yum.svg)](https://supermarket.chef.io/cookbooks/yum) -[![Travis status](http://img.shields.io/travis/chef-cookbooks/yum.svg)](https://travis-ci.org/chef-cookbooks/yum) +## NOTES +WARNING: Yum cookbook version 3.0.0 and above contain non-backwards compatible breaking changes and will not work with cookbooks written against the 2.x and 1.x series. Changes have been made to the yum_repository resource, and the yum_key resource has been eliminated entirely. Recipes have been eliminated and moved into their own cookbooks. Please lock yum to the 2.x series in your Chef environments until all dependent cookbooks have been ported. -The Yum cookbook exposes the `yum_globalconfig` and `yum_repository` -resources that allows a user to both control global behavior and make -individual Yum repositories available for use. These resources aim to -allow the user to configure all options listed in the `yum.conf` man -page, found at http://linux.die.net/man/5/yum.conf +## Requirements +### Platforms +- RHEL/CentOS and derivatives +- Fedora -NOTES ------ -WARNING: Yum cookbook version 3.0.0 and above contain non-backwards -compatible breaking changes and will not work with cookbooks written -against the 2.x and 1.x series. Changes have been made to the -yum_repository resource, and the yum_key resource has been eliminated -entirely. Recipes have been eliminated and moved into their own -cookbooks. Please lock yum to the 2.x series in your Chef environments -until all dependent cookbooks have been ported. +### Chef +- Chef 11+ -Requirements ------------- -* Chef 11 or higher -* Ruby 1.9 (preferably from the Chef full-stack installer) -* RHEL5, RHEL6, or other platforms within the family +### Cookbooks +- none -Resources/Providers -------------------- +## Resources/Providers ### yum_repository -This resource manages a yum repository configuration file at -/etc/yum.repos.d/`repositoryid`.repo. When the file needs to be -repaired, it calls yum-makecache so packages in the repo become -available to the next resource. +This resource manages a yum repository configuration file at /etc/yum.repos.d/`repositoryid`.repo. When the file needs to be repaired, it calls yum-makecache so packages in the repo become available to the next resource. #### Example -``` ruby + +```ruby # add the Zenoss repository yum_repository 'zenoss' do description "Zenoss Stable repo" @@ -55,7 +41,7 @@ yum_repository 'epel' do end ``` -``` ruby +```ruby # delete CentOS-Media repo yum_repository 'CentOS-Media' do action :delete @@ -68,108 +54,47 @@ end - `:makecache` - update yum cache #### Parameters -* `baseurl` - Must be a URL to the directory where the yum repository's - 'repodata' directory lives. Can be an http://, ftp:// or file:// - URL. You can specify multiple URLs in one baseurl statement. -* `cost` - relative cost of accessing this repository. Useful for - weighing one repo's packages as greater/less than any other. - defaults to 1000 -* `description` - Maps to the 'name' parameter in a repository .conf. - Descriptive name for the repository channel. This directive must be - specified. -* `enabled` - Either `true` or `false`. This tells yum whether or not use this repository. -* `enablegroups` - Either `true` or `false`. Determines whether yum - will allow the use of package groups for this repository. Default is - `true` (package groups are allowed). -* `exclude` - List of packages to exclude from updates or installs. This - should be a space separated list in a single string. Shell globs using wildcards (eg. * - and ?) are allowed. -* `failovermethod` - Either 'roundrobin' or 'priority'. -* `fastestmirror_enabled` - Either `true` or `false` -* `gpgcheck` - Either `true` or `false`. This tells yum whether or not - it should perform a GPG signature check on packages. When this is - set in the [main] section it sets the default for all repositories. - The default is `true`. -* `gpgkey` - A URL pointing to the ASCII-armored GPG key file for the - repository. This option is used if yum needs a public key to verify - a package and the required key hasn't been imported into the RPM - database. If this option is set, yum will automatically import the - key from the specified URL. -* `http_caching` - Either 'all', 'packages', or 'none'. Determines how - upstream HTTP caches are instructed to handle any HTTP downloads - that Yum does. Defaults to 'all' -* `includepkgs` - Inverse of exclude. This is a list of packages you - want to use from a repository. If this option lists only one package - then that is all yum will ever see from the repository. Defaults to - an empty list. -* `keepalive` - Either `true` or `false`. This tells yum whether or not - HTTP/1.1 keepalive should be used with this repository. -* `make_cache` - Optional, Default is `true`, if `false` then `yum -q makecache` will not - be ran -* `max_retries` - Set the number of times any attempt to retrieve a file - should retry before returning an error. Setting this to '0' makes - yum try forever. Default is '10'. -* `metadata_expire` - Time (in seconds) after which the metadata will - expire. So that if the current metadata downloaded is less than this - many seconds old then yum will not update the metadata against the - repository. If you find that yum is not downloading information on - updates as often as you would like lower the value of this option. - You can also change from the default of using seconds to using days, - hours or minutes by appending a d, h or m respectively. The default - is 6 hours, to compliment yum-updatesd running once an hour. It's - also possible to use the word "never", meaning that the metadata - will never expire. Note that when using a metalink file the metalink - must always be newer than the metadata for the repository, due to - the validation, so this timeout also applies to the metalink file. -* `mirrorlist` - Specifies a URL to a file containing a list of - baseurls. This can be used instead of or with the baseurl option. - Substitution variables, described below, can be used with this - option. As a special hack is the mirrorlist URL contains the word - "metalink" then the value of mirrorlist is copied to metalink (if - metalink is not set) -* `mirror_expire` - Time (in seconds) after which the mirrorlist locally - cached will expire. If the current mirrorlist is less than this many - seconds old then yum will not download another copy of the - mirrorlist, it has the same extra format as metadata_expire. If you - find that yum is not downloading the mirrorlists as often as you - would like lower the value of this option. -* `mirrorlist_expire` - alias for mirror_expire -* `mode` - Permissions mode of .repo file on disk. Useful for - scenarios where secrets are in the repo file. If set to '600', - normal users will not be able to use yum search, yum info, etc. - Defaults to '0644' -* `priority` - When the yum-priorities plug-in is enabled, you set - priorities on repository entries, where N is an integer from 1 to 99. The - default priority for repositories is 99. -* `proxy` - URL to the proxy server that yum should use. -* `proxy_username` - username to use for proxy -* `proxy_password` - password for this proxy -* `report_instanceid` - Report instance ID when using Amazon Linux AMIs - and repositories -* `repositoryid` - Must be a unique name for each repository, one word. - Defaults to name attribute. -* `source` - Use a custom template source instead of the default one - in the yum cookbook -* `sslcacert` - Path to the directory containing the databases of the - certificate authorities yum should use to verify SSL certificates. - Defaults to none - uses system default -* `sslclientcert` - Path to the SSL client certificate yum should use to - connect to repos/remote sites Defaults to none. -* `sslclientkey` - Path to the SSL client key yum should use to connect - to repos/remote sites Defaults to none. -* `sslverify` - Either `true` or `false`. Determines if yum will verify SSL certificates/hosts. Defaults to `true` -* `timeout` - Number of seconds to wait for a connection before timing - out. Defaults to 30 seconds. This may be too short of a time for - extremely overloaded sites. +- `baseurl` - Must be a URL to the directory where the yum repository's 'repodata' directory lives. Can be an http://, ftp:// or file:// URL. You can specify multiple URLs in one baseurl statement. +- `cost` - relative cost of accessing this repository. Useful for weighing one repo's packages as greater/less than any other. defaults to 1000 +- `clean_metadata` - Run "yum clean metadata " during repository creation. defaults to true. +- `description` - Maps to the 'name' parameter in a repository .conf. Descriptive name for the repository channel. This directive must be specified. +- `enabled` - Either `true` or `false`. This tells yum whether or not use this repository. +- `enablegroups` - Either `true` or `false`. Determines whether yum will allow the use of package groups for this repository. Default is `true` (package groups are allowed). +- `exclude` - List of packages to exclude from updates or installs. This should be a space separated list in a single string. Shell globs using wildcards (eg. * and ?) are allowed. +- `failovermethod` - Either 'roundrobin' or 'priority'. +- `fastestmirror_enabled` - Either `true` or `false` +- `gpgcheck` - Either `true` or `false`. This tells yum whether or not it should perform a GPG signature check on packages. When this is set in the [main] section it sets the default for all repositories. The default is `true`. +- `gpgkey` - A URL pointing to the ASCII-armored GPG key file for the repository. This option is used if yum needs a public key to verify a package and the required key hasn't been imported into the RPM database. If this option is set, yum will automatically import the key from the specified URL. +- `http_caching` - Either 'all', 'packages', or 'none'. Determines how upstream HTTP caches are instructed to handle any HTTP downloads that Yum does. Defaults to 'all' +- `includepkgs` - Inverse of exclude. This is a list of packages you want to use from a repository. If this option lists only one package then that is all yum will ever see from the repository. Defaults to an empty list. +- `keepalive` - Either `true` or `false`. This tells yum whether or not HTTP/1.1 keepalive should be used with this repository. +- `make_cache` - Optional, Default is `true`, if `false` then `yum -q makecache` will not be ran +- `max_retries` - Set the number of times any attempt to retrieve a file should retry before returning an error. Setting this to '0' makes yum try forever. Default is '10'. +- `metadata_expire` - Time (in seconds) after which the metadata will expire. So that if the current metadata downloaded is less than this many seconds old then yum will not update the metadata against the repository. If you find that yum is not downloading information on updates as often as you would like lower the value of this option. You can also change from the default of using seconds to using days, hours or minutes by appending a d, h or m respectively. The default is 6 hours, to compliment yum-updatesd running once an hour. It's also possible to use the word "never", meaning that the metadata will never expire. Note that when using a metalink file the metalink must always be newer than the metadata for the repository, due to the validation, so this timeout also applies to the metalink file. +- `mirrorlist` - Specifies a URL to a file containing a list of baseurls. This can be used instead of or with the baseurl option. Substitution variables, described below, can be used with this option. As a special hack is the mirrorlist URL contains the word "metalink" then the value of mirrorlist is copied to metalink (if metalink is not set) +- `mirror_expire` - Time (in seconds) after which the mirrorlist locally cached will expire. If the current mirrorlist is less than this many seconds old then yum will not download another copy of the mirrorlist, it has the same extra format as metadata_expire. If you find that yum is not downloading the mirrorlists as often as you would like lower the value of this option. +- `mirrorlist_expire` - alias for mirror_expire +- `mode` - Permissions mode of .repo file on disk. Useful for scenarios where secrets are in the repo file. If set to '600', normal users will not be able to use yum search, yum info, etc. Defaults to '0644' +- `priority` - When the yum-priorities plug-in is enabled, you set priorities on repository entries, where N is an integer from 1 to 99. The default priority for repositories is 99. +- `proxy` - URL to the proxy server that yum should use. +- `proxy_username` - username to use for proxy +- `proxy_password` - password for this proxy +- `report_instanceid` - Report instance ID when using Amazon Linux AMIs and repositories +- `repositoryid` - Must be a unique name for each repository, one word. Defaults to name attribute. +- `sensitive` - Optional, Default is `false`, if `true` then content of repository file is hidden from chef run output. +- `source` - Use a custom template source instead of the default one in the yum cookbook +- `sslcacert` - Path to the directory containing the databases of the certificate authorities yum should use to verify SSL certificates. Defaults to none - uses system default +- `sslclientcert` - Path to the SSL client certificate yum should use to connect to repos/remote sites Defaults to none. +- `sslclientkey` - Path to the SSL client key yum should use to connect to repos/remote sites Defaults to none. +- `sslverify` - Either `true` or `false`. Determines if yum will verify SSL certificates/hosts. Defaults to `true` +- `timeout` - Number of seconds to wait for a connection before timing out. Defaults to 30 seconds. This may be too short of a time for extremely overloaded sites. ### 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`. +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 + +```ruby yum_globalconfig '/my/chroot/etc/yum.conf' do cachedir '/my/chroot/etc/yum.conf' keepcache 'yes' @@ -180,47 +105,24 @@ end ``` #### Parameters -`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: -http://linux.die.net/man/5/yum.conf +`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: [http://linux.die.net/man/5/yum.conf](http://linux.die.net/man/5/yum.conf) +- `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. -* `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. - -Recipes -------- -* `default` - Configures `yum_globalconfig[/etc/yum.conf]` with values - found in node attributes at `node['yum']['main']` +## 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 as Chef does not yet (as of Q4 2015) have native support for DNF. This recipe should be 1st on a Fedora runlist -Attributes ----------- +## Attributes The following attributes are set by default -``` ruby +```ruby default['yum']['main']['cachedir'] = '/var/cache/yum/$basearch/$releasever' default['yum']['main']['keepcache'] = false default['yum']['main']['debuglevel'] = nil @@ -233,38 +135,30 @@ default['yum']['main']['installonlypkgs'] = nil default['yum']['main']['installroot'] = nil ``` -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. +## 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 -* 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. -Usage ------ -Put `depends 'yum'` in your metadata.rb to gain access to the -yum_repository resource. - -License & Authors ------------------ +## License & Authors - Author:: Eric G. Wolfe -- Author:: Matt Ray () -- Author:: Joshua Timberman () -- Author:: Sean OMeara () +- 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 Chef +Copyright:: 2013-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. diff --git a/cookbooks/yum/attributes/main.rb b/cookbooks/yum/attributes/main.rb index 9c0012c..7c09fff 100644 --- a/cookbooks/yum/attributes/main.rb +++ b/cookbooks/yum/attributes/main.rb @@ -1,24 +1,24 @@ # http://linux.die.net/man/5/yum.conf -case node['platform_version'].to_i -when 5 - default['yum']['main']['cachedir'] = '/var/cache/yum' -else - default['yum']['main']['cachedir'] = '/var/cache/yum/$basearch/$releasever' -end +default['yum']['main']['cachedir'] = case node['platform_version'].to_i + when 5 + '/var/cache/yum' + else + '/var/cache/yum/$basearch/$releasever' + end -case node['platform'] -when 'amazon' - default['yum']['main']['distroverpkg'] = 'system-release' -when 'scientific' - default['yum']['main']['distroverpkg'] = 'sl-release' -when 'redhat' - default['yum']['main']['distroverpkg'] = nil -else - default['yum']['main']['distroverpkg'] = "#{node['platform']}-release" -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']['alwaysprompt'] = nil # [TrueClass, FalseClass] -default['yum']['main']['assumeyes'] = nil # [TrueClass, FalseClass] +default['yum']['main']['assumeyes'] = nil # [TrueClass, FalseClass] default['yum']['main']['bandwidth'] = nil # /^\d+$/ default['yum']['main']['bugtracker_url'] = nil # /.*/ default['yum']['main']['clean_requirements_on_remove'] = nil # [TrueClass, FalseClass] @@ -36,6 +36,7 @@ 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 # [TrueClass, FalseClass] default['yum']['main']['debuglevel'] = nil # /^\d+$/ default['yum']['main']['diskspacecheck'] = nil # [TrueClass, FalseClass] default['yum']['main']['enable_group_conditionals'] = nil # [TrueClass, FalseClass] @@ -55,14 +56,14 @@ default['yum']['main']['installroot'] = nil # /.*/ default['yum']['main']['keepalive'] = nil # [TrueClass, FalseClass] default['yum']['main']['keepcache'] = false # [TrueClass, FalseClass] default['yum']['main']['kernelpkgnames'] = nil # /.*/ -default['yum']['main']['localpkg_gpgcheck'] = nil # [TrueClass,# FalseClass] +default['yum']['main']['localpkg_gpgcheck'] = false # [TrueClass,# FalseClass] 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 # [TrueClass, FalseClass] +default['yum']['main']['obsoletes'] = nil # [TrueClass, FalseClass] default['yum']['main']['overwrite_groups'] = nil # [TrueClass, FalseClass] default['yum']['main']['password'] = nil # /.*/ default['yum']['main']['path'] = '/etc/yum.conf' # /.*/ diff --git a/cookbooks/yum/metadata.json b/cookbooks/yum/metadata.json index f5b2c8e..aeac5ff 100644 --- a/cookbooks/yum/metadata.json +++ b/cookbooks/yum/metadata.json @@ -1 +1 @@ -{"name":"yum","version":"3.6.1","description":"Configures various yum components on Red Hat-like systems","long_description":"","maintainer":"Chef","maintainer_email":"cookbooks@chef.io","license":"Apache 2.0","platforms":{"redhat":">= 0.0.0","centos":">= 0.0.0","scientific":">= 0.0.0","amazon":">= 0.0.0","fedora":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file +{"name":"yum","version":"3.10.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"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file diff --git a/cookbooks/yum/providers/globalconfig.rb b/cookbooks/yum/providers/globalconfig.rb index dfd9db5..867d1c2 100644 --- a/cookbooks/yum/providers/globalconfig.rb +++ b/cookbooks/yum/providers/globalconfig.rb @@ -25,12 +25,12 @@ def whyrun_supported? true end -action :create do +action :create do template new_resource.path do source 'main.erb' cookbook 'yum' mode '0644' - variables(:config => new_resource) + variables(config: new_resource) end end diff --git a/cookbooks/yum/providers/repository.rb b/cookbooks/yum/providers/repository.rb index 9999060..8319671 100644 --- a/cookbooks/yum/providers/repository.rb +++ b/cookbooks/yum/providers/repository.rb @@ -30,12 +30,19 @@ def whyrun_supported? true end -action :create do +action :create do # Hack around the lack of "use_inline_resources" before Chef 11 by # uniquely naming the execute[yum-makecache] resources. Set the # notifies timing to :immediately for the same reasons. Remove both # of these when dropping Chef 10 support. + if new_resource.clean_headers + Chef::Log.warn <<-eos + Use of `clean_headers` in resource yum[#{new_resource.repositoryid}] is now deprecated and will be removed in a future release. + `clean_metadata` should be used instead + eos + end + template "/etc/yum.repos.d/#{new_resource.repositoryid}.repo" do if new_resource.source.nil? source 'repo.erb' @@ -44,22 +51,23 @@ action :create do source new_resource.source end mode new_resource.mode - variables(:config => new_resource) + sensitive new_resource.sensitive + variables(config: new_resource) if new_resource.make_cache - notifies :run, "execute[yum clean #{new_resource.repositoryid}]", :immediately + 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 - execute "yum clean #{new_resource.repositoryid}" do - command "yum clean all --disablerepo=* --enablerepo=#{new_resource.repositoryid}" + 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 execute "yum-makecache-#{new_resource.repositoryid}" do - command "yum -q makecache --disablerepo=* --enablerepo=#{new_resource.repositoryid}" + command "yum -q -y makecache --disablerepo=* --enablerepo=#{new_resource.repositoryid}" action :nothing only_if { new_resource.enabled } end @@ -74,11 +82,11 @@ end action :delete do file "/etc/yum.repos.d/#{new_resource.repositoryid}.repo" do action :delete - notifies :run, "execute[yum clean #{new_resource.repositoryid}]", :immediately + notifies :run, "execute[yum clean all #{new_resource.repositoryid}]", :immediately notifies :create, "ruby_block[yum-cache-reload-#{new_resource.repositoryid}]", :immediately end - execute "yum clean #{new_resource.repositoryid}" do + execute "yum clean all #{new_resource.repositoryid}" do command "yum clean all --disablerepo=* --enablerepo=#{new_resource.repositoryid}" only_if "yum repolist | grep -P '^#{new_resource.repositoryid}([ \t]|$)'" action :nothing diff --git a/cookbooks/yum/recipes/default.rb b/cookbooks/yum/recipes/default.rb index 2b41e4a..a89e2d1 100644 --- a/cookbooks/yum/recipes/default.rb +++ b/cookbooks/yum/recipes/default.rb @@ -19,7 +19,7 @@ yum_globalconfig '/etc/yum.conf' do node['yum']['main'].each do |config, value| - send(config.to_sym, value) + send(config.to_sym, value) unless value.nil? end action :create diff --git a/cookbooks/yum/recipes/dnf_yum_compat.rb b/cookbooks/yum/recipes/dnf_yum_compat.rb new file mode 100644 index 0000000..dff6df6 --- /dev/null +++ b/cookbooks/yum/recipes/dnf_yum_compat.rb @@ -0,0 +1,23 @@ +# +# Author:: Tim Smith () +# Recipe:: yum::fedora_yum_compat +# +# Copyright 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. + +execute 'install yum' do + command 'dnf install yum -y' + not_if { ::File.exist?('/var/lib/yum') } + action :run +end diff --git a/cookbooks/yum/resources/globalconfig.rb b/cookbooks/yum/resources/globalconfig.rb index 3802428..b8d66d9 100644 --- a/cookbooks/yum/resources/globalconfig.rb +++ b/cookbooks/yum/resources/globalconfig.rb @@ -23,86 +23,87 @@ actions :create, :delete default_action :create # http://linux.die.net/man/5/yum.conf -attribute :alwaysprompt, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :assumeyes, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :bandwidth, :kind_of => String, :regex => /^\d+/, :default => nil -attribute :bugtracker_url, :kind_of => String, :regex => /.*/, :default => nil -attribute :clean_requirements_on_remove, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :cachedir, :kind_of => String, :regex => /.*/, :default => '/var/cache/yum/$basearch/$releasever' -attribute :color, :kind_of => String, :equal_to => %w(always never), :default => nil -attribute :color_list_available_downgrade, :kind_of => String, :regex => /.*/, :default => nil -attribute :color_list_available_install, :kind_of => String, :regex => /.*/, :default => nil -attribute :color_list_available_reinstall, :kind_of => String, :regex => /.*/, :default => nil -attribute :color_list_available_upgrade, :kind_of => String, :regex => /.*/, :default => nil -attribute :color_list_installed_extra, :kind_of => String, :regex => /.*/, :default => nil -attribute :color_list_installed_newer, :kind_of => String, :regex => /.*/, :default => nil -attribute :color_list_installed_older, :kind_of => String, :regex => /.*/, :default => nil -attribute :color_list_installed_reinstall, :kind_of => String, :regex => /.*/, :default => nil -attribute :color_search_match, :kind_of => String, :regex => /.*/, :default => nil -attribute :color_update_installed, :kind_of => String, :regex => /.*/, :default => nil -attribute :color_update_local, :kind_of => String, :regex => /.*/, :default => nil -attribute :color_update_remote, :kind_of => String, :regex => /.*/, :default => nil -attribute :commands, :kind_of => String, :regex => /.*/, :default => nil -attribute :debuglevel, :kind_of => String, :regex => /^\d+$/, :default => '2' -attribute :diskspacecheck, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :distroverpkg, :kind_of => String, :regex => /.*/, :default => nil -attribute :enable_group_conditionals, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :errorlevel, :kind_of => String, :regex => /^\d+$/, :default => nil -attribute :exactarch, :kind_of => [TrueClass, FalseClass], :default => true -attribute :exclude, :kind_of => String, :regex => /.*/, :default => nil -attribute :gpgcheck, :kind_of => [TrueClass, FalseClass], :default => true -attribute :group_package_types, :kind_of => String, :regex => /.*/, :default => nil -attribute :groupremove_leaf_only, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :history_list_view, :kind_of => String, :equal_to => %w(users commands single-user-commands), :default => nil -attribute :history_record, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :history_record_packages, :kind_of => String, :regex => /.*/, :default => nil -attribute :http_caching, :kind_of => String, :equal_to => %w(packages all none), :default => nil -attribute :installonly_limit, :kind_of => String, :regex => [/^\d+/, /keep/], :default => '3' -attribute :installonlypkgs, :kind_of => String, :regex => /.*/, :default => nil -attribute :installroot, :kind_of => String, :regex => /.*/, :default => nil -attribute :keepalive, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :keepcache, :kind_of => [TrueClass, FalseClass], :default => false -attribute :kernelpkgnames, :kind_of => String, :regex => /.*/, :default => nil -attribute :localpkg_gpgcheck, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :logfile, :kind_of => String, :regex => /.*/, :default => '/var/log/yum.log' -attribute :max_retries, :kind_of => String, :regex => /^\d+$/, :default => nil -attribute :mdpolicy, :kind_of => String, :equal_to => %w(instant group:primary group:small group:main group:all), :default => nil -attribute :metadata_expire, :kind_of => String, :regex => [/^\d+$/, /^\d+[mhd]$/, /never/], :default => nil -attribute :mirrorlist_expire, :kind_of => String, :regex => /^\d+$/, :default => nil -attribute :multilib_policy, :kind_of => String, :equal_to => %w(all best), :default => nil -attribute :obsoletes, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :overwrite_groups, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :password, :kind_of => String, :regex => /.*/, :default => nil -attribute :path, :kind_of => String, :regex => /.*/, :default => nil, :name_attribute => true -attribute :persistdir, :kind_of => String, :regex => /.*/, :default => nil -attribute :pluginconfpath, :kind_of => String, :regex => /.*/, :default => nil -attribute :pluginpath, :kind_of => String, :regex => /.*/, :default => nil -attribute :plugins, :kind_of => [TrueClass, FalseClass], :default => true -attribute :protected_multilib, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :protected_packages, :kind_of => String, :regex => /.*/, :default => nil -attribute :proxy, :kind_of => String, :regex => /.*/, :default => nil -attribute :proxy_password, :kind_of => String, :regex => /.*/, :default => nil -attribute :proxy_username, :kind_of => String, :regex => /.*/, :default => nil -attribute :recent, :kind_of => String, :regex => /^\d+$/, :default => nil -attribute :releasever, :kind_of => String, :regex => /.*/, :default => nil -attribute :repo_gpgcheck, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :reposdir, :kind_of => String, :regex => /.*/, :default => nil -attribute :reset_nice, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :rpmverbosity, :kind_of => String, :equal_to => %w(info critical emergency error warn debug), :default => nil -attribute :showdupesfromrepos, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :skip_broken, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :ssl_check_cert_permissions, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :sslcacert, :kind_of => String, :regex => /.*/, :default => nil -attribute :sslclientcert, :kind_of => String, :regex => /.*/, :default => nil -attribute :sslclientkey, :kind_of => String, :regex => /.*/, :default => nil -attribute :sslverify, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :syslog_device, :kind_of => String, :regex => /.*/, :default => nil -attribute :syslog_facility, :kind_of => String, :regex => /.*/, :default => nil -attribute :syslog_ident, :kind_of => String, :regex => /.*/, :default => nil -attribute :throttle, :kind_of => String, :regex => [/\d+k/, /\d+M/, /\d+G/], :default => nil -attribute :timeout, :kind_of => String, :regex => /^\d+$/, :default => nil -attribute :tolerant, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :tsflags, :kind_of => String, :regex => /.*/, :default => nil -attribute :username, :kind_of => String, :regex => /.*/, :default => nil +attribute :alwaysprompt, kind_of: [TrueClass, FalseClass], default: nil +attribute :assumeyes, kind_of: [TrueClass, FalseClass], default: nil +attribute :bandwidth, kind_of: String, regex: /^\d+/, default: nil +attribute :bugtracker_url, kind_of: String, regex: /.*/, default: nil +attribute :clean_requirements_on_remove, kind_of: [TrueClass, FalseClass], default: nil +attribute :cachedir, kind_of: String, regex: /.*/, default: '/var/cache/yum/$basearch/$releasever' +attribute :color, kind_of: String, equal_to: %w(always never), default: nil +attribute :color_list_available_downgrade, kind_of: String, regex: /.*/, default: nil +attribute :color_list_available_install, kind_of: String, regex: /.*/, default: nil +attribute :color_list_available_reinstall, kind_of: String, regex: /.*/, default: nil +attribute :color_list_available_upgrade, kind_of: String, regex: /.*/, default: nil +attribute :color_list_installed_extra, kind_of: String, regex: /.*/, default: nil +attribute :color_list_installed_newer, kind_of: String, regex: /.*/, default: nil +attribute :color_list_installed_older, kind_of: String, regex: /.*/, default: nil +attribute :color_list_installed_reinstall, kind_of: String, regex: /.*/, default: nil +attribute :color_search_match, kind_of: String, regex: /.*/, default: nil +attribute :color_update_installed, kind_of: String, regex: /.*/, default: nil +attribute :color_update_local, kind_of: String, regex: /.*/, default: nil +attribute :color_update_remote, kind_of: String, regex: /.*/, default: nil +attribute :commands, kind_of: String, regex: /.*/, default: nil +attribute :debuglevel, kind_of: String, regex: /^\d+$/, default: '2' +attribute :deltarpm, kind_of: [TrueClass, FalseClass], default: nil +attribute :diskspacecheck, kind_of: [TrueClass, FalseClass], default: nil +attribute :distroverpkg, kind_of: String, regex: /.*/, default: nil +attribute :enable_group_conditionals, kind_of: [TrueClass, FalseClass], default: nil +attribute :errorlevel, kind_of: String, regex: /^\d+$/, default: nil +attribute :exactarch, kind_of: [TrueClass, FalseClass], default: true +attribute :exclude, kind_of: String, regex: /.*/, default: nil +attribute :gpgcheck, kind_of: [TrueClass, FalseClass], default: true +attribute :group_package_types, kind_of: String, regex: /.*/, default: nil +attribute :groupremove_leaf_only, kind_of: [TrueClass, FalseClass], default: nil +attribute :history_list_view, kind_of: String, equal_to: %w(users commands single-user-commands), default: nil +attribute :history_record, kind_of: [TrueClass, FalseClass], default: nil +attribute :history_record_packages, kind_of: String, regex: /.*/, default: nil +attribute :http_caching, kind_of: String, equal_to: %w(packages all none), default: nil +attribute :installonly_limit, kind_of: String, regex: [/^\d+/, /keep/], default: '3' +attribute :installonlypkgs, kind_of: String, regex: /.*/, default: nil +attribute :installroot, kind_of: String, regex: /.*/, default: nil +attribute :keepalive, kind_of: [TrueClass, FalseClass], default: nil +attribute :keepcache, kind_of: [TrueClass, FalseClass], default: false +attribute :kernelpkgnames, kind_of: String, regex: /.*/, default: nil +attribute :localpkg_gpgcheck, kind_of: [TrueClass, FalseClass], default: nil +attribute :logfile, kind_of: String, regex: /.*/, default: '/var/log/yum.log' +attribute :max_retries, kind_of: String, regex: /^\d+$/, default: nil +attribute :mdpolicy, kind_of: String, equal_to: %w(instant group:primary group:small group:main group:all), default: nil +attribute :metadata_expire, kind_of: String, regex: [/^\d+$/, /^\d+[mhd]$/, /never/], default: nil +attribute :mirrorlist_expire, kind_of: String, regex: /^\d+$/, default: nil +attribute :multilib_policy, kind_of: String, equal_to: %w(all best), default: nil +attribute :obsoletes, kind_of: [TrueClass, FalseClass], default: nil +attribute :overwrite_groups, kind_of: [TrueClass, FalseClass], default: nil +attribute :password, kind_of: String, regex: /.*/, default: nil +attribute :path, kind_of: String, regex: /.*/, name_attribute: true +attribute :persistdir, kind_of: String, regex: /.*/, default: nil +attribute :pluginconfpath, kind_of: String, regex: /.*/, default: nil +attribute :pluginpath, kind_of: String, regex: /.*/, default: nil +attribute :plugins, kind_of: [TrueClass, FalseClass], default: true +attribute :protected_multilib, kind_of: [TrueClass, FalseClass], default: nil +attribute :protected_packages, kind_of: String, regex: /.*/, default: nil +attribute :proxy, kind_of: String, regex: /.*/, default: nil +attribute :proxy_password, kind_of: String, regex: /.*/, default: nil +attribute :proxy_username, kind_of: String, regex: /.*/, default: nil +attribute :recent, kind_of: String, regex: /^\d+$/, default: nil +attribute :releasever, kind_of: String, regex: /.*/, default: nil +attribute :repo_gpgcheck, kind_of: [TrueClass, FalseClass], default: nil +attribute :reposdir, kind_of: String, regex: /.*/, default: nil +attribute :reset_nice, kind_of: [TrueClass, FalseClass], default: nil +attribute :rpmverbosity, kind_of: String, equal_to: %w(info critical emergency error warn debug), default: nil +attribute :showdupesfromrepos, kind_of: [TrueClass, FalseClass], default: nil +attribute :skip_broken, kind_of: [TrueClass, FalseClass], default: nil +attribute :ssl_check_cert_permissions, kind_of: [TrueClass, FalseClass], default: nil +attribute :sslcacert, kind_of: String, regex: /.*/, default: nil +attribute :sslclientcert, kind_of: String, regex: /.*/, default: nil +attribute :sslclientkey, kind_of: String, regex: /.*/, default: nil +attribute :sslverify, kind_of: [TrueClass, FalseClass], default: nil +attribute :syslog_device, kind_of: String, regex: /.*/, default: nil +attribute :syslog_facility, kind_of: String, regex: /.*/, default: nil +attribute :syslog_ident, kind_of: String, regex: /.*/, default: nil +attribute :throttle, kind_of: String, regex: [/\d+k/, /\d+M/, /\d+G/], default: nil +attribute :timeout, kind_of: String, regex: /^\d+$/, default: nil +attribute :tolerant, kind_of: [TrueClass, FalseClass], default: nil +attribute :tsflags, kind_of: String, regex: /.*/, default: nil +attribute :username, kind_of: String, regex: /.*/, default: nil -attribute :options, :kind_of => Hash +attribute :options, kind_of: Hash diff --git a/cookbooks/yum/resources/repository.rb b/cookbooks/yum/resources/repository.rb index 9e6043d..abcaa98 100644 --- a/cookbooks/yum/resources/repository.rb +++ b/cookbooks/yum/resources/repository.rb @@ -23,46 +23,49 @@ actions :create, :delete, :add, :remove, :makecache default_action :create # http://linux.die.net/man/5/yum.conf -attribute :baseurl, :kind_of => String, :regex => /.*/, :default => nil -attribute :cost, :kind_of => String, :regex => /^\d+$/, :default => nil -attribute :description, :kind_of => String, :regex => /.*/, :default => 'Ye Ole Rpm Repo' -attribute :enabled, :kind_of => [TrueClass, FalseClass], :default => true -attribute :enablegroups, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :exclude, :kind_of => String, :regex => /.*/, :default => nil -attribute :failovermethod, :kind_of => String, :equal_to => %w(priority roundrobin), :default => nil -attribute :fastestmirror_enabled, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :gpgcheck, :kind_of => [TrueClass, FalseClass], :default => true -attribute :gpgkey, :kind_of => [String, Array], :regex => /.*/, :default => nil -attribute :http_caching, :kind_of => String, :equal_to => %w(packages all none), :default => nil -attribute :include_config, :kind_of => String, :regex => /.*/, :default => nil -attribute :includepkgs, :kind_of => String, :regex => /.*/, :default => nil -attribute :keepalive, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :make_cache, :kind_of => [TrueClass, FalseClass], :default => true -attribute :max_retries, :kind_of => String, :regex => /.*/, :default => nil -attribute :metadata_expire, :kind_of => String, :regex => [/^\d+$/, /^\d+[mhd]$/, /never/], :default => nil -attribute :mirrorexpire, :kind_of => String, :regex => /.*/, :default => nil -attribute :mirrorlist, :kind_of => String, :regex => /.*/, :default => nil -attribute :mirror_expire, :kind_of => String, :regex => [/^\d+$/, /^\d+[mhd]$/], :default => nil -attribute :mirrorlist_expire, :kind_of => String, :regex => [/^\d+$/, /^\d+[mhd]$/], :default => nil -attribute :mode, :default => '0644' -attribute :priority, :kind_of => String, :regex => /^(\d?[0-9]|[0-9][0-9])$/, :default => nil -attribute :proxy, :kind_of => String, :regex => /.*/, :default => nil -attribute :proxy_username, :kind_of => String, :regex => /.*/, :default => nil -attribute :proxy_password, :kind_of => String, :regex => /.*/, :default => nil -attribute :username, :kind_of => String, :regex => /.*/, :default => nil -attribute :password, :kind_of => String, :regex => /.*/, :default => nil -attribute :repo_gpgcheck, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :report_instanceid, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :repositoryid, :kind_of => String, :regex => /.*/, :name_attribute => true -attribute :skip_if_unavailable, :kind_of => [TrueClass, FalseClass], :default => nil -attribute :source, :kind_of => String, :regex => /.*/, :default => nil -attribute :sslcacert, :kind_of => String, :regex => /.*/, :default => nil -attribute :sslclientcert, :kind_of => String, :regex => /.*/, :default => nil -attribute :sslclientkey, :kind_of => String, :regex => /.*/, :default => nil -attribute :sslverify, :kind_of => [TrueClass, FalseClass], :default => true -attribute :timeout, :kind_of => String, :regex => /^\d+$/, :default => nil +attribute :baseurl, kind_of: String, regex: /.*/, default: nil +attribute :cost, kind_of: String, regex: /^\d+$/, default: nil +attribute :clean_headers, kind_of: [TrueClass, FalseClass], default: false # deprecated +attribute :clean_metadata, kind_of: [TrueClass, FalseClass], default: true +attribute :description, kind_of: String, regex: /.*/, default: 'Ye Ole Rpm Repo' +attribute :enabled, kind_of: [TrueClass, FalseClass], default: true +attribute :enablegroups, kind_of: [TrueClass, FalseClass], default: nil +attribute :exclude, kind_of: String, regex: /.*/, default: nil +attribute :failovermethod, kind_of: String, equal_to: %w(priority roundrobin), default: nil +attribute :fastestmirror_enabled, kind_of: [TrueClass, FalseClass], default: nil +attribute :gpgcheck, kind_of: [TrueClass, FalseClass], default: true +attribute :gpgkey, kind_of: [String, Array], regex: /.*/, default: nil +attribute :http_caching, kind_of: String, equal_to: %w(packages all none), default: nil +attribute :include_config, kind_of: String, regex: /.*/, default: nil +attribute :includepkgs, kind_of: String, regex: /.*/, default: nil +attribute :keepalive, kind_of: [TrueClass, FalseClass], default: nil +attribute :make_cache, kind_of: [TrueClass, FalseClass], default: true +attribute :max_retries, kind_of: [String, Integer], default: nil +attribute :metadata_expire, kind_of: String, regex: [/^\d+$/, /^\d+[mhd]$/, /never/], default: nil +attribute :mirrorexpire, kind_of: String, regex: /.*/, default: nil +attribute :mirrorlist, kind_of: String, regex: /.*/, default: nil +attribute :mirror_expire, kind_of: String, regex: [/^\d+$/, /^\d+[mhd]$/], default: nil +attribute :mirrorlist_expire, kind_of: String, regex: [/^\d+$/, /^\d+[mhd]$/], default: nil +attribute :mode, default: '0644' +attribute :priority, kind_of: String, regex: /^(\d?[0-9]|[0-9][0-9])$/, default: nil +attribute :proxy, kind_of: String, regex: /.*/, default: nil +attribute :proxy_username, kind_of: String, regex: /.*/, default: nil +attribute :proxy_password, kind_of: String, regex: /.*/, default: nil +attribute :username, kind_of: String, regex: /.*/, default: nil +attribute :password, kind_of: String, regex: /.*/, default: nil +attribute :repo_gpgcheck, kind_of: [TrueClass, FalseClass], default: nil +attribute :report_instanceid, kind_of: [TrueClass, FalseClass], default: nil +attribute :repositoryid, kind_of: String, regex: /.*/, name_attribute: true +attribute :sensitive, kind_of: [TrueClass, FalseClass], default: false +attribute :skip_if_unavailable, kind_of: [TrueClass, FalseClass], default: nil +attribute :source, kind_of: String, regex: /.*/, default: nil +attribute :sslcacert, kind_of: String, regex: /.*/, default: nil +attribute :sslclientcert, kind_of: String, regex: /.*/, default: nil +attribute :sslclientkey, kind_of: String, regex: /.*/, default: nil +attribute :sslverify, kind_of: [TrueClass, FalseClass], default: nil +attribute :timeout, kind_of: String, regex: /^\d+$/, default: nil -attribute :options, :kind_of => Hash +attribute :options, kind_of: Hash alias_method :url, :baseurl alias_method :keyurl, :gpgkey diff --git a/cookbooks/yum/templates/default/main.erb b/cookbooks/yum/templates/default/main.erb index 01bf7ce..dd2b0f5 100644 --- a/cookbooks/yum/templates/default/main.erb +++ b/cookbooks/yum/templates/default/main.erb @@ -65,6 +65,11 @@ commands=<%= @config.commands %> <% 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 %> @@ -129,7 +134,9 @@ keepcache=0 kernelpkgnames=<%= @config.kernelpkgnames %> <% end %> <% if @config.localpkg_gpgcheck %> -localpkg_gpgcheck=<%= @config.localpkg_gpgcheck %> +localpkg_gpgcheck=1 +<% else %> +localpkg_gpgcheck=0 <% end %> <% if @config.logfile %> logfile=<%= @config.logfile %> @@ -226,7 +233,7 @@ sslclientcert=<%= @config.sslclientcert %> sslclientkey=<%= @config.sslclientkey %> <% end %> <% unless @config.sslverify.nil? %> -sslverify=<%= @config.sslverify %> +sslverify=<%= ( @config.sslverify ) ? 'true' : 'false' %> <% end %> <% if @config.syslog_device %> syslog_device=<%= @config.syslog_device %> diff --git a/cookbooks/yum/templates/default/repo.erb b/cookbooks/yum/templates/default/repo.erb index d462f00..7d9a2d0 100644 --- a/cookbooks/yum/templates/default/repo.erb +++ b/cookbooks/yum/templates/default/repo.erb @@ -103,7 +103,7 @@ sslclientcert=<%= @config.sslclientcert %> sslclientkey=<%= @config.sslclientkey %> <% end %> <% unless @config.sslverify.nil? %> -sslverify=<%= @config.sslverify %> +sslverify=<%= ( @config.sslverify ) ? 'true' : 'false' %> <% end %> <% if @config.timeout %> timeout=<%= @config.timeout %>