Set up an instance of Mastodon for Kosmos
Refs #19 Use new application cookbook, update our cookbooks
This commit is contained in:
@@ -1,103 +1,96 @@
|
||||
application Cookbook CHANGELOG
|
||||
=======================
|
||||
This file is used to list changes made in each version of the application cookbook.
|
||||
# Application Changelog
|
||||
|
||||
## v5.1.0
|
||||
|
||||
v4.1.6
|
||||
------
|
||||
- Support for Chef 12.
|
||||
- Add `strict_ssh` option to enable host key checking.
|
||||
- Add `keep_releases` option to control number of releases to keep.
|
||||
- Allow passing a path to a file for `deploy_key`.
|
||||
* Add `application_cookbook_file`, `application_file`, and `application_template resources.
|
||||
|
||||
v4.1.4
|
||||
------
|
||||
### Bug
|
||||
- **[COOK-3343](https://tickets.opscode.com/browse/COOK-3343)** - Can't parse release candidate version number
|
||||
## v5.0.0
|
||||
|
||||
* Massive rewrite on top of newer Chef patterns. See the 5.0 README for details.
|
||||
|
||||
v4.1.2
|
||||
------
|
||||
### Bug
|
||||
- **[COOK-3343](https://tickets.opscode.com/browse/COOK-3343)** - Can't parse release candidate version number
|
||||
## v4.1.6
|
||||
|
||||
* Support for Chef 12.
|
||||
* Add `strict_ssh` option to enable host key checking.
|
||||
* Add `keep_releases` option to control number of releases to keep.
|
||||
* Allow passing a path to a file for `deploy_key`.
|
||||
|
||||
v4.1.0
|
||||
------
|
||||
### Bug
|
||||
- [COOK-3343] - Can't parse release candidate version number
|
||||
## v4.1.4
|
||||
|
||||
* [COOK-3343](https://tickets.opscode.com/browse/COOK-3343) - Can't parse release candidate version number.
|
||||
|
||||
v4.0.0
|
||||
------
|
||||
### Breaking
|
||||
- Removes compatability with Chef 10
|
||||
## v4.1.2
|
||||
|
||||
* [COOK-3343](https://tickets.opscode.com/browse/COOK-3343) - Can't parse release candidate version number.
|
||||
|
||||
## v4.1.0
|
||||
|
||||
* [COOK-3343] - Can't parse release candidate version number.
|
||||
|
||||
## v4.0.0
|
||||
|
||||
* Removes compatability with Chef 10.
|
||||
* [COOK-3564](https://tickets.opscode.com/browse/COOK-3564) - Replace calls to `Chef::Mixin::RecipeDefinitionDSLCore`.
|
||||
|
||||
## v3.0.0
|
||||
|
||||
* [COOK-3306]: Multiple Memory Leaks in Application Cookbook.
|
||||
|
||||
## v2.0.4
|
||||
|
||||
* [COOK-2812]: application cookbook doesn't allow to specify a block as `restart_command`.
|
||||
|
||||
## v2.0.2
|
||||
|
||||
* [COOK-2537]: Provide proper `respond_to` behavior when using `method_missing`.
|
||||
* [COOK-2713]: application resource should Allow sub-resource attributes to propogate up.
|
||||
|
||||
### Improvement
|
||||
- **[COOK-3564](https://tickets.opscode.com/browse/COOK-3564)** - Replace calls to `Chef::Mixin::RecipeDefinitionDSLCore`
|
||||
* [COOK-2597]: Allow customization for `shallow_clone` when doing a git deploy.
|
||||
|
||||
v3.0.0
|
||||
------
|
||||
### Bug
|
||||
- [COOK-3306]: Multiple Memory Leaks in Application Cookbook
|
||||
## v2.0.0
|
||||
|
||||
v2.0.4
|
||||
------
|
||||
### Bug
|
||||
- [COOK-2812]: application cookbook doesn't allow to specify a block as `restart_command`
|
||||
|
||||
v2.0.2
|
||||
------
|
||||
### Bug
|
||||
- [COOK-2537]: Provide proper `respond_to` behavior when using `method_missing`
|
||||
- [COOK-2713]: application resource should Allow sub-resource attributes to propogate up
|
||||
|
||||
### Improvement
|
||||
- [COOK-2597]: Allow customization for `shallow_clone` when doing a git deploy
|
||||
|
||||
v2.0.0
|
||||
------
|
||||
This release is incompatible with previous releases (hence major version change). The recipes used in older versions are deprecated and completely removed. See README.md for further detail.
|
||||
|
||||
- [COOK-1673] - `deploy_revision` in the application cookbook gives an argument error
|
||||
- [COOK-1820] - Application cookbook: remove deprecated recipes
|
||||
* [COOK-1673] - `deploy_revision` in the application cookbook gives an argument error.
|
||||
* [COOK-1820] - Application cookbook: remove deprecated recipes.
|
||||
|
||||
v1.0.4
|
||||
------
|
||||
- [COOK-1567] - Add git submodules to application cookbook
|
||||
## v1.0.4
|
||||
|
||||
v1.0.2
|
||||
------
|
||||
- [COOK-1312] - string callbacks fail with method not found (really included this time)
|
||||
- [COOK-1332] - add `release_path` and `shared_path` methods
|
||||
- [COOK-1333] - add example for running migrations
|
||||
- [COOK-1360] - fix minor typos in README
|
||||
- [COOK-1374] - use runit attributes in unicorn run script
|
||||
* [COOK-1567] - Add git submodules to application cookbook.
|
||||
|
||||
## v1.0.2
|
||||
|
||||
* [COOK-1312] - string callbacks fail with method not found (really included this time).
|
||||
* [COOK-1332] - add `release_path` and `shared_path` methods.
|
||||
* [COOK-1333] - add example for running migrations.
|
||||
* [COOK-1360] - fix minor typos in README.
|
||||
* [COOK-1374] - use runit attributes in unicorn run script.
|
||||
|
||||
## v1.0.0
|
||||
|
||||
v1.0.0
|
||||
------
|
||||
This release introduces the LWRP for application deployment, as well as other improvements. The recipes will be deprecated in August 2012 as indicated by their warning messages and in the README.md.
|
||||
|
||||
- [COOK-634] - Implement LWRP for application deployment
|
||||
- [COOK-1116] - use other SCMs than git
|
||||
- [COOK-1252] - add `:force_deploy` that maps to corresponding action of deploy resource
|
||||
- [COOK-1253] - fix rollback error
|
||||
- [COOK-1312] - string callbacks fail with method not found
|
||||
- [COOK-1313] - implicit file based hooks aren't invoked
|
||||
- [COOK-1318] - Create `to_ary` method to resolve issue in resources() lookup on "application[foo]" resources
|
||||
* [COOK-634] - Implement LWRP for application deployment.
|
||||
* [COOK-1116] - use other SCMs than git.
|
||||
* [COOK-1252] - add `:force_deploy` that maps to corresponding action of deploy resource.
|
||||
* [COOK-1253] - fix rollback error.
|
||||
* [COOK-1312] - string callbacks fail with method not found.
|
||||
* [COOK-1313] - implicit file based hooks aren't invoked.
|
||||
* [COOK-1318] - Create `to_ary` method to resolve issue in resources() lookup on "application[foo]" resources.
|
||||
|
||||
v0.99.14
|
||||
--------
|
||||
- [COOK-1065] - use pip in virtualenv during deploy
|
||||
## v0.99.14
|
||||
|
||||
v0.99.12
|
||||
--------
|
||||
- [COOK-606] application cookbook deployment recipes should use ipaddress instead of fqdn
|
||||
* [COOK-1065] - use pip in virtualenv during deploy.
|
||||
|
||||
v0.99.11
|
||||
--------
|
||||
- make the `_default` `chef_environment` look like production rails env
|
||||
## v0.99.12
|
||||
|
||||
v0.99.10
|
||||
--------
|
||||
- Use Chef 0.10's `node.chef_environment` instead of `node['app_environment']`.
|
||||
* [COOK-606] application cookbook deployment recipes should use ipaddress instead of fqdn.
|
||||
|
||||
## v0.99.11
|
||||
|
||||
* make the `_default` `chef_environment` look like production rails env.
|
||||
|
||||
## v0.99.10
|
||||
|
||||
* Use Chef 0.10's `node.chef_environment` instead of `node['app_environment']`.
|
||||
|
||||
@@ -1,206 +1,259 @@
|
||||
Application cookbook
|
||||
====================
|
||||
This cookbook is designed to be able to describe and deploy web applications. It provides the basic infrastructure; other cookbooks are required to support specific combinations of frameworks and application servers. The following cookbooks are available at this time:
|
||||
# Application cookbook
|
||||
|
||||
- [application_java](https://github.com/opscode-cookbooks/application_java) (Java and Tomcat)
|
||||
- [application_nginx](https://github.com/opscode-cookbooks/application_nginx) (nginx reverse proxy)
|
||||
- [application_php](https://github.com/opscode-cookbooks/application_php) (PHP with `mod_php_apache2`)
|
||||
- [application_python](https://github.com/opscode-cookbooks/application_python) (Django with Gunicorn)
|
||||
- [application_ruby](https://github.com/opscode-cookbooks/application_ruby) (Rails with Passenger or Unicorn)
|
||||
[](https://travis-ci.org/poise/application)
|
||||
[](https://rubygems.org/gems/poise-application)
|
||||
[](https://supermarket.chef.io/cookbooks/application)
|
||||
[](https://codeclimate.com/github/poise/application)
|
||||
[](https://gemnasium.com/poise/application)
|
||||
[](https://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
A [Chef](https://www.chef.io/) cookbook to deploy applications.
|
||||
|
||||
Backwards Compatibility
|
||||
-----------------------
|
||||
- Version 4.0.0 dropped support for Chef 10
|
||||
- Version 2.0.0 dropped support for the `apps` data bag.
|
||||
## Getting Started
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
The previous dependencies have been moved out to the application-stack-specific cookbooks, and this cookbook has no external dependencies.
|
||||
|
||||
|
||||
Resources/Providers
|
||||
-------------------
|
||||
The `application` LWRP configures the basic properties of most applications, regardless of the framework or application server they use. These include:
|
||||
|
||||
- SCM information for the deployment, such as the repository URL and branch name;
|
||||
- deployment destination, including the filesystem path to deploy to;
|
||||
- any OS packages to install as dependencies;
|
||||
- optional callback to control the deployment.
|
||||
|
||||
This LWRP uses the `deploy_revision` LWRP to perform the bulk of its tasks, and many concepts and parameters map directly to it. Check the documentation for `deploy_revision` for more information.
|
||||
|
||||
Configuration of framework-specific aspects of the application are performed by invoking a sub-resource; see the appropriate cookbook for more documentation.
|
||||
|
||||
### Actions
|
||||
- `:deploy`: deploy an application, including any necessary configuration, restarting the associated service if necessary
|
||||
- `:force_deploy`: same as `:deploy`, but it will send a `:force_deploy` action to the deploy resource, directing it to deploy the application even if the same revision is already deployed
|
||||
|
||||
### Attribute Parameters
|
||||
- `name`: name attribute. The name of the application you are setting up. This will be used to derive the default value for other attribute
|
||||
- `packages`: an Array or Hash of packages to be installed before starting the deployment
|
||||
- `path`: target path of the deployment; it will be created if it does not exist
|
||||
- `owner`: the user that shall own the target path
|
||||
- `group`: the group that shall own the target path
|
||||
- `keep_releases`: count of keep releases
|
||||
- `strategy`: the underlying LWRP that will be used to perform the deployment. The default is `:deploy_revision`, and it should never be necessary to change it
|
||||
- `scm_provider`: the provider class to use for the deployment. It defaults to `Chef::Provider::Git`, you can set it to `Chef::Provider::Subversion` to deploy from an SVN repository
|
||||
- `repository`: the URL of the repository the application should be checked out from
|
||||
- `revision`: an identifier pointing to the revision that should be checked out
|
||||
- `deploy_key`: the private key to use to access the repository via SSH, or path to a file containing the key
|
||||
- `rollback_on_error`: if true, exceptions during a deployment will be caught and a clean rollback to the previous version will be attempted; the exception will then be re-raised. Defaults to true; change it only if you know what you are doing
|
||||
- `environment`: a Hash of environment variables to set while running migrations
|
||||
- `purge_before_symlink`: an Array of paths (relative to the checkout) to remove before creating symlinks
|
||||
- `create_dirs_before_symlink`: an Array of paths (relative to the checkout) pointing to directories to create before creating symlinks
|
||||
- `symlinks`: a Hash of shared/dir/path => release/dir/path. It determines which files and dirs in the shared directory get symlinked to the current release directory
|
||||
- `symlink_before_migrate`: similar to symlinks, except that they will be linked before any migration is run
|
||||
- `migrate`: if `true` then migrations will be run; defaults to false
|
||||
- `migration_command`: a command to run to migrate the application from the previous to the current state
|
||||
- `restart_command`: a command to run when restarting the application
|
||||
- `environment_name`: the name of a framework-specific "environment" (for example the Rails environment). By default it is the same as the Chef environment, unless it is `_default`, in which case it is set to `production`
|
||||
- `enable_submodules`: whether to enable git submodules in the deploy, passed into the deploy resource.
|
||||
|
||||
### Callback Attributes
|
||||
You can also set a few attributes on this LWRP that are interpreted as callback to be called at specific points during a deployment. If you pass a block, it will be evaluated within a new context. If you pass a string, it will be interpreted as a path (relative to the release directory) to a file; if it exists, it will be loaded and evaluated as though it were a Chef recipe.
|
||||
|
||||
The following callback attributes are available:
|
||||
|
||||
- `before_deploy`: invoked immediately after initial setup and before the deployment proper is started. This callback will be invoked on every Chef run
|
||||
- `before_migrate`
|
||||
- `before_symlink`
|
||||
- `before_restart`
|
||||
- `after_restart`
|
||||
|
||||
### Sub-resources
|
||||
Anything that is not a known attribute will be interpreted as the name of a sub-resource; the resource will be looked up, and any nested attribute will be passed to it. More than one sub-resource can be added to an application; the order is significant, with the latter sub-resources overriding any sub-resource that comes before.
|
||||
|
||||
Sub-resources can set their own values for some attributes; if they do, they will be merged together with the attribute set on the main resource. The attributes that support this behavior are the following:
|
||||
|
||||
- `environment`: environment variables from the application and from sub-resources will be merged together, with later resources overriding values set in the application or previous resources
|
||||
- `migration_command`: commands from the application and from sub-resources will be concatenated together joined with '&&' and run as a single shell command. The migration will only succeed if all the commands succeed
|
||||
- `restart_command`: commands from the application and from sub-resources will be evaluated in order
|
||||
- `symlink_before_migrate`: will be concatenated as a single array
|
||||
- `callbacks`: sub-resources callbacks will be invoked first, followed by the application callbacks
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
To use the application cookbook we recommend creating a cookbook named after the application, e.g. `my_app`. In `metadata.rb` you should declare a dependency on this cookbook and any framework cookbook the application may need. For example a Rails application may include:
|
||||
The application cookbook provides a central framework to deploy applications
|
||||
using Chef. Generally this will be web applications using things like Rails,
|
||||
Django, or NodeJS, but the framework makes no specific assumptions. The core
|
||||
`application` resource provides DSL support and helpers, but the heavy lifting
|
||||
is all done in specific plugins detailed below. Each deployment starts with
|
||||
an `application` resource:
|
||||
|
||||
```ruby
|
||||
depends 'application'
|
||||
depends 'application_ruby'
|
||||
application '/path/to/deploy' do
|
||||
owner 'root'
|
||||
group 'root'
|
||||
|
||||
# ...
|
||||
end
|
||||
```
|
||||
|
||||
The default recipe should describe your application using the `application` LWRP; you may also include additional recipes, for example to set up a database, queues, search engines and other components of your application.
|
||||
|
||||
A recipe using this LWRP may look like this:
|
||||
The `application` resource uses the Poise subresource system for plugins. This
|
||||
means you configure the steps of the deployment like normal recipe code inside
|
||||
the `application` resource, with a few special additions:
|
||||
|
||||
```ruby
|
||||
application 'my_app' do
|
||||
path '/deploy/to/dir'
|
||||
owner 'app-user'
|
||||
group 'app-group'
|
||||
application '/path/to/deploy' do
|
||||
# Application resource properties.
|
||||
owner 'root'
|
||||
group 'root'
|
||||
|
||||
repository 'http://git.example.com/my-app.git'
|
||||
revision 'production'
|
||||
|
||||
# Apply the rails LWRP from application_ruby
|
||||
rails do
|
||||
# Rails-specific configuration. See the README in the
|
||||
# application_ruby cookbook for more information.
|
||||
# Subresources, like normal recipe code.
|
||||
package 'ruby'
|
||||
git '/path/to/deploy' do
|
||||
repository 'https://github.com/example/myapp.git'
|
||||
end
|
||||
|
||||
# Apply the passenger_apache2 LWRP, also from application_ruby
|
||||
passenger_apache2 do
|
||||
# Passenger-specific configuration.
|
||||
application_rails '/path/to/deploy' do
|
||||
database 'mysql://dbhost/myapp'
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
You can of course use any code necessary to determine the value of attributes:
|
||||
When evaluating the recipe inside the `application` resource, it first checks
|
||||
for `application_#{resource}`, as well as looking for an LWRP of the same name
|
||||
in any cookbook starting with `application_`. This means that a resource named
|
||||
`application_foo` can be used as `foo` inside the `application` resource:
|
||||
|
||||
```ruby
|
||||
application 'my_app' do
|
||||
repository 'http://git.example.com/my-app.git'
|
||||
revision node.chef_environment == 'production' ? 'production' : 'develop'
|
||||
application '/path/to/deploy' do
|
||||
owner 'root'
|
||||
group 'root'
|
||||
|
||||
rails '/path/to/deploy' do
|
||||
database 'mysql://dbhost/myapp'
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
Attributes from the application and from sub-resources are merged together:
|
||||
Additionally if a resource inside the `application` block doesn't have a name,
|
||||
it uses the same name as the application resource itself:
|
||||
|
||||
```ruby
|
||||
application 'my_app' do
|
||||
restart_command 'kill -1 `cat /var/run/one.pid`'
|
||||
environment 'LC_ALL' => 'en', 'FOO' => 'bar'
|
||||
application '/path/to/deploy' do
|
||||
owner 'root'
|
||||
group 'root'
|
||||
|
||||
rails do
|
||||
restart_command 'touch /tmp/something'
|
||||
environment 'LC_ALL' => 'en_US'
|
||||
end
|
||||
|
||||
passenger_apache2 do
|
||||
environment 'FOO' => 'baz'
|
||||
end
|
||||
end
|
||||
|
||||
# at the end, you will have:
|
||||
#
|
||||
# restart_command #=> kill -1 `cat /var/run/one.pid` && touch /tmp/something
|
||||
# environment #=> LC_ALL=en_US FOO=baz
|
||||
```
|
||||
|
||||
Most databases have the concept of migrations (or you can just use your own):
|
||||
|
||||
```ruby
|
||||
application 'my_app' do
|
||||
path '/deploy/to/dir'
|
||||
owner 'app-user'
|
||||
group 'app-group'
|
||||
|
||||
repository 'http://git.example.com/my-app.git'
|
||||
revision 'production'
|
||||
|
||||
php do
|
||||
migrate true
|
||||
migration_command 'your-applications-migrate-command'
|
||||
database 'mysql://dbhost/myapp'
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
This will run `your-applications-migrate-command`, with the current directory set to the directory of the current checkout.
|
||||
Other than those two special features, the recipe code inside the `application`
|
||||
resource is processed just like any other recipe.
|
||||
|
||||
To use the application cookbook, we recommend creating a role named after the application, e.g. `my_app`. Create a Ruby DSL role in your chef-repo, or create the role directly with knife.
|
||||
## Available Plugins
|
||||
|
||||
* [`application_git`](https://github.com/poise/application_git) – Deploy
|
||||
application code from a git repository.
|
||||
* [`application_ruby`](https://github.com/poise/application_ruby) – Manage Ruby
|
||||
deployments, such as Rails or Sinatra applications.
|
||||
* [`application_python`](https://github.com/poise/application_python) – Manage
|
||||
Python deployments, such as Django or Flask applications.
|
||||
* [`application_javascript`](https://github.com/poise/application_javascript) –
|
||||
Manage server-side JavaScript deployments using Node.js or io.js.
|
||||
* `application_java` – *Coming soon!*
|
||||
* `application_go` – *Coming soon!*
|
||||
* `application_erlang` – *Coming soon!*
|
||||
|
||||
## Requirements
|
||||
|
||||
Chef 12 or newer is required.
|
||||
|
||||
## Resources
|
||||
|
||||
### `application`
|
||||
|
||||
The `application` resource has top-level configuration properties for each
|
||||
deployment and acts as a container for other deployment plugin resources.
|
||||
|
||||
```ruby
|
||||
name 'my_app'
|
||||
description 'My application deployment'
|
||||
run_list([
|
||||
'recipe[my_app::default]'
|
||||
])
|
||||
application '/opt/test_sinatra' do
|
||||
git 'https://github.com/example/my_sinatra_app.git'
|
||||
bundle_install do
|
||||
deployment true
|
||||
end
|
||||
unicorn do
|
||||
port 9000
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
License and Authors
|
||||
-------------------
|
||||
- Author: Adam Jacob (<adam@opscode.com>)
|
||||
- Author: Andrea Campi (<andrea.campi@zephirworks.com.com>)
|
||||
- Author: Joshua Timberman (<joshua@opscode.com>)
|
||||
- Author: Noah Kantrowitz (<noah@opscode.com>)
|
||||
- Author: Seth Chisamore (<schisamo@opscode.com>)
|
||||
#### Actions
|
||||
|
||||
```text
|
||||
Copyright 2009-2013, Opscode, Inc.
|
||||
* `:deploy` – Deploy the application. *(default)*
|
||||
* `:start` - Run `:start` on all subresources that support it.
|
||||
* `:stop` - Run `:stop` on all subresources that support it.
|
||||
* `:restart` - Run `:restart` on all subresources that support it.
|
||||
* `:reload` - Run `:reload` on all subresources that support it.
|
||||
|
||||
#### Properties
|
||||
|
||||
* `path` – Path to deploy the application to. *(name attribute)*
|
||||
* `environment` – Environment variables for all application deployment steps.
|
||||
* `group` – System group to deploy the application as.
|
||||
* `owner` – System user to deploy the application as.
|
||||
* `action_on_update` – Action to run on the application resource when any
|
||||
subresource is updated. *(default: restart)*
|
||||
* `action_on_update_immediately` – Run the `action_on_update` notification with
|
||||
`:immediately`. *(default: false)*
|
||||
|
||||
### `application_cookbook_file`, `application_file`, `application_template`
|
||||
|
||||
The `application_cookbook_file`, `application_file`, and `application_template`
|
||||
resources extend the core Chef resources to take some application-level
|
||||
configuration in to account:
|
||||
|
||||
```ruby
|
||||
application '/opt/myapp' do
|
||||
template 'myapp.conf' do
|
||||
source 'myapp.conf.erb'
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
If the resource name is a relative path, it will be expanded relative to the
|
||||
application path. If an owner or group is declared for the application, those
|
||||
will be the default user and group for the resource.
|
||||
|
||||
All other actions and properties are the same as the similar resource in core Chef.
|
||||
|
||||
## Examples
|
||||
|
||||
Some test recipes are available as examples for common application frameworks:
|
||||
|
||||
* [Sinatra](https://github.com/poise/application_ruby/blob/master/test/cookbooks/application_ruby_test/recipes/sinatra.rb)
|
||||
* [Rails](https://github.com/poise/application_ruby/blob/master/test/cookbooks/application_ruby_test/recipes/rails.rb)
|
||||
* [Flask](https://github.com/poise/application_python/blob/master/test/cookbooks/application_python_test/recipes/flask.rb)
|
||||
* [Django](https://github.com/poise/application_python/blob/master/test/cookbooks/application_python_test/recipes/django.rb)
|
||||
* [Express](https://github.com/poise/application_javascript/blob/master/test/cookbooks/application_javascript_test/recipes/express.rb)
|
||||
|
||||
## Upgrading From 4.x
|
||||
|
||||
While the overall design of the revamped application resource is similar to the
|
||||
4.x version, some changes will need to be made. The `name` property no longer
|
||||
exists, with the name attribute being used as the path to the deployment.
|
||||
The `packages` property has been removed as this is more easily handled via
|
||||
normal recipe code.
|
||||
|
||||
The SCM-related properties like `repository` and `revision` are now handled by
|
||||
normal plugins. If you were deploying from a private git repository you will
|
||||
likely want to use the `application_git` cookbook, otherwise just use the
|
||||
built-in `git` or `svn` resources as per normal.
|
||||
|
||||
The properties related to the `deploy` resource like `strategy` and `symlinks`
|
||||
have been removed. The `deploy` resource is no longer used so these aren't
|
||||
relevant. As a side effect of this, you'll likely want to point the upgraded
|
||||
deployment at a new folder or manually clean the `current` and `shared` folders
|
||||
from the existing folder. The pseudo-Capistrano layout used by the `deploy`
|
||||
resource has few benefits in a config-managed world and introduced a lot of
|
||||
complexity and moving pieces that are no longer required.
|
||||
|
||||
With the removal of the `deploy` resource, the callback properties and commands
|
||||
are no longer used as well. Subresources no longer use the complex
|
||||
actions-as-callbacks arrangement as existed before, instead following normal
|
||||
Chef recipe flow. Individual subresources may need to be tweaked to work with
|
||||
newer versions of the cookbooks they come from, though most have stayed similar
|
||||
in overall approach.
|
||||
|
||||
## Database Migrations and Chef
|
||||
|
||||
Several of the web application deployment plugins include optional support to
|
||||
run database migrations from Chef. For "toy" applications where the app and
|
||||
database run together on a single machine, this is fine and is a nice time
|
||||
saver. For anything more complex I highly recommend not running database
|
||||
migrations from Chef. Some initial operations like creating the database and/or
|
||||
database user are more reasonable as they tend to be done only once and by their
|
||||
nature the application does not yet have users so some level of eventual
|
||||
consistency is more acceptable. With migrations on a production application, I
|
||||
encourage using Chef and the application cookbooks to handle deploying the code
|
||||
and writing configuration files, but use something more specific to run the
|
||||
actual migration task. [Fabric](http://www.fabfile.org/),
|
||||
[Capistrano](http://capistranorb.com/), and [Rundeck](http://rundeck.org/) are
|
||||
all good choices for this orchestration tooling.
|
||||
|
||||
Migrations can generally be applied idempotently but they have unique
|
||||
constraints (pun definitely intended) that make them tricky in a Chef-like,
|
||||
convergence-based system. First and foremost is that many table alterations
|
||||
lock the table for updating for at least some period of time. That can mean that
|
||||
while staging the new code or configuration data can happen within a window, the
|
||||
migration itself needs to be run in careful lockstep with the rest of the
|
||||
deployment process (eg. moving things in and out of load balancers). Beyond
|
||||
that, while most web frameworks have internal idempotence checks for migrations,
|
||||
running the process on two servers at the same time can have unexpected effects.
|
||||
|
||||
Overall migrations are best thought of as a procedural step rather than a
|
||||
declaratively modeled piece of the system.
|
||||
|
||||
## Application Signals and Updates
|
||||
|
||||
The `application` resource exposes `start`, `stop`, `restart`, and `reload`
|
||||
actions which will dispatch to any subresources attached to the application.
|
||||
This allows for generic application-level restart or reload signals that will
|
||||
work with any type of deployment.
|
||||
|
||||
Additionally the `action_on_update` property is used to set a default
|
||||
notification so any subresource that updates will trigger an application
|
||||
restart or reload. This can be disabled by setting `action_on_update false` if
|
||||
you want to take manual control of service restarts.
|
||||
|
||||
## Sponsors
|
||||
|
||||
Development sponsored by [Chef Software](https://www.chef.io/), [Symonds & Son](http://symondsandson.com/), and [Orion](https://www.orionlabs.co/).
|
||||
|
||||
The Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/).
|
||||
|
||||
## License
|
||||
|
||||
Copyright 2015, Noah Kantrowitz
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
```
|
||||
|
||||
25
cookbooks/application/files/halite_gem/poise_application.rb
Normal file
25
cookbooks/application/files/halite_gem/poise_application.rb
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# Copyright 2015, Noah Kantrowitz
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
|
||||
module PoiseApplication
|
||||
autoload :AppMixin, 'poise_application/app_mixin'
|
||||
autoload :Error, 'poise_application/error'
|
||||
autoload :Resources, 'poise_application/resources'
|
||||
autoload :ServiceMixin, 'poise_application/service_mixin'
|
||||
autoload :Utils, 'poise_application/utils'
|
||||
autoload :VERSION, 'poise_application/version'
|
||||
end
|
||||
@@ -0,0 +1,61 @@
|
||||
#
|
||||
# Copyright 2015, Noah Kantrowitz
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
require 'poise/utils'
|
||||
|
||||
require 'poise_application/app_mixin'
|
||||
|
||||
|
||||
module PoiseApplication
|
||||
# A helper mixin for `file`-like resources to make them take application
|
||||
# resource data. Relative paths are expanded against the application path and
|
||||
# the app owner/group are the default user/group for the resource.
|
||||
#
|
||||
# @api private
|
||||
# @since 5.1.0
|
||||
module AppFileMixin
|
||||
include Poise::Utils::ResourceProviderMixin
|
||||
|
||||
module Resource
|
||||
include PoiseApplication::AppMixin
|
||||
|
||||
def initialize(*)
|
||||
super
|
||||
# So our lazy default below can work. Not needed on 12.7+.
|
||||
remove_instance_variable(:@path) if instance_variable_defined?(:@path)
|
||||
end
|
||||
|
||||
# @!attribute path
|
||||
# Override the default path to be relative to the app path.
|
||||
# @return [String]
|
||||
attribute(:path, kind_of: String, default: lazy { parent ? ::File.expand_path(name, parent.path) : name })
|
||||
|
||||
# @!attribute group
|
||||
# Override the default group to be the app group if unspecified.
|
||||
# @return [String, Integer]
|
||||
attribute(:group, kind_of: [String, Integer, NilClass], default: lazy { parent && parent.group })
|
||||
|
||||
# @!attribute user
|
||||
# Override the default user to be the app owner if unspecified.
|
||||
# @return [String, Integer]
|
||||
attribute(:user, kind_of: [String, Integer, NilClass], default: lazy { parent && parent.owner })
|
||||
end
|
||||
|
||||
module Provider
|
||||
include PoiseApplication::AppMixin
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,69 @@
|
||||
#
|
||||
# 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/provider'
|
||||
require 'poise/resource'
|
||||
require 'poise/utils'
|
||||
|
||||
|
||||
module PoiseApplication
|
||||
# A helper mixin for application resources and providers. These are things
|
||||
# intended to be used as subresources of the `application` resource.
|
||||
#
|
||||
# @since 5.0.0
|
||||
module AppMixin
|
||||
include Poise::Utils::ResourceProviderMixin
|
||||
|
||||
# A helper mixin for application resources.
|
||||
module Resource
|
||||
include Poise::Resource
|
||||
|
||||
# Set the parent type and optional flag.
|
||||
poise_subresource(:application, true)
|
||||
|
||||
# @!attribute path
|
||||
# Base path for the application.
|
||||
# @return [String]
|
||||
attribute(:path, kind_of: String, name_attribute: true)
|
||||
|
||||
# A delegator for accessing the application state. If no application
|
||||
# parent is found, the state will be tracked internally within the
|
||||
# resource.
|
||||
#
|
||||
# @return [Hash<Symbol, Object>]
|
||||
def app_state
|
||||
if parent
|
||||
parent.app_state
|
||||
else
|
||||
# If there isn't a parent, just track within the resource.
|
||||
@local_app_state ||= Mash.new
|
||||
end
|
||||
end
|
||||
|
||||
# Environment variables stored in the application state.
|
||||
#
|
||||
# @return [Hash<String, String>]
|
||||
def app_state_environment
|
||||
app_state[:environment] ||= Mash.new
|
||||
end
|
||||
end
|
||||
|
||||
module Provider
|
||||
include Poise::Provider
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,14 +1,11 @@
|
||||
#
|
||||
# Cookbook Name:: application
|
||||
# Recipe:: default
|
||||
#
|
||||
# Copyright:: 2012, Opscode, Inc <legal@opscode.com>
|
||||
# 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
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,4 +13,5 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# Empty placeholder recipe, use the LWRPs, see README.md.
|
||||
|
||||
require 'poise_application/resources'
|
||||
@@ -0,0 +1,24 @@
|
||||
#
|
||||
# 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 PoiseApplication
|
||||
# Base exception class for poise-application errors.
|
||||
#
|
||||
# @since 5.0.0
|
||||
class Error < Exception
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,29 @@
|
||||
#
|
||||
# Copyright 2015, Noah Kantrowitz
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
require 'poise_application/resources/application'
|
||||
require 'poise_application/resources/application_cookbook_file'
|
||||
require 'poise_application/resources/application_file'
|
||||
require 'poise_application/resources/application_template'
|
||||
|
||||
|
||||
module PoiseApplication
|
||||
# Chef resources and providers for poise-application.
|
||||
#
|
||||
# @since 5.0.0
|
||||
module Resources
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,259 @@
|
||||
#
|
||||
# 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/dsl/recipe' # On 12.4+ this will pull in chef/dsl/resources.
|
||||
require 'chef/resource'
|
||||
require 'chef/provider'
|
||||
require 'poise'
|
||||
|
||||
|
||||
module PoiseApplication
|
||||
module Resources
|
||||
# (see Application::Resource)
|
||||
# @since 5.0.0
|
||||
module Application
|
||||
# An `application` resource to manage application deployment.
|
||||
#
|
||||
# @since 5.0.0
|
||||
# @provides application
|
||||
# @action deploy
|
||||
# @action start
|
||||
# @action stop
|
||||
# @action restart
|
||||
# @action reload
|
||||
# @example
|
||||
# application '/srv/myapp' do
|
||||
# git '...'
|
||||
# poise_service 'myapp' do
|
||||
# command '/srv/myapp/main'
|
||||
# end
|
||||
# end
|
||||
class Resource < Chef::Resource
|
||||
include Poise(container: true, container_namespace: false)
|
||||
provides(:application)
|
||||
actions(:deploy, :start, :stop, :restart, :reload)
|
||||
|
||||
# @!attribute path
|
||||
# Application base path.
|
||||
# @return [String]
|
||||
attribute(:path, kind_of: String, name_attribute: true)
|
||||
# @!attribute environment
|
||||
# Environment variables to set for the whole application.
|
||||
# @return [Hash<String, String>]
|
||||
attribute(:environment, kind_of: Hash, default: lazy { Mash.new })
|
||||
# @!attribute owner
|
||||
# System user that will own the application. This can be overriden in
|
||||
# individual subresources.
|
||||
# @return [String]
|
||||
attribute(:owner, kind_of: String)
|
||||
# @!attribute group
|
||||
# System group that will own the application. This can be overriden in
|
||||
# individual subresources.
|
||||
# @return [String]
|
||||
attribute(:group, kind_of: String)
|
||||
# @!attribute action_on_update
|
||||
# Action to run when any subresource is updated. Defaults to `:restart`.
|
||||
# @return [String, Symbol, nil, false]
|
||||
attribute(:action_on_update, kind_of: [Symbol, String, NilClass, FalseClass], default: :restart)
|
||||
# @!attribute action_on_update_immediately
|
||||
# Run the {#action_on_update} notification with `:immediately`.
|
||||
# @return [Boolean]
|
||||
attribute(:action_on_update_immediately, equal_to: [true, false], default: false)
|
||||
|
||||
# Run the DSL rewire when the resource object is created.
|
||||
# @api private
|
||||
def initialize(*args)
|
||||
super
|
||||
_rewire_dsl! if node
|
||||
end
|
||||
|
||||
# Application-specific state values used as a way to communicate between
|
||||
# subresources.
|
||||
#
|
||||
# @return [Mash]
|
||||
# @example
|
||||
# if new_resource.parent && new_resource.parent.app_state['gemfile_path']
|
||||
def app_state
|
||||
@app_state ||= Mash.new(environment: environment)
|
||||
end
|
||||
|
||||
# Override Container#register_subresource to add our action_on_update.
|
||||
#
|
||||
# @api private
|
||||
def register_subresource(resource)
|
||||
super.tap do |added|
|
||||
if added && action_on_update
|
||||
Chef::Log.debug("[#{self}] Registering #{action_on_update_immediately ? 'immediate ' : ''}#{action_on_update} notification from #{resource}")
|
||||
resource.notifies action_on_update.to_sym, self, (action_on_update_immediately ? :immediately : :delayed)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Find all resources that need to be rewired. This is anything with a
|
||||
# name starting with application_.
|
||||
#
|
||||
# @return [Array<String>]
|
||||
def _rewire_resources
|
||||
if defined?(Chef::DSL::Resources)
|
||||
# Chef >= 12.4.
|
||||
Chef::DSL::Resources.instance_methods
|
||||
else
|
||||
# Chef < 12.4 >= 12.0.
|
||||
Chef::Resource.descendants.map do |klass|
|
||||
klass.node_map.instance_variable_get(:@map).keys + if klass.dsl_name.include?('::')
|
||||
# Probably not valid.
|
||||
# :nocov:
|
||||
[]
|
||||
# :nocov:
|
||||
else
|
||||
# Needed for things that don't call provides().
|
||||
[klass.dsl_name]
|
||||
end
|
||||
end.flatten
|
||||
end.map {|name| name.to_s }.select {|name| name.start_with?('application_') }.uniq
|
||||
end
|
||||
|
||||
# Find all cookbooks that might contain LWRPs matching our name scheme.
|
||||
#
|
||||
# @return [Array<String>]
|
||||
def _rewire_cookbooks
|
||||
# Run context might be unset during test setup.
|
||||
if run_context
|
||||
run_context.cookbook_collection.keys.select {|cookbook_name| cookbook_name.start_with?('application_') }
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
# Build the mapping of new_name => old_name for each resource to rewire.
|
||||
#
|
||||
# @return [Hash<String, String>]
|
||||
def _rewire_map
|
||||
application_cookbooks = _rewire_cookbooks
|
||||
_rewire_resources.inject({}) do |memo, name|
|
||||
# Grab the resource class to check if it is an LWRP.
|
||||
klass = Chef::Resource.resource_for_node(name.to_sym, node)
|
||||
# Find the part to trim. Check for LWRP first, then just application_.
|
||||
trim = if klass < Chef::Resource::LWRPBase
|
||||
application_cookbooks.find {|cookbook_name| name.start_with?(cookbook_name) && name != cookbook_name } || 'application'
|
||||
else
|
||||
# Non-LWRPs are assumed to have a better name.
|
||||
'application'
|
||||
end
|
||||
# Map trimmed to untrimmed.
|
||||
memo[name[trim.length+1..-1]] = name
|
||||
memo
|
||||
end
|
||||
end
|
||||
|
||||
# Build new DSL methods to implement the foo -> application_foo behavior.
|
||||
#
|
||||
# @return [void]
|
||||
def _rewire_dsl!
|
||||
# Generate stub methods for all the rewiring.
|
||||
_rewire_map.each do |new_name, old_name|
|
||||
# This is defined as a singleton method on self so it looks like
|
||||
# the DSL but is scoped to just this context.
|
||||
define_singleton_method(new_name) do |name=nil, *args, &block|
|
||||
# Store the caller to correct the source_line.
|
||||
created_at = caller[0]
|
||||
public_send(old_name, name, *args) do
|
||||
# Set the declared type to be the native name.
|
||||
self.declared_type = self.class.resource_name
|
||||
# Fix the source location. For Chef 12.4 we could do this with the
|
||||
# declared_at parameter on the initial send.
|
||||
self.source_line = created_at
|
||||
# Run the original block.
|
||||
instance_exec(&block) if block
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Provider for `application`.
|
||||
#
|
||||
# @since 5.0.0
|
||||
# @see Resource
|
||||
# @provides application
|
||||
class Provider < Chef::Provider
|
||||
include Poise
|
||||
provides(:application)
|
||||
|
||||
# `deploy` action for `application`. Creates the application base folder.
|
||||
#
|
||||
# @return [void]
|
||||
def action_deploy
|
||||
notifying_block do
|
||||
directory new_resource.path do
|
||||
owner new_resource.owner
|
||||
group new_resource.group
|
||||
mode '755'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# `start` action for `application`. Proxies to subresources.
|
||||
#
|
||||
# @return [void]
|
||||
def action_start
|
||||
proxy_action(:start)
|
||||
end
|
||||
|
||||
# `stop` action for `application`. Proxies to subresources.
|
||||
#
|
||||
# @return [void]
|
||||
def action_stop
|
||||
proxy_action(:stop)
|
||||
end
|
||||
|
||||
# `restart` action for `application`. Proxies to subresources.
|
||||
#
|
||||
# @return [void]
|
||||
def action_restart
|
||||
proxy_action(:restart)
|
||||
end
|
||||
|
||||
# `reload` action for `application`. Proxies to subresources.
|
||||
#
|
||||
# @return [void]
|
||||
def action_reload
|
||||
proxy_action(:reload)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Proxy an action to any subresources that support it.
|
||||
#
|
||||
# @param action [Symbol] Action to proxy.
|
||||
# @return [void]
|
||||
def proxy_action(action)
|
||||
Chef::Log.debug("[#{new_resource} Running proxied #{action} action")
|
||||
new_resource.subresources.each do |r|
|
||||
begin
|
||||
r.run_action(action) if r.allowed_actions.include?(action)
|
||||
rescue Chef::Exceptions::UnsupportedAction
|
||||
# Don't care, just move on.
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,54 @@
|
||||
#
|
||||
# Copyright 2015, Noah Kantrowitz
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
require 'poise_application/app_file_mixin'
|
||||
|
||||
|
||||
module PoiseApplication
|
||||
module Resources
|
||||
# (see ApplicationCookbookFile::Resource)
|
||||
# @since 5.1.0
|
||||
module ApplicationCookbookFile
|
||||
# An `application_cookbook_file` resource to manage Chef cookbook_files inside and
|
||||
# Application cookbook deployment.
|
||||
#
|
||||
# @provides application_cookbook_file
|
||||
# @action create
|
||||
# @action create_if_missing
|
||||
# @action delete
|
||||
# @action touch
|
||||
# @example
|
||||
# application '/srv/myapp' do
|
||||
# cookbook_file 'myapp.conf' do
|
||||
# source 'myapp.conf'
|
||||
# end
|
||||
# end
|
||||
class Resource < Chef::Resource::CookbookFile
|
||||
include PoiseApplication::AppFileMixin
|
||||
provides(:application_cookbook_file)
|
||||
actions(:create, :create_if_missing, :delete, :touch)
|
||||
subclass_providers!
|
||||
|
||||
def initialize(*args)
|
||||
super
|
||||
# For older Chef.
|
||||
@resource_name = :application_cookbook_file
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,54 @@
|
||||
#
|
||||
# Copyright 2015, Noah Kantrowitz
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
require 'poise_application/app_file_mixin'
|
||||
|
||||
|
||||
module PoiseApplication
|
||||
module Resources
|
||||
# (see ApplicationFile::Resource)
|
||||
# @since 5.1.0
|
||||
module ApplicationFile
|
||||
# An `application_file` resource to manage Chef files inside and
|
||||
# Application cookbook deployment.
|
||||
#
|
||||
# @provides application_file
|
||||
# @action create
|
||||
# @action create_if_missing
|
||||
# @action delete
|
||||
# @action touch
|
||||
# @example
|
||||
# application '/srv/myapp' do
|
||||
# file 'myapp.conf' do
|
||||
# source 'myapp.conf.erb'
|
||||
# end
|
||||
# end
|
||||
class Resource < Chef::Resource::File
|
||||
include PoiseApplication::AppFileMixin
|
||||
provides(:application_file)
|
||||
actions(:create, :create_if_missing, :delete, :touch)
|
||||
subclass_providers!
|
||||
|
||||
def initialize(*args)
|
||||
super
|
||||
# For older Chef.
|
||||
@resource_name = :application_file
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,54 @@
|
||||
#
|
||||
# Copyright 2015, Noah Kantrowitz
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
require 'poise_application/app_file_mixin'
|
||||
|
||||
|
||||
module PoiseApplication
|
||||
module Resources
|
||||
# (see ApplicationTemplate::Resource)
|
||||
# @since 5.1.0
|
||||
module ApplicationTemplate
|
||||
# An `application_template` resource to manage Chef templates inside and
|
||||
# Application cookbook deployment.
|
||||
#
|
||||
# @provides application_template
|
||||
# @action create
|
||||
# @action create_if_missing
|
||||
# @action delete
|
||||
# @action touch
|
||||
# @example
|
||||
# application '/srv/myapp' do
|
||||
# template 'myapp.conf' do
|
||||
# source 'myapp.conf.erb'
|
||||
# end
|
||||
# end
|
||||
class Resource < Chef::Resource::Template
|
||||
include PoiseApplication::AppFileMixin
|
||||
provides(:application_template)
|
||||
actions(:create, :create_if_missing, :delete, :touch)
|
||||
subclass_providers!
|
||||
|
||||
def initialize(*args)
|
||||
super
|
||||
# For older Chef.
|
||||
@resource_name = :application_template
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,116 @@
|
||||
#
|
||||
# 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/resource'
|
||||
require 'chef/provider'
|
||||
require 'poise/utils'
|
||||
require 'poise_service/service_mixin'
|
||||
require 'poise_service/utils'
|
||||
|
||||
require 'poise_application/app_mixin'
|
||||
require 'poise_application/utils'
|
||||
|
||||
|
||||
module PoiseApplication
|
||||
# Mixin for application services. This is any resource that will be part of
|
||||
# an application deployment and involves running a persistent service.
|
||||
#
|
||||
# @api public
|
||||
# @since 5.0.0
|
||||
# @example
|
||||
# module MyApp
|
||||
# class Resource < Chef::Resource
|
||||
# include Poise
|
||||
# provides(:my_app)
|
||||
# include PoiseApplication::ServiceMixin
|
||||
# end
|
||||
#
|
||||
# class Provider < Chef::Provider
|
||||
# include Poise
|
||||
# provides(:my_app)
|
||||
# include PoiseApplication::ServiceMixin
|
||||
#
|
||||
# def action_enable
|
||||
# notifying_block do
|
||||
# template '/etc/myapp.conf' do
|
||||
# # ...
|
||||
# end
|
||||
# end
|
||||
# super
|
||||
# end
|
||||
#
|
||||
# def service_options(r)
|
||||
# super
|
||||
# r.command('myapp --serve')
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
module ServiceMixin
|
||||
include Poise::Utils::ResourceProviderMixin
|
||||
|
||||
# Mixin for application service resources.
|
||||
#
|
||||
# @see ServiceMixin
|
||||
module Resource
|
||||
include PoiseService::ServiceMixin::Resource
|
||||
include PoiseApplication::AppMixin::Resource
|
||||
|
||||
module ClassMethods
|
||||
# @api private
|
||||
def included(klass)
|
||||
super
|
||||
klass.extend(ClassMethods)
|
||||
klass.class_exec do
|
||||
attribute(:path, kind_of: String, name_attribute: true)
|
||||
# Redefines from the PoiseService version so we get a better default.
|
||||
attribute(:service_name, kind_of: String, default: lazy { PoiseService::Utils.parse_service_name(path) })
|
||||
attribute(:user, kind_of: [String, Integer], default: lazy { parent ? parent.owner : 'root' })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
extend ClassMethods
|
||||
end
|
||||
|
||||
# Mixin for application service providers.
|
||||
#
|
||||
# @see ServiceMixin
|
||||
module Provider
|
||||
include PoiseService::ServiceMixin::Provider
|
||||
include PoiseApplication::AppMixin::Provider
|
||||
|
||||
private
|
||||
|
||||
# Abstract hook to set parameters on {#service_resource} when it is
|
||||
# created. This is required to set at least `resource.command`.
|
||||
#
|
||||
# @api public
|
||||
# @param resource [Chef::Resource] Resource instance to set parameters on.
|
||||
# @return [void]
|
||||
# @example
|
||||
# def service_options(resource)
|
||||
# super
|
||||
# resource.command('myapp --serve')
|
||||
# end
|
||||
def service_options(resource)
|
||||
super
|
||||
resource.directory(new_resource.path)
|
||||
resource.user(new_resource.user)
|
||||
resource.environment.update(new_resource.app_state_environment) if new_resource.parent
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,51 @@
|
||||
#
|
||||
# Copyright 2015, Noah Kantrowitz
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
require 'etc'
|
||||
|
||||
|
||||
module PoiseApplication
|
||||
# Utility methods for PoiseApplication.
|
||||
#
|
||||
# @api public
|
||||
# @since 5.0.0
|
||||
module Utils
|
||||
# Methods are also available as module-level methods as well as a mixin.
|
||||
extend self
|
||||
|
||||
# Try to find the primary group name for a given user.
|
||||
#
|
||||
# @param user [String, Integer] User to check, if given as an integer this
|
||||
# is used as a UID, otherwise it is the username.
|
||||
# @return [String]
|
||||
# @example
|
||||
# attribute(:group, kind_of: [String, Integer], default: lazy { PoiseApplication::Utils.primary_group_for(user) })
|
||||
def primary_group_for(user)
|
||||
# Force a reload in case any users were created earlier in the run.
|
||||
Etc.endpwent
|
||||
Etc.endgrent
|
||||
user = if user.is_a?(Integer)
|
||||
Etc.getpwuid(user)
|
||||
else
|
||||
Etc.getpwnam(user.to_s)
|
||||
end
|
||||
Etc.getgrgid(user.gid).name
|
||||
rescue ArgumentError
|
||||
# One of the get* calls exploded. ¯\_(ツ)_/¯
|
||||
user.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# 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 PoiseApplication
|
||||
VERSION = '5.1.0'
|
||||
end
|
||||
@@ -1,15 +1,11 @@
|
||||
#
|
||||
# Author:: Noah Kantrowitz <noah@opscode.com>
|
||||
# Cookbook Name:: application
|
||||
# Library:: default
|
||||
#
|
||||
# Copyright:: 2011-2012, Opscode, Inc <legal@opscode.com>
|
||||
# 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
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -18,172 +14,6 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
require "chef/mixin/from_file"
|
||||
|
||||
class Chef
|
||||
class Resource
|
||||
# Monkey-Patch the blacklists to prevent infinite recursion in #to_json and similar
|
||||
# (this is global state,thus the set-union operator to change it idempotently + to not leak)
|
||||
[ :@application, :@application_provider ].each do |ivar|
|
||||
FORBIDDEN_IVARS << ivar unless FORBIDDEN_IVARS.include?(ivar)
|
||||
HIDDEN_IVARS << ivar unless HIDDEN_IVARS.include?(ivar)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class ApplicationCookbook
|
||||
|
||||
module OptionsCollector
|
||||
def options
|
||||
@options ||= {}
|
||||
end
|
||||
|
||||
def method_missing(method_sym, value=nil, &block)
|
||||
super
|
||||
rescue NameError
|
||||
value ||= block
|
||||
method_sym = method_sym.to_s.chomp('=').to_sym
|
||||
options[method_sym] = value if value
|
||||
options[method_sym] ||= nil
|
||||
end
|
||||
end
|
||||
|
||||
module ResourceBase
|
||||
def self.included(klass)
|
||||
klass.actions :before_compile, :before_deploy, :before_migrate, :before_symlink, :before_restart, :after_restart
|
||||
klass.attribute :id, :kind_of => String, :name_attribute => true
|
||||
klass.attribute :environment, :kind_of => Hash, :default => {}
|
||||
klass.attribute :purge_before_symlink, :kind_of => Array, :default => []
|
||||
klass.attribute :create_dirs_before_symlink, :kind_of => Array, :default => []
|
||||
klass.attribute :symlinks, :kind_of => Hash, :default => {}
|
||||
klass.attribute :symlink_before_migrate, :kind_of => Hash, :default => {}
|
||||
klass.attribute :migration_command, :kind_of => [String, NilClass], :default => nil
|
||||
klass.attribute :application
|
||||
klass.attribute :application_provider
|
||||
klass.attribute :type
|
||||
end
|
||||
|
||||
def restart_command(arg=nil, &block)
|
||||
arg ||= block
|
||||
raise "Invalid restart command" unless !arg || arg.is_a?(String) || arg.is_a?(Proc)
|
||||
@restart_command = arg if arg
|
||||
@restart_command
|
||||
end
|
||||
|
||||
def method_missing(name, *args)
|
||||
if application.respond_to? name
|
||||
application.send(name, *args)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
class OptionsBlock
|
||||
include ApplicationCookbook::OptionsCollector
|
||||
end
|
||||
|
||||
def options_block(options=nil, &block)
|
||||
options ||= {}
|
||||
if block
|
||||
collector = OptionsBlock.new
|
||||
collector.instance_eval(&block)
|
||||
options.update(collector.options)
|
||||
end
|
||||
options
|
||||
end
|
||||
|
||||
def find_matching_role(role, single=true, &block)
|
||||
return nil if !role
|
||||
nodes = []
|
||||
if node['roles'].include? role
|
||||
nodes << node
|
||||
end
|
||||
if !single || nodes.empty?
|
||||
search(:node, "role:#{role} AND chef_environment:#{node.chef_environment}") do |n|
|
||||
nodes << n
|
||||
end
|
||||
end
|
||||
if block
|
||||
nodes.each do |n|
|
||||
yield n
|
||||
end
|
||||
else
|
||||
if single
|
||||
nodes.first
|
||||
else
|
||||
nodes
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def find_database_server(role)
|
||||
dbm = find_matching_role(role)
|
||||
Chef::Log.warn("No node with role #{role}") if role && !dbm
|
||||
|
||||
if respond_to?(:database) && database.has_key?('host')
|
||||
database['host']
|
||||
elsif dbm && dbm.attribute?('cloud')
|
||||
dbm['cloud']['local_ipv4']
|
||||
elsif dbm
|
||||
dbm['ipaddress']
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module ProviderBase
|
||||
|
||||
def self.included(klass)
|
||||
klass.send(:include, Chef::Mixin::FromFile)
|
||||
end
|
||||
|
||||
def deploy_provider
|
||||
@deploy_provider ||= begin
|
||||
provider = @deploy_resource.provider_for_action(:nothing)
|
||||
provider.load_current_resource
|
||||
provider
|
||||
end
|
||||
end
|
||||
|
||||
def release_path
|
||||
deploy_provider.release_path
|
||||
end
|
||||
|
||||
def shared_path
|
||||
@deploy_resource.shared_path
|
||||
end
|
||||
|
||||
def callback(what, callback_code=nil)
|
||||
Chef::Log.debug("Got callback #{what}: #{callback_code.inspect}")
|
||||
@collection = Chef::ResourceCollection.new
|
||||
case callback_code
|
||||
when Proc
|
||||
Chef::Log.info "#{@new_resource} running callback #{what}"
|
||||
safe_recipe_eval(&callback_code)
|
||||
when String
|
||||
callback_file = "#{release_path}/#{callback_code}"
|
||||
unless ::File.exist?(callback_file)
|
||||
raise RuntimeError, "Can't find your callback file #{callback_file}"
|
||||
end
|
||||
run_callback_from_file(callback_file)
|
||||
when nil
|
||||
nil
|
||||
else
|
||||
raise RuntimeError, "You gave me a callback I don't know what to do with: #{callback_code.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
def run_callback_from_file(callback_file)
|
||||
if ::File.exist?(callback_file)
|
||||
Dir.chdir(release_path) do
|
||||
Chef::Log.info "#{@new_resource} running deploy hook #{callback_file}"
|
||||
safe_recipe_eval { from_file(callback_file) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def safe_recipe_eval(&callback_code)
|
||||
recipe_eval(&callback_code)
|
||||
converge if respond_to?(:converge)
|
||||
end
|
||||
end
|
||||
end
|
||||
raise 'Halite is not compatible with no_lazy_load false, please set no_lazy_load true in your Chef configuration file.' unless Chef::Config[:no_lazy_load]
|
||||
$LOAD_PATH << File.expand_path('../../files/halite_gem', __FILE__)
|
||||
require "poise_application/cheftie"
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
if defined?(ChefSpec)
|
||||
|
||||
def deploy_application(resource)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(:application, :deploy, resource)
|
||||
end
|
||||
|
||||
def force_deploy_application(resource)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(:application, :force_deploy, resource)
|
||||
end
|
||||
|
||||
end
|
||||
File diff suppressed because one or more lines are too long
@@ -1,191 +0,0 @@
|
||||
#
|
||||
# Author:: Noah Kantrowitz <noah@opscode.com>
|
||||
# Cookbook Name:: application
|
||||
# Provider:: default
|
||||
#
|
||||
# Copyright:: 2011-2012, Opscode, Inc <legal@opscode.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
include ApplicationCookbook::ProviderBase
|
||||
|
||||
action :deploy do
|
||||
|
||||
before_compile
|
||||
|
||||
before_deploy
|
||||
|
||||
run_deploy
|
||||
|
||||
end
|
||||
|
||||
action :force_deploy do
|
||||
|
||||
before_compile
|
||||
|
||||
before_deploy
|
||||
|
||||
run_deploy(true)
|
||||
|
||||
end
|
||||
|
||||
action :restart do
|
||||
|
||||
before_compile
|
||||
|
||||
run_actions_with_context(:before_restart, @run_context)
|
||||
|
||||
run_restart
|
||||
|
||||
run_actions_with_context(:after_restart, @run_context)
|
||||
|
||||
@new_resource.updated_by_last_action(true)
|
||||
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def before_compile
|
||||
new_resource.application_provider self
|
||||
new_resource.sub_resources.each do |resource|
|
||||
resource.application_provider self
|
||||
resource.run_action :before_compile
|
||||
end
|
||||
end
|
||||
|
||||
def before_deploy
|
||||
new_resource.packages.each do |pkg,ver|
|
||||
package pkg do
|
||||
action :install
|
||||
version ver if ver && ver.length > 0
|
||||
end
|
||||
end
|
||||
|
||||
directory new_resource.path do
|
||||
owner new_resource.owner
|
||||
group new_resource.group
|
||||
mode '0755'
|
||||
recursive true
|
||||
end
|
||||
|
||||
directory "#{new_resource.path}/shared" do
|
||||
owner new_resource.owner
|
||||
group new_resource.group
|
||||
mode '0755'
|
||||
recursive true
|
||||
end
|
||||
|
||||
if new_resource.deploy_key
|
||||
|
||||
if ::File.exists?(new_resource.deploy_key)
|
||||
deploy_key = open(new_resource.deploy_key, &:read)
|
||||
else
|
||||
deploy_key = new_resource.deploy_key
|
||||
end
|
||||
|
||||
file "#{new_resource.path}/id_deploy" do
|
||||
content deploy_key
|
||||
owner new_resource.owner
|
||||
group new_resource.group
|
||||
mode '0600'
|
||||
end
|
||||
|
||||
template "#{new_resource.path}/deploy-ssh-wrapper" do
|
||||
source "deploy-ssh-wrapper.erb"
|
||||
cookbook "application"
|
||||
owner new_resource.owner
|
||||
group new_resource.group
|
||||
mode "0755"
|
||||
variables :id => new_resource.name, :deploy_to => new_resource.path, :strict_ssh => new_resource.strict_ssh
|
||||
end
|
||||
end
|
||||
|
||||
ruby_block "#{new_resource.name} before_deploy" do
|
||||
block do
|
||||
new_resource.sub_resources.each do |resource|
|
||||
resource.run_action :before_deploy
|
||||
end
|
||||
callback(:before_deploy, new_resource.before_deploy)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def run_deploy(force = false)
|
||||
# Alias to a variable so I can use in sub-resources
|
||||
new_resource = @new_resource
|
||||
# Also alias to variable so it can be used in sub-resources
|
||||
app_provider = self
|
||||
|
||||
@deploy_resource = send(new_resource.strategy.to_sym, new_resource.name) do
|
||||
action force ? :force_deploy : :deploy
|
||||
scm_provider new_resource.scm_provider
|
||||
revision new_resource.revision
|
||||
repository new_resource.repository
|
||||
enable_submodules new_resource.enable_submodules
|
||||
user new_resource.owner
|
||||
group new_resource.group
|
||||
keep_releases new_resource.keep_releases
|
||||
deploy_to new_resource.path
|
||||
ssh_wrapper "#{new_resource.path}/deploy-ssh-wrapper" if new_resource.deploy_key
|
||||
shallow_clone new_resource.shallow_clone
|
||||
rollback_on_error new_resource.rollback_on_error
|
||||
all_environments = ([new_resource.environment]+new_resource.sub_resources.map{|res| res.environment}).inject({}){|acc, val| acc.merge(val)}
|
||||
environment all_environments
|
||||
migrate new_resource.migrate
|
||||
all_migration_commands = ([new_resource.migration_command]+new_resource.sub_resources.map{|res| res.migration_command}).select{|cmd| cmd && !cmd.empty?}
|
||||
migration_command all_migration_commands.join(' && ')
|
||||
restart_command do
|
||||
([new_resource]+new_resource.sub_resources).each do |res|
|
||||
cmd = res.restart_command
|
||||
if cmd.is_a? Proc
|
||||
app_provider.deploy_provider.instance_eval(&cmd) # @see libraries/default.rb
|
||||
elsif cmd && !cmd.empty?
|
||||
execute cmd do
|
||||
user new_resource.owner
|
||||
group new_resource.group
|
||||
environment all_environments
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
purge_before_symlink (new_resource.purge_before_symlink + new_resource.sub_resources.map(&:purge_before_symlink)).flatten
|
||||
create_dirs_before_symlink (new_resource.create_dirs_before_symlink + new_resource.sub_resources.map(&:create_dirs_before_symlink)).flatten
|
||||
all_symlinks = [new_resource.symlinks]+new_resource.sub_resources.map{|res| res.symlinks}
|
||||
symlinks all_symlinks.inject({}){|acc, val| acc.merge(val)}
|
||||
all_symlinks_before_migrate = [new_resource.symlink_before_migrate]+new_resource.sub_resources.map{|res| res.symlink_before_migrate}
|
||||
symlink_before_migrate all_symlinks_before_migrate.inject({}){|acc, val| acc.merge(val)}
|
||||
before_migrate do
|
||||
app_provider.send(:run_actions_with_context, :before_migrate, @run_context)
|
||||
end
|
||||
before_symlink do
|
||||
app_provider.send(:run_actions_with_context, :before_symlink, @run_context)
|
||||
end
|
||||
before_restart do
|
||||
app_provider.send(:run_actions_with_context, :before_restart, @run_context)
|
||||
end
|
||||
after_restart do
|
||||
app_provider.send(:run_actions_with_context, :after_restart, @run_context)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def run_actions_with_context(action, context)
|
||||
new_resource.sub_resources.each do |resource|
|
||||
saved_run_context = resource.instance_variable_get :@run_context
|
||||
resource.instance_variable_set :@run_context, context
|
||||
resource.run_action action
|
||||
resource.instance_variable_set :@run_context, saved_run_context
|
||||
end
|
||||
callback(action, new_resource.send(action))
|
||||
end
|
||||
@@ -1,178 +0,0 @@
|
||||
#
|
||||
# Author:: Noah Kantrowitz <noah@opscode.com>
|
||||
# Cookbook Name:: application
|
||||
# Resource:: default
|
||||
#
|
||||
# Copyright:: 2011-2012, Opscode, Inc <legal@opscode.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
require 'weakref'
|
||||
|
||||
include Chef::DSL::Recipe
|
||||
|
||||
def initialize(*args)
|
||||
super
|
||||
@action = :deploy
|
||||
@sub_resources = []
|
||||
end
|
||||
|
||||
actions :deploy, :force_deploy
|
||||
|
||||
attribute :name, :kind_of => String, :name_attribute => true
|
||||
attribute :environment_name, :kind_of => String, :default => (node.chef_environment =~ /_default/ ? "production" : node.chef_environment)
|
||||
attribute :path, :kind_of => String
|
||||
attribute :owner, :kind_of => String
|
||||
attribute :group, :kind_of => String
|
||||
attribute :keep_releases, :kind_of => Integer, :default => 5
|
||||
attribute :strategy, :kind_of => [String, Symbol], :default => :deploy_revision
|
||||
attribute :scm_provider, :kind_of => [Class, String, Symbol]
|
||||
attribute :revision, :kind_of => String
|
||||
attribute :repository, :kind_of => String
|
||||
attribute :enable_submodules, :kind_of => [TrueClass, FalseClass], :default => false
|
||||
attribute :environment, :kind_of => Hash, :default => {}
|
||||
attribute :deploy_key, :kind_of => [String, NilClass], :default => nil
|
||||
attribute :strict_ssh, :kind_of => [TrueClass, FalseClass], :default => false
|
||||
attribute :shallow_clone, :kind_of => [TrueClass, FalseClass], :default => false
|
||||
attribute :force, :kind_of => [TrueClass, FalseClass], :default => false
|
||||
attribute :rollback_on_error, :kind_of => [TrueClass, FalseClass], :default => true
|
||||
attribute :purge_before_symlink, :kind_of => Array, :default => []
|
||||
attribute :create_dirs_before_symlink, :kind_of => Array, :default => []
|
||||
attribute :symlinks, :kind_of => Hash, :default => {}
|
||||
attribute :symlink_before_migrate, :kind_of => Hash, :default => {}
|
||||
attribute :migrate, :kind_of => [TrueClass, FalseClass], :default => false
|
||||
attribute :migration_command, :kind_of => [String, NilClass], :default => nil
|
||||
attribute :packages, :kind_of => [Array, Hash], :default => []
|
||||
attribute :application_provider
|
||||
attr_reader :sub_resources
|
||||
|
||||
def restart_command(arg=nil, &block)
|
||||
arg ||= block
|
||||
set_or_return(:restart_command, arg, :kind_of => [Proc, String])
|
||||
end
|
||||
|
||||
# Callback fires before deploy is started.
|
||||
def before_deploy(arg=nil, &block)
|
||||
arg ||= block
|
||||
set_or_return(:before_deploy, arg, :kind_of => [Proc, String])
|
||||
end
|
||||
|
||||
# Callback fires before migration is run.
|
||||
def before_migrate(arg=nil, &block)
|
||||
arg ||= block
|
||||
set_or_return(:before_migrate, arg, :kind_of => [Proc, String])
|
||||
end
|
||||
|
||||
# Callback fires before symlinking
|
||||
def before_symlink(arg=nil, &block)
|
||||
arg ||= block
|
||||
set_or_return(:before_symlink, arg, :kind_of => [Proc, String])
|
||||
end
|
||||
|
||||
# Callback fires before restart
|
||||
def before_restart(arg=nil, &block)
|
||||
arg ||= block
|
||||
set_or_return(:before_restart, arg, :kind_of => [Proc, String])
|
||||
end
|
||||
|
||||
# Callback fires after restart
|
||||
def after_restart(arg=nil, &block)
|
||||
arg ||= block
|
||||
set_or_return(:after_restart, arg, :kind_of => [Proc, String])
|
||||
end
|
||||
|
||||
def release_path
|
||||
application_provider.release_path
|
||||
end
|
||||
|
||||
def shared_path
|
||||
application_provider.shared_path
|
||||
end
|
||||
|
||||
def method_missing(name, *args, &block)
|
||||
# Build the set of names to check for a valid resource
|
||||
lookup_path = ["application_#{name}"]
|
||||
run_context.cookbook_collection.each do |cookbook_name, cookbook_ver|
|
||||
if cookbook_name.start_with?("application_")
|
||||
lookup_path << "#{cookbook_name}_#{name}"
|
||||
end
|
||||
end
|
||||
lookup_path << name
|
||||
resource = nil
|
||||
# Try to find our resource
|
||||
lookup_path.each do |resource_name|
|
||||
begin
|
||||
Chef::Log.debug "Trying to load application resource #{resource_name} for #{name}"
|
||||
resource = super(resource_name.to_sym, self.name, &block)
|
||||
break
|
||||
rescue NameError => e
|
||||
# Works on any MRI ruby
|
||||
if e.name == resource_name.to_sym || e.inspect =~ /\b#{resource_name}\b/
|
||||
next
|
||||
else
|
||||
raise e
|
||||
end
|
||||
end
|
||||
end
|
||||
raise NameError, "No resource found for #{name}. Tried #{lookup_path.join(', ')}" unless resource
|
||||
# Enforce action :nothing in case people forget
|
||||
resource.action :nothing
|
||||
# Make this a weakref to prevent a cycle between the application resource and the sub resources
|
||||
resource.application WeakRef.new(self)
|
||||
resource.type name
|
||||
@sub_resources << resource
|
||||
resource
|
||||
end
|
||||
|
||||
def do_i_respond_to?(*args)
|
||||
name = args.first.to_s
|
||||
# Build the set of names to check for a valid resource
|
||||
lookup_path = ["application_#{name}"]
|
||||
run_context.cookbook_collection.each do |cookbook_name, cookbook_ver|
|
||||
if cookbook_name.start_with?("application_")
|
||||
lookup_path << "#{cookbook_name}_#{name}"
|
||||
end
|
||||
end
|
||||
lookup_path << name
|
||||
found = false
|
||||
# Try to find our resource
|
||||
lookup_path.each do |resource_name|
|
||||
begin
|
||||
Chef::Log.debug "Looking for application resource #{resource_name} for #{name}"
|
||||
Chef::Resource.resource_for_node(resource_name.to_sym, node)
|
||||
found = true
|
||||
break
|
||||
rescue NameError => e
|
||||
# Keep calm and carry on
|
||||
end
|
||||
end
|
||||
found
|
||||
end
|
||||
|
||||
# If we are using a current version of ruby, use respond_to_missing?
|
||||
# instead of respond_to? so we provide proper behavior
|
||||
if(Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('1.9.1'))
|
||||
def respond_to_missing?(*args)
|
||||
super || do_i_respond_to?(*args)
|
||||
end
|
||||
else
|
||||
def respond_to?(*args)
|
||||
super || do_i_respond_to?(*args)
|
||||
end
|
||||
end
|
||||
|
||||
def to_ary
|
||||
nil
|
||||
end
|
||||
alias :to_a :to_ary
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Deploy SSH Wrapper
|
||||
# App: <%= @id %>
|
||||
#
|
||||
# Rendered by Chef - local changes will be replaced
|
||||
|
||||
/usr/bin/env ssh <% unless @strict_ssh %>-o "StrictHostKeyChecking=no" <% end %>-i "<%= @deploy_to %>/id_deploy" $@
|
||||
Reference in New Issue
Block a user