Commit a5a26e8a authored by Tugdual Saunier's avatar Tugdual Saunier

added initial set of files

parents
.kitchen
.kitchen.yml
Gemfile.lock
Berksfile.lock
/vendor
/bin
---
driver:
name: docker
platforms:
- name: debian-6
driver_config:
image: chef/debian-6
platform: debian
require_chef_omnibus: false
- name: debian-7
driver_config:
image: chef/debian-7
platform: debian
require_chef_omnibus: false
- name: ubuntu-12.04
driver_config:
image: chef/ubuntu-12.04
platform: ubuntu
require_chef_omnibus: false
- name: ubuntu-14.04
driver_config:
image: chef/ubuntu-14.04
platform: ubuntu
require_chef_omnibus: false
- name: centos-6.4
driver_config:
image: chef/centos-6
platform: centos
require_chef_omnibus: false
suites:
- name: docker
run_list:
- recipe[apt]
- recipe[blackfire::mock]
- recipe[blackfire]
attributes:
blackfire:
agent:
collector: 'http://127.0.0.1:8780'
server_id: 'foo'
server_token: 'bar'
restart_mode: 'immediately'
---
driver:
name: vagrant
platforms:
- name: debian-7.6
driver_config:
box: chef/debian-7.6
- name: ubuntu-14.04
- name: centos-6.4
- name: fedora-20
suites:
- name: default
run_list:
- recipe[apt]
- recipe[blackfire::mock]
- recipe[blackfire]
attributes:
blackfire:
agent:
collector: 'http://127.0.0.1:8780'
server_id: 'foo'
server_token: 'bar'
restart_mode: 'immediately'
Documentation:
Enabled: false
LineLength:
Enabled: false
Style/ExtraSpacing:
Enabled: false
sudo: false
language: ruby
rvm:
- 2.1.2
bundler_args: --without development --without kitchen_vagrant
cache: bundler
before_install:
- 'echo ''gem: --no-ri --no-rdoc'' > ~/.gemrc'
gemfile:
- Gemfile
script:
- bundle exec rake travis
source 'http://api.berkshelf.com'
metadata
group :integration do
cookbook 'apt'
end
# CHANGELOG for blackfire cookbook
This file is used to list changes made in each version of blackfire cookbook.
## 2.0.0:
* Initial open-source release of blackfire cookbook
* Added tests
* Use Blackfire.io's API to retrieve versions
* Added support for redhat based distributions
source 'https://rubygems.org'
ruby '2.1.2'
gem 'foodcritic'
gem 'rubocop'
gem 'rake'
group :development do
gem 'chefspec'
gem 'berkshelf'
gem 'test-kitchen'
gem 'kitchen-vagrant'
gem 'kitchen-docker'
end
group :deployment do
gem 'stove'
end
Copyright (c) 2014-2015 SensioLabs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
\ No newline at end of file
Blackfire Cookbook
===========================
This cookbook installs and configures the blackfire stack.
Requirements
------------
#### Platform
* Ubuntu (10.04/11.04/12.04/13.04/14.04)
* Debian (6.0/7.0)
* RedHat Based (CentOS 6.4 and Fedora 20 tested, others should work)
#### cookbooks
- apt
- yum
Attributes
----------
The following attributes are available to affect the installation/configuration of the Backfire stack
#### blackfire::default
* `node['blackfire']['agent']['version']` - Sets which version of the agent to install. Default last version.
* `node['blackfire']['agent']['server_id']` - Sets the Server ID to use for the agent (See https://blackfire.io/account/agents)
* `node['blackfire']['agent']['server_token']` - Sets the Server Token to use for the agent (See https://blackfire.io/account/agents)
* `node['blackfire']['agent']['log_level']` - Sets the logging level for the agent. Default 1
* `node['blackfire']['agent']['log_file']` - Sets where the agent write logs. Default "stderr"
* `node['blackfire']['agent']['socket']` - Sets where the socket the agent will listen to. Default "unix:///var/run/blackfire/agent.sock"
#### blackfire::php
* `node['blackfire']['php']['version']` - Sets which version of the PHP extension will be installed. Default last version.
* `node['blackfire']['php']['agent_timeout']` - Sets the PHP extension timeout when communicating with the agent. Default '0.25'
* `node['blackfire']['php']['log_level']` - Sets the logging level for the PHP extension.
* `node['blackfire']['php']['log_file']` - Sets where the PHP extension write logs.
* `node['blackfire']['php']['ini_path']` - Sets where the PHP configuration will be written.
Usage
-----
#### blackfire::default
Add agent Server ID and token and include `blackfire` in your node's `run_list`:
```json
{
"name":"my_node",
"run_list": [
"recipe[blackfire]"
],
"blackfire": {
"agent": {
"server_id": "my-agent-server-id",
"server_token": "my-agent-server-token"
}
}
}
```
#### blackfire::agent
Used if you wish to install only the agent.
#### blackfire::php
Used if you wish to install only the PHP extension.
### Note about blackfire::php
This cookbook makes no assumption about the webserver you use.
Therefore this is *your* responsability to write a wrapper and notify your
webserver (ie. Apache or php5-fpm) for reload/restart or subscribe the good
resources.
You can obtain futher informations on wrapper cookbooks here:
https://www.getchef.com/blog/2013/12/03/doing-wrapper-cookbooks-right/
One way to do that (maybe the best to avoid disturbing logs messages):
```ruby
include_recipe "blackfire"
begin
r = resources(:ruby_block => "blackfire-php-restart-webserver")
r.block do
end
r.notifies :reload, "service[php5-fpm]"
rescue Chef::Exceptions::ResourceNotFound
Chef::Log.warn 'could not find resource "ruby_block[blackfire-php-restart-webserver]" to override!'
end
```
Contributing
------------
1. Fork the repository on Github
2. Create a named feature branch (like `add_component_x`)
3. Write you change
4. Write tests for your change (if applicable)
5. Run the tests, ensuring they all pass
6. Submit a Pull Request using Github
Tests
-----
Three test suites exist:
- two using kitchen.ci (meant to be run localy by contributors)
- one using rspec (meant to be run by travis, not localy).
These test suites can be launched by using `rake integration:vagrant` or
`rake integration:docker` for the kitchen.ci one and `rake travis` for rspec.
Supermarket share
-----------------
You need [stove](http://sethvargo.github.io/stove/) to publish the cookbook on
supermarket. Once it's done use `rake publish`
License and Authors
-------------------
- Author:: Tugdual Saunier (<tugdual.saunier@sensiolabs.com>)
```text
Copyright:: 2014-2015 SensioLabs
See LICENSE file
```
require './libraries/blackfire_versions_helper.rb'
require './libraries/blackfire_collector_mock.rb'
require 'rspec/core/rake_task'
require 'stove/rake_task'
require 'rubocop/rake_task'
require 'foodcritic'
require 'kitchen'
# Style tests. Rubocop and Foodcritic
namespace :style do
desc 'Run Ruby style checks'
RuboCop::RakeTask.new(:ruby)
desc 'Run Chef style checks'
FoodCritic::Rake::LintTask.new(:chef)
end
desc 'Run all style checks'
task style: ['style:chef', 'style:ruby']
# Rspec and ChefSpec
desc 'Run ChefSpec examples'
RSpec::Core::RakeTask.new(:spec)
# Integration tests. Kitchen.ci
namespace :integration do
desc 'Run Kitchen Tests with Vagrant'
task :vagrant do
Kitchen.logger = Kitchen.default_file_logger
@loader = Kitchen::Loader::YAML.new(project_config: './.kitchen.vagrant.yml')
Kitchen::Config.new(loader: @loader).instances.each do |instance|
instance.test(:always)
end
end
desc 'Run Kitchen Tests with Docker'
task :docker do
Kitchen.logger = Kitchen.default_file_logger
@loader = Kitchen::Loader::YAML.new(project_config: './.kitchen.docker.yml')
Kitchen::Config.new(loader: @loader).instances.each do |instance|
instance.test(:always)
end
end
desc 'Run Kitchen Tests with cloud plugins'
task :cloud do
run_kitchen = true
if ENV['TRAVIS'] == 'true' && ENV['TRAVIS_PULL_REQUEST'] != 'false'
run_kitchen = false
end
if run_kitchen
Kitchen.logger = Kitchen.default_file_logger
@loader = Kitchen::Loader::YAML.new(project_config: './.kitchen.cloud.yml')
config = Kitchen::Config.new(loader: @loader)
config.instances.each do |instance|
instance.test(:always)
end
end
end
end
namespace :blackfire do
desc 'Show current blackfire versions packages'
task :versions do
puts "Agent: #{Blackfire::Versions.agent}"
puts "Probe: #{Blackfire::Versions.probe}"
end
namespace :collector do
desc 'Run the mock collector for debug purpose'
task :mock do
Blackfire::CollectorMock.run('http://localhost:8780')
sleep(10)
end
end
end
desc 'Deploy to supermarket'
Stove::RakeTask.new
desc 'Run all tests on Travis'
task travis: %w(style blackfire:versions spec)
# Default
task default: %w(style integration:vagrant)
#
# Author:: Tugdual Saunier (<tugdual.saunier@sensiolabs.com>)
# Cookbook Name:: blackfire
# Attributes:: default
#
# Copyright 2014-2015, SensioLabs
default['blackfire']['repository'] = 'http://packages.blackfire.io'
default['blackfire']['install_repository'] = true
default['blackfire']['agent']['version'] = nil
default['blackfire']['agent']['collector'] = 'https://blackfire.io'
default['blackfire']['agent']['server_id'] = nil
default['blackfire']['agent']['server_token'] = nil
default['blackfire']['agent']['log_level'] = 1
default['blackfire']['agent']['log_file'] = 'stderr'
default['blackfire']['agent']['socket'] = 'unix:///var/run/blackfire/agent.sock'
default['blackfire']['agent']['restart_mode'] = :delayed
#
# Author:: Tugdual Saunier (<tugdual.saunier@sensiolabs.com>)
# Cookbook Name:: blackfire
# Attributes:: php
#
# Copyright 2014-2015, SensioLabs
default['blackfire']['php']['version'] = nil
default['blackfire']['php']['agent_timeout'] = '0.25'
default['blackfire']['php']['log_level'] = nil
default['blackfire']['php']['log_file'] = nil
if platform_family?('rhel', 'fedora')
default['blackfire']['php']['ini_path'] = '/etc/php.d/zz-blackfire.ini'
elsif platform?('debian') && node['platform_version'].to_f < 7.0
default['blackfire']['php']['ini_path'] = '/etc/php5/conf.d/blackfire.ini'
elsif platform?('ubuntu') && node['platform_version'].to_f <= 13.04
default['blackfire']['php']['ini_path'] = '/etc/php5/conf.d/blackfire.ini'
else
default['blackfire']['php']['ini_path'] = '/etc/php5/mods-available/blackfire.ini'
end
require 'socket'
require 'uri'
module Blackfire
class CollectorMock
@response = <<EOS
{
"publicKey":"RWTZMyTkp\/ZMEwdZQRRpANepfi5+3i9Kex2f89EYv7o9KHaIPC\/THc19",
"signature":"RWTZMyTkp\/ZME54jWsRriZrRqXgdoVKLT47AFsuf+gywfgjldfkcnx",
"expires":"20480101"
}
EOS
@headers = "HTTP/1.1 200 OK\r\n" \
"Content-Type: application/json\r\n" \
"Content-Length: #{@response.bytesize}\r\n" \
"Connection: close\r\n" \
"\r\n"
def self.run(endpoint = nil)
uri = URI.parse(endpoint)
server = TCPServer.new(uri.host, uri.port)
Thread.new { listen(server) }
end
def self.listen(server)
loop do
socket = server.accept
socket.gets
socket.print @headers
socket.print @response
socket.close
end
end
end
end
require 'net/http'
require 'json'
module Blackfire
class Versions
@endpoint = 'https://blackfire.io'
def self.agent(node = nil)
fetch_versions(node)['agent']
end
def self.probe(node = nil)
fetch_versions(node)['probe']['php']
end
def self.fetch_versions(node = nil)
return @versions if @versions
@versions = JSON.parse(fetch_releases(node))
end
def self.fetch_releases(node = nil)
uri = URI.parse("#{get_endpoint(node)}/api/v1/releases")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = 'https' == uri.scheme
response = http.get(uri.request_uri)
fail 'Impossible to fetch Blackfire versions' unless '200' == response.code
response.body
end
def self.get_endpoint(node = nil)
return node['blackfire']['releases_endpoint'] if node && node['blackfire'].key?('releases_endpoint')
@endpoint
end
end
end
name 'blackfire'
maintainer 'SensioLabs'
maintainer_email 'support@sensiolabs.com'
license 'MIT'
description 'Installs and configures blackfire stack'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '2.0.0'
recipe 'default', 'Installs blackfire-php & blackfire-agent.'
recipe 'php', 'Installs only blackfire-php'
recipe 'agent', 'Installs only blackfire-agent'
recipe 'repository', 'Setup Blackfire repository'
supports 'debian'
supports 'ubuntu'
supports 'redhat'
supports 'fedora'
supports 'centos'
depends 'apt'
depends 'yum'
#
# Cookbook Name:: blackfire
# Recipe:: agent
#
# Copyright 2014-2015, SensioLabs
# See LICENSE file
#
include_recipe "#{cookbook_name}::repository"
agent_version = node[cookbook_name]['agent']['version'] ? node[cookbook_name]['agent']['version'] : Blackfire::Versions.agent(node)
agent_version << '-1' if platform_family?('rhel', 'fedora')
package 'blackfire-agent' do
version agent_version
end
template '/etc/blackfire/agent' do
source 'agent.erb'
variables(
'ca_cert' => node[cookbook_name]['agent']['ca_cert'],
'collector' => node[cookbook_name]['agent']['collector'],
'server_id' => node[cookbook_name]['agent']['server_id'],
'server_token' => node[cookbook_name]['agent']['server_token'],
'log_file' => node[cookbook_name]['agent']['log_file'],
'log_level' => node[cookbook_name]['agent']['log_level'],
'socket' => node[cookbook_name]['agent']['socket'],
'spec' => node[cookbook_name]['agent']['spec']
)
end
service 'blackfire-agent' do
supports status: true, start: true, stop: true, restart: true
action [:enable]
subscribes :restart, 'template[/etc/blackfire/agent]', node[cookbook_name]['agent']['restart_mode']
end
#
# Cookbook Name:: blackfire
# Recipe:: default
#
# Copyright 2014-2015, SensioLabs
# See LICENSE file
#
include_recipe "#{cookbook_name}::agent"
include_recipe "#{cookbook_name}::php"
#
# Cookbook Name:: blackfire
# Recipe:: mock
#
# Copyright 2014-2015, SensioLabs
# See LICENSE file
#
ruby_block 'run Blackfire Collector Mock' do
block do
Blackfire::CollectorMock.run(node[cookbook_name]['agent']['collector'])
end
end
#
# Cookbook Name:: blackfire
# Recipe:: php
#
# Copyright 2014-2015, SensioLabs
# See LICENSE file
#
include_recipe "#{cookbook_name}::repository"
ruby_block 'blackfire-php-restart-webserver' do
block do
Chef::Log.warn "\033[31mBlackfire PHP extension has been updated.\033[0m"
Chef::Log.warn "\033[31mPlease restart your WebServers or\033[0m"
Chef::Log.warn "\033[31mconsider having your resources subscribing to\033[0m"
Chef::Log.warn "\033[31mblackfire::php resources\033[0m"
end
action :nothing
end
probe_version = node[cookbook_name]['php']['version'] ? node[cookbook_name]['php']['version'] : Blackfire::Versions.probe(node)
probe_version << '-1' if platform_family?('rhel', 'fedora')
package 'blackfire-php' do
version probe_version
notifies :run, 'ruby_block[blackfire-php-restart-webserver]'
end
template node[cookbook_name]['php']['ini_path'] do
source 'blackfire.ini.erb'
variables(
'agent_timeout' => node[cookbook_name]['php']['agent_timeout'],
'log_file' => node[cookbook_name]['php']['log_file'],
'log_level' => node[cookbook_name]['php']['log_level'],
'socket' => node[cookbook_name]['agent']['socket']
)
notifies :run, 'ruby_block[blackfire-php-restart-webserver]', :immediately
end