Class: Inspec::Metadata

Inherits:
Object
  • Object
show all
Defined in:
lib/inspec/metadata.rb

Overview

Extract metadata.rb information

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ref, logger = nil) ⇒ Metadata

Returns a new instance of Metadata.



15
16
17
18
19
20
# File 'lib/inspec/metadata.rb', line 15

def initialize(ref, logger = nil)
  @ref = ref
  @logger = logger || Logger.new(nil)
  @params = {}
  @missing_methods = []
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sth, *args) ⇒ Object



125
126
127
128
# File 'lib/inspec/metadata.rb', line 125

def method_missing(sth, *args)
  @logger.warn "#{ref} doesn't support: #{sth} #{args}"
  @missing_methods.push(sth)
end

Instance Attribute Details

#paramsObject

Returns the value of attribute params.



14
15
16
# File 'lib/inspec/metadata.rb', line 14

def params
  @params
end

#refObject (readonly)

rubocop:disable Metrics/ClassLength



13
14
15
# File 'lib/inspec/metadata.rb', line 13

def ref
  @ref
end

Class Method Details

.finalize(metadata, profile_id, options, logger = nil) ⇒ Object



197
198
199
200
201
202
203
204
205
206
207
# File 'lib/inspec/metadata.rb', line 197

def self.finalize(, profile_id, options, logger = nil)
  return nil if .nil?
  param = .params || {}
  options ||= {}
  param['version'] = param['version'].to_s unless param['version'].nil?
  .params = symbolize_keys(param)
  .params[:supports] = finalize_supports(.params[:supports], logger)
  finalize_name(, profile_id, options[:target])

  
end

.finalize_name(metadata, profile_id, original_target) ⇒ Object



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/inspec/metadata.rb', line 180

def self.finalize_name(, profile_id, original_target)
  # profile_id always overwrites whatever already exists as the name
  unless profile_id.to_s.empty?
    .params[:name] = profile_id.to_s
    return
  end

  # don't overwrite an existing name
  return unless .params[:name].nil?

  # if there's a title, there is no need to set a name too
  return unless .params[:title].nil?

  # create a new name based on the original target if it exists
  .params[:name] = "tests from #{original_target}" unless original_target.to_s.empty?
end

.finalize_supports(supports, logger) ⇒ Object



166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/inspec/metadata.rb', line 166

def self.finalize_supports(supports, logger)
  case x = supports
  when Hash   then [finalize_supports_elem(x, logger)]
  when Array  then x.map { |e| finalize_supports_elem(e, logger) }.compact
  when nil    then []
  else
    logger ||= Logger.new(nil)
    logger.warn(
      "Do not use deprecated `supports: #{x}` syntax. Instead use:\n"\
      "supports:\n  - os-family: #{x}\n\n")
    [{ :'os-family' => x }]
  end
end

.finalize_supports_elem(elem, logger) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/inspec/metadata.rb', line 145

def self.finalize_supports_elem(elem, logger)
  case x = elem
  when Hash
    x[:release] = x[:release].to_s if x[:release]
    x
  when Array
    logger.warn(
      'Failed to read supports entry that is an array. Please use '\
      'the `supports: {os-family: xyz}` syntax.',
    )
    nil
  when nil then nil
  else
    logger ||= Logger.new(nil)
    logger.warn(
      "Do not use deprecated `supports: #{x}` syntax. Instead use:\n"\
      "supports:\n  - os-family: #{x}\n\n")
    { :'os-family' => x }
  end
end

.from_file(path, profile_id, logger = nil) ⇒ Object



236
237
238
239
240
241
242
243
244
# File 'lib/inspec/metadata.rb', line 236

def self.from_file(path, profile_id, logger = nil)
  unless File.file?(path)
    logger ||= Logger.new(nil)
    logger.error "Can't find metadata file #{path}"
    return nil
  end

  from_ref(File.basename(path), File.read(path), profile_id, logger)
end

.from_ref(ref, contents, profile_id, logger = nil) ⇒ Object



221
222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/inspec/metadata.rb', line 221

def self.from_ref(ref, contents, profile_id, logger = nil)
  # NOTE there doesn't have to exist an actual file, it may come from an
  # archive (i.e., contents)
  case File.basename(ref)
  when 'inspec.yml'
    from_yaml(ref, contents, profile_id, logger)
  when 'metadata.rb'
    from_ruby(ref, contents, profile_id, logger)
  else
    logger ||= Logger.new(nil)
    logger.error "Don't know how to handle metadata in #{ref}"
    nil
  end
end

.from_ruby(ref, contents, profile_id, logger = nil) ⇒ Object



