diff --git a/lib/resources/service.rb b/lib/resources/service.rb index c6b7c8c4d..72b98a4d2 100644 --- a/lib/resources/service.rb +++ b/lib/resources/service.rb @@ -250,7 +250,17 @@ module Inspec::Resources end def is_enabled?(service_name) - inspec.command("#{service_ctl} is-enabled #{service_name} --quiet").exit_status == 0 + result = inspec.command("#{service_ctl} is-enabled #{service_name} --quiet") + return true if result.exit_status == 0 + + # Some systems may not have a `.service` file for a particular service + # which causes the `systemctl is-enabled` check to fail despite the + # service being enabled. In that event we fallback to `sysv_service`. + if result.stderr =~ /Failed to get.*No such file or directory/ + return inspec.sysv_service(service_name).enabled? + end + + false end def is_active?(service_name) diff --git a/test/helper.rb b/test/helper.rb index c380778b1..5e86ec099 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -201,7 +201,10 @@ class MockLoader mock.mock_command('', '', '', 0) } - cmd_exit_1 = mock.mock_command('', '', '', 1) + cmd_exit_1 = lambda { |x = nil| + stderr = x.nil? ? '' : File.read(File.join(scriptpath, 'unit/mock/cmd', x)) + mock.mock_command('', '', stderr, 1) + } mock.commands = { '' => empty.call, @@ -234,7 +237,7 @@ class MockLoader 'dpkg -s held-package' => cmd.call('dpkg-s-held-package'), 'rpm -qia curl' => cmd.call('rpm-qia-curl'), 'rpm -qia --dbpath /var/lib/fake_rpmdb curl' => cmd.call('rpm-qia-curl'), - 'rpm -qia --dbpath /var/lib/rpmdb_does_not_exist curl' => cmd_exit_1, + 'rpm -qia --dbpath /var/lib/rpmdb_does_not_exist curl' => cmd_exit_1.call, 'pacman -Qi curl' => cmd.call('pacman-qi-curl'), 'brew info --json=v1 curl' => cmd.call('brew-info--json-v1-curl'), '/usr/local/bin/brew info --json=v1 curl' => cmd.call('brew-info--json-v1-curl'), @@ -248,7 +251,7 @@ class MockLoader "Rscript -e 'packageVersion(\"DBI\")'" => cmd.call('r-print-version'), "Rscript -e 'packageVersion(\"DoesNotExist\")'" => cmd.call('r-print-version-not-installed'), "perl -le 'eval \"require $ARGV[0]\" and print $ARGV[0]->VERSION or exit 1' DBD::Pg" => cmd.call('perl-print-version'), - "perl -le 'eval \"require $ARGV[0]\" and print $ARGV[0]->VERSION or exit 1' DOES::Not::Exist" => cmd_exit_1, + "perl -le 'eval \"require $ARGV[0]\" and print $ARGV[0]->VERSION or exit 1' DOES::Not::Exist" => cmd_exit_1.call, 'pip show jinja2' => cmd.call('pip-show-jinja2'), 'pip show django' => cmd.call('pip-show-django'), '/test/path/pip show django' => cmd.call('pip-show-non-standard-django'), @@ -281,6 +284,7 @@ class MockLoader 'initctl --version' => cmd.call('initctl--version'), # show ssh service Centos 7 'systemctl show --all sshd' => cmd.call('systemctl-show-all-sshd'), + 'systemctl show --all apache2' => cmd.call('systemctl-show-all-apache2'), '/path/to/systemctl show --all sshd' => cmd.call('systemctl-show-all-sshd'), 'systemctl show --all dbus' => cmd.call('systemctl-show-all-dbus'), '/path/to/systemctl show --all dbus' => cmd.call('systemctl-show-all-dbus'), @@ -454,13 +458,16 @@ class MockLoader "bash -c 'type \"firewall-cmd\"'" => cmd.call('firewall-cmd'), 'rpm -qia firewalld' => cmd.call('pkg-info-firewalld'), 'systemctl is-active sshd --quiet' => empty.call, + 'systemctl is-active apache2 --quiet' => empty.call, 'systemctl is-enabled sshd --quiet' => empty.call, + 'systemctl is-enabled apache2 --quiet' => cmd_exit_1.call('systemctl-is-enabled-apache2-stderr'), 'systemctl is-active dbus --quiet' => empty.call, 'systemctl is-enabled dbus --quiet' => empty.call, '/path/to/systemctl is-active sshd --quiet' => empty.call, '/path/to/systemctl is-enabled sshd --quiet' => empty.call, '/usr/sbin/service sshd status' => empty.call, '/sbin/service sshd status' => empty.call, + 'service apache2 status' => cmd_exit_1.call, 'type "lsof"' => empty.call, # http resource - remote worker' diff --git a/test/unit/mock/cmd/find-etc-rc-d-name-S b/test/unit/mock/cmd/find-etc-rc-d-name-S index 275577cb9..d4f668fe4 100644 --- a/test/unit/mock/cmd/find-etc-rc-d-name-S +++ b/test/unit/mock/cmd/find-etc-rc-d-name-S @@ -10,3 +10,7 @@ /etc/rc.d/rc4.d/S08ip6tables /etc/rc.d/rc4.d/S90crond /etc/rc.d/rc4.d/S55sshd +/etc/rc2.d/S02apache2 +/etc/rc3.d/S02apache2 +/etc/rc4.d/S02apache2 +/etc/rc5.d/S02apache2 diff --git a/test/unit/mock/cmd/ls-1-etc-init.d b/test/unit/mock/cmd/ls-1-etc-init.d index 9f3549f88..2712d0c0a 100644 --- a/test/unit/mock/cmd/ls-1-etc-init.d +++ b/test/unit/mock/cmd/ls-1-etc-init.d @@ -1,2 +1,3 @@ crond sshd +apache2 diff --git a/test/unit/mock/cmd/systemctl-is-enabled-apache2-stderr b/test/unit/mock/cmd/systemctl-is-enabled-apache2-stderr new file mode 100644 index 000000000..21fc65dd7 --- /dev/null +++ b/test/unit/mock/cmd/systemctl-is-enabled-apache2-stderr @@ -0,0 +1 @@ +Failed to get unit file state for apache2.service: No such file or directory diff --git a/test/unit/mock/cmd/systemctl-show-all-apache2 b/test/unit/mock/cmd/systemctl-show-all-apache2 new file mode 100644 index 000000000..a7f233c4b --- /dev/null +++ b/test/unit/mock/cmd/systemctl-show-all-apache2 @@ -0,0 +1,7 @@ +Id=apache2.service +Names=apache2.service +Description=LSB: Apache2 web server +LoadState=loaded +UnitFileState= +SubState=running +ActiveState=active diff --git a/test/unit/resources/service_test.rb b/test/unit/resources/service_test.rb index 51a32b7d9..b0cae0bb6 100644 --- a/test/unit/resources/service_test.rb +++ b/test/unit/resources/service_test.rb @@ -268,6 +268,27 @@ describe 'Inspec::Resources::Service' do _(resource.params).must_equal params end + # debian 8 with systemd but no service file + it 'gets the correct service info when the `.service` file is missing' do + resource = MockLoader.new(:debian8).load_resource('service', 'apache2') + params = Hashie::Mash.new( + 'ActiveState' => 'active', + 'Description' => 'LSB: Apache2 web server', + 'Id' => 'apache2.service', + 'LoadState' => 'loaded', + 'Names' => 'apache2.service', + 'SubState' => 'running', + 'UnitFileState' => '' + ) + _(resource.type).must_equal 'systemd' + _(resource.name).must_equal 'apache2.service' + _(resource.description).must_equal 'LSB: Apache2 web server' + _(resource.installed?).must_equal true + _(resource.enabled?).must_equal true + _(resource.running?).must_equal true + _(resource.params).must_equal params + end + # macos test it 'verify mac osx service parsing' do resource = MockLoader.new(:osx104).load_resource('service', 'ssh')