mirror of
https://github.com/inspec/inspec
synced 2024-09-21 15:02:01 +00:00
Merge pull request #55 from chef/unit+lint
Start Linting remaining resources
This commit is contained in:
commit
308dbef369
15 changed files with 647 additions and 488 deletions
|
@ -1,5 +1,14 @@
|
|||
#
|
||||
# Cookbook Name:: build-cookbook
|
||||
# Recipe:: default
|
||||
# Recipe:: lint
|
||||
#
|
||||
# Copyright (c) 2015 The Authors, All Rights Reserved.
|
||||
# Copyright (c) 2015 Chef Software Inc., All Rights Reserved.
|
||||
# Author:: Dominik Richter
|
||||
|
||||
include_recipe 'build-cookbook::prepare'
|
||||
|
||||
execute 'rubocop' do
|
||||
command 'bundle exec rubocop -D'
|
||||
cwd node['delivery_builder']['repo']
|
||||
user node['delivery_builder']['build_user']
|
||||
end
|
||||
|
|
21
.delivery/build-cookbook/recipes/prepare.rb
Normal file
21
.delivery/build-cookbook/recipes/prepare.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
#
|
||||
# Cookbook Name:: build-cookbook
|
||||
# Recipe:: prepare
|
||||
#
|
||||
# Copyright (c) 2015 Chef Software Inc., All Rights Reserved.
|
||||
# Author:: Dominik Richter
|
||||
|
||||
repo_dir = node['delivery_builder']['repo']
|
||||
cache_dir = File.join(repo_dir, '.cache')
|
||||
|
||||
directory cache_dir do
|
||||
owner node['delivery_builder']['build_user']
|
||||
mode '0755'
|
||||
end
|
||||
|
||||
execute 'bundle install' do
|
||||
command 'bundle install --without=integration --without=tools --path='+cache_dir
|
||||
cwd repo_dir
|
||||
user node['delivery_builder']['build_user']
|
||||
end
|
||||
|
|
@ -1,5 +1,14 @@
|
|||
#
|
||||
# Cookbook Name:: build-cookbook
|
||||
# Recipe:: default
|
||||
# Recipe:: unit
|
||||
#
|
||||
# Copyright (c) 2015 The Authors, All Rights Reserved.
|
||||
# Copyright (c) 2015 Chef Software Inc., All Rights Reserved.
|
||||
# Author:: Dominik Richter
|
||||
|
||||
include_recipe 'build-cookbook::prepare'
|
||||
|
||||
execute 'rake test' do
|
||||
command 'bundle exec rake'
|
||||
cwd node['delivery_builder']['repo']
|
||||
user node['delivery_builder']['build_user']
|
||||
end
|
||||
|
|
|
@ -5,8 +5,11 @@
|
|||
"path": ".delivery/build-cookbook"
|
||||
},
|
||||
"skip_phases": [
|
||||
"syntax",
|
||||
"security",
|
||||
"quality",
|
||||
"smoke",
|
||||
"quality"
|
||||
"deploy"
|
||||
],
|
||||
"build_nodes": {}
|
||||
}
|
||||
|
|
|
@ -2,22 +2,21 @@
|
|||
# copyright: 2015, Vulcano Security GmbH
|
||||
# license: All rights reserved
|
||||
|
||||
$__SCOPE = self
|
||||
|
||||
class MysqlSession < Vulcano.resource(1)
|
||||
name 'mysql_session'
|
||||
|
||||
def initialize(user, pass)
|
||||
@user = user
|
||||
@pass = pass
|
||||
initialize_fallback if user.nil? or pass.nil?
|
||||
init_fallback if user.nil? or pass.nil?
|
||||
skip_resource("Can't run MySQL SQL checks without authentication") if @user.nil? or @pass.nil?
|
||||
end
|
||||
|
||||
def describe(query, db = '', &block)
|
||||
def query(q, db = '')
|
||||
# TODO: simple escape, must be handled by a library
|
||||
# that does this securely
|
||||
escaped_query = query.gsub(/\\/, '\\\\').gsub(/"/, '\\"').gsub(/\$/, '\\$')
|
||||
escaped_query = q.gsub(/\\/, '\\\\').gsub(/"/, '\\"').gsub(/\$/, '\\$')
|
||||
|
||||
# run the query
|
||||
cmd = vulcano.run_command("mysql -u#{@user} -p#{@pass} #{db} -s -e \"#{escaped_query}\"")
|
||||
out = cmd.stdout + "\n" + cmd.stderr
|
||||
|
@ -25,14 +24,15 @@ class MysqlSession < Vulcano.resource(1)
|
|||
out.downcase =~ /^error/
|
||||
# skip this test if the server can't run the query
|
||||
skip_resource("Can't connect to MySQL instance for SQL checks.")
|
||||
else
|
||||
$__SCOPE.describe(cmd, &block)
|
||||
end
|
||||
|
||||
# return the raw command output
|
||||
cmd
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def initialize_fallback
|
||||
def init_fallback
|
||||
# support debian mysql administration login
|
||||
debian = vulcano.run_command('test -f /etc/mysql/debian.cnf && cat /etc/mysql/debian.cnf').stdout
|
||||
return if debian.empty?
|
||||
|
|
|
@ -158,54 +158,61 @@ class LinuxPorts < PortsInfo
|
|||
return nil if cmd.exit_status.to_i != 0
|
||||
|
||||
ports = []
|
||||
# split on each newline
|
||||
# parse all lines
|
||||
cmd.stdout.each_line do |line|
|
||||
# parse each line
|
||||
# 1 - Proto, 2 - Recv-Q, 3 - Send-Q, 4 - Local Address, 5 - Foreign Address, 6 - State, 7 - Inode, 8 - PID/Program name
|
||||
parsed = /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)$/.match(line)
|
||||
port_info = parse_netstat_line(line)
|
||||
|
||||
if !parsed.nil?
|
||||
protocol = parsed[1].downcase
|
||||
|
||||
# parse ip4 and ip6 addresses
|
||||
net_addr = parsed[4]
|
||||
if protocol.eql?('tcp6') || protocol.eql?('udp6')
|
||||
# prep for URI parsing, parse ip6 port
|
||||
ip6 = /^(\S+:)(\d+)$/.match(net_addr)
|
||||
ip6addr = ip6[1]
|
||||
ip6addr = '::' if /^:::$/.match(ip6addr)
|
||||
# build uri
|
||||
ip_addr = URI('addr://[' + ip6addr +']:' + ip6[2])
|
||||
# replace []
|
||||
host = ip_addr.host[1..ip_addr.host.size-2]
|
||||
port = ip_addr.port
|
||||
else
|
||||
ip_addr = URI('addr://'+net_addr)
|
||||
host = ip_addr.host
|
||||
port = ip_addr.port
|
||||
end
|
||||
|
||||
# extract PID
|
||||
process = parsed[9].split('/')
|
||||
pid = process[0]
|
||||
pid = pid.to_i if /^\d+$/.match(pid)
|
||||
process = process[1]
|
||||
|
||||
# map data
|
||||
port_info = {
|
||||
port: port,
|
||||
address: host,
|
||||
protocol: protocol,
|
||||
process: process,
|
||||
pid: pid,
|
||||
}
|
||||
|
||||
# push data, if its a known protocol tcp, tcp6, udp, udp6
|
||||
ports.push(port_info) if %w{tcp tcp6 udp udp6}.include?(protocol)
|
||||
end
|
||||
# only push protocols we are interested in
|
||||
next unless %w{tcp tcp6 udp udp6}.include?(port_info[:protocol])
|
||||
ports.push(port_info)
|
||||
end
|
||||
ports
|
||||
end
|
||||
|
||||
def parse_net_address(net_addr, protocol)
|
||||
if protocol.eql?('tcp6') || protocol.eql?('udp6')
|
||||
# prep for URI parsing, parse ip6 port
|
||||
ip6 = /^(\S+:)(\d+)$/.match(net_addr)
|
||||
ip6addr = ip6[1]
|
||||
ip6addr = '::' if /^:::$/.match(ip6addr)
|
||||
# build uri
|
||||
ip_addr = URI('addr://[' + ip6addr +']:' + ip6[2])
|
||||
# replace []
|
||||
host = ip_addr.host[1..ip_addr.host.size-2]
|
||||
port = ip_addr.port
|
||||
else
|
||||
ip_addr = URI('addr://'+net_addr)
|
||||
host = ip_addr.host
|
||||
port = ip_addr.port
|
||||
end
|
||||
[host, port]
|
||||
end
|
||||
|
||||
def parse_netstat_line(line)
|
||||
# parse each line
|
||||
# 1 - Proto, 2 - Recv-Q, 3 - Send-Q, 4 - Local Address, 5 - Foreign Address, 6 - State, 7 - Inode, 8 - PID/Program name
|
||||
parsed = /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)$/.match(line)
|
||||
return {} if parsed.nil?
|
||||
|
||||
# parse ip4 and ip6 addresses
|
||||
protocol = parsed[1].downcase
|
||||
host, port = parse_net_address(parsed[4], protocol)
|
||||
|
||||
# extract PID
|
||||
process = parsed[9].split('/')
|
||||
pid = process[0]
|
||||
pid = pid.to_i if /^\d+$/.match(pid)
|
||||
process = process[1]
|
||||
|
||||
# map data
|
||||
{
|
||||
port: port,
|
||||
address: host,
|
||||
protocol: protocol,
|
||||
process: process,
|
||||
pid: pid,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
# extracts information from sockstat
|
||||
|
@ -217,58 +224,66 @@ class FreeBsdPorts < PortsInfo
|
|||
ports = []
|
||||
# split on each newline
|
||||
cmd.stdout.each_line do |line|
|
||||
# 1 - USER, 2 - COMMAND, 3 - PID, 4 - FD 5 - PROTO, 6 - LOCAL ADDRESS, 7 - FOREIGN ADDRESS
|
||||
parsed = /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)$/.match(line)
|
||||
port_info = parse_sockstat_line(line)
|
||||
|
||||
if !parsed.nil?
|
||||
protocol = parsed[5].downcase
|
||||
net_addr = parsed[6]
|
||||
|
||||
# extract ip information
|
||||
case protocol
|
||||
when 'tcp4', 'udp4'
|
||||
# replace * with 0.0.0.0
|
||||
net_addr = net_addr.gsub(/^\*:/, '0.0.0.0:') if /^*:(\d+)$/.match(net_addr)
|
||||
ip_addr = URI('addr://'+net_addr)
|
||||
host = ip_addr.host
|
||||
port = ip_addr.port
|
||||
when 'tcp6', 'udp6'
|
||||
next if net_addr == '*:*' # abort for now
|
||||
# replace * with 0:0:0:0:0:0:0:0
|
||||
net_addr = net_addr.gsub(/^\*:/, '0:0:0:0:0:0:0:0:') if /^*:(\d+)$/.match(net_addr)
|
||||
# extract port
|
||||
ip6 = /^(\S+):(\d+)$/.match(net_addr)
|
||||
ip6addr = ip6[1]
|
||||
ip_addr = URI('addr://[' + ip6addr +']:' + ip6[2])
|
||||
# replace []
|
||||
host = ip_addr.host[1..ip_addr.host.size-2]
|
||||
port = ip_addr.port
|
||||
end
|
||||
|
||||
# extract process
|
||||
process = parsed[2]
|
||||
|
||||
# extract PID
|
||||
pid = parsed[3]
|
||||
pid = pid.to_i if /^\d+$/.match(pid)
|
||||
|
||||
# map tcp4 and udp4
|
||||
protocol = 'tcp' if protocol.eql?('tcp4')
|
||||
protocol = 'udp' if protocol.eql?('udp4')
|
||||
|
||||
# map data
|
||||
port_info = {
|
||||
port: port,
|
||||
address: host,
|
||||
protocol: protocol,
|
||||
process: process,
|
||||
pid: pid,
|
||||
}
|
||||
|
||||
# push data, if not headerfile
|
||||
ports.push(port_info) if %w{tcp tcp6 udp udp6}.include?(protocol)
|
||||
end
|
||||
# push data, if not headerfile
|
||||
next unless %w{tcp tcp6 udp udp6}.include?(port_info[:protocol])
|
||||
ports.push(port_info)
|
||||
end
|
||||
ports
|
||||
end
|
||||
|
||||
def parse_net_address(net_addr, protocol)
|
||||
case protocol
|
||||
when 'tcp4', 'udp4'
|
||||
# replace * with 0.0.0.0
|
||||
net_addr = net_addr.gsub(/^\*:/, '0.0.0.0:') if /^*:(\d+)$/.match(net_addr)
|
||||
ip_addr = URI('addr://'+net_addr)
|
||||
host = ip_addr.host
|
||||
port = ip_addr.port
|
||||
when 'tcp6', 'udp6'
|
||||
return [] if net_addr == '*:*' # abort for now
|
||||
# replace * with 0:0:0:0:0:0:0:0
|
||||
net_addr = net_addr.gsub(/^\*:/, '0:0:0:0:0:0:0:0:') if /^*:(\d+)$/.match(net_addr)
|
||||
# extract port
|
||||
ip6 = /^(\S+):(\d+)$/.match(net_addr)
|
||||
ip6addr = ip6[1]
|
||||
ip_addr = URI('addr://[' + ip6addr +']:' + ip6[2])
|
||||
# replace []
|
||||
host = ip_addr.host[1..ip_addr.host.size-2]
|
||||
port = ip_addr.port
|
||||
end
|
||||
[host, port]
|
||||
end
|
||||
|
||||
def parse_sockstat_line(line)
|
||||
# 1 - USER, 2 - COMMAND, 3 - PID, 4 - FD 5 - PROTO, 6 - LOCAL ADDRESS, 7 - FOREIGN ADDRESS
|
||||
parsed = /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)$/.match(line)
|
||||
return {} if parsed.nil?
|
||||
|
||||
# extract ip information
|
||||
protocol = parsed[5].downcase
|
||||
host, port = parse_net_address(parsed[6], protocol)
|
||||
return {} if host.nil? or port.nil?
|
||||
|
||||
# extract process
|
||||
process = parsed[2]
|
||||
|
||||
# extract PID
|
||||
pid = parsed[3]
|
||||
pid = pid.to_i if /^\d+$/.match(pid)
|
||||
|
||||
# map tcp4 and udp4
|
||||
protocol = 'tcp' if protocol.eql?('tcp4')
|
||||
protocol = 'udp' if protocol.eql?('udp4')
|
||||
|
||||
# map data
|
||||
{
|
||||
port: port,
|
||||
address: host,
|
||||
protocol: protocol,
|
||||
process: process,
|
||||
pid: pid,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,12 +22,14 @@ class Service < Vulcano.resource(1)
|
|||
|
||||
def initialize(service_name)
|
||||
@service_name = service_name
|
||||
|
||||
# select package manager
|
||||
@service_mgmt = nil
|
||||
@cache = nil
|
||||
select_package_manager
|
||||
end
|
||||
|
||||
def select_package_manager # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
||||
family = vulcano.os[:family]
|
||||
|
||||
case family
|
||||
# Ubuntu
|
||||
# @see: https://wiki.ubuntu.com/SystemdForUpstartUsers
|
||||
|
@ -309,8 +311,7 @@ class WindowsSrv < ServiceManager
|
|||
# - 6: Pause Pending
|
||||
# - 7: Paused
|
||||
def info(service_name)
|
||||
srv_cmd = "New-Object -Type PSObject | Add-Member -MemberType NoteProperty -Name Service -Value (Get-Service -Name #{service_name}| Select-Object -Property Name, DisplayName, Status) -PassThru | Add-Member -MemberType NoteProperty -Name WMI -Value (Get-WmiObject -Class Win32_Service | Where-Object {$_.Name -eq '#{service_name}' -or $_.DisplayName -eq '#{service_name}'} | Select-Object -Property StartMode) -PassThru | ConvertTo-Json"
|
||||
cmd = @vulcano.run_command(srv_cmd)
|
||||
cmd = @vulcano.run_command("New-Object -Type PSObject | Add-Member -MemberType NoteProperty -Name Service -Value (Get-Service -Name #{service_name}| Select-Object -Property Name, DisplayName, Status) -PassThru | Add-Member -MemberType NoteProperty -Name WMI -Value (Get-WmiObject -Class Win32_Service | Where-Object {$_.Name -eq '#{service_name}' -or $_.DisplayName -eq '#{service_name}'} | Select-Object -Property StartMode) -PassThru | ConvertTo-Json")
|
||||
|
||||
# cannot rely on exit code for now, successful command returns exit code 1
|
||||
# return nil if cmd.exit_status != 0
|
||||
|
@ -324,27 +325,36 @@ class WindowsSrv < ServiceManager
|
|||
# check that we got a response
|
||||
return nil if service.nil? || service['Service'].nil?
|
||||
|
||||
# detect if service is running
|
||||
if !service['Service']['Status'].nil? && service['Service']['Status'] == 4
|
||||
running = true
|
||||
else
|
||||
running = false
|
||||
end
|
||||
|
||||
# detect if service is enabled
|
||||
if !service['WMI'].nil? && !service['WMI']['StartMode'].nil? && service['WMI']['StartMode'] == 'Auto'
|
||||
enabled = true
|
||||
else
|
||||
enabled = false
|
||||
end
|
||||
|
||||
{
|
||||
name: service['Service']['Name'],
|
||||
description: service['Service']['DisplayName'],
|
||||
installed: true,
|
||||
running: running,
|
||||
enabled: enabled,
|
||||
running: service_running?(service),
|
||||
enabled: service_enabled?(service),
|
||||
type: 'windows',
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# detect if service is enabled
|
||||
def service_enabled?(service)
|
||||
if !service['WMI'].nil? &&
|
||||
!service['WMI']['StartMode'].nil? &&
|
||||
service['WMI']['StartMode'] == 'Auto'
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
# detect if service is running
|
||||
def service_running?(service)
|
||||
if !service['Service']['Status'].nil? &&
|
||||
service['Service']['Status'] == 4
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,12 +14,4 @@ require 'vulcano/resource'
|
|||
require 'vulcano/rspec_json_formatter'
|
||||
require 'vulcano/rule'
|
||||
require 'vulcano/runner'
|
||||
|
||||
require 'matchers/matchers'
|
||||
|
||||
# Dummy module for handling additional attributes
|
||||
# which may be injected by the user. This covers data
|
||||
# like passwords, usernames, or configuration flags.
|
||||
def attributes(what, required: false)
|
||||
nil
|
||||
end
|
||||
|
|
30
lib/vulcano/plugins/backend_detect_darwin.rb
Normal file
30
lib/vulcano/plugins/backend_detect_darwin.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
# encoding: utf-8
|
||||
#
|
||||
# This is heavily based on:
|
||||
#
|
||||
# OHAI https://github.com/chef/ohai
|
||||
# by Adam Jacob, Chef Software Inc
|
||||
#
|
||||
|
||||
class Vulcano::Plugins::Backend
|
||||
module DetectDarwin
|
||||
def detect_darwin
|
||||
cmd = @backend.run_command('/usr/bin/sw_vers')
|
||||
# TODO: print an error in this step of the detection,
|
||||
# as it shouldnt happen
|
||||
return false if cmd.exit_status != 0
|
||||
# TODO: ditto on error
|
||||
return false if cmd.stdout.empty?
|
||||
|
||||
name = cmd.stdout[/^ProductName:\s+(.+)$/, 1]
|
||||
# TODO: ditto on error
|
||||
return false if name.nil?
|
||||
@platform[:name] = name.downcase.chomp.tr(' ', '_')
|
||||
@platform[:release] = cmd.stdout[/^ProductVersion:\s+(.+)$/, 1]
|
||||
@platform[:build] = cmd.stdout[/^BuildVersion:\s+(.+)$/, 1]
|
||||
# TODO: keep for now due to backwards compatibility with serverspec
|
||||
@platform[:family] = 'darwin'
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
116
lib/vulcano/plugins/backend_detect_linux.rb
Normal file
116
lib/vulcano/plugins/backend_detect_linux.rb
Normal file
|
@ -0,0 +1,116 @@
|
|||
# encoding: utf-8
|
||||
#
|
||||
# This is heavily based on:
|
||||
#
|
||||
# OHAI https://github.com/chef/ohai
|
||||
# by Adam Jacob, Chef Software Inc
|
||||
#
|
||||
|
||||
require 'vulcano/plugins/backend_linux_lsb'
|
||||
|
||||
class Vulcano::Plugins::Backend
|
||||
module DetectLinux
|
||||
include LinuxLSB
|
||||
|
||||
def detect_linux_via_config # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
||||
if !(raw = get_config('oracle-release')).nil?
|
||||
@platform[:family] = 'oracle'
|
||||
@platform[:release] = redhatish_version(raw)
|
||||
elsif !(raw = get_config('/etc/enterprise-release')).nil?
|
||||
@platform[:family] = 'oracle'
|
||||
@platform[:release] = redhatish_version(raw)
|
||||
elsif !(_raw = get_config('/etc/debian_version')).nil?
|
||||
case lsb[:id]
|
||||
when /ubuntu/i
|
||||
@platform[:family] = 'ubuntu'
|
||||
@platform[:release] = lsb[:release]
|
||||
when /linuxmint/i
|
||||
@platform[:family] = 'linuxmint'
|
||||
@platform[:release] = lsb[:release]
|
||||
else
|
||||
@platform[:family] = 'debian'
|
||||
@platform[:family] = 'raspbian' if unix_file?('/usr/bin/raspi-config')
|
||||
if !(rel = get_config('/etc/debian_version')).nil?
|
||||
@platform[:release] = rel.chomp
|
||||
end
|
||||
end
|
||||
elsif !(raw = get_config('/etc/parallels-release')).nil?
|
||||
@platform[:family] = redhatish_platform(raw)
|
||||
@platform[:release] = raw[/(\d\.\d\.\d)/, 1]
|
||||
elsif !(raw = get_config('/etc/redhat-release')).nil?
|
||||
# TODO: Cisco
|
||||
@platform[:family] = redhatish_platform(raw)
|
||||
@platform[:release] = redhatish_version(raw)
|
||||
elsif !(raw = get_config('/etc/system-release')).nil?
|
||||
# Amazon Linux
|
||||
@platform[:family] = redhatish_platform(raw)
|
||||
@platform[:release] = redhatish_version(raw)
|
||||
elsif !(suse = get_config('/etc/SuSE-release')).nil?
|
||||
version = suse.scan(/VERSION = (\d+)\nPATCHLEVEL = (\d+)/).flatten.join('.')
|
||||
version = suse[/VERSION = ([\d\.]{2,})/, 1] if version == ''
|
||||
@platform[:release] = version
|
||||
@platform[:family] = 'suse'
|
||||
@platform[:family] = 'opensuse' if suse =~ /^openSUSE/
|
||||
elsif !(raw = get_config('/etc/arch-release')).nil?
|
||||
@platform[:family] = 'arch'
|
||||
# Because this is a rolling release distribution,
|
||||
# use the kernel release, ex. 4.1.6-1-ARCH
|
||||
@platform[:release] = uname_r
|
||||
elsif !(raw = get_config('/etc/slackware-version')).nil?
|
||||
@platform[:family] = 'slackware'
|
||||
@platform[:release] = raw.scan(/(\d+|\.+)/).join
|
||||
elsif !(raw = get_config('/etc/exherbo-release')).nil?
|
||||
@platform[:family] = 'exherbo'
|
||||
# Because this is a rolling release distribution,
|
||||
# use the kernel release, ex. 4.1.6
|
||||
@platform[:release] = uname_r
|
||||
elsif !(raw = get_config('/etc/gentoo-release')).nil?
|
||||
@platform[:family] = 'gentoo'
|
||||
@platform[:release] = raw.scan(/(\d+|\.+)/).join
|
||||
elsif !(raw = get_config('/etc/alpine-release')).nil?
|
||||
@platform[:family] = 'alpine'
|
||||
@platform[:release] = raw.strip
|
||||
elsif !(raw = get_config('/etc/coreos/update.conf')).nil?
|
||||
@platform[:family] = 'coreos'
|
||||
meta = lsb_config(raw)
|
||||
@platform[:release] = meta[:release]
|
||||
else
|
||||
# in all other cases we didn't detect it
|
||||
return false
|
||||
end
|
||||
# when we get here the detection returned a result
|
||||
true
|
||||
end
|
||||
|
||||
def uname_s
|
||||
@uname_s ||= @backend.run_command('uname -s').stdout
|
||||
end
|
||||
|
||||
def uname_r
|
||||
@uname_r ||= (
|
||||
res = @backend.run_command('uname -r').stdout
|
||||
res.strip! unless res.nil?
|
||||
res
|
||||
)
|
||||
end
|
||||
|
||||
def redhatish_platform(conf)
|
||||
conf[/^red hat/i] ? 'redhat' : conf[/(\w+)/i, 1].downcase
|
||||
end
|
||||
|
||||
def redhatish_version(conf)
|
||||
conf[/rawhide/i] ? conf[/((\d+) \(Rawhide\))/i, 1].downcase : conf[/release ([\d\.]+)/, 1]
|
||||
end
|
||||
|
||||
def detect_linux
|
||||
# TODO: print an error in this step of the detection
|
||||
return false if uname_s.nil? || uname_s.empty?
|
||||
return false if uname_r.nil? || uname_r.empty?
|
||||
|
||||
return true if detect_linux_via_config
|
||||
return true if detect_linux_via_lsb
|
||||
# in all other cases we failed the detection
|
||||
@platform[:family] = 'unknown'
|
||||
end
|
||||
end
|
||||
end
|
75
lib/vulcano/plugins/backend_detect_unix.rb
Normal file
75
lib/vulcano/plugins/backend_detect_unix.rb
Normal file
|
@ -0,0 +1,75 @@
|
|||
# encoding: utf-8
|
||||
#
|
||||
# This is heavily based on:
|
||||
#
|
||||
# OHAI https://github.com/chef/ohai
|
||||
# by Adam Jacob, Chef Software Inc
|
||||
#
|
||||
|
||||
class Vulcano::Plugins::Backend
|
||||
module DetectUnix
|
||||
def detect_via_uname # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
||||
case uname_s.downcase
|
||||
when /aix/
|
||||
@platform[:family] = 'aix'
|
||||
out = @backend.run_command('uname -rvp').stdout
|
||||
m = out.match(/(\d+)\s+(\d+)\s+(.*)/)
|
||||
unless m.nil?
|
||||
@platform[:release] = "#{m[2]}.#{m[1]}"
|
||||
@platform[:arch] = m[3].to_s
|
||||
end
|
||||
|
||||
when /freebsd/
|
||||
@platform[:family] = 'freebsd'
|
||||
@platform[:name] = uname_s.lines[0].chomp
|
||||
@platform[:release] = uname_r.lines[0].chomp
|
||||
|
||||
when /netbsd/
|
||||
@platform[:family] = 'netbsd'
|
||||
@platform[:name] = uname_s.lines[0].chomp
|
||||
@platform[:release] = uname_r.lines[0].chomp
|
||||
|
||||
when /openbsd/
|
||||
@platform[:family] = 'openbsd'
|
||||
@platform[:name] = uname_s.lines[0].chomp
|
||||
@platform[:release] = uname_r.lines[0].chomp
|
||||
|
||||
when /sunos/
|
||||
@platform[:family] = 'solaris'
|
||||
if uname_r =~ /5\.10/
|
||||
# TODO: should be string!
|
||||
@platform[:release] = 10
|
||||
else
|
||||
rel = get_config('/etc/release')
|
||||
case rel
|
||||
when /^.*(SmartOS).*$/
|
||||
@platform[:family] = 'smartos'
|
||||
when !(m = /^\s*(OmniOS).*r(\d+).*$/).nil?
|
||||
@platform[:family] = 'omnios'
|
||||
@platform[:release] = m[2]
|
||||
when !(m = /^\s*(OpenIndiana).*oi_(\d+).*$/).nil?
|
||||
@platform[:family] = 'openindiana'
|
||||
@platform[:release] = m[2]
|
||||
when /^\s*(OpenSolaris).*snv_(\d+).*$/
|
||||
@platform[:family] = 'opensolaris'
|
||||
@platform[:release] = m[2]
|
||||
when !(m = /Oracle Solaris (\d+)/).nil?
|
||||
# TODO: should be string!
|
||||
@platform[:release] = m[1].to_i
|
||||
@platform[:family] = 'solaris2'
|
||||
when /^\s*(Solaris)\s.*$/
|
||||
@platform[:family] = 'solaris2'
|
||||
when /^\s*(NexentaCore)\s.*$/
|
||||
@platform[:family] = 'nexentacore'
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
# in all other cases we didn't detect it
|
||||
return false
|
||||
end
|
||||
# when we get here the detection returned a result
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
70
lib/vulcano/plugins/backend_detect_windows.rb
Normal file
70
lib/vulcano/plugins/backend_detect_windows.rb
Normal file
|
@ -0,0 +1,70 @@
|
|||
# encoding: utf-8
|
||||
#
|
||||
# This is heavily based on:
|
||||
#
|
||||
# OHAI https://github.com/chef/ohai
|
||||
# by Adam Jacob, Chef Software Inc
|
||||
#
|
||||
|
||||
class Vulcano::Plugins::Backend
|
||||
module DetectWindows
|
||||
# See: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724832%28v=vs.85%29.aspx
|
||||
# Product Type:
|
||||
# Work Station (1)
|
||||
# Domain Controller (2)
|
||||
# Server (3)
|
||||
WINDOWS_VERSIONS = {
|
||||
'0' => '3.1',
|
||||
'140' => '95',
|
||||
'1410' => '98',
|
||||
'1490' => 'ME',
|
||||
'1351' => 'NT 3.51',
|
||||
'3351' => 'NT 3.51 Server',
|
||||
'1240' => 'NT 4.0',
|
||||
'3240' => 'NT 4.0 Server',
|
||||
'1250' => '2000',
|
||||
'1251' => 'XP',
|
||||
'3252' => 'Server 2003',
|
||||
'1252' => 'Vista',
|
||||
'3260' => 'Server 2008',
|
||||
'1261' => '7',
|
||||
'3261' => 'Server 2008 R2',
|
||||
'1262' => '8',
|
||||
'3262' => 'Server 2012',
|
||||
'1263' => '8.1',
|
||||
'3263' => 'Server 2012 R2',
|
||||
'12100' => '10',
|
||||
'32100' => 'Server 2016',
|
||||
}
|
||||
|
||||
def windows_version(json)
|
||||
producttype = json['OS']['ProductType'].to_s
|
||||
# do not distigush between domain controller and server
|
||||
producttype = '3' if producttype == '2'
|
||||
platform = json['OSVersion']['Platform'].to_s
|
||||
major = json['OSVersion']['Version']['Major'].to_s
|
||||
minor = json['OSVersion']['Version']['Minor'].to_s
|
||||
# construct it
|
||||
producttype + platform + major + minor
|
||||
end
|
||||
|
||||
def detect_windows
|
||||
cmd = 'New-Object -Type PSObject | Add-Member -MemberType NoteProperty '\
|
||||
'-Name OS -Value (Get-WmiObject -Class Win32_OperatingSystem) '\
|
||||
'-PassThru | Add-Member -MemberType NoteProperty -Name OSVersion '\
|
||||
'-Value ([Environment]::OSVersion) -PassThru | ConvertTo-Json'
|
||||
res = @backend.run_command(cmd)
|
||||
# TODO: error as this shouldnt be happening at this point
|
||||
return false if res.exit_status != 0 or res.stdout.empty?
|
||||
|
||||
json = JSON.parse(res.stdout)
|
||||
return false if json.nil? or json.empty?
|
||||
version = windows_version(json)
|
||||
|
||||
@platform[:family] = 'windows'
|
||||
@platform[:name] = WINDOWS_VERSIONS[version]
|
||||
@platform[:release] = version
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
58
lib/vulcano/plugins/backend_linux_lsb.rb
Normal file
58
lib/vulcano/plugins/backend_linux_lsb.rb
Normal file
|
@ -0,0 +1,58 @@
|
|||
# encoding: utf-8
|
||||
#
|
||||
# This is heavily based on:
|
||||
#
|
||||
# OHAI https://github.com/chef/ohai
|
||||
# by Adam Jacob, Chef Software Inc
|
||||
#
|
||||
|
||||
class Vulcano::Plugins::Backend
|
||||
module LinuxLSB
|
||||
def lsb_config(content)
|
||||
{
|
||||
id: content[/^DISTRIB_ID=["']?(.+?)["']?$/, 1],
|
||||
release: content[/^DISTRIB_RELEASE=["']?(.+?)["']?$/, 1],
|
||||
codename: content[/^DISTRIB_CODENAME=["']?(.+?)["']?$/, 1],
|
||||
}
|
||||
end
|
||||
|
||||
def lsb_release
|
||||
raw = @backend.run_command('lsb_release -a').stdout
|
||||
{
|
||||
id: raw[/^Distributor ID:\s+(.+)$/, 1],
|
||||
release: raw[/^Release:\s+(.+)$/, 1],
|
||||
codename: raw[/^Codename:\s+(.+)$/, 1],
|
||||
}
|
||||
end
|
||||
|
||||
def lsb
|
||||
return @lsb unless @lsb.nil?
|
||||
@lsb = {}
|
||||
if !(raw = get_config('/etc/lsb-release')).nil?
|
||||
@lsb = lsb_config(raw)
|
||||
elsif unix_file?('/usr/bin/lsb_release')
|
||||
@lsb = lsb_release
|
||||
end
|
||||
@lsb
|
||||
end
|
||||
|
||||
def detect_linux_via_lsb
|
||||
return false if lsb[:id].nil?
|
||||
id = lsb[:id].downcase
|
||||
case id
|
||||
when /redhat/
|
||||
@platform[:family] = 'redhat'
|
||||
when /amazon/
|
||||
@platform[:family] = 'amazon'
|
||||
when /scientificsl/
|
||||
@platform[:family] = 'scientific'
|
||||
when /xenserver/
|
||||
@platform[:family] = 'xenserver'
|
||||
else
|
||||
@platform[:family] = id
|
||||
end
|
||||
@platform[:release] = lsb[:release]
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
|
@ -6,8 +6,18 @@
|
|||
# by Adam Jacob, Chef Software Inc
|
||||
#
|
||||
|
||||
require 'vulcano/plugins/backend_detect_darwin'
|
||||
require 'vulcano/plugins/backend_detect_linux'
|
||||
require 'vulcano/plugins/backend_detect_unix'
|
||||
require 'vulcano/plugins/backend_detect_windows'
|
||||
|
||||
class Vulcano::Plugins::Backend
|
||||
class OSCommon
|
||||
include DetectDarwin
|
||||
include DetectLinux
|
||||
include DetectUnix
|
||||
include DetectWindows
|
||||
|
||||
def initialize(backend, platform = nil)
|
||||
@backend = backend
|
||||
@platform = platform || {}
|
||||
|
@ -53,7 +63,6 @@ class Vulcano::Plugins::Backend
|
|||
pf = @platform[:family]
|
||||
|
||||
return detect_windos if pf == 'windows'
|
||||
|
||||
return detect_darwin if pf == 'darwin'
|
||||
|
||||
if %w{freebsd netbsd openbsd aix solaris2}.include?(pf)
|
||||
|
@ -63,263 +72,10 @@ class Vulcano::Plugins::Backend
|
|||
# unix based systems combine the above
|
||||
return true if pf == 'unix' and (detect_darwin or detect_via_uname)
|
||||
|
||||
# if we arrive here, we most likey have a regular linux
|
||||
detect_linux
|
||||
end
|
||||
|
||||
# See: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724832%28v=vs.85%29.aspx
|
||||
# Product Type:
|
||||
# Work Station (1)
|
||||
# Domain Controller (2)
|
||||
# Server (3)
|
||||
WindowsVersions = {
|
||||
'0' => '3.1',
|
||||
'140' => '95',
|
||||
'1410' => '98',
|
||||
'1490' => 'ME',
|
||||
'1351' => 'NT 3.51',
|
||||
'3351' => 'NT 3.51 Server',
|
||||
'1240' => 'NT 4.0',
|
||||
'3240' => 'NT 4.0 Server',
|
||||
'1250' => '2000',
|
||||
'1251' => 'XP',
|
||||
'3252' => 'Server 2003',
|
||||
'1252' => 'Vista',
|
||||
'3260' => 'Server 2008',
|
||||
'1261' => '7',
|
||||
'3261' => 'Server 2008 R2',
|
||||
'1262' => '8',
|
||||
'3262' => 'Server 2012',
|
||||
'1263' => '8.1',
|
||||
'3263' => 'Server 2012 R2',
|
||||
'12100' => '10',
|
||||
'32100' => 'Server 2016',
|
||||
}
|
||||
|
||||
def windows_version(json)
|
||||
producttype = json['OS']['ProductType'].to_s
|
||||
# do not distigush between domain controller and server
|
||||
producttype = '3' if producttype == '2'
|
||||
platform = json['OSVersion']['Platform'].to_s
|
||||
major = json['OSVersion']['Version']['Major'].to_s
|
||||
minor = json['OSVersion']['Version']['Minor'].to_s
|
||||
# construct it
|
||||
producttype + platform + major + minor
|
||||
end
|
||||
|
||||
def detect_windows
|
||||
cmd = 'New-Object -Type PSObject | Add-Member -MemberType NoteProperty '\
|
||||
'-Name OS -Value (Get-WmiObject -Class Win32_OperatingSystem) '\
|
||||
'-PassThru | Add-Member -MemberType NoteProperty -Name OSVersion '\
|
||||
'-Value ([Environment]::OSVersion) -PassThru | ConvertTo-Json'
|
||||
res = @backend.run_command(cmd)
|
||||
# TODO: error as this shouldnt be happening at this point
|
||||
return false if res.exit_status != 0 or res.stdout.empty?
|
||||
|
||||
json = JSON.parse(res.stdout)
|
||||
return false if json.nil? or json.empty?
|
||||
version = windows_version(json)
|
||||
|
||||
@platform[:family] = 'windows'
|
||||
@platform[:name] = versions[version]
|
||||
@platform[:release] = version
|
||||
true
|
||||
end
|
||||
|
||||
def detect_darwin
|
||||
cmd = @backend.run_command('/usr/bin/sw_vers')
|
||||
# TODO: print an error in this step of the detection,
|
||||
# as it shouldnt happen
|
||||
return false if cmd.exit_status != 0
|
||||
# TODO: ditto on error
|
||||
return false if cmd.stdout.empty?
|
||||
|
||||
name = cmd.stdout[/^ProductName:\s+(.+)$/, 1]
|
||||
# TODO: ditto on error
|
||||
return false if name.nil?
|
||||
@platform[:name] = name.downcase.chomp.tr(' ', '_')
|
||||
@platform[:release] = cmd.stdout[/^ProductVersion:\s+(.+)$/, 1]
|
||||
@platform[:build] = cmd.stdout[/^BuildVersion:\s+(.+)$/, 1]
|
||||
# TODO: keep for now due to backwards compatibility with serverspec
|
||||
@platform[:family] = 'darwin'
|
||||
true
|
||||
end
|
||||
|
||||
def detect_via_uname
|
||||
case uname_s.downcase
|
||||
when /aix/
|
||||
@platform[:family] = 'aix'
|
||||
out = @backend.run_command('uname -rvp').stdout
|
||||
m = out.match(/(\d+)\s+(\d+)\s+(.*)/)
|
||||
unless m.nil?
|
||||
@platform[:release] = "#{m[2]}.#{m[1]}"
|
||||
@platform[:arch] = m[3].to_s
|
||||
end
|
||||
|
||||
when /freebsd/
|
||||
@platform[:family] = 'freebsd'
|
||||
@platform[:name] = uname_s.lines[0].chomp
|
||||
@platform[:release] = uname_r.lines[0].chomp
|
||||
|
||||
when /netbsd/
|
||||
@platform[:family] = 'netbsd'
|
||||
@platform[:name] = uname_s.lines[0].chomp
|
||||
@platform[:release] = uname_r.lines[0].chomp
|
||||
|
||||
when /openbsd/
|
||||
@platform[:family] = 'openbsd'
|
||||
@platform[:name] = uname_s.lines[0].chomp
|
||||
@platform[:release] = uname_r.lines[0].chomp
|
||||
|
||||
when /sunos/
|
||||
@platform[:family] = 'solaris'
|
||||
if uname_r =~ /5\.10/
|
||||
# TODO: should be string!
|
||||
@platform[:release] = 10
|
||||
else
|
||||
rel = get_config('/etc/release')
|
||||
case rel
|
||||
when /^.*(SmartOS).*$/
|
||||
@platform[:family] = 'smartos'
|
||||
when !(m = /^\s*(OmniOS).*r(\d+).*$/).nil?
|
||||
@platform[:family] = 'omnios'
|
||||
@platform[:release] = m[2]
|
||||
when !(m = /^\s*(OpenIndiana).*oi_(\d+).*$/).nil?
|
||||
@platform[:family] = 'openindiana'
|
||||
@platform[:release] = m[2]
|
||||
when /^\s*(OpenSolaris).*snv_(\d+).*$/
|
||||
@platform[:family] = 'opensolaris'
|
||||
@platform[:release] = m[2]
|
||||
when !(m = /Oracle Solaris (\d+)/).nil?
|
||||
# TODO: should be string!
|
||||
@platform[:release] = m[1].to_i
|
||||
@platform[:family] = 'solaris2'
|
||||
when /^\s*(Solaris)\s.*$/
|
||||
@platform[:family] = 'solaris2'
|
||||
when /^\s*(NexentaCore)\s.*$/
|
||||
@platform[:family] = 'nexentacore'
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
# in all other cases we didn't detect it
|
||||
return false
|
||||
end
|
||||
# when we get here the detection returned a result
|
||||
true
|
||||
end
|
||||
|
||||
def detect_linux_via_config
|
||||
if !(raw = get_config('oracle-release')).nil?
|
||||
@platform[:family] = 'oracle'
|
||||
@platform[:release] = redhatish_version(raw)
|
||||
elsif !(raw = get_config('/etc/enterprise-release')).nil?
|
||||
@platform[:family] = 'oracle'
|
||||
@platform[:release] = redhatish_version(raw)
|
||||
elsif !(_raw = get_config('/etc/debian_version')).nil?
|
||||
case lsb[:id]
|
||||
when /ubuntu/i
|
||||
@platform[:family] = 'ubuntu'
|
||||
@platform[:release] = lsb[:release]
|
||||
when /linuxmint/i
|
||||
@platform[:family] = 'linuxmint'
|
||||
@platform[:release] = lsb[:release]
|
||||
else
|
||||
@platform[:family] = 'debian'
|
||||
@platform[:family] = 'raspbian' if unix_file?('/usr/bin/raspi-config')
|
||||
if !(rel = get_config('/etc/debian_version')).nil?
|
||||
@platform[:release] = rel.chomp
|
||||
end
|
||||
end
|
||||
elsif !(raw = get_config('/etc/parallels-release')).nil?
|
||||
@platform[:family] = redhatish_platform(raw)
|
||||
@platform[:release] = raw[/(\d\.\d\.\d)/, 1]
|
||||
elsif !(raw = get_config('/etc/redhat-release')).nil?
|
||||
# TODO: Cisco
|
||||
@platform[:family] = redhatish_platform(raw)
|
||||
@platform[:release] = redhatish_version(raw)
|
||||
elsif !(raw = get_config('/etc/system-release')).nil?
|
||||
# Amazon Linux
|
||||
@platform[:family] = redhatish_platform(raw)
|
||||
@platform[:release] = redhatish_version(raw)
|
||||
elsif !(suse = get_config('/etc/SuSE-release')).nil?
|
||||
version = suse.scan(/VERSION = (\d+)\nPATCHLEVEL = (\d+)/).flatten.join('.')
|
||||
version = suse[/VERSION = ([\d\.]{2,})/, 1] if version == ''
|
||||
@platform[:release] = version
|
||||
@platform[:family] = 'suse'
|
||||
@platform[:family] = 'opensuse' if suse =~ /^openSUSE/
|
||||
elsif !(raw = get_config('/etc/arch-release')).nil?
|
||||
@platform[:family] = 'arch'
|
||||
# Because this is a rolling release distribution,
|
||||
# use the kernel release, ex. 4.1.6-1-ARCH
|
||||
@platform[:release] = uname_r
|
||||
elsif !(raw = get_config('/etc/slackware-version')).nil?
|
||||
@platform[:family] = 'slackware'
|
||||
@platform[:release] = raw.scan(/(\d+|\.+)/).join
|
||||
elsif !(raw = get_config('/etc/exherbo-release')).nil?
|
||||
@platform[:family] = 'exherbo'
|
||||
# Because this is a rolling release distribution,
|
||||
# use the kernel release, ex. 4.1.6
|
||||
@platform[:release] = uname_r
|
||||
elsif !(raw = get_config('/etc/gentoo-release')).nil?
|
||||
@platform[:family] = 'gentoo'
|
||||
@platform[:release] = raw.scan(/(\d+|\.+)/).join
|
||||
elsif !(raw = get_config('/etc/alpine-release')).nil?
|
||||
@platform[:family] = 'alpine'
|
||||
@platform[:release] = raw.strip
|
||||
elsif !(raw = get_config('/etc/coreos/update.conf')).nil?
|
||||
@platform[:family] = 'coreos'
|
||||
meta = lsb_config(raw)
|
||||
@platform[:release] = meta[:release]
|
||||
else
|
||||
# in all other cases we didn't detect it
|
||||
return false
|
||||
end
|
||||
# when we get here the detection returned a result
|
||||
true
|
||||
end
|
||||
|
||||
def detect_linux_via_lsb
|
||||
return false if lsb[:id].nil?
|
||||
id = lsb[:id].downcase
|
||||
case id
|
||||
when /redhat/
|
||||
@platform[:family] = 'redhat'
|
||||
when /amazon/
|
||||
@platform[:family] = 'amazon'
|
||||
when /scientificsl/
|
||||
@platform[:family] = 'scientific'
|
||||
when /xenserver/
|
||||
@platform[:family] = 'xenserver'
|
||||
else
|
||||
@platform[:family] = id
|
||||
end
|
||||
@platform[:release] = lsb[:release]
|
||||
true
|
||||
end
|
||||
|
||||
def uname_s
|
||||
@uname_s ||= @backend.run_command('uname -s').stdout
|
||||
end
|
||||
|
||||
def uname_r
|
||||
@uname_r ||= (
|
||||
res = @backend.run_command('uname -r').stdout
|
||||
res.strip! unless res.nil?
|
||||
res
|
||||
)
|
||||
end
|
||||
|
||||
def detect_linux
|
||||
# TODO: print an error in this step of the detection
|
||||
return false if uname_s.nil? || uname_s.empty?
|
||||
return false if uname_r.nil? || uname_r.empty?
|
||||
|
||||
return true if detect_linux_via_config
|
||||
return true if detect_linux_via_lsb
|
||||
# in all other cases we failed the detection
|
||||
@platform[:family] = 'unknown'
|
||||
end
|
||||
|
||||
def get_config(path)
|
||||
res = @backend.run_command("test -f #{path} && cat #{path}")
|
||||
# ignore files that can't be read
|
||||
|
@ -330,41 +86,5 @@ class Vulcano::Plugins::Backend
|
|||
def unix_file?(path)
|
||||
@backend.run_command("test -f #{path}").exit_status == 0
|
||||
end
|
||||
|
||||
def redhatish_platform(conf)
|
||||
conf[/^red hat/i] ? 'redhat' : conf[/(\w+)/i, 1].downcase
|
||||
end
|
||||
|
||||
def redhatish_version(conf)
|
||||
conf[/rawhide/i] ? conf[/((\d+) \(Rawhide\))/i, 1].downcase : conf[/release ([\d\.]+)/, 1]
|
||||
end
|
||||
|
||||
def lsb_config(content)
|
||||
{
|
||||
id: content[/^DISTRIB_ID=["']?(.+?)["']?$/, 1],
|
||||
release: content[/^DISTRIB_RELEASE=["']?(.+?)["']?$/, 1],
|
||||
codename: content[/^DISTRIB_CODENAME=["']?(.+?)["']?$/, 1],
|
||||
}
|
||||
end
|
||||
|
||||
def lsb_release
|
||||
raw = @backend.run_command('lsb_release -a').stdout
|
||||
{
|
||||
id: raw[/^Distributor ID:\s+(.+)$/, 1],
|
||||
release: raw[/^Release:\s+(.+)$/, 1],
|
||||
codename: raw[/^Codename:\s+(.+)$/, 1],
|
||||
}
|
||||
end
|
||||
|
||||
def lsb
|
||||
return @lsb unless @lsb.nil?
|
||||
@lsb = {}
|
||||
if !(raw = get_config('/etc/lsb-release')).nil?
|
||||
@lsb = lsb_config(raw)
|
||||
elsif unix_file?('/usr/bin/lsb_release')
|
||||
@lsb = lsb_release
|
||||
end
|
||||
@lsb
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,70 +15,10 @@ module Vulcano
|
|||
@profile_id = profile_id
|
||||
@rules = profile_registry
|
||||
@only_ifs = only_ifs
|
||||
profile_context_owner = self
|
||||
|
||||
dsl = Module.new do
|
||||
Vulcano::Resource.registry.each do |id, r|
|
||||
define_method id.to_sym do |*args|
|
||||
r.new(backend, *args)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
rule_class = Class.new(Vulcano::Rule) do
|
||||
include RSpec::Core::DSL
|
||||
include dsl
|
||||
end
|
||||
|
||||
outer_dsl = Class.new do
|
||||
include dsl
|
||||
|
||||
define_method :rule do |*args, &block|
|
||||
id = args[0]
|
||||
opts = args[1] || {}
|
||||
return if @skip_profile
|
||||
__register_rule rule_class.new(id, opts, &block)
|
||||
end
|
||||
|
||||
define_method :describe do |*args, &block|
|
||||
path = block.source_location[0]
|
||||
line = block.source_location[1]
|
||||
id = "#{File.basename(path)}:#{line}"
|
||||
rule = rule_class.new(id, {}) do
|
||||
describe(*args, &block)
|
||||
end
|
||||
__register_rule rule, &block
|
||||
end
|
||||
|
||||
def skip_rule(id)
|
||||
__unregister_rule id
|
||||
end
|
||||
|
||||
def only_if(&block)
|
||||
return unless block_given?
|
||||
@skip_profile = !block.call
|
||||
end
|
||||
end
|
||||
|
||||
# This is the heart of the profile context
|
||||
# An instantiated object which has all resources registered to it
|
||||
# and exposes them to the a test file.
|
||||
# rubocop:disable Lint/NestedMethodDefinition
|
||||
ctx = Class.new(outer_dsl) do
|
||||
include Vulcano::DSL
|
||||
|
||||
define_method :__register_rule do |*args|
|
||||
profile_context_owner.register_rule(*args)
|
||||
end
|
||||
define_method :__unregister_rule do |*args|
|
||||
profile_context_owner.unregister_rule(*args)
|
||||
end
|
||||
|
||||
def to_s
|
||||
'Profile Context Run'
|
||||
end
|
||||
end
|
||||
# rubocop:enable all
|
||||
dsl = create_inner_dsl(backend)
|
||||
outer_dsl = create_outer_dsl(dsl)
|
||||
ctx = create_context(outer_dsl)
|
||||
|
||||
@profile_context = ctx.new
|
||||
end
|
||||
|
@ -107,5 +47,96 @@ module Vulcano
|
|||
Vulcano::Rule.merge(existing, r)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Creates the inner DSL which includes all resources for
|
||||
# creating tests. It is always connected to one target,
|
||||
# which is specified via the backend argument.
|
||||
#
|
||||
# @param backend [BackendRunner] exposing the target to resources
|
||||
# @return [InnerDSLModule]
|
||||
def create_inner_dsl(backend)
|
||||
Module.new do
|
||||
Vulcano::Resource.registry.each do |id, r|
|
||||
define_method id.to_sym do |*args|
|
||||
r.new(backend, *args)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Creates the outer DSL which includes all methods for creating
|
||||
# tests and control structures.
|
||||
#
|
||||
# @param dsl [InnerDSLModule] which contains all resources
|
||||
# @return [OuterDSLClass]
|
||||
def create_outer_dsl(dsl)
|
||||
rule_class = Class.new(Vulcano::Rule) do
|
||||
include RSpec::Core::DSL
|
||||
include dsl
|
||||
end
|
||||
|
||||
# rubocop:disable Lint/NestedMethodDefinition
|
||||
Class.new do
|
||||
include dsl
|
||||
|
||||
define_method :rule do |*args, &block|
|
||||
id = args[0]
|
||||
opts = args[1] || {}
|
||||
return if @skip_profile
|
||||
__register_rule rule_class.new(id, opts, &block)
|
||||
end
|
||||
|
||||
define_method :describe do |*args, &block|
|
||||
path = block.source_location[0]
|
||||
line = block.source_location[1]
|
||||
id = "#{File.basename(path)}:#{line}"
|
||||
rule = rule_class.new(id, {}) do
|
||||
describe(*args, &block)
|
||||
end
|
||||
__register_rule rule, &block
|
||||
end
|
||||
|
||||
def skip_rule(id)
|
||||
__unregister_rule id
|
||||
end
|
||||
|
||||
def only_if(&block)
|
||||
return unless block_given?
|
||||
@skip_profile = !block.call
|
||||
end
|
||||
end
|
||||
# rubocop:enable all
|
||||
end
|
||||
|
||||
# Creates the heart of the profile context:
|
||||
# An instantiated object which has all resources registered to it
|
||||
# and exposes them to the a test file. The profile context serves as a
|
||||
# container for all profiles which are registered. Within the context
|
||||
# profiles get access to all DSL calls for creating tests and controls.
|
||||
#
|
||||
# @param outer_dsl [OuterDSLClass]
|
||||
# @return [ProfileContextClass]
|
||||
def create_context(outer_dsl)
|
||||
profile_context_owner = self
|
||||
|
||||
# rubocop:disable Lint/NestedMethodDefinition
|
||||
Class.new(outer_dsl) do
|
||||
include Vulcano::DSL
|
||||
|
||||
define_method :__register_rule do |*args|
|
||||
profile_context_owner.register_rule(*args)
|
||||
end
|
||||
define_method :__unregister_rule do |*args|
|
||||
profile_context_owner.unregister_rule(*args)
|
||||
end
|
||||
|
||||
def to_s
|
||||
'Profile Context Run'
|
||||
end
|
||||
end
|
||||
# rubocop:enable all
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue