diff --git a/.gitignore b/.gitignore
index 54e2457..2046da8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
metadata.json
+.kitchen/
+.kitchen.local.yml
diff --git a/.kitchen.yml b/.kitchen.yml
new file mode 100644
index 0000000..a81fdf9
--- /dev/null
+++ b/.kitchen.yml
@@ -0,0 +1,30 @@
+---
+busser:
+ root_path: /var/tmp/kitchen
+
+driver:
+ name: vagrant
+
+provisioner:
+ name: chef_solo
+ kitchen_root: /var/tmp/kitchen
+
+platforms:
+ - name: ubuntu-12.04
+ - name: centos-6.4
+
+suites:
+ - name: package
+ run_list:
+ - recipe[redis2::default_instance]
+ attributes:
+ redis2:
+ install_from: package
+ excludes:
+ - centos-6.4
+ - name: source
+ run_list:
+ - recipe[redis2::default_instance]
+ attributes:
+ redis2:
+ install_from: source
diff --git a/.rspec b/.rspec
new file mode 100644
index 0000000..16f9cdb
--- /dev/null
+++ b/.rspec
@@ -0,0 +1,2 @@
+--color
+--format documentation
diff --git a/Berksfile b/Berksfile
index c4bb297..2e1a070 100644
--- a/Berksfile
+++ b/Berksfile
@@ -1,3 +1,3 @@
-site :opscode
+source "https://api.berkshelf.com"
metadata
diff --git a/Berksfile.lock b/Berksfile.lock
new file mode 100644
index 0000000..1c8d2ec
--- /dev/null
+++ b/Berksfile.lock
@@ -0,0 +1,30 @@
+DEPENDENCIES
+ redis2
+ path: .
+ metadata: true
+
+GRAPH
+ 7-zip (1.0.2)
+ windows (>= 1.2.2)
+ ark (0.9.0)
+ 7-zip (>= 0.0.0)
+ windows (>= 0.0.0)
+ build-essential (2.0.6)
+ chef_handler (1.1.6)
+ ohai (2.0.1)
+ redis2 (0.5.1)
+ ark (>= 0.0.0)
+ build-essential (>= 0.0.0)
+ runit (>= 1.0.0)
+ sysctl (>= 0.0.0)
+ runit (1.5.10)
+ build-essential (>= 0.0.0)
+ yum (~> 3.0)
+ yum-epel (>= 0.0.0)
+ sysctl (0.6.0)
+ ohai (>= 0.0.0)
+ windows (1.34.6)
+ chef_handler (>= 0.0.0)
+ yum (3.3.2)
+ yum-epel (0.5.1)
+ yum (~> 3.0)
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..5b7cb4b
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,7 @@
+source 'https://rubygems.org'
+
+gem 'berkshelf'
+gem 'test-kitchen'
+gem 'busser-serverspec'
+gem 'kitchen-vagrant'
+gem 'chefspec'
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 0000000..1097003
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,193 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ addressable (2.3.6)
+ berkshelf (3.1.3)
+ addressable (~> 2.3.4)
+ berkshelf-api-client (~> 1.2)
+ buff-config (~> 1.0)
+ buff-extensions (~> 1.0)
+ buff-shell_out (~> 0.1)
+ celluloid (~> 0.16.0.pre)
+ celluloid-io (~> 0.16.0.pre)
+ faraday (~> 0.9.0)
+ minitar (~> 0.5.4)
+ octokit (~> 3.0)
+ retryable (~> 1.3.3)
+ ridley (~> 4.0)
+ solve (~> 1.1)
+ thor (~> 0.18)
+ berkshelf-api-client (1.2.0)
+ faraday (~> 0.9.0)
+ buff-config (1.0.1)
+ buff-extensions (~> 1.0)
+ varia_model (~> 0.4)
+ buff-extensions (1.0.0)
+ buff-ignore (1.1.1)
+ buff-ruby_engine (0.1.0)
+ buff-shell_out (0.1.1)
+ buff-ruby_engine (~> 0.1.0)
+ busser (0.6.0)
+ thor
+ busser-serverspec (0.2.6)
+ busser
+ celluloid (0.16.0.pre3)
+ timers (~> 4.0.0)
+ celluloid-io (0.16.0.pre2)
+ celluloid (>= 0.16.0.pre)
+ nio4r (>= 1.0.0)
+ chef (11.16.2)
+ chef-zero (~> 2.1, >= 2.1.4)
+ diff-lcs (~> 1.2, >= 1.2.4)
+ erubis (~> 2.7)
+ ffi-yajl (~> 1.0)
+ highline (~> 1.6, >= 1.6.9)
+ mime-types (~> 1.16)
+ mixlib-authentication (~> 1.3)
+ mixlib-cli (~> 1.4)
+ mixlib-config (~> 2.0)
+ mixlib-log (~> 1.3)
+ mixlib-shellout (~> 1.4)
+ net-ssh (~> 2.6)
+ net-ssh-multi (~> 1.1)
+ ohai (~> 7.4)
+ plist (~> 3.1.0)
+ pry (~> 0.9)
+ rest-client (>= 1.0.4, <= 1.6.7)
+ chef-zero (2.2)
+ hashie (~> 2.0)
+ json
+ mixlib-log (~> 1.3)
+ rack
+ chefspec (4.0.2)
+ chef (~> 11.12)
+ fauxhai (~> 2.0)
+ rspec (~> 3.0)
+ coderay (1.1.0)
+ dep-selector-libgecode (1.0.2)
+ dep_selector (1.0.3)
+ dep-selector-libgecode (~> 1.0)
+ ffi (~> 1.9)
+ diff-lcs (1.2.5)
+ erubis (2.7.0)
+ faraday (0.9.0)
+ multipart-post (>= 1.2, < 3)
+ fauxhai (2.2.0)
+ net-ssh
+ ohai
+ ffi (1.9.3)
+ ffi-yajl (1.1.0)
+ ffi (~> 1.5)
+ libyajl2 (~> 1.0)
+ hashie (2.1.2)
+ highline (1.6.21)
+ hitimes (1.2.2)
+ ipaddress (0.8.0)
+ json (1.8.1)
+ kitchen-vagrant (0.15.0)
+ test-kitchen (~> 1.0)
+ libyajl2 (1.0.1)
+ method_source (0.8.2)
+ mime-types (1.25.1)
+ minitar (0.5.4)
+ mixlib-authentication (1.3.0)
+ mixlib-log
+ mixlib-cli (1.5.0)
+ mixlib-config (2.1.0)
+ mixlib-log (1.6.0)
+ mixlib-shellout (1.4.0)
+ multipart-post (2.0.0)
+ net-http-persistent (2.9.4)
+ net-scp (1.2.1)
+ net-ssh (>= 2.6.5)
+ net-ssh (2.9.1)
+ net-ssh-gateway (1.2.0)
+ net-ssh (>= 2.6.5)
+ net-ssh-multi (1.2.0)
+ net-ssh (>= 2.6.5)
+ net-ssh-gateway (>= 1.2.0)
+ nio4r (1.0.0)
+ octokit (3.2.0)
+ sawyer (~> 0.5.3)
+ ohai (7.4.0)
+ ffi (~> 1.9)
+ ffi-yajl (~> 1.0)
+ ipaddress
+ mime-types (~> 1.16)
+ mixlib-cli
+ mixlib-config (~> 2.0)
+ mixlib-log
+ mixlib-shellout (~> 1.2)
+ systemu (~> 2.6.4)
+ wmi-lite (~> 1.0)
+ plist (3.1.0)
+ pry (0.10.1)
+ coderay (~> 1.1.0)
+ method_source (~> 0.8.1)
+ slop (~> 3.4)
+ rack (1.5.2)
+ rest-client (1.6.7)
+ mime-types (>= 1.16)
+ retryable (1.3.5)
+ ridley (4.0.0)
+ addressable
+ buff-config (~> 1.0)
+ buff-extensions (~> 1.0)
+ buff-ignore (~> 1.1)
+ buff-shell_out (~> 0.1)
+ celluloid (~> 0.16.0.pre)
+ celluloid-io (~> 0.16.0.pre)
+ erubis
+ faraday (~> 0.9.0)
+ hashie (>= 2.0.2, < 3.0.0)
+ json (>= 1.7.7)
+ mixlib-authentication (>= 1.3.0)
+ net-http-persistent (>= 2.8)
+ retryable
+ semverse (~> 1.1)
+ varia_model (~> 0.4)
+ rspec (3.1.0)
+ rspec-core (~> 3.1.0)
+ rspec-expectations (~> 3.1.0)
+ rspec-mocks (~> 3.1.0)
+ rspec-core (3.1.5)
+ rspec-support (~> 3.1.0)
+ rspec-expectations (3.1.2)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.1.0)
+ rspec-mocks (3.1.2)
+ rspec-support (~> 3.1.0)
+ rspec-support (3.1.1)
+ safe_yaml (1.0.3)
+ sawyer (0.5.4)
+ addressable (~> 2.3.5)
+ faraday (~> 0.8, < 0.10)
+ semverse (1.2.1)
+ slop (3.6.0)
+ solve (1.2.0)
+ dep_selector (~> 1.0)
+ semverse (~> 1.1)
+ systemu (2.6.4)
+ test-kitchen (1.2.1)
+ mixlib-shellout (~> 1.2)
+ net-scp (~> 1.1)
+ net-ssh (~> 2.7)
+ safe_yaml (~> 1.0)
+ thor (~> 0.18)
+ thor (0.19.1)
+ timers (4.0.0)
+ hitimes
+ varia_model (0.4.0)
+ buff-extensions (~> 1.0)
+ hashie (>= 2.0.2, < 3.0.0)
+ wmi-lite (1.0.0)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ berkshelf
+ busser-serverspec
+ chefspec
+ kitchen-vagrant
+ test-kitchen
diff --git a/README.rdoc b/README.rdoc
index 3caac9d..a6990b5 100644
--- a/README.rdoc
+++ b/README.rdoc
@@ -17,10 +17,11 @@ redis_instance "datastore" do
port 8866
data_dir "/mnt/redis/datastore"
master master_node
+ nofile 16384
end
-_port_, data_dir and _master_ are the only attributes directly configurable using the definition syntax. Other attributes can be configured using the normal attribute interface under the node["redis2"]["instances"][instance_name] scope. Missing attributes will be merged from node["redis2"]["instances"]["default"]
+_nofile_, _port_, data_dir and _master_ are the only attributes directly configurable using the definition syntax. Other attributes can be configured using the normal attribute interface under the node["redis2"]["instances"][instance_name] scope. Missing attributes will be merged from node["redis2"]["instances"]["default"]
The _master_ attribute will set up redis as a slave of a the same redis instance on another server. It will not set node["redis2"]["instances"][instance_name]["replication"]["role"] (which can be _slave_ or _master_), because redis can be both at the same time (e.g. chained masters).
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..e9449f6
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,24 @@
+require 'rake'
+require 'rspec/core/rake_task'
+
+task :spec => 'spec:all'
+task :default => :spec
+
+namespace :spec do
+ targets = []
+ Dir.glob('./spec/*').each do |dir|
+ next unless File.directory?(dir)
+ targets << File.basename(dir)
+ end
+
+ task :all => targets
+ task :default => :all
+
+ targets.each do |target|
+ desc "Run serverspec tests to #{target}"
+ RSpec::Core::RakeTask.new(target.to_sym) do |t|
+ ENV['TARGET_HOST'] = target
+ t.pattern = "spec/#{target}/*_spec.rb"
+ end
+ end
+end
diff --git a/Thorfile b/Thorfile
new file mode 100644
index 0000000..b23ee16
--- /dev/null
+++ b/Thorfile
@@ -0,0 +1,12 @@
+# encoding: utf-8
+
+require 'bundler'
+require 'bundler/setup'
+require 'berkshelf/thor'
+
+begin
+ require 'kitchen/thor_tasks'
+ Kitchen::ThorTasks.new
+rescue LoadError
+ puts ">>>>> Kitchen gem not loaded, omitting tasks" unless ENV['CI']
+end
diff --git a/chefignore b/chefignore
new file mode 100644
index 0000000..a6de142
--- /dev/null
+++ b/chefignore
@@ -0,0 +1,96 @@
+# Put files/directories that should be ignored in this file when uploading
+# or sharing to the community site.
+# Lines that start with '# ' are comments.
+
+# OS generated files #
+######################
+.DS_Store
+Icon?
+nohup.out
+ehthumbs.db
+Thumbs.db
+
+# SASS #
+########
+.sass-cache
+
+# EDITORS #
+###########
+\#*
+.#*
+*~
+*.sw[a-z]
+*.bak
+REVISION
+TAGS*
+tmtags
+*_flymake.*
+*_flymake
+*.tmproj
+.project
+.settings
+mkmf.log
+
+## COMPILED ##
+##############
+a.out
+*.o
+*.pyc
+*.so
+*.com
+*.class
+*.dll
+*.exe
+*/rdoc/
+
+# Testing #
+###########
+.watchr
+.rspec
+spec/*
+spec/fixtures/*
+test/*
+features/*
+Guardfile
+Procfile
+
+# SCM #
+#######
+.git
+*/.git
+.gitignore
+.gitmodules
+.gitconfig
+.gitattributes
+.svn
+*/.bzr/*
+*/.hg/*
+*/.svn/*
+
+# Berkshelf #
+#############
+Berksfile
+Berksfile.lock
+cookbooks/*
+tmp
+
+# Cookbooks #
+#############
+CONTRIBUTING
+CHANGELOG*
+
+# Strainer #
+############
+Colanderfile
+Strainerfile
+.colander
+.strainer
+
+# Vagrant #
+###########
+.vagrant
+Vagrantfile
+
+# Travis #
+##########
+.travis.yml
diff --git a/definitions/instance.rb b/definitions/instance.rb
index d69ae51..5252c58 100644
--- a/definitions/instance.rb
+++ b/definitions/instance.rb
@@ -1,4 +1,10 @@
-define :redis_instance, :port => nil, :data_dir => nil, :master => nil, :service_timeouts => Hash.new do
+define(:redis_instance,
+ :port => nil,
+ :data_dir => nil,
+ :master => nil,
+ :service_timeouts => Hash.new,
+ :nofile => 16384
+) do
raise ::Chef::Exceptions::InvalidResourceSpecification, "redis instance name can't be \"default\"" \
if params[:name] == "default"
include_recipe "redis2"
@@ -75,9 +81,10 @@
log_template_name "redis"
cookbook "redis2"
options \
- :user => node["redis2"]["user"],
+ :user => node["redis2"]["user"],
:config_file => ::File.join(node["redis2"]["conf_dir"], "#{instance_name}.conf"),
- :timeouts => uplevel_params[:service_timeouts]
+ :timeouts => uplevel_params[:service_timeouts],
+ :nofile => uplevel_params[:nofile]
end
end
diff --git a/metadata.rb b/metadata.rb
index 95a1c5a..300fc8d 100644
--- a/metadata.rb
+++ b/metadata.rb
@@ -4,7 +4,7 @@
description "Installs/Configures redis"
long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
name "redis2"
-version "0.5.0"
+version "0.5.1"
supports "ubuntu", ">= 9.04"
supports "debian", ">= 6.0"
@@ -13,6 +13,7 @@
depends "runit", ">= 1.0.0"
depends "build-essential"
depends "ark"
+depends "sysctl"
recipe "redis2", "Installs and configures redis"
recipe "redis2::auto", "Configures and activates redis instances defined by attributes"
diff --git a/recipes/default.rb b/recipes/default.rb
index b98a86e..f6e8052 100644
--- a/recipes/default.rb
+++ b/recipes/default.rb
@@ -17,6 +17,12 @@
# limitations under the License.
#
include_recipe "runit"
+include_recipe "sysctl"
+
+sysctl_param "vm.overcommit_memory" do
+ value 1
+end
+
if node["redis2"]["install_from"] == "package"
include_recipe "redis2::package"
else
diff --git a/spec/redis2_spec.rb b/spec/redis2_spec.rb
new file mode 100644
index 0000000..8c34354
--- /dev/null
+++ b/spec/redis2_spec.rb
@@ -0,0 +1,34 @@
+require_relative 'spec_helper'
+
+describe "redis2::default" do
+ let(:chef_run) { ChefSpec::Runner.new }
+
+ it "Runs redis2::source and correctly sets node['redis2']['daemon']" do
+ chef_run.node.set['redis2']['install_from'] = "source"
+ chef_run.converge(described_recipe)
+ expect(chef_run).to include_recipe("redis2::source")
+ expect(chef_run.node["redis2"]["daemon"]).to eq("/usr/local/bin/redis-server")
+ end
+
+ it "Runs redis2::package if install_from is set to package" do
+ chef_run.node.set['redis2']['install_from'] = "package"
+ chef_run.converge(described_recipe)
+ expect(chef_run).to include_recipe("redis2::package")
+ end
+end
+
+describe "redis2::package" do
+ let(:chef_run) { ChefSpec::Runner.new.converge(described_recipe) }
+ it "Install redis package" do
+ expect(chef_run).to install_package("redis-server")
+ end
+end
+
+describe "redis2::default_instance" do
+ let(:chef_run) { ChefSpec::Runner.new.converge(described_recipe) }
+ it "Install redis-prime instance" do
+ #expect(chef_run).to enable_runit_service("redis_prime")
+ #expect(chef_run).to start_runit_service("redis_prime")
+ expect(chef_run).to create_directory("/var/lib/redis/prime")
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 0000000..cbd550c
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,24 @@
+require 'chefspec'
+require 'chefspec/berkshelf'
+ChefSpec::Coverage.start!
+
+RSpec.configure do |config|
+ # Specify the path for Chef Solo to find cookbooks (default: [inferred from
+ # the location of the calling spec file])
+ #config.cookbook_path = 'berks-cookbooks'
+
+ # Specify the path for Chef Solo to find roles (default: [ascending search])
+ #config.role_path = 'roles'
+
+ # Specify the Chef log_level (default: :warn)
+ #config.log_level = :warn
+
+ # Specify the path to a local JSON file with Ohai data (default: nil)
+ #config.path = 'ohai.json'
+
+ # Specify the operating platform to mock Ohai data from (default: nil)
+ config.platform = 'ubuntu'
+
+ # Specify the operating version to mock Ohai data from (default: nil)
+ config.version = '12.04'
+end
diff --git a/templates/default/sv-redis-run.erb b/templates/default/sv-redis-run.erb
index 7276c33..7241800 100644
--- a/templates/default/sv-redis-run.erb
+++ b/templates/default/sv-redis-run.erb
@@ -1,3 +1,3 @@
#!/bin/sh
exec 2>&1
-exec chpst -u <%= @options[:user] %> <%= node["redis2"]["daemon"] %> <%= @options[:config_file] %>
+exec chpst -o <%= @options[:nofile] %> -u <%= @options[:user] %> <%= node["redis2"]["daemon"] %> <%= @options[:config_file] %>
diff --git a/test/integration/helpers/serverspec/main.rb b/test/integration/helpers/serverspec/main.rb
new file mode 100644
index 0000000..54812f8
--- /dev/null
+++ b/test/integration/helpers/serverspec/main.rb
@@ -0,0 +1,49 @@
+require 'serverspec'
+
+set :backend, :exec
+
+shared_examples 'redis::default' do
+ describe "Redis instances pre-requisites" do
+ describe file("/etc/redis") do
+ it { should be_directory }
+ it { should be_owned_by "root" }
+ it { should be_mode "755" }
+ end
+
+ describe file("/var/lib/redis") do
+ it { should be_directory }
+ it { should be_owned_by "redis" }
+ it { should be_mode "750" }
+ end
+
+ describe file("/var/log/redis") do
+ it { should be_directory }
+ it { should be_owned_by "redis" }
+ it { should be_mode "750" }
+ end
+ end
+
+ describe "Redis prime instance" do
+
+ it "should have a data directory" do
+ expect(file("/var/lib/redis/prime")).to be_directory
+ expect(file("/var/lib/redis/prime")).to be_owned_by("redis")
+ expect(file("/var/lib/redis/prime")).to be_mode("750")
+ end
+
+ it "should have a log file" do
+ expect(file("/var/log/redis/redis_prime.log")).to be_file
+ expect(file("/var/log/redis/redis_prime.log")).to be_owned_by("redis")
+ expect(file("/var/log/redis/redis_prime.log")).to be_mode("644")
+ end
+
+ it "is listening on port 6379" do
+ expect(port(6379)).to be_listening
+ end
+
+ it "has a running service of redis-prime" do
+ expect(service("redis-server")).to be_running
+ end
+
+ end
+end
diff --git a/test/integration/helpers/serverspec/spec_helper.rb b/test/integration/helpers/serverspec/spec_helper.rb
new file mode 100644
index 0000000..081a5d7
--- /dev/null
+++ b/test/integration/helpers/serverspec/spec_helper.rb
@@ -0,0 +1,5 @@
+require 'serverspec'
+require_relative 'main'
+
+set :backend, :exec
+
diff --git a/test/integration/package/serverspec/.redis_server_spec.rb.swp b/test/integration/package/serverspec/.redis_server_spec.rb.swp
new file mode 100644
index 0000000..f48e52e
Binary files /dev/null and b/test/integration/package/serverspec/.redis_server_spec.rb.swp differ
diff --git a/test/integration/package/serverspec/redis_server_spec.rb b/test/integration/package/serverspec/redis_server_spec.rb
new file mode 100644
index 0000000..c31dbac
--- /dev/null
+++ b/test/integration/package/serverspec/redis_server_spec.rb
@@ -0,0 +1,13 @@
+require_relative 'spec_helper'
+
+describe "Redis prime instance" do
+ include_examples "redis::default"
+
+ it "should install package" do
+ expect(package("redis-server")).to be_installed
+ end
+
+ describe process("redis-server") do
+ its(:args) { should match /\/etc\/redis\/redis_prime.conf/ }
+ end
+end
diff --git a/test/integration/source/serverspec/redis_server_spec.rb b/test/integration/source/serverspec/redis_server_spec.rb
new file mode 100644
index 0000000..847e17e
--- /dev/null
+++ b/test/integration/source/serverspec/redis_server_spec.rb
@@ -0,0 +1,14 @@
+require_relative 'spec_helper'
+
+describe "Redis prime instance" do
+ include_examples "redis::default"
+
+ it "should install redis binary from source" do
+ expect(file("/usr/local/bin/redis-server")).to be_file
+ expect(file("/usr/local/bin/redis-server")).to be_mode "755"
+ end
+
+ describe process("redis-server") do
+ its(:args) { should match /0.0.0.0:6379/ }
+ end
+end