215
216
217
218
219
# File 'lib/inspec/metadata.rb', line 215

def self.from_ruby(ref, contents, profile_id, logger = nil)
  res = Metadata.new(ref, logger)
  res.instance_eval(contents, ref, 1)
  finalize(res, profile_id, {}, logger)
end

.from_yaml(ref, contents, profile_id, logger = nil) ⇒ Object



209
210
211
212
213
# File 'lib/inspec/metadata.rb', line 209

def self.from_yaml(ref, contents, profile_id, logger = nil)
  res = Metadata.new(ref, logger)
  res.params = YAML.load(contents)
  finalize(res, profile_id, {}, logger)
end

.symbolize_keys(obj) ⇒ Object



134
135
136
137
138
139
140
141
142
143
# File 'lib/inspec/metadata.rb', line 134

def self.symbolize_keys(obj)
  return obj.map { |i| symbolize_keys(i) } if obj.is_a?(Array)
  return obj unless obj.is_a?(Hash)

  obj.each_with_object({}) {|(k, v), h|
    v = symbolize_keys(v) if v.is_a?(Hash)
    v = symbolize_keys(v) if v.is_a?(Array)
    h[k.to_sym] = v
  }
end

Instance Method Details

#dependenciesObject



39
40
41
# File 'lib/inspec/metadata.rb', line 39

def dependencies
  params[:depends] || []
end

#inspec_requirementObject



78
79
80
81
# File 'lib/inspec/metadata.rb', line 78

def inspec_requirement
  inspec = params[:supports].find { |x| !x[:inspec].nil? } || {}
  Gem::Requirement.create(inspec[:inspec])
end

#is_supported?(os, entry) ⇒ Boolean

Returns:

  • (Boolean)


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
# File 'lib/inspec/metadata.rb', line 49

def is_supported?(os, entry)
  name = entry[:'os-name'] || entry[:os]
  family = entry[:'os-family']
  release = entry[:release]

  # return true if the backend matches the supported OS's
  # fields act as masks, i.e. any value configured for os-name, os-family,
  # or release must be met by the backend; any field that is nil acts as
  # a glob expression i.e. is true

  # os name is both saved in :family and :name, so check both
  name_ok = name.nil? ||
            os[:name] == name || os[:family] == name

  family_check = family.to_s + '?'
  family_ok = family.nil? || os[:family] == family ||
              (
                os.respond_to?(family_check) &&
                # this call will return true if the family matches
                os.method(family_check).call
              )

  # ensure we do have a string if we have a non-nil value eg. 16.06
  release_ok = release.nil? || os[:release] == release

  # we want to make sure that all matchers are true
  name_ok && family_ok && release_ok
end

#supports(sth, version = nil) ⇒ Object



43
44
45
46
47
# File 'lib/inspec/metadata.rb', line 43

def supports(sth, version = nil)
  # Ignore supports with metadata.rb. This file is legacy and the way it
  # it handles `supports` deprecated. A deprecation warning will be printed
  # already.
end

#supports_runtime?Boolean

Returns:

  • (Boolean)


83
84
85
86
# File 'lib/inspec/metadata.rb', line 83

def supports_runtime?
  running = Gem::Version.new(Inspec::VERSION)
  inspec_requirement.satisfied_by?(running)
end

#supports_transport?(backend) ⇒ Boolean

Returns:

  • (Boolean)


88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/inspec/metadata.rb', line 88

def supports_transport?(backend)
  # with no supports specified, always return true, as there are no
  # constraints on the supported backend; it is equivalent to putting
  # all fields into accept-all mode
  return true if params[:supports].empty?

  found = params[:supports].find do |entry|
    is_supported?(backend.os, entry)
  end

  # finally, if we found a supported entry, we are good to go
  !found.nil?
end

#unsupportedObject



130
131
132
# File 'lib/inspec/metadata.rb', line 130

def unsupported
  @missing_methods
end

#validObject

return all warn and errors



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/inspec/metadata.rb', line 103

def valid
  errors = []
  warnings = []

  %w{ name version }.each do |field|
    next unless params[field.to_sym].nil?
    errors.push("Missing profile #{field} in #{ref}")
  end
  %w{ title summary maintainer copyright }.each do |field|
    next unless params[field.to_sym].nil?
    warnings.push("Missing profile #{field} in #{ref}")
  end

  [errors, warnings]
end

#valid?Boolean

returns true or false

Returns:

  • (Boolean)


120
121
122
123
# File 'lib/inspec/metadata.rb', line 120

def valid?
  errors, _warnings = valid
  errors.empty? && unsupported.empty?
end