Skip to content
This repository has been archived by the owner on Dec 31, 2022. It is now read-only.

Commit

Permalink
feat(logrotate): implement logrotate
Browse files Browse the repository at this point in the history
Currently, frameworks (rails) and webservers (apache2 and nginx) are
supported.

Resolves #78
  • Loading branch information
ajgon committed Apr 25, 2017
1 parent e216972 commit 86ebc10
Show file tree
Hide file tree
Showing 14 changed files with 165 additions and 8 deletions.
1 change: 1 addition & 0 deletions attributes/default.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
%w(tmp public config ../../shared/cache ../../shared/assets)
default['defaults']['global']['purge_before_symlink'] = %w(log tmp/cache tmp/pids public/system public/assets)
default['defaults']['global']['rollback_on_error'] = true
default['defaults']['global']['logrotate_rotate'] = 30

# database
## common
Expand Down
6 changes: 6 additions & 0 deletions docs/source/attributes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ Global parameters apply to the whole application, and can be used by any section
- **Default:** ``true``
- When set to true, any failed deploy will be removed from ``releases`` directory.

- ``app['global']['logrotate_rotate']``

- **Type:** integer
- **Default:** ``30``
- **Important Notice:** The parameter is in days

database
~~~~~~~~

Expand Down
48 changes: 48 additions & 0 deletions libraries/drivers_dsl_logrotate.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# frozen_string_literal: true

module Drivers
module Dsl
module Logrotate
def self.included(klass)
klass.instance_eval do
def log_paths(*log_paths)
@log_paths ||= []
@log_paths += Array.wrap(log_paths)
@log_paths
end
end
end
# rubocop:enable Metrics/MethodLength

def log_paths
self.class.log_paths.presence ||
(self.class.superclass.respond_to?(:log_paths) && self.class.superclass.log_paths)
end

def configure_logrotate
return if (log_paths || []).empty?
lr_path = logrotate_log_paths
lr_rotate = logrotate_rotate

context.logrotate_app "#{app['shortname']}-#{adapter}-#{deploy_env}" do
path lr_path
frequency 'daily'
rotate lr_rotate
options %w[missingok compress delaycompress notifempty copytruncate sharedscripts]
end
end

def logrotate_log_paths
log_paths.map do |log_path|
next log_path.call(self) if log_path.is_a?(Proc)
next log_path if log_path.start_with?('/')
File.join(deploy_dir(app), log_path)
end.flatten.uniq
end

def logrotate_rotate
globals(:logrotate_rotate, app['shortname'])
end
end
end
end
5 changes: 5 additions & 0 deletions libraries/drivers_framework_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@
module Drivers
module Framework
class Base < Drivers::Base
include Drivers::Dsl::Logrotate
include Drivers::Dsl::Output
include Drivers::Dsl::Packages

def setup
handle_packages
end

def configure
configure_logrotate
end

def deploy_before_migrate
link_sqlite_database
end
Expand Down
1 change: 1 addition & 0 deletions libraries/drivers_framework_hanami.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def raw_out

def configure
build_env
super
end

def deploy_before_restart
Expand Down
4 changes: 4 additions & 0 deletions libraries/drivers_framework_rails.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ class Rails < Drivers::Framework::Base
:envs_in_console
]
packages debian: 'zlib1g-dev', rhel: 'zlib-devel'
log_paths lambda { |context|
File.join(context.send(:deploy_dir, context.app), 'shared', 'log', "#{context.send(:deploy_env)}.log")
}

def raw_out
super.merge(deploy_environment: { 'RAILS_ENV' => deploy_env })
Expand All @@ -20,6 +23,7 @@ def configure
rdses.each do |rds|
database_yml(Drivers::Db::Factory.build(context, app, rds: rds))
end
super
end

def deploy_after_restart
Expand Down
6 changes: 6 additions & 0 deletions libraries/drivers_webserver_apache2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ class Apache2 < Drivers::Webserver::Base
action: :restart, resource: { debian: 'service[apache2]', rhel: 'service[httpd]' }, timer: :delayed
notifies :undeploy,
action: :restart, resource: { debian: 'service[apache2]', rhel: 'service[httpd]' }, timer: :delayed
log_paths lambda { |context|
%w[access.log error.log].map do |log_type|
File.join(context.raw_out[:log_dir], "#{context.app[:domains].first}.#{log_type}")
end
}

def raw_out
output = node['defaults']['webserver'].merge(
Expand Down Expand Up @@ -40,6 +45,7 @@ def configure
remove_defaults
add_appserver_config
enable_appserver_config
super
end

def before_deploy
Expand Down
5 changes: 5 additions & 0 deletions libraries/drivers_webserver_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@
module Drivers
module Webserver
class Base < Drivers::Base
include Drivers::Dsl::Logrotate
include Drivers::Dsl::Notifies
include Drivers::Dsl::Output
include Drivers::Dsl::Packages

def configure
configure_logrotate
end

def out
handle_output(raw_out)
end
Expand Down
6 changes: 6 additions & 0 deletions libraries/drivers_webserver_nginx.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ class Nginx < Drivers::Webserver::Base
]
notifies :deploy, action: :restart, resource: 'service[nginx]', timer: :delayed
notifies :undeploy, action: :restart, resource: 'service[nginx]', timer: :delayed
log_paths lambda { |context|
%w[access.log error.log].map do |log_type|
File.join(context.raw_out[:log_dir], "#{context.app[:domains].first}.#{log_type}")
end
}

