diff --git a/.gitignore b/.gitignore index 643f34b..119031f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ metadata.json .vagrant Berksfile.lock +Cheffile.lock *~ *# .#* diff --git a/.kitchen.cloud.yml b/.kitchen.cloud.yml index 6ea66d1..891b09b 100644 --- a/.kitchen.cloud.yml +++ b/.kitchen.cloud.yml @@ -1,81 +1,103 @@ +#<% require 'kitchen-sync' %> --- -driver_plugin: vagrant -driver_plugin: digitalocean driver_config: - digitalocean_client_id: <%= ENV['DIGITAL_OCEAN_CLIENT_ID'] %> - digitalocean_api_key: <%= ENV['DIGITAL_OCEAN_API_KEY'] %> - aws_access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> + digitalocean_api_token: <%= ENV['DIGITALOCEAN_API_TOKEN'] %> + aws_access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> aws_secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> aws_ssh_key_id: <%= ENV['AWS_KEYPAIR_NAME'] %> - ssh_key: <%= ENV['AWS_PRIVATE_KEY_PATH'] %> - rackspace_username: <%= ENV['RACKSPACE_USERNAME'] %> - rackspace_api_key: <%= ENV['RACKSPACE_API_KEY'] %> + flavor_id: <%= ENV['EC2_FLAVOR_ID'] %> + availability_zone: <%= ENV['AWS_AVAILABILITY_ZONE'] %> + +provisioner: + name: chef_zero require_chef_omnibus: latest platforms: - name: centos-5.8 - driver_plugin: digitalocean + driver_plugin: digital_ocean driver_config: - image_id: 1601 - flavor_id: 63 - region_id: 1 - ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> + size: 2gb + image: centos-5-8-x64 + region: <%= ENV['DIGITALOCEAN_REGION'] %> + ssh_key_ids: <%= ENV['DIGITALOCEAN_SSH_KEYS'] %> + ssh_key: <%= ENV['DIGITALOCEAN_SSH_KEY_PATH'] %> + run_list: + - recipe[yum-epel] -- name: centos-6.4 - driver_plugin: digitalocean +- name: centos-6.5 + driver_plugin: digital_ocean driver_config: - image_id: 562354 - flavor_id: 63 - region_id: 1 - ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> + size: 2gb + image: centos-6-5-x64 + region: <%= ENV['DIGITALOCEAN_REGION'] %> + ssh_key_ids: <%= ENV['DIGITALOCEAN_SSH_KEYS'] %> + ssh_key: <%= ENV['DIGITALOCEAN_SSH_KEY_PATH'] %> -- name: amazon-2013.09 +- name: centos-7.0 + driver_plugin: digital_ocean + driver_config: + size: 2gb + image: centos-7-0-x64 + region: <%= ENV['DIGITALOCEAN_REGION'] %> + ssh_key_ids: <%= ENV['DIGITALOCEAN_SSH_KEYS'] %> + ssh_key: <%= ENV['DIGITALOCEAN_SSH_KEY_PATH'] %> + +- name: amazon-2014.09 driver_plugin: ec2 driver_config: - image_id: ami-3be4bc52 + image_id: ami-9a6ed3f2 username: ec2-user + ssh_key: <%= ENV['EC2_SSH_KEY_PATH'] %> -# - name: fedora-19 -# driver_plugin: digitalocean -# driver_config: -# image_id: 696598 -# flavor_id: 63 -# region_id: 1 -# ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> +- name: fedora-21 + driver_plugin: digital_ocean + driver_config: + size: 2gb + image: fedora-21-x64 + region: <%= ENV['DIGITALOCEAN_REGION'] %> + ssh_key_ids: <%= ENV['DIGITALOCEAN_SSH_KEYS'] %> + ssh_key: <%= ENV['DIGITALOCEAN_SSH_KEY_PATH'] %> + +- name: debian-7.0 + driver_plugin: digital_ocean + driver_config: + size: 2gb + image: debian-7-0-x64 + region: <%= ENV['DIGITALOCEAN_REGION'] %> + ssh_key_ids: <%= ENV['DIGITALOCEAN_SSH_KEYS'] %> + ssh_key: <%= ENV['DIGITALOCEAN_SSH_KEY_PATH'] %> + run_list: + - recipe[apt] -- name: ubuntu-1004 - driver_plugin: digitalocean +- name: ubuntu-12.04 + driver_plugin: digital_ocean driver_config: - image_id: 14097 - flavor_id: 63 - region_id: 1 - ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> + size: 2gb + image: ubuntu-12-04-x64 + region: <%= ENV['DIGITALOCEAN_REGION'] %> + ssh_key_ids: <%= ENV['DIGITALOCEAN_SSH_KEYS'] %> + ssh_key: <%= ENV['DIGITALOCEAN_SSH_KEY_PATH'] %> run_list: - recipe[apt] -- name: ubuntu-1204 - driver_plugin: digitalocean +- name: ubuntu-14.04 + driver_plugin: digital_ocean driver_config: - image_id: 1505447 - flavor_id: 63 - region_id: 1 - ssh_key_ids: <%= ENV['DIGITAL_OCEAN_SSH_KEY_IDS'] %> + size: 2gb + image: ubuntu-14-04-x64 + region: <%= ENV['DIGITALOCEAN_REGION'] %> + ssh_key_ids: <%= ENV['DIGITALOCEAN_SSH_KEYS'] %> + ssh_key: <%= ENV['DIGITALOCEAN_SSH_KEY_PATH'] %> run_list: - recipe[apt] suites: - name: default run_list: - - recipe[minitest-handler] - - recipe[runit] - recipe[runit_test] - - recipe[runit-other_test] attributes: {} - name: service run_list: - - recipe[minitest-handler] - - recipe[runit] - recipe[runit_test::service] - - recipe[runit-other_test] attributes: {} diff --git a/.kitchen.yml b/.kitchen.yml index b57623d..ff784d4 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -6,25 +6,33 @@ provisioner: platforms: - name: centos-5.11 + run_list: + - recipe[yum-epel] - name: centos-6.6 + run_list: + - recipe[yum-epel] + - name: centos-7.0 - name: fedora-21 - name: ubuntu-10.04 + run_list: + - recipe[apt] - name: ubuntu-12.04 + run_list: + - recipe[apt] - name: ubuntu-14.04 + run_list: + - recipe[apt] + - name: debian-7.8 + run_list: + - recipe[apt] suites: - name: default - run_list: - - recipe[minitest-handler] - - recipe[runit] + run_list: - recipe[runit_test] - - recipe[runit-other_test] attributes: {} - name: service run_list: - - recipe[minitest-handler] - - recipe[runit] - recipe[runit_test::service] - - recipe[runit-other_test] attributes: {} diff --git a/.rubocop.yml b/.rubocop.yml index f18e2d2..d917331 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,8 +1,41 @@ +AlignParameters: + Enabled: false + Encoding: Enabled: false +ClassLength: + Enabled: false + +MethodLength: + Enabled: false + LineLength: - Max: 200 + Enabled: false + +# HashSyntax: +# EnforcedStyle: hash_rockets + +Documentation: + Enabled: false -HashSyntax: - EnforcedStyle: hash_rockets +PerceivedComplexity: + Enabled: false + +CyclomaticComplexity: + Enabled: false + +Style/FileName: + Enabled: false + +Metrics/AbcSize: + Enabled: false + +AllCops: + Exclude: + - 'Guardfile' + - 'tmp/**/*' + - 'cookbooks/**/*' + +Style/GuardClause: + Enabled: false diff --git a/Berksfile.disabled b/Berksfile.disabled new file mode 100644 index 0000000..87ff9d5 --- /dev/null +++ b/Berksfile.disabled @@ -0,0 +1,11 @@ +source 'https://supermarket.chef.io' + +metadata + +group :integration do + cookbook 'apt' + cookbook 'yum-epel' +end + +cookbook 'runit_test', path: 'test/cookbooks/runit_test' +cookbook 'runit_other_test', path: 'test/cookbooks/runit_other_test' \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index c10a8b0..505414e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ runit Cookbook CHANGELOG ======================== This file is used to list changes made in each version of the runit cookbook. +v1.7.0 (2015-06-18) +---------- +* Modernize runit_service provider by rewriting pure Ruby as LWRP (#107) +* Modernize integration tests by rewriting Minitest suites as ServerSpec (#107) +* Fix regression in support for alternate sv binary on debian platforms (#92, #123) +* Fix regression in default logger's config location (#117) +* Tighten permissions on environment variable config files from 0644 to 0640 (#125) +* Add `start_down` and `delete_downfile` attributes to support configuring services with default state of 'down' (#105) + v1.6.0 (2015-04-06) -------------------- * Fedora 21 support diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 67d6eb9..999dfad 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -132,21 +132,30 @@ wiki page. ## Functional and Unit Tests -This cookbook is set up to run tests under -[Chef's test-kitchen](https://github.com/chef/test-kitchen). It -uses minitest-chef to run integration tests after the node has been -converged to verify that the state of the node. +This cookbook is set up to run unit tests under [ChefSpec](http://sethvargo.github.io/chefspec/) +and integration tests under [Test Kitchen](https://github.com/chef/test-kitchen). After Test Kitchen +has converged a node, it runs [ServerSpec](http://serverspec.org) tests +to verify the node's state. + +You can execute the unit tests by running +``` +bundle exec rake spec +``` + +You can execute the integration tests by running +``` +bundle exec kitchen test +``` Test kitchen should run completely without exception using the default [baseboxes provided by Chef](https://github.com/chef/bento). Because Test Kitchen creates VirtualBox machines and runs through -every configuration in the Kitchenfile, it may take some time for +every configuration in the `.kitchen.yml` config file, it may take some time for these tests to complete. -If your changes are only for a specific recipe, run only its -configuration with Test Kitchen. If you are adding a new recipe, or -other functionality such as a LWRP or definition, please add -appropriate tests and ensure they run with Test Kitchen. +If you are adding a new recipe, or other functionality such as a +LWRP or definition, please add appropriate tests and ensure they +run with Test Kitchen. If any don't pass, investigate them before submitting your patch. diff --git a/Cheffile b/Cheffile index 71af84f..e874d52 100644 --- a/Cheffile +++ b/Cheffile @@ -2,7 +2,10 @@ site 'https://supermarket.chef.io/api/v1' +# loosely coupled prerequisites for test-kitchen +cookbook 'apt' +cookbook 'yum-epel' + cookbook 'runit', path: '.' cookbook 'runit_test', path: './test/cookbooks/runit_test' -cookbook 'runit-other_test', path: './test/cookbooks/runit-other_test' -cookbook 'minitest-handler' +cookbook 'runit_other_test', path: './test/cookbooks/runit_other_test' diff --git a/Cheffile.lock b/Cheffile.lock deleted file mode 100644 index b3783b6..0000000 --- a/Cheffile.lock +++ /dev/null @@ -1,30 +0,0 @@ -SITE - remote: https://supermarket.chef.io/api/v1 - specs: - chef_handler (1.1.6) - minitest-handler (1.3.2) - chef_handler (>= 0.0.0) - packagecloud (0.0.17) - -PATH - remote: . - specs: - runit (1.5.18) - packagecloud (>= 0.0.0) - -PATH - remote: ./test/cookbooks/runit-other_test - specs: - runit-other_test (1.0.0) - -PATH - remote: ./test/cookbooks/runit_test - specs: - runit_test (1.0.0) - -DEPENDENCIES - minitest-handler (>= 0) - runit (>= 0) - runit-other_test (>= 0) - runit_test (>= 0) - diff --git a/Gemfile b/Gemfile index f519751..753cb99 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ source 'https://rubygems.org' -gem 'berkshelf', '~> 2.0' -gem 'chefspec', '~> 3.0' +gem 'berkshelf', '~> 3.0' +gem 'chefspec', '~> 4.0' gem 'foodcritic', '~> 3.0' gem 'rubocop' diff --git a/README.md b/README.md index 9f1fbb8..6318d87 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,9 @@ Many of these parameters are only used in the `:enable` action. - **restart_on_update** - Whether the service should be restarted when the run script is updated. Defaults to `true`. Set to `false` if the service shouldn't be restarted when the run script is updated. +- **start_down** - Set the default state of the runit service to 'down' by creating + `/down` file +- **delete_downfile** - Delete previously created `/down` file Unlike previous versions of the cookbook using the `runit_service` definition, the `runit_service` resource can be notified. See __Usage__ examples below. @@ -185,7 +188,7 @@ exec svlogd -tt /var/log/service_name ``` ### Examples -These are example use cases of the `runit_service` resource described above. There are others in the `runit_test` cookbook that is included in the [git repository](https://github.com/chef-cookbooks/runit). +These are example use cases of the `runit_service` resource described above. There are others in the `runit_test` cookbook that is included in the [git repository](https://github.com/hw-cookbooks/runit). **Default Example** @@ -396,16 +399,17 @@ end **More Examples** -For more examples, see the `runit_test` cookbook's `service` recipe in the [git repository](https://github.com/chef-cookbooks/runit). +For more examples, see the `runit_test` cookbook's `service` recipe in the [git repository](https://github.com/hw-cookbooks/runit). License & Authors ----------------- - Author:: Adam Jacob - Author:: Joshua Timberman +- Author:: Sean OMeara ```text -Copyright:: 2008-2013, Chef Software, Inc +Copyright:: 2008-2016, Chef Software, Inc Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/Rakefile b/Rakefile index 2f2ab79..029db27 100644 --- a/Rakefile +++ b/Rakefile @@ -6,18 +6,18 @@ require 'rake' require 'foodcritic' require 'rspec/core/rake_task' -task :default => [:spec] +task default: [:spec] RSpec::Core::RakeTask.new(:spec) do |t| - t.pattern = "./test/spec{,/*/**}/*_spec.rb" + t.pattern = './spec{,/*/**}/*_spec.rb' end FoodCritic::Rake::LintTask.new do |t| - t.options = {:fail_tags => ['correctness']} + t.options = { fail_tags: ['correctness'] } end begin require 'emeril/rake' rescue LoadError - puts ">>>>> Emerial gem not loaded, omitting taskes" unless ENV['CI'] + puts '>>>>> Emerial gem not loaded, omitting taskes' unless ENV['CI'] end diff --git a/TESTING.md b/TESTING.md index d238ac8..689bf0f 100644 --- a/TESTING.md +++ b/TESTING.md @@ -2,7 +2,7 @@ Testing ======= This cookbook has tests in the GitHub repository. To run the tests: - git clone git://github.com/chef-cookbooks/runit.git + git clone git://github.com/hw-cookbooks/runit.git cd runit bundle install diff --git a/libraries/helpers.rb b/libraries/helpers.rb index fc47d66..bd07be1 100644 --- a/libraries/helpers.rb +++ b/libraries/helpers.rb @@ -2,8 +2,9 @@ # Cookbook:: runit # Libraries:: helpers # -# Author: Joshua Timberman -# Copyright (c) 2014, Chef Software, Inc. +# Author: Joshua Timberman +# Author: Sean OMeara +# Copyright 2008-2015, Chef Software, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,28 +19,171 @@ # limitations under the License. # -require 'chef/mixin/shell_out' -include Chef::Mixin::ShellOut -module Runit +module RunitCookbook module Helpers - def runit_installed? - return true if runit_rpm_installed? || (runit_executable? && runit_sv_works?) + + # include Chef::Mixin::ShellOut if it is not already included in the calling class + def self.included(klass) + unless(klass.ancestors.include?(Chef::Mixin::ShellOut)) + klass.class_eval{ include Chef::Mixin::ShellOut } + end + end + + # Default settings for resource properties. + def parsed_sv_bin + return new_resource.sv_bin if new_resource.sv_bin + '/usr/bin/sv' + end + + def parsed_sv_dir + return new_resource.sv_dir if new_resource.sv_dir + '/etc/sv' + end + + def parsed_service_dir + return new_resource.service_dir if new_resource.service_dir + '/etc/service' + end + + def parsed_lsb_init_dir + return new_resource.lsb_init_dir if new_resource.lsb_init_dir + '/etc/init.d' + end + + # misc helper functions + def inside_docker? + results = `cat /proc/1/cgroup`.strip.split("\n") + results.any? { |val| /docker/ =~ val } + end + + def down_file + "#{sv_dir_name}/down" + end + + def env_dir + "#{sv_dir_name}/env" end - def runit_executable? - ::File.executable?(node['runit']['executable']) + def extra_env_files? + files = [] + Dir.glob("#{service_dir_name}/env/*").each do |f| + files << File.basename(f) + end + return true if files.sort != new_resource.env.keys.sort + false + end + + def zap_extra_env_files + Dir.glob("#{service_dir_name}/env/*").each do |f| + unless new_resource.env.key?(File.basename(f)) + File.unlink(f) + Chef::Log.info("removing file #{f}") + end + end + end + + def wait_for_service + unless inside_docker? + sleep 1 until ::FileTest.pipe?("#{service_dir_name}/supervise/ok") + + if new_resource.log + sleep 1 until ::FileTest.pipe?("#{service_dir_name}/log/supervise/ok") + end + end end def runit_sv_works? - sv = shell_out("#{node['runit']['sv_bin']} --help") + sv = shell_out("#{sv_bin} --help") sv.exitstatus == 100 && sv.stderr =~ /usage: sv .* command service/ end - def runit_rpm_installed? - shell_out('rpm -qa | grep -q "^runit"').exitstatus == 0 + def runit_send_signal(signal, friendly_name = nil) + friendly_name ||= signal + converge_by("send #{friendly_name} to #{new_resource}") do + shell_out!("#{sv_bin} #{sv_args}#{signal} #{service_dir_name}") + Chef::Log.info("#{new_resource} sent #{friendly_name}") + end + end + + def running? + cmd = shell_out("#{sv_bin} #{sv_args}status #{service_dir_name}") + (cmd.stdout =~ /^run:/ && cmd.exitstatus == 0) + end + + def log_running? + cmd = shell_out("#{sv_bin} #{sv_args}status #{service_dir_name}/log") + (cmd.stdout =~ /^run:/ && cmd.exitstatus == 0) + end + + def enabled? + ::File.exist?("#{service_dir_name}/run") + end + + def log_service_name + "#{new_resource.service_name}/log" + end + + def sv_dir_name + "#{parsed_sv_dir}/#{new_resource.service_name}" + end + + def sv_args + sv_args = '' + sv_args += "-w '#{new_resource.sv_timeout}' " unless new_resource.sv_timeout.nil? + sv_args += '-v ' if new_resource.sv_verbose + sv_args + end + + def sv_bin + parsed_sv_bin + end + + def service_dir_name + "#{new_resource.service_dir}/#{new_resource.service_name}" + end + + def log_dir_name + "#{new_resource.service_dir}/#{new_resource.service_name}/log" + end + + def template_cookbook + new_resource.cookbook.nil? ? new_resource.cookbook_name.to_s : new_resource.cookbook + end + + def default_logger_content + <<-EOS +#!/bin/sh +exec svlogd -tt /var/log/#{new_resource.service_name} + EOS + end + + def disable_service + shell_out("#{new_resource.sv_bin} #{sv_args}down #{service_dir_name}") + FileUtils.rm(service_dir_name) + end + + def start_service + shell_out!("#{new_resource.sv_bin} #{sv_args}start #{service_dir_name}") + end + + def stop_service + shell_out!("#{new_resource.sv_bin} #{sv_args}stop #{service_dir_name}") + end + + def restart_service + shell_out!("#{new_resource.sv_bin} #{sv_args}restart #{service_dir_name}") + end + + def restart_log_service + shell_out!("#{new_resource.sv_bin} #{sv_args}restart #{service_dir_name}/log") + end + + def reload_service + shell_out!("#{new_resource.sv_bin} #{sv_args}force-reload #{service_dir_name}") + end + + def reload_log_service + shell_out!("#{new_resource.sv_bin} #{sv_args}force-reload #{service_dir_name}/log") end end end - -Chef::Recipe.send(:include, Runit::Helpers) -Chef::Resource.send(:include, Runit::Helpers) diff --git a/libraries/matchers.rb b/libraries/matchers.rb index c7c6d29..760156e 100644 --- a/libraries/matchers.rb +++ b/libraries/matchers.rb @@ -1,5 +1,7 @@ if defined?(ChefSpec) + ChefSpec.define_matcher(:runit_service) + def start_runit_service(service) ChefSpec::Matchers::ResourceMatcher.new(:runit_service, :start, service) end diff --git a/libraries/provider_runit_service.rb b/libraries/provider_runit_service.rb index 3fefe0f..c08f979 100644 --- a/libraries/provider_runit_service.rb +++ b/libraries/provider_runit_service.rb @@ -2,8 +2,9 @@ # Cookbook Name:: runit # Provider:: service # -# Copyright 2011, Joshua Timberman -# Copyright 2011, Chef Software, Inc. +# Author:: Joshua Timberman +# Author:: Sean OMeara +# Copyright 2011-2015, Chef Software, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,533 +19,263 @@ # limitations under the License. # -require 'chef/provider/service' -require 'chef/provider/link' -require 'chef/resource/link' -require 'chef/provider/directory' -require 'chef/resource/directory' -require 'chef/provider/template' -require 'chef/resource/template' -require 'chef/provider/file' -require 'chef/resource/file' -require 'chef/mixin/shell_out' -require 'chef/mixin/language' - class Chef class Provider - class Service - class Runit < Chef::Provider::Service - # refactor this whole thing into a Chef11 LWRP - include Chef::Mixin::ShellOut - - def initialize(*args) - super - new_resource.supports[:status] = true - end - - def load_current_resource - @current_resource = Chef::Resource::RunitService.new(new_resource.name) - current_resource.service_name(new_resource.service_name) - - Chef::Log.debug("Checking status of service #{new_resource.service_name}") + class RunitService < Chef::Provider::LWRPBase + use_inline_resources if defined?(use_inline_resources) - # verify Runit was installed properly - unless ::File.exist?(new_resource.sv_bin) && ::File.executable?(new_resource.sv_bin) - no_runit_message = "Could not locate main runit sv_bin at \"#{new_resource.sv_bin}\". " - no_runit_message << "Did you remember to install runit before declaring a \"runit_service\" resource? " - no_runit_message << "\n\nTry adding the following to the top of your recipe:\n\ninclude_recipe \"runit\"" - fail no_runit_message - end + def whyrun_supported? + true + end - current_resource.running(running?) - current_resource.enabled(enabled?) - current_resource.env(get_current_env) - current_resource - end + # Mix in helpers from libraries/helpers.rb + include RunitCookbook::Helpers - # - # Chef::Provider::Service overrides - # + # actions + action :create do + # sv_templates + if new_resource.sv_templates - def action_create - configure_service # Do this every run, even if service is already enabled and running - Chef::Log.info("#{new_resource} configured") - end + directory sv_dir_name do + owner new_resource.owner + group new_resource.group + mode '0755' + recursive true + action :create + end - def action_enable - configure_service # Do this every run, even if service is already enabled and running - Chef::Log.info("#{new_resource} configured") - if current_resource.enabled - Chef::Log.debug("#{new_resource} already enabled - nothing to do") - else - enable_service - Chef::Log.info("#{new_resource} enabled") + template "#{sv_dir_name}/run" do + owner new_resource.owner + group new_resource.group + source "sv-#{new_resource.run_template_name}-run.erb" + cookbook template_cookbook + mode '0755' + variables(options: new_resource.options) + action :create end - load_new_resource_state - new_resource.enabled(true) - restart_service if new_resource.restart_on_update && run_script.updated_by_last_action? - restart_log_service if new_resource.restart_on_update && log_run_script.updated_by_last_action? - restart_log_service if new_resource.restart_on_update && log_config_file.updated_by_last_action? - end - def configure_service - if new_resource.sv_templates - Chef::Log.debug("Creating sv_dir for #{new_resource.service_name}") - do_action(sv_dir, :create) - Chef::Log.debug("Creating run_script for #{new_resource.service_name}") - do_action(run_script, :create) - - if new_resource.log - Chef::Log.debug("Setting up svlog for #{new_resource.service_name}") - do_action(log_dir, :create) - do_action(log_main_dir, :create) - do_action(default_log_dir, :create) if new_resource.default_logger - do_action(log_run_script, :create) - do_action(log_config_file, :create) - else - Chef::Log.debug("log not specified for #{new_resource.service_name}, continuing") + # log stuff + if new_resource.log + directory "#{sv_dir_name}/log" do + owner new_resource.owner + group new_resource.group + recursive true + action :create end - unless new_resource.env.empty? - Chef::Log.debug("Setting up environment files for #{new_resource.service_name}") - do_action(env_dir, :create) - env_files.each do |file| - file.action.each { |action| do_action(file, action) } - end - else - Chef::Log.debug("Environment not specified for #{new_resource.service_name}, continuing") + directory "#{sv_dir_name}/log/main" do + owner new_resource.owner + group new_resource.group + mode '0755' + recursive true + action :create end - if new_resource.check - Chef::Log.debug("Creating check script for #{new_resource.service_name}") - do_action(check_script, :create) - else - Chef::Log.debug("Check script not specified for #{new_resource.service_name}, continuing") - end + if new_resource.default_logger + directory "/var/log/#{new_resource.service_name}" do + owner new_resource.owner + group new_resource.group + mode '00755' + recursive true + action :create + end + + link "/var/log/#{new_resource.service_name}/config" do + to "#{sv_dir_name}/log/config" + end - if new_resource.finish - Chef::Log.debug("Creating finish script for #{new_resource.service_name}") - do_action(finish_script, :create) + file "#{sv_dir_name}/log/run" do + content default_logger_content + owner new_resource.owner + group new_resource.group + mode '00755' + action :create + end else - Chef::Log.debug("Finish script not specified for #{new_resource.service_name}, continuing") + template "#{sv_dir_name}/log/run" do + owner new_resource.owner + group new_resource.group + mode '00755' + source "sv-#{new_resource.log_template_name}-log-run.erb" + cookbook template_cookbook + variables(options: new_resource.options) + action :create + end end - unless new_resource.control.empty? - Chef::Log.debug("Creating control signal scripts for #{new_resource.service_name}") - do_action(control_dir, :create) - control_signal_files.each { |file| do_action(file, :create) } - else - Chef::Log.debug("Control signals not specified for #{new_resource.service_name}, continuing") + template "#{sv_dir_name}/log/config" do + owner new_resource.owner + group new_resource.group + mode '00644' + cookbook 'runit' + source 'log-config.erb' + variables(config: new_resource) + action :create end end - Chef::Log.debug("Creating lsb_init compatible interface #{new_resource.service_name}") - do_action(lsb_init, :create) - end - - def enable_service - Chef::Log.debug("Creating symlink in service_dir for #{new_resource.service_name}") - do_action(service_link, :create) - - unless inside_docker? - Chef::Log.debug("waiting until named pipe #{service_dir_name}/supervise/ok exists.") - until ::FileTest.pipe?("#{service_dir_name}/supervise/ok") - sleep 1 - Chef::Log.debug('.') - end + # environment stuff + directory "#{sv_dir_name}/env" do + owner new_resource.owner + group new_resource.group + mode '00755' + action :create + end - if new_resource.log - Chef::Log.debug("waiting until named pipe #{service_dir_name}/log/supervise/ok exists.") - until ::FileTest.pipe?("#{service_dir_name}/log/supervise/ok") - sleep 1 - Chef::Log.debug('.') - end + new_resource.env.map do |var, value| + file "#{sv_dir_name}/env/#{var}" do + owner new_resource.owner + group new_resource.group + content value + mode 00640 + action :create end - else - Chef::Log.debug("skipping */supervise/ok check inside docker") end - end - - def disable_service - shell_out("#{new_resource.sv_bin} #{sv_args}down #{service_dir_name}") - Chef::Log.debug("#{new_resource} down") - FileUtils.rm(service_dir_name) - Chef::Log.debug("#{new_resource} service symlink removed") - end - - def start_service - shell_out!("#{new_resource.sv_bin} #{sv_args}start #{service_dir_name}") - end - - def stop_service - shell_out!("#{new_resource.sv_bin} #{sv_args}stop #{service_dir_name}") - end - - def restart_service - shell_out!("#{new_resource.sv_bin} #{sv_args}restart #{service_dir_name}") - end - - def restart_log_service - shell_out!("#{new_resource.sv_bin} #{sv_args}restart #{service_dir_name}/log") - end - - def reload_service - shell_out!("#{new_resource.sv_bin} #{sv_args}force-reload #{service_dir_name}") - end - - def reload_log_service - shell_out!("#{new_resource.sv_bin} #{sv_args}force-reload #{service_dir_name}/log") - end - # - # Addtional Runit-only actions - # + ruby_block 'zap extra env files' do + block { zap_extra_env_files } + only_if { extra_env_files? } + action :run + end - # only take action if the service is running - [:down, :hup, :int, :term, :kill, :quit].each do |signal| - define_method "action_#{signal}".to_sym do - if current_resource.running - runit_send_signal(signal) - else - Chef::Log.debug("#{new_resource} not running - nothing to do") + if new_resource.check + template "#{sv_dir_name}/check" do + owner new_resource.owner + group new_resource.group + mode '00755' + cookbook template_cookbook + source "sv-#{new_resource.check_script_template_name}-check.erb" + variables(options: new_resource.options) + action :create end end - end - # only take action if service is *not* running - [:up, :once, :cont].each do |signal| - define_method "action_#{signal}".to_sym do - if current_resource.running - Chef::Log.debug("#{new_resource} already running - nothing to do") - else - runit_send_signal(signal) + if new_resource.finish + template "#{sv_dir_name}/finish" do + owner new_resource.owner + group new_resource.group + mode '00755' + source "sv-#{new_resource.finish_script_template_name}-finish.erb" + cookbook template_cookbook + variables(options: new_resource.options) if new_resource.options.respond_to?(:has_key?) + action :create end end - end - - def action_usr1 - runit_send_signal(1, :usr1) - end - def action_usr2 - runit_send_signal(2, :usr2) - end - - private - - def runit_send_signal(signal, friendly_name = nil) - friendly_name ||= signal - converge_by("send #{friendly_name} to #{new_resource}") do - shell_out!("#{new_resource.sv_bin} #{sv_args}#{signal} #{service_dir_name}") - Chef::Log.info("#{new_resource} sent #{friendly_name}") + directory "#{sv_dir_name}/control" do + owner new_resource.owner + group new_resource.group + mode '00755' + action :create end - end - def running? - cmd = shell_out("#{new_resource.sv_bin} #{sv_args}status #{service_dir_name}") - (cmd.stdout =~ /^run:/ && cmd.exitstatus == 0) - end - - def log_running? - cmd = shell_out("#{new_resource.sv_bin} #{sv_args}status #{service_dir_name}/log") - (cmd.stdout =~ /^run:/ && cmd.exitstatus == 0) - end - - def enabled? - ::File.exists?(::File.join(service_dir_name, 'run')) - end - - def log_service_name - ::File.join(new_resource.service_name, 'log') - end - - def sv_dir_name - ::File.join(new_resource.sv_dir, new_resource.service_name) - end - - def sv_args - sv_args = '' - sv_args += "-w '#{new_resource.sv_timeout}' " unless new_resource.sv_timeout.nil? - sv_args += '-v ' if new_resource.sv_verbose - sv_args - end - - def service_dir_name - ::File.join(new_resource.service_dir, new_resource.service_name) - end - - def log_dir_name - ::File.join(new_resource.service_dir, new_resource.service_name, log) - end - - def template_cookbook - new_resource.cookbook.nil? ? new_resource.cookbook_name.to_s : new_resource.cookbook - end - - def default_logger_content - "#!/bin/sh -exec svlogd -tt /var/log/#{new_resource.service_name}" - end - - # - # Helper Resources - # - def do_action(resource, action) - resource.run_action(action) - new_resource.updated_by_last_action(true) if resource.updated_by_last_action? - end - - def sv_dir - @sv_dir ||= - begin - d = Chef::Resource::Directory.new(sv_dir_name, run_context) - d.recursive(true) - d.owner(new_resource.owner) - d.group(new_resource.group) - d.mode(00755) - d + new_resource.control.map do |signal| + template "#{sv_dir_name}/control/#{signal}" do + owner new_resource.owner + group new_resource.group + mode '0755' + source "sv-#{new_resource.control_template_names[signal]}-#{signal}.erb" + cookbook template_cookbook + variables(options: new_resource.options) + action :create end - end - - def run_script - @run_script ||= - begin - t = Chef::Resource::Template.new(::File.join(sv_dir_name, 'run'), run_context) - t.owner(new_resource.owner) - t.group(new_resource.group) - t.source("sv-#{new_resource.run_template_name}-run.erb") - t.cookbook(template_cookbook) - t.mode(00755) - t.variables(:options => new_resource.options) if new_resource.options.respond_to?(:has_key?) - t - end - end + end - def log_dir - @log_dir ||= - begin - d = Chef::Resource::Directory.new(::File.join(sv_dir_name, 'log'), run_context) - d.recursive(true) - d.owner(new_resource.owner) - d.group(new_resource.group) - d.mode(00755) - d + # lsb_init + if node['platform'] == 'debian' + ruby_block "unlink #{parsed_lsb_init_dir}/#{new_resource.service_name}" do + block { ::File.unlink("#{parsed_lsb_init_dir}/#{new_resource.service_name}") } + only_if { ::File.symlink?("#{parsed_lsb_init_dir}/#{new_resource.service_name}") } end - end - def log_main_dir - @log_main_dir ||= - begin - d = Chef::Resource::Directory.new(::File.join(sv_dir_name, 'log', 'main'), run_context) - d.recursive(true) - d.owner(new_resource.owner) - d.group(new_resource.group) - d.mode(00755) - d + template "#{parsed_lsb_init_dir}/#{new_resource.service_name}" do + owner 'root' + group 'root' + mode '00755' + cookbook 'runit' + source 'init.d.erb' + variables( + name: new_resource.service_name, + sv_bin: new_resource.sv_bin, + init_dir: ::File.join(parsed_lsb_init_dir, '') + ) + action :create end - end - - def default_log_dir - @default_log_dir ||= - begin - d = Chef::Resource::Directory.new(::File.join("/var/log/#{new_resource.service_name}"), run_context) - d.recursive(true) - d.owner(new_resource.owner) - d.group(new_resource.group) - d.mode(00755) - d + else + link "#{parsed_lsb_init_dir}/#{new_resource.service_name}" do + to sv_bin + action :create end - end + end - def log_run_script - @log_run_script ||= - begin - if new_resource.default_logger - f = Chef::Resource::File.new( - ::File.join(sv_dir_name, 'log', 'run'), - run_context - ) - f.content(default_logger_content) - f.owner(new_resource.owner) - f.group(new_resource.group) - f.mode(00755) - f - else - t = Chef::Resource::Template.new( - ::File.join(sv_dir_name, 'log', 'run'), - run_context - ) - t.owner(new_resource.owner) - t.group(new_resource.group) - t.mode(00755) - t.source("sv-#{new_resource.log_template_name}-log-run.erb") - t.cookbook(template_cookbook) - t.variables(:options => new_resource.options) if new_resource.options.respond_to?(:has_key?) - t - end - end - end + # Create/Delete service down file + # To prevent unexpected behavior, require users to explicitly set + # delete_downfile to remove any down file that may already exist + df_action = :nothing + if new_resource.start_down + df_action = :create + elsif new_resource.delete_downfile + df_action = :delete + end - def log_config_file - @log_config_file ||= - begin - t = Chef::Resource::Template.new(::File.join(sv_dir_name, 'log', 'config'), run_context) - t.owner(new_resource.owner) - t.group(new_resource.group) - t.mode(00644) - t.cookbook('runit') - t.source('log-config.erb') - t.variables( - :size => new_resource.log_size, - :num => new_resource.log_num, - :min => new_resource.log_min, - :timeout => new_resource.log_timeout, - :processor => new_resource.log_processor, - :socket => new_resource.log_socket, - :prefix => new_resource.log_prefix, - :append => new_resource.log_config_append - ) - t - end + file down_file do + mode 00644 + backup false + content '# File created and managed by chef!' + action df_action + end end + end - def env_dir - @env_dir ||= - begin - d = Chef::Resource::Directory.new(::File.join(sv_dir_name, 'env'), run_context) - d.owner(new_resource.owner) - d.group(new_resource.group) - d.mode(00755) - d - end + action :disable do + ruby_block "disable #{new_resource.service_name}" do + block { disable_service } + only_if { enabled? } end + end - def env_files - @env_files ||= - begin - create_files = new_resource.env.map do |var, value| - f = Chef::Resource::File.new(::File.join(sv_dir_name, 'env', var), run_context) - f.owner(new_resource.owner) - f.group(new_resource.group) - f.content(value) - f.action(:create) - f - end - extra_env = current_resource.env.reject { |k,_| new_resource.env.key?(k) } - delete_files = extra_env.map do |k,_| - f = Chef::Resource::File.new(::File.join(sv_dir_name, 'env', k), run_context) - f.action(:delete) - f - end - create_files + delete_files - end - end + action :enable do + # FIXME: remove action_create in next major version + action_create - def get_current_env - env_dir = ::File.join(sv_dir_name, 'env') - return {} unless ::File.directory? env_dir - files = ::Dir.glob(::File.join(env_dir,'*')) - env = files.reduce({}) do |c,o| - contents = ::IO.read(o).rstrip - c.merge!(::File.basename(o) => contents) - end - env + link "#{service_dir_name}" do + to sv_dir_name + action :create end - def check_script - @check_script ||= - begin - t = Chef::Resource::Template.new(::File.join(sv_dir_name, 'check'), run_context) - t.owner(new_resource.owner) - t.group(new_resource.group) - t.source("sv-#{new_resource.check_script_template_name}-check.erb") - t.cookbook(template_cookbook) - t.mode(00755) - t.variables(:options => new_resource.options) if new_resource.options.respond_to?(:has_key?) - t - end - end + # FIXME: replace me + # ruby_block 'wait_for_service' do + # block wait_for_service + # end + end - def finish_script - @finish_script ||= - begin - t = Chef::Resource::Template.new(::File.join(sv_dir_name, 'finish'), run_context) - t.owner(new_resource.owner) - t.group(new_resource.group) - t.mode(00755) - t.source("sv-#{new_resource.finish_script_template_name}-finish.erb") - t.cookbook(template_cookbook) - t.variables(:options => new_resource.options) if new_resource.options.respond_to?(:has_key?) - t - end + # signals + [:down, :hup, :int, :term, :kill, :quit].each do |signal| + action signal do + runit_send_signal(signal) end + end - def control_dir - @control_dir ||= - begin - d = Chef::Resource::Directory.new(::File.join(sv_dir_name, 'control'), run_context) - d.owner(new_resource.owner) - d.group(new_resource.group) - d.mode(00755) - d - end + [:up, :once, :cont].each do |signal| + action signal do + runit_send_signal(signal) end + end - def control_signal_files - @control_signal_files ||= - begin - new_resource.control.map do |signal| - t = Chef::Resource::Template.new( - ::File.join(sv_dir_name, 'control', signal), - run_context - ) - t.owner(new_resource.owner) - t.group(new_resource.group) - t.mode(00755) - t.source("sv-#{new_resource.control_template_names[signal]}-#{signal}.erb") - t.cookbook(template_cookbook) - t.variables(:options => new_resource.options) if new_resource.options.respond_to?(:has_key?) - t - end - end - end + action :usr1 do + runit_send_signal(1, :usr1) + end - def lsb_init - @lsb_init ||= - begin - initfile = ::File.join(new_resource.lsb_init_dir, new_resource.service_name) - if node['platform'] == 'debian' - ::File.unlink(initfile) if ::File.symlink?(initfile) - t = Chef::Resource::Template.new(initfile, run_context) - t.owner('root') - t.group('root') - t.mode(00755) - t.cookbook('runit') - t.source('init.d.erb') - t.variables(:name => new_resource.service_name) - t - else - l = Chef::Resource::Link.new(initfile, run_context) - l.to(new_resource.sv_bin) - l - end - end - end + action :usr2 do + runit_send_signal(2, :usr2) + end - def service_link - @service_link ||= - begin - l = Chef::Resource::Link.new(::File.join(service_dir_name), run_context) - l.to(sv_dir_name) - l - end - end + action :nothing do + end - def inside_docker? - results = `cat /proc/1/cgroup`.strip.split("\n") - results.any?{|val| /docker/ =~ val} - end + action :restart do + restart_service end - end + end end end diff --git a/libraries/resource_runit_service.rb b/libraries/resource_runit_service.rb index ec651de..c29b7e6 100644 --- a/libraries/resource_runit_service.rb +++ b/libraries/resource_runit_service.rb @@ -29,8 +29,8 @@ def initialize(name, run_context = nil) super runit_node = runit_attributes_from_node(run_context) @resource_name = :runit_service - @provider = Chef::Provider::Service::Runit - @supports = { :restart => true, :reload => true, :status => true } + @provider = Chef::Provider::RunitService + @supports = { restart: true, reload: true, status: true } @action = :enable @allowed_actions = [:nothing, :start, :stop, :enable, :disable, :restart, :reload, :status, :once, :hup, :cont, :term, :kill, :up, :down, :usr1, :usr2, :create] @@ -47,6 +47,8 @@ def initialize(name, run_context = nil) @log = true @cookbook = nil @check = false + @start_down = false + @delete_downfile = false @finish = false @owner = nil @group = nil @@ -94,103 +96,111 @@ def initialize(name, run_context = nil) end def sv_bin(arg = nil) - set_or_return(:sv_bin, arg, :kind_of => [String]) + set_or_return(:sv_bin, arg, kind_of: [String]) end def sv_dir(arg = nil) - set_or_return(:sv_dir, arg, :kind_of => [String, FalseClass]) + set_or_return(:sv_dir, arg, kind_of: [String, FalseClass]) end def sv_timeout(arg = nil) - set_or_return(:sv_timeout, arg, :kind_of => [Fixnum]) + set_or_return(:sv_timeout, arg, kind_of: [Fixnum]) end def sv_verbose(arg = nil) - set_or_return(:sv_verbose, arg, :kind_of => [TrueClass, FalseClass]) + set_or_return(:sv_verbose, arg, kind_of: [TrueClass, FalseClass]) end def service_dir(arg = nil) - set_or_return(:service_dir, arg, :kind_of => [String]) + set_or_return(:service_dir, arg, kind_of: [String]) end def lsb_init_dir(arg = nil) - set_or_return(:lsb_init_dir, arg, :kind_of => [String]) + set_or_return(:lsb_init_dir, arg, kind_of: [String]) end def control(arg = nil) - set_or_return(:control, arg, :kind_of => [Array]) + set_or_return(:control, arg, kind_of: [Array]) end def options(arg = nil) - @env.empty? ? opts = @options : opts = @options.merge!(:env_dir => ::File.join(@sv_dir, @service_name, 'env')) + @env.empty? ? opts = @options : opts = @options.merge!(env_dir: ::File.join(@sv_dir, @service_name, 'env')) set_or_return( :options, arg, - :kind_of => [Hash], - :default => opts + kind_of: [Hash], + default: opts ) end def env(arg = nil) - set_or_return(:env, arg, :kind_of => [Hash]) + set_or_return(:env, arg, kind_of: [Hash]) end ## set log to current instance value if nothing is passed. def log(arg = @log) - set_or_return(:log, arg, :kind_of => [TrueClass, FalseClass]) + set_or_return(:log, arg, kind_of: [TrueClass, FalseClass]) end def cookbook(arg = nil) - set_or_return(:cookbook, arg, :kind_of => [String]) + set_or_return(:cookbook, arg, kind_of: [String]) end def finish(arg = nil) - set_or_return(:finish, arg, :kind_of => [TrueClass, FalseClass]) + set_or_return(:finish, arg, kind_of: [TrueClass, FalseClass]) end def check(arg = nil) - set_or_return(:check, arg, :kind_of => [TrueClass, FalseClass]) + set_or_return(:check, arg, kind_of: [TrueClass, FalseClass]) + end + + def start_down(arg = nil) + set_or_return(:start_down, arg, :kind_of => [TrueClass, FalseClass]) + end + + def delete_downfile(arg = nil) + set_or_return(:delete_downfile, arg, :kind_of => [TrueClass, FalseClass]) end def owner(arg = nil) - set_or_return(:owner, arg, :regex => [Chef::Config[:user_valid_regex]]) + set_or_return(:owner, arg, regex: [Chef::Config[:user_valid_regex]]) end def group(arg = nil) - set_or_return(:group, arg, :regex => [Chef::Config[:group_valid_regex]]) + set_or_return(:group, arg, regex: [Chef::Config[:group_valid_regex]]) end def default_logger(arg = nil) - set_or_return(:default_logger, arg, :kind_of => [TrueClass, FalseClass]) + set_or_return(:default_logger, arg, kind_of: [TrueClass, FalseClass]) end def restart_on_update(arg = nil) - set_or_return(:restart_on_update, arg, :kind_of => [TrueClass, FalseClass]) + set_or_return(:restart_on_update, arg, kind_of: [TrueClass, FalseClass]) end def run_template_name(arg = nil) - set_or_return(:run_template_name, arg, :kind_of => [String]) + set_or_return(:run_template_name, arg, kind_of: [String]) end alias_method :template_name, :run_template_name def log_template_name(arg = nil) - set_or_return(:log_template_name, arg, :kind_of => [String]) + set_or_return(:log_template_name, arg, kind_of: [String]) end def check_script_template_name(arg = nil) - set_or_return(:check_script_template_name, arg, :kind_of => [String]) + set_or_return(:check_script_template_name, arg, kind_of: [String]) end def finish_script_template_name(arg = nil) - set_or_return(:finish_script_template_name, arg, :kind_of => [String]) + set_or_return(:finish_script_template_name, arg, kind_of: [String]) end def control_template_names(arg = nil) set_or_return( :control_template_names, arg, - :kind_of => [Hash], - :default => set_control_template_names + kind_of: [Hash], + default: set_control_template_names ) end @@ -202,39 +212,39 @@ def set_control_template_names end def sv_templates(arg = nil) - set_or_return(:sv_templates, arg, :kind_of => [TrueClass, FalseClass]) + set_or_return(:sv_templates, arg, kind_of: [TrueClass, FalseClass]) end def log_size(arg = nil) - set_or_return(:log_size, arg, :kind_of => [Integer]) + set_or_return(:log_size, arg, kind_of: [Integer]) end def log_num(arg = nil) - set_or_return(:log_num, arg, :kind_of => [Integer]) + set_or_return(:log_num, arg, kind_of: [Integer]) end def log_min(arg = nil) - set_or_return(:log_min, arg, :kind_of => [Integer]) + set_or_return(:log_min, arg, kind_of: [Integer]) end def log_timeout(arg = nil) - set_or_return(:log_timeout, arg, :kind_of => [Integer]) + set_or_return(:log_timeout, arg, kind_of: [Integer]) end def log_processor(arg = nil) - set_or_return(:log_processor, arg, :kind_of => [String]) + set_or_return(:log_processor, arg, kind_of: [String]) end def log_socket(arg = nil) - set_or_return(:log_socket, arg, :kind_of => [String, Hash]) + set_or_return(:log_socket, arg, kind_of: [String, Hash]) end def log_prefix(arg = nil) - set_or_return(:log_prefix, arg, :kind_of => [String]) + set_or_return(:log_prefix, arg, kind_of: [String]) end def log_config_append(arg = nil) - set_or_return(:log_config_append, arg, :kind_of => [String]) + set_or_return(:log_config_append, arg, kind_of: [String]) end def runit_attributes_from_node(run_context) diff --git a/metadata.rb b/metadata.rb index 0f46f3d..f31a5f2 100644 --- a/metadata.rb +++ b/metadata.rb @@ -1,14 +1,14 @@ -name 'runit' -maintainer 'Heavy Water Operations, LLC.' -maintainer_email 'support@hw-ops.com' -license 'Apache 2.0' -description 'Installs runit and provides runit_service definition' -long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) -version '1.6.0' +name 'runit' +maintainer 'Heavy Water Operations, LLC.' +maintainer_email 'support@hw-ops.com' +license 'Apache 2.0' +description 'Installs runit and provides runit_service definition' +long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) +version '1.7.0' recipe 'runit', 'Installs and configures runit' -%w{ ubuntu debian gentoo centos redhat amazon scientific oracle enterpriseenterprise }.each do |os| +%w(ubuntu debian gentoo centos redhat amazon scientific oracle enterpriseenterprise).each do |os| supports os end diff --git a/recipes/default.rb b/recipes/default.rb index c3439f8..a11e503 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -42,6 +42,12 @@ packagecloud_repo 'imeyer/runit' unless node['runit']['prefer_local_yum'] package 'runit' + if node['platform_version'].to_i == 7 + service 'runsvdir-start' do + action [:start, :enable] + end + end + when 'debian', 'gentoo' if platform?('gentoo') diff --git a/spec/runit_service/centos_58_service_spec.rb b/spec/runit_service/centos_58_service_spec.rb new file mode 100644 index 0000000..e86cf17 --- /dev/null +++ b/spec/runit_service/centos_58_service_spec.rb @@ -0,0 +1,80 @@ +require 'spec_helper' + +describe 'runit_test::service on centos-5.8' do + cached(:centos_58_service) do + ChefSpec::SoloRunner.new( + platform: 'centos', + version: '5.8', + # step_into: 'runit_service' + ) do |node| + node.set['runit']['version'] = '0.0' + end.converge('runit_test::service') + end + + # Resource in runit_test::service + context 'compiling the test recipe' do + it 'creates runit_service[plain-defaults]' do + expect(centos_58_service).to enable_runit_service('plain-defaults') + end + + it 'creates runit_service[no-svlog]' do + expect(centos_58_service).to enable_runit_service('no-svlog') + end + + it 'creates runit_service[default-svlog]' do + expect(centos_58_service).to enable_runit_service('default-svlog') + end + + it 'creates runit_service[checker]' do + expect(centos_58_service).to enable_runit_service('checker') + end + + it 'creates runit_service[finisher]' do + expect(centos_58_service).to enable_runit_service('finisher') + end + + it 'creates runit_service[env-files]' do + expect(centos_58_service).to enable_runit_service('env-files') + end + + it 'creates runit_service[template-options]' do + expect(centos_58_service).to enable_runit_service('template-options') + end + + it 'creates runit_service[control-signals]' do + expect(centos_58_service).to enable_runit_service('control-signals') + end + + it 'creates runit_service[runsvdir-floyd]' do + expect(centos_58_service).to enable_runit_service('runsvdir-floyd') + end + + it 'creates runit_service[timer]' do + expect(centos_58_service).to enable_runit_service('timer') + end + + it 'creates runit_service[chatterbox]' do + expect(centos_58_service).to enable_runit_service('chatterbox') + end + + it 'creates runit_service[floyds-app]' do + expect(centos_58_service).to enable_runit_service('floyds-app') + end + + it 'creates runit_service[yerba]' do + expect(centos_58_service).to enable_runit_service('yerba') + end + + it 'creates runit_service[yerba-alt]' do + expect(centos_58_service).to enable_runit_service('yerba-alt') + end + + it 'creates runit_service[ayahuasca]' do + expect(centos_58_service).to enable_runit_service('ayahuasca') + end + + it 'creates runit_service[exist-disabled]' do + expect(centos_58_service).to disable_runit_service('exist-disabled') + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..9b0f1f7 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,20 @@ +COOKBOOK_RESOLVERS = { + 'batali' => ['Batali', 'batali/chefspec'], + 'berkshelf' => ['Berksfile', 'chefspec/berkshelf'], + 'librarian' => ['Cheffile', 'chefspec/librarian'] +} + +require 'chefspec' + +if ENV['COOKBOOK_RESOLVER'] + require COOKBOOK_RESOLVERS[ENV['COOKBOOK_RESOLVER']] +else + resolver_lib = COOKBOOK_RESOLVERS.values.detect do |r_file, _r_lib| + File.exist?(File.join(File.dirname(__FILE__), '..', r_file)) + end + fail 'Failed to locate valid cookbook resolver files!' unless resolver_lib + puts "Resolving cookbooks from #{resolver_lib.first}" + require resolver_lib.last +end + +at_exit { ChefSpec::Coverage.report! } diff --git a/templates/debian/init.d.erb b/templates/debian/init.d.erb index 48b5367..491d53f 100644 --- a/templates/debian/init.d.erb +++ b/templates/debian/init.d.erb @@ -13,8 +13,8 @@ PATH=/sbin:/usr/sbin:/bin:/usr/bin DESC="runit-managed <%= @name %>" NAME=<%= @name %> -RUNIT=/usr/bin/sv -SCRIPTNAME=/etc/init.d/$NAME +RUNIT=<%= @sv_bin %> +SCRIPTNAME=<%= @init_dir %>$NAME # Exit if runit is not installed [ -x $RUNIT ] || exit 0 diff --git a/templates/default/log-config.erb b/templates/default/log-config.erb index 6e33db1..68322b6 100644 --- a/templates/default/log-config.erb +++ b/templates/default/log-config.erb @@ -1,24 +1,24 @@ -<% if @size -%> -s<%= @size %> +<% if @config.log_size -%> +s<%= @config.log_size %> <% end -%> -<% if @num -%> -n<%= @num %> +<% if @config.log_num -%> +n<%= @config.log_num %> <% end -%> -<% if @min -%> -N<%= @min %> +<% if @config.log_min -%> +N<%= @config.log_min %> <% end -%> -<% if @timeout -%> -t<%= @timeout %> +<% if @config.log_timeout -%> +t<%= @config.log_timeout %> <% end -%> -<% if @processor -%> -!<%= @processor %> +<% if @config.log_processor -%> +!<%= @config.log_processor %> <% end -%> -<% if @socket -%> -u<%= @socket %> +<% if @config.log_socket -%> +u<%= @config.log_socket %> <% end -%> -<% if @prefix -%> -p<%= @prefix %> +<% if @config.log_prefix -%> +p<%= @config.log_prefix %> <% end -%> -<% if @append -%> -<%= @append %> +<% if @config.log_config_append -%> +<%= @config.log_config_append %> <% end -%> diff --git a/test/cookbooks/runit-other_test/metadata.rb b/test/cookbooks/runit-other_test/metadata.rb deleted file mode 100644 index b4df69e..0000000 --- a/test/cookbooks/runit-other_test/metadata.rb +++ /dev/null @@ -1,6 +0,0 @@ -name 'runit-other_test' -maintainer 'Chef Software, Inc.' -maintainer_email 'cookbooks@chef.io' -license 'Apache 2.0' -description 'This cookbook is used with test-kitchen to test the parent, runit cookbok' -version '1.0.0' diff --git a/test/cookbooks/runit-other_test/recipes/default.rb b/test/cookbooks/runit-other_test/recipes/default.rb deleted file mode 100644 index 0f3b141..0000000 --- a/test/cookbooks/runit-other_test/recipes/default.rb +++ /dev/null @@ -1 +0,0 @@ -# Empty recipe for test-kitchen diff --git a/test/cookbooks/runit-other_test/templates/default/sv-other-cookbook-templates-run.erb b/test/cookbooks/runit-other_test/templates/default/sv-other-cookbook-templates-run.erb deleted file mode 100644 index 4d93a15..0000000 --- a/test/cookbooks/runit-other_test/templates/default/sv-other-cookbook-templates-run.erb +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -exec 2>1 -exec tail -f /var/log/* diff --git a/test/cookbooks/runit-other_test/README.md b/test/cookbooks/runit_other_test/README.md similarity index 100% rename from test/cookbooks/runit-other_test/README.md rename to test/cookbooks/runit_other_test/README.md diff --git a/test/cookbooks/runit_other_test/metadata.rb b/test/cookbooks/runit_other_test/metadata.rb new file mode 100644 index 0000000..4903a44 --- /dev/null +++ b/test/cookbooks/runit_other_test/metadata.rb @@ -0,0 +1,6 @@ +name 'runit_other_test' +maintainer 'Chef Software, Inc.' +maintainer_email 'cookbooks@chef.io' +license 'Apache 2.0' +description 'This cookbook is used with test-kitchen to test the "template cookbook" option in the runit cookbook' +version '1.0.0' diff --git a/test/cookbooks/runit_other_test/templates/default/sv-ayahuasca-run.erb b/test/cookbooks/runit_other_test/templates/default/sv-ayahuasca-run.erb new file mode 100644 index 0000000..71ce53c --- /dev/null +++ b/test/cookbooks/runit_other_test/templates/default/sv-ayahuasca-run.erb @@ -0,0 +1,3 @@ +#!/bin/sh +exec 2>&1 +exec nc -l 3005 diff --git a/test/cookbooks/runit_test/files/default/tests/minitest/default_test.rb b/test/cookbooks/runit_test/files/default/tests/minitest/default_test.rb deleted file mode 100644 index 5bedba6..0000000 --- a/test/cookbooks/runit_test/files/default/tests/minitest/default_test.rb +++ /dev/null @@ -1,43 +0,0 @@ -# -# Cookbook Name:: runit_test -# Recipe:: default -# -# Copyright 2012, Chef Software, Inc. -# -# 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 File.expand_path('../support/helpers', __FILE__) - -describe 'runit_test::default' do - include Helpers::RunitTest - - describe 'packages' do - it 'has been installed' do - package('runit').must_be_installed - end - end - - it 'The service runitsvdir should be running' do - service('runsvdir').must_be_running if node['platform_family'] == 'ubuntu' - end - - it 'The directory /etc/service should exist' do - directory('/etc/service').must_exist - end - - it 'It should have a file called run in /etc/sv/getty-5' do - file('/etc/sv/getty-5/run').must_exist if node['platform_family'] == 'debian' - end - -end diff --git a/test/cookbooks/runit_test/files/default/tests/minitest/service_test.rb b/test/cookbooks/runit_test/files/default/tests/minitest/service_test.rb deleted file mode 100644 index 94574c1..0000000 --- a/test/cookbooks/runit_test/files/default/tests/minitest/service_test.rb +++ /dev/null @@ -1,129 +0,0 @@ -# -# Cookbook:: runit_test -# Minitest:: service -# -# Copyright 2012, Chef Software, Inc. -# -# 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 File.expand_path('../support/helpers', __FILE__) - -describe 'runit_test::service' do - include Helpers::RunitTest - MiniTest::Chef::Resources.register_resource(:runit_service) - - it 'creates a service with the defaults' do - runit_service('plain-defaults').must_be_running - file('/etc/service/plain-defaults/run').must_exist - file('/etc/service/plain-defaults/log/run').must_exist - file('/etc/init.d/plain-defaults').must_exist - unless node['platform'] == 'gentoo' - link('/etc/service/plain-defaults').must_exist.with( - :link_type, :symbolic).and(:to, '/etc/sv/plain-defaults') - end - end - - it 'creates a service that doesnt use the svlog' do - runit_service('no-svlog').must_be_running - directory('/etc/sv/no-svlog/log').wont_exist - end - - it 'creates a service that uses the default svlog' do - regexp = %r{#!/bin/sh\nexec svlogd -tt /var/log/default-svlog} - runit_service('default-svlog').must_be_running - file('/etc/service/default-svlog/log/run').must_match(regexp) - end - - it 'creates a service that has a check script' do - runit_service('checker').must_be_running - file('/etc/service/checker/check').must_exist - end - - it 'creates a service that has a finish script' do - runit_service('finisher').must_be_running - file('/etc/service/finisher/finish').must_exist - end - - it 'creates a service using sv_timeout' do - runit_service('timer').must_be_running - end - - it 'creates a service using sv_verbose' do - runit_service('chatterbox').must_be_running - end - - it 'creates a service that uses env files' do - regexp = %r{\$PATH:/opt/chef/embedded/bin} - runit_service('env-files').must_be_running - file('/etc/service/env-files/env/PATH').must_match(regexp) - end - - it 'creates a service that sets options for the templates' do - runit_service('template-options').must_be_running - file('/etc/service/template-options/run').must_match('# Options are delicious') - end - - it 'creates a service that uses control signal files' do - runit_service('control-signals').must_be_running - file('/etc/service/control-signals/control/u').must_match(/control signal up/) - end - - it 'creates a runsvdir service for a normal user' do - regexp = %r{exec chpst -ufloyd runsvdir /home/floyd/service} - runit_service('runsvdir-floyd').must_be_running - file('/etc/service/runsvdir-floyd/run').must_match(regexp) - end - - it 'creates a service running by a normal user in its runsvdir' do - floyds_app = shell_out( - "#{node['runit']['sv_bin']} status /home/floyd/service/floyds-app", - :user => 'floyd', - :cwd => '/home/floyd' - ) - assert floyds_app.stdout.include?('run:') - file('/home/floyd/service/floyds-app/run').must_exist.with(:owner, 'floyd') - file('/home/floyd/service/floyds-app/log/run').must_exist.with(:owner, 'floyd') - file('/etc/init.d/floyds-app').must_exist - unless node['platform'] == 'gentoo' - link('/home/floyd/service/floyds-app').must_exist.with( - :link_type, :symbolic).and(:to, '/home/floyd/sv/floyds-app') - end - end - - it 'creates a service with differently named template files' do - runit_service('yerba').must_be_running - end - - it 'creates a service with differently named run script template' do - runit_service('yerba-alt').must_be_running - end - - it 'creates a service that should exist but be disabled' do - file('/etc/sv/exist-disabled/run').must_exist - link('/etc/service/exist-disabled').wont_exist unless node['platform'] == 'gentoo' - end - - it 'can use templates from another cookbook' do - runit_service('other-cookbook-templates').must_be_running - end - - it 'creates a service that has its own run scripts' do - skip 'RHEL platforms dont ship runit scripts' if node['platform_family'] == 'rhel' || node['platform_family'] == 'fedora' - - git_daemon = shell_out("#{node['runit']['sv_bin']} status /etc/service/git-daemon") - assert git_daemon.stdout.include?('run:') - link('/etc/service/git-daemon').must_exist.with( - :link_type, :symbolic).and(:to, '/etc/sv/git-daemon') - end -end diff --git a/test/cookbooks/runit_test/files/default/tests/minitest/support/helpers.rb b/test/cookbooks/runit_test/files/default/tests/minitest/support/helpers.rb deleted file mode 100644 index fe86ccb..0000000 --- a/test/cookbooks/runit_test/files/default/tests/minitest/support/helpers.rb +++ /dev/null @@ -1,30 +0,0 @@ -# -# Cookbook Name:: runit_test -# Recipe:: default -# -# Copyright 2012, Chef Software, Inc. -# -# 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/mixin/shell_out' - -module Helpers - # Missing top-level module documentation comment. - module RunitTest - include MiniTest::Chef::Assertions - include MiniTest::Chef::Context - include MiniTest::Chef::Resources - include Chef::Mixin::ShellOut - end -end diff --git a/test/cookbooks/runit_test/metadata.rb b/test/cookbooks/runit_test/metadata.rb index 1b3e368..829a223 100644 --- a/test/cookbooks/runit_test/metadata.rb +++ b/test/cookbooks/runit_test/metadata.rb @@ -1,6 +1,9 @@ -name 'runit_test' -maintainer 'Chef Software, Inc.' -maintainer_email 'cookbooks@chef.io' -license 'Apache 2.0' -description 'This cookbook is used with test-kitchen to test the parent, runit cookbok' -version '1.0.0' +name 'runit_test' +maintainer 'Chef Software, Inc.' +maintainer_email 'cookbooks@chef.io' +license 'Apache 2.0' +description 'This cookbook is used with test-kitchen to test the parent, runit cookbook' +version '1.0.1' + +depends 'runit' +depends 'runit_other_test' diff --git a/test/cookbooks/runit_test/recipes/service.rb b/test/cookbooks/runit_test/recipes/service.rb index 0428c16..95ae065 100644 --- a/test/cookbooks/runit_test/recipes/service.rb +++ b/test/cookbooks/runit_test/recipes/service.rb @@ -19,6 +19,12 @@ include_recipe 'runit::default' +link '/usr/local/bin/sv' do + to '/usr/bin/sv' +end + +package 'socat' + package 'netcat' do package_name 'nc' if platform_family?('rhel', 'fedora') end @@ -36,17 +42,15 @@ shell '/bin/bash' home '/home/floyd' manage_home true - supports :manage_home => true + supports manage_home: true end -%w{ sv service }.each do |dir| - +%w(sv service).each do |dir| directory "/home/floyd/#{dir}" do owner 'floyd' group 'floyd' recursive true end - end # Create a service with all the fixin's @@ -60,6 +64,9 @@ # Create a service that uses the default svlog runit_service 'default-svlog' do default_logger true + log_size 10000 # smallish 10k + log_num 12 + log_processor 'gzip' end # Create a service that has a check script @@ -79,7 +86,7 @@ # Create a service that sets options for the templates runit_service 'template-options' do - options(:raspberry => 'delicious') + options(raspberry: 'delicious') end # Create a service that uses control signal files @@ -116,11 +123,20 @@ finish_script_template_name 'yerba-matte' end + +# Create a service with differently named template file, using default logger runit_service 'yerba-alt' do run_template_name 'calabash' default_logger true end +# Create a service with a template sourced from another cookbook +runit_service 'ayahuasca' do + run_template_name 'ayahuasca' + default_logger true + cookbook 'runit_other_test' +end + # Note: this won't update the run script for the above due to # http://tickets.chef.io/browse/COOK-2353 # runit_service 'the other name for yerba-alt' do @@ -128,27 +144,18 @@ # default_logger true # end -# Create a service that should exist but be disabled -runit_service 'exist-disabled' - -log 'Created the exist-disabled service, now disable it' - runit_service 'exist-disabled' do - action :disable -end - -runit_service 'other-cookbook-templates' do - cookbook 'runit-other_test' + action [:create, :disable] end -unless platform_family?('rhel', 'fedora') - # Create a service that has a package with its own service directory - package 'git-daemon-run' +# unless platform_family?('rhel', 'fedora') +# # Create a service that has a package with its own service directory +# package 'git-daemon-run' - runit_service 'git-daemon' do - sv_templates false - end -end +# runit_service 'git-daemon' do +# sv_templates false +# end +# end # Despite waiting for runit to create supervise/ok, sometimes services # are supervised, but not actually fully started @@ -158,17 +165,55 @@ end end -# Notify the plain defaults service as a normal service resource +# # Notify the plain defaults service as a normal service resource file '/tmp/notifier' do content Time.now.to_s notifies :restart, 'service[plain-defaults]', :immediately end -# Test for COOK-2867 -link '/etc/init.d/cook-2867' do - to '/usr/bin/sv' +file '/tmp/notifier-2' do + content Time.now.to_s + notifies :restart, 'runit_service[plain-defaults]', :immediately end -runit_service 'cook-2867' do - default_logger true +# # Test for COOK-2867 +# link '/etc/init.d/cook-2867' do +# to '/usr/bin/sv' +# end + +# runit_service 'cook-2867' do +# default_logger true +# end + + +# create a service using an alternate sv binary +runit_service 'alternative-sv-bin' do + sv_bin '/usr/local/bin/sv' +end + +runit_service "downed-service-6702" do + start_down true +end + +runit_service "un-downed-service" do + start_down true +end + +runit_service "un-downed-service remove down" do + service_name 'un-downed-service' + log_template_name 'un-downed-service' + run_template_name 'un-downed-service' + start_down false +end + +runit_service "un-downed-service-deleted" do + start_down true +end + +runit_service "un-downed-service-deleted remove down" do + service_name 'un-downed-service-deleted' + log_template_name 'un-downed-service-deleted' + run_template_name 'un-downed-service-deleted' + start_down false + delete_downfile true end diff --git a/test/cookbooks/runit-other_test/templates/default/sv-other-cookbook-templates-log-run.erb b/test/cookbooks/runit_test/templates/default/sv-alternative-sv-bin-log-run.erb similarity index 100% rename from test/cookbooks/runit-other_test/templates/default/sv-other-cookbook-templates-log-run.erb rename to test/cookbooks/runit_test/templates/default/sv-alternative-sv-bin-log-run.erb diff --git a/test/cookbooks/runit_test/templates/default/sv-alternative-sv-bin-run.erb b/test/cookbooks/runit_test/templates/default/sv-alternative-sv-bin-run.erb new file mode 100755 index 0000000..96a5126 --- /dev/null +++ b/test/cookbooks/runit_test/templates/default/sv-alternative-sv-bin-run.erb @@ -0,0 +1,3 @@ +#!/bin/sh +exec 2>&1 +exec nc -l 3008 diff --git a/test/cookbooks/runit_test/templates/default/sv-default-svlog-run.erb b/test/cookbooks/runit_test/templates/default/sv-default-svlog-run.erb index edd2dbc..f976810 100644 --- a/test/cookbooks/runit_test/templates/default/sv-default-svlog-run.erb +++ b/test/cookbooks/runit_test/templates/default/sv-default-svlog-run.erb @@ -1,3 +1,3 @@ #!/bin/sh exec 2>&1 -exec nc -l 6701 +exec socat - TCP4-LISTEN:6701,fork diff --git a/test/cookbooks/runit_test/templates/default/sv-downed-service-log-run.erb b/test/cookbooks/runit_test/templates/default/sv-downed-service-6702-log-run.erb similarity index 100% rename from test/cookbooks/runit_test/templates/default/sv-downed-service-log-run.erb rename to test/cookbooks/runit_test/templates/default/sv-downed-service-6702-log-run.erb diff --git a/test/cookbooks/runit_test/templates/default/sv-downed-service-run.erb b/test/cookbooks/runit_test/templates/default/sv-downed-service-6702-run.erb similarity index 100% rename from test/cookbooks/runit_test/templates/default/sv-downed-service-run.erb rename to test/cookbooks/runit_test/templates/default/sv-downed-service-6702-run.erb diff --git a/test/cookbooks/runit_test/templates/default/sv-un-downed-service-deleted-log-run.erb b/test/cookbooks/runit_test/templates/default/sv-un-downed-service-deleted-log-run.erb new file mode 100644 index 0000000..a79a518 --- /dev/null +++ b/test/cookbooks/runit_test/templates/default/sv-un-downed-service-deleted-log-run.erb @@ -0,0 +1,2 @@ +#!/bin/sh +exec svlogd -tt ./main diff --git a/test/cookbooks/runit_test/templates/default/sv-un-downed-service-deleted-run.erb b/test/cookbooks/runit_test/templates/default/sv-un-downed-service-deleted-run.erb new file mode 100644 index 0000000..35e5a8d --- /dev/null +++ b/test/cookbooks/runit_test/templates/default/sv-un-downed-service-deleted-run.erb @@ -0,0 +1,3 @@ +#!/bin/sh +exec 2>&1 +exec nc -l 6716 diff --git a/test/cookbooks/runit_test/templates/default/sv-un-downed-service-log-run.erb b/test/cookbooks/runit_test/templates/default/sv-un-downed-service-log-run.erb new file mode 100644 index 0000000..a79a518 --- /dev/null +++ b/test/cookbooks/runit_test/templates/default/sv-un-downed-service-log-run.erb @@ -0,0 +1,2 @@ +#!/bin/sh +exec svlogd -tt ./main diff --git a/test/cookbooks/runit_test/templates/default/sv-un-downed-service-run.erb b/test/cookbooks/runit_test/templates/default/sv-un-downed-service-run.erb new file mode 100644 index 0000000..f915f5b --- /dev/null +++ b/test/cookbooks/runit_test/templates/default/sv-un-downed-service-run.erb @@ -0,0 +1,3 @@ +#!/bin/sh +exec 2>&1 +exec nc -l 6715 diff --git a/test/integration/default/serverspec/linux_spec.rb b/test/integration/default/serverspec/linux_spec.rb new file mode 100644 index 0000000..5a6f3b8 --- /dev/null +++ b/test/integration/default/serverspec/linux_spec.rb @@ -0,0 +1,23 @@ +require 'serverspec' + +set :backend, :exec + +puts "os: #{os}" + +if %w( redhat fedora debian ubuntu ).include? os[:family] + describe package('runit') do + it { should be_installed } + end + + describe command('ps -ef | grep -v grep | grep "runsvdir"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsvdir/) } + end + + describe file('/etc/service') do + it { should be_directory } + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end +end diff --git a/test/integration/service/serverspec/debian_spec.rb b/test/integration/service/serverspec/debian_spec.rb new file mode 100644 index 0000000..99d2639 --- /dev/null +++ b/test/integration/service/serverspec/debian_spec.rb @@ -0,0 +1,286 @@ +require 'serverspec' + +set :backend, :exec + +puts "os: #{os}" + +if %w( debian ).include? os[:family] + + # plain-defaults + describe 'creates a service with the defaults' do + describe command('ps -ef | grep -v grep | grep "runsv plain-defaults"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv plain-defaults/) } + end + + describe file('/etc/init.d/plain-defaults') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + + describe file('/etc/service/plain-defaults') do + it { should be_symlink } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + + describe file('/etc/service/plain-defaults/run') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + + describe file('/etc/service/plain-defaults/log') do + it { should be_directory } + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + + describe file('/etc/service/plain-defaults/log/run') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + end + + # no-svlog + describe 'creates a service that doesnt use the svlog' do + describe command('ps -ef | grep -v grep | grep "runsv no-svlog"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv no-svlog/) } + end + + describe file('/etc/service/no-svlog/log') do + it { should_not be_directory } + end + end + + # default-svlog + describe 'creates a service that uses the default svlog' do + describe command('ps -ef | grep -v grep | grep "runsv default-svlog"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv default-svlog/) } + end + + describe file('/etc/service/default-svlog/log/run') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + regexp = %r{#!/bin/sh\nexec svlogd -tt /var/log/default-svlog} + its(:content) { should match regexp } + end + end + + # Send some random data to the service logs and wait for logs to be written + describe command('dd if=/dev/urandom bs=5K count=10 | strings --bytes=1 | socat - "TCP4:127.0.0.1:6701" && sleep 2') do + its(:exit_status) { should eq 0 } + end + + describe command('file /var/log/default-svlog/*.s') do + its(:stdout) { should contain('gzip compressed data') } + end + + # checker + describe 'creates a service that has a check script' do + describe command('ps -ef | grep -v grep | grep "runsv checker"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv checker/) } + end + + describe file('/etc/service/checker/check') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + end + + # finisher + describe 'creates a service that has a finish script' do + describe command('ps -ef | grep -v grep | grep "runsv finisher"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv finisher/) } + end + + describe file('/etc/service/finisher/finish') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + end + + # env-files + describe 'creates a service that uses env files' do + describe command('ps -ef | grep -v grep | grep "runsv env-files"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv env-files/) } + end + + describe file('/etc/service/env-files/env/PATH') do + it { should be_mode 640 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + regexp = %r{\$PATH:/opt/chef/embedded/bin} + its(:content) { should match regexp } + end + end + + # template-options + describe 'creates a service that sets options for the templates' do + describe command('ps -ef | grep -v grep | grep "runsv template-options"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv template-options/) } + end + + describe file('/etc/service/template-options/run') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + regexp = '# Options are delicious' + its(:content) { should match regexp } + end + end + + # control-signals + describe 'creates a service that uses control signal files' do + describe command('ps -ef | grep -v grep | grep "runsv control-signals"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv control-signals/) } + end + + describe file('/etc/service/control-signals/control/u') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + regexp = 'control signal up' + its(:content) { should match regexp } + end + end + + # runsvdir-floyd + describe 'creates a runsvdir service for a normal user' do + describe command('ps -ef | grep -v grep | grep "runsv runsvdir-floyd"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv runsvdir-floyd/) } + end + + describe file('/etc/service/runsvdir-floyd/run') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + regexp = %r{exec chpst -ufloyd runsvdir /home/floyd/service} + its(:content) { should match regexp } + end + end + + # timer + describe 'creates a service using sv_timeout' do + describe command('ps -ef | grep -v grep | grep "runsv timer"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv timer/) } + end + # FIXME: add something here + end + + # chatterbox + describe 'creates a service using sv_verbose' do + describe command('ps -ef | grep -v grep | grep "runsv chatterbox"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv chatterbox/) } + end + # FIXME: add something here + end + + # floyds-app + describe 'creates a service running by a normal user in its runsvdir' do + describe command('ps -ef | grep -v grep | grep "runsv floyds-app"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv floyds-app/) } + end + + describe file('/etc/init.d/floyds-app') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + + describe file('/home/floyd/service/floyds-app') do + it { should be_symlink } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + + describe file('/home/floyd/service/floyds-app/run') do + it { should be_mode 755 } + it { should be_owned_by 'floyd' } + it { should be_grouped_into 'floyd' } + end + + describe file('/home/floyd/service/floyds-app/log') do + it { should be_directory } + it { should be_mode 755 } + it { should be_owned_by 'floyd' } + it { should be_grouped_into 'floyd' } + end + + describe file('/home/floyd/service/floyds-app/log/run') do + it { should be_mode 755 } + it { should be_owned_by 'floyd' } + it { should be_grouped_into 'floyd' } + end + end + + # yerba + describe 'creates a service with differently named template files' do + describe command('ps -ef | grep -v grep | grep "runsv yerba"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv yerba/) } + end + # FIXME: add something here + end + + # yerba-alt + describe 'creates a service with differently named run script template' do + describe command('ps -ef | grep -v grep | grep "runsv yerba-alt"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv yerba-alt/) } + end + # FIXME: add something here + end + + # ayahuasca + describe 'creates a service with a template from another cookbook' do + describe command('ps -ef | grep -v grep | grep "runsv ayahuasca"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv ayahuasca/) } + end + end + + # exist-disabled + describe 'creates a service that should exist but be disabled' do + describe command('ps -ef | grep -v grep | grep "runsv control-signals"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should_not match(/runsv exist-disabled/) } + end + + describe file('/etc/sv/exist-disabled/run') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + end + + # alternative-sv-bin + describe 'creates a service with an alternative sv_bin' do + describe command('ps -ef | grep -v grep | grep "runsv alternative-sv-bin"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv alternative-sv-bin/) } + end + + describe file('/etc/init.d/alternative-sv-bin') do + its(:content) { should match(/^RUNIT=\/usr\/local\/bin\/sv$/) } + end + end + +end diff --git a/test/integration/service/serverspec/linux_spec.rb b/test/integration/service/serverspec/linux_spec.rb new file mode 100644 index 0000000..3fde460 --- /dev/null +++ b/test/integration/service/serverspec/linux_spec.rb @@ -0,0 +1,337 @@ +require 'serverspec' + +set :backend, :exec + +puts "os: #{os}" + +if %w( redhat fedora ubuntu ).include? os[:family] + + # plain-defaults + describe 'creates a service with the defaults' do + describe command('ps -ef | grep -v grep | grep "runsv plain-defaults"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv plain-defaults/) } + end + + describe file('/etc/init.d/plain-defaults') do + it { should be_symlink } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + + describe file('/etc/service/plain-defaults') do + it { should be_symlink } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + + describe file('/etc/service/plain-defaults/run') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + + describe file('/etc/service/plain-defaults/log') do + it { should be_directory } + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + + describe file('/etc/service/plain-defaults/log/run') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + end + + # no-svlog + describe 'creates a service that doesnt use the svlog' do + describe command('ps -ef | grep -v grep | grep "runsv no-svlog"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv no-svlog/) } + end + + describe file('/etc/service/no-svlog/log') do + it { should_not be_directory } + end + end + + # default-svlog + describe 'creates a service that uses the default svlog' do + describe command('ps -ef | grep -v grep | grep "runsv default-svlog"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv default-svlog/) } + end + + describe file('/etc/service/default-svlog/log/run') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + regexp = %r{#!/bin/sh\nexec svlogd -tt /var/log/default-svlog} + its(:content) { should match regexp } + end + + # Send some random data to the service logs and wait for logs to be written + describe command('dd if=/dev/urandom bs=5K count=10 | strings --bytes=1 | socat - "TCP4:127.0.0.1:6701" && sleep 2') do + its(:exit_status) { should eq 0 } + end + + describe command('file /var/log/default-svlog/*.s') do + its(:stdout) { should contain('gzip compressed data') } + end + end + + # checker + describe 'creates a service that has a check script' do + describe command('ps -ef | grep -v grep | grep "runsv checker"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv checker/) } + end + + describe file('/etc/service/checker/check') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + end + + # finisher + describe 'creates a service that has a finish script' do + describe command('ps -ef | grep -v grep | grep "runsv finisher"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv finisher/) } + end + + describe file('/etc/service/finisher/finish') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + end + + # env-files + describe 'creates a service that uses env files' do + describe command('ps -ef | grep -v grep | grep "runsv env-files"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv env-files/) } + end + + describe file('/etc/service/env-files/env/PATH') do + it { should be_mode 640 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + regexp = %r{\$PATH:/opt/chef/embedded/bin} + its(:content) { should match regexp } + end + end + + # template-options + describe 'creates a service that sets options for the templates' do + describe command('ps -ef | grep -v grep | grep "runsv template-options"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv template-options/) } + end + + describe file('/etc/service/template-options/run') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + regexp = '# Options are delicious' + its(:content) { should match regexp } + end + end + + # control-signals + describe 'creates a service that uses control signal files' do + describe command('ps -ef | grep -v grep | grep "runsv control-signals"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv control-signals/) } + end + + describe file('/etc/service/control-signals/control/u') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + regexp = 'control signal up' + its(:content) { should match regexp } + end + end + + # runsvdir-floyd + describe 'creates a runsvdir service for a normal user' do + describe command('ps -ef | grep -v grep | grep "runsv runsvdir-floyd"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv runsvdir-floyd/) } + end + + describe file('/etc/service/runsvdir-floyd/run') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + regexp = %r{exec chpst -ufloyd runsvdir /home/floyd/service} + its(:content) { should match regexp } + end + end + + # timer + describe 'creates a service using sv_timeout' do + describe command('ps -ef | grep -v grep | grep "runsv timer"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv timer/) } + end + # FIXME: add something here + end + + # chatterbox + describe 'creates a service using sv_verbose' do + describe command('ps -ef | grep -v grep | grep "runsv chatterbox"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv chatterbox/) } + end + # FIXME: add something here + end + + # floyds-app + describe 'creates a service running by a normal user in its runsvdir' do + describe command('ps -ef | grep -v grep | grep "runsv floyds-app"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv floyds-app/) } + end + + describe file('/etc/init.d/floyds-app') do + it { should be_symlink } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + + describe file('/home/floyd/service/floyds-app') do + it { should be_symlink } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + + describe file('/home/floyd/service/floyds-app/run') do + it { should be_mode 755 } + it { should be_owned_by 'floyd' } + it { should be_grouped_into 'floyd' } + end + + describe file('/home/floyd/service/floyds-app/log') do + it { should be_directory } + it { should be_mode 755 } + it { should be_owned_by 'floyd' } + it { should be_grouped_into 'floyd' } + end + + describe file('/home/floyd/service/floyds-app/log/run') do + it { should be_mode 755 } + it { should be_owned_by 'floyd' } + it { should be_grouped_into 'floyd' } + end + end + + # yerba + describe 'creates a service with differently named template files' do + describe command('ps -ef | grep -v grep | grep "runsv yerba"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv yerba/) } + end + # FIXME: add something here + end + + # yerba-alt + describe 'creates a service with differently named run script template' do + describe command('ps -ef | grep -v grep | grep "runsv yerba-alt"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv yerba-alt/) } + end + # FIXME: add something here + end + + # ayahuasca + describe 'creates a service with a template from another cookbook' do + describe command('ps -ef | grep -v grep | grep "runsv ayahuasca"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv ayahuasca/) } + end + end + + # exist-disabled + describe 'creates a service that should exist but be disabled' do + describe command('ps -ef | grep -v grep | grep "runsv control-signals"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should_not match(/runsv exist-disabled/) } + end + + describe file('/etc/sv/exist-disabled/run') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + end + + # alternative-sv-bin + describe 'creates a service with an alternative sv_bin' do + describe command('ps -ef | grep -v grep | grep "runsv alternative-sv-bin"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv alternative-sv-bin/) } + end + + describe file('/etc/init.d/alternative-sv-bin') do + it { should be_symlink } + it { should be_linked_to('/usr/local/bin/sv') } + end + end + + # downed service + describe 'creates and manages down file for service' do + describe 'creates a service with a default state of down' do + describe file('/etc/sv/downed-service-6702/run') do + it { should be_mode 755 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + + describe file('/etc/service/downed-service-6702') do + it { should be_symlink } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + + describe file('/etc/sv/downed-service-6702/down') do + it { should be_mode 644 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + + describe command('ps -ef | grep -v grep | grep "runsv downed-service-6702"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv downed-service-6702/) } + end + + describe command('netstat -tuplen | grep LISTEN | grep 6702') do + its(:exit_status) { should eq 1 } + end + end + + describe 'leaves existing downfile in place when down true -> false' do + describe file('/etc/sv/un-downed-service/down') do + it { should be_mode 644 } + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + end + + describe command('ps -ef | grep -v grep | grep "runsv un-downed-service"') do + its(:exit_status) { should eq 0 } + its(:stdout) { should match(/runsv un-downed-service/) } + end + end + describe 'removes existing downfile when requested' do + describe file('/etc/sv/un-downed-service-deleted/down') do + it { should_not exist } + end + end + end + +end diff --git a/test/spec/libraries/provider_runit_service_spec.rb b/test/spec/libraries/provider_runit_service_spec.rb deleted file mode 100644 index c95e099..0000000 --- a/test/spec/libraries/provider_runit_service_spec.rb +++ /dev/null @@ -1,669 +0,0 @@ -# -# Author:: Joshua Timberman -# Author:: Seth Chisamore -# -# Copyright:: Copyright (c) 2012, Chef Software, Inc. -# -# 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. -# - -$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..')) -require 'spec_helper' - -describe Chef::Provider::Service::Runit do - - subject(:provider) { Chef::Provider::Service::Runit.new(new_resource, run_context) } - - let(:sv_bin) { '/usr/bin/sv' } - let(:service_name) { 'getty.service' } - let(:service_dir) { '/etc/service' } - let(:service_dir_name) { "#{service_dir}/#{service_name}" } - let(:service_status_command) { "#{sv_bin} status #{service_dir}/#{service_name}" } - let(:run_script) { File.join(service_dir, service_name, 'run') } - let(:log_run_script) { File.join(service_dir, service_name, 'log', 'run') } - let(:log_config_file) { File.join(service_dir, service_name, 'log', 'config') } - - let(:node) do - node = Chef::Node.new - node.automatic['platform'] = 'ubuntu' - node.automatic['platform_version'] = '12.04' - node.set['runit']['sv_bin'] = sv_bin - node - end - let(:events) { Chef::EventDispatch::Dispatcher.new } - let(:run_context) { Chef::RunContext.new(node, {}, events) } - - let(:new_resource) { Chef::Resource::RunitService.new('getty.service') } - let(:current_resource) { Chef::Resource::RunitService.new('getty.service') } - - before do - provider.stub(:load_current_resource).and_return(current_resource) - provider.new_resource = new_resource - provider.current_resource = current_resource - end - - describe '#load_current_resource' do - - before do - provider.unstub(:load_current_resource) - end - - describe 'runit is not installed' do - it 'raises an exception' do - ->{ provider.load_current_resource }.should raise_error - end - end - - context 'runit is installed' do - - let(:status_output) { "run: #{service_name}: (pid 29018) 3s; run: log: (pid 24470) 46882s" } - - before do - File.stub(:exist?).with(sv_bin).and_return(true) - File.stub(:executable?).with(sv_bin).and_return(true) - provider.stub(:shell_out) - .with(service_status_command) - .and_return(double('ouput', :stdout => status_output, :exitstatus => 0)) - provider.load_current_resource - end - - describe 'parsing sv status output' do - - context 'returns a pid' do - let(:status_output) { "run: #{service_name}: (pid 29018) 3s; run: log: (pid 24470) 46882s" } - - it 'sets resource running state to true' do - provider.current_resource.running.should be_true - end - end - - context 'returns an empty pid' do - let(:status_output) { "down: #{service_name}: 2s, normally up; run: log: (pid 24470) 46250s" } - - it 'sets resource running state to false' do - provider.current_resource.running.should be_false - end - end - end - - describe 'checking for service run script' do - context 'service run script is present in service_dir' do - before do - ::File.stub(:exists?).with(run_script).and_return(true) - provider.load_current_resource - end - - it 'sets resource enabled state to true' do - provider.current_resource.enabled.should be_true - end - end - - context 'service run script is missing' do - before do - ::File.stub(:exists?).with(run_script).and_return(false) - provider.load_current_resource - end - - it 'sets resource enabled state to false' do - provider.current_resource.enabled.should be_false - end - end - end - - describe 'set the current environment' do - let(:sv_env_dir_name) { ::File.join(new_resource.sv_dir, new_resource.service_name, 'env') } - context 'present env dir' do - before do - ::File.stub(:directory?).with(sv_env_dir_name).and_return(true) - ::Dir.stub(:glob).with(::File.join(sv_env_dir_name,'*')).and_return([::File.join(sv_env_dir_name,'FOO')]) - ::IO.stub(:read).with(::File.join(sv_env_dir_name,'FOO')).and_return('bar') - provider.load_current_resource - end - it 'should load environment from env dir' do - provider.current_resource.env.should eq({'FOO' => 'bar'}) - end - end - context 'no env dir' do - before do - ::File.stub(:directory?).with(sv_env_dir_name).and_return(false) - end - it 'should set env to an empty hash' do - provider.current_resource.env.should eq({}) - end - end - end - end - end - - describe 'actions' do - describe 'start' do - - before do - provider.current_resource.running(false) - end - - %w{start up once cont}.each do |action| - it "sends the #{action} command to the sv binary" do - provider.should_receive(:shell_out!).with("#{sv_bin} #{action} #{service_dir_name}") - provider.run_action(action.to_sym) - end - end - end - - describe 'action_usr1' do - it 'sends the usr1 signal to the sv binary' do - provider.should_receive(:shell_out!).with("#{sv_bin} 1 #{service_dir_name}") - provider.run_action(:usr1) - end - end - - describe 'action_usr2' do - it 'sends the usr2 signal to the sv binary' do - provider.should_receive(:shell_out!).with("#{sv_bin} 2 #{service_dir_name}") - provider.run_action(:usr2) - end - end - - describe 'actions that manage a running service' do - before do - provider.current_resource.running(true) - end - - %w{stop down restart hup int term kill quit}.each do |action| - it "sends the '#{action}' command to the sv binary" do - provider.should_receive(:shell_out!).with("#{sv_bin} #{action} #{service_dir_name}") - provider.run_action(action.to_sym) - end - end - - describe 'action_reload' do - it "sends the 'force-reload' command to the sv binary" do - provider.should_receive(:shell_out!).with("#{sv_bin} force-reload #{service_dir_name}") - provider.run_action(:reload) - end - end - end - - describe 'action_disable' do - before do - provider.current_resource.enabled(true) - end - - it 'disables the service by running the down command and removing the symlink' do - provider.should_receive(:shell_out).with("#{sv_bin} down #{service_dir_name}") - FileUtils.should_receive(:rm).with(service_dir_name) - provider.run_action(:disable) - end - end - - describe 'action_enable' do - let(:sv_dir_name) { ::File.join(new_resource.sv_dir, new_resource.service_name) } - - before(:each) do - provider.current_resource.enabled(false) - FileTest.stub(:pipe?).with("#{service_dir_name}/supervise/ok").and_return(true) - FileTest.stub(:pipe?).with("#{service_dir_name}/log/supervise/ok").and_return(true) - end - - it 'creates the sv_dir directory' do - provider.send(:sv_dir).path.should eq(sv_dir_name) - provider.send(:sv_dir).recursive.should be_true - provider.send(:sv_dir).owner.should eq(new_resource.owner) - provider.send(:sv_dir).group.should eq(new_resource.group) - provider.send(:sv_dir).mode.should eq(00755) - end - - it 'creates the run script template' do - provider.send(:run_script).path.should eq(::File.join(sv_dir_name, 'run')) - provider.send(:run_script).owner.should eq(new_resource.owner) - provider.send(:run_script).group.should eq(new_resource.group) - provider.send(:run_script).mode.should eq(00755) - provider.send(:run_script).source.should eq("sv-#{new_resource.service_name}-run.erb") - provider.send(:run_script).cookbook.should be_empty - end - - it 'sets up the supervised log directory and run script' do - provider.send(:log_dir).path.should eq(::File.join(sv_dir_name, 'log')) - provider.send(:log_dir).recursive.should be_true - provider.send(:log_dir).owner.should eq(new_resource.owner) - provider.send(:log_dir).group.should eq(new_resource.group) - provider.send(:log_dir).mode.should eq(00755) - provider.send(:log_main_dir).path.should eq(::File.join(sv_dir_name, 'log', 'main')) - provider.send(:log_main_dir).recursive.should be_true - provider.send(:log_main_dir).owner.should eq(new_resource.owner) - provider.send(:log_main_dir).group.should eq(new_resource.group) - provider.send(:log_main_dir).mode.should eq(00755) - provider.send(:log_run_script).path.should eq(::File.join(sv_dir_name, 'log', 'run')) - provider.send(:log_run_script).owner.should eq(new_resource.owner) - provider.send(:log_run_script).group.should eq(new_resource.group) - provider.send(:log_run_script).mode.should eq(00755) - provider.send(:log_run_script).source.should eq("sv-#{new_resource.log_template_name}-log-run.erb") - provider.send(:log_run_script).cookbook.should be_empty - provider.send(:log_config_file).path.should eq(::File.join(sv_dir_name, 'log', 'config')) - provider.send(:log_config_file).owner.should eq(new_resource.owner) - provider.send(:log_config_file).group.should eq(new_resource.group) - provider.send(:log_config_file).mode.should eq(00644) - provider.send(:log_config_file).source.should eq('log-config.erb') - provider.send(:log_config_file).cookbook.should eq('runit') - end - - it 'creates log/run with default content if default_logger parameter is true' do - script_content = "exec svlogd -tt /var/log/#{new_resource.service_name}" - new_resource.default_logger(true) - provider.send(:log_run_script).path.should eq(::File.join(sv_dir_name, 'log', 'run')) - provider.send(:log_run_script).owner.should eq(new_resource.owner) - provider.send(:log_run_script).group.should eq(new_resource.group) - provider.send(:log_run_script).mode.should eq(00755) - provider.send(:log_run_script).content.should include(script_content) - provider.send(:default_log_dir).path.should eq(::File.join('/var', 'log', new_resource.service_name)) - provider.send(:default_log_dir).recursive.should be_true - provider.send(:default_log_dir).owner.should eq(new_resource.owner) - provider.send(:default_log_dir).group.should eq(new_resource.group) - provider.send(:default_log_dir).mode.should eq(00755) - end - - it 'creates env directory and files' do - provider.send(:env_dir).path.should eq(::File.join(sv_dir_name, 'env')) - provider.send(:env_dir).owner.should eq(new_resource.owner) - provider.send(:env_dir).group.should eq(new_resource.group) - provider.send(:env_dir).mode.should eq(00755) - new_resource.env('PATH' => '$PATH:/usr/local/bin') - provider.send(:env_files)[0].path.should eq(::File.join(sv_dir_name, 'env', 'PATH')) - provider.send(:env_files)[0].owner.should eq(new_resource.owner) - provider.send(:env_files)[0].group.should eq(new_resource.group) - provider.send(:env_files)[0].content.should eq('$PATH:/usr/local/bin') - end - - it 'removes env files that are not referenced in env' do - provider.current_resource.stub(:env).and_return('FOO' => 'Bar') - new_resource.stub(:env).and_return('PATH' => '/bin') - delete = provider.send(:env_files).select { |x| x.action.include? :delete } - delete.first.path.should eq(::File.join(sv_dir_name, 'env', 'FOO')) - end - - it 'creates a check script as a template if check_script parameter is true' do - provider.send(:check_script).path.should eq(::File.join(sv_dir_name, 'check')) - provider.send(:check_script).owner.should eq(new_resource.owner) - provider.send(:check_script).group.should eq(new_resource.group) - provider.send(:check_script).mode.should eq(00755) - provider.send(:check_script).source.should eq("sv-#{new_resource.check_script_template_name}-check.erb") - provider.send(:check_script).cookbook.should be_empty - end - - it 'creates a finish script as a template if finish_script parameter is true' do - provider.send(:finish_script).path.should eq(::File.join(sv_dir_name, 'finish')) - provider.send(:finish_script).owner.should eq(new_resource.owner) - provider.send(:finish_script).group.should eq(new_resource.group) - provider.send(:finish_script).mode.should eq(00755) - provider.send(:finish_script).source.should eq("sv-#{new_resource.finish_script_template_name}-finish.erb") - provider.send(:finish_script).cookbook.should be_empty - end - - it 'creates control directory and signal files' do - provider.send(:control_dir).path.should eq(::File.join(sv_dir_name, 'control')) - provider.send(:control_dir).owner.should eq(new_resource.owner) - provider.send(:control_dir).group.should eq(new_resource.group) - provider.send(:control_dir).mode.should eq(00755) - new_resource.control(['s']) - provider.send(:control_signal_files)[0].path.should eq(::File.join(sv_dir_name, 'control', 's')) - provider.send(:control_signal_files)[0].owner.should eq(new_resource.owner) - provider.send(:control_signal_files)[0].group.should eq(new_resource.group) - provider.send(:control_signal_files)[0].mode.should eq(00755) - provider.send(:control_signal_files)[0].source.should eq("sv-#{new_resource.control_template_names['s']}-s.erb") - provider.send(:control_signal_files)[0].cookbook.should be_empty - end - - it 'creates a symlink for LSB script compliance unless the platform is debian' do - node.automatic['platform'] = 'not_debian' - provider.send(:lsb_init).path.should eq(::File.join('/etc', 'init.d', new_resource.service_name)) - provider.send(:lsb_init).to.should eq(sv_bin) - end - - it 'creates an init script as a template for LSB compliance if the platform is debian' do - node.automatic['platform'] = 'debian' - provider.send(:lsb_init).path.should eq(::File.join('/etc', 'init.d', new_resource.service_name)) - provider.send(:lsb_init).owner.should eq('root') - provider.send(:lsb_init).group.should eq('root') - provider.send(:lsb_init).mode.should eq(00755) - provider.send(:lsb_init).cookbook.should eq('runit') - provider.send(:lsb_init).source.should eq('init.d.erb') - provider.send(:lsb_init).variables.should have_key(:name) - provider.send(:lsb_init).variables[:name].should eq(new_resource.service_name) - end - - it 'does not create anything in the sv_dir if it is nil or false' do - current_resource.stub(:enabled).and_return(false) - new_resource.stub(:sv_templates).and_return(false) - provider.should_not_receive(:sv_dir) - provider.send(:run_script).should_not_receive(:run_action).with(:create) - provider.send(:log_run_script).should_not_receive(:run_action).with(:create) - provider.should_not_receive(:log) - provider.should_not_receive(:log_main_dir) - provider.send(:lsb_init).should_receive(:run_action).with(:create) - provider.send(:service_link).should_receive(:run_action).with(:create) - provider.run_action(:enable) - end - - describe 'when sv_timeout is set' do - before do - new_resource.sv_timeout(60) - end - - %w{start up once cont}.each do |action| - it "pass a timeout argument on #{action} action to the sv binary" do - provider.current_resource.running(false) - provider.should_receive(:shell_out!).with("#{sv_bin} -w '60' #{action} #{service_dir_name}") - provider.run_action(action.to_sym) - end - end - - { - :usr1 => 1, - :usr2 => 2, - :reload => 'force-reload', - }.each do |action, arg| - it "pass a timeout argument on #{action} action to the sv binary" do - provider.current_resource.running(true) - provider.should_receive(:shell_out!).with("#{sv_bin} -w '60' #{arg} #{service_dir_name}") - provider.run_action(action.to_sym) - end - end - - %w{stop down restart hup int term kill quit}.each do |action| - it "pass a timeout argument on #{action} action to the sv binary" do - provider.current_resource.running(true) - provider.should_receive(:shell_out!).with("#{sv_bin} -w '60' #{action} #{service_dir_name}") - provider.run_action(action.to_sym) - end - end - - end - - describe 'when sv_verbose is true' do - before do - new_resource.sv_verbose(true) - end - - %w{start up once cont}.each do |action| - it "pass a verbose argument on #{action} action to the sv binary" do - provider.current_resource.running(false) - provider.should_receive(:shell_out!).with("#{sv_bin} -v #{action} #{service_dir_name}") - provider.run_action(action.to_sym) - end - end - - { - :usr1 => 1, - :usr2 => 2, - :reload => 'force-reload', - }.each do |action, arg| - it "pass a verbose argument on #{action} action to the sv binary" do - provider.current_resource.running(true) - provider.should_receive(:shell_out!).with("#{sv_bin} -v #{arg} #{service_dir_name}") - provider.run_action(action.to_sym) - end - end - - %w{stop down restart hup int term kill quit}.each do |action| - it "pass a verbose argument on #{action} action to the sv binary" do - provider.current_resource.running(true) - provider.should_receive(:shell_out!).with("#{sv_bin} -v #{action} #{service_dir_name}") - provider.run_action(action.to_sym) - end - end - - end - - describe 'when both sv_timeout and sv_verbose are set' do - before do - new_resource.sv_timeout(60) - new_resource.sv_verbose(true) - end - - %w{ start up once cont }.each do |action| - it "pass both timeout and verbose arguments on #{action} action to the sv binary" do - provider.current_resource.running(false) - provider.should_receive(:shell_out!).with("#{sv_bin} -w '60' -v #{action} #{service_dir_name}") - provider.run_action(action.to_sym) - end - end - - { - :usr1 => 1, - :usr2 => 2, - :reload => 'force-reload', - }.each do |action, arg| - it "pass both timeout and verbose arguments on #{action} action to the sv binary" do - provider.current_resource.running(true) - provider.should_receive(:shell_out!).with("#{sv_bin} -w '60' -v #{arg} #{service_dir_name}") - provider.run_action(action.to_sym) - end - end - - %w{stop down restart hup int term kill quit}.each do |action| - it "pass both timeout and verbose arguments argument on #{action} action to the sv binary" do - provider.current_resource.running(true) - provider.should_receive(:shell_out!).with("#{sv_bin} -w '60' -v #{action} #{service_dir_name}") - provider.run_action(action.to_sym) - end - end - - end - - it 'creates a symlink from the sv dir to the service' do - provider.send(:service_link).path.should eq(service_dir_name) - provider.send(:service_link).to.should eq(sv_dir_name) - end - - it 'enables the service with memoized resource creation methods' do - current_resource.stub(:enabled).and_return(false) - provider.send(:sv_dir).should_receive(:run_action).with(:create) - provider.send(:run_script).should_receive(:run_action).with(:create) - provider.send(:log_dir).should_receive(:run_action).with(:create) - provider.send(:log_main_dir).should_receive(:run_action).with(:create) - provider.send(:log_run_script).should_receive(:run_action).with(:create) - provider.send(:log_config_file).should_receive(:run_action).with(:create) - provider.send(:lsb_init).should_receive(:run_action).with(:create) - provider.send(:service_link).should_receive(:run_action).with(:create) - provider.run_action(:enable) - end - - describe 'run_script template changes' do - before do - provider.stub(:configure_service) - provider.stub(:enable_service) - end - - context 'run_script is updated' do - before { provider.send(:run_script).stub(:updated_by_last_action?).and_return(true) } - - context 'restart_on_update attribute is true' do - before { new_resource.restart_on_update(true) } - - it 'restarts the service' do - provider.should_receive(:restart_service) - provider.run_action(:enable) - end - end - - context 'restart_on_update attribute is false' do - before { new_resource.restart_on_update(false) } - - it 'does not restart the service' do - provider.should_not_receive(:restart_service) - provider.run_action(:enable) - end - end - end - - context 'run script is unchanged' do - before { provider.send(:run_script).stub(:updated_by_last_action?).and_return(false) } - - context 'restart_on_update attribute is true' do - before { new_resource.restart_on_update(true) } - - it 'does not restart the service' do - provider.should_not_receive(:restart_service) - provider.run_action(:enable) - end - end - - context 'restart_on_update attribute is false' do - before { new_resource.restart_on_update(false) } - - it 'does not restart the service' do - provider.should_not_receive(:restart_service) - provider.run_action(:enable) - end - end - end - end - - describe 'log_run_script template changes' do - before do - provider.stub(:configure_service) - provider.stub(:enable_service) - end - - context 'log_run_script is updated' do - before { provider.send(:log_run_script).stub(:updated_by_last_action?).and_return(true) } - - context 'restart_on_update attribute is true' do - before { new_resource.restart_on_update(true) } - - it 'restarts the service' do - provider.should_receive(:restart_log_service) - provider.run_action(:enable) - end - end - - context 'restart_on_update attribute is false' do - before { new_resource.restart_on_update(false) } - - it 'does not restart the service' do - provider.should_not_receive(:restart_log_service) - provider.run_action(:enable) - end - end - end - - context 'log_run_script is unchanged' do - before { provider.send(:log_run_script).stub(:updated_by_last_action?).and_return(false) } - - context 'restart_on_update attribute is true' do - before { new_resource.restart_on_update(true) } - - it 'does not restart the service' do - provider.should_not_receive(:restart_log_service) - provider.run_action(:enable) - end - end - - context 'restart_on_update attribute is false' do - before { new_resource.restart_on_update(false) } - - it 'does not restart the service' do - provider.should_not_receive(:restart_log_service) - provider.run_action(:enable) - end - end - end - end - - describe 'log_config_file template changes' do - before do - provider.stub(:configure_service) - provider.stub(:enable_service) - end - - context 'log_config_file is updated' do - before { provider.send(:log_config_file).stub(:updated_by_last_action?).and_return(true) } - - context 'restart_on_update attribute is true' do - before { new_resource.restart_on_update(true) } - - it 'restarts the service' do - provider.should_receive(:restart_log_service) - provider.run_action(:enable) - end - end - - context 'restart_on_update attribute is false' do - before { new_resource.restart_on_update(false) } - - it 'does not restart the service' do - provider.should_not_receive(:restart_log_service) - provider.run_action(:enable) - end - end - end - - context 'log_config_file is unchanged' do - before { provider.send(:log_config_file).stub(:updated_by_last_action?).and_return(false) } - - context 'restart_on_update attribute is true' do - before { new_resource.restart_on_update(true) } - - it 'does not restart the service' do - provider.should_not_receive(:restart_log_service) - provider.run_action(:enable) - end - end - - context 'restart_on_update attribute is false' do - before { new_resource.restart_on_update(false) } - - it 'does not restart the service' do - provider.should_not_receive(:restart_log_service) - provider.run_action(:enable) - end - end - end - end - - context 'new resource conditionals' do - before(:each) do - current_resource.stub(:enabled).and_return(false) - provider.send(:sv_dir).stub(:run_action).with(:create) - provider.send(:run_script).stub(:run_action).with(:create) - provider.send(:lsb_init).stub(:run_action).with(:create) - provider.send(:service_link).stub(:run_action).with(:create) - provider.send(:log_dir).stub(:run_action).with(:create) - provider.send(:log_main_dir).stub(:run_action).with(:create) - provider.send(:log_run_script).stub(:run_action).with(:create) - provider.send(:log_config_file).stub(:run_action).with(:create) - end - - it 'doesnt create the log dir or run script if log is false' do - new_resource.stub(:log).and_return(false) - provider.should_not_receive(:log) - provider.run_action(:enable) - end - - it 'creates the env dir and config files if env is set' do - new_resource.stub(:env).and_return('PATH' => '/bin') - provider.send(:env_dir).should_receive(:run_action).with(:create) - provider.send(:env_files).should_receive(:each).once - provider.run_action(:enable) - end - - it 'creates the control dir and signal files if control is set' do - new_resource.stub(:control).and_return %w{ s u } - provider.send(:control_dir).should_receive(:run_action).with(:create) - provider.send(:control_signal_files).should_receive(:each).once - provider.run_action(:enable) - end - end - end - end -end diff --git a/test/spec/libraries/resource_runit_service_spec.rb b/test/spec/libraries/resource_runit_service_spec.rb deleted file mode 100644 index ef1fb41..0000000 --- a/test/spec/libraries/resource_runit_service_spec.rb +++ /dev/null @@ -1,314 +0,0 @@ -# -# Author:: Joshua Timberman -# Author:: Seth Chisamore -# -# Copyright:: Copyright (c) 2012, Chef Software, Inc. -# -# 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. -# - -$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..')) -require 'spec_helper' - -describe Chef::Resource::RunitService do - - subject(:resource) { Chef::Resource::RunitService.new(service_name, run_context) } - - let(:service_name) { 'getty.service' } - let(:node) { Chef::Node.new } - let(:events) { Chef::EventDispatch::Dispatcher.new } - let(:run_context) { Chef::RunContext.new(node, {}, events) } - - its(:class) { should be Chef::Resource::RunitService } - its(:resource_name) { should eq(:runit_service) } - its(:provider) { should eq(Chef::Provider::Service::Runit) } - its(:service_name) { should eq('getty.service') } - its(:sv_dir) { should eq('/etc/sv') } - its(:sv_bin) { should eq('/usr/bin/sv') } - its(:lsb_init_dir) { should eq('/etc/init.d') } - its(:sv_timeout) { should eq(nil) } - its(:sv_verbose) { should eq(false) } - - describe 'setting supported default values from node attributes' do - let(:sv_bin) { '/fake/bin/sv_bin' } - let(:sv_dir) { '/fake/sv_dir/path' } - let(:service_dir) { '/fake/service_dir' } - let(:lsb_init_dir) { '/fake/lsb_init_dir' } - let(:node) do - node = Chef::Node.new - node.set['runit']['sv_bin'] = sv_bin - node.set['runit']['sv_dir'] = sv_dir - node.set['runit']['service_dir'] = service_dir - node.set['runit']['lsb_init_dir'] = lsb_init_dir - node - end - - its(:sv_bin) { should eq sv_bin } - its(:sv_dir) { should eq sv_dir } - its(:service_dir) { should eq service_dir } - its(:lsb_init_dir) { should eq lsb_init_dir } - end - - describe 'backward compatiblility hack' do - - let(:simple_service_name) { "service[#{service_name}]" } - - it 'creates a simple service with the same name' do - resource_collection = resource.run_context.resource_collection - simple_service = resource_collection.find(simple_service_name) - simple_service.to_s.should eq(simple_service_name) - simple_service.class.should be Chef::Resource::Service - simple_service.provider.should be Chef::Provider::Service::Simple - end - - end - - it 'has an sv_dir parameter that can be set' do - resource.sv_dir('/var/lib/sv') - resource.sv_dir.should eq('/var/lib/sv') - end - - it 'allows sv_dir parameter to be set false (so users can use an existing sv dir)' do - resource.sv_dir(false) - resource.sv_dir.should be_false - end - - it 'has a service_dir parameter set to /etc/service by default' do - resource.service_dir.should eq('/etc/service') - end - - it 'has a service_dir parameter that can be set' do - resource.service_dir('/var/service') - resource.service_dir.should eq('/var/service') - end - - it 'has a lsb_init_dir parameter set to /etc/init.d by default' do - resource.lsb_init_dir.should eq('/etc/init.d') - end - - it 'has a lsb_init_dir parameter that can be set' do - resource.lsb_init_dir('/other/lsb_init_dir') - resource.lsb_init_dir.should eq('/other/lsb_init_dir') - end - - it 'has a control parameter that can be set as an array of service control characters' do - resource.control %w{ s u } - resource.control.should eq %w{ s u } - end - - it 'has an options parameter that can be set as a hash of arbitrary options' do - resource.options(:binary => '/usr/bin/noodles') - resource.options.should have_key(:binary) - resource.options[:binary].should eq('/usr/bin/noodles') - end - - it 'has an env parameter that can be set as a hash of environment variables' do - resource.env('PATH' => '$PATH:/usr/local/bin') - resource.env.should have_key('PATH') - resource.env['PATH'].should include('/usr/local/bin') - end - - it 'adds :env_dir to options if env is set' do - resource.env('PATH' => '/bin') - resource.options.should have_key(:env_dir) - resource.options[:env_dir].should eq(::File.join(resource.sv_dir, resource.service_name, 'env')) - end - - it 'has a log parameter to control whether a log service is setup' do - resource.log.should be_true - end - - it 'has a log parameter that can be set to false' do - resource.log(false) - resource.log.should be_false - end - - it 'should return default (true) if the log parameter is set to nil' do - resource.log(nil) - resource.log.should be true - end - - it 'has a cookbook parameter that can be set' do - resource.cookbook('noodles') - resource.cookbook.should eq('noodles') - end - - it 'has a check parameter that is false by default' do - resource.check.should be_false - end - - it 'hash a check parameter that controls whether a check script is created' do - resource.check(true) - resource.check.should be_true - end - - it 'has a finish parameter that is false by default' do - resource.finish.should be_false - end - - it 'hash a finish parameter that controls whether a finish script is created' do - resource.finish(true) - resource.finish.should be_true - end - - it 'has an owner parameter that can be set' do - resource.owner('monkey') - resource.owner.should eq('monkey') - end - - it 'has a group parameter that can be set' do - resource.group('primates') - resource.group.should eq('primates') - end - - it 'has an enabled parameter to determine if the current resource is enabled' do - resource.enabled.should be_false - end - - it 'has a running parameter to determine if the current resource is running' do - resource.running.should be_false - end - - it 'has a default_logger parameter that is false by default' do - resource.default_logger.should be_false - end - - it 'has a default_logger parameter that controls whether a default log template should be created' do - resource.default_logger(true) - resource.default_logger.should be_true - end - - it 'has a restart_on_update parameter that is true by default' do - resource.restart_on_update.should be_true - end - - it 'has a restart_on_update parameter that controls whether a the service is restarted when the run script is updated' do - resource.restart_on_update(false) - resource.restart_on_update.should be_false - end - - it 'sets the run_template_name to the service_name by default' do - resource.run_template_name.should eq(resource.service_name) - end - - it 'sets the log_template_name to the service_name by default' do - resource.log_template_name.should eq(resource.service_name) - end - - it 'has a run_template_name parameter to allow a custom template name for the run run script' do - resource.run_template_name('foo_bar') - resource.run_template_name.should eq('foo_bar') - end - - it 'has a template_name parameter to allow a custom template name for the run run script for backwards compatiblility' do - resource.template_name('foo_baz') - resource.run_template_name.should eq('foo_baz') - end - - it 'has a log_template_name parameter to allow a custom template name for the log run script' do - resource.log_template_name('write_noodles') - resource.log_template_name.should eq('write_noodles') - end - - it 'sets the control_template_names for each control character to the service_name by default' do - resource.control %w{ s u } - resource.control_template_names.should have_key('s') - resource.control_template_names.should have_key('u') - resource.control_template_names['s'].should eq(resource.service_name) - resource.control_template_names['u'].should eq(resource.service_name) - end - - it 'has a control_template_names parameter to allow custom template names for the control scripts' do - resource.control_template_names( - 's' => 'banana_start', - 'u' => 'noodle_up' - ) - resource.control_template_names.should have_key('s') - resource.control_template_names.should have_key('u') - resource.control_template_names['s'].should eq('banana_start') - resource.control_template_names['u'].should eq('noodle_up') - end - - it 'sets the check_script_template_name to the service_name by default' do - resource.check_script_template_name.should eq(resource.service_name) - end - - it 'has a check_script_template_name parameter to allow a custom template name for the check script' do - resource.check_script_template_name('eat_bananas') - resource.check_script_template_name.should eq('eat_bananas') - end - - it 'sets the finish_script_template_name to the service_name by default' do - resource.finish_script_template_name.should eq(resource.service_name) - end - - it 'has a finish_script_template_name parameter to allow a custom template name for the finish script' do - resource.finish_script_template_name('eat_bananas') - resource.finish_script_template_name.should eq('eat_bananas') - end - - it 'has a sv_templates parameter to control whether the sv_dir templates are created' do - resource.sv_templates(false) - resource.sv_templates.should be_false - end - - it 'has a sv_timeout parameter to control sv_bin timeout' do - resource.sv_timeout(30) - resource.sv_timeout.should eq(30) - end - - it 'has a sv_verbose parameter to control sv_bin verbose mode' do - resource.sv_verbose(true) - resource.sv_verbose.should eq(true) - end - - it 'has a log_size parameter to control the maximum log size' do - resource.log_size(1_000_000) - resource.log_size.should eq(1_000_000) - end - - it 'has a log_num parameter to control the maximum number of logs' do - resource.log_num(10) - resource.log_num.should eq(10) - end - - it 'has a log_min parameter to control the minimum number of logs' do - resource.log_min(5) - resource.log_min.should eq(5) - end - - it 'has a log_timeout parameter to control the maximum age of a log file' do - resource.log_timeout(60 * 60) - resource.log_timeout.should eq(60 * 60) - end - - it 'has a log_processor parameter to allow logs to be fed through it after rotation' do - resource.log_processor('/usr/local/bin/process') - resource.log_processor.should eq('/usr/local/bin/process') - end - - it 'has a log_socket parameter to allow log lines to be sent to a UDP socket' do - resource.log_socket('127.0.0.1:1514') - resource.log_socket.should eq('127.0.0.1:1514') - end - - it 'has a log_prefix parameter to allow log lines to be prefixed with a fixed string' do - resource.log_prefix('myservice:') - resource.log_prefix.should eq('myservice:') - end - - it 'has a log_config_append parameter to allow arbitrary configuration entries to be added to the configuration' do - resource.log_config_append('-bogus') - resource.log_config_append.should eq('-bogus') - end -end diff --git a/test/spec/spec_helper.rb b/test/spec/spec_helper.rb deleted file mode 100644 index 100360b..0000000 --- a/test/spec/spec_helper.rb +++ /dev/null @@ -1,28 +0,0 @@ - -require 'chef/platform' -require 'chef/run_context' -require 'chef/resource' -require 'chef/resource/service' -require 'chef/provider/service/simple' -require 'chef/event_dispatch/base' -require 'chef/event_dispatch/dispatcher' - -$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', 'libraries')) -require 'provider_runit_service' -require 'resource_runit_service' - -RSpec.configure do |config| - # Use color in STDOUT - config.color_enabled = true - - # Use color not only in STDOUT but also in pagers and files - config.tty = true - - # Use the specified formatter - config.formatter = :documentation # :progress, :html, :textmate - - # :focus support to allow zooming in a single test/block - config.filter_run :focus => true - config.run_all_when_everything_filtered = true - config.treat_symbols_as_metadata_keys_with_true_values = true -end