diff options
author | Serdar Sutay <serdar@opscode.com> | 2014-10-21 11:14:19 -0700 |
---|---|---|
committer | Serdar Sutay <serdar@opscode.com> | 2014-10-21 11:14:19 -0700 |
commit | eeb45770585a50d78e412682b0ae44524e29e727 (patch) | |
tree | c1d2e00403722fa111e6bd01d2f56bc0ccabe790 | |
parent | ccb220a72ba07a9b2cbabba25f88edb7e7064d7b (diff) | |
parent | 09fbf4a6efacad4c635531b005dbc5832e8c03c8 (diff) | |
download | chef-eeb45770585a50d78e412682b0ae44524e29e727.tar.gz |
Merge pull request #2028 from ClogenyTechnologies/kd/aix-service
aix service provider
-rw-r--r-- | lib/chef/platform/provider_mapping.rb | 3 | ||||
-rw-r--r-- | lib/chef/provider/service/aix.rb | 126 | ||||
-rw-r--r-- | lib/chef/provider/service/aixinit.rb | 117 | ||||
-rw-r--r-- | lib/chef/providers.rb | 2 | ||||
-rwxr-xr-x | spec/functional/assets/chefinittest | 34 | ||||
-rwxr-xr-x | spec/functional/assets/testchefsubsys | 11 | ||||
-rwxr-xr-x | spec/functional/resource/aix_service_spec.rb | 136 | ||||
-rwxr-xr-x | spec/functional/resource/aixinit_service_spec.rb | 211 | ||||
-rw-r--r-- | spec/spec_helper.rb | 1 | ||||
-rw-r--r-- | spec/unit/provider/service/aix_service_spec.rb | 181 | ||||
-rw-r--r-- | spec/unit/provider/service/aixinit_service_spec.rb | 269 |
11 files changed, 1090 insertions, 1 deletions
diff --git a/lib/chef/platform/provider_mapping.rb b/lib/chef/platform/provider_mapping.rb index 9e15ea5658..e6d948276c 100644 --- a/lib/chef/platform/provider_mapping.rb +++ b/lib/chef/platform/provider_mapping.rb @@ -394,7 +394,8 @@ class Chef :ifconfig => Chef::Provider::Ifconfig::Aix, :cron => Chef::Provider::Cron::Aix, :package => Chef::Provider::Package::Aix, - :user => Chef::Provider::User::Aix + :user => Chef::Provider::User::Aix, + :service => Chef::Provider::Service::Aix } }, :exherbo => { diff --git a/lib/chef/provider/service/aix.rb b/lib/chef/provider/service/aix.rb new file mode 100644 index 0000000000..6f70f797b9 --- /dev/null +++ b/lib/chef/provider/service/aix.rb @@ -0,0 +1,126 @@ +# +# Author:: kaustubh (<kaustubh@clogeny.com>) +# Copyright:: Copyright (c) 2014 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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/provider/service' + +class Chef + class Provider + class Service + class Aix < Chef::Provider::Service + attr_reader :status_load_success + + def initialize(new_resource, run_context) + super + end + + def load_current_resource + @current_resource = Chef::Resource::Service.new(@new_resource.name) + @current_resource.service_name(@new_resource.service_name) + + @status_load_success = true + @priority_success = true + @is_resource_group = false + + determine_current_status! + + @current_resource + end + + def whyrun_supported? + true + end + + def start_service + if @is_resource_group + shell_out!("startsrc -g #{@new_resource.service_name}") + else + shell_out!("startsrc -s #{@new_resource.service_name}") + end + end + + def stop_service + if @is_resource_group + shell_out!("stopsrc -g #{@new_resource.service_name}") + else + shell_out!("stopsrc -s #{@new_resource.service_name}") + end + end + + def restart_service + stop_service + start_service + end + + def reload_service + if @is_resource_group + shell_out!("refresh -g #{@new_resource.service_name}") + else + shell_out!("refresh -s #{@new_resource.service_name}") + end + end + + def shared_resource_requirements + super + requirements.assert(:all_actions) do |a| + a.assertion { @status_load_success } + a.whyrun ["Service status not available. Assuming a prior action would have installed the service.", "Assuming status of not running."] + end + end + + def define_resource_requirements + # FIXME? need reload from service.rb + shared_resource_requirements + end + + protected + def determine_current_status! + Chef::Log.debug "#{@new_resource} using lssrc to check the status " + begin + services = shell_out!("lssrc -a | grep -w #{@new_resource.service_name}").stdout.split("\n") + is_resource_group?(services) + + if services.length == 1 && services[0].split(' ').last == "active" + @current_resource.running true + else + @current_resource.running false + end + Chef::Log.debug "#{@new_resource} running: #{@current_resource.running}" + # ShellOut sometimes throws different types of Exceptions than ShellCommandFailed. + # Temporarily catching different types of exceptions here until we get Shellout fixed. + # TODO: Remove the line before one we get the ShellOut fix. + rescue Mixlib::ShellOut::ShellCommandFailed, SystemCallError + @status_load_success = false + @current_resource.running false + nil + end + end + + def is_resource_group? (services) + if services.length > 1 + Chef::Log.debug("#{@new_resource.service_name} is a group") + @is_resource_group = true + elsif services[0].split(' ')[1] == @new_resource.service_name + Chef::Log.debug("#{@new_resource.service_name} is a group") + @is_resource_group = true + end + end + end + end + end +end + diff --git a/lib/chef/provider/service/aixinit.rb b/lib/chef/provider/service/aixinit.rb new file mode 100644 index 0000000000..ab4b8e5406 --- /dev/null +++ b/lib/chef/provider/service/aixinit.rb @@ -0,0 +1,117 @@ +# +# Author:: kaustubh (<kaustubh@clogeny.com>) +# Copyright:: Copyright (c) 2014 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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/provider/service/init' + +class Chef + class Provider + class Service + class AixInit < Chef::Provider::Service::Init + RC_D_SCRIPT_NAME = /\/etc\/rc.d\/rc2.d\/([SK])(\d\d|)/i + + def initialize(new_resource, run_context) + super + @init_command = "/etc/rc.d/init.d/#{@new_resource.service_name}" + end + + def load_current_resource + super + @priority_success = true + @rcd_status = nil + + set_current_resource_attributes + @current_resource + end + + def action_enable + if @new_resource.priority.nil? + priority_ok = true + else + priority_ok = @current_resource.priority == @new_resource.priority + end + if @current_resource.enabled and priority_ok + Chef::Log.debug("#{@new_resource} already enabled - nothing to do") + else + converge_by("enable service #{@new_resource}") do + enable_service + Chef::Log.info("#{@new_resource} enabled") + end + end + load_new_resource_state + @new_resource.enabled(true) + end + + def enable_service + Dir.glob(["/etc/rc.d/rc2.d/[SK][0-9][0-9]#{@new_resource.service_name}", "/etc/rc.d/rc2.d/[SK]#{@new_resource.service_name}"]).each { |f| ::File.delete(f)} + + if @new_resource.priority.is_a? Integer + create_symlink(2, 'S', @new_resource.priority) + + elsif @new_resource.priority.is_a? Hash + @new_resource.priority.each do |level,o| + create_symlink(level,(o[0] == :start ? 'S' : 'K'),o[1]) + end + else + create_symlink(2, 'S', '') + end + end + + def disable_service + Dir.glob(["/etc/rc.d/rc2.d/[SK][0-9][0-9]#{@new_resource.service_name}", "/etc/rc.d/rc2.d/[SK]#{@new_resource.service_name}"]).each { |f| ::File.delete(f) } + + if @new_resource.priority.is_a? Integer + create_symlink(2, 'K',100 - @new_resource.priority) + elsif @new_resource.priority.is_a? Hash + @new_resource.priority.each do |level,o| + create_symlink(level, 'K', 100 - o[1]) if o[0] == :stop + end + else + create_symlink(2, 'K', '') + end + end + + def create_symlink(run_level, status, priority) + ::File.symlink("/etc/rc.d/init.d/#{@new_resource.service_name}", "/etc/rc.d/rc#{run_level}.d/#{status}#{priority}#{@new_resource.service_name}") + end + + def set_current_resource_attributes + # assuming run level 2 for aix + is_enabled = false + files = Dir.glob(["/etc/rc.d/rc2.d/[SK][0-9][0-9]#{@new_resource.service_name}", "/etc/rc.d/rc2.d/[SK]#{@new_resource.service_name}"]) + + priority = {} + + files.each do |file| + if (RC_D_SCRIPT_NAME =~ file) + priority[2] = [($1 == "S" ? :start : :stop), ($2.empty? ? '' : $2.to_i)] + if $1 == "S" + is_enabled = true + end + end + end + + if is_enabled && files.length == 1 + priority = priority[2][1] + end + @current_resource.enabled(is_enabled) + @current_resource.priority(priority) + end + end + end + end +end
\ No newline at end of file diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb index fec00d0e63..bceb1f7106 100644 --- a/lib/chef/providers.rb +++ b/lib/chef/providers.rb @@ -88,6 +88,8 @@ require 'chef/provider/service/upstart' require 'chef/provider/service/windows' require 'chef/provider/service/solaris' require 'chef/provider/service/macosx' +require 'chef/provider/service/aixinit' +require 'chef/provider/service/aix' require 'chef/provider/user/dscl' require 'chef/provider/user/pw' diff --git a/spec/functional/assets/chefinittest b/spec/functional/assets/chefinittest new file mode 100755 index 0000000000..79e064cd5f --- /dev/null +++ b/spec/functional/assets/chefinittest @@ -0,0 +1,34 @@ +#!/bin/ksh + +function create_chef_txt { + touch /tmp/chefinittest.txt +} + +function delete_chef_txt { + rm /tmp/chefinittest.txt +} + +function rename_chef_txt { + mv /tmp/chefinittest.txt /tmp/$1 +} + +case "$1" in +start ) + create_chef_txt + ;; +stop ) + delete_chef_txt + ;; +status ) + [ -f /tmp/chefinittest.txt ] || [ -f /tmp/chefinittest_reload.txt ] || [ -f /tmp/chefinittest_restart.txt ] + ;; +reload ) + rename_chef_txt "chefinittest_reload.txt" + ;; +restart ) + rename_chef_txt "chefinittest_restart.txt" + ;; +* ) + echo "Usage: $0 (start | stop | restart | reload)" + exit 1 +esac diff --git a/spec/functional/assets/testchefsubsys b/spec/functional/assets/testchefsubsys new file mode 100755 index 0000000000..e9ff30d4aa --- /dev/null +++ b/spec/functional/assets/testchefsubsys @@ -0,0 +1,11 @@ +#!/bin/bash +# trapchild + +sleep 120 & + +pid="$!" + +trap 'echo I am going down, so killing off my processes..; kill $pid; exit' SIGHUP SIGINT + SIGQUIT SIGTERM + +wait
\ No newline at end of file diff --git a/spec/functional/resource/aix_service_spec.rb b/spec/functional/resource/aix_service_spec.rb new file mode 100755 index 0000000000..6008fdea8f --- /dev/null +++ b/spec/functional/resource/aix_service_spec.rb @@ -0,0 +1,136 @@ +# encoding: UTF-8 +# +# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>) +# Copyright:: Copyright (c) 2014 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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 'spec_helper' +require 'functional/resource/base' +require 'chef/mixin/shell_out' + +shared_examples "src service" do + + include Chef::Mixin::ShellOut + + def service_should_be_started + expect(shell_out!("lssrc -a | grep #{new_resource.service_name}").stdout.split(' ').last).to eq("active") + end + + def service_should_be_stopped + expect(shell_out!("lssrc -a | grep #{new_resource.service_name}").stdout.split(' ').last).to eq("inoperative") + end + + def get_service_pid + args = shell_out!("lssrc -a | grep #{new_resource.service_name}").stdout.split(' ') + if args.length == 3 + args[1] + else + args[2] + end + end + + describe "start service" do + it "should start the service" do + new_resource.run_action(:start) + service_should_be_started + end + end + + describe "stop service" do + before do + new_resource.run_action(:start) + end + + it "should stop the service" do + new_resource.run_action(:stop) + service_should_be_stopped + end + end + + describe "restart service" do + before do + new_resource.run_action(:start) + end + + it "should restart the service" do + new_resource.run_action(:restart) + service_should_be_started + end + end +end + +describe Chef::Resource::Service, :requires_root, :aix_only do + def get_user_id + shell_out("id -u #{ENV['USER']}").stdout.chomp + end + + describe "When service is a subsystem" do + before(:all) do + script_dir = File.join(File.dirname(__FILE__), "/../assets/") + shell_out!("mkssys -s ctestsys -p #{script_dir}/testchefsubsys -u #{get_user_id} -S -n 15 -f 9 -R -Q") + end + + after(:each) do + shell_out("stopsrc -s ctestsys") + end + + after(:all) do + shell_out!("rmssys -s ctestsys") + end + + + let(:new_resource) do + new_resource = Chef::Resource::Service.new("ctestsys", run_context) + new_resource + end + + let(:provider) do + provider = new_resource.provider_for_action(new_resource.action) + provider + end + + it_behaves_like "src service" + end + + + describe "When service is a group" do + before(:all) do + script_dir = File.join(File.dirname(__FILE__), "/../assets/") + shell_out!("mkssys -s ctestsys -p #{script_dir}/testchefsubsys -u #{get_user_id} -S -n 15 -f 9 -R -Q -G ctestgrp") + end + + after(:each) do + shell_out("stopsrc -g ctestgrp") + end + + after(:all) do + # rmssys supports only -s option. + shell_out!("rmssys -s ctestsys") + end + + let(:new_resource) do + new_resource = Chef::Resource::Service.new("ctestgrp", run_context) + new_resource + end + + let(:provider) do + provider = new_resource.provider_for_action(new_resource.action) + provider + end + + it_behaves_like "src service" + end +end diff --git a/spec/functional/resource/aixinit_service_spec.rb b/spec/functional/resource/aixinit_service_spec.rb new file mode 100755 index 0000000000..a99309187c --- /dev/null +++ b/spec/functional/resource/aixinit_service_spec.rb @@ -0,0 +1,211 @@ +# encoding: UTF-8 +# +# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>) +# Copyright:: Copyright (c) 2014 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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 'spec_helper' +require 'functional/resource/base' +require 'chef/mixin/shell_out' +require 'fileutils' + +describe Chef::Resource::Service, :requires_root, :aix_only do + + include Chef::Mixin::ShellOut + + # Platform specific validation routines. + def service_should_be_started(file_name) + # The existance of this file indicates that the service was started. + expect(File.exists?("/tmp/#{file_name}")).to be_true + end + + def service_should_be_stopped(file_name) + expect(File.exists?("/tmp/#{file_name}")).to be_false + end + + def valide_symlinks(expected_output, run_level = nil, status = nil, priority = nil) + directory = [] + if priority.is_a?Hash + priority.each do |level,o| + directory << "/etc/rc.d/rc#{level}.d/#{(o[0] == :start ? 'S' : 'K')}#{o[1]}#{new_resource.service_name}" + end + directory + else + directory << "/etc/rc.d/rc#{run_level}.d/#{status}#{priority}#{new_resource.service_name}" + end + expect(Dir.glob(directory)).to eq(expected_output) + File.delete(*directory) + end + + def delete_test_files + files = Dir.glob("/tmp/chefinit[a-z_]*.txt") + File.delete(*files) + end + + # Actual tests + let(:new_resource) do + new_resource = Chef::Resource::Service.new("chefinittest", run_context) + new_resource.provider Chef::Provider::Service::AixInit + new_resource.supports({:status => true, :restart => true, :reload => true}) + new_resource + end + + let(:provider) do + provider = new_resource.provider_for_action(new_resource.action) + provider + end + + before(:all) do + File.delete("/etc/rc.d/init.d/chefinittest") if File.exists?("/etc/rc.d/init.d/chefinittest") + FileUtils.cp("#{File.join(File.dirname(__FILE__), "/../assets/chefinittest")}", "/etc/rc.d/init.d/chefinittest") + end + + after(:all) do + File.delete("/etc/rc.d/init.d/chefinittest") if File.exists?("/etc/rc.d/init.d/chefinittest") + end + + before(:each) do + delete_test_files + end + + after(:each) do + delete_test_files + end + + describe "start service" do + it "should start the service" do + new_resource.run_action(:start) + service_should_be_started("chefinittest.txt") + end + end + + describe "stop service" do + before do + new_resource.run_action(:start) + end + + it "should stop the service" do + new_resource.run_action(:stop) + service_should_be_stopped("chefinittest.txt") + end + end + + describe "restart service" do + before do + new_resource.run_action(:start) + end + + it "should restart the service" do + new_resource.run_action(:restart) + service_should_be_started("chefinittest_restart.txt") + end + end + + describe "reload service" do + before do + new_resource.run_action(:start) + end + + it "should reload the service" do + new_resource.run_action(:reload) + service_should_be_started("chefinittest_reload.txt") + end + end + + describe "enable service" do + + context "when the service doesn't set a priority" do + it "creates symlink with status S" do + new_resource.run_action(:enable) + valide_symlinks(["/etc/rc.d/rc2.d/Schefinittest"],2,'S') + end + end + + context "when the service sets a simple priority (integer)" do + before do + new_resource.priority(75) + end + + it "creates a symlink with status S and a priority" do + new_resource.run_action(:enable) + valide_symlinks(["/etc/rc.d/rc2.d/S75chefinittest"], 2,'S',75) + end + end + + context "when the service sets complex priorities (hash)" do + before do + priority = {2 => [:start, 20], 3 => [:stop, 10]} + new_resource.priority(priority) + end + + it "create symlink with status start (S) or stop (K) and a priority " do + new_resource.run_action(:enable) + valide_symlinks(["/etc/rc.d/rc2.d/S20chefinittest", "/etc/rc.d/rc3.d/K10chefinittest"], 2,'S',new_resource.priority) + end + end + end + + describe "disable_service" do + + context "when the service doesn't set a priority" do + before do + File.symlink("/etc/rc.d/init.d/chefinittest", "/etc/rc.d/rc2.d/Schefinittest") + end + + after do + File.delete("/etc/rc.d/rc2.d/Schefinittest") if File.exists?("/etc/rc.d/rc2.d/chefinittest") + end + + it "creates symlink with status K" do + new_resource.run_action(:disable) + valide_symlinks(["/etc/rc.d/rc2.d/Kchefinittest"], 2,'K') + end + end + + context "when the service sets a simple priority (integer)" do + before do + new_resource.priority(75) + File.symlink("/etc/rc.d/init.d/chefinittest", "/etc/rc.d/rc2.d/Schefinittest") + end + + after do + File.delete("/etc/rc.d/rc2.d/Schefinittest") if File.exists?("/etc/rc.d/rc2.d/chefinittest") + end + + it "creates a symlink with status K and a priority" do + new_resource.run_action(:disable) + valide_symlinks(["/etc/rc.d/rc2.d/K25chefinittest"], 2,'K',25) + end + end + + context "when the service sets complex priorities (hash)" do + before do + @priority = {2 => [:stop, 20], 3 => [:start, 10]} + new_resource.priority(@priority) + File.symlink("/etc/rc.d/init.d/chefinittest", "/etc/rc.d/rc2.d/Schefinittest") + end + + after do + File.delete("/etc/rc.d/rc2.d/Schefinittest") if File.exists?("/etc/rc.d/rc2.d/chefinittest") + end + + it "create symlink with status stop (K) and a priority " do + new_resource.run_action(:disable) + valide_symlinks(["/etc/rc.d/rc2.d/K80chefinittest"], 2,'K',80) + end + end + end +end
\ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index d29215f5fe..b1d7cdbd64 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -119,6 +119,7 @@ RSpec.configure do |config| config.filter_run_excluding :solaris_only => true unless solaris? config.filter_run_excluding :system_windows_service_gem_only => true unless system_windows_service_gem? config.filter_run_excluding :unix_only => true unless unix? + config.filter_run_excluding :aix_only => true unless aix? config.filter_run_excluding :supports_cloexec => true unless supports_cloexec? config.filter_run_excluding :selinux_only => true unless selinux_enabled? config.filter_run_excluding :ruby_18_only => true unless ruby_18? diff --git a/spec/unit/provider/service/aix_service_spec.rb b/spec/unit/provider/service/aix_service_spec.rb new file mode 100644 index 0000000000..070f618b99 --- /dev/null +++ b/spec/unit/provider/service/aix_service_spec.rb @@ -0,0 +1,181 @@ +# +# Author:: Kaustubh <kaustubh@clogeny.com> +# Copyright:: Copyright (c) 2014 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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 'spec_helper' + +describe Chef::Provider::Service::Aix do + before(:each) do + @node = Chef::Node.new + @events = Chef::EventDispatch::Dispatcher.new + @run_context = Chef::RunContext.new(@node, {}, @events) + + @new_resource = Chef::Resource::Service.new("chef") + @current_resource = Chef::Resource::Service.new("chef") + + @provider = Chef::Provider::Service::Aix.new(@new_resource, @run_context) + Chef::Resource::Service.stub(:new).and_return(@current_resource) + end + + describe "load current resource" do + it "should create a current resource with the name of the new resource and determine the status" do + @status = double("Status", :exitstatus => 0, :stdout => @stdout) + @provider.stub(:shell_out!).and_return(@status) + + Chef::Resource::Service.should_receive(:new).and_return(@current_resource) + @current_resource.should_receive(:service_name).with("chef") + @provider.should_receive(:determine_current_status!) + + @provider.load_current_resource + end + end + + describe "determine current status" do + context "when the service is active" do + before do + @status = double("Status", :exitstatus => 0, :stdout => "chef chef 12345 active\n") + end + + it "current resource is running" do + @provider.should_receive(:shell_out!).with("lssrc -a | grep -w chef").and_return(@status) + @provider.should_receive(:is_resource_group?).with(["chef chef 12345 active"]) + + @provider.load_current_resource + @current_resource.running.should be_true + end + end + + context "when the service is inoprative" do + before do + @status = double("Status", :exitstatus => 0, :stdout => "chef chef inoperative\n") + end + + it "current resource is not running" do + @provider.should_receive(:shell_out!).with("lssrc -a | grep -w chef").and_return(@status) + @provider.should_receive(:is_resource_group?).with(["chef chef inoperative"]) + + @provider.load_current_resource + @current_resource.running.should be_false + end + end + end + + describe "is resource group" do + context "when there are mutiple subsystems associated with group" do + before do + @status = double("Status", :exitstatus => 0, :stdout => "chef1 chef 12345 active\nchef2 chef 12334 active\nchef3 chef inoperative") + end + + it "service is a group" do + @provider.should_receive(:shell_out!).with("lssrc -a | grep -w chef").and_return(@status) + @provider.load_current_resource + @provider.instance_eval("@is_resource_group").should be_true + end + end + + context "when there is a single subsystem in the group" do + before do + @status = double("Status", :exitstatus => 0, :stdout => "chef1 chef inoperative\n") + end + + it "service is a group" do + @provider.should_receive(:shell_out!).with("lssrc -a | grep -w chef").and_return(@status) + @provider.load_current_resource + @provider.instance_eval("@is_resource_group").should be_true + end + end + + context "when there service is a subsytem" do + before do + @status = double("Status", :exitstatus => 0, :stdout => "chef chef123 inoperative\n") + end + + it "service is a subsystem" do + @provider.should_receive(:shell_out!).with("lssrc -a | grep -w chef").and_return(@status) + @provider.load_current_resource + @provider.instance_eval("@is_resource_group").should be_false + end + end + end + + describe "when starting the service" do + before do + @new_resource.service_name "apache" + end + + it "should call the start command for groups" do + @provider.instance_eval('@is_resource_group = true') + @provider.should_receive(:shell_out!).with("startsrc -g #{@new_resource.service_name}") + + @provider.start_service + end + + it "should call the start command for subsystem" do + @provider.should_receive(:shell_out!).with("startsrc -s #{@new_resource.service_name}") + + @provider.start_service + end + end + + describe "when stopping a service" do + before do + @new_resource.service_name "apache" + end + + it "should call the stop command for groups" do + @provider.instance_eval('@is_resource_group = true') + @provider.should_receive(:shell_out!).with("stopsrc -g #{@new_resource.service_name}") + + @provider.stop_service + end + + it "should call the stop command for subsystem" do + @provider.should_receive(:shell_out!).with("stopsrc -s #{@new_resource.service_name}") + + @provider.stop_service + end + end + + describe "when reloading a service" do + before do + @new_resource.service_name "apache" + end + + it "should call the reload command for groups" do + @provider.instance_eval('@is_resource_group = true') + @provider.should_receive(:shell_out!).with("refresh -g #{@new_resource.service_name}") + + @provider.reload_service + end + + it "should call the reload command for subsystem" do + @provider.should_receive(:shell_out!).with("refresh -s #{@new_resource.service_name}") + + @provider.reload_service + end + end + + describe "when restarting the service" do + it "should call stop service followed by start service" do + @provider.should_receive(:stop_service) + @provider.should_receive(:start_service) + + @provider.restart_service + end + end +end + diff --git a/spec/unit/provider/service/aixinit_service_spec.rb b/spec/unit/provider/service/aixinit_service_spec.rb new file mode 100644 index 0000000000..bb090b112c --- /dev/null +++ b/spec/unit/provider/service/aixinit_service_spec.rb @@ -0,0 +1,269 @@ +# +# Author:: kaustubh (<kaustubh@clogeny.com>) +# Copyright:: Copyright (c) 2014 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# 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 'spec_helper' + +describe Chef::Provider::Service::AixInit do + before(:each) do + @node = Chef::Node.new + @node.automatic_attrs[:command] = {:ps => 'fuuuu'} + @events = Chef::EventDispatch::Dispatcher.new + @run_context = Chef::RunContext.new(@node, {}, @events) + + @new_resource = Chef::Resource::Service.new("chef") + @provider = Chef::Provider::Service::AixInit.new(@new_resource, @run_context) + + @current_resource = Chef::Resource::Service.new("chef") + @provider.current_resource = @current_resource + + @pid, @stdin, @stdout, @stderr = nil, nil, nil, nil + end + + describe "load_current_resource" do + it "sets current resource attributes" do + @provider.should_receive(:set_current_resource_attributes) + + @provider.load_current_resource + end + end + + describe "action_enable" do + shared_examples_for "the service is up to date" do + it "does not enable the service" do + @provider.should_not_receive(:enable_service) + @provider.action_enable + @provider.set_updated_status + @provider.new_resource.should_not be_updated + end + end + + shared_examples_for "the service is not up to date" do + it "enables the service and sets the resource as updated" do + @provider.should_receive(:enable_service).and_return(true) + @provider.action_enable + @provider.set_updated_status + @provider.new_resource.should be_updated + end + end + + context "when the service is disabled" do + before do + @current_resource.enabled(false) + end + + it_behaves_like "the service is not up to date" + end + + context "when the service is enabled" do + before do + @current_resource.enabled(true) + @current_resource.priority(80) + end + + context "and the service sets no priority" do + it_behaves_like "the service is up to date" + end + + context "and the service requests the same priority as is set" do + before do + @new_resource.priority(80) + end + it_behaves_like "the service is up to date" + end + + context "and the service requests a different priority than is set" do + before do + @new_resource.priority(20) + end + it_behaves_like "the service is not up to date" + end + end + end + + describe "enable_service" do + before do + Dir.stub(:glob).with(["/etc/rc.d/rc2.d/[SK][0-9][0-9]#{@new_resource.service_name}", "/etc/rc.d/rc2.d/[SK]#{@new_resource.service_name}"]).and_return([]) + end + + context "when the service doesn't set a priority" do + it "creates symlink with status S" do + @provider.should_receive(:create_symlink).with(2,'S','') + + @provider.enable_service + end + end + + context "when the service sets a simple priority (integer)" do + before do + @new_resource.priority(75) + end + + it "creates a symlink with status S and a priority" do + @provider.should_receive(:create_symlink).with(2,'S',75) + + @provider.enable_service + end + end + + context "when the service sets complex priorities (hash)" do + before do + priority = {2 => [:start, 20], 3 => [:stop, 10]} + @new_resource.priority(priority) + end + + it "create symlink with status start (S) or stop (K) and a priority " do + @provider.should_receive(:create_symlink).with(2,'S',20) + @provider.should_receive(:create_symlink).with(3,'K',10) + + @provider.enable_service + end + end + end + + describe "disable_service" do + before do + Dir.stub(:glob).with(["/etc/rc.d/rc2.d/[SK][0-9][0-9]#{@new_resource.service_name}", "/etc/rc.d/rc2.d/[SK]#{@new_resource.service_name}"]).and_return([]) + end + + context "when the service doesn't set a priority" do + it "creates symlinks with status stop (K)" do + @provider.should_receive(:create_symlink).with(2,'K','') + + @provider.disable_service + end + end + + context "when the service sets a simple priority (integer)" do + before do + @new_resource.priority(75) + end + + it "create symlink with status stop (k) and a priority " do + @provider.should_receive(:create_symlink).with(2,'K',25) + + @provider.disable_service + end + end + + context "when the service sets complex priorities (hash)" do + before do + @priority = {2 => [:start, 20], 3 => [:stop, 10]} + @new_resource.priority(@priority) + end + + it "create symlink with status stop (k) and a priority " do + @provider.should_receive(:create_symlink).with(3,'K',90) + + @provider.disable_service + end + end + end + + describe "set_current_resource_attributes" do + context "when rc2.d contains only start script" do + before do + files = ["/etc/rc.d/rc2.d/S20apache"] + + Dir.stub(:glob).with(["/etc/rc.d/rc2.d/[SK][0-9][0-9]#{@new_resource.service_name}", "/etc/rc.d/rc2.d/[SK]chef"]).and_return(files) + end + + it "the service is enabled" do + @provider.current_resource.should_receive(:enabled).with(true) + @provider.current_resource.should_receive(:priority).with(20) + + @provider.set_current_resource_attributes + end + end + + context "when rc2.d contains only stop script" do + before do + files = ["/etc/rc.d/rc2.d/K20apache"] + @priority = {2 => [:stop, 20]} + + Dir.stub(:glob).with(["/etc/rc.d/rc2.d/[SK][0-9][0-9]#{@new_resource.service_name}", "/etc/rc.d/rc2.d/[SK]chef"]).and_return(files) + end + it "the service is not enabled" do + @provider.current_resource.should_receive(:enabled).with(false) + @provider.current_resource.should_receive(:priority).with(@priority) + + @provider.set_current_resource_attributes + end + end + + context "when rc2.d contains both start and stop scripts" do + before do + @files = ["/etc/rc.d/rc2.d/S20apache", "/etc/rc.d/rc2.d/K80apache"] + @priority = {2 => [:start, 20], 2 => [:stop, 80]} + + Dir.stub(:glob).with(["/etc/rc.d/rc2.d/[SK][0-9][0-9]#{@new_resource.service_name}", "/etc/rc.d/rc2.d/[SK]chef"]).and_return(@files) + end + it "the service is enabled" do + @current_resource.should_receive(:enabled).with(true) + @current_resource.should_receive(:priority).with(@priority) + + @provider.set_current_resource_attributes + end + end + + context "when rc2.d contains only start script (without priority)" do + before do + files = ["/etc/rc.d/rc2.d/Sapache"] + + Dir.stub(:glob).with(["/etc/rc.d/rc2.d/[SK][0-9][0-9]#{@new_resource.service_name}", "/etc/rc.d/rc2.d/[SK]#{@new_resource.service_name}"]).and_return(files) + end + + it "the service is enabled" do + @provider.current_resource.should_receive(:enabled).with(true) + @provider.current_resource.should_receive(:priority).with('') + + @provider.set_current_resource_attributes + end + end + + context "when rc2.d contains only stop script (without priority)" do + before do + files = ["/etc/rc.d/rc2.d/Kapache"] + @priority = {2 => [:stop, '']} + + Dir.stub(:glob).with(["/etc/rc.d/rc2.d/[SK][0-9][0-9]#{@new_resource.service_name}", "/etc/rc.d/rc2.d/[SK]#{@new_resource.service_name}"]).and_return(files) + end + it "the service is not enabled" do + @provider.current_resource.should_receive(:enabled).with(false) + @provider.current_resource.should_receive(:priority).with(@priority) + + @provider.set_current_resource_attributes + end + end + + context "when rc2.d contains both start and stop scripts" do + before do + files = ["/etc/rc.d/rc2.d/Sapache", "/etc/rc.d/rc2.d/Kapache"] + @priority = {2 => [:start, ''], 2 => [:stop, '']} + + Dir.stub(:glob).with(["/etc/rc.d/rc2.d/[SK][0-9][0-9]#{@new_resource.service_name}", "/etc/rc.d/rc2.d/[SK]#{@new_resource.service_name}"]).and_return(files) + end + it "the service is enabled" do + @current_resource.should_receive(:enabled).with(true) + @current_resource.should_receive(:priority).with(@priority) + + @provider.set_current_resource_attributes + end + end + end +end + |