-
Notifications
You must be signed in to change notification settings - Fork 59
/
Copy pathinspec_gem.rb
143 lines (120 loc) · 4.33 KB
/
inspec_gem.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
provides :inspec_gem
unified_mode true
resource_name :inspec_gem
property :gem_name, String, name_property: true
property :version, String
property :source, String
default_action :install
action :install do
# detect if installation is required
compatible_version = compatible_with_client?(new_resource.version)
installation_required = inspec_info.nil? || !new_resource.version.nil?
# detect if the same version is already installed
unless inspec_info.nil?
installed_version = inspec_info.version.to_s
Chef::Log.debug("Installed Chef-InSpec version: #{installed_version}")
if new_resource.version == installed_version
installation_required = false
Chef::Log.info("inspec_gem: not installing Chef-InSpec. Requested version #{new_resource.version} already installed")
return
end
end
if installation_required && compatible_version
Chef::Log.info("Installation of Chef-InSpec required: #{installation_required}")
unless inspec_info.nil?
converge_by 'uninstall all inspec and train gem versions' do
uninstall_inspec_gem
end
end
converge_by 'install given Chef-InSpec version' do
install_inspec_gem(version: new_resource.version, source: new_resource.source)
end
elsif new_resource.version.nil?
Chef::Log.info('inspec_gem: not installing Chef-InSpec. No Chef-Inspec version specified')
elsif !compatible_version
Chef::Log.warn("inspec_gem: not installing Chef-InSpec. Requested version #{new_resource.version} is not compatible with chef-client #{Chef::VERSION}")
end
end
action_class do
def install_inspec_gem(options)
gem_source = options[:source]
gem_version = options[:version]
gem_version = nil if gem_version == 'latest'
# use inspec-core for recent inspec versions
gem_name = use_inspec_core?(gem_version) ? 'inspec-core' : 'inspec'
chef_gem gem_name do
version gem_version unless gem_version.nil?
unless gem_source.nil?
clear_sources true
include_default_source false if respond_to?(:include_default_source)
source gem_source
end
compile_time false
action :install
end
chef_gem 'inspec-core-bin' do
version gem_version unless gem_version.nil?
unless gem_source.nil?
clear_sources true
include_default_source false if respond_to?(:include_default_source)
source gem_source
end
compile_time false
action :install
only_if { need_inspec_core_bin?(gem_version) }
end
end
def compatible_with_client?(gem_version)
# No version specified so they will get the latest
return true if gem_version.nil?
if chef_gte_15?
# Chef-15 can only run with the version of inspec-core and train-core that's being bundled with
# It's pinned here: grep "inspec-" /opt/chef/bin/chef-client
Chef::Log.warn('inspec_gem: Chef Infra Client >= 15 detected, can only use the embedded InSpec gem!!!')
false
else
# min version required to run the audit handler
Gem::Requirement.new(['>= 1.25.1']).satisfied_by?(Gem::Version.new(gem_version))
end
end
def chef_gte_15?
Gem::Requirement.new('>= 15').satisfied_by?(Gem::Version.new(Chef::VERSION))
end
def use_inspec_core?(gem_version)
return true if gem_version.nil? # latest version
Gem::Requirement.new('>= 2.1.67').satisfied_by?(Gem::Version.new(gem_version))
end
# Inspec 4+ does not include inspec binaries and requires an additional gem
def need_inspec_core_bin?(gem_version)
return true if gem_version.nil? # latest version
Gem::Requirement.new('>= 4').satisfied_by?(Gem::Version.new(gem_version))
end
def uninstall_inspec_gem
chef_gem 'remove all inspec versions' do
package_name 'inspec'
action :remove
end
chef_gem 'remove all inspec-core versions' do
package_name 'inspec-core'
action :remove
end
chef_gem 'remove all inspec-core-bin versions' do
package_name 'inspec-core-bin'
action :remove
end
chef_gem 'remove all train versions' do
package_name 'train'
action :remove
end
chef_gem 'remove all train-core versions' do
package_name 'train-core'
action :remove
end
end
def inspec_info
require 'rubygems'
Gem::Specification.find { |s| %w(inspec inspec-core).include?(s.name) }
rescue LoadError
nil
end
end