Update cookbooks
This commit is contained in:
parent
3854ab7232
commit
c50b096c37
10
Batali
10
Batali
@ -5,7 +5,13 @@ Batali.define do
|
||||
|
||||
cookbook 'mediawiki',
|
||||
git: 'https://github.com/67P/mediawiki-cookbook.git',
|
||||
ref: 'master'
|
||||
ref: 'nginx'
|
||||
cookbook 'php-fpm',
|
||||
git: 'https://github.com/67P/cookbook-php-fpm.git',
|
||||
ref: 'ubuntu_systemd'
|
||||
cookbook 'wordpress',
|
||||
git: 'https://github.com/67P/wordpress-cookbook.git',
|
||||
ref: 'relax_dependencies'
|
||||
cookbook 'postfix'
|
||||
cookbook 'unattended-upgrades'
|
||||
cookbook 'application_nodejs',
|
||||
@ -20,6 +26,7 @@ Batali.define do
|
||||
git: 'https://github.com/phlipper/chef-redis.git',
|
||||
ref: 'v0.5.6'
|
||||
cookbook 'ufw'
|
||||
cookbook 'firewall'
|
||||
cookbook 'ssh_known_hosts'
|
||||
cookbook 'nginx'
|
||||
cookbook 'build-essential', '~> 2.2.4'
|
||||
@ -29,6 +36,5 @@ Batali.define do
|
||||
cookbook 'omnibus_updater', '~> 1.0.4'
|
||||
cookbook 'timezone-ii'
|
||||
cookbook 'nodejs', '~> 2.4.4'
|
||||
cookbook 'wordpress'
|
||||
end
|
||||
|
||||
|
633
batali.manifest
633
batali.manifest
@ -2,43 +2,107 @@
|
||||
"infrastructure": false,
|
||||
"cookbook": [
|
||||
{
|
||||
"name": "mediawiki",
|
||||
"name": "php-fpm",
|
||||
"dependencies": [
|
||||
[
|
||||
"apache2",
|
||||
"apt",
|
||||
"> 0"
|
||||
],
|
||||
[
|
||||
"php",
|
||||
"> 0"
|
||||
],
|
||||
[
|
||||
"mysql",
|
||||
"> 0"
|
||||
],
|
||||
[
|
||||
"database",
|
||||
"> 0"
|
||||
"yum",
|
||||
">= 3.0"
|
||||
]
|
||||
],
|
||||
"version": "0.1.0",
|
||||
"version": "0.7.5",
|
||||
"source": {
|
||||
"url": "https://github.com/67P/mediawiki-cookbook.git",
|
||||
"ref": "35e33e3d563987fa7c156def2d26654ecc4cb9a1",
|
||||
"url": "https://github.com/67P/cookbook-php-fpm.git",
|
||||
"ref": "00ae43a225cf23fd3ed937f27ab25aba8d812db9",
|
||||
"type": "Batali::Source::Git",
|
||||
"subdirectory": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "apache2",
|
||||
"name": "apt",
|
||||
"dependencies": [
|
||||
|
||||
],
|
||||
"version": "3.1.0",
|
||||
"version": "2.9.2",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/apache2/versions/3.1.0/download",
|
||||
"version": "3.1.0"
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/apt/versions/2.9.2/download",
|
||||
"version": "2.9.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "yum",
|
||||
"dependencies": [
|
||||
|
||||
],
|
||||
"version": "3.10.0",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/yum/versions/3.10.0/download",
|
||||
"version": "3.10.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wordpress",
|
||||
"dependencies": [
|
||||
[
|
||||
"php",
|
||||
"> 0"
|
||||
],
|
||||
[
|
||||
"openssl",
|
||||
"> 0"
|
||||
],
|
||||
[
|
||||
"apache2",
|
||||
">= 2.0.0"
|
||||
],
|
||||
[
|
||||
"database",
|
||||
">= 1.6.0"
|
||||
],
|
||||
[
|
||||
"mysql",
|
||||
">= 6.0"
|
||||
],
|
||||
[
|
||||
"mysql2_chef_gem",
|
||||
"~> 1.0.1"
|
||||
],
|
||||
[
|
||||
"build-essential",
|
||||
"> 0"
|
||||
],
|
||||
[
|
||||
"iis",
|
||||
">= 1.6.2"
|
||||
],
|
||||
[
|
||||
"tar",
|
||||
">= 0.3.1"
|
||||
],
|
||||
[
|
||||
"nginx",
|
||||
"~> 2.7.4"
|
||||
],
|
||||
[
|
||||
"php-fpm",
|
||||
"> 0"
|
||||
],
|
||||
[
|
||||
"selinux",
|
||||
"~> 0.7"
|
||||
]
|
||||
],
|
||||
"version": "3.0.0",
|
||||
"source": {
|
||||
"url": "https://github.com/67P/wordpress-cookbook.git",
|
||||
"ref": "bc6a108fcfb05c3fafd903bcf81ac33617e6cef9",
|
||||
"type": "Batali::Source::Git",
|
||||
"subdirectory": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -131,11 +195,11 @@
|
||||
">= 0.0.0"
|
||||
]
|
||||
],
|
||||
"version": "6.1.2",
|
||||
"version": "6.1.3",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/mysql/versions/6.1.2/download",
|
||||
"version": "6.1.2"
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/mysql/versions/6.1.3/download",
|
||||
"version": "6.1.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -153,18 +217,6 @@
|
||||
"version": "0.1.21"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "yum",
|
||||
"dependencies": [
|
||||
|
||||
],
|
||||
"version": "3.10.0",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/yum/versions/3.10.0/download",
|
||||
"version": "3.10.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "smf",
|
||||
"dependencies": [
|
||||
@ -249,6 +301,33 @@
|
||||
"version": "4.1.6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "openssl",
|
||||
"dependencies": [
|
||||
[
|
||||
"chef-sugar",
|
||||
">= 3.1.1"
|
||||
]
|
||||
],
|
||||
"version": "4.4.0",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/openssl/versions/4.4.0/download",
|
||||
"version": "4.4.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "apache2",
|
||||
"dependencies": [
|
||||
|
||||
],
|
||||
"version": "3.1.0",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/apache2/versions/3.1.0/download",
|
||||
"version": "3.1.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "database",
|
||||
"dependencies": [
|
||||
@ -288,30 +367,212 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "apt",
|
||||
"name": "mysql2_chef_gem",
|
||||
"dependencies": [
|
||||
|
||||
[
|
||||
"build-essential",
|
||||
">= 0.0.0"
|
||||
],
|
||||
[
|
||||
"mysql",
|
||||
"~> 6.0"
|
||||
],
|
||||
[
|
||||
"mariadb",
|
||||
">= 0.0.0"
|
||||
]
|
||||
],
|
||||
"version": "2.9.2",
|
||||
"version": "1.0.2",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/apt/versions/2.9.2/download",
|
||||
"version": "2.9.2"
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/mysql2_chef_gem/versions/1.0.2/download",
|
||||
"version": "1.0.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "openssl",
|
||||
"name": "mariadb",
|
||||
"dependencies": [
|
||||
[
|
||||
"chef-sugar",
|
||||
">= 3.1.1"
|
||||
"apt",
|
||||
">= 0.0.0"
|
||||
],
|
||||
[
|
||||
"yum",
|
||||
">= 0.0.0"
|
||||
],
|
||||
[
|
||||
"yum-epel",
|
||||
">= 0.0.0"
|
||||
]
|
||||
],
|
||||
"version": "4.4.0",
|
||||
"version": "0.3.1",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/openssl/versions/4.4.0/download",
|
||||
"version": "4.4.0"
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/mariadb/versions/0.3.1/download",
|
||||
"version": "0.3.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"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": "nginx",
|
||||
"dependencies": [
|
||||
[
|
||||
"apt",
|
||||
"~> 2.2"
|
||||
],
|
||||
[
|
||||
"bluepill",
|
||||
"~> 2.3"
|
||||
],
|
||||
[
|
||||
"build-essential",
|
||||
"~> 2.0"
|
||||
],
|
||||
[
|
||||
"ohai",
|
||||
"~> 2.0"
|
||||
],
|
||||
[
|
||||
"runit",
|
||||
"~> 1.2"
|
||||
],
|
||||
[
|
||||
"yum-epel",
|
||||
"~> 0.3"
|
||||
]
|
||||
],
|
||||
"version": "2.7.6",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/nginx/versions/2.7.6/download",
|
||||
"version": "2.7.6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "bluepill",
|
||||
"dependencies": [
|
||||
[
|
||||
"rsyslog",
|
||||
"~> 2.0"
|
||||
]
|
||||
],
|
||||
"version": "2.4.1",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/bluepill/versions/2.4.1/download",
|
||||
"version": "2.4.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "rsyslog",
|
||||
"dependencies": [
|
||||
|
||||
],
|
||||
"version": "2.2.0",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/rsyslog/versions/2.2.0/download",
|
||||
"version": "2.2.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ohai",
|
||||
"dependencies": [
|
||||
|
||||
],
|
||||
"version": "2.1.0",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/ohai/versions/2.1.0/download",
|
||||
"version": "2.1.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "runit",
|
||||
"dependencies": [
|
||||
[
|
||||
"packagecloud",
|
||||
">= 0.0.0"
|
||||
]
|
||||
],
|
||||
"version": "1.7.6",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/runit/versions/1.7.6/download",
|
||||
"version": "1.7.6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "packagecloud",
|
||||
"dependencies": [
|
||||
|
||||
],
|
||||
"version": "0.2.0",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/packagecloud/versions/0.2.0/download",
|
||||
"version": "0.2.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"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"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "mediawiki",
|
||||
"dependencies": [
|
||||
[
|
||||
"apache2",
|
||||
"> 0"
|
||||
],
|
||||
[
|
||||
"php",
|
||||
"> 0"
|
||||
],
|
||||
[
|
||||
"mysql",
|
||||
"> 0"
|
||||
],
|
||||
[
|
||||
"database",
|
||||
"> 0"
|
||||
],
|
||||
[
|
||||
"nginx",
|
||||
"> 0"
|
||||
],
|
||||
[
|
||||
"mysql2_chef_gem",
|
||||
"> 0"
|
||||
],
|
||||
[
|
||||
"php-fpm",
|
||||
"> 0"
|
||||
]
|
||||
],
|
||||
"version": "0.2.0",
|
||||
"source": {
|
||||
"type": "Batali::Source::Path",
|
||||
"path": "/Users/kare/code/kosmos/cookbooks/mediawiki-cookbook"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -445,33 +706,6 @@
|
||||
"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"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "application",
|
||||
"dependencies": [
|
||||
@ -586,11 +820,11 @@
|
||||
">= 0.0.0"
|
||||
]
|
||||
],
|
||||
"version": "2.4.0",
|
||||
"version": "2.5.0",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/firewall/versions/2.4.0/download",
|
||||
"version": "2.4.0"
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/firewall/versions/2.5.0/download",
|
||||
"version": "2.5.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -620,153 +854,6 @@
|
||||
"version": "1.0.9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nginx",
|
||||
"dependencies": [
|
||||
[
|
||||
"apt",
|
||||
"~> 2.2"
|
||||
],
|
||||
[
|
||||
"bluepill",
|
||||
"~> 2.3"
|
||||
],
|
||||
[
|
||||
"build-essential",
|
||||
"~> 2.0"
|
||||
],
|
||||
[
|
||||
"ohai",
|
||||
"~> 2.0"
|
||||
],
|
||||
[
|
||||
"runit",
|
||||
"~> 1.2"
|
||||
],
|
||||
[
|
||||
"yum-epel",
|
||||
"~> 0.3"
|
||||
]
|
||||
],
|
||||
"version": "2.7.6",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/nginx/versions/2.7.6/download",
|
||||
"version": "2.7.6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "bluepill",
|
||||
"dependencies": [
|
||||
[
|
||||
"rsyslog",
|
||||
"~> 2.0"
|
||||
]
|
||||
],
|
||||
"version": "2.4.1",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/bluepill/versions/2.4.1/download",
|
||||
"version": "2.4.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "rsyslog",
|
||||
"dependencies": [
|
||||
|
||||
],
|
||||
"version": "2.2.0",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/rsyslog/versions/2.2.0/download",
|
||||
"version": "2.2.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ohai",
|
||||
"dependencies": [
|
||||
|
||||
],
|
||||
"version": "2.1.0",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/ohai/versions/2.1.0/download",
|
||||
"version": "2.1.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "runit",
|
||||
"dependencies": [
|
||||
[
|
||||
"packagecloud",
|
||||
">= 0.0.0"
|
||||
]
|
||||
],
|
||||
"version": "1.7.6",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/runit/versions/1.7.6/download",
|
||||
"version": "1.7.6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "packagecloud",
|
||||
"dependencies": [
|
||||
|
||||
],
|
||||
"version": "0.2.0",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/packagecloud/versions/0.2.0/download",
|
||||
"version": "0.2.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "mysql2_chef_gem",
|
||||
"dependencies": [
|
||||
[
|
||||
"build-essential",
|
||||
">= 0.0.0"
|
||||
],
|
||||
[
|
||||
"mysql",
|
||||
"~> 6.0"
|
||||
],
|
||||
[
|
||||
"mariadb",
|
||||
">= 0.0.0"
|
||||
]
|
||||
],
|
||||
"version": "1.0.2",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/mysql2_chef_gem/versions/1.0.2/download",
|
||||
"version": "1.0.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "mariadb",
|
||||
"dependencies": [
|
||||
[
|
||||
"apt",
|
||||
">= 0.0.0"
|
||||
],
|
||||
[
|
||||
"yum",
|
||||
">= 0.0.0"
|
||||
],
|
||||
[
|
||||
"yum-epel",
|
||||
">= 0.0.0"
|
||||
]
|
||||
],
|
||||
"version": "0.3.1",
|
||||
"source": {
|
||||
"type": "Batali::Source::Site",
|
||||
"url": "https://supermarket.chef.io:443/api/v1/cookbooks/mariadb/versions/0.3.1/download",
|
||||
"version": "0.3.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "omnibus_updater",
|
||||
"dependencies": [
|
||||
@ -790,108 +877,6 @@
|
||||
"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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -2,6 +2,14 @@ firewall Cookbook CHANGELOG
|
||||
=======================
|
||||
This file is used to list changes made in each version of the firewall cookbook.
|
||||
|
||||
v2.5.0 (2016-03-08)
|
||||
-------------------
|
||||
* Don't modify parameter for port (#120)
|
||||
* Remove a reference to the wrong variable name under windows (#123)
|
||||
* Add support for mobile shell default firewall rule (#121)
|
||||
* New rubocop rules and style fixes
|
||||
* Correct a README.md example for `action :allow`
|
||||
|
||||
v2.4.0 (2016-01-28)
|
||||
-------------------
|
||||
* Expose default iptables ruleset so that raw rules can be used in conjunction
|
||||
|
@ -87,6 +87,7 @@ The default recipe creates a firewall resource with action install, and if `node
|
||||
# Attributes
|
||||
|
||||
* `default['firewall']['allow_ssh'] = false`, set true to open port 22 for SSH when the default recipe runs
|
||||
* `default['firewall']['allow_mosh'] = false`, set to true to open UDP ports 60000 - 61000 for [Mosh][0] when the default recipe runs
|
||||
* `default['firewall']['allow_winrm'] = false`, set true to open port 5989 for WinRM when the default recipe runs
|
||||
|
||||
* `default['firewall']['ubuntu_iptables'] = false`, set to true to use iptables on Ubuntu / Debian when using the default recipe
|
||||
@ -245,7 +246,7 @@ end
|
||||
firewall_rule 'http/https' do
|
||||
protocol :tcp
|
||||
port [80, 443]
|
||||
action :allow
|
||||
command :allow
|
||||
end
|
||||
|
||||
firewall 'default' do
|
||||
@ -321,3 +322,5 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
```
|
||||
|
||||
[0]: https://mosh.mit.edu/
|
||||
|
@ -1,2 +1,3 @@
|
||||
default['firewall']['allow_ssh'] = false
|
||||
default['firewall']['allow_winrm'] = false
|
||||
default['firewall']['allow_mosh'] = false
|
||||
|
@ -10,8 +10,8 @@ module FirewallCookbook
|
||||
elsif p && p.is_a?(Integer)
|
||||
p.to_s
|
||||
elsif p && p.is_a?(Array)
|
||||
p.map! { |o| port_to_s(o) }
|
||||
p.sort.join(',')
|
||||
p_strings = p.map { |o| port_to_s(o) }
|
||||
p_strings.sort.join(',')
|
||||
elsif p && p.is_a?(Range)
|
||||
if platform_family?('windows')
|
||||
"#{p.first}-#{p.last}"
|
||||
@ -79,10 +79,10 @@ module FirewallCookbook
|
||||
rules.each do |k, v|
|
||||
next unless v == sorted_value
|
||||
contents << if k.start_with?('COMMIT')
|
||||
'COMMIT'
|
||||
else
|
||||
k
|
||||
end
|
||||
'COMMIT'
|
||||
else
|
||||
k
|
||||
end
|
||||
end
|
||||
end
|
||||
"#{contents.join("\n")}\n"
|
||||
|
@ -42,7 +42,7 @@ module FirewallCookbook
|
||||
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
|
||||
raise msg
|
||||
end
|
||||
|
||||
# if we don't do this, ufw will fail as it does not support protocol numbers, so we'll only allow it to run if specifying icmp/tcp/udp protocol types
|
||||
@ -51,7 +51,7 @@ module FirewallCookbook
|
||||
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
|
||||
raise msg
|
||||
end
|
||||
|
||||
# some examples:
|
||||
|
@ -66,7 +66,7 @@ module FirewallCookbook
|
||||
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['interfacetype'] = new_resource.interface ? new_resource.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
|
||||
|
@ -25,7 +25,7 @@ class Chef
|
||||
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
|
||||
raise 'could not find a firewall resource' unless firewall_resource
|
||||
|
||||
new_resource.notifies(:restart, firewall_resource, :delayed)
|
||||
new_resource.updated_by_last_action(true)
|
||||
|
File diff suppressed because one or more lines are too long
@ -39,6 +39,13 @@ firewall_rule 'allow world to winrm' do
|
||||
only_if { windows? && node['firewall']['allow_winrm'] }
|
||||
end
|
||||
|
||||
firewall_rule 'allow world to mosh' do
|
||||
protocol :udp
|
||||
port 60000..61000
|
||||
source '0.0.0.0/0'
|
||||
only_if { linux? && node['firewall']['allow_mosh'] }
|
||||
end
|
||||
|
||||
# allow established connections, ufw defaults to this but iptables does not
|
||||
firewall_rule 'established' do
|
||||
stateful [:related, :established]
|
||||
|
@ -1,16 +1,26 @@
|
||||
default["mediawiki"]["version"] = "1.23.1"
|
||||
default["mediawiki"]["webdir"] = node['apache']['docroot_dir'] + "/mediawiki-" + default["mediawiki"]["version"]
|
||||
default["mediawiki"]["version"] = "1.26.2"
|
||||
default["mediawiki"]["docroot_dir"] = "/var/www"
|
||||
default["mediawiki"]["webdir"] = "#{default["mediawiki"]["docroot_dir"]}/mediawiki-#{default["mediawiki"]["version"]}"
|
||||
default["mediawiki"]["tarball"]["name"] = "mediawiki-" + default["mediawiki"]["version"] + ".tar.gz"
|
||||
default["mediawiki"]["tarball"]["url"] = "https://releases.wikimedia.org/mediawiki/1.23/" + default["mediawiki"]["tarball"]["name"]
|
||||
default["mediawiki"]["database"]["name"] = "mediawiki"
|
||||
default["mediawiki"]["database"]["user"] = "mediawiki"
|
||||
default["mediawiki"]["database"]["password"] = "Ub3rPa55w0rd"
|
||||
default["mediawiki"]["tarball"]["url"] = "https://releases.wikimedia.org/mediawiki/1.26/" + default["mediawiki"]["tarball"]["name"]
|
||||
default["mediawiki"]["server_name"] = "wiki.localhost"
|
||||
default["mediawiki"]["scriptpath"] = ""
|
||||
default['mysql']['server_root_password'] = 'Fak3Pa55w0rd'
|
||||
|
||||
default["mediawiki"]["server"] = "http://" + default["mediawiki"]["server_name"]
|
||||
default["mediawiki"]["server"] = "http://" + default["mediawiki"]["server_name"]
|
||||
default["mediawiki"]["site_name"] = "my Wiki"
|
||||
default["mediawiki"]["language_code"] = "fr"
|
||||
default["mediawiki"]["language_code"] = "en"
|
||||
default["mediawiki"]["admin_user"] = "administrator"
|
||||
default["mediawiki"]["admin_password"] = "admin"
|
||||
|
||||
default["mediawiki"]["php_options"] = { "php_admin_value[upload_max_filesize]" => "50M", "php_admin_value[post_max_size]" => "55M" }
|
||||
|
||||
default['mediawiki']['db']['root_password'] = 'my_root_password'
|
||||
default['mediawiki']['db']['instance_name'] = 'default'
|
||||
default['mediawiki']['db']['name'] = "mediawikidb"
|
||||
default['mediawiki']['db']['user'] = "mediawikiuser"
|
||||
default['mediawiki']['db']['pass'] = nil
|
||||
default['mediawiki']['db']['prefix'] = 'wp_'
|
||||
default['mediawiki']['db']['host'] = 'localhost'
|
||||
default['mediawiki']['db']['port'] = '3307' # Must be a string
|
||||
default['mediawiki']['db']['charset'] = 'utf8'
|
||||
default['mediawiki']['db']['collate'] = ''
|
||||
|
@ -3,12 +3,15 @@ maintainer 'pulsation'
|
||||
license 'BSD'
|
||||
description 'Installs/Configures mediawiki'
|
||||
long_description 'Installs/Configures mediawiki'
|
||||
version '0.1.0'
|
||||
version '0.2.0'
|
||||
|
||||
depends 'apache2'
|
||||
depends 'php'
|
||||
depends 'mysql'
|
||||
depends 'database'
|
||||
depends 'nginx'
|
||||
depends 'mysql2_chef_gem'
|
||||
depends 'php-fpm'
|
||||
|
||||
attribute 'mediawiki/version',
|
||||
:display_name => "Mediawiki version",
|
||||
|
10
cookbooks/mediawiki/recipes/apache2.rb
Normal file
10
cookbooks/mediawiki/recipes/apache2.rb
Normal file
@ -0,0 +1,10 @@
|
||||
include_recipe "apache2"
|
||||
include_recipe "apache2::mod_php5"
|
||||
include_recipe "apache2::mod_rewrite"
|
||||
|
||||
# Add virtualhost
|
||||
web_app "mediawiki" do
|
||||
server_name node["mediawiki"]["server_name"]
|
||||
docroot node["mediawiki"]["webdir"]
|
||||
end
|
||||
|
63
cookbooks/mediawiki/recipes/database.rb
Normal file
63
cookbooks/mediawiki/recipes/database.rb
Normal file
@ -0,0 +1,63 @@
|
||||
::Chef::Recipe.send(:include, Opscode::OpenSSL::Password)
|
||||
|
||||
node.set_unless['mediawiki']['db']['pass'] = secure_password
|
||||
node.save unless Chef::Config[:solo]
|
||||
|
||||
db = node["mediawiki"]["db"]
|
||||
|
||||
mysql_client "default" do
|
||||
action :create
|
||||
end
|
||||
|
||||
mysql2_chef_gem "default" do
|
||||
action :install
|
||||
end
|
||||
|
||||
mysql_service db["instance_name"] do
|
||||
port db["port"]
|
||||
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
|
||||
|
||||
# Database connection information
|
||||
mysql_connection_info = {
|
||||
:host => "localhost",
|
||||
:username => "root",
|
||||
:socket => socket,
|
||||
:password => db["root_password"]
|
||||
}
|
||||
|
||||
# Create new database
|
||||
mysql_database db["name"] do
|
||||
connection mysql_connection_info
|
||||
action :create
|
||||
end
|
||||
|
||||
# Create new user
|
||||
mysql_database_user db["user"] do
|
||||
connection mysql_connection_info
|
||||
password db["pass"]
|
||||
action :create
|
||||
end
|
||||
|
||||
# Grant privilages to user
|
||||
mysql_database_user db["user"] do
|
||||
connection mysql_connection_info
|
||||
database_name db["name"]
|
||||
privileges [:all]
|
||||
action :grant
|
||||
end
|
@ -8,61 +8,25 @@
|
||||
#
|
||||
|
||||
include_recipe "apt"
|
||||
include_recipe "apache2"
|
||||
include_recipe "apache2::mod_php5"
|
||||
include_recipe "apache2::mod_rewrite"
|
||||
include_recipe "mysql::server"
|
||||
include_recipe "database::mysql"
|
||||
|
||||
include_recipe "php::default"
|
||||
include_recipe "php::module_apc"
|
||||
include_recipe "php::module_mysql"
|
||||
|
||||
include_recipe "mediawiki::database"
|
||||
|
||||
# Download mediawiki tarball
|
||||
remote_file "#{Chef::Config[:file_cache_path]}/" + node['mediawiki']['tarball']['name'] do
|
||||
remote_file "#{Chef::Config[:file_cache_path]}/#{node['mediawiki']['tarball']['name']}" do
|
||||
source node['mediawiki']['tarball']['url']
|
||||
notifies :run, "bash[extract_mediawiki]", :immediately
|
||||
end
|
||||
|
||||
# Extract mediawiki tarball
|
||||
bash "extract_mediawkiki" do
|
||||
bash "extract_mediawiki" do
|
||||
user "root"
|
||||
cwd node['apache']['docroot_dir']
|
||||
code "tar -zxf #{Chef::Config[:file_cache_path]}/" + node['mediawiki']['tarball']['name']
|
||||
action :run
|
||||
end
|
||||
|
||||
# Database connection information
|
||||
mysql_connection_info = {
|
||||
:host => 'localhost',
|
||||
:username => 'root',
|
||||
:password => node['mysql']['server_root_password']
|
||||
}
|
||||
|
||||
# Create new database
|
||||
mysql_database node['mediawiki']['database']['name'] do
|
||||
connection mysql_connection_info
|
||||
action :create
|
||||
end
|
||||
|
||||
# Create new user
|
||||
mysql_database_user node['mediawiki']['database']['user'] do
|
||||
connection mysql_connection_info
|
||||
password node['mediawiki']['database']['password']
|
||||
action :create
|
||||
end
|
||||
|
||||
# Grant privilages to user
|
||||
mysql_database_user node['mediawiki']['database']['user'] do
|
||||
connection mysql_connection_info
|
||||
database_name node["mediawiki"]["database"]["name"]
|
||||
privileges [:all]
|
||||
action :grant
|
||||
end
|
||||
|
||||
# Add virtualhost
|
||||
web_app "mediawiki" do
|
||||
server_name node["mediawiki"]["server_name"]
|
||||
docroot node["mediawiki"]["webdir"]
|
||||
cwd node["mediawiki"]["docroot_dir"]
|
||||
code "tar -zxf #{Chef::Config[:file_cache_path]}/#{node['mediawiki']['tarball']['name']}; chown -R #{node['nginx']['user']}:#{node['nginx']['group']} #{node['mediawiki']['docroot_dir']}"
|
||||
action :nothing
|
||||
end
|
||||
|
||||
# Additional packages
|
||||
@ -70,31 +34,33 @@ case node["platform_family"]
|
||||
when "rhel"
|
||||
package "php-xml"
|
||||
package "libicu-devel"
|
||||
service "apache2" do
|
||||
action :restart
|
||||
end
|
||||
when "debian"
|
||||
package "libicu-dev"
|
||||
end
|
||||
|
||||
|
||||
php_pear "intl" do
|
||||
action :install
|
||||
action :install
|
||||
end
|
||||
|
||||
# Configure mediawiki database
|
||||
bash "configure_mediawkiki_database" do
|
||||
user "root"
|
||||
cwd node["mediawiki"]["webdir"]
|
||||
code "php maintenance/install.php" +
|
||||
" --pass '" + node["mediawiki"]["admin_password"] +
|
||||
"' --dbname '" + node["mediawiki"]["database"]["name"] +
|
||||
"' --dbpass '" + node["mediawiki"]["database"]["password"] +
|
||||
"' --dbuser '" + node["mediawiki"]["database"]["name"] +
|
||||
"' --server '" + node["mediawiki"]["server"] +
|
||||
"' --scriptpath '" + node["mediawiki"]["scriptpath"] +
|
||||
bash "configure_mediawiki_database" do
|
||||
user node["nginx"]["user"]
|
||||
cwd node["mediawiki"]["webdir"]
|
||||
code "php maintenance/install.php" +
|
||||
" --pass '" + node["mediawiki"]["admin_password"] +
|
||||
"' --dbname '" + node["mediawiki"]["db"]["name"] +
|
||||
"' --dbpass '" + node["mediawiki"]["db"]["pass"] +
|
||||
"' --dbuser '" + node["mediawiki"]["db"]["user"] +
|
||||
"' --server '" + node["mediawiki"]["server"] +
|
||||
"' --scriptpath '" + node["mediawiki"]["scriptpath"] +
|
||||
"' --lang '" + node["mediawiki"]["language_code"] +
|
||||
"' '" + node["mediawiki"]["site_name"] + "' '" + node["mediawiki"]["admin_user"] + "'"
|
||||
action :run
|
||||
not_if { File.exist? "#{node["mediawiki"]["webdir"]}/LocalSettings.php" }
|
||||
action :run
|
||||
end
|
||||
|
||||
file "#{node["mediawiki"]["webdir"]}/LocalSettings.php" do
|
||||
mode "0640"
|
||||
owner node["nginx"]["user"]
|
||||
group node["nginx"]["group"]
|
||||
end
|
||||
|
59
cookbooks/mediawiki/recipes/nginx.rb
Normal file
59
cookbooks/mediawiki/recipes/nginx.rb
Normal file
@ -0,0 +1,59 @@
|
||||
#
|
||||
# Cookbook Name:: mediawiki
|
||||
# Recipe:: nginx
|
||||
#
|
||||
|
||||
node.set_unless['php-fpm']['pools'] = []
|
||||
|
||||
include_recipe "php-fpm"
|
||||
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 :install
|
||||
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 "php-fpm" do
|
||||
service_name php_fpm_service_name
|
||||
supports :start => true, :stop => true, :restart => true, :reload => true
|
||||
action [ :enable, :start ]
|
||||
end
|
||||
|
||||
php_fpm_pool "www" do
|
||||
enable false
|
||||
end
|
||||
|
||||
php_fpm_pool "mediawiki" do
|
||||
listen "127.0.0.1:9002"
|
||||
user node['nginx']['user']
|
||||
group node['nginx']['group']
|
||||
listen_owner node['nginx']['user']
|
||||
listen_group node['nginx']['group']
|
||||
php_options node['mediawiki']['php_options']
|
||||
start_servers 5
|
||||
enable true
|
||||
end
|
||||
|
||||
include_recipe "php::module_mysql"
|
||||
include_recipe "nginx"
|
||||
|
||||
directory node["mediawiki"]["docroot_dir"] do
|
||||
user node['nginx']['user']
|
||||
group node['nginx']['group']
|
||||
recursive true
|
||||
end
|
1
cookbooks/mysql/.foodcritic
Normal file
1
cookbooks/mysql/.foodcritic
Normal file
@ -0,0 +1 @@
|
||||
~FC005
|
@ -1,156 +1,163 @@
|
||||
mysql Cookbook CHANGELOG
|
||||
========================
|
||||
# mysql Cookbook CHANGELOG
|
||||
|
||||
v6.1.2 (2015-10-05)
|
||||
--------------------
|
||||
- Amazon Linux 2015.09
|
||||
This file is used to list changes made in each version of the mysql cookbook.
|
||||
|
||||
## v6.1.3 (2016-03-14)
|
||||
|
||||
- Added support for Ubuntu 15.10
|
||||
- Added support for Amazon Linux 2016-03
|
||||
- Updated Kitchen testing configs
|
||||
|
||||
## v6.1.2 (2015-10-05)
|
||||
|
||||
- Added support for Amazon Linux 2015.09
|
||||
|
||||
## v6.1.1 (2015-09-24)
|
||||
|
||||
v6.1.1 (2015-09-24)
|
||||
--------------------
|
||||
- Completing ChefSpec matchers
|
||||
|
||||
v6.1.0 (2015-07-17)
|
||||
--------------------
|
||||
## 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)
|
||||
--------------------
|
||||
## v6.0.31 (2015-07-13)
|
||||
|
||||
- Reverting create_stop_system_service checks
|
||||
|
||||
v6.0.30 (2015-07-13)
|
||||
--------------------
|
||||
## 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)
|
||||
--------------------
|
||||
## 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)
|
||||
--------------------
|
||||
## v6.0.28 (2015-07-10)
|
||||
|
||||
- Fixes for 12.4.x
|
||||
|
||||
v6.0.27 (2015-07-09)
|
||||
--------------------
|
||||
## v6.0.27 (2015-07-09)
|
||||
|
||||
- Allowing integer value for port number
|
||||
|
||||
v6.0.26 (2015-07-07)
|
||||
--------------------
|
||||
## v6.0.26 (2015-07-07)
|
||||
|
||||
- Reverting breaking changes introduced in 6.0.25
|
||||
|
||||
v6.0.25 (2015-07-06)
|
||||
--------------------
|
||||
## 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.24 (2015-06-27)
|
||||
|
||||
v6.0.23 (2015-06-21)
|
||||
--------------------
|
||||
- #354 Better handling of long MySQL startup times
|
||||
- 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)
|
||||
|
||||
v6.0.22 (2015-05-07)
|
||||
--------------------
|
||||
- Debian 8 (Jessie) support
|
||||
|
||||
v6.0.21 (2015-04-08)
|
||||
--------------------
|
||||
## v6.0.21 (2015-04-08)
|
||||
|
||||
- Fix to Upstart prestart script when using custom socket
|
||||
- Adding --explicit_defaults_for_timestamp mysql_install_db_cmd for
|
||||
5.6 and above
|
||||
- 5.6 and above
|
||||
|
||||
v6.0.20 (2015-03-27)
|
||||
--------------------
|
||||
- #318 - Fixing Upstart pre-start script to handle custom socket paths
|
||||
## v6.0.20 (2015-03-27)
|
||||
|
||||
- 318 - Fixing Upstart pre-start script to handle custom socket paths
|
||||
|
||||
## v6.0.19 (2015-03-25)
|
||||
|
||||
v6.0.19 (2015-03-25)
|
||||
--------------------
|
||||
- Adding support for Amazon Linux 2015.03
|
||||
|
||||
v6.0.18 (2015-03-24)
|
||||
--------------------
|
||||
## v6.0.18 (2015-03-24)
|
||||
|
||||
- Adding support for 5.6 and 5.7 packages from dotdeb repos on Debian 7
|
||||
|
||||
v6.0.17 (2015-03-13)
|
||||
--------------------
|
||||
## v6.0.17 (2015-03-13)
|
||||
|
||||
- Updated for MySQL 5.7.6.
|
||||
- Handing removal of mysql_install_db and mysqld_safe
|
||||
|
||||
v6.0.16 (2015-03-10)
|
||||
--------------------
|
||||
## v6.0.16 (2015-03-10)
|
||||
|
||||
- Moved --defaults-file as first option to mysql_install_db_script
|
||||
|
||||
v6.0.15 (2015-02-26)
|
||||
--------------------
|
||||
## v6.0.15 (2015-02-26)
|
||||
|
||||
- Updating docker detection fix to pass specs
|
||||
|
||||
v6.0.14 (2015-02-26)
|
||||
--------------------
|
||||
## v6.0.14 (2015-02-26)
|
||||
|
||||
- Fixed debian system service :disable action. Now survives reboot
|
||||
- Fixing centos-7 instance :enable action. Now survives
|
||||
- Not applying Apparmor policy if running in a Docker container
|
||||
|
||||
v6.0.13 (2015-02-15)
|
||||
--------------------
|
||||
## v6.0.13 (2015-02-15)
|
||||
|
||||
- Adding support for special characters in initial_root_password
|
||||
- Fixing failure status bug in sysvinit script
|
||||
|
||||
v6.0.12 (2015-02-30)
|
||||
--------------------
|
||||
- No changes. Released a 6.0.11 that was identical to 6.0.10.
|
||||
Git before coffee.
|
||||
## v6.0.12 (2015-02-30)
|
||||
|
||||
- No changes. Released a 6.0.11 that was identical to 6.0.10.
|
||||
- Git before coffee.
|
||||
|
||||
## v6.0.11 (2015-02-30)
|
||||
|
||||
v6.0.11 (2015-02-30)
|
||||
--------------------
|
||||
- Adding support for configurable socket files
|
||||
|
||||
v6.0.10 (2015-01-19)
|
||||
------------------
|
||||
## v6.0.10 (2015-01-19)
|
||||
|
||||
- Fix #282 - Fixing up data_dir template variable
|
||||
|
||||
v6.0.9 (2015-01-19)
|
||||
------------------
|
||||
## v6.0.9 (2015-01-19)
|
||||
|
||||
- Fix #282 - undefined method `parsed_data_dir' bug
|
||||
|
||||
v6.0.8 (2015-01-19)
|
||||
------------------
|
||||
## v6.0.8 (2015-01-19)
|
||||
|
||||
- Refactoring helper methods out of resource classes
|
||||
|
||||
v6.0.7 (2015-01-14)
|
||||
------------------
|
||||
- Fixing timing issue with Upstart provider :restart and :reload
|
||||
actions where service returns before being available
|
||||
## v6.0.7 (2015-01-14)
|
||||
|
||||
- Fixing timing issue with Upstart provider :restart and :reload
|
||||
- actions where service returns before being available
|
||||
|
||||
## v6.0.6 (2014-12-26)
|
||||
|
||||
v6.0.6 (2014-12-26)
|
||||
------------------
|
||||
- Fixing subtle bug where MysqlCookbook::Helper methods were polluting Chef::Resource
|
||||
|
||||
v6.0.5 (2014-12-25)
|
||||
------------------
|
||||
## v6.0.5 (2014-12-25)
|
||||
|
||||
- Using 'include_recipe' instead of 'recipe_eval' in LWRP
|
||||
- Fixing type checking on package_name attribute in mysql_client resource.
|
||||
|
||||
v6.0.4 (2014-12-21)
|
||||
------------------
|
||||
## v6.0.4 (2014-12-21)
|
||||
|
||||
- Suggest available versions if current is not available for current platform.
|
||||
|
||||
v6.0.3 (2014-12-17)
|
||||
------------------
|
||||
## v6.0.3 (2014-12-17)
|
||||
|
||||
- Adding bind_address parameter to mysql_service resource
|
||||
|
||||
v6.0.2 (2014-12-17)
|
||||
------------------
|
||||
## v6.0.2 (2014-12-17)
|
||||
|
||||
- Fixing sysvinit provider to survive reboots
|
||||
|
||||
v6.0.1 (2014-12-16)
|
||||
------------------
|
||||
## v6.0.1 (2014-12-16)
|
||||
|
||||
- Fixing Upstart template to survive reboots
|
||||
|
||||
v6.0.0 (2014-12-15)
|
||||
------------------
|
||||
## v6.0.0 (2014-12-15)
|
||||
|
||||
- Major version update
|
||||
- Cookbook now provides LWRPs instead of recipes
|
||||
- Platform providers re-factored into init system providers
|
||||
@ -164,12 +171,12 @@ v6.0.0 (2014-12-15)
|
||||
- Refactored acceptance tests
|
||||
- Temporarily dropped FreeBSD support
|
||||
|
||||
v5.6.1 (2014-10-29)
|
||||
------------------
|
||||
## v5.6.1 (2014-10-29)
|
||||
|
||||
- Use Gem::Version instead of Chef::Version
|
||||
|
||||
v5.6.0 (2014-10-29)
|
||||
------------------
|
||||
## v5.6.0 (2014-10-29)
|
||||
|
||||
- Changing default charset to utf8
|
||||
- Quoting passwords in debian.cnf.erb
|
||||
- Amazon 2014.09 support
|
||||
@ -177,47 +184,47 @@ v5.6.0 (2014-10-29)
|
||||
- Only hide passwords from STDOUT via "sensitive true" in chef-client higher than 11.14
|
||||
- Updating test harness
|
||||
|
||||
v5.5.4 (2014-10-07)
|
||||
------------------
|
||||
## v5.5.4 (2014-10-07)
|
||||
|
||||
- Adding sensitive flag to execute resources to protect passwords from logs
|
||||
|
||||
v5.5.3 (2014-09-24)
|
||||
------------------
|
||||
## v5.5.3 (2014-09-24)
|
||||
|
||||
- Reverting back to Upstart on Ubuntu 14.04
|
||||
|
||||
v5.5.2 (2014-09-8)
|
||||
------------------
|
||||
## v5.5.2 (2014-09-8)
|
||||
|
||||
- Reverting commit that broke Debian pass_string
|
||||
|
||||
v5.5.1 (2014-09-2)
|
||||
------------------
|
||||
## v5.5.1 (2014-09-2)
|
||||
|
||||
- Switching Ubuntu service provider to use SysVinit instead of Upstart
|
||||
|
||||
v5.5.0 (2014-08-27)
|
||||
-------------------
|
||||
## v5.5.0 (2014-08-27)
|
||||
|
||||
- Adding package version and action parameters to mysql_service resource
|
||||
- Fixing Debian pass_string
|
||||
|
||||
v5.4.4 (2014-08-27)
|
||||
-------------------
|
||||
## v5.4.4 (2014-08-27)
|
||||
|
||||
- Changing module namespace to MysqlCookbook
|
||||
|
||||
v5.4.3 (2014-08-25)
|
||||
-------------------
|
||||
## v5.4.3 (2014-08-25)
|
||||
|
||||
- More refactoring. Moving helper function bits into resource parsed_parameters
|
||||
|
||||
v5.4.2 (2014-08-25)
|
||||
-------------------
|
||||
## v5.4.2 (2014-08-25)
|
||||
|
||||
- Moving provider local variables into definitions for RHEL provider
|
||||
|
||||
v5.4.1 (2014-08-25)
|
||||
-------------------
|
||||
## v5.4.1 (2014-08-25)
|
||||
|
||||
- Refactoring resources into the LWRP style with parsed parameters
|
||||
- Moving provider local variables into definitions
|
||||
|
||||
v5.4.0 (2014-08-25)
|
||||
-------------------
|
||||
- #212 - support for centos-7 (mysql55 and mysql56)
|
||||
## v5.4.0 (2014-08-25)
|
||||
|
||||
- 212 - support for centos-7 (mysql55 and mysql56)
|
||||
- Adding (untested) Debian-6 support
|
||||
- Adding Suse support to metadata.rb
|
||||
- Adding ability to change MySQL root password
|
||||
@ -225,198 +232,170 @@ v5.4.0 (2014-08-25)
|
||||
- Appeasing AppArmor
|
||||
- Reducing duplication in client provider
|
||||
|
||||
v5.3.6 (2014-06-18)
|
||||
-------------------
|
||||
## v5.3.6 (2014-06-18)
|
||||
|
||||
- Fixing pid path location. Updating tests to include real RHEL
|
||||
|
||||
## v5.3.4 (2014-06-16)
|
||||
|
||||
v5.3.4 (2014-06-16)
|
||||
-------------------
|
||||
- Fixing specs for Amazon Linux server package names
|
||||
|
||||
## v5.3.2 (2014-06-16)
|
||||
|
||||
v5.3.2 (2014-06-16)
|
||||
-------------------
|
||||
- Fixing Amazon Linux support
|
||||
|
||||
## v5.3.0 (2014-06-11)
|
||||
|
||||
v5.3.0 (2014-06-11)
|
||||
-------------------
|
||||
- #189 - Fix server_repl_password description
|
||||
- #191 - Adding support for server55 and server56 on el-6
|
||||
- #193 - Fix syntax in mysql_service example
|
||||
- #199 - Adding Suse support
|
||||
- 189 - Fix server_repl_password description
|
||||
- 191 - Adding support for server55 and server56 on el-6
|
||||
- 193 - Fix syntax in mysql_service example
|
||||
- 199 - Adding Suse support
|
||||
|
||||
## v5.2.12 (2014-05-19)
|
||||
|
||||
v5.2.12 (2014-05-19)
|
||||
--------------------
|
||||
PR #192 - recipes/server.rb should honor parameter node['mysql']['version']
|
||||
|
||||
## v5.2.10 (2014-05-15)
|
||||
|
||||
v5.2.10 (2014-05-15)
|
||||
--------------------
|
||||
- COOK-4394 - restore freebsd support
|
||||
|
||||
## v5.2.8 (2014-05-15)
|
||||
|
||||
v5.2.8 (2014-05-15)
|
||||
-------------------
|
||||
- [COOK-4653] - Missing mySQL 5.6 support for Ubuntu 14.04
|
||||
|
||||
## v5.2.6 (2014-05-07)
|
||||
|
||||
v5.2.6 (2014-05-07)
|
||||
-------------------
|
||||
- [COOK-4625] - Fix password resource parameter consumption on Debian and Ubuntu
|
||||
- Fix up typos and version numbers in PLATFORMS.md
|
||||
- Fix up specs from COOK-4613 changes
|
||||
|
||||
## v5.2.4 (2014-05-02)
|
||||
|
||||
v5.2.4 (2014-05-02)
|
||||
-------------------
|
||||
- [COOK-4613] - Fix permissions on mysql data_dir to allow global access to mysql.sock
|
||||
|
||||
## v5.2.2 (2014-04-24)
|
||||
|
||||
v5.2.2 (2014-04-24)
|
||||
-------------------
|
||||
- [COOK-4564] - Using positive tests for datadir move
|
||||
|
||||
## v5.2.0 (2014-04-22)
|
||||
|
||||
v5.2.0 (2014-04-22)
|
||||
-------------------
|
||||
- [COOK-4551] - power grants.sql from resource parameters
|
||||
|
||||
## v5.1.12 (2014-04-21)
|
||||
|
||||
v5.1.12 (2014-04-21)
|
||||
--------------------
|
||||
- [COOK-4554] - Support for Debian Sid
|
||||
|
||||
## v5.1.10 (2014-04-21)
|
||||
|
||||
v5.1.10 (2014-04-21)
|
||||
--------------------
|
||||
- [COOK-4565] Support for Ubuntu 14.04
|
||||
- [COOK-4565] Adding Specs and TK platform
|
||||
- Removing non-LTS 13.10 specs and TK platform
|
||||
|
||||
## v5.1.8 (2014-04-12)
|
||||
|
||||
v5.1.8 (2014-04-12)
|
||||
-------------------
|
||||
Adding Ubuntu 13.04 to Platforminfo
|
||||
|
||||
## v5.1.6 (2014-04-11)
|
||||
|
||||
v5.1.6 (2014-04-11)
|
||||
-------------------
|
||||
- [COOK-4548] - Add template[/etc/mysql/debian.cnf] to Ubuntu provider
|
||||
|
||||
## v5.1.4 (2014-04-11)
|
||||
|
||||
v5.1.4 (2014-04-11)
|
||||
-------------------
|
||||
- [COOK-4547] - Shellescape server_root_password
|
||||
|
||||
## v5.1.2 (2014-04-09)
|
||||
|
||||
v5.1.2 (2014-04-09)
|
||||
-------------------
|
||||
- [COOK-4519] - Fix error in run_dir for Ubuntu
|
||||
- [COOK-4531] - Fix pid and run_dir for Debian
|
||||
|
||||
## v5.1.0 (2014-04-08)
|
||||
|
||||
v5.1.0 (2014-04-08)
|
||||
-------------------
|
||||
[COOK-4523] - Allow for both :restart and :reload
|
||||
|
||||
## v5.0.6 (2014-04-07)
|
||||
|
||||
v5.0.6 (2014-04-07)
|
||||
-------------------
|
||||
- [COOK-4519] - Updating specs to reflect pid file change on Ubuntu
|
||||
|
||||
## v5.0.4 (2014-04-07)
|
||||
|
||||
v5.0.4 (2014-04-07)
|
||||
-------------------
|
||||
- [COOK-4519] - Fix path to pid file on Ubuntu
|
||||
|
||||
## v5.0.2 (2014-04-01)
|
||||
|
||||
v5.0.2 (2014-04-01)
|
||||
-------------------
|
||||
- Moving server_deprecated into recipes directory
|
||||
|
||||
## v5.0.0 (2014-03-31)
|
||||
|
||||
v5.0.0 (2014-03-31)
|
||||
-------------------
|
||||
- Rewriting as a library cookbook
|
||||
- Exposing mysql_service and mysql_client resources
|
||||
- User now needs to supply configuration
|
||||
- Moving attribute driven recipe to server-deprecated
|
||||
|
||||
## v4.1.2 (2014-02-28)
|
||||
|
||||
v4.1.2 (2014-02-28)
|
||||
-------------------
|
||||
- [COOK-4349] - Fix invalid platform check
|
||||
- [COOK-4184] - Better handling of Ubuntu upstart service
|
||||
- [COOK-2100] - Changing innodb_log_file_size tunable results in inability to start MySQL
|
||||
|
||||
## v4.1.1 (2014-02-25)
|
||||
|
||||
v4.1.1 (2014-02-25)
|
||||
-------------------
|
||||
- **[COOK-2966] - Address foodcritic failures'
|
||||
- **[COOK-4182] - Template parse failure in /etc/init/mysql.conf (data_dir)'
|
||||
- **[COOK-4198] - Added missing tunable'
|
||||
- **[COOK-4206] - create root@127.0.0.1, as well as root@localhost'
|
||||
|
||||
## v4.0.20 (2014-01-18)
|
||||
|
||||
v4.0.20 (2014-01-18)
|
||||
--------------------
|
||||
* [COOK-3931] - MySQL Server Recipe Regression for Non-LTS Ubuntu Versions
|
||||
* [COOK-3945] - MySQL cookbook fails on Ubuntu 13.04/13.10
|
||||
* [COOK-3966] - mysql::server recipe can't find a template with debian 7.x
|
||||
* [COOK-3985] - Missing /etc/mysql/debian.cnf template on mysql::_server_debian.rb recipe (mysql 4.0.4)
|
||||
* [COOK-3974] - debian.cnf not updated
|
||||
* [COOK-4001] - Pull request: Fixes for broken mysql::server on Debian
|
||||
* [COOK-4071] - Mysql cookbook doesn't work on debian 7.2
|
||||
- [COOK-3931] - MySQL Server Recipe Regression for Non-LTS Ubuntu Versions
|
||||
- [COOK-3945] - MySQL cookbook fails on Ubuntu 13.04/13.10
|
||||
- [COOK-3966] - mysql::server recipe can't find a template with debian 7.x
|
||||
- [COOK-3985] - Missing /etc/mysql/debian.cnf template on mysql::_server_debian.rb recipe (mysql 4.0.4)
|
||||
- [COOK-3974] - debian.cnf not updated
|
||||
- [COOK-4001] - Pull request: Fixes for broken mysql::server on Debian
|
||||
- [COOK-4071] - Mysql cookbook doesn't work on debian 7.2
|
||||
|
||||
## v4.0.14
|
||||
|
||||
v4.0.14
|
||||
-------
|
||||
Fixing style cops
|
||||
|
||||
## v4.0.12
|
||||
|
||||
v4.0.12
|
||||
-------
|
||||
### Bug
|
||||
|
||||
- **[COOK-4068](https://tickets.chef.io/browse/COOK-4068)** - rework MySQL Windows recipe
|
||||
|
||||
### Improvement
|
||||
|
||||
- **[COOK-3801](https://tickets.chef.io/browse/COOK-3801)** - Add innodb_adaptive_flushing_method and innodb_adaptive_checkpoint
|
||||
|
||||
## v4.0.10
|
||||
|
||||
v4.0.10
|
||||
-------
|
||||
fixing metadata version error. locking to 3.0
|
||||
|
||||
## v4.0.8
|
||||
|
||||
v4.0.8
|
||||
------
|
||||
Locking yum dependency to '< 3'
|
||||
|
||||
## v4.0.6
|
||||
|
||||
v4.0.6
|
||||
------
|
||||
# Bug
|
||||
|
||||
- [COOK-3943] Notifying service restart on grants update
|
||||
|
||||
## v4.0.4
|
||||
|
||||
v4.0.4
|
||||
------
|
||||
[COOK-3952] - Adding 'recursive true' to directory resources
|
||||
|
||||
## v4.0.2
|
||||
|
||||
v4.0.2
|
||||
------
|
||||
### BUGS
|
||||
|
||||
- Adding support for Amazon Linux in attributes/server_rhel.rb
|
||||
- Fixing bug where unprivileged users cannot connect over a local socket. Adding integration test.
|
||||
- Fixing bug in mysql_grants_cmd generation
|
||||
|
||||
## v4.0.0
|
||||
|
||||
v4.0.0
|
||||
------
|
||||
- [COOK-3928] Heavily refactoring for readability. Moving platform implementation into separate recipes
|
||||
- Moving integration tests from minitest to serverspec, removing "improper" tests
|
||||
- Moving many attributes into the ['mysql']['server']['whatever'] namespace
|
||||
@ -426,27 +405,26 @@ v4.0.0
|
||||
- [COOK-3807] - Don't use execute[assign-root-password] on Debian and Ubuntu
|
||||
- [COOK-3881] - Fixing /etc being owned by mysql user
|
||||
|
||||
## v3.0.12
|
||||
|
||||
v3.0.12
|
||||
-------
|
||||
### Bug
|
||||
|
||||
- **[COOK-3752](https://tickets.chef.io/browse/COOK-3752)** - mysql service fails to start in mysql::server recipe
|
||||
|
||||
## v3.0.10
|
||||
|
||||
v3.0.10
|
||||
-------
|
||||
- Fix a failed release attempt for v3.0.8
|
||||
|
||||
## v3.0.8
|
||||
|
||||
v3.0.8
|
||||
------
|
||||
### Bug
|
||||
|
||||
- **[COOK-3749](https://tickets.chef.io/browse/COOK-3749)** - Fix a regression with Chef 11-specific features
|
||||
|
||||
## v3.0.6
|
||||
|
||||
v3.0.6
|
||||
------
|
||||
### Bug
|
||||
|
||||
- **[COOK-3674](https://tickets.chef.io/browse/COOK-3674)** - Fix an issue where the MySQL server fails to set the root password correctly when `data_dir` is a non-default value
|
||||
- **[COOK-3647](https://tickets.chef.io/browse/COOK-3647)** - Fix README typo (databas => database)
|
||||
- **[COOK-3477](https://tickets.chef.io/browse/COOK-3477)** - Fix log-queries-not-using-indexes not working
|
||||
@ -457,30 +435,33 @@ v3.0.6
|
||||
- **[COOK-2606](https://tickets.chef.io/browse/COOK-2606)** - Use proper bind address on cloud providers
|
||||
|
||||
### Improvement
|
||||
|
||||
- **[COOK-3498](https://tickets.chef.io/browse/COOK-3498)** - Add support for replicate_* variables in my.cnf
|
||||
|
||||
## v3.0.4
|
||||
|
||||
v3.0.4
|
||||
------
|
||||
### Bug
|
||||
|
||||
- **[COOK-3310](https://tickets.chef.io/browse/COOK-3310)** - Fix missing `GRANT` option
|
||||
- **[COOK-3233](https://tickets.chef.io/browse/COOK-3233)** - Fix escaping special characters
|
||||
- **[COOK-3156](https://tickets.chef.io/browse/COOK-3156)** - Fix GRANTS file when `remote_root_acl` is specified
|
||||
- **[COOK-3134](https://tickets.chef.io/browse/COOK-3134)** - Fix Chef 11 support
|
||||
- **[COOK-2318](https://tickets.chef.io/browse/COOK-2318)** - Remove redundant `if` block around `node.mysql.tunable.log_bin`
|
||||
|
||||
v3.0.2
|
||||
------
|
||||
## v3.0.2
|
||||
|
||||
### Bug
|
||||
|
||||
- [COOK-2158]: apt-get update is run twice at compile time
|
||||
- [COOK-2832]: mysql grants.sql file has errors depending on attrs
|
||||
- [COOK-2995]: server.rb is missing a platform_family comparison value
|
||||
|
||||
### Sub-task
|
||||
|
||||
- [COOK-2102]: `innodb_flush_log_at_trx_commit` value is incorrectly set based on CPU count
|
||||
|
||||
v3.0.0
|
||||
------
|
||||
## v3.0.0
|
||||
|
||||
**Note** This is a backwards incompatible version with previous versions of the cookbook. Tickets that introduce incompatibility are COOK-2615 and COOK-2617.
|
||||
|
||||
- [COOK-2478] - Duplicate 'read_only' server attribute in base and tunable
|
||||
@ -501,24 +482,24 @@ v3.0.0
|
||||
- [COOK-2618] - myisam-recover not using attribute value
|
||||
- [COOK-2617] - open-files is a duplicate of open-files-limit
|
||||
|
||||
v2.1.2
|
||||
------
|
||||
## v2.1.2
|
||||
|
||||
- [COOK-2172] - Mysql cookbook duplicates `binlog_format` configuration
|
||||
|
||||
v2.1.0
|
||||
------
|
||||
## v2.1.0
|
||||
|
||||
- [COOK-1669] - Using platform("ubuntu") in default attributes always returns true
|
||||
- [COOK-1694] - Added additional my.cnf fields and reorganized cookbook to avoid race conditions with mysql startup and sql script execution
|
||||
- [COOK-1851] - Support server-id and binlog_format settings
|
||||
- [COOK-1929] - Update msyql server attributes file because setting attributes without specifying a precedence is deprecated
|
||||
- [COOK-1999] - Add read_only tunable useful for replication slave servers
|
||||
|
||||
v2.0.2
|
||||
------
|
||||
## v2.0.2
|
||||
|
||||
- [COOK-1967] - mysql: trailing comma in server.rb platform family
|
||||
|
||||
v2.0.0
|
||||
------
|
||||
## v2.0.0
|
||||
|
||||
**Important note for this release**
|
||||
|
||||
Under Chef Solo, you must set the node attributes for the root, debian and repl passwords or the run will completely fail. See COOK-1737 for background on this.
|
||||
@ -534,8 +515,8 @@ Under Chef Solo, you must set the node attributes for the root, debian and repl
|
||||
- [COOK-1769] - link to database recipe in mysql README goes to old chef/cookbooks repo instead of chef-cookbook organization
|
||||
- [COOK-1963] - use `platform_family`
|
||||
|
||||
v1.3.0
|
||||
------
|
||||
## v1.3.0
|
||||
|
||||
**Important note for this release**
|
||||
|
||||
This version no longer installs Ruby bindings in the client recipe by default. Use the ruby recipe if you'd like the RubyGem. If you'd like packages from your distribution, use them in your application's specific cookbook/recipe, or modify the client packages attribute. This resolves the following tickets:
|
||||
@ -558,56 +539,56 @@ The following issues are also addressed in this release.
|
||||
- [COOK-934] - remove deprecated mysql/libraries/database.rb, use the database cookbook instead.
|
||||
- [COOK-1475] - fix restart on config change
|
||||
|
||||
v1.2.6
|
||||
------
|
||||
## v1.2.6
|
||||
|
||||
- [COOK-1113] - Use an attribute to determine if upstart is used
|
||||
- [COOK-1121] - Add support for Windows
|
||||
- [COOK-1140] - Fix conf.d on Debian
|
||||
- [COOK-1151] - Fix server_ec2 handling /var/lib/mysql bind mount
|
||||
- [COOK-1321] - Document setting password attributes for solo
|
||||
|
||||
v1.2.4
|
||||
------
|
||||
## v1.2.4
|
||||
|
||||
- [COOK-992] - fix FATAL nameerror
|
||||
- [COOK-827] - `mysql:server_ec2` recipe can't mount `data_dir`
|
||||
- [COOK-945] - FreeBSD support
|
||||
|
||||
v1.2.2
|
||||
------
|
||||
## v1.2.2
|
||||
|
||||
- [COOK-826] mysql::server recipe doesn't quote password string
|
||||
- [COOK-834] Add 'scientific' and 'amazon' platforms to mysql cookbook
|
||||
|
||||
v1.2.1
|
||||
------
|
||||
## v1.2.1
|
||||
|
||||
- [COOK-644] Mysql client cookbook 'package missing' error message is confusing
|
||||
- [COOK-645] RHEL6/CentOS6 - mysql cookbook contains 'skip-federated' directive which is unsupported on MySQL 5.1
|
||||
|
||||
v1.2.0
|
||||
------
|
||||
## v1.2.0
|
||||
|
||||
- [COOK-684] remove mysql_database LWRP
|
||||
|
||||
v1.0.8
|
||||
------
|
||||
## v1.0.8
|
||||
|
||||
- [COOK-633] ensure "cloud" attribute is available
|
||||
|
||||
v1.0.7
|
||||
------
|
||||
## v1.0.7
|
||||
|
||||
- [COOK-614] expose all mysql tunable settings in config
|
||||
- [COOK-617] bind to private IP if available
|
||||
|
||||
v1.0.6
|
||||
------
|
||||
## v1.0.6
|
||||
|
||||
- [COOK-605] install mysql-client package on ubuntu/debian
|
||||
|
||||
v1.0.5
|
||||
------
|
||||
## v1.0.5
|
||||
|
||||
- [COOK-465] allow optional remote root connections to mysql
|
||||
- [COOK-455] improve platform version handling
|
||||
- externalize conf_dir attribute for easier cross platform support
|
||||
- change datadir attribute to data_dir for consistency
|
||||
|
||||
v1.0.4
|
||||
------
|
||||
## v1.0.4
|
||||
|
||||
- fix regressions on debian platform
|
||||
- [COOK-578] wrap root password in quotes
|
||||
- [COOK-562] expose all tunables in my.cnf
|
||||
|
2
cookbooks/mysql/CONTRIBUTING.md
Normal file
2
cookbooks/mysql/CONTRIBUTING.md
Normal file
@ -0,0 +1,2 @@
|
||||
Please refer to
|
||||
https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD
|
19
cookbooks/mysql/MAINTAINERS.md
Normal file
19
cookbooks/mysql/MAINTAINERS.md
Normal file
@ -0,0 +1,19 @@
|
||||
<!-- This is a generated file. Please do not edit directly -->
|
||||
|
||||
# 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)
|
@ -1,28 +1,22 @@
|
||||
MySQL Cookbook
|
||||
=====================
|
||||
# MySQL Cookbook
|
||||
|
||||
[](https://gitter.im/chef-cookbooks/mysql?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://travis-ci.org/chef-cookbooks/mysql) [](https://supermarket.chef.io/cookbooks/mysql)
|
||||
|
||||
The Mysql Cookbook is a library cookbook that provides resource primitives
|
||||
(LWRPs) for use in recipes. It is designed to be a reference example for
|
||||
creating highly reusable cross-platform cookbooks.
|
||||
The Mysql Cookbook is a library cookbook that provides resource primitives (LWRPs) for use in recipes. It is designed to be a reference example for creating highly reusable cross-platform cookbooks.
|
||||
|
||||
Scope
|
||||
-----
|
||||
This cookbook is concerned with the "MySQL Community Server",
|
||||
particularly those shipped with F/OSS Unix and Linux distributions. It
|
||||
does not address forks or value-added repackaged MySQL distributions
|
||||
like Drizzle, MariaDB, or Percona.
|
||||
## Scope
|
||||
|
||||
This cookbook is concerned with the "MySQL Community Server", particularly those shipped with F/OSS Unix and Linux distributions. It does not address forks or value-added repackaged MySQL distributions like Drizzle, MariaDB, or Percona.
|
||||
|
||||
## Requirements
|
||||
|
||||
Requirements
|
||||
------------
|
||||
- Chef 11 or higher
|
||||
- Ruby 1.9 or higher (preferably from the Chef full-stack installer)
|
||||
- Network accessible package repositories
|
||||
- 'recipe[selinux::disabled]' on RHEL platforms
|
||||
|
||||
Platform Support
|
||||
----------------
|
||||
## Platform Support
|
||||
|
||||
The following platforms have been tested with Test Kitchen:
|
||||
|
||||
```
|
||||
@ -31,8 +25,6 @@ The following platforms have been tested with Test Kitchen:
|
||||
|----------------+-----+-----+-----+-----+-----|
|
||||
| debian-7 | | | X | | |
|
||||
|----------------+-----+-----+-----+-----+-----|
|
||||
| ubuntu-10.04 | | X | | | |
|
||||
|----------------+-----+-----+-----+-----+-----|
|
||||
| ubuntu-12.04 | | | X | | |
|
||||
|----------------+-----+-----+-----+-----+-----|
|
||||
| ubuntu-14.04 | | | X | X | |
|
||||
@ -47,24 +39,21 @@ The following platforms have been tested with Test Kitchen:
|
||||
|----------------+-----+-----+-----+-----+-----|
|
||||
| amazon | | | X | X | X |
|
||||
|----------------+-----+-----+-----+-----+-----|
|
||||
| fedora-20 | | | X | X | X |
|
||||
| fedora-22 | | | X | X | X |
|
||||
|----------------+-----+-----+-----+-----+-----|
|
||||
| suse-11.3 | | | X | | |
|
||||
|----------------+-----+-----+-----+-----+-----|
|
||||
| omnios-151006 | | | X | X | |
|
||||
|----------------+-----+-----+-----+-----+-----|
|
||||
| smartos-14.3.0 | | | X | X | |
|
||||
| fedora-23 | | | X | X | X |
|
||||
|----------------+-----+-----+-----+-----+-----|
|
||||
```
|
||||
|
||||
Cookbook Dependencies
|
||||
------------
|
||||
## Cookbook Dependencies
|
||||
|
||||
- yum-mysql-community
|
||||
- smf
|
||||
|
||||
Usage
|
||||
-----
|
||||
## Usage
|
||||
|
||||
Place a dependency on the mysql cookbook in your cookbook's metadata.rb
|
||||
|
||||
```ruby
|
||||
depends 'mysql', '~> 6.0'
|
||||
```
|
||||
@ -80,11 +69,9 @@ mysql_service 'foo' do
|
||||
end
|
||||
```
|
||||
|
||||
The service name on the OS is `mysql-foo`. You can manually start and
|
||||
stop it with `service mysql-foo start` and `service mysql-foo stop`.
|
||||
The service name on the OS is `mysql-foo`. You can manually start and stop it with `service mysql-foo start` and `service mysql-foo stop`.
|
||||
|
||||
The configuration file is at `/etc/mysql-foo/my.cnf`. It contains the
|
||||
minimum options to get the service running. It looks like this.
|
||||
The configuration file is at `/etc/mysql-foo/my.cnf`. It contains the minimum options to get the service running. It looks like this.
|
||||
|
||||
```
|
||||
# Chef generated my.cnf for instance mysql-foo
|
||||
@ -111,8 +98,7 @@ log-error = /var/log/mysql-foo/error.log
|
||||
socket = /var/run/mysql-foo/mysqld.sock
|
||||
```
|
||||
|
||||
You can put extra configuration into the conf.d directory by using the
|
||||
`mysql_config` resource, like this:
|
||||
You can put extra configuration into the conf.d directory by using the `mysql_config` resource, like this:
|
||||
|
||||
```ruby
|
||||
mysql_service 'foo' do
|
||||
@ -129,130 +115,65 @@ mysql_config 'foo' do
|
||||
end
|
||||
```
|
||||
|
||||
You are responsible for providing `my_extra_settings.erb` in your own
|
||||
cookbook's templates folder.
|
||||
You are responsible for providing `my_extra_settings.erb` in your own cookbook's templates folder.
|
||||
|
||||
Connecting with the mysql CLI command
|
||||
-------------------------------------
|
||||
Logging into the machine and typing `mysql` with no extra arguments
|
||||
will fail. You need to explicitly connect over the socket with `mysql
|
||||
-S /var/run/mysql-foo/mysqld.sock`, or over the network with `mysql -h
|
||||
127.0.0.1`
|
||||
## Connecting with the mysql CLI command
|
||||
|
||||
Upgrading from older version of the mysql cookbook
|
||||
--------------------------------------------------
|
||||
- It is strongly recommended that you rebuild the machine from
|
||||
scratch. This is easy if you have your `data_dir` on a dedicated
|
||||
mount point. If you *must* upgrade in-place, follow the instructions
|
||||
below.
|
||||
Logging into the machine and typing `mysql` with no extra arguments will fail. You need to explicitly connect over the socket with `mysql -S /var/run/mysql-foo/mysqld.sock`, or over the network with `mysql -h 127.0.0.1`
|
||||
|
||||
- The 6.x series supports multiple service instances on a single
|
||||
machine. It dynamically names the support directories and service
|
||||
names. `/etc/mysql becomes /etc/mysql-instance_name`. Other support
|
||||
directories in `/var` `/run` etc work the same way. Make sure to
|
||||
specify the `data_dir` property on the `mysql_service` resource to
|
||||
point to the old `/var/lib/mysql` directory.
|
||||
## Upgrading from older version of the mysql cookbook
|
||||
|
||||
- It is strongly recommended that you rebuild the machine from scratch. This is easy if you have your `data_dir` on a dedicated mount point. If you _must_ upgrade in-place, follow the instructions below.
|
||||
- The 6.x series supports multiple service instances on a single machine. It dynamically names the support directories and service names. `/etc/mysql becomes /etc/mysql-instance_name`. Other support directories in `/var` `/run` etc work the same way. Make sure to specify the `data_dir` property on the `mysql_service` resource to point to the old `/var/lib/mysql` directory.
|
||||
|
||||
## Resources Overview
|
||||
|
||||
Resources Overview
|
||||
------------------
|
||||
### mysql_service
|
||||
|
||||
The `mysql_service` resource manages the basic plumbing needed to get a
|
||||
MySQL server instance running with minimal configuration.
|
||||
The `mysql_service` resource manages the basic plumbing needed to get a MySQL server instance running with minimal configuration.
|
||||
|
||||
The `:create` action handles package installation, support
|
||||
directories, socket files, and other operating system level concerns.
|
||||
The internal configuration file contains just enough to get the
|
||||
service up and running, then loads extra configuration from a conf.d
|
||||
directory. Further configurations are managed with the `mysql_config` resource.
|
||||
The `:create` action handles package installation, support directories, socket files, and other operating system level concerns. The internal configuration file contains just enough to get the service up and running, then loads extra configuration from a conf.d directory. Further configurations are managed with the `mysql_config` resource.
|
||||
|
||||
- If the `data_dir` is empty, a database will be initialized, and a
|
||||
root user will be set up with `initial_root_password`. If this
|
||||
directory already contains database files, no action will be taken.
|
||||
- root user will be set up with `initial_root_password`. If this
|
||||
- directory already contains database files, no action will be taken.
|
||||
|
||||
The `:start` action starts the service on the machine using the
|
||||
appropriate provider for the platform. The `:start` action should be
|
||||
omitted when used in recipes designed to build containers.
|
||||
The `:start` action starts the service on the machine using the appropriate provider for the platform. The `:start` action should be omitted when used in recipes designed to build containers.
|
||||
|
||||
#### Example
|
||||
|
||||
```ruby
|
||||
mysql_service 'default' do
|
||||
version '5.7'
|
||||
bind_address '0.0.0.0'
|
||||
port '3306'
|
||||
port '3306'
|
||||
data_dir '/data'
|
||||
initial_root_password 'Ch4ng3me'
|
||||
action [:create, :start]
|
||||
end
|
||||
```
|
||||
|
||||
Please note that when using `notifies` or `subscribes`, the resource
|
||||
to reference is `mysql_service[name]`, not `service[mysql]`.
|
||||
Please note that when using `notifies` or `subscribes`, the resource to reference is `mysql_service[name]`, not `service[mysql]`.
|
||||
|
||||
#### Parameters
|
||||
|
||||
- `charset` - specifies the default character set. Defaults to `utf8`.
|
||||
|
||||
- `data_dir` - determines where the actual data files are kept
|
||||
on the machine. This is useful when mounting external storage. When
|
||||
omitted, it will default to the platform's native location.
|
||||
|
||||
- `data_dir` - determines where the actual data files are kept on the machine. This is useful when mounting external storage. When omitted, it will default to the platform's native location.
|
||||
- `error_log` - Tunable location of the error_log
|
||||
|
||||
- `initial_root_password` - allows the user to specify the initial
|
||||
root password for mysql when initializing new databases.
|
||||
This can be set explicitly in a recipe, driven from a node
|
||||
attribute, or from data_bags. When omitted, it defaults to
|
||||
`ilikerandompasswords`. Please be sure to change it.
|
||||
|
||||
- `instance` - A string to identify the MySQL service. By convention,
|
||||
to allow for multiple instances of the `mysql_service`, directories
|
||||
and files on disk are named `mysql-<instance_name>`. Defaults to the
|
||||
resource name.
|
||||
|
||||
- `initial_root_password` - allows the user to specify the initial root password for mysql when initializing new databases. This can be set explicitly in a recipe, driven from a node attribute, or from data_bags. When omitted, it defaults to `ilikerandompasswords`. Please be sure to change it.
|
||||
- `instance` - A string to identify the MySQL service. By convention, to allow for multiple instances of the `mysql_service`, directories and files on disk are named `mysql-<instance_name>`. Defaults to the resource name.
|
||||
- `package_action` - Defaults to `:install`.
|
||||
|
||||
- `package_name` - Defaults to a value looked up in an internal map.
|
||||
|
||||
- `package_version` - Specific version of the package to install,
|
||||
passed onto the underlying package manager. Defaults to `nil`.
|
||||
|
||||
- `bind_address` - determines the listen IP address for the mysqld service. When
|
||||
omitted, it will be determined by MySQL. If the address is "regular" IPv4/IPv6
|
||||
address (e.g 127.0.0.1 or ::1), the server accepts TCP/IP connections only for
|
||||
that particular address. If the address is "0.0.0.0" (IPv4) or "::" (IPv6), the
|
||||
server accepts TCP/IP connections on all IPv4 or IPv6 interfaces.
|
||||
|
||||
- `mysqld_options` - A key value hash of options to be rendered into
|
||||
the main my.cnf. WARNING - It is highly recommended that you use the
|
||||
`mysql_config` resource instead of sending extra config into a
|
||||
`mysql_service` resource. This will allow you to set up
|
||||
notifications and subscriptions between the service and its
|
||||
configuration. That being said, this can be useful for adding extra
|
||||
options needed for database initialization at first run.
|
||||
|
||||
- `port` - determines the listen port for the mysqld service. When
|
||||
omitted, it will default to '3306'.
|
||||
|
||||
- `run_group` - The name of the system group the `mysql_service`
|
||||
should run as. Defaults to 'mysql'.
|
||||
|
||||
- `run_user` - The name of the system user the `mysql_service` should
|
||||
run as. Defaults to 'mysql'.
|
||||
|
||||
- `package_version` - Specific version of the package to install,passed onto the underlying package manager. Defaults to `nil`.
|
||||
- `bind_address` - determines the listen IP address for the mysqld service. When omitted, it will be determined by MySQL. If the address is "regular" IPv4/IPv6address (e.g 127.0.0.1 or ::1), the server accepts TCP/IP connections only for that particular address. If the address is "0.0.0.0" (IPv4) or "::" (IPv6), the server accepts TCP/IP connections on all IPv4 or IPv6 interfaces.
|
||||
- `mysqld_options` - A key value hash of options to be rendered into the main my.cnf. WARNING - It is highly recommended that you use the `mysql_config` resource instead of sending extra config into a `mysql_service` resource. This will allow you to set up notifications and subscriptions between the service and its configuration. That being said, this can be useful for adding extra options needed for database initialization at first run.
|
||||
- `port` - determines the listen port for the mysqld service. When omitted, it will default to '3306'.
|
||||
- `run_group` - The name of the system group the `mysql_service` should run as. Defaults to 'mysql'.
|
||||
- `run_user` - The name of the system user the `mysql_service` should run as. Defaults to 'mysql'.
|
||||
- `pid_file` - Tunable location of the pid file.
|
||||
|
||||
- `socket` - determines where to write the socket file for the
|
||||
`mysql_service` instance. Useful when configuring clients on the
|
||||
same machine to talk over socket and skip the networking stack.
|
||||
Defaults to a calculated value based on platform and instance name.
|
||||
|
||||
- `socket` - determines where to write the socket file for the `mysql_service` instance. Useful when configuring clients on the same machine to talk over socket and skip the networking stack. Defaults to a calculated value based on platform and instance name.
|
||||
- `tmp_dir` - Tunable location of the tmp_dir
|
||||
|
||||
- `version` - allows the user to select from the versions available
|
||||
for the platform, where applicable. When omitted, it will install
|
||||
the default MySQL version for the target platform. Available version
|
||||
numbers are `5.0`, `5.1`, `5.5`, `5.6`, and `5.7`, depending on platform.
|
||||
- `version` - allows the user to select from the versions available for the platform, where applicable. When omitted, it will install the default MySQL version for the target platform. Available version numbers are `5.0`, `5.1`, `5.5`, `5.6`, and `5.7`, depending on platform.
|
||||
|
||||
#### Actions
|
||||
|
||||
@ -264,8 +185,8 @@ omitted, it will default to the platform's native location.
|
||||
- `:reload` - Reloads the underlying operating system service
|
||||
|
||||
#### Providers
|
||||
Chef selects the appropriate provider based on platform and version,
|
||||
but you can specify one if your platform support it.
|
||||
|
||||
Chef selects the appropriate provider based on platform and version, but you can specify one if your platform support it.
|
||||
|
||||
```ruby
|
||||
mysql_service[instance-1] do
|
||||
@ -276,31 +197,15 @@ mysql_service[instance-1] do
|
||||
end
|
||||
```
|
||||
|
||||
- `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::MysqlServiceSmf` - Starts a `mysql_service` using
|
||||
the Service Management Facility, used by Solaris and IllumOS. Manages
|
||||
the FMRI and method script.
|
||||
|
||||
- `Chef::Provider::MysqlServiceSystemd` - Starts a `mysql_service`
|
||||
using SystemD. Manages the unit file and activation state
|
||||
|
||||
- `Chef::Provider::MysqlServiceSysvinit` - Starts a `mysql_service`
|
||||
using SysVinit. Manages the init script and status.
|
||||
|
||||
- `Chef::Provider::MysqlServiceUpstart` - Starts a `mysql_service`
|
||||
using Upstart. Manages job definitions and status.
|
||||
- `Chef::Provider::MysqlServiceBase` - Configures everything needed to run a MySQL service except the platform service facility. This provider should never be used directly. The `:start`, `:stop`, `:restart`, and `:reload` actions are stubs meant to be overridden by the providers below.
|
||||
- `Chef::Provider::MysqlServiceSmf` - Starts a `mysql_service` using the Service Management Facility, used by Solaris and Illumos. Manages the FMRI and method script.
|
||||
- `Chef::Provider::MysqlServiceSystemd` - Starts a `mysql_service` using SystemD. Manages the unit file and activation state
|
||||
- `Chef::Provider::MysqlServiceSysvinit` - Starts a `mysql_service` using SysVinit. Manages the init script and status.
|
||||
- `Chef::Provider::MysqlServiceUpstart` - Starts a `mysql_service` using Upstart. Manages job definitions and status.
|
||||
|
||||
### mysql_config
|
||||
|
||||
The `mysql_config` resource is a wrapper around the core Chef
|
||||
`template` resource. Instead of a `path` parameter, it uses the
|
||||
`instance` parameter to calculate the path on the filesystem where
|
||||
file is rendered.
|
||||
The `mysql_config` resource is a wrapper around the core Chef `template` resource. Instead of a `path` parameter, it uses the `instance` parameter to calculate the path on the filesystem where file is rendered.
|
||||
|
||||
#### Example
|
||||
|
||||
@ -313,38 +218,22 @@ end
|
||||
|
||||
#### Parameters
|
||||
|
||||
- `config_name` - The base name of the configuration file to be
|
||||
rendered into the conf.d directory on disk. Defaults to the resource
|
||||
name.
|
||||
|
||||
- `cookbook` - The name of the cookbook to look for the template
|
||||
source. Defaults to nil
|
||||
|
||||
- `config_name` - The base name of the configuration file to be rendered into the conf.d directory on disk. Defaults to the resource name.
|
||||
- `cookbook` - The name of the cookbook to look for the template source. Defaults to nil
|
||||
- `group` - System group for file ownership. Defaults to 'mysql'.
|
||||
|
||||
- `instance` - Name of the `mysql_service` instance the config is
|
||||
meant for. Defaults to 'default'.
|
||||
|
||||
- `instance` - Name of the `mysql_service` instance the config is meant for. Defaults to 'default'.
|
||||
- `owner` - System user for file ownership. Defaults to 'mysql'.
|
||||
|
||||
- `source` - Template in cookbook to be rendered.
|
||||
|
||||
- `variables` - Variables to be passed to the underlying `template`
|
||||
resource.
|
||||
|
||||
- `version` - Version of the `mysql_service` instance the config is
|
||||
meant for. Used to calculate path. Only necessary when using
|
||||
packages with unique configuration paths, such as RHEL Software
|
||||
Collections or OmniOS. Defaults to 'nil'
|
||||
- `variables` - Variables to be passed to the underlying `template` resource.
|
||||
- `version` - Version of the `mysql_service` instance the config is meant for. Used to calculate path. Only necessary when using packages with unique configuration paths, such as RHEL Software Collections or OmniOS. Defaults to 'nil'
|
||||
|
||||
#### Actions
|
||||
- `:create` - Renders the template to disk at a path calculated using
|
||||
the instance parameter.
|
||||
|
||||
- `:delete` - Deletes the file from the conf.d directory calculated
|
||||
using the instance parameter.
|
||||
|
||||
- `:create` - Renders the template to disk at a path calculated using the instance parameter.
|
||||
- `:delete` - Deletes the file from the conf.d directory calculated using the instance parameter.
|
||||
|
||||
#### More Examples
|
||||
|
||||
```ruby
|
||||
mysql_service 'instance-1' do
|
||||
action [:create, :start]
|
||||
@ -372,15 +261,13 @@ end
|
||||
```
|
||||
|
||||
### mysql_client
|
||||
The `mysql_client` resource manages the MySQL client binaries and
|
||||
development libraries.
|
||||
|
||||
It is an example of a "singleton" resource. Declaring two
|
||||
`mysql_client` resources on a machine usually won't yield two separate
|
||||
copies of the client binaries, except for platforms that support
|
||||
multiple versions (RHEL SCL, OmniOS).
|
||||
The `mysql_client` resource manages the MySQL client binaries and development libraries.
|
||||
|
||||
It is an example of a "singleton" resource. Declaring two `mysql_client` resources on a machine usually won't yield two separate copies of the client binaries, except for platforms that support multiple versions (RHEL SCL, OmniOS).
|
||||
|
||||
#### Example
|
||||
|
||||
```ruby
|
||||
mysql_client 'default' do
|
||||
action :create
|
||||
@ -388,26 +275,19 @@ end
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
- `package_name` - An array of packages to be installed. Defaults to a
|
||||
value looked up in an internal map.
|
||||
|
||||
- `package_version` - Specific versions of the package to install,
|
||||
passed onto the underlying package manager. Defaults to `nil`.
|
||||
- `package_name` - An array of packages to be installed. Defaults to a value looked up in an internal map.
|
||||
- `package_version` - Specific versions of the package to install, passed onto the underlying package manager. Defaults to `nil`.
|
||||
- `version` - Major MySQL version number of client packages. Only valid on for platforms that support multiple versions, such as RHEL via Software Collections and OmniOS.
|
||||
|
||||
- `version` - Major MySQL version number of client packages. Only
|
||||
valid on for platforms that support multiple versions, such as RHEL
|
||||
via Software Collections and OmniOS.
|
||||
|
||||
#### Actions
|
||||
|
||||
- `:create` - Installs the client software
|
||||
- `:delete` - Removes the client software
|
||||
|
||||
Advanced Usage Examples
|
||||
-----------------------
|
||||
There are a number of configuration scenarios supported by the use of
|
||||
resource primitives in recipes. For example, you might want to run
|
||||
multiple MySQL services, as different users, and mount block devices
|
||||
that contain pre-existing databases.
|
||||
## Advanced Usage Examples
|
||||
|
||||
There are a number of configuration scenarios supported by the use of resource primitives in recipes. For example, you might want to run multiple MySQL services, as different users, and mount block devices that contain pre-existing databases.
|
||||
|
||||
### Multiple Instances as Different Users
|
||||
|
||||
@ -472,92 +352,77 @@ end
|
||||
```
|
||||
|
||||
### Replication Testing
|
||||
Use multiple `mysql_service` instances to test a replication setup.
|
||||
This particular example serves as a smoke test in Test Kitchen because
|
||||
it exercises different resources and requires service restarts.
|
||||
|
||||
https://github.com/chef-cookbooks/mysql/blob/master/test/fixtures/cookbooks/mysql_replication_test/recipes/default.rb
|
||||
Use multiple `mysql_service` instances to test a replication setup. This particular example serves as a smoke test in Test Kitchen because it exercises different resources and requires service restarts.
|
||||
|
||||
Frequently Asked Questions
|
||||
--------------------------
|
||||
<https://github.com/chef-cookbooks/mysql/blob/master/test/fixtures/cookbooks/mysql_replication_test/recipes/default.rb>
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
### How do I run this behind my firewall?
|
||||
|
||||
On Linux, the `mysql_service` resource uses the platform's underlying
|
||||
package manager to install software. For this to work behind
|
||||
firewalls, you'll need to either:
|
||||
On Linux, the `mysql_service` resource uses the platform's underlying package manager to install software. For this to work behind firewalls, you'll need to either:
|
||||
|
||||
- Configure the system yum/apt utilities to use a proxy server that
|
||||
can reach the Internet
|
||||
- can reach the Internet
|
||||
- Host a package repository on a network that the machine can talk to
|
||||
|
||||
On the RHEL platform_family, applying the `yum::default` recipe will
|
||||
allow you to drive the `yum_globalconfig` resource with attributes to
|
||||
change the global yum proxy settings.
|
||||
On the RHEL platform_family, applying the `yum::default` recipe will allow you to drive the `yum_globalconfig` resource with attributes to change the global yum proxy settings.
|
||||
|
||||
If hosting repository mirrors, applying one of the following recipes
|
||||
and adjust the settings with node attributes.
|
||||
If hosting repository mirrors, applying one of the following recipes and adjust the settings with node attributes.
|
||||
|
||||
- `recipe[yum-centos::default]` from the Supermarket
|
||||
https://supermarket.chef.io/cookbooks/yum-centos
|
||||
https://github.com/chef-cookbooks/yum-centos
|
||||
|
||||
|
||||
<https://supermarket.chef.io/cookbooks/yum-centos>
|
||||
|
||||
<https://github.com/chef-cookbooks/yum-centos>
|
||||
|
||||
- `recipe[yum-mysql-community::default]` from the Supermarket
|
||||
https://supermarket.chef.io/cookbooks/yum-mysql-community
|
||||
https://github.com/chef-cookbooks/yum-mysql-community
|
||||
|
||||
|
||||
<https://supermarket.chef.io/cookbooks/yum-mysql-community>
|
||||
|
||||
<https://github.com/chef-cookbooks/yum-mysql-community>
|
||||
|
||||
### The mysql command line doesn't work
|
||||
|
||||
If you log into the machine and type `mysql`, you may see an error
|
||||
like this one:
|
||||
If you log into the machine and type `mysql`, you may see an error like this one:
|
||||
|
||||
`Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock'`
|
||||
|
||||
This is because MySQL is hardcoded to read the defined default my.cnf
|
||||
file, typically at /etc/my.cnf, and this LWRP deletes it to prevent
|
||||
overlap among multiple MySQL configurations.
|
||||
This is because MySQL is hardcoded to read the defined default my.cnf file, typically at /etc/my.cnf, and this LWRP deletes it to prevent overlap among multiple MySQL configurations.
|
||||
|
||||
To connect to the socket from the command line, check the socket in the relevant my.cnf file and use something like this:
|
||||
|
||||
`mysql -S /var/run/mysql-foo/mysqld.sock -Pwhatever`
|
||||
|
||||
Or to connect over the network, use something like this:
|
||||
connect over the network..
|
||||
Or to connect over the network, use something like this: connect over the network..
|
||||
|
||||
`mysql -h 127.0.0.1 -Pwhatever`
|
||||
|
||||
These network or socket ssettings can also be put in you
|
||||
$HOME/.my.cnf, if preferred.
|
||||
These network or socket ssettings can also be put in you $HOME/.my.cnf, if preferred.
|
||||
|
||||
### What about MariaDB, Percona, Drizzle, WebScaleSQL, etc.
|
||||
|
||||
MySQL forks are purposefully out of scope for this cookbook. This is
|
||||
mostly to reduce the testing matrix to a manageable size. Cookbooks
|
||||
for these technologies can easily be created by copying and adapting
|
||||
this cookbook. However, there will be differences.
|
||||
MySQL forks are purposefully out of scope for this cookbook. This is mostly to reduce the testing matrix to a manageable size. Cookbooks for these technologies can easily be created by copying and adapting this cookbook. However, there will be differences.
|
||||
|
||||
Package repository locations, package version names, software major
|
||||
version numbers, supported platform matrices, and the availability of
|
||||
software such as XtraDB and Galera are the main reasons that creating
|
||||
multiple cookbooks to make sense.
|
||||
Package repository locations, package version names, software major version numbers, supported platform matrices, and the availability of software such as XtraDB and Galera are the main reasons that creating multiple cookbooks to make sense.
|
||||
|
||||
Warnings
|
||||
--------
|
||||
## Warnings
|
||||
|
||||
## Hacking / Testing / TODO
|
||||
|
||||
Hacking / Testing / TODO
|
||||
-------------------------
|
||||
Please refer to the HACKING.md
|
||||
|
||||
License & Authors
|
||||
-----------------
|
||||
- Author:: Joshua Timberman (<joshua@chef.io>)
|
||||
- Author:: AJ Christensen (<aj@chef.io>)
|
||||
- Author:: Seth Chisamore (<schisamo@chef.io>)
|
||||
- Author:: Brian Bianco (<brian.bianco@gmail.com>)
|
||||
- Author:: Jesse Howarth (<him@jessehowarth.com>)
|
||||
- Author:: Andrew Crump (<andrew@kotirisoftware.com>)
|
||||
- Author:: Christoph Hartmann (<chris@lollyrock.com>)
|
||||
- Author:: Sean OMeara (<sean@chef.io>)
|
||||
## License & Authors
|
||||
|
||||
- Author:: Joshua Timberman ([joshua@chef.io](mailto:joshua@chef.io))
|
||||
- Author:: AJ Christensen ([aj@chef.io](mailto:aj@chef.io))
|
||||
- Author:: Seth Chisamore ([schisamo@chef.io](mailto:schisamo@chef.io))
|
||||
- Author:: Brian Bianco ([brian.bianco@gmail.com](mailto:brian.bianco@gmail.com))
|
||||
- Author:: Jesse Howarth ([him@jessehowarth.com](mailto:him@jessehowarth.com))
|
||||
- Author:: Andrew Crump ([andrew@kotirisoftware.com](mailto:andrew@kotirisoftware.com))
|
||||
- Author:: Christoph Hartmann ([chris@lollyrock.com](mailto:chris@lollyrock.com))
|
||||
- Author:: Sean OMeara ([sean@chef.io](mailto:sean@chef.io))
|
||||
|
||||
```text
|
||||
Copyright:: 2009-2014 Chef Software, Inc
|
||||
|
@ -280,6 +280,8 @@ EOSQL
|
||||
@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']['15.10']['5.6']['client_package'] = %w(mysql-client-5.6 libmysqlclient-dev)
|
||||
@pkginfo.set['debian']['15.10']['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)
|
||||
@ -336,6 +338,14 @@ EOSQL
|
||||
@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']['2016.03']['5.1']['server_package'] = %w(mysql51 mysql51-devel)
|
||||
@pkginfo.set['rhel']['2016.03']['5.1']['server_package'] = 'mysql51-server'
|
||||
@pkginfo.set['rhel']['2016.03']['5.5']['client_package'] = %w(mysql-community-client mysql-community-devel)
|
||||
@pkginfo.set['rhel']['2016.03']['5.5']['server_package'] = 'mysql-community-server'
|
||||
@pkginfo.set['rhel']['2016.03']['5.6']['client_package'] = %w(mysql-community-client mysql-community-devel)
|
||||
@pkginfo.set['rhel']['2016.03']['5.6']['server_package'] = 'mysql-community-server'
|
||||
@pkginfo.set['rhel']['2016.03']['5.7']['client_package'] = %w(mysql-community-client mysql-community-devel)
|
||||
@pkginfo.set['rhel']['2016.03']['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)
|
||||
@ -382,7 +392,7 @@ EOSQL
|
||||
Chef::Log.error("Unsupported Version: You requested to install a Mysql #{type_label} version that is not supported by your platform")
|
||||
Chef::Log.error("Platform: #{platform_family} #{platform_version} - Request Mysql #{type_label} version: #{version}")
|
||||
Chef::Log.error("Availabe versions for your platform are: #{info.map { |k, _v| k }.join(' - ')}")
|
||||
fail "Unsupported Mysql #{type_label} Version"
|
||||
raise "Unsupported Mysql #{type_label} Version"
|
||||
end
|
||||
info[version][type]
|
||||
end
|
||||
@ -454,6 +464,7 @@ EOSQL
|
||||
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'
|
||||
return '5.6' if node['platform_family'] == 'debian' && node['platform_version'] == '15.10'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -3,7 +3,7 @@ class Chef
|
||||
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)
|
||||
if defined?(provides) # foodcritic ~FC023
|
||||
provides :mysql_service, os: %w(solaris2 omnios smartos openindiana opensolaris nexentacore) do
|
||||
File.exist?('/usr/sbin/svccfg')
|
||||
end
|
||||
|
@ -3,7 +3,7 @@ require_relative 'provider_mysql_service_base'
|
||||
class Chef
|
||||
class Provider
|
||||
class MysqlServiceSystemd < Chef::Provider::MysqlServiceBase
|
||||
if defined?(provides)
|
||||
if defined?(provides) # foodcritic ~FC023
|
||||
provides :mysql_service, os: 'linux' do
|
||||
Chef::Platform::ServiceHelpers.service_resource_providers.include?(:systemd)
|
||||
end
|
||||
|
@ -3,7 +3,7 @@ require_relative 'provider_mysql_service_base'
|
||||
class Chef
|
||||
class Provider
|
||||
class MysqlServiceUpstart < Chef::Provider::MysqlServiceBase
|
||||
if defined?(provides)
|
||||
if defined?(provides) # foodcritic ~FC023
|
||||
provides :mysql_service, os: 'linux' do
|
||||
Chef::Platform::ServiceHelpers.service_resource_providers.include?(:upstart) &&
|
||||
!Chef::Platform::ServiceHelpers.service_resource_providers.include?(:redhat)
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
begin
|
||||
require 'chef/platform/provider_priority_map'
|
||||
rescue LoadError
|
||||
rescue LoadError # rubocop: disable Lint/HandleExceptions
|
||||
end
|
||||
|
||||
require_relative 'provider_mysql_service_smf'
|
||||
|
File diff suppressed because one or more lines are too long
21
cookbooks/php-fpm/.kitchen.yml
Normal file
21
cookbooks/php-fpm/.kitchen.yml
Normal file
@ -0,0 +1,21 @@
|
||||
---
|
||||
driver:
|
||||
name: vagrant
|
||||
|
||||
provisioner:
|
||||
name: chef_solo
|
||||
|
||||
platforms:
|
||||
- name: ubuntu-12.04
|
||||
- name: centos-6.4
|
||||
- name: fedora-21
|
||||
|
||||
suites:
|
||||
- name: default
|
||||
run_list:
|
||||
- recipe[php-fpm::default]
|
||||
attributes:
|
||||
php-fpm:
|
||||
pools:
|
||||
- name: web
|
||||
listen: '127.0.0.1:9081'
|
1
cookbooks/php-fpm/.ruby-version
Normal file
1
cookbooks/php-fpm/.ruby-version
Normal file
@ -0,0 +1 @@
|
||||
1.9.3-p327
|
3
cookbooks/php-fpm/Berksfile
Normal file
3
cookbooks/php-fpm/Berksfile
Normal file
@ -0,0 +1,3 @@
|
||||
source "https://supermarket.getchef.com"
|
||||
|
||||
metadata
|
20
cookbooks/php-fpm/Gemfile
Normal file
20
cookbooks/php-fpm/Gemfile
Normal file
@ -0,0 +1,20 @@
|
||||
source 'https://rubygems.org'
|
||||
|
||||
gem 'berkshelf'
|
||||
|
||||
# Uncomment these lines if you want to live on the Edge:
|
||||
#
|
||||
# group :development do
|
||||
# gem "berkshelf", github: "berkshelf/berkshelf"
|
||||
# gem "vagrant", github: "mitchellh/vagrant", tag: "v1.6.3"
|
||||
# end
|
||||
#
|
||||
# group :plugins do
|
||||
# gem "vagrant-berkshelf", github: "berkshelf/vagrant-berkshelf"
|
||||
# gem "vagrant-omnibus", github: "schisamo/vagrant-omnibus"
|
||||
# end
|
||||
|
||||
gem 'test-kitchen'
|
||||
gem 'kitchen-vagrant'
|
||||
gem 'stove'
|
||||
gem 'serverspec'
|
179
cookbooks/php-fpm/Gemfile.lock
Normal file
179
cookbooks/php-fpm/Gemfile.lock
Normal file
@ -0,0 +1,179 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activesupport (3.2.19)
|
||||
i18n (~> 0.6, >= 0.6.4)
|
||||
multi_json (~> 1.0)
|
||||
addressable (2.3.6)
|
||||
akami (1.2.2)
|
||||
gyoku (>= 0.4.0)
|
||||
nokogiri
|
||||
berkshelf (2.0.18)
|
||||
activesupport (~> 3.2.0)
|
||||
addressable (~> 2.3.4)
|
||||
buff-shell_out (~> 0.1)
|
||||
chozo (>= 0.6.1)
|
||||
faraday (~> 0.8.5)
|
||||
hashie (~> 2.0)
|
||||
minitar (~> 0.5.4)
|
||||
rbzip2 (~> 0.2.0)
|
||||
retryable (~> 1.3.3)
|
||||
ridley (~> 1.7.0)
|
||||
solve (~> 0.8.2)
|
||||
thor (~> 0.18.0)
|
||||
buff-config (0.4.0)
|
||||
buff-extensions (~> 0.3)
|
||||
varia_model (~> 0.1)
|
||||
buff-extensions (0.5.0)
|
||||
buff-ignore (1.1.1)
|
||||
buff-ruby_engine (0.1.0)
|
||||
buff-shell_out (0.2.0)
|
||||
buff-ruby_engine (~> 0.1.0)
|
||||
builder (3.2.2)
|
||||
celluloid (0.16.0)
|
||||
timers (~> 4.0.0)
|
||||
celluloid-io (0.16.1)
|
||||
celluloid (>= 0.16.0)
|
||||
nio4r (>= 1.0.0)
|
||||
chef-api (0.5.0)
|
||||
logify (~> 0.1)
|
||||
mime-types
|
||||
chozo (0.6.1)
|
||||
activesupport (>= 3.2.0)
|
||||
hashie (>= 2.0.2)
|
||||
multi_json (>= 1.3.0)
|
||||
diff-lcs (1.2.5)
|
||||
erubis (2.7.0)
|
||||
faraday (0.8.9)
|
||||
multipart-post (~> 1.2.0)
|
||||
ffi (1.9.6)
|
||||
gssapi (1.0.3)
|
||||
ffi (>= 1.0.1)
|
||||
gyoku (1.2.2)
|
||||
builder (>= 2.1.2)
|
||||
hashie (2.1.2)
|
||||
hitimes (1.2.2)
|
||||
httpclient (2.5.1)
|
||||
httpi (0.9.7)
|
||||
rack
|
||||
i18n (0.6.11)
|
||||
json (1.8.1)
|
||||
kitchen-vagrant (0.15.0)
|
||||
test-kitchen (~> 1.0)
|
||||
little-plugger (1.1.3)
|
||||
logging (1.8.2)
|
||||
little-plugger (>= 1.1.3)
|
||||
multi_json (>= 1.8.4)
|
||||
logify (0.2.0)
|
||||
mime-types (2.4.2)
|
||||
mini_portile (0.6.0)
|
||||
minitar (0.5.4)
|
||||
mixlib-authentication (1.3.0)
|
||||
mixlib-log
|
||||
mixlib-log (1.6.0)
|
||||
mixlib-shellout (1.6.1)
|
||||
multi_json (1.10.1)
|
||||
multipart-post (1.2.0)
|
||||
net-http-persistent (2.9.4)
|
||||
net-scp (1.2.1)
|
||||
net-ssh (>= 2.6.5)
|
||||
net-ssh (2.9.1)
|
||||
nio4r (1.0.1)
|
||||
nokogiri (1.6.3.1)
|
||||
mini_portile (= 0.6.0)
|
||||
nori (1.1.5)
|
||||
rack (1.5.2)
|
||||
rbzip2 (0.2.0)
|
||||
retryable (1.3.6)
|
||||
ridley (1.7.1)
|
||||
addressable
|
||||
buff-config (~> 0.2)
|
||||
buff-extensions (~> 0.3)
|
||||
buff-ignore (~> 1.1)
|
||||
buff-shell_out (~> 0.1)
|
||||
celluloid (~> 0.15)
|
||||
celluloid-io (~> 0.15)
|
||||
erubis
|
||||
faraday (>= 0.8.4)
|
||||
hashie (>= 2.0.2)
|
||||
json (>= 1.7.7)
|
||||
mixlib-authentication (>= 1.3.0)
|
||||
net-http-persistent (>= 2.8)
|
||||
net-ssh
|
||||
retryable
|
||||
solve (>= 0.4.4)
|
||||
varia_model (~> 0.1)
|
||||
winrm (~> 1.1.0)
|
||||
rspec (3.1.0)
|
||||
rspec-core (~> 3.1.0)
|
||||
rspec-expectations (~> 3.1.0)
|
||||
rspec-mocks (~> 3.1.0)
|
||||
rspec-core (3.1.7)
|
||||
rspec-support (~> 3.1.0)
|
||||
rspec-expectations (3.1.2)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.1.0)
|
||||
rspec-its (1.0.1)
|
||||
rspec-core (>= 2.99.0.beta1)
|
||||
rspec-expectations (>= 2.99.0.beta1)
|
||||
rspec-mocks (3.1.3)
|
||||
rspec-support (~> 3.1.0)
|
||||
rspec-support (3.1.2)
|
||||
rubyntlm (0.1.1)
|
||||
safe_yaml (1.0.4)
|
||||
savon (0.9.5)
|
||||
akami (~> 1.0)
|
||||
builder (>= 2.1.2)
|
||||
gyoku (>= 0.4.0)
|
||||
httpi (~> 0.9)
|
||||
nokogiri (>= 1.4.0)
|
||||
nori (~> 1.0)
|
||||
wasabi (~> 1.0)
|
||||
serverspec (2.3.1)
|
||||
multi_json
|
||||
rspec (~> 3.0)
|
||||
rspec-its
|
||||
specinfra (~> 2.3)
|
||||
solve (0.8.2)
|
||||
specinfra (2.3.0)
|
||||
net-scp
|
||||
net-ssh
|
||||
stove (3.2.3)
|
||||
chef-api (~> 0.5)
|
||||
logify (~> 0.2)
|
||||
test-kitchen (1.2.1)
|
||||
mixlib-shellout (~> 1.2)
|
||||
net-scp (~> 1.1)
|
||||
net-ssh (~> 2.7)
|
||||
safe_yaml (~> 1.0)
|
||||
thor (~> 0.18)
|
||||
thor (0.18.1)
|
||||
timers (4.0.1)
|
||||
hitimes
|
||||
uuidtools (2.1.5)
|
||||
varia_model (0.3.2)
|
||||
buff-extensions (~> 0.2)
|
||||
hashie (>= 2.0.2)
|
||||
wasabi (1.0.0)
|
||||
nokogiri (>= 1.4.0)
|
||||
winrm (1.1.3)
|
||||
gssapi (~> 1.0.0)
|
||||
httpclient (~> 2.2, >= 2.2.0.2)
|
||||
logging (~> 1.6, >= 1.6.1)
|
||||
nokogiri (~> 1.5)
|
||||
rubyntlm (~> 0.1.1)
|
||||
savon (= 0.9.5)
|
||||
uuidtools (~> 2.1.2)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
berkshelf
|
||||
kitchen-vagrant
|
||||
serverspec
|
||||
stove
|
||||
test-kitchen
|
||||
|
||||
BUNDLED WITH
|
||||
1.10.3
|
@ -24,7 +24,7 @@ The `apt_repository` and `yum_repository` LWRPs are used from these cookbooks to
|
||||
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).
|
||||
Creates a PHP-FPM configuration file at the path specified. Meant to be deployed with a service init scheme/supervisor such as runit. Please see the `application::php-fpm` recipe for a complete working example. In depth information about PHP-FPM's configuration values can be [found in the PHP-FPM documentation](http://php.net/manual/en/install.fpm.configuration.php).
|
||||
|
||||
Usage
|
||||
=====
|
||||
@ -38,18 +38,18 @@ name "php-fpm"
|
||||
description "php fpm role"
|
||||
run_list "recipe[php-fpm]"
|
||||
override_attributes "php-fpm" => {
|
||||
"pools" => [
|
||||
{
|
||||
:name => "default"
|
||||
"pools" => {
|
||||
"default" => {
|
||||
:enable => true
|
||||
},
|
||||
{
|
||||
:name => "www",
|
||||
"www" => {
|
||||
:enable => "true",
|
||||
:cookbook => "another-cookbook",
|
||||
:process_manager => "dynamic",
|
||||
:max_requests => 5000,
|
||||
:php_options => { 'php_admin_flag[log_errors]' => 'on', 'php_admin_value[memory_limit]' => '32M' }
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
13
cookbooks/php-fpm/Rakefile
Normal file
13
cookbooks/php-fpm/Rakefile
Normal file
@ -0,0 +1,13 @@
|
||||
begin
|
||||
require 'kitchen/rake_tasks'
|
||||
Kitchen::RakeTasks.new
|
||||
rescue LoadError
|
||||
puts ">>>>> Kitchen gem not loaded, omitting tasks" unless ENV['CI']
|
||||
end
|
||||
|
||||
begin
|
||||
require 'stove/rake_task'
|
||||
Stove::RakeTask.new
|
||||
rescue LoadErro
|
||||
pust ">>>>> Stove gem not loaded, omitting tasks" unless ENV['CI']
|
||||
end
|
12
cookbooks/php-fpm/Thorfile
Normal file
12
cookbooks/php-fpm/Thorfile
Normal file
@ -0,0 +1,12 @@
|
||||
# encoding: utf-8
|
||||
|
||||
require 'bundler'
|
||||
require 'bundler/setup'
|
||||
require 'berkshelf/thor'
|
||||
|
||||
begin
|
||||
require 'kitchen/thor_tasks'
|
||||
Kitchen::ThorTasks.new
|
||||
rescue LoadError
|
||||
puts ">>>>> Kitchen gem not loaded, omitting tasks" unless ENV['CI']
|
||||
end
|
90
cookbooks/php-fpm/Vagrantfile
vendored
Normal file
90
cookbooks/php-fpm/Vagrantfile
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
|
||||
VAGRANTFILE_API_VERSION = "2"
|
||||
|
||||
Vagrant.require_version ">= 1.5.0"
|
||||
|
||||
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||
# All Vagrant configuration is done here. The most common configuration
|
||||
# options are documented and commented below. For a complete reference,
|
||||
# please see the online documentation at vagrantup.com.
|
||||
|
||||
config.vm.hostname = "php-fpm-berkshelf"
|
||||
|
||||
# Set the version of chef to install using the vagrant-omnibus plugin
|
||||
config.omnibus.chef_version = :latest
|
||||
|
||||
# Every Vagrant virtual environment requires a box to build off of.
|
||||
# If this value is a shorthand to a box in Vagrant Cloud then
|
||||
# config.vm.box_url doesn't need to be specified.
|
||||
# config.vm.box = "chef/ubuntu-14.04"
|
||||
case ENV['VMBOX']
|
||||
when 'centos65'
|
||||
config.vm.box = "opscode-centos-6.5"
|
||||
config.vm.box_url = "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5_chef-provisionerless.box"
|
||||
else
|
||||
config.vm.box = "opscode-ubuntu-12.04"
|
||||
config.vm.box_url = "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-12.04_chef-provisionerless.box"
|
||||
end
|
||||
|
||||
# The url from where the 'config.vm.box' box will be fetched if it
|
||||
# is not a Vagrant Cloud box and if it doesn't already exist on the
|
||||
# user's system.
|
||||
# config.vm.box_url = "https://vagrantcloud.com/chef/ubuntu-14.04/version/1/provider/virtualbox.box"
|
||||
|
||||
# Assign this VM to a host-only network IP, allowing you to access it
|
||||
# via the IP. Host-only networks can talk to the host machine as well as
|
||||
# any other machines on the same network, but cannot be accessed (through this
|
||||
# network interface) by any external networks.
|
||||
# config.vm.network :private_network, type: "dhcp"
|
||||
config.vm.network :private_network, ip: "33.33.33.10"
|
||||
|
||||
# Create a forwarded port mapping which allows access to a specific port
|
||||
# within the machine from a port on the host machine. In the example below,
|
||||
# accessing "localhost:8080" will access port 80 on the guest machine.
|
||||
|
||||
# Share an additional folder to the guest VM. The first argument is
|
||||
# the path on the host to the actual folder. The second argument is
|
||||
# the path on the guest to mount the folder. And the optional third
|
||||
# argument is a set of non-required options.
|
||||
# config.vm.synced_folder "../data", "/vagrant_data"
|
||||
|
||||
# Provider-specific configuration so you can fine-tune various
|
||||
# backing providers for Vagrant. These expose provider-specific options.
|
||||
# Example for VirtualBox:
|
||||
#
|
||||
# config.vm.provider :virtualbox do |vb|
|
||||
# # Don't boot with headless mode
|
||||
# vb.gui = true
|
||||
#
|
||||
# # Use VBoxManage to customize the VM. For example to change memory:
|
||||
# vb.customize ["modifyvm", :id, "--memory", "1024"]
|
||||
# end
|
||||
#
|
||||
# View the documentation for the provider you're using for more
|
||||
# information on available options.
|
||||
|
||||
# The path to the Berksfile to use with Vagrant Berkshelf
|
||||
# config.berkshelf.berksfile_path = "./Berksfile"
|
||||
|
||||
# Enabling the Berkshelf plugin. To enable this globally, add this configuration
|
||||
# option to your ~/.vagrant.d/Vagrantfile file
|
||||
config.berkshelf.enabled = true
|
||||
|
||||
# An array of symbols representing groups of cookbook described in the Vagrantfile
|
||||
# to exclusively install and copy to Vagrant's shelf.
|
||||
# config.berkshelf.only = []
|
||||
|
||||
# An array of symbols representing groups of cookbook described in the Vagrantfile
|
||||
# to skip installing and copying to Vagrant's shelf.
|
||||
# config.berkshelf.except = []
|
||||
|
||||
config.vm.provision :chef_solo do |chef|
|
||||
chef.run_list = [
|
||||
"recipe[apt]",
|
||||
"recipe[php-fpm::default]"
|
||||
]
|
||||
end
|
||||
end
|
@ -1,4 +1,5 @@
|
||||
if node.platform_family == "rhel"
|
||||
case node["platform_family"]
|
||||
when "rhel", "fedora"
|
||||
user = "apache"
|
||||
group = "apache"
|
||||
conf_dir = "/etc/php.d"
|
||||
@ -26,18 +27,30 @@ default['php-fpm']['conf_dir'] = conf_dir
|
||||
default['php-fpm']['pool_conf_dir'] = pool_conf_dir
|
||||
default['php-fpm']['conf_file'] = conf_file
|
||||
default['php-fpm']['pid'] = pid
|
||||
default['php-fpm']['log_dir'] = '/var/log/php-fpm'
|
||||
default['php-fpm']['error_log'] = error_log
|
||||
default['php-fpm']['log_level'] = "notice"
|
||||
default['php-fpm']['emergency_restart_threshold'] = 0
|
||||
default['php-fpm']['emergency_restart_interval'] = 0
|
||||
default['php-fpm']['process_control_timeout'] = 0
|
||||
default['php-fpm']['pools'] = [
|
||||
{
|
||||
:name => "www"
|
||||
default['php-fpm']['pools'] = {
|
||||
"www" => {
|
||||
:enable => true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
default['php-fpm']['skip_repository_install'] = false
|
||||
default['php-fpm']['installation_action'] = :install
|
||||
default['php-fpm']['version'] = nil
|
||||
|
||||
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"
|
||||
case node["platform_family"]
|
||||
when "rhel"
|
||||
default['php-fpm']['yum_url'] = "http://rpms.famillecollet.com/enterprise/$releasever/remi/$basearch/"
|
||||
default['php-fpm']['yum_mirrorlist'] = "http://rpms.famillecollet.com/enterprise/$releasever/remi/mirror"
|
||||
when "fedora"
|
||||
default['php-fpm']['skip_repository_install'] = true
|
||||
end
|
||||
|
||||
default['php-fpm']['dotdeb_repository']['uri'] = "http://packages.dotdeb.org"
|
||||
default['php-fpm']['dotdeb_repository']['key'] = "http://www.dotdeb.org/dotdeb.gpg"
|
||||
default['php-fpm']['dotdeb-php53_repository']['uri'] = "http://php53.dotdeb.org"
|
||||
|
101
cookbooks/php-fpm/chefignore
Normal file
101
cookbooks/php-fpm/chefignore
Normal file
@ -0,0 +1,101 @@
|
||||
# Put files/directories that should be ignored in this file when uploading
|
||||
# or sharing to the community site.
|
||||
# Lines that start with '# ' are comments.
|
||||
|
||||
# OS generated files #
|
||||
######################
|
||||
.DS_Store
|
||||
Icon?
|
||||
nohup.out
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
# SASS #
|
||||
########
|
||||
.sass-cache
|
||||
|
||||
# EDITORS #
|
||||
###########
|
||||
\#*
|
||||
.#*
|
||||
*~
|
||||
*.sw[a-z]
|
||||
*.bak
|
||||
REVISION
|
||||
TAGS*
|
||||
tmtags
|
||||
*_flymake.*
|
||||
*_flymake
|
||||
*.tmproj
|
||||
.project
|
||||
.settings
|
||||
mkmf.log
|
||||
|
||||
## COMPILED ##
|
||||
##############
|
||||
a.out
|
||||
*.o
|
||||
*.pyc
|
||||
*.so
|
||||
*.com
|
||||
*.class
|
||||
*.dll
|
||||
*.exe
|
||||
*/rdoc/
|
||||
|
||||
# Testing #
|
||||
###########
|
||||
.watchr
|
||||
.rspec
|
||||
spec/*
|
||||
spec/fixtures/*
|
||||
test/*
|
||||
features/*
|
||||
Guardfile
|
||||
Procfile
|
||||
|
||||
# SCM #
|
||||
#######
|
||||
.git
|
||||
*/.git
|
||||
.gitignore
|
||||
.gitmodules
|
||||
.gitconfig
|
||||
.gitattributes
|
||||
.svn
|
||||
*/.bzr/*
|
||||
*/.hg/*
|
||||
*/.svn/*
|
||||
|
||||
# Berkshelf #
|
||||
#############
|
||||
Berksfile
|
||||
Berksfile.lock
|
||||
cookbooks/*
|
||||
tmp
|
||||
|
||||
# Cookbooks #
|
||||
#############
|
||||
CONTRIBUTING
|
||||
CHANGELOG*
|
||||
|
||||
# Strainer #
|
||||
############
|
||||
Colanderfile
|
||||
Strainerfile
|
||||
.colander
|
||||
.strainer
|
||||
|
||||
# Vagrant #
|
||||
###########
|
||||
.vagrant
|
||||
Vagrantfile
|
||||
|
||||
# Travis #
|
||||
##########
|
||||
.travis.yml
|
||||
|
||||
# Other #
|
||||
##########
|
||||
.sandbox
|
||||
.bundle
|
@ -48,7 +48,9 @@ define :php_fpm_pool, :template => "pool.conf.erb", :enable => true do
|
||||
: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'],
|
||||
:access_log => params[:access_log] || false,
|
||||
:php_options => params[:php_options] || {},
|
||||
:request_terminate_timeout => params[:request_terminate_timeout],
|
||||
:params => params
|
||||
)
|
||||
notifies :restart, "service[php-fpm]"
|
||||
|
@ -1,37 +0,0 @@
|
||||
{
|
||||
"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 (<schisamo@opscode.com>)\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": {
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ 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"
|
||||
version "0.7.5"
|
||||
|
||||
depends "apt"
|
||||
depends "yum", ">= 3.0"
|
||||
|
@ -28,7 +28,13 @@ end
|
||||
|
||||
if node['php-fpm']['pools']
|
||||
node['php-fpm']['pools'].each do |pool|
|
||||
php_fpm_pool pool[:name] do
|
||||
if pool.is_a?(Array)
|
||||
pool_name = pool[0]
|
||||
pool = pool[1]
|
||||
else
|
||||
pool_name = pool[:name]
|
||||
end
|
||||
php_fpm_pool pool_name do
|
||||
pool.each do |k, v|
|
||||
self.params[k.to_sym] = v
|
||||
end
|
||||
|
@ -19,9 +19,10 @@
|
||||
#
|
||||
|
||||
include_recipe 'php-fpm::repository' unless node['php-fpm']['skip_repository_install']
|
||||
include_recipe 'apt::default' if node['platform_family'] == 'debian'
|
||||
|
||||
if node['php-fpm']['package_name'].nil?
|
||||
if platform_family?("rhel")
|
||||
if platform_family?("rhel", "fedora")
|
||||
php_fpm_package_name = "php-fpm"
|
||||
else
|
||||
php_fpm_package_name = "php5-fpm"
|
||||
@ -31,7 +32,8 @@ else
|
||||
end
|
||||
|
||||
package php_fpm_package_name do
|
||||
action :upgrade
|
||||
action node['php-fpm']['installation_action']
|
||||
version node['php-fpm']['version'] if node['php-fpm']['version']
|
||||
end
|
||||
|
||||
if node['php-fpm']['service_name'].nil?
|
||||
@ -40,13 +42,9 @@ 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
|
||||
directory node['php-fpm']['log_dir']
|
||||
|
||||
service "php-fpm" do
|
||||
provider service_provider if service_provider
|
||||
service_name php_fpm_service_name
|
||||
supports :start => true, :stop => true, :restart => true, :reload => true
|
||||
action [ :enable, :start ]
|
||||
|
@ -40,33 +40,33 @@ when 'debian'
|
||||
# http://www.dotdeb.org/instructions/
|
||||
if node.platform_version.to_f >= 7.0
|
||||
apt_repository "dotdeb" do
|
||||
uri "http://packages.dotdeb.org"
|
||||
uri node['php-fpm']['dotdeb_repository']['uri']
|
||||
distribution "stable"
|
||||
components ['all']
|
||||
key "http://www.dotdeb.org/dotdeb.gpg"
|
||||
key node['php-fpm']['dotdeb_repository']['key']
|
||||
action :add
|
||||
end
|
||||
elsif node.platform_version.to_f >= 6.0
|
||||
apt_repository "dotdeb" do
|
||||
uri "http://packages.dotdeb.org"
|
||||
uri node['php-fpm']['dotdeb_repository']['uri']
|
||||
distribution "squeeze"
|
||||
components ['all']
|
||||
key "http://www.dotdeb.org/dotdeb.gpg"
|
||||
key node['php-fpm']['dotdeb_repository']['key']
|
||||
action :add
|
||||
end
|
||||
else
|
||||
apt_repository "dotdeb" do
|
||||
uri "http://packages.dotdeb.org"
|
||||
uri node['php-fpm']['dotdeb_repository']['uri']
|
||||
distribution "oldstable"
|
||||
components ['all']
|
||||
key "http://www.dotdeb.org/dotdeb.gpg"
|
||||
key node['php-fpm']['dotdeb_repository']['key']
|
||||
action :add
|
||||
end
|
||||
apt_repository "dotdeb-php53" do
|
||||
uri "http://php53.dotdeb.org"
|
||||
uri node['php-fpm']['dotdeb-php53_repository']['uri']
|
||||
distribution "oldstable"
|
||||
components ['all']
|
||||
key "http://www.dotdeb.org/dotdeb.gpg"
|
||||
key node['php-fpm']['dotdeb_repository']['key']
|
||||
action :add
|
||||
end
|
||||
end
|
||||
|
@ -112,7 +112,7 @@ pm.max_children = <%= @max_children || 50 %>
|
||||
; 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 %>
|
||||
pm.start_servers = <%= @start_servers %>
|
||||
<% end %>
|
||||
|
||||
; The desired minimum number of idle server processes.
|
||||
@ -257,7 +257,9 @@ pm.max_requests = <%= @max_requests || 500 %>
|
||||
|
||||
; The access log file
|
||||
; Default: not set
|
||||
;access.log = log/$pool.access.log
|
||||
<% if @access_log %>
|
||||
access.log = <%= node['php-fpm']['log_dir'] %>/$pool.access.log
|
||||
<% end %>
|
||||
|
||||
; The access log format.
|
||||
; The following syntax is allowed
|
||||
@ -330,7 +332,7 @@ pm.max_requests = <%= @max_requests || 500 %>
|
||||
; 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
|
||||
request_terminate_timeout = <%=@request_terminate_timeout || 0 %>
|
||||
|
||||
; Set open file descriptor rlimit.
|
||||
; Default Value: system defined value
|
||||
@ -364,6 +366,7 @@ pm.max_requests = <%= @max_requests || 500 %>
|
||||
; Default Value: no
|
||||
catch_workers_output = <%= @catch_workers_output || "no" %>
|
||||
|
||||
<% if node['platform'] != 'ubuntu' && node['platform_version'] != '10.04' %>
|
||||
; Limits the extensions of the main script FPM will allow to parse. This can
|
||||
; prevent configuration mistakes on the web server side. You should only limit
|
||||
; FPM to .php extensions to prevent malicious users to use other extensions to
|
||||
@ -372,6 +375,7 @@ catch_workers_output = <%= @catch_workers_output || "no" %>
|
||||
; Default Value: .php
|
||||
;security.limit_extensions = .php .php3 .php4 .php5
|
||||
security.limit_extensions = <%=@security_limit_extensions || ".php" %>
|
||||
<% end %>
|
||||
|
||||
; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
|
||||
; the current environment.
|
||||
|
@ -0,0 +1,7 @@
|
||||
require 'serverspec'
|
||||
|
||||
set :backend, :exec
|
||||
|
||||
describe port(9081) do
|
||||
it { should be_listening }
|
||||
end
|
@ -1,35 +0,0 @@
|
||||
# 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!
|
@ -1,410 +0,0 @@
|
||||
# Poise-Service Cookbook
|
||||
|
||||
[](https://travis-ci.org/poise/poise-service)
|
||||
[](https://rubygems.org/gems/poise-service)
|
||||
[](https://supermarket.chef.io/cookbooks/poise-service)
|
||||
[](https://codecov.io/github/poise/poise-service)
|
||||
[](https://gemnasium.com/poise/poise-service)
|
||||
[](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/<service_name>` 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.
|
@ -1,19 +0,0 @@
|
||||
#
|
||||
# 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'] = {}
|
@ -1,25 +0,0 @@
|
||||
#
|
||||
# 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
|
@ -1,18 +0,0 @@
|
||||
#
|
||||
# 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'
|
@ -1,20 +0,0 @@
|
||||
#
|
||||
# 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
|
@ -1,27 +0,0 @@
|
||||
#
|
||||
# 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
|
@ -1,162 +0,0 @@
|
||||
#
|
||||
# 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
|
@ -1,241 +0,0 @@
|
||||
#
|
||||
# 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
|
@ -1,138 +0,0 @@
|
||||
#
|
||||
# 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
|
@ -1,192 +0,0 @@
|
||||
#
|
||||
# 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
|
@ -1,38 +0,0 @@
|
||||
#
|
||||
# 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
|
@ -1,193 +0,0 @@
|
||||
#
|
||||
# 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<Symbol>]
|
||||
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
|
@ -1,156 +0,0 @@
|
||||
#
|
||||
# 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
|
@ -1,150 +0,0 @@
|
||||
#
|
||||
# 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
|
@ -1,83 +0,0 @@
|
||||
#
|
||||
# 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
|
@ -1,91 +0,0 @@
|
||||
#
|
||||
# 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
|
@ -1,128 +0,0 @@
|
||||
#
|
||||
# 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
|
@ -1,45 +0,0 @@
|
||||
#
|
||||
# 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
|
@ -1,20 +0,0 @@
|
||||
#
|
||||
# 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
|
@ -1,19 +0,0 @@
|
||||
#
|
||||
# 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"
|
File diff suppressed because one or more lines are too long
@ -1,7 +0,0 @@
|
||||
<%= {command: @command,
|
||||
directory: @directory,
|
||||
environment: @environment,
|
||||
name: @name,
|
||||
reload_signal: @reload_signal,
|
||||
stop_signal: @stop_signal,
|
||||
user: @user}.to_json %>
|
@ -1,15 +0,0 @@
|
||||
#!/bin/sh
|
||||
exec /opt/chef/embedded/bin/ruby <<EOH
|
||||
require 'etc'
|
||||
IO.write("<%= @pid_file %>", 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
|
@ -1,13 +0,0 @@
|
||||
[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
|
@ -1,190 +0,0 @@
|
||||
#!/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 <<EOH
|
||||
require 'etc'
|
||||
pid_file = <%= @pid_file.inspect %>
|
||||
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
|
@ -1,49 +0,0 @@
|
||||
# <%= @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 <<EOH
|
||||
require 'etc'
|
||||
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
|
||||
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 -%>
|
@ -1,163 +0,0 @@
|
||||
# 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.
|
||||
* Fix for finding the correct cookbook for a file when using vendored gems.
|
||||
* New flag for the OptionCollector helper, `parser`:
|
||||
|
||||
```ruby
|
||||
class Resource < Chef::Resource
|
||||
include Poise
|
||||
attribute(:options, option_collector: true, parser: proc {|val| parse(val) })
|
||||
|
||||
def parse(val)
|
||||
{name: val}
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
* Fix for a possible infinite loop when using `ResourceProviderMixin` in a nested
|
||||
module structure.
|
||||
|
||||
## v2.0.0
|
||||
|
||||
Major overhaul! Poise is now a Halite gem/cookbook. New helpers:
|
||||
|
||||
* ChefspecMatchers – Automatically create Chefspec matchers for Poise resources.
|
||||
* DefinedIn – Track which file (and cookbook) a resource or provider is defined in.
|
||||
* Fused – Experimental support for defining provider actions in the resource class.
|
||||
* Inversion – Support for end-user dependency inversion with providers.
|
||||
|
||||
All helpers are compatible with Chef >= 12.0. Chef 11 is now deprecated, if you
|
||||
need to support Chef 11 please continue to use Poise 1.
|
||||
|
||||
## v1.0.12
|
||||
|
||||
* Correctly propagate errors from inside notifying_block.
|
||||
|
||||
## v1.0.10
|
||||
|
||||
* Fixes an issue with the LWRPPolyfill helper and false values.
|
||||
|
||||
|
||||
## v1.0.8
|
||||
|
||||
* Delayed notifications from nested converges will still only run at the end of
|
||||
the main converge.
|
||||
|
||||
## v1.0.6
|
||||
|
||||
* The include_recipe helper now works correctly when used at compile time.
|
||||
|
||||
## v1.0.4
|
||||
|
||||
* Redeclaring a template attribute with the same name as a parent class will
|
||||
inherit its options.
|
||||
|
||||
## v1.0.2
|
||||
|
||||
* New template attribute pattern.
|
||||
|
||||
```ruby
|
||||
attribute(:config, template: true)
|
||||
|
||||
...
|
||||
|
||||
resource 'name' do
|
||||
config_source 'template.erb'
|
||||
end
|
||||
|
||||
...
|
||||
|
||||
new_resource.config_content
|
||||
```
|
||||
|
||||
## v1.0.0
|
||||
|
||||
* Initial release!
|
@ -1,233 +0,0 @@
|
||||
# Poise
|
||||
|
||||
[](https://travis-ci.org/poise/poise)
|
||||
[](https://rubygems.org/gems/poise)
|
||||
[](https://supermarket.chef.io/cookbooks/poise)
|
||||
[](https://codecov.io/github/poise/poise)
|
||||
[](https://gemnasium.com/poise/poise)
|
||||
[](https://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
## What is Poise?
|
||||
|
||||
The poise cookbook is a set of libraries for writing reusable cookbooks. It
|
||||
provides helpers for common patterns and a standard structure to make it easier to create flexible cookbooks.
|
||||
|
||||
## Writing your first resource
|
||||
|
||||
Rather than LWRPs, Poise promotes the idea of using normal, or "heavy weight"
|
||||
resources, while including helpers to reduce much of boilerplate needed for this. Each resource goes in its own file under `libraries/` named to match
|
||||
the resource, which is in turn based on the class name. This means that the file `libraries/my_app.rb` would contain `Chef::Resource::MyApp` which maps to the resource `my_app`.
|
||||
|
||||
An example of a simple shell to start from:
|
||||
|
||||
```ruby
|
||||
require 'poise'
|
||||
require 'chef/resource'
|
||||
require 'chef/provider'
|
||||
|
||||
module MyApp
|
||||
class Resource < Chef::Resource
|
||||
include Poise
|
||||
provides(:my_app)
|
||||
actions(:enable)
|
||||
|
||||
attribute(:path, kind_of: String)
|
||||
# Other attribute definitions.
|
||||
end
|
||||
|
||||
class Provider < Chef::Provider
|
||||
include Poise
|
||||
provides(:my_app)
|
||||
|
||||
def action_enable
|
||||
notifying_block do
|
||||
... # Normal Chef recipe code goes here
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
Starting from the top, first we require the libraries we will be using. Then we
|
||||
create a module to hold our resource and provider. If your cookbook declares
|
||||
multiple resources and/or providers, you might want additional nesting here.
|
||||
Then we declare the resource class, which inherits from `Chef::Resource`. This
|
||||
is similar to the `resources/` file in an LWRP, and a similar DSL can be used.
|
||||
We then include the `Poise` mixin to load our helpers, and then call
|
||||
`provides(:my_app)` to tell Chef this class will implement the `my_app`
|
||||
resource. Then we use the familiar DSL, though with a few additions we'll cover
|
||||
later.
|
||||
|
||||
Then we declare the provider class, again similar to the `providers/` file in an
|
||||
LWRP. We include the `Poise` mixin again to get access to all the helpers and
|
||||
call `provides()` to tell Chef what provider this is. Rather than use the
|
||||
`action :enable do ... end` DSL from LWRPs, we just define the action method
|
||||
directly. The implementation of action comes from a block of recipe code
|
||||
wrapped with `notifying_block` to capture changes in much the same way as
|
||||
`use_inline_resources`, see below for more information about all the features of
|
||||
`notifying_block`.
|
||||
|
||||
We can then use this resource like any other Chef resource:
|
||||
|
||||
```ruby
|
||||
my_app 'one' do
|
||||
path '/tmp'
|
||||
end
|
||||
```
|
||||
|
||||
## Helpers
|
||||
|
||||
While not exposed as a specific method, Poise will automatically set the
|
||||
`resource_name` based on the class name.
|
||||
|
||||
### Notifying Block
|
||||
|
||||
As mentioned above, `notifying_block` is similar to `use_inline_resources` in LWRPs. Any Chef resource created inside the block will be converged in a sub-context and if any have updated it will trigger notifications on the current resource. Unlike `use_inline_resources`, resources inside the sub-context can still see resources outside of it, with lookups propagating up sub-contexts until a match is found. Also any delayed notifications are scheduled to run at the end of the main converge cycle, instead of the end of this inner converge.
|
||||
|
||||
This can be used to write action methods using the normal Chef recipe DSL, while still offering more flexibility through subclassing and other forms of code reuse.
|
||||
|
||||
### Include Recipe
|
||||
|
||||
In keeping with `notifying_block` to implement action methods using the Chef DSL, Poise adds an `include_recipe` helper to match the method of the same name in recipes. This will load and converge the requested recipe.
|
||||
|
||||
### Resource DSL
|
||||
|
||||
To make writing resource classes easier, Poise exposes a DSL similar to LWRPs for defining actions and attributes. Both `actions` and
|
||||
`default_action` are just like in LWRPs, though `default_action` is rarely needed as the first action becomes the default. `attribute` is also available just like in LWRPs, but with some enhancements noted below.
|
||||
|
||||
One notable difference over the standard DSL method is that Poise attributes
|
||||
can take a block argument.
|
||||
|
||||
#### Template Content
|
||||
|
||||
A common pattern with resources is to allow passing either a template filename or raw file content to be used in a configuration file. Poise exposes a new attribute flag to help with this behavior:
|
||||
|
||||
```ruby
|
||||
attribute(:name, template: true)
|
||||
```
|
||||
|
||||
This creates four methods on the class, `name_source`, `name_cookbook`,
|
||||
`name_content`, and `name_options`. If the name is set to `''`, no prefix is applied to the function names. The content method can be set directly, but if not set and source is set, then it will render the template and return it as a string. Default values can also be set for any of these:
|
||||
|
||||
```ruby
|
||||
attribute(:name, template: true, default_source: 'app.cfg.erb',
|
||||
default_options: {host: 'localhost'})
|
||||
```
|
||||
|
||||
As an example, you can replace this:
|
||||
|
||||
```ruby
|
||||
if new_resource.source
|
||||
template new_resource.path do
|
||||
source new_resource.source
|
||||
owner 'app'
|
||||
group 'app'
|
||||
variables new_resource.options
|
||||
end
|
||||
else
|
||||
file new_resource.path do
|
||||
content new_resource.content
|
||||
owner 'app'
|
||||
group 'app'
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
with simply:
|
||||
|
||||
```ruby
|
||||
file new_resource.path do
|
||||
content new_resource.content
|
||||
owner 'app'
|
||||
group 'app'
|
||||
end
|
||||
```
|
||||
|
||||
As the content method returns the rendered template as a string, this can also
|
||||
be useful within other templates to build from partials.
|
||||
|
||||
#### Lazy Initializers
|
||||
|
||||
One issue with Poise-style resources is that when the class definition is executed, Chef hasn't loaded very far so things like the node object are not
|
||||
yet available. This means setting defaults based on node attributes does not work directly:
|
||||
|
||||
```ruby
|
||||
attribute(:path, default: node['myapp']['path'])
|
||||
...
|
||||
NameError: undefined local variable or method 'node'
|
||||
```
|
||||
|
||||
To work around this, Poise extends the idea of lazy initializers from Chef recipes to work with resource definitions as well:
|
||||
|
||||
```ruby
|
||||
attribute(:path, default: lazy { node['myapp']['path'] })
|
||||
```
|
||||
|
||||
These initializers are run in the context of the resource object, allowing
|
||||
complex default logic to be moved to a method if desired:
|
||||
|
||||
```ruby
|
||||
attribute(:path, default: lazy { my_default_path })
|
||||
|
||||
def my_default_path
|
||||
...
|
||||
end
|
||||
```
|
||||
|
||||
#### Option Collector
|
||||
|
||||
Another common pattern with resources is to need a set of key/value pairs for
|
||||
configuration data or options. This can done with a simple Hash, but an option collector attribute can offer a nicer syntax:
|
||||
|
||||
```ruby
|
||||
attribute(:mydata, option_collector: true)
|
||||
...
|
||||
|
||||
my_app 'name' do
|
||||
mydata do
|
||||
key1 'value1'
|
||||
key2 'value2'
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
This will be converted to `{key1: 'value1', key2: 'value2'}`. You can also pass a Hash to an option collector attribute just as you would with a normal attribute.
|
||||
|
||||
## Debugging Poise
|
||||
|
||||
Poise has its own extra-verbose level of debug logging that can be enabled in
|
||||
three different ways. You can either set the environment variable `$POISE_DEBUG`,
|
||||
set a node attribute `node['POISE_DEBUG']`, or touch the file `/POISE_DEBUG`.
|
||||
You will see a log message `Extra verbose logging enabled` at the start of the
|
||||
run to confirm Poise debugging has been enabled. Make sure you also set Chef's
|
||||
log level to `debug`, usually via `-l debug` on the command line.
|
||||
|
||||
## Upgrading from Poise 1.x
|
||||
|
||||
The biggest change when upgrading from Poise 1.0 is that the mixin is no longer
|
||||
loaded automatically. You must add `require 'poise'` to your code is you want to
|
||||
load it, as you would with normal Ruby code outside of Chef. It is also highly
|
||||
recommended to add `provides(:name)` calls to your resources and providers, this
|
||||
will be required in Chef 13 and will display a deprecation warning if you do
|
||||
not. This also means you can move your code out of the `Chef` module namespace
|
||||
and instead declare it in your own namespace. An example of this is shown above.
|
||||
|
||||
## Sponsors
|
||||
|
||||
The Poise test server infrastructure is generously sponsored by [Rackspace](https://rackspace.com/). Thanks Rackspace!
|
||||
|
||||
## License
|
||||
|
||||
Copyright 2013-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.
|
@ -1,107 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
require 'chef/provider'
|
||||
require 'chef/resource'
|
||||
|
||||
require 'poise/utils/resource_provider_mixin'
|
||||
|
||||
|
||||
module Poise
|
||||
include Poise::Utils::ResourceProviderMixin
|
||||
autoload :Backports, 'poise/backports'
|
||||
autoload :Helpers, 'poise/helpers'
|
||||
autoload :NOT_PASSED, 'poise/backports/not_passed'
|
||||
autoload :Provider, 'poise/provider'
|
||||
autoload :Resource, 'poise/resource'
|
||||
autoload :Subcontext, 'poise/subcontext'
|
||||
autoload :Utils, 'poise/utils'
|
||||
autoload :VERSION, 'poise/version'
|
||||
|
||||
# Check if Poise's extra debugging output is enabled. This produces a *lot*
|
||||
# of logging.
|
||||
#
|
||||
# @param node [Chef::Node, Chef::RunContext] Optional node to check for
|
||||
# attributes. If not given, Chef.node is used instead.
|
||||
# @return [Boolean]
|
||||
def self.debug?(node=nil)
|
||||
node = node.node if node.is_a?(Chef::RunContext)
|
||||
node ||= Chef.node if defined?(Chef.node)
|
||||
@debug_file_upper = ::File.exist?('/POISE_DEBUG') unless defined?(@debug_file_upper)
|
||||
@debug_file_lower = ::File.exist?('/poise_debug') unless defined?(@debug_file_lower)
|
||||
!!(
|
||||
(ENV['POISE_DEBUG'] && ENV['POISE_DEBUG'] != 'false') ||
|
||||
(ENV['poise_debug'] && ENV['poise_debug'] != 'false') ||
|
||||
(node && node['POISE_DEBUG']) ||
|
||||
(node && node['poise_debug']) ||
|
||||
@debug_file_upper ||
|
||||
@debug_file_lower
|
||||
)
|
||||
end
|
||||
|
||||
# Log a message only if Poise's extra debugging output is enabled.
|
||||
#
|
||||
# @see #debug?
|
||||
# @param msg [String] Log message.
|
||||
# @return [void]
|
||||
def self.debug(msg)
|
||||
Chef::Log.debug(msg) if debug?
|
||||
end
|
||||
end
|
||||
|
||||
# Callable form to allow passing in options:
|
||||
# include Poise(ParentResource)
|
||||
# include Poise(parent: ParentResource)
|
||||
# include Poise(container: true)
|
||||
def Poise(options={})
|
||||
# Allow passing a class as a shortcut
|
||||
if options.is_a?(Class)
|
||||
options = {parent: options}
|
||||
end
|
||||
|
||||
# Create a new anonymous module
|
||||
mod = Module.new
|
||||
|
||||
# Fake the name.
|
||||
mod.define_singleton_method(:name) do
|
||||
super() || 'Poise'
|
||||
end
|
||||
|
||||
mod.define_singleton_method(:included) do |klass|
|
||||
super(klass)
|
||||
# Pull in the main helper to cover most of the needed logic.
|
||||
klass.class_exec { include Poise }
|
||||
# Set the defined_in values as needed.
|
||||
klass.poise_defined!(caller)
|
||||
# Resource-specific options.
|
||||
if klass < Chef::Resource
|
||||
klass.poise_subresource(options[:parent], options[:parent_optional], options[:parent_auto]) if options[:parent]
|
||||
klass.poise_subresource_container(options[:container_namespace], options[:container_default]) if options[:container]
|
||||
klass.poise_fused if options[:fused]
|
||||
klass.poise_inversion(options[:inversion_options_resource]) if options[:inversion]
|
||||
end
|
||||
# Provider-specific options.
|
||||
if klass < Chef::Provider
|
||||
klass.poise_inversion(options[:inversion], options[:inversion_attribute]) if options[:inversion]
|
||||
end
|
||||
end
|
||||
|
||||
mod
|
||||
end
|
||||
|
||||
# Display a message if poise_debug is enabled. Off in ChefSpec so I don't get
|
||||
# extra logging stuff that I don't care about.
|
||||
Poise.debug('[Poise] Extra verbose logging enabled') unless defined?(ChefSpec)
|
@ -1,28 +0,0 @@
|
||||
#
|
||||
# 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
|
@ -1,52 +0,0 @@
|
||||
#
|
||||
# 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
|
@ -1,33 +0,0 @@
|
||||
#
|
||||
# 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
|
@ -1,24 +0,0 @@
|
||||
#
|
||||
# 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
|
||||
# Base exception class for Poise errors.
|
||||
#
|
||||
# @since 2.0.0
|
||||
class Error < Exception
|
||||
end
|
||||
end
|
@ -1,35 +0,0 @@
|
||||
#
|
||||
# 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 Helpers
|
||||
autoload :ChefspecMatchers, 'poise/helpers/chefspec_matchers'
|
||||
autoload :DefinedIn, 'poise/helpers/defined_in'
|
||||
autoload :Fused, 'poise/helpers/fused'
|
||||
autoload :IncludeRecipe, 'poise/helpers/include_recipe'
|
||||
autoload :Inversion, 'poise/helpers/inversion'
|
||||
autoload :LazyDefault, 'poise/helpers/lazy_default'
|
||||
autoload :LWRPPolyfill, 'poise/helpers/lwrp_polyfill'
|
||||
autoload :NotifyingBlock, 'poise/helpers/notifying_block'
|
||||
autoload :OptionCollector, 'poise/helpers/option_collector'
|
||||
autoload :ResourceCloning, 'poise/helpers/resource_cloning'
|
||||
autoload :ResourceName, 'poise/helpers/resource_name'
|
||||
autoload :ResourceSubclass, 'poise/helpers/resource_subclass'
|
||||
autoload :Subresources, 'poise/helpers/subresources'
|
||||
autoload :TemplateContent, 'poise/helpers/template_content'
|
||||
end
|
||||
end
|
@ -1,92 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
# Not requiring chefspec or rspec/expectations since this code should only
|
||||
# activate if they are already loaded.
|
||||
|
||||
require 'poise/helpers/lwrp_polyfill'
|
||||
require 'poise/helpers/resource_name'
|
||||
|
||||
|
||||
module Poise
|
||||
module Helpers
|
||||
# A resource mixin to register ChefSpec matchers for a resource
|
||||
# automatically.
|
||||
#
|
||||
# If you are using the provides() form for naming resources, ensure that is
|
||||
# set before declaring actions.
|
||||
#
|
||||
# @since 2.0.0
|
||||
# @example Define a class
|
||||
# class Chef::Resource::MyResource < Chef::Resource
|
||||
# include Poise::Helpers::ChefspecMatchers
|
||||
# actions(:run)
|
||||
# end
|
||||
# @example Use a matcher
|
||||
# expect(chef_run).to run_my_resource('...')
|
||||
module ChefspecMatchers
|
||||
include Poise::Helpers::LWRPPolyfill::Resource
|
||||
include Poise::Helpers::ResourceName
|
||||
|
||||
# Create a matcher for a given resource type and action. This is
|
||||
# idempotent so if a matcher already exists, it will not be recreated.
|
||||
#
|
||||
# @api private
|
||||
def self.create_matcher(resource, action)
|
||||
# Check that we have everything we need.
|
||||
return unless defined?(ChefSpec) && defined?(RSpec::Matchers) && resource
|
||||
method = :"#{action}_#{resource}"
|
||||
return if RSpec::Matchers.method_defined?(method)
|
||||
RSpec::Matchers.send(:define_method, method) do |resource_name|
|
||||
ChefSpec::Matchers::ResourceMatcher.new(resource, action, resource_name)
|
||||
end
|
||||
end
|
||||
|
||||
# @!classmethods
|
||||
module ClassMethods
|
||||
# Create a resource-level matcher for this resource.
|
||||
#
|
||||
# @see Resource::ResourceName.provides
|
||||
def provides(name, *args, &block)
|
||||
super(name, *args, &block)
|
||||
ChefSpec.define_matcher(name) if defined?(ChefSpec)
|
||||
# Call #actions here to grab any actions from a parent class.
|
||||
actions.each do |action|
|
||||
ChefspecMatchers.create_matcher(name, action)
|
||||
end
|
||||
end
|
||||
|
||||
# Create matchers for all declared actions.
|
||||
#
|
||||
# @see Resource::LWRPPolyfill.actions
|
||||
def actions(*names)
|
||||
super.tap do |actions|
|
||||
actions.each do |action|
|
||||
ChefspecMatchers.create_matcher(resource_name, action)
|
||||
end if resource_name && resource_name != :resource && !names.empty?
|
||||
end
|
||||
end
|
||||
|
||||
def included(klass)
|
||||
super
|
||||
klass.extend ClassMethods
|
||||
end
|
||||
end
|
||||
|
||||
extend ClassMethods
|
||||
end
|
||||
end
|
||||
end
|
@ -1,111 +0,0 @@
|
||||
#
|
||||
# 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/utils'
|
||||
|
||||
|
||||
module Poise
|
||||
module Helpers
|
||||
# A mixin to track where a resource or provider was defined. This can
|
||||
# provide either the filename of the class or the cookbook it was defined in.
|
||||
#
|
||||
# @since 2.0.0
|
||||
# @example
|
||||
# class MyProvider < Chef::provider
|
||||
# include Poise::Helpers::DefinedIn
|
||||
#
|
||||
# def action_create
|
||||
# template '...' do
|
||||
# # ...
|
||||
# cookbook new_resource.poise_defined_in
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
module DefinedIn
|
||||
# Wrapper for {.poise_defined_in_cookbook} to pass the run context for you.
|
||||
#
|
||||
# @see .poise_defined_in_cookbook
|
||||
# @param file [String, nil] Optional file path to check instead of the path
|
||||
# this class was defined in.
|
||||
# @return [String]
|
||||
def poise_defined_in_cookbook(file=nil)
|
||||
self.class.poise_defined_in_cookbook(run_context, file)
|
||||
end
|
||||
|
||||
# @!classmethods
|
||||
module ClassMethods
|
||||
# The file this class or module was defined in, or nil if it isn't found.
|
||||
#
|
||||
# @return [String]
|
||||
def poise_defined_in
|
||||
raise Poise::Error.new("Unable to determine location of #{self.name}") unless @poise_defined_in
|
||||
@poise_defined_in
|
||||
end
|
||||
|
||||
# The cookbook this class or module was defined in. Can pass a file to
|
||||
# check that instead.
|
||||
#
|
||||
# @param run_context [Chef::RunContext] Run context to check cookbooks in.
|
||||
# @param file [String, nil] Optional file path to check instead of the
|
||||
# path this class was defined in.
|
||||
# @return [String]
|
||||
def poise_defined_in_cookbook(run_context, file=nil)
|
||||
file ||= poise_defined_in
|
||||
Poise.debug("[#{self.name}] Checking cookbook name for #{file}")
|
||||
Poise::Utils.find_cookbook_name(run_context, file).tap do |cookbook|
|
||||
Poise.debug("[#{self.name}] found cookbook #{cookbook.inspect}")
|
||||
end
|
||||
end
|
||||
|
||||
# Record that the class/module was defined. Called automatically by Ruby
|
||||
# for all normal cases.
|
||||
#
|
||||
# @param caller_array [Array<String>] A strack trace returned by #caller.
|
||||
# @return [void]
|
||||
def poise_defined!(caller_array)
|
||||
# Only try to set this once.
|
||||
return if @poise_defined_in
|
||||
# Path to ignore, assumes Halite transformation which I'm not thrilled
|
||||
# about.
|
||||
poise_libraries = File.expand_path('../..', __FILE__)
|
||||
# Parse out just the filenames.
|
||||
caller_array = caller_array.map {|line| line.split(/:/, 2).first }
|
||||
# Find the first non-poise line.
|
||||
caller_path = caller_array.find do |line|
|
||||
!line.start_with?(poise_libraries)
|
||||
end
|
||||
Chef::Log.debug("[#{self.name}] Recording poise_defined_in as #{caller_path}")
|
||||
@poise_defined_in = caller_path
|
||||
end
|
||||
|
||||
# @api private
|
||||
def inherited(klass)
|
||||
super
|
||||
klass.poise_defined!(caller)
|
||||
end
|
||||
|
||||
def included(klass)
|
||||
super
|
||||
klass.extend(ClassMethods)
|
||||
klass.poise_defined!(caller)
|
||||
end
|
||||
end
|
||||
|
||||
extend ClassMethods
|
||||
end
|
||||
end
|
||||
end
|
@ -1,127 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
require 'chef/provider'
|
||||
|
||||
|
||||
module Poise
|
||||
module Helpers
|
||||
# Resource mixin to create "fused" resources where the resource and provider
|
||||
# are implemented in the same class.
|
||||
#
|
||||
# @since 2.0.0
|
||||
# @example
|
||||
# class Chef::Resource::MyResource < Chef::Resource
|
||||
# include Poise(fused: true)
|
||||
# attribute(:path, kind_of: String)
|
||||
# attribute(:message, kind_of: String)
|
||||
# action(:run) do
|
||||
# file new_resource.path do
|
||||
# content new_resource.message
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
module Fused
|
||||
# Hack is_a? so that the DSL will consider this a Provider for the
|
||||
# purposes of attaching enclosing_provider.
|
||||
#
|
||||
# @api private
|
||||
# @param klass [Class]
|
||||
# @return [Boolean]
|
||||
def is_a?(klass)
|
||||
if klass == Chef::Provider
|
||||
# Lies, damn lies, and Ruby code.
|
||||
true
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
# Hack provider_for_action so that the resource is also the provider.
|
||||
#
|
||||
# @api private
|
||||
# @param action [Symbol]
|
||||
# @return [Chef::Provider]
|
||||
def provider_for_action(action)
|
||||
provider(self.class.fused_provider_class) unless provider
|
||||
super
|
||||
end
|
||||
|
||||
# @!classmethods
|
||||
module ClassMethods
|
||||
# Define a provider action. The block should contain the usual provider
|
||||
# code.
|
||||
#
|
||||
# @param name [Symbol] Name of the action.
|
||||
# @param block [Proc] Action implementation.
|
||||
# @example
|
||||
# action(:run) do
|
||||
# file '/temp' do
|
||||
# user 'root'
|
||||
# content 'temp'
|
||||
# end
|
||||
# end
|
||||
def action(name, &block)
|
||||
fused_actions[name.to_sym] = block
|
||||
# Make sure this action is allowed, also sets the default if first.
|
||||
if respond_to?(:actions)
|
||||
actions(name.to_sym)
|
||||
end
|
||||
end
|
||||
|
||||
# Storage accessor for fused action blocks. Maps action name to proc.
|
||||
#
|
||||
# @api private
|
||||
# @return [Hash<Symbol, Proc>]
|
||||
def fused_actions
|
||||
(@fused_actions ||= {})
|
||||
end
|
||||
|
||||
# Create a provider class for the fused actions in this resource.
|
||||
# Inherits from the fused provider class of the resource's superclass if
|
||||
# present.
|
||||
#
|
||||
# @api private
|
||||
# @return [Class]
|
||||
def fused_provider_class
|
||||
@fused_provider_class ||= begin
|
||||
provider_superclass = begin
|
||||
self.superclass.fused_provider_class
|
||||
rescue NoMethodError
|
||||
Chef::Provider
|
||||
end
|
||||
actions = fused_actions
|
||||
class_name = self.name
|
||||
Class.new(provider_superclass) do
|
||||
include Poise
|
||||
define_singleton_method(:name) { class_name + ' (fused)' }
|
||||
actions.each do |action, block|
|
||||
define_method(:"action_#{action}", &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def included(klass)
|
||||
super
|
||||
klass.extend(ClassMethods)
|
||||
end
|
||||
end
|
||||
|
||||
extend ClassMethods
|
||||
end
|
||||
end
|
||||
end
|
@ -1,62 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
require 'poise/helpers/subcontext_block'
|
||||
require 'poise/subcontext/runner'
|
||||
|
||||
|
||||
module Poise
|
||||
module Helpers
|
||||
# A provider mixin to add #include_recipe that can be called from action
|
||||
# methods.
|
||||
#
|
||||
# @since 2.0.0
|
||||
module IncludeRecipe
|
||||
include Poise::Helpers::SubcontextBlock
|
||||
|
||||
def include_recipe(*recipes)
|
||||
loaded_recipes = []
|
||||
subcontext = subcontext_block do
|
||||
recipes.each do |recipe|
|
||||
case recipe
|
||||
when String
|
||||
# Process normally
|
||||
Chef::Log.debug("Loading recipe #{recipe} via include_recipe (poise)")
|
||||
loaded_recipes += run_context.include_recipe(recipe)
|
||||
when Proc
|
||||
# Pretend its a block of recipe code
|
||||
fake_recipe = Chef::Recipe.new(cookbook_name, new_resource.recipe_name, run_context)
|
||||
fake_recipe.instance_eval(&recipe)
|
||||
loaded_recipes << fake_recipe
|
||||
end
|
||||
end
|
||||
end
|
||||
# Converge the new context.
|
||||
Poise::Subcontext::Runner.new(new_resource, subcontext).converge
|
||||
collection = global_resource_collection
|
||||
subcontext.resource_collection.each do |r|
|
||||
Chef::Log.debug("Poise::IncludeRecipe: Adding #{r} to global collection #{collection.object_id}")
|
||||
# Insert the local resource into the global context
|
||||
collection.insert(r)
|
||||
# Skip the iterator forward so we don't double-execute the inserted resource
|
||||
# If running at compile time, the iterator is nil
|
||||
collection.iterator.skip_forward if collection.iterator
|
||||
end
|
||||
loaded_recipes
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,414 +0,0 @@
|
||||
#
|
||||
# Copyright 2015, Noah Kantrowitz
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
require 'chef/node'
|
||||
require 'chef/node_map'
|
||||
require 'chef/provider'
|
||||
require 'chef/resource'
|
||||
|
||||
require 'poise/backports'
|
||||
require 'poise/helpers/defined_in'
|
||||
require 'poise/error'
|
||||
require 'poise/helpers/inversion/options_resource'
|
||||
require 'poise/utils/resource_provider_mixin'
|
||||
|
||||
|
||||
module Poise
|
||||
module Helpers
|
||||
# A mixin for dependency inversion in Chef.
|
||||
#
|
||||
# @since 2.0.0
|
||||
module Inversion
|
||||
autoload :OptionsResource, 'poise/helpers/inversion/options_resource'
|
||||
autoload :OptionsProvider, 'poise/helpers/inversion/options_provider'
|
||||
|
||||
include Poise::Utils::ResourceProviderMixin
|
||||
|
||||
# Resource implementation for {Poise::Helpers::Inversion}.
|
||||
# @see Poise::Helpers::Inversion
|
||||
module Resource
|
||||
# @overload options(val=nil)
|
||||
# Set or return provider options for all providers.
|
||||
# @param val [Hash] Provider options to set.
|
||||
# @return [Hash]
|
||||
# @example
|
||||
# my_resource 'thing_one' do
|
||||
# options depends: 'thing_two'
|
||||
# end
|
||||
# @overload options(provider, val=nil)
|
||||
# Set or return provider options for a specific provider.
|
||||
# @param provider [Symbol] Provider to set for.
|
||||
# @param val [Hash] Provider options to set.
|
||||
# @return [Hash]
|
||||
# @example
|
||||
# my_resource 'thing_one' do
|
||||
# options :my_provider, depends: 'thing_two'
|
||||
# end
|
||||
def options(provider=nil, val=nil)
|
||||
key = :options
|
||||
if !val && provider.is_a?(Hash)
|
||||
val = provider
|
||||
elsif provider
|
||||
key = :"options_#{provider}"
|
||||
end
|
||||
set_or_return(key, val ? Mash.new(val) : val, kind_of: Hash, default: lazy { Mash.new })
|
||||
end
|
||||
|
||||
# Allow setting the provider directly using the same names as the attribute
|
||||
# settings.
|
||||
#
|
||||
# @param val [String, Symbol, Class, nil] Value to set the provider to.
|
||||
# @return [Class]
|
||||
# @example
|
||||
# my_resource 'thing_one' do
|
||||
# provider :my_provider
|
||||
# end
|
||||
def provider(val=nil)
|
||||
if val && !val.is_a?(Class)
|
||||
resource_names = [resource_name]
|
||||
# If subclass_providers! might be in play, check for those names too.
|
||||
resource_names.concat(self.class.subclass_resource_equivalents) if self.class.respond_to?(:subclass_resource_equivalents)
|
||||
# Silly ruby tricks to find the first provider that exists and no more.
|
||||
provider_class = resource_names.lazy.map {|name| Poise::Helpers::Inversion.provider_for(name, node, val) }.select {|x| x }.first
|
||||
Poise.debug("[#{self}] Checking for an inversion provider for #{val}: #{provider_class && provider_class.name}")
|
||||
val = provider_class if provider_class
|
||||
end
|
||||
super
|
||||
end
|
||||
|
||||
# Set or return the array of provider names to be blocked from
|
||||
# auto-resolution.
|
||||
#
|
||||
# @param val [String, Array<String>] Value to set.
|
||||
# @return [Array<String>]
|
||||
def provider_no_auto(val=nil)
|
||||
# Coerce to an array.
|
||||
val = Array(val).map(&:to_s) if val
|
||||
set_or_return(:provider_no_auto, val, kind_of: Array, default: [])
|
||||
end
|
||||
|
||||
# @!classmethods
|
||||
module ClassMethods
|
||||
# Options resource class.
|
||||
attr_reader :inversion_options_resource_class
|
||||
# Options provider class.
|
||||
attr_reader :inversion_options_provider_class
|
||||
|
||||
# @overload inversion_options_resource()
|
||||
# Return the options resource mode for this class.
|
||||
# @return [Boolean]
|
||||
# @overload inversion_options_resource(val)
|
||||
# Set the options resource mode for this class. Set to true to
|
||||
# automatically create an options resource. Defaults to true.
|
||||
# @param val [Boolean] Enable/disable setting.
|
||||
# @return [Boolean]
|
||||
def inversion_options_resource(val=nil)
|
||||
@poise_inversion_options_resource = val unless val.nil?
|
||||
@poise_inversion_options_resource
|
||||
end
|
||||
|
||||
# Create resource and provider classes for an options resource.
|
||||
#
|
||||
# @param name [String, Symbol] DSL name for the base resource.
|
||||
# @return [void]
|
||||
def create_inversion_options_resource!(name)
|
||||
enclosing_class = self
|
||||
options_resource_name = :"#{name}_options"
|
||||
# Create the resource class.
|
||||
@inversion_options_resource_class = Class.new(Chef::Resource) do
|
||||
include Poise::Helpers::Inversion::OptionsResource
|
||||
define_singleton_method(:name) do
|
||||
"#{enclosing_class}::OptionsResource"
|
||||
end
|
||||
define_singleton_method(:inversion_resource_class) do
|
||||
enclosing_class
|
||||
end
|
||||
provides(options_resource_name)
|
||||
inversion_resource(name)
|
||||
end
|
||||
# Create the provider class.
|
||||
@inversion_options_provider_class = Class.new(Chef::Provider) do
|
||||
include Poise::Helpers::Inversion::OptionsProvider
|
||||
define_singleton_method(:name) do
|
||||
"#{enclosing_class}::OptionsProvider"
|
||||
end
|
||||
define_singleton_method(:inversion_resource_class) do
|
||||
enclosing_class
|
||||
end
|
||||
provides(options_resource_name)
|
||||
end
|
||||
end
|
||||
|
||||
# Wrap #provides() to create an options resource if desired.
|
||||
#
|
||||
# @param name [Symbol] Resource name
|
||||
# return [void]
|
||||
def provides(name, *args, &block)
|
||||
create_inversion_options_resource!(name) if inversion_options_resource
|
||||
super(name, *args, &block) if defined?(super)
|
||||
end
|
||||
|
||||
def included(klass)
|
||||
super
|
||||
klass.extend(ClassMethods)
|
||||
end
|
||||
end
|
||||
|
||||
extend ClassMethods
|
||||
end
|
||||
|
||||
# Provider implementation for {Poise::Helpers::Inversion}.
|
||||
# @see Poise::Helpers::Inversion
|
||||
module Provider
|
||||
include DefinedIn
|
||||
|
||||
# Compile all the different levels of inversion options together.
|
||||
#
|
||||
# @return [Hash]
|
||||
# @example
|
||||
# def action_run
|
||||
# if options['depends']
|
||||
# # ...
|
||||
# end
|
||||
# end
|
||||
def options
|
||||
@options ||= self.class.inversion_options(node, new_resource)
|
||||
end
|
||||
|
||||
# @!classmethods
|
||||
module ClassMethods
|
||||
# @overload inversion_resource()
|
||||
# Return the inversion resource name for this class.
|
||||
# @return [Symbo, nill]
|
||||
# @overload inversion_resource(val)
|
||||
# Set the inversion resource name for this class. You can pass either
|
||||
# a symbol in DSL format or a resource class that uses Poise. This
|
||||
# name is used to determine which resources the inversion provider is
|
||||
# a candidate for.
|
||||
# @param val [Symbol, Class] Name to set.
|
||||
# @return [Symbol, nil]
|
||||
def inversion_resource(val=Poise::NOT_PASSED)
|
||||
if val != Poise::NOT_PASSED
|
||||
val = val.resource_name if val.is_a?(Class)
|
||||
Chef::Log.debug("[#{self.name}] Setting inversion resource to #{val}")
|
||||
@poise_inversion_resource = val.to_sym
|
||||
end
|
||||
if defined?(@poise_inversion_resource)
|
||||
@poise_inversion_resource
|
||||
else
|
||||
Poise::Utils.ancestor_send(self, :inversion_resource, default: nil)
|
||||
end
|
||||
end
|
||||
|
||||
# @overload inversion_attribute()
|
||||
# Return the inversion attribute name(s) for this class.
|
||||
# @return [Array<String>, 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<String>] Attribute path.
|
||||
# @return [Array<String>, nil]
|
||||
def inversion_attribute(val=Poise::NOT_PASSED)
|
||||
if val != Poise::NOT_PASSED
|
||||
# Coerce to an array of strings.
|
||||
val = Array(val).map {|name| name.to_s }
|
||||
@poise_inversion_attribute = val
|
||||
end
|
||||
if defined?(@poise_inversion_attribute)
|
||||
@poise_inversion_attribute
|
||||
else
|
||||
Poise::Utils.ancestor_send(self, :inversion_attribute, default: nil)
|
||||
end
|
||||
end
|
||||
|
||||
# Default attribute paths to check for inversion options. Based on
|
||||
# the cookbook this class and its superclasses are defined in.
|
||||
#
|
||||
# @param node [Chef::Node] Node to load from.
|
||||
# @return [Array<Array<String>>]
|
||||
def default_inversion_attributes(node)
|
||||
klass = self
|
||||
tried = []
|
||||
while klass.respond_to?(:poise_defined_in_cookbook)
|
||||
cookbook = klass.poise_defined_in_cookbook(node.run_context)
|
||||
if node[cookbook]
|
||||
return [cookbook]
|
||||
end
|
||||
tried << cookbook
|
||||
klass = klass.superclass
|
||||
end
|
||||
raise Poise::Error.new("Unable to find inversion attributes, tried: #{tried.join(', ')}")
|
||||
end
|
||||
|
||||
# Resolve the node attribute used as the base for inversion options
|
||||
# for this class. This can be set explicitly with {.inversion_attribute}
|
||||
# or the default is to use the name of the cookbook the provider is
|
||||
# defined in.
|
||||
#
|
||||
# @param node [Chef::Node] Node to load from.
|
||||
# @return [Chef::Node::Attribute]
|
||||
def resolve_inversion_attribute(node)
|
||||
# Default to using just the name of the cookbook.
|
||||
attribute_names = inversion_attribute || default_inversion_attributes(node)
|
||||
return {} if attribute_names.empty?
|
||||
attribute_names.inject(node) do |memo, key|
|
||||
memo[key] || begin
|
||||
raise Poise::Error.new("Attribute #{key} not set when expanding inversion attribute for #{self.name}: #{memo}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Compile all the different levels of inversion options together.
|
||||
#
|
||||
# @param node [Chef::Node] Node to load from.
|
||||
# @param resource [Chef::Resource] Resource to load from.
|
||||
# @return [Hash]
|
||||
def inversion_options(node, resource)
|
||||
Mash.new.tap do |opts|
|
||||
attrs = resolve_inversion_attribute(node)
|
||||
# Cast the run state to a Mash because string vs. symbol keys. I can
|
||||
# at least promise poise_inversion will be a str so cut down on the
|
||||
# amount of data to convert.
|
||||
run_state = Mash.new(node.run_state.fetch('poise_inversion', {}).fetch(inversion_resource, {}))[resource.name] || {}
|
||||
# Class-level defaults.
|
||||
opts.update(default_inversion_options(node, resource))
|
||||
# Resource options for all providers.
|
||||
opts.update(resource.options) if resource.respond_to?(:options)
|
||||
# Global provider from node attributes.
|
||||
opts.update(provider: attrs['provider']) if attrs['provider']
|
||||
# Attribute options for all providers.
|
||||
opts.update(attrs['options']) if attrs['options']
|
||||
# Resource options for this provider.
|
||||
opts.update(resource.options(provides)) if resource.respond_to?(:options)
|
||||
# Attribute options for this resource name.
|
||||
opts.update(attrs[resource.name]) if attrs[resource.name]
|
||||
# Options resource options for all providers.
|
||||
opts.update(run_state['*']) if run_state['*']
|
||||
# Options resource options for this provider.
|
||||
opts.update(run_state[provides]) if run_state[provides]
|
||||
# Vomitdebug output for tracking down weirdness.
|
||||
Poise.debug("[#{resource}] Resolved inversion options: #{opts.inspect}")
|
||||
end
|
||||
end
|
||||
|
||||
# Default options data for this provider class.
|
||||
#
|
||||
# @param node [Chef::Node] Node to load from.
|
||||
# @param resource [Chef::Resource] Resource to load from.
|
||||
# @return [Hash]
|
||||
def default_inversion_options(node, resource)
|
||||
{}
|
||||
end
|
||||
|
||||
# Resolve which provider name should be used for a resource.
|
||||
#
|
||||
# @param node [Chef::Node] Node to load from.
|
||||
# @param resource [Chef::Resource] Resource to query.
|
||||
# @return [String]
|
||||
def resolve_inversion_provider(node, resource)
|
||||
inversion_options(node, resource)['provider'] || 'auto'
|
||||
end
|
||||
|
||||
# Override the normal #provides to set the inversion provider name
|
||||
# instead of adding to the normal provider map.
|
||||
#
|
||||
# @overload provides()
|
||||
# Return the inversion provider name for the class.
|
||||
# @return [Symbol]
|
||||
# @overload provides(name, opts={}, &block)
|
||||
# Set the inversion provider name for the class.
|
||||
# @param name [Symbol] Provider name.
|
||||
# @param opts [Hash] NodeMap filter options.
|
||||
# @param block [Proc] NodeMap filter proc.
|
||||
# @return [Symbol]
|
||||
def provides(name=nil, opts={}, &block)
|
||||
if name
|
||||
raise Poise::Error.new("Inversion resource name not set for #{self.name}") unless inversion_resource
|
||||
@poise_inversion_provider = name
|
||||
Chef::Log.debug("[#{self.name}] Setting inversion provider name to #{name}")
|
||||
Poise::Helpers::Inversion.provider_map(inversion_resource).set(name.to_sym, self, opts, &block)
|
||||
# Set the actual Chef-level provides name for DSL dispatch.
|
||||
super(inversion_resource)
|
||||
end
|
||||
@poise_inversion_provider
|
||||
end
|
||||
|
||||
# Override the default #provides? to check for our inverted providers.
|
||||
#
|
||||
# @api private
|
||||
# @param node [Chef::Node] Node to use for attribute checks.
|
||||
# @param resource [Chef::Resource] Resource instance to match.
|
||||
# @return [Boolean]
|
||||
def provides?(node, resource)
|
||||
raise Poise::Error.new("Inversion resource name not set for #{self.name}") unless inversion_resource
|
||||
resource_name_equivalents = {resource.resource_name => true}
|
||||
# If subclass_providers! might be in play, check for those names too.
|
||||
if resource.class.respond_to?(:subclass_resource_equivalents)
|
||||
resource.class.subclass_resource_equivalents.each do |name|
|
||||
resource_name_equivalents[name] = true
|
||||
end
|
||||
end
|
||||
return false unless resource_name_equivalents[inversion_resource]
|
||||
provider_name = resolve_inversion_provider(node, resource)
|
||||
Poise.debug("[#{resource}] Checking provides? on #{self.name}. Got provider_name #{provider_name.inspect}")
|
||||
provider_name == provides.to_s || ( provider_name == 'auto' && !resource.provider_no_auto.include?(provides.to_s) && provides_auto?(node, resource) )
|
||||
end
|
||||
|
||||
# Subclass hook to provide auto-detection for providers.
|
||||
#
|
||||
# @param node [Chef::Node] Node to check against.
|
||||
# @param resource [Chef::Resource] Resource to check against.
|
||||
# @return [Boolean]
|
||||
def provides_auto?(node, resource)
|
||||
false
|
||||
end
|
||||
|
||||
def included(klass)
|
||||
super
|
||||
klass.extend(ClassMethods)
|
||||
end
|
||||
end
|
||||
|
||||
extend ClassMethods
|
||||
end
|
||||
|
||||
# The provider map for a given resource type.
|
||||
#
|
||||
# @param resource_type [Symbol] Resource type in DSL format.
|
||||
# @return [Chef::NodeMap]
|
||||
# @example
|
||||
# Poise::Helpers::Inversion.provider_map(:my_resource)
|
||||
def self.provider_map(resource_type)
|
||||
@provider_maps ||= {}
|
||||
@provider_maps[resource_type.to_sym] ||= Chef::NodeMap.new
|
||||
end
|
||||
|
||||
# Find a specific provider class for a resource.
|
||||
#
|
||||
# @param resource_type [Symbol] Resource type in DSL format.
|
||||
# @param node [Chef::Node] Node to use for the lookup.
|
||||
# @param provider_type [Symbol] Provider type in DSL format.
|
||||
# @return [Class]
|
||||
# @example
|
||||
# Poise::Helpers::Inversion.provider_for(:my_resource, node, :my_provider)
|
||||
def self.provider_for(resource_type, node, provider_type)
|
||||
provider_map(resource_type).get(node, provider_type.to_sym)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,41 +0,0 @@
|
||||
#
|
||||
# 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 Helpers
|
||||
module Inversion
|
||||
# A mixin for inversion options providers.
|
||||
#
|
||||
# @api private
|
||||
# @since 2.0.0
|
||||
# @see Poise::Helper::Inversion
|
||||
module OptionsProvider
|
||||
# @api private
|
||||
def self.included(klass)
|
||||
klass.class_exec { include Poise }
|
||||
end
|
||||
|
||||
# A blank run action.
|
||||
#
|
||||
# @return [void]
|
||||
def action_run
|
||||
# This space left intentionally blank.
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,101 +0,0 @@
|
||||
#
|
||||
# Copyright 2015, Noah Kantrowitz
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
require 'chef/mash'
|
||||
|
||||
require 'poise/error'
|
||||
|
||||
|
||||
module Poise
|
||||
module Helpers
|
||||
module Inversion
|
||||
# A mixin for inversion options resources.
|
||||
#
|
||||
# @api private
|
||||
# @since 2.0.0
|
||||
# @see Poise::Helpers::Inversion
|
||||
module OptionsResource
|
||||
include Poise
|
||||
|
||||
# Method missing delegation to allow DSL-style options.
|
||||
#
|
||||
# @example
|
||||
# my_app_options 'app' do
|
||||
# key1 'value1'
|
||||
# key2 'value2'
|
||||
# end
|
||||
def method_missing(method_sym, *args, &block)
|
||||
super(method_sym, *args, &block)
|
||||
rescue NoMethodError
|
||||
# First time we've seen this key and using it as an rvalue, NOPE.GIF.
|
||||
raise unless !args.empty? || block || _options[method_sym]
|
||||
if !args.empty? || block
|
||||
_options[method_sym] = block || args.first
|
||||
end
|
||||
_options[method_sym]
|
||||
end
|
||||
|
||||
# Insert the options data in to the run state. This has to match the
|
||||
# layout used in {Poise::Helpers::Inversion::Provider.inversion_options}.
|
||||
#
|
||||
# @api private
|
||||
def after_created
|
||||
raise Poise::Error.new("Inversion resource name not set for #{self.class.name}") unless self.class.inversion_resource
|
||||
node.run_state['poise_inversion'] ||= {}
|
||||
node.run_state['poise_inversion'][self.class.inversion_resource] ||= {}
|
||||
node.run_state['poise_inversion'][self.class.inversion_resource][resource] ||= {}
|
||||
node.run_state['poise_inversion'][self.class.inversion_resource][resource][for_provider] ||= {}
|
||||
node.run_state['poise_inversion'][self.class.inversion_resource][resource][for_provider].update(_options)
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
# @overload inversion_resource()
|
||||
# Return the inversion resource name for this class.
|
||||
# @return [Symbol]
|
||||
# @overload inversion_resource(val)
|
||||
# Set the inversion resource name for this class. You can pass either
|
||||
# a symbol in DSL format or a resource class that uses Poise. This
|
||||
# name is used to determine which resources the inversion provider is
|
||||
# a candidate for.
|
||||
# @param val [Symbol, Class] Name to set.
|
||||
# @return [Symbol]
|
||||
def inversion_resource(val=nil)
|
||||
if val
|
||||
val = val.resource_name if val.is_a?(Class)
|
||||
Chef::Log.debug("[#{self.name}] Setting inversion resource to #{val}")
|
||||
@poise_inversion_resource = val.to_sym
|
||||
end
|
||||
@poise_inversion_resource || (superclass.respond_to?(:inversion_resource) ? superclass.inversion_resource : nil)
|
||||
end
|
||||
|
||||
# @api private
|
||||
def included(klass)
|
||||
super
|
||||
klass.extend(ClassMethods)
|
||||
klass.class_exec do
|
||||
actions(:run)
|
||||
attribute(:resource, kind_of: String, name_attribute: true)
|
||||
attribute(:for_provider, kind_of: [String, Symbol], default: '*')
|
||||
attribute(:_options, kind_of: Hash, default: lazy { Mash.new })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
extend ClassMethods
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,79 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
require 'chef/version'
|
||||
|
||||
|
||||
module Poise
|
||||
module Helpers
|
||||
# Resource mixin to allow lazyily-evaluated defaults in resource attributes.
|
||||
# This is designed to be used with {LWRPPolyfill} or a similar #attributes
|
||||
# method.
|
||||
#
|
||||
# @since 1.0.0
|
||||
# @example
|
||||
# class MyResource < Chef::Resource
|
||||
# include Poise::Helpers::LWRPPolyfill
|
||||
# include Poise::Helpers::LazyDefault
|
||||
# attribute(:path, default: lazy { name + '_temp' })
|
||||
# end
|
||||
module LazyDefault
|
||||
# Check if this version of Chef already supports lazy defaults. This is
|
||||
# true for Chef 12.5+.
|
||||
#
|
||||
# @since 2.0.3
|
||||
# @api private
|
||||
# @return [Boolean]
|
||||
def self.needs_polyfill?
|
||||
@needs_polyfill ||= Gem::Requirement.new('< 12.5.pre').satisfied_by?(Gem::Version.new(Chef::VERSION))
|
||||
end
|
||||
|
||||
# Override the default set_or_return to support lazy evaluation of the
|
||||
# default value. This only actually matters when it is called from a class
|
||||
# level context via #attributes.
|
||||
def set_or_return(symbol, arg, validation)
|
||||
if LazyDefault.needs_polyfill? && validation && validation[:default].is_a?(Chef::DelayedEvaluator)
|
||||
validation = validation.dup
|
||||
if (arg.nil? || arg == Poise::NOT_PASSED) && (!instance_variable_defined?(:"@#{symbol}") || instance_variable_get(:"@#{symbol}").nil?)
|
||||
validation[:default] = instance_eval(&validation[:default])
|
||||
else
|
||||
# Clear the default.
|
||||
validation.delete(:default)
|
||||
end
|
||||
end
|
||||
super(symbol, arg, validation)
|
||||
end
|
||||
|
||||
# @!classmethods
|
||||
module ClassMethods
|
||||
# Create a lazyily-evaluated block.
|
||||
#
|
||||
# @param block [Proc] Callable to return the default value.
|
||||
# @return [Chef::DelayedEvaluator]
|
||||
def lazy(&block)
|
||||
Chef::DelayedEvaluator.new(&block)
|
||||
end
|
||||
|
||||
def included(klass)
|
||||
super
|
||||
klass.extend(ClassMethods)
|
||||
end
|
||||
end
|
||||
|
||||
extend ClassMethods
|
||||
end
|
||||
end
|
||||
end
|
@ -1,163 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
require 'chef/resource'
|
||||
|
||||
require 'poise/utils/resource_provider_mixin'
|
||||
|
||||
|
||||
module Poise
|
||||
module Helpers
|
||||
# A resource and provider mixin to add back some compatability with Chef's
|
||||
# LWRPBase classes.
|
||||
#
|
||||
# @since 1.0.0
|
||||
module LWRPPolyfill
|
||||
include Poise::Utils::ResourceProviderMixin
|
||||
|
||||
# Provide default_action and actions like LWRPBase but better equipped for subclassing.
|
||||
module Resource
|
||||
def initialize(*args)
|
||||
super
|
||||
# Try to not stomp on stuff if already set in a parent. Coerce @action
|
||||
# to an array because this behavior may change in the future in Chef.
|
||||
@action = self.class.default_action if Array(@action) == [:nothing]
|
||||
(@allowed_actions << self.class.actions).flatten!.uniq!
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
# @overload default_action()
|
||||
# Get the default action for this resource class. If no explicit
|
||||
# default is set, the first action in the list will be used.
|
||||
# @see #actions
|
||||
# @return [Array<Symbol>]
|
||||
# @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<Symbol>] Name of the action(s).
|
||||
# @return [Array<Symbol>]
|
||||
# @example
|
||||
# class MyApp < Chef::Resource
|
||||
# include Poise
|
||||
# default_action(:install)
|
||||
# end
|
||||
def default_action(name=nil)
|
||||
if name
|
||||
name = Array(name).flatten.map(&:to_sym)
|
||||
@default_action = name
|
||||
actions(*name)
|
||||
end
|
||||
if @default_action
|
||||
@default_action
|
||||
elsif respond_to?(:superclass) && superclass != Chef::Resource && superclass.respond_to?(:default_action) && superclass.default_action && Array(superclass.default_action) != %i{nothing}
|
||||
superclass.default_action
|
||||
elsif first_non_nothing = actions.find {|action| action != :nothing }
|
||||
[first_non_nothing]
|
||||
else
|
||||
%i{nothing}
|
||||
end
|
||||
end
|
||||
|
||||
# @overload actions()
|
||||
# Get all actions allowed for this resource class. This includes
|
||||
# any actions allowed on parent classes.
|
||||
# @return [Array<Symbol>]
|
||||
# @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<Symbol>] One or more actions to set.
|
||||
# @return [Array<Symbol>]
|
||||
# @example
|
||||
# class MyApp < Chef::Resource
|
||||
# include Poise
|
||||
# actions(:install, :uninstall)
|
||||
# end
|
||||
def actions(*names)
|
||||
@actions ||= ( respond_to?(:superclass) && superclass.respond_to?(:actions) && superclass.actions.dup ) || ( respond_to?(:superclass) && superclass != Chef::Resource && superclass.respond_to?(:allowed_actions) && superclass.allowed_actions.dup ) || []
|
||||
(@actions << names).tap {|actions| actions.flatten!; actions.uniq! }
|
||||
end
|
||||
|
||||
# Create a resource property (née attribute) on this resource class.
|
||||
# This follows the same usage as the helper of the same name in Chef
|
||||
# LWRPs.
|
||||
#
|
||||
# @param name [Symbol] Name of the property.
|
||||
# @param opts [Hash<Symbol, Object>] Validation options and flags.
|
||||
# @return [void]
|
||||
# @example
|
||||
# class MyApp < Chef::Resource
|
||||
# include Poise
|
||||
# attribute(:path, name_attribute: true)
|
||||
# attribute(:port, kind_of: Integer, default: 8080)
|
||||
# end
|
||||
def attribute(name, opts={})
|
||||
# Freeze the default value. This is done upstream too in Chef 12.5+.
|
||||
opts[:default].freeze if opts && opts[:default]
|
||||
# Ruby 1.8 can go to hell.
|
||||
define_method(name) do |arg=nil, &block|
|
||||
arg = block if arg.nil? # Try to allow passing either.
|
||||
set_or_return(name, arg, opts)
|
||||
end
|
||||
end
|
||||
|
||||
# For forward compat with Chef 12.5+.
|
||||
alias_method :property, :attribute
|
||||
|
||||
def included(klass)
|
||||
super
|
||||
klass.extend(ClassMethods)
|
||||
end
|
||||
end
|
||||
|
||||
extend ClassMethods
|
||||
end
|
||||
|
||||
# Helper to handle load_current_resource for direct subclasses of Provider
|
||||
module Provider
|
||||
module LoadCurrentResource
|
||||
def load_current_resource
|
||||
@current_resource = if new_resource
|
||||
new_resource.class.new(new_resource.name, run_context)
|
||||
else
|
||||
# Better than nothing, subclass can overwrite anyway.
|
||||
Chef::Resource.new(nil, run_context)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# @!classmethods
|
||||
module ClassMethods
|
||||
def included(klass)
|
||||
super
|
||||
klass.extend(ClassMethods)
|
||||
|
||||
# Mask Chef::Provider#load_current_resource because it throws NotImplementedError.
|
||||
if klass.is_a?(Class) && klass.superclass == Chef::Provider
|
||||
klass.send(:include, LoadCurrentResource)
|
||||
end
|
||||
|
||||
# Reinstate the Chef DSL, removed in Chef 12.
|
||||
klass.send(:include, Chef::DSL::Recipe)
|
||||
end
|
||||
end
|
||||
|
||||
extend ClassMethods
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,78 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
require 'poise/helpers/subcontext_block'
|
||||
require 'poise/subcontext/runner'
|
||||
|
||||
|
||||
module Poise
|
||||
module Helpers
|
||||
# A provider mixin to provide #notifying_block, a scoped form of Chef's
|
||||
# use_inline_resources.
|
||||
#
|
||||
# @since 1.0.0
|
||||
# @example
|
||||
# class MyProvider < Chef::Provider
|
||||
# include Chef::Helpers::NotifyingBlock
|
||||
#
|
||||
# def action_run
|
||||
# notifying_block do
|
||||
# template '/etc/myapp.conf' do
|
||||
# # ...
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
module NotifyingBlock
|
||||
include Poise::Helpers::SubcontextBlock
|
||||
|
||||
private
|
||||
|
||||
# Create and converge a subcontext for the recipe DSL. This is similar to
|
||||
# Chef's use_inline_resources but is scoped to a block. All DSL resources
|
||||
# declared inside the block will be converged when the block returns, and
|
||||
# the updated_by_last_action flag will be set if any of the inner
|
||||
# resources are updated.
|
||||
#
|
||||
# @api public
|
||||
# @param block [Proc] Block to run in the subcontext.
|
||||
# @return [void]
|
||||
# @example
|
||||
# def action_run
|
||||
# notifying_block do
|
||||
# template '/etc/myapp.conf' do
|
||||
# # ...
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
def notifying_block(&block)
|
||||
# Make sure to mark the resource as updated-by-last-action if
|
||||
# any sub-run-context resources were updated (any actual
|
||||
# actions taken against the system) during the
|
||||
# sub-run-context convergence.
|
||||
begin
|
||||
subcontext = subcontext_block(&block)
|
||||
# Converge the new context.
|
||||
Poise::Subcontext::Runner.new(new_resource, subcontext).converge
|
||||
ensure
|
||||
new_resource.updated_by_last_action(
|
||||
subcontext && subcontext.resource_collection.any?(&:updated?)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,142 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
require 'chef/mash'
|
||||
|
||||
require 'poise/error'
|
||||
|
||||
|
||||
module Poise
|
||||
module Helpers
|
||||
# A resource mixin to add a new kind of attribute, an option collector.
|
||||
# These attributes can act as mini-DSLs for things which would otherwise be
|
||||
# key/value pairs.
|
||||
#
|
||||
# @since 1.0.0
|
||||
# @example Defining an option collector
|
||||
# class MyResource < Chef::Resource
|
||||
# include Poise::Helpers::OptionCollector
|
||||
# attribute(:my_options, option_collector: true)
|
||||
# end
|
||||
# @example Using an option collector
|
||||
# my_resource 'name' do
|
||||
# my_options do
|
||||
# key1 'value1'
|
||||
# key2 'value2'
|
||||
# end
|
||||
# end
|
||||
module OptionCollector
|
||||
# Instance context used to eval option blocks.
|
||||
# @api private
|
||||
class OptionEvalContext
|
||||
attr_reader :_options
|
||||
|
||||
def initialize(parent, forced_keys)
|
||||
@parent = parent
|
||||
@forced_keys = forced_keys
|
||||
@_options = {}
|
||||
end
|
||||
|
||||
def method_missing(method_sym, *args, &block)
|
||||
# Deal with forced keys.
|
||||
if @forced_keys.include?(method_sym)
|
||||
@_options[method_sym] = args.first || block if !args.empty? || block
|
||||
return @_options[method_sym]
|
||||
end
|
||||
# Try the resource context.
|
||||
@parent.send(method_sym, *args, &block)
|
||||
rescue NameError
|
||||
# Even though method= in the block will set a variable instead of
|
||||
# calling method_missing, still try to cope in case of self.method=.
|
||||
method_sym = method_sym.to_s.chomp('=').to_sym
|
||||
if !args.empty? || block
|
||||
@_options[method_sym] = args.first || block
|
||||
elsif !@_options.include?(method_sym)
|
||||
# We haven't seen this name before, re-raise the NameError.
|
||||
raise
|
||||
end
|
||||
@_options[method_sym]
|
||||
end
|
||||
end
|
||||
|
||||
# @!classmethods
|
||||
module ClassMethods
|
||||
# Override the normal #attribute() method to support defining option
|
||||
# collectors too.
|
||||
def attribute(name, options={})
|
||||
# If present but false-y, make sure it is removed anyway so it
|
||||
# doesn't confuse ParamsValidate.
|
||||
if options.delete(:option_collector)
|
||||
option_collector_attribute(name, options)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
# Define an option collector attribute. Normally used via {.attribute}.
|
||||
#
|
||||
# @param name [String, Symbol] Name of the attribute to define.
|
||||
# @param default [Hash] Default value for the options.
|
||||
# @param parser [Proc, Symbol] Optional parser method. If a symbol it is
|
||||
# called as a method on self. Takes a non-hash value and returns a
|
||||
# hash of its parsed representation.
|
||||
# @param forced_keys [Array<Symbol>, Set<Symbol>] 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}"
|
||||
|
||||
value = instance_variable_get(iv_sym) || begin
|
||||
default = instance_eval(&default) if default.is_a?(Chef::DelayedEvaluator) # Handle lazy{}
|
||||
Mash.new(default) # Wrap in a mash because fuck str vs sym.
|
||||
end
|
||||
if arg
|
||||
if !arg.is_a?(Hash) && parser
|
||||
arg = case parser
|
||||
when Proc
|
||||
instance_exec(arg, &parser)
|
||||
when Symbol
|
||||
send(parser, arg)
|
||||
end
|
||||
end
|
||||
raise Exceptions::ValidationFailed, "Option #{name} must be a Hash" if !arg.is_a?(Hash)
|
||||
# Should this and the update below be a deep merge?
|
||||
value.update(arg)
|
||||
end
|
||||
if block
|
||||
ctx = OptionEvalContext.new(self, forced_keys)
|
||||
ctx.instance_exec(&block)
|
||||
value.update(ctx._options)
|
||||
end
|
||||
instance_variable_set(iv_sym, value)
|
||||
value
|
||||
end
|
||||
end
|
||||
|
||||
def included(klass)
|
||||
super
|
||||
klass.extend(ClassMethods)
|
||||
end
|
||||
end
|
||||
|
||||
extend ClassMethods
|
||||
end
|
||||
end
|
||||
end
|
@ -1,72 +0,0 @@
|
||||
#
|
||||
# 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
|
@ -1,107 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
require 'chef/mixin/convert_to_class_name'
|
||||
|
||||
|
||||
module Poise
|
||||
module Helpers
|
||||
# A resource mixin to automatically set @resource_name.
|
||||
#
|
||||
# @since 1.0.0
|
||||
# @example
|
||||
# class MyResource < Chef::Resource
|
||||
# include Poise::Helpers::ResourceName
|
||||
# provides(:my_resource)
|
||||
# end
|
||||
module ResourceName
|
||||
def initialize(*args)
|
||||
super
|
||||
# If provides() was explicitly set, unconditionally set @resource_name.
|
||||
# This helps when subclassing core Chef resources which set it
|
||||
# themselves in #initialize.
|
||||
if self.class.resource_name(false)
|
||||
@resource_name = self.class.resource_name
|
||||
else
|
||||
@resource_name ||= self.class.resource_name
|
||||
end
|
||||
end
|
||||
|
||||
# @!classmethods
|
||||
module ClassMethods
|
||||
# Set the DSL name for the the resource class.
|
||||
#
|
||||
# @param name [Symbol] Name of the resource.
|
||||
# @return [void]
|
||||
# @example
|
||||
# class MyResource < Chef::Resource
|
||||
# include Poise::Resource::ResourceName
|
||||
# provides(:my_resource)
|
||||
# end
|
||||
def provides(name, *args, &block)
|
||||
# Patch self.constantize so this can cope with anonymous classes.
|
||||
# This does require that the anonymous class define self.name though.
|
||||
if self.name && respond_to?(:constantize)
|
||||
old_constantize = instance_method(:constantize)
|
||||
define_singleton_method(:constantize) do |const_name|
|
||||
( const_name == self.name ) ? self : old_constantize.bind(self).call(const_name)
|
||||
end
|
||||
end
|
||||
# Store the name for later.
|
||||
@provides_name ||= name
|
||||
# Call the original if present. The defined? is for old Chef.
|
||||
super(name, *args, &block) if defined?(super)
|
||||
end
|
||||
|
||||
# Retreive the DSL name for the resource class. If not set explicitly
|
||||
# via {provides} this will try to auto-detect based on the class name.
|
||||
#
|
||||
# @param auto [Boolean] Try to auto-detect based on class name.
|
||||
# @return [Symbol]
|
||||
def resource_name(auto=true)
|
||||
# In 12.4+ we need to proxy through the super class for setting.
|
||||
return super(auto) if defined?(super) && (auto.is_a?(Symbol) || auto.is_a?(String))
|
||||
return @provides_name unless auto
|
||||
@provides_name || if name
|
||||
mode = if name.start_with?('Chef::Resource')
|
||||
[name, 'Chef::Resource']
|
||||
else
|
||||
[name.split('::').last]
|
||||
end
|
||||
Chef::Mixin::ConvertToClassName.convert_to_snake_case(*mode).to_sym
|
||||
elsif defined?(super)
|
||||
# No name on 12.4+ probably means this is an LWRP, use super().
|
||||
super()
|
||||
end
|
||||
end
|
||||
|
||||
# Used by Resource#to_text to find the human name for the resource.
|
||||
#
|
||||
# @api private
|
||||
def dsl_name
|
||||
resource_name.to_s
|
||||
end
|
||||
|
||||
def included(klass)
|
||||
super
|
||||
klass.extend(ClassMethods)
|
||||
end
|
||||
end
|
||||
|
||||
extend ClassMethods
|
||||
end
|
||||
end
|
||||
end
|
@ -1,82 +0,0 @@
|
||||
#
|
||||
# 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<Symbol>]
|
||||
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
|
@ -1,72 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
require 'poise/subcontext/resource_collection'
|
||||
|
||||
|
||||
module Poise
|
||||
module Helpers
|
||||
# A provider mixin to help with creating subcontexts. Mostly for internal
|
||||
# use within Poise.
|
||||
#
|
||||
# @since 1.0.0
|
||||
module SubcontextBlock
|
||||
private
|
||||
|
||||
def subcontext_block(parent_context=nil, &block)
|
||||
# Setup a subcontext.
|
||||
parent_context ||= @run_context
|
||||
sub_run_context = parent_context.dup
|
||||
# Reset state for the subcontext. In 12.4+ this uses the built-in
|
||||
# support, otherwise do it manually.
|
||||
if defined?(sub_run_context.initialize_child_state)
|
||||
sub_run_context.initialize_child_state
|
||||
else
|
||||
# Audits was added in 12.1 I think.
|
||||
sub_run_context.audits = {} if defined?(sub_run_context.audits)
|
||||
# Dup and clear to preserve the default behavior without copy-pasta.
|
||||
sub_run_context.immediate_notification_collection = parent_context.immediate_notification_collection.dup.clear
|
||||
sub_run_context.delayed_notification_collection = parent_context.delayed_notification_collection.dup.clear
|
||||
end
|
||||
# Create the subcollection.
|
||||
sub_run_context.resource_collection = Poise::Subcontext::ResourceCollection.new(parent_context.resource_collection)
|
||||
# Create an accessor for the parent run context.
|
||||
sub_run_context.define_singleton_method(:parent_run_context) { parent_context }
|
||||
|
||||
# Declare sub-resources within the sub-run-context. Since they
|
||||
# are declared here, they do not pollute the parent run-context.
|
||||
begin
|
||||
outer_run_context = @run_context
|
||||
@run_context = sub_run_context
|
||||
instance_eval(&block)
|
||||
ensure
|
||||
@run_context = outer_run_context
|
||||
end
|
||||
|
||||
# Return the inner context to do other things with
|
||||
sub_run_context
|
||||
end
|
||||
|
||||
def global_resource_collection
|
||||
collection = @run_context.resource_collection
|
||||
while collection.respond_to?(:parent) && collection.parent
|
||||
collection = collection.parent
|
||||
end
|
||||
collection
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,29 +0,0 @@
|
||||
#
|
||||
# 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 Helpers
|
||||
# Mixins and helpers for managing subresources, resources with a
|
||||
# parent/child relationship.
|
||||
#
|
||||
# @since 2.0.0
|
||||
module Subresources
|
||||
autoload :Child, 'poise/helpers/subresources/child'
|
||||
autoload :Container, 'poise/helpers/subresources/container'
|
||||
end
|
||||
end
|
||||
end
|
@ -1,276 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
require 'chef/resource'
|
||||
|
||||
require 'poise/error'
|
||||
require 'poise/helpers/subresources/default_containers'
|
||||
|
||||
|
||||
module Poise
|
||||
module Helpers
|
||||
module Subresources
|
||||
# A resource mixin for child subresources.
|
||||
#
|
||||
# @since 1.0.0
|
||||
module Child
|
||||
# Little class used to fix up the display of subresources in #to_text.
|
||||
# Without this you get the full parent resource shown for @parent et al.
|
||||
# @api private
|
||||
class ParentRef
|
||||
attr_accessor :resource
|
||||
|
||||
def initialize(resource)
|
||||
@resource = resource
|
||||
end
|
||||
|
||||
def inspect
|
||||
to_text
|
||||
end
|
||||
|
||||
def to_text
|
||||
if @resource.nil?
|
||||
'nil'
|
||||
else
|
||||
@resource.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# @overload parent()
|
||||
# Get the parent resource for this child. This may be nil if the
|
||||
# resource is set to parent_optional = true.
|
||||
# @return [Chef::Resource, nil]
|
||||
# @overload parent(val)
|
||||
# Set the parent resource. The parent can be set as resource
|
||||
# object, a string (either a bare resource name or a type[name]
|
||||
# string), or a type:name hash.
|
||||
# @param val [String, Hash, Chef::Resource] Parent resource to set.
|
||||
# @return [Chef::Resource, nil]
|
||||
def parent(*args)
|
||||
# Lie about this method if the parent type is true.
|
||||
if self.class.parent_type == true
|
||||
raise NoMethodError.new("undefined method `parent' for #{self}")
|
||||
end
|
||||
_parent(:parent, self.class.parent_type, self.class.parent_optional, self.class.parent_auto, self.class.parent_default, *args)
|
||||
end
|
||||
|
||||
# Register ourself with parents in case this is not a nested resource.
|
||||
#
|
||||
# @api private
|
||||
def after_created
|
||||
super
|
||||
self.class.parent_attributes.each_key do |name|
|
||||
parent = self.send(name)
|
||||
parent.register_subresource(self) if parent && parent.respond_to?(:register_subresource)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Generic form of the parent getter/setter.
|
||||
#
|
||||
# @since 2.0.0
|
||||
# @see #parent
|
||||
def _parent(name, parent_type, parent_optional, parent_auto, parent_default, *args)
|
||||
# Allow using a DSL symbol as the parent type.
|
||||
if parent_type.is_a?(Symbol)
|
||||
parent_type = Chef::Resource.resource_for_node(parent_type, node)
|
||||
end
|
||||
# Grab the ivar for local use.
|
||||
parent_ref = instance_variable_get(:"@#{name}")
|
||||
if !args.empty?
|
||||
val = args.first
|
||||
if val.nil?
|
||||
# Unsetting the parent.
|
||||
parent = parent_ref = nil
|
||||
else
|
||||
if val.is_a?(String) && !val.include?('[')
|
||||
raise Poise::Error.new("Cannot use a string #{name} without defining a parent type") if parent_type == Chef::Resource
|
||||
# Try to find the most recent instance of parent_type with a
|
||||
# matching name. This takes subclassing parent_type into account.
|
||||
found_val = nil
|
||||
iterator = run_context.resource_collection.respond_to?(:recursive_each) ? :recursive_each : :each
|
||||
# This will find the last matching value due to overwriting
|
||||
# found_val as it goes. Will be the nearest match.
|
||||
run_context.resource_collection.public_send(iterator) do |res|
|
||||
found_val = res if res.is_a?(parent_type) && res.name == val
|
||||
end
|
||||
# If found_val is nil, fall back to using lookup even though
|
||||
# it won't work with subclassing, better than nothing?
|
||||
val = found_val || "#{parent_type.resource_name}[#{val}]"
|
||||
end
|
||||
if val.is_a?(String) || val.is_a?(Hash)
|
||||
parent = @run_context.resource_collection.find(val)
|
||||
else
|
||||
parent = val
|
||||
end
|
||||
if !parent.is_a?(parent_type)
|
||||
raise Poise::Error.new("Parent resource is not an instance of #{parent_type.name}: #{val.inspect}")
|
||||
end
|
||||
parent_ref = ParentRef.new(parent)
|
||||
end
|
||||
elsif !parent_ref || !parent_ref.resource
|
||||
if parent_default
|
||||
parent = if parent_default.is_a?(Chef::DelayedEvaluator)
|
||||
instance_eval(&parent_default)
|
||||
else
|
||||
parent_default
|
||||
end
|
||||
end
|
||||
# The @parent_ref means we won't run this if we previously set
|
||||
# ParentRef.new(nil). This means auto-lookup only happens during
|
||||
# after_created.
|
||||
if !parent && !parent_ref && parent_auto
|
||||
# Automatic sibling lookup for sequential composition.
|
||||
# Find the last instance of the parent class as the default parent.
|
||||
# This is super flaky and should only be a last resort.
|
||||
parent = Poise::Helpers::Subresources::DefaultContainers.find(parent_type, run_context, self_resource: self)
|
||||
end
|
||||
# Can't find a valid parent, if it wasn't optional raise an error.
|
||||
raise Poise::Error.new("No #{name} found for #{self}") unless parent || parent_optional
|
||||
parent_ref = ParentRef.new(parent)
|
||||
else
|
||||
parent = parent_ref.resource
|
||||
end
|
||||
raise Poise::Error.new("Cannot set the #{name} of #{self} to itself") if parent.equal?(self)
|
||||
# Store the ivar back.
|
||||
instance_variable_set(:"@#{name}", parent_ref)
|
||||
# Return the actual resource.
|
||||
parent
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
# @overload parent_type()
|
||||
# Get the class of the default parent link on this resource.
|
||||
# @return [Class, Symbol]
|
||||
# @overload parent_type(type)
|
||||
# Set the class of the default parent link on this resource.
|
||||
# @param type [Class, Symbol] Class to set.
|
||||
# @return [Class, Symbol]
|
||||
def parent_type(type=nil)
|
||||
if type
|
||||
raise Poise::Error.new("Parent type must be a class, symbol, or true, got #{type.inspect}") unless type.is_a?(Class) || type.is_a?(Symbol) || type == true
|
||||
# Setting to true shouldn't actually do anything if a type was already set.
|
||||
@parent_type = type unless type == true && !@parent_type.nil?
|
||||
end
|
||||
# First ancestor_send looks for a non-true && non-default value,
|
||||
# second one is to check for default vs true if no real value is found.
|
||||
@parent_type || Poise::Utils.ancestor_send(self, :parent_type, ignore: [Chef::Resource, true]) || Poise::Utils.ancestor_send(self, :parent_type, default: Chef::Resource)
|
||||
end
|
||||
|
||||
# @overload parent_optional()
|
||||
# Get the optional mode for the default parent link on this resource.
|
||||
# @return [Boolean]
|
||||
# @overload parent_optional(val)
|
||||
# Set the optional mode for the default parent link on this resource.
|
||||
# @param val [Boolean] Mode to set.
|
||||
# @return [Boolean]
|
||||
def parent_optional(val=nil)
|
||||
unless val.nil?
|
||||
@parent_optional = val
|
||||
end
|
||||
if @parent_optional.nil?
|
||||
Poise::Utils.ancestor_send(self, :parent_optional, default: false)
|
||||
else
|
||||
@parent_optional
|
||||
end
|
||||
end
|
||||
|
||||
# @overload parent_auto()
|
||||
# Get the auto-detect mode for the default parent link on this resource.
|
||||
# @return [Boolean]
|
||||
# @overload parent_auto(val)
|
||||
# Set the auto-detect mode for the default parent link on this resource.
|
||||
# @param val [Boolean] Mode to set.
|
||||
# @return [Boolean]
|
||||
def parent_auto(val=nil)
|
||||
unless val.nil?
|
||||
@parent_auto = val
|
||||
end
|
||||
if @parent_auto.nil?
|
||||
Poise::Utils.ancestor_send(self, :parent_auto, default: true)
|
||||
else
|
||||
@parent_auto
|
||||
end
|
||||
end
|
||||
|
||||
# @overload parent_default()
|
||||
# Get the default value for the default parent link on this resource.
|
||||
# @since 2.3.0
|
||||
# @return [Object, Chef::DelayedEvaluator]
|
||||
# @overload parent_default(val)
|
||||
# Set the default value for the default parent link on this resource.
|
||||
# @since 2.3.0
|
||||
# @param val [Object, Chef::DelayedEvaluator] Default value to set.
|
||||
# @return [Object, Chef::DelayedEvaluator]
|
||||
def parent_default(*args)
|
||||
unless args.empty?
|
||||
@parent_default = args.first
|
||||
end
|
||||
if defined?(@parent_default)
|
||||
@parent_default
|
||||
else
|
||||
Poise::Utils.ancestor_send(self, :parent_default)
|
||||
end
|
||||
end
|
||||
|
||||
# Create a new kind of parent link.
|
||||
#
|
||||
# @since 2.0.0
|
||||
# @param name [Symbol] Name of the relationship. This becomes a method
|
||||
# name on the resource instance.
|
||||
# @param type [Class] Class of the parent.
|
||||
# @param optional [Boolean] If the parent is optional.
|
||||
# @param auto [Boolean] If the parent is auto-detected.
|
||||
# @return [void]
|
||||
def parent_attribute(name, type: Chef::Resource, optional: false, auto: true, default: nil)
|
||||
name = :"parent_#{name}"
|
||||
(@parent_attributes ||= {})[name] = type
|
||||
define_method(name) do |*args|
|
||||
_parent(name, type, optional, auto, default, *args)
|
||||
end
|
||||
end
|
||||
|
||||
# Return the name of all parent relationships on this class.
|
||||
#
|
||||
# @since 2.0.0
|
||||
# @return [Hash<Symbol, Class>]
|
||||
def parent_attributes
|
||||
{}.tap do |attrs|
|
||||
# Grab superclass's attributes if possible.
|
||||
attrs.update(Poise::Utils.ancestor_send(self, :parent_attributes, default: {}))
|
||||
# Local default parent.
|
||||
attrs[:parent] = parent_type
|
||||
# Extra locally defined parents.
|
||||
attrs.update(@parent_attributes) if @parent_attributes
|
||||
# Remove anything with the type set to true.
|
||||
attrs.reject! {|name, type| type == true }
|
||||
end
|
||||
end
|
||||
|
||||
# @api private
|
||||
def included(klass)
|
||||
super
|
||||
klass.extend(ClassMethods)
|
||||
end
|
||||
end
|
||||
|
||||
extend ClassMethods
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,229 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
require 'chef/dsl/recipe'
|
||||
|
||||
require 'poise/helpers/subcontext_block'
|
||||
require 'poise/helpers/subresources/default_containers'
|
||||
|
||||
|
||||
module Poise
|
||||
module Helpers
|
||||
module Subresources
|
||||
# A resource mixin for subresource containers.
|
||||
#
|
||||
# @since 1.0.0
|
||||
module Container
|
||||
# A resource collection that has much more condensed text output. This
|
||||
# is used to show the value of @subresources during Chef's error formatting.
|
||||
# @api private
|
||||
class NoPrintingResourceCollection < Chef::ResourceCollection
|
||||
def inspect
|
||||
to_text
|
||||
end
|
||||
|
||||
def to_text
|
||||
"[#{all_resources.map(&:to_s).join(', ')}]"
|
||||
end
|
||||
end
|
||||
|
||||
include SubcontextBlock
|
||||
include Chef::DSL::Recipe
|
||||
|
||||
attr_reader :subresources
|
||||
attr_reader :subcontexts
|
||||
|
||||
def initialize(*args)
|
||||
super
|
||||
@subresources = NoPrintingResourceCollection.new
|
||||
@subcontexts = []
|
||||
end
|
||||
|
||||
def after_created
|
||||
super
|
||||
# Register as a default container if needed.
|
||||
Poise::Helpers::Subresources::DefaultContainers.register!(self, run_context) if self.class.container_default
|
||||
# Add all internal subresources to the resource collection.
|
||||
unless @subresources.empty?
|
||||
Chef::Log.debug("[#{self}] Adding subresources to collection:")
|
||||
# Because after_create is run before adding the container to the resource collection
|
||||
# we need to jump through some hoops to get it swapped into place.
|
||||
self_ = self
|
||||
order_fixer = Chef::Resource::RubyBlock.new('subresource_order_fixer', @run_context)
|
||||
# respond_to? is for <= 12.0.2, remove some day when I stop caring.
|
||||
order_fixer.declared_type = 'ruby_block' if order_fixer.respond_to?(:declared_type=)
|
||||
order_fixer.block do
|
||||
Chef::Log.debug("[#{self_}] Running order fixer")
|
||||
collection = self_.run_context.resource_collection
|
||||
# Delete the current container resource from its current position.
|
||||
collection.all_resources.delete(self_)
|
||||
# Replace the order fixer with the container so it runs before all
|
||||
# subresources.
|
||||
collection.all_resources[collection.iterator.position] = self_
|
||||
# Hack for Chef 11 to reset the resources_by_name position too.
|
||||
# @todo Remove this when I drop support for Chef 11.
|
||||
if resources_by_name = collection.instance_variable_get(:@resources_by_name)
|
||||
resources_by_name[self_.to_s] = collection.iterator.position
|
||||
end
|
||||
# Step back so we re-run the "current" resource, which is now the
|
||||
# container.
|
||||
collection.iterator.skip_back
|
||||
Chef::Log.debug("Collection: #{@run_context.resource_collection.map(&:to_s).join(', ')}")
|
||||
end
|
||||
@run_context.resource_collection.insert(order_fixer)
|
||||
@subcontexts.each do |ctx|
|
||||
# Copy all resources to the outer context.
|
||||
ctx.resource_collection.each do |r|
|
||||
Chef::Log.debug(" * #{r}")
|
||||
# Fix the subresource to use the outer run context.
|
||||
r.run_context = @run_context
|
||||
@run_context.resource_collection.insert(r)
|
||||
end
|
||||
# Copy all notifications to the outer context.
|
||||
%w{immediate delayed}.each do |notification_type|
|
||||
ctx.send(:"#{notification_type}_notification_collection").each do |key, notifications|
|
||||
notifications.each do |notification|
|
||||
parent_notifications = @run_context.send(:"#{notification_type}_notification_collection")[key]
|
||||
unless parent_notifications.any? { |existing_notification| existing_notification.duplicates?(notification) }
|
||||
parent_notifications << notification
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Chef::Log.debug("Collection: #{@run_context.resource_collection.map(&:to_s).join(', ')}")
|
||||
end
|
||||
end
|
||||
|
||||
def declare_resource(type, name, created_at=nil, &block)
|
||||
Chef::Log.debug("[#{self}] Creating subresource from #{type}(#{name})")
|
||||
self_ = self
|
||||
# Used to break block context, non-local return from subcontext_block.
|
||||
resource = []
|
||||
# Grab the caller so we can make the subresource look like it comes from
|
||||
# correct place.
|
||||
created_at ||= caller[0]
|
||||
# Run this inside a subcontext to avoid adding to the current resource collection.
|
||||
# It will end up added later, indirected via @subresources to ensure ordering.
|
||||
@subcontexts << subcontext_block do
|
||||
namespace = if self.class.container_namespace == true
|
||||
# If the value is true, use the name of the container resource.
|
||||
self.name
|
||||
elsif self.class.container_namespace.is_a?(Proc)
|
||||
instance_eval(&self.class.container_namespace)
|
||||
else
|
||||
self.class.container_namespace
|
||||
end
|
||||
sub_name = if name && !name.empty?
|
||||
if namespace
|
||||
"#{namespace}::#{name}"
|
||||
else
|
||||
name
|
||||
end
|
||||
else
|
||||
# If you pass in nil or '', you just get the namespace or parent name.
|
||||
namespace || self.name
|
||||
end
|
||||
resource << super(type, sub_name, created_at) do
|
||||
# Apply the correct parent before anything else so it is available
|
||||
# in after_created for the subresource. It might raise
|
||||
# NoMethodError is there isn't a real parent.
|
||||
begin
|
||||
parent(self_) if respond_to?(:parent)
|
||||
rescue NoMethodError
|
||||
# This space left intentionally blank.
|
||||
end
|
||||
# Run the resource block.
|
||||
instance_exec(&block) if block
|
||||
end
|
||||
end
|
||||
# Try and add to subresources. For normal subresources this is handled
|
||||
# in the after_created.
|
||||
register_subresource(resource.first) if resource.first
|
||||
# Return whatever we have
|
||||
resource.first
|
||||
end
|
||||
|
||||
# Register a resource as part of this container. Returns true if the
|
||||
# resource was added to the collection and false if it was already
|
||||
# known.
|
||||
#
|
||||
# @note Return value added in 2.4.0.
|
||||
# @return [Boolean]
|
||||
def register_subresource(resource)
|
||||
subresources.lookup(resource)
|
||||
false
|
||||
rescue Chef::Exceptions::ResourceNotFound
|
||||
Chef::Log.debug("[#{self}] Adding #{resource} to subresources")
|
||||
subresources.insert(resource)
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Thanks Array.flatten, big help you are. Specifically the
|
||||
# method_missing in the recipe DSL will make a flatten on an array of
|
||||
# resources fail, so make this safe.
|
||||
def to_ary
|
||||
nil
|
||||
end
|
||||
|
||||
# @!classmethods
|
||||
module ClassMethods
|
||||
def container_namespace(val=nil)
|
||||
@container_namespace = val unless val.nil?
|
||||
if @container_namespace.nil?
|
||||
# Not set here, look at the superclass or true by default for backwards compat.
|
||||
Poise::Utils.ancestor_send(self, :container_namespace, default: true)
|
||||
else
|
||||
@container_namespace
|
||||
end
|
||||
end
|
||||
|
||||
# @overload container_default()
|
||||
# Get the default mode for this resource. If false, this resource
|
||||
# class will not be used for default container lookups. Defaults to
|
||||
# true.
|
||||
# @since 2.3.0
|
||||
# @return [Boolean]
|
||||
# @overload container_default(val)
|
||||
# Set the default mode for this resource.
|
||||
# @since 2.3.0
|
||||
# @param val [Boolean] Default mode to set.
|
||||
# @return [Boolean]
|
||||
def container_default(val=nil)
|
||||
@container_default = val unless val.nil?
|
||||
if @container_default.nil?
|
||||
# Not set here, look at the superclass or true by default for backwards compat.
|
||||
Poise::Utils.ancestor_send(self, :container_default, default: true)
|
||||
else
|
||||
@container_default
|
||||
end
|
||||
end
|
||||
|
||||
def included(klass)
|
||||
super
|
||||
klass.extend(ClassMethods)
|
||||
klass.const_get(:HIDDEN_IVARS) << :@subcontexts
|
||||
klass.const_get(:FORBIDDEN_IVARS) << :@subcontexts
|
||||
end
|
||||
end
|
||||
|
||||
extend ClassMethods
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user