#! /usr/bin/env ruby # # Unit testing for the SMF service Provider # # author Dominic Cleal # require 'spec_helper' provider_class = Puppet::Type.type(:service).provider(:smf) describe provider_class, :if => Puppet.features.posix? do before(:each) do # Create a mock resource @resource = Puppet::Type.type(:service).new( :name => "/system/myservice", :ensure => :running, :enable => :true) @provider = provider_class.new(@resource) FileTest.stubs(:file?).with('/usr/sbin/svcadm').returns true FileTest.stubs(:executable?).with('/usr/sbin/svcadm').returns true FileTest.stubs(:file?).with('/usr/bin/svcs').returns true FileTest.stubs(:executable?).with('/usr/bin/svcs').returns true end describe ".instances" do it "should have an instances method" do expect(provider_class).to respond_to :instances end it "should get a list of services (excluding legacy)" do provider_class.expects(:svcs).with('-H').returns File.read(my_fixture('svcs.out')) instances = provider_class.instances.map { |p| {:name => p.get(:name), :ensure => p.get(:ensure)} } # we dont manage legacy expect(instances.size).to eq(2) expect(instances[0]).to eq({:name => 'svc:/system/svc/restarter:default', :ensure => :running }) expect(instances[1]).to eq({:name => 'svc:/network/cswrsyncd:default', :ensure => :maintenance }) end end it "should have a restart method" do expect(@provider).to respond_to(:restart) end it "should have a restartcmd method" do expect(@provider).to respond_to(:restartcmd) end it "should have a start method" do expect(@provider).to respond_to(:start) end it "should have a stop method" do expect(@provider).to respond_to(:stop) end it "should have an enabled? method" do expect(@provider).to respond_to(:enabled?) end it "should have an enable method" do expect(@provider).to respond_to(:enable) end it "should have a disable method" do expect(@provider).to respond_to(:disable) end describe "when checking status" do it "should call the external command 'svcs /system/myservice' once" do @provider.expects(:svcs).with('-H', '-o', 'state,nstate', "/system/myservice").returns("online\t-") @provider.status end it "should return stopped if svcs can't find the service" do @provider.stubs(:svcs).raises(Puppet::ExecutionFailure.new("no svc found")) expect(@provider.status).to eq(:stopped) end it "should return running if online in svcs output" do @provider.stubs(:svcs).returns("online\t-") expect(@provider.status).to eq(:running) end it "should return stopped if disabled in svcs output" do @provider.stubs(:svcs).returns("disabled\t-") expect(@provider.status).to eq(:stopped) end it "should return maintenance if in maintenance in svcs output" do @provider.stubs(:svcs).returns("maintenance\t-") expect(@provider.status).to eq(:maintenance) end it "should return target state if transitioning in svcs output" do @provider.stubs(:svcs).returns("online\tdisabled") expect(@provider.status).to eq(:stopped) end it "should throw error if it's a legacy service in svcs output" do @provider.stubs(:svcs).returns("legacy_run\t-") expect { @provider.status }.to raise_error(Puppet::Error, "Cannot manage legacy services through SMF") end end describe "when starting" do it "should enable the service if it is not enabled" do @provider.expects(:status).returns :stopped @provider.expects(:texecute).with(:start, ['/usr/sbin/svcadm', :enable, '-s', '/system/myservice'], true) @provider.expects(:wait).with('online') @provider.start end it "should always execute external command 'svcadm enable /system/myservice'" do @provider.expects(:status).returns :running @provider.expects(:texecute).with(:start, ['/usr/sbin/svcadm', :enable, '-s', '/system/myservice'], true) @provider.expects(:wait).with('online') @provider.start end it "should execute external command 'svcadm clear /system/myservice' if in maintenance" do @provider.stubs(:status).returns :maintenance @provider.expects(:texecute).with(:start, ["/usr/sbin/svcadm", :clear, "/system/myservice"], true) @provider.expects(:wait).with('online') @provider.start end it "should error if timeout occurs while starting the service" do @provider.expects(:status).returns :stopped @provider.expects(:texecute).with(:start, ["/usr/sbin/svcadm", :enable, "-s", "/system/myservice"], true) Timeout.expects(:timeout).with(60).raises(Timeout::Error) expect { @provider.start }.to raise_error Puppet::Error, ('Timed out waiting for /system/myservice to transition states') end end describe "when starting a service with a manifest" do before(:each) do @resource = Puppet::Type.type(:service).new(:name => "/system/myservice", :ensure => :running, :enable => :true, :manifest => "/tmp/myservice.xml") @provider = provider_class.new(@resource) $CHILD_STATUS.stubs(:exitstatus).returns(1) end it "should import the manifest if service is missing" do @provider.expects(:svccfg).with(:import, "/tmp/myservice.xml") @provider.expects(:texecute).with(:start, ["/usr/sbin/svcadm", :enable, "-s", "/system/myservice"], true) @provider.expects(:wait).with('online') @provider.expects(:svcs).with('-H', '-o', 'state,nstate', "/system/myservice").returns("online\t-") @provider.start end it "should handle failures if importing a manifest" do @provider.expects(:svccfg).raises(Puppet::ExecutionFailure.new("can't svccfg import")) expect { @provider.start }.to raise_error(Puppet::Error, "Cannot config /system/myservice to enable it: can't svccfg import") end end describe "when stopping" do it "should execute external command 'svcadm disable /system/myservice'" do @provider.expects(:texecute).with(:stop, ["/usr/sbin/svcadm", :disable, "-s", "/system/myservice"], true) @provider.expects(:wait).with('offline', 'disabled', 'uninitialized') @provider.stop end it "should error if timeout occurs while stopping the service" do @provider.expects(:texecute).with(:stop, ["/usr/sbin/svcadm", :disable, "-s", "/system/myservice"], true) Timeout.expects(:timeout).with(60).raises(Timeout::Error) expect { @provider.stop }.to raise_error Puppet::Error, ('Timed out waiting for /system/myservice to transition states') end end describe "when restarting" do it "should call 'svcadm restart /system/myservice'" do @provider.expects(:texecute).with(:restart, ["/usr/sbin/svcadm", :restart, "/system/myservice"], true) @provider.expects(:wait).with('online') @provider.restart end it "should error if timeout occurs while restarting the service" do @provider.expects(:texecute).with(:restart, ["/usr/sbin/svcadm", :restart, "/system/myservice"], true) Timeout.expects(:timeout).with(60).raises(Timeout::Error) expect { @provider.restart }.to raise_error Puppet::Error, ('Timed out waiting for /system/myservice to transition states') end end end