def raw_out
output = node['defaults']['webserver'].merge(node['nginx']).merge(
Expand All @@ -36,6 +41,7 @@ def configure

add_appserver_config
enable_appserver_config
super
end

def before_deploy
Expand Down
3 changes: 2 additions & 1 deletion metadata.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
version '1.4.0'

depends 'deployer'
depends 'ruby-ng'
depends 'chef_nginx'
depends 'logrotate'
depends 'ruby-ng'

supports 'amazon', '>= 2015.03'
supports 'ubuntu', '>= 12.04'
Expand Down
43 changes: 36 additions & 7 deletions spec/unit/recipes/configure_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,16 @@
)
end

it 'creates logrotate file for rails' do
expect(chef_run)
.to enable_logrotate_app("#{aws_opsworks_app['shortname']}-rails-staging")
end

it 'creates logrotate file for nginx' do
expect(chef_run)
.to enable_logrotate_app("#{aws_opsworks_app['shortname']}-nginx-staging")
end

it 'creates proper unicorn.conf file' do
expect(chef_run)
.to render_file("/srv/www/#{aws_opsworks_app['shortname']}/shared/config/unicorn.conf")
Expand Down Expand Up @@ -332,6 +342,11 @@
stub_search(:aws_opsworks_rds_db_instance, '*:*').and_return([aws_opsworks_rds_db_instance(engine: 'mysql')])
end

it 'creates logrotate file for apache2' do
expect(chef_run)
.to enable_logrotate_app("#{aws_opsworks_app['shortname']}-apache2-staging")
end

it 'creates proper .env.*' do
db_config =
Drivers::Db::Mysql.new(chef_run, aws_opsworks_app, rds: aws_opsworks_rds_db_instance(engine: 'mysql')).out
Expand Down Expand Up @@ -895,13 +910,27 @@
end
end

it 'empty node[\'deploy\']' do
chef_run = ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '14.04') do |solo_node|
solo_node.set['lsb'] = node['lsb']
end.converge(described_recipe)
context 'empty node[\'deploy\']' do
let(:chef_run) do
ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '14.04') do |solo_node|
solo_node.set['lsb'] = node['lsb']
end.converge(described_recipe)
end

it 'not raises error' do
expect do
chef_run
end.not_to raise_error
end

expect do
chef_run
end.not_to raise_error
it 'creates logrotate file for rails' do
expect(chef_run)
.to enable_logrotate_app("#{aws_opsworks_app['shortname']}-rails-production")
end

it 'creates logrotate file for rails' do
expect(chef_run)
.to enable_logrotate_app("#{aws_opsworks_app['shortname']}-nginx-production")
end
end
end
3 changes: 3 additions & 0 deletions spec/unit/recipes/deploy_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,9 @@
expect(chef_run).to create_template('/srv/www/a1/shared/scripts/puma.service')
expect(chef_run).to create_template('/etc/nginx/sites-available/a1.conf')
expect(chef_run).to create_link('/etc/nginx/sites-enabled/a1.conf')
expect(chef_run).to enable_logrotate_app('a1-nginx-production')
expect(chef_run).to enable_logrotate_app('a1-rails-production')

expect(service).to do_nothing
expect(chef_run).to deploy_deploy('a1')
expect(chef_run).not_to deploy_deploy('a2')
Expand Down
27 changes: 27 additions & 0 deletions test/integration/default/serverspec/default_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,21 @@

describe 'opsworks_ruby::configure' do
context 'webserver' do
describe file('/etc/logrotate.d/dummy_project-nginx-production') do
its(:content) do
should include '"/var/log/nginx/dummy-project.example.com.access.log" ' \
'"/var/log/nginx/dummy-project.example.com.error.log" {'
end
its(:content) { should include ' daily' }
its(:content) { should include ' rotate 30' }
its(:content) { should include ' missingok' }
its(:content) { should include ' compress' }
its(:content) { should include ' delaycompress' }
its(:content) { should include ' notifempty' }
its(:content) { should include ' copytruncate' }
its(:content) { should include ' sharedscripts' }
end

describe file('/etc/nginx/ssl/dummy-project.example.com.key') do
its(:content) { should include '-----BEGIN RSA PRIVATE KEY-----' }
end
Expand Down Expand Up @@ -68,6 +83,18 @@
end

context 'framework' do
describe file('/etc/logrotate.d/dummy_project-rails-production') do
its(:content) { should include '"/srv/www/dummy_project/shared/log/production.log" {' }
its(:content) { should include ' daily' }
its(:content) { should include ' rotate 30' }
its(:content) { should include ' missingok' }
its(:content) { should include ' compress' }
its(:content) { should include ' delaycompress' }
its(:content) { should include ' notifempty' }
its(:content) { should include ' copytruncate' }
its(:content) { should include ' sharedscripts' }
end

describe file('/srv/www/dummy_project/current/config/database.yml') do
its(:content) { should include 'adapter: sqlite3' }
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,21 @@

describe 'opsworks_ruby::configure' do
context 'webserver' do
describe file('/etc/logrotate.d/dummy_project-apache2-production') do
its(:content) do
should include '"/var/log/apache2/dummy-project.example.com.access.log" ' \
'"/var/log/apache2/dummy-project.example.com.error.log" {'
end
its(:content) { should include ' daily' }
its(:content) { should include ' rotate 30' }
its(:content) { should include ' missingok' }
its(:content) { should include ' compress' }
its(:content) { should include ' delaycompress' }
its(:content) { should include ' notifempty' }
its(:content) { should include ' copytruncate' }
its(:content) { should include ' sharedscripts' }
end

describe file('/etc/apache2/ssl/dummy-project.example.com.key') do
its(:content) { should include '-----BEGIN RSA PRIVATE KEY-----' }
end
Expand Down

0 comments on commit 86ebc10

Please sign in to comment.