MurgaNikolay/chef-eye

View on GitHub
README.md

Summary

Maintainability
Test Coverage
# chef_eye cookbook

Cookbook for setup [eye](https://github.com/kostya/eye) services and applications

[![Code Climate](https://codeclimate.com/github/MurgaNikolay/chef-eye/badges/gpa.svg)](https://codeclimate.com/github/MurgaNikolay/chef-eye)
[![Build Status](https://travis-ci.org/MurgaNikolay/chef-eye.svg?branch=master)](https://travis-ci.org/MurgaNikolay/chef-eye)

### Related projects

[Capistrano chef eye](https://github.com/MurgaNikolay/capistrano-chef-eye) cookbook companion for Capistrano.

## Supported Platforms

* Ubuntu 12.04
* Ubuntu 14.04

## Attributes


| Key | Type | Description | Default |
|-----|------|-------------|---------|
| chef_eye.eye_bin | String  |  Path to eye executable file | /usr/local/bin/eye |
| chef_eye.leye_bin | String  |  Path to local eye executable file | /usr/local/bin/leye |
| chef_eye.services | Hash or Array  |  Array of users or Hash with users as keys and service options as value | ['root'] |
| chef_eye.service_provider | String |  `'upstart'` or `'init'` | `'upstart'`|
| chef_eye.applications | Hash  | Applications configurations | {} |
| chef_eye.install_ruby | Boolean  | Try to install ruby packages `ruby`, `ruby-dev`. If you want to install ruby using another way, you should set this value to `false` | true |


## Usage

This cookbook provides two strategies of usage `eye`. "Eye" per user and "eye" per project (local eye).
First strategy run one eye daemon for all configurations and load it.

Eye per user file structure (for user vagrant):

    /etc/init/eye_vagrant.conf # Eye service for user vagrant (generated by chef_eye::service recipe)
    /etc/eye/config.eye # Main eye file. This file contains eye service settings and load config files from /etc/eye/vagrant/*.eye
    /etc/eye/vagrant/application1.eye # Application config (generated by chef_eye_application lwrp)
    /etc/eye/vagrant/application2.eye
    /etc/eye/vagrant/*.eye

Eye per project (local eye) file structure (generated by provider `Chef::Provider::ChefEyeApplicationLocal` ):

    /etc/init/leye_application.conf
    /var/www/application/shared # Eye home
    /var/www/application/shared/Eyefile # Local eye service configuration and loader for application config
    /var/www/application/shared/.eye/sock
    /var/www/application/shared/.eye/pid
    /var/www/application/shared/config/application.eye # Configuration file for application. Default path <eye_home>/config/<application_name>.eye

## Recipes

### chef_eye::default

Include `chef_eye` in your node's `run_list`:

```json
{
  "run_list": [
    "recipe[chef_eye::default]"
  ]
}
```

### chef_eye::ruby

Cookbook used system ruby and try to install `ruby`, `ruby-dev` packages if `node['chef_eye']['install_ruby']` set to `true`
If  you want to use custom system ruby, you need set `node['chef_eye']['install_ruby']` to `false` and install custom ruby before
before this cookbook. For example, if you want to use `uid` and `gid` [application options](https://github.com/kostya/eye/issues/50),
you need install ruby 2.0.0 as system ruby. Its installation is your concern.

## chef_eye::service

This recipe configure `chef_eye_service` for using with per user strategy

By default service named by `eye_<username>`. For example, service for user vagrant, will be named as `eye_vagrant`, service for user root as `eye_root`, etc.

If you need to reload service for user `vagrant`, you can use

```ruby
some_resource do
  ...
  notifies :reload, 'chef_eye_service[eye_vagrant]'
end
```

If you want to change configuration for service for `ubuntu`:

```ruby
default['chef_eye']['services'] = {
  ubuntu: {
    'logger' => '/var/log/eye/ubuntu.log'
    'mail' => {
      'host' => 'mx.some.host',
      'port' => 25,
      'domain' => 'some.host'
    },
    contacts: {
      'errors' => {
        'type' => 'mail',
        'contact' => 'error@some.host'
      },
      'dev' => {
        'type' => 'mail',
        'contact' => 'error@some.host',
        'opts' => {}
      },
    }
  }
}
```

### chef_eye::applications

This service generate `chef_eye_application` LWRP's using `node['chef_eye']['applications']` attributes. 
For example:

```ruby
default['chef_eye']['applications']['my_app'] = {
  type: 'local',
  owner: 'vagrant', # required
  group: 'vagrant',
  config_dir: '/var/www/rails_sample/shared/config',
  
  # for local version
  eye_file: 'Eyefile',
  eye_home: '/var/www/rails_sample/shared',
  eye_config: {
    logger: '/var/www/rails_sample/shared/log/eye.log'
  },
  service_provider: 'upstart',
  #application config
  config: {
    working_dir: '/var/www/rails_sample/current',
    checks: {
      cpu: {
        :every => 30,
        :below => 80,
        :times => 3
      },
      memory:{
        :every => 30,
        :below => 73400320,
        :times => [ 3, 5 ]
      }
    },
    process: {
      unicorn: {
        daemonize:  true,
        pid_file: 'puma.pid',
        stdall: 'puma.log',
        start_command: 'bundle exec unicorn --port 33280 --environment production Config.ru',
        stop_signals: ['TERM', 5, 'KILL']
      },
      resque: {
        pid_file: 'tmp/pids/resque.pid',
        start_command: 'bin/resque work --queue=high',
        checks: {
          cpu: {
            :every => 30,
            :below => 80,
            :times => 3
          }
        }
      }
    }
  }
}
```
## LWRPs

### chef_eye_service

#### Attributes  


|  Name       |  Type  | Description  |  Default Value |
|-------------|--------|--------------|----------------|
|  service_name | String | Name of the system service and system configuration file (/etc/init/<service_name>.conf).  | This is a name_attribute |
|  type     | String | Type need for set execution file `eye` or `leye`. Can be 'local' or 'user'   |  `'user'`  |
|  service_provider      | String | `upstart` or `init` | `'upstart'`    |
|  owner   | String | Owner of service | `'root'`  |
|  group   |String | Group of service | `'root'`    |
|  cookbook   | Symbol, String, NilClass | Cookbook name for searching templates | `nil` |
|  eye_home   | String, NilClass | Home directory for eye process. Used only for 'local' service type  | `nil`    |
|  eye_file   | String, NilClass | Main configuration file for loading by service. For `local` service this is `Eyefile` name, for `user` '/etc/<username>.eye'. This file must be generated by another LWRP. | `nil`    |


#### Actions   


|  Name         | Description  |   |
|---------------|--------------|--------------|
|  :nothing     |   |  default  |
|  :start       | Start eye service  |    |
|  :stop        | Stop eye service   |  |
|  :restart     | Restart eye service |  |
|  :stop_all    | Send start to all loaded applications |  |
|  :start_all   | Send stop to all loaded applications |  |
|  :restart_all | Send restart to all loaded applications  |  |



### chef_eye_application
  
  This is a main LWRP for configure eye application. 
  You can use any valid eye [options](https://github.com/kostya/eye/tree/master/examples) for config attribute.

#### Attributes:

|  Name       |  Type  | Description  |  Default Value |
|-------------|--------|--------------|----------------|
|  owner      | String | Owner fo application |  `'root'`    |
|  group      | String | Owner fo application |   `'root'`      |
|  cookbook   | String | Cookbook name for searching templates    | `'chef_eye'`  |
|  config     | Hash or Block | Application configuration  |  `{}`   |
|  config_dir     | String, NilClass | Application configuration |   nil (set dynamic: <eye_home>/config for `local`, /etc/eye/<user_name>/ for `user` strategies)   |
|  service_provider | string | Application configuration   |    node['chef_eye']['service_type'] |
|  eye_home | String, NillClass | Home for `.eye` directory, used only for `local` strategy. If empty, provider try to resolve eye_home path by `eye_file`. If eye_file is relative path, and eye_home empty, provider raise exception.  |    |
|  eye_file | String | Application service configuration file name (relative of eye_home) or absolute path, used only for `local` strategy    | `'Eyefile'` |
|  eye_config | Hash or Block | Application Service configuration, used only for `local` strategy |    `{}`  |


#### Providers

| Provider Name |      Description   |
|---------------|---------------------|
| Chef::Provider::ChefEyeApplication  | Default provider. This provider implement `user` application strategy   |  
| Chef::Provider::ChefEyeApplicationLocal | Default provider. This provider implement `local` application strategy |


Cookbook provide `chef_eye_application` resource. This is a main resource for generate eye application configuration.

```ruby
chef_eye_application 'name_of_my_app' do
  owner 'ubuntu'
  group 'ubuntu'
  working_dir '/var/www/rails_sample'
  config do
    env 'RAILS_ENV' => 'production'
    working_dir '/var/www/my_app'
    trigger :flapping, :times => 10, :within => 1.minute
    process :puma do
      daemonize true
      pid_file "puma.pid"
      stdall "puma.log"
      start_command "bundle exec puma --port 33280 --environment production thin.ru"
      stop_signals [:TERM, 5.seconds, :KILL]
      restart_command "kill -USR2 {PID}"
      restart_grace 10.seconds
      check :cpu, :every => 30, :below => 80, :times => 3
      check :memory, :every => 30, :below => 70.megabytes, :times => [3,5]
    end
  end
  action :configure # or :delete
  notifies :reload, 'chef_eye_service[eye_ubuntu]' # you need notify service for reload
end
```

Or as hash

```ruby
chef_eye_application 'name_of_my_app' do
  owner 'ubuntu'
  group 'ubuntu'
  config({
      env: {
        RAILS_ENV: 'production'
      },
      working_dir: '/var/www/my_app',
      triggers: {
        flapping: {
          :times => 10,
          :within => 1.minute
        }
      },
      processes: {
        puma: {
          daemonize: true,
          pid_file: "puma.pid",
          stdall: "puma.log",
          start_command: "bundle exec puma --port 33280 --environment production thin.ru",
          stop_signals: [:TERM, 5.seconds, :KILL],
          restart_command: "kill -USR2 {PID}",
          restart_grace: 10.seconds,
          checks: {
            cpu: {:every => 30, :below => 80, :times => 3},
            memory: {:every => 30, :below => 70.megabytes, :times => [3, 5]}
          }
        }
      }
    })
  action :configure # or :delete
  notifies :reload, 'chef_eye_service[eye_ubuntu]' # you need notify service for reload
end
```

## TODO

  * Add unit tests
  * Add integration tests
  

## License and Authors

Author:: Nikolay Murga (nikolay.m@randrmusic.com)