class Inspec::Resources::Service

TODO: extend the logic to detect the running init system, independently of OS
Ubuntu < 15.04 : upstart
Ubuntu 15.04 : systemd
RedHat 7 : systemd
Fedora 15 : systemd
system.
We detect the init system for each operating system, based on the operating

def description

returns the service description from info
def description
  return nil if info.nil?
  info[:description]
end

def enabled?(_level = nil)

verifies if the service is enabled
def enabled?(_level = nil)
  return false if info.nil?
  info[:enabled]
end

def has_start_mode?(mode)

supported only on windows.
matcher equivalent to startmode property; compares start-up mode
def has_start_mode?(mode)
  raise Inspec::Exceptions::ResourceSkipped, "The `has_start_mode` matcher is not supported on your OS yet." unless inspec.os.windows?
  mode == startmode
end

def info

def info
  return nil if @service_mgmt.nil?
  @cache ||= @service_mgmt.info(@service_name)
end

def initialize(service_name, service_ctl = nil)

def initialize(service_name, service_ctl = nil)
  @service_name = service_name
  @service_mgmt = nil
  @service_ctl ||= service_ctl
  @cache = nil
  @service_mgmt = select_service_mgmt
  return skip_resource "The `service` resource is not supported on your OS yet." if @service_mgmt.nil?
end

def installed?(_name = nil, _version = nil)

verifies the service is registered
def installed?(_name = nil, _version = nil)
  return false if info.nil?
  info[:installed]
end

def monitored_by?(monitoring_tool)

matcher to check if the service is monitored by the given monitoring tool/software
def monitored_by?(monitoring_tool)
  # Currently supported monitoring tools are: monit & god
  # To add support for new monitoring tools, extend the case statement with additional monitoring tool and
  # add the definition and logic in a new class (inheriting the base class MonitoringTool: optional)
  case monitoring_tool
  when "monit"
    current_monitoring_tool = Monit.new(inspec, @service_name)
  when "god"
    current_monitoring_tool = God.new(inspec, @service_name)
  else
    puts "The monitoring tool #{monitoring_tool} is not yet supported by InSpec."
  end
  current_monitoring_tool.is_service_monitored?
end

def name

returns the service name from info
def name
  return @service_name if info.nil?
  info[:name]
end

def params

def params
  return {} if info.nil?
  Hashie::Mash.new(info[:params] || {})
end

def resource_id

def resource_id
  @service_name || "Service"
end

def runlevels(*args)

get all runlevels that are available and their configuration
def runlevels(*args)
  return Runlevels.new(self) if info.nil? || info[:runlevels].nil?
  Runlevels.from_hash(self, info[:runlevels], args)
end

def running?(_under = nil)

verifies the service is currently running
def running?(_under = nil)
  return false if info.nil?
  info[:running]
end

def select_service_mgmt # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength

rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
def select_service_mgmt # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
  os = inspec.os
  platform = os[:name]
  return WindowsSrv.new(inspec) if os.windows?
  # Ubuntu
  # @see: https://wiki.ubuntu.com/SystemdForUpstartUsers
  # Ubuntu 15.04 : Systemd
  #   Systemd runs with PID 1 as /sbin/init.
  #   Upstart runs with PID 1 as /sbin/upstart.
  # Ubuntu < 15.04 : Upstart
  # Upstart runs with PID 1 as /sbin/init.
  # Systemd runs with PID 1 as /lib/systemd/systemd.
  case platform
  when "ubuntu"
    version = os[:release].to_f
    if version < 15.04
      Upstart.new(inspec, service_ctl)
    else
      Systemd.new(inspec, service_ctl)
    end
  when "linuxmint"
    version = os[:release].to_f
    if version < 18
      Upstart.new(inspec, service_ctl)
    else
      Systemd.new(inspec, service_ctl)
    end
  when "debian"
    if os[:release] == "buster/sid"
      version = 10
    else
      version = os[:release].to_i
    end
    if version > 7
      Systemd.new(inspec, service_ctl)
    elsif version > 0
      SysV.new(inspec, service_ctl || "/usr/sbin/service")
    end
  when "redhat", "fedora", "centos", "oracle", "cloudlinux", "scientific", "rocky", "almalinux"
    version = os[:release].to_i
    systemd = ((platform != "fedora" && version >= 7) ||
               (platform == "fedora" && version >= 15))
    if systemd
      Systemd.new(inspec, service_ctl)
    else
      SysV.new(inspec, service_ctl || "/sbin/service")
    end
  when "alibaba"
    if os[:release].to_i >= 3
      Systemd.new(inspec, service_ctl)
    else
      SysV.new(inspec, service_ctl || "/sbin/service")
    end
  when "wrlinux"
    SysV.new(inspec, service_ctl)
  when "mac_os_x", "darwin"
    LaunchCtl.new(inspec, service_ctl)
  when "freebsd"
    version = os[:release].to_f
    if version < 10
      BSDInit.new(inspec, service_ctl)
    else
      FreeBSD10Init.new(inspec, service_ctl)
    end
  when "arch"
    Systemd.new(inspec, service_ctl)
  when "coreos"
    Systemd.new(inspec, service_ctl)
  when "suse", "opensuse"
    if os[:release].to_i >= 12
      Systemd.new(inspec, service_ctl)
    else
      SysV.new(inspec, service_ctl || "/sbin/service")
    end
  when "aix"
    SrcMstr.new(inspec)
  when "amazon"
    # If `initctl` exists on the system, use `Upstart`. Else use `Systemd` since all-new Amazon Linux supports `systemctl`.
    # This way, it is not dependent on the version of Amazon Linux.
    if inspec.command("initctl").exist? || inspec.command("/sbin/initctl").exist?
      Upstart.new(inspec, service_ctl)
    else
      Systemd.new(inspec, service_ctl)
    end
  when "solaris", "smartos", "omnios", "openindiana", "opensolaris", "nexentacore"
    Svcs.new(inspec)
  when "yocto"
    Systemd.new(inspec, service_ctl)
  when "alpine"
    SysV.new(inspec, service_ctl)
  end
end

def startmode

returns the service start up mode from info
def startmode
  return nil if info.nil?
  info[:startmode]
end

def startname

returns the service's user from info
def startname
  return nil if info.nil?
  info[:startname]
end

def to_s

def to_s
  "Service #{@service_name}"
end

def type

returns the service type from info
def type
  return nil if info.nil?
  info[:type]
end