ohai 15.7.4 → 16.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3836d8ca7e3ae0f1beb6a8f4cd3ca01cc016b8803d01d7ff2aca39dd3622cdc1
4
- data.tar.gz: c09ced6abcc3ee95ddb69f35a08f34291bbc7b8b9f4e855fd809e88f7fae5eed
3
+ metadata.gz: b01a821d5ffa3a329d434aa798b7e6396cd38329a5aed167cc9fa5d790e1e40b
4
+ data.tar.gz: 832b596c834b379cd996bdad0d097e38684be9e175fcd50d59fce4cebc04ec19
5
5
  SHA512:
6
- metadata.gz: a8d390efe3e82e70e744249ef71e9087898c2dc1f6fcb76b08797d5079d8138a2c56fc11189ad785b6b8057dc1679ae4c2fa97318d6239a4dc4c286d01a483e5
7
- data.tar.gz: 5a513712ac8a5173b2a31ce39b80777f6e7c08bab22d5e8642c906c2cad1545ecc5d4ea1702c04624bfcbf8f0ebdbe92be73f7efd01ab1c2da671601cbf9508b
6
+ metadata.gz: ad4cbe610a98f04f3525b4d025e7053712dbe7c9218d38e506dd6beb031ded0e5d969ede709a0b2fdf95cea747905d18b021eea7d29db25271f24792c439bc4b
7
+ data.tar.gz: 5359aff83afbfceb44068bc838ce4a8153e863a6684319a65b1164e48169e6ba406e38e537c4686d1102e4bfc29e1f783fe4bdc216654fd0d19af53d8c5fbbf0
data/Gemfile CHANGED
@@ -13,10 +13,6 @@ group :development do
13
13
  gem "ipaddr_extensions"
14
14
  end
15
15
 
16
- group :ci do
17
- gem "rspec_junit_formatter"
18
- end
19
-
20
16
  group :docs do
21
17
  gem "yard"
22
18
  gem "redcarpet"
@@ -26,6 +22,6 @@ end
26
22
  group :debug do
27
23
  gem "pry"
28
24
  gem "pry-byebug"
29
- gem "pry-stack_explorer"
25
+ gem "pry-stack_explorer", "~> 0.4.0" # pin until we drop ruby < 2.6
30
26
  gem "rb-readline"
31
27
  end
@@ -111,6 +111,15 @@ module Ohai
111
111
  id
112
112
  end
113
113
 
114
+ SKIPPED_CONVENIENCE_KEYS = %w{
115
+ application_identifier
116
+ caption
117
+ creation_class_name
118
+ size
119
+ system_creation_class_name
120
+ record_id
121
+ }.freeze
122
+
114
123
  # create simplified convenience access keys for each record type
115
124
  # for single occurrences of one type, copy to top level all fields and values
116
125
  # for multiple occurrences of same type, copy to top level all fields and values that are common to all records
@@ -122,13 +131,12 @@ module Ohai
122
131
 
123
132
  records[:all_records].each do |record|
124
133
  record.each do |field, value|
125
- next if value.is_a?(Mash)
126
- next if field.to_s == "application_identifier"
127
- next if field.to_s == "size"
128
- next if field.to_s == "record_id"
134
+ next unless value.is_a?(String)
129
135
 
130
136
  translated = field.downcase.gsub(/[^a-z0-9]/, "_")
131
- value = value.strip
137
+ next if SKIPPED_CONVENIENCE_KEYS.include?(translated.to_s)
138
+
139
+ value = value.strip
132
140
  if in_common.key?(translated)
133
141
  in_common[translated] = nil unless in_common[translated] == value
134
142
  else
@@ -39,7 +39,7 @@ module Ohai
39
39
  # causes all optional plugins to be run.
40
40
  default :run_all_plugins, false
41
41
  # optional plugins are the set of plugins that are marked optional but you wish to run.
42
- default :optional_plugins, []
42
+ default(:optional_plugins, []).writes_value { |arr| arr.map(&:to_sym) }
43
43
  default :shellout_timeout, 30
44
44
  end
45
45
  end
@@ -1,201 +1,21 @@
1
- # Copyright (c) 2009 Dan Kubb
2
-
3
- # Permission is hereby granted, free of charge, to any person obtaining
4
- # a copy of this software and associated documentation files (the
5
- # "Software"), to deal in the Software without restriction, including
6
- # without limitation the rights to use, copy, modify, merge, publish,
7
- # distribute, sublicense, and/or sell copies of the Software, and to
8
- # permit persons to whom the Software is furnished to do so, subject to
9
- # the following conditions:
10
-
11
- # The above copyright notice and this permission notice shall be
12
- # included in all copies or substantial portions of the Software.
13
-
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
-
22
- # ---
23
- # ---
24
-
25
- # Some portions of blank.rb and mash.rb are verbatim copies of software
26
- # licensed under the MIT license. That license is included below:
27
-
28
- # Copyright (c) 2005-2008 David Heinemeier Hansson
29
-
30
- # Permission is hereby granted, free of charge, to any person obtaining
31
- # a copy of this software and associated documentation files (the
32
- # "Software"), to deal in the Software without restriction, including
33
- # without limitation the rights to use, copy, modify, merge, publish,
34
- # distribute, sublicense, and/or sell copies of the Software, and to
35
- # permit persons to whom the Software is furnished to do so, subject to
36
- # the following conditions:
37
-
38
- # The above copyright notice and this permission notice shall be
39
- # included in all copies or substantial portions of the Software.
40
-
41
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
42
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
43
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
44
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
45
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
46
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
47
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
48
-
49
- # This class has dubious semantics and we only have it so that people can write
50
- # params[:key] instead of params['key'].
51
- class Mash < Hash
52
-
53
- # @param constructor [Object] The default value for the mash.
54
- # If constructor is a Hash, a new mash will be created based on the keys of the hash and
55
- # no default value will be set.
56
- def initialize(constructor = {})
57
- if constructor.is_a?(Hash)
58
- super()
59
- update(constructor)
60
- else
61
- super(constructor)
62
- end
63
- end
64
-
65
- # @param key [Object] The default value for the mash.
66
- # If key is a Symbol and it is a key in the mash, then the default value will be set to
67
- # the value matching the key.
68
- def default(key = nil)
69
- if key.is_a?(Symbol) && include?(key = key.to_s)
70
- self[key]
71
- else
72
- super
73
- end
74
- end
75
-
76
- alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
77
- alias_method :regular_update, :update unless method_defined?(:regular_update)
78
-
79
- # @param key [Object] The key to set.
80
- # @param value [Object] The value to set the key to.
81
- #
82
- # @see Mash#convert_key
83
- # @see Mash#convert_value
84
- def []=(key, value)
85
- regular_writer(convert_key(key), convert_value(value))
86
- end
87
-
88
- # @param other_hash [Hash]
89
- # A hash to update values in the mash with. The keys and the values will be
90
- # converted to Mash format.
91
- #
92
- # @return [Mash] The updated mash.
93
- def update(other_hash)
94
- other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
95
- self
96
- end
97
-
98
- alias_method :merge!, :update
99
-
100
- # @param key [Object] The key to check for. This will be run through convert_key.
101
- #
102
- # @return [Boolean] True if the key exists in the mash.
103
- def key?(key)
104
- super(convert_key(key))
105
- end
106
-
107
- # def include? def has_key? def member?
108
- alias_method :include?, :key?
109
- alias_method :has_key?, :key?
110
- alias_method :member?, :key?
111
-
112
- # @param key [Object] The key to fetch. This will be run through convert_key.
113
- # @param extras [Array] Default value.
114
- #
115
- # @return [Object] The value at key or the default value.
116
- def fetch(key, *extras)
117
- super(convert_key(key), *extras)
118
- end
119
-
120
- # @param indices [Array] The keys to retrieve values for. These will be run through +convert_key+.
121
- #
122
- # @return [Array] The values at each of the provided keys
123
- def values_at(*indices)
124
- indices.collect { |key| self[convert_key(key)] }
125
- end
126
-
127
- # @param hash [Hash] The hash to merge with the mash.
128
- #
129
- # @return [Mash] A new mash with the hash values merged in.
130
- def merge(hash)
131
- dup.update(hash)
132
- end
133
-
134
- # @param key [Object] The key to delete from the mash.
135
- def delete(key)
136
- super(convert_key(key))
137
- end
138
-
139
- # @param keys [Array<String, Symbol>] The mash keys to exclude.
140
- #
141
- # @return [Mash] A new mash without the selected keys.
142
- #
143
- # @example
144
- # { :one => 1, :two => 2, :three => 3 }.except(:one)
145
- # #=> { "two" => 2, "three" => 3 }
146
- def except(*keys)
147
- super(*keys.map { |k| convert_key(k) })
148
- end
149
-
150
- # Used to provide the same interface as Hash.
151
- #
152
- # @return [Mash] This mash unchanged.
153
- def stringify_keys!; self end
154
-
155
- # @return [Hash] The mash as a Hash with symbolized keys.
156
- def symbolize_keys
157
- h = Hash.new(default)
158
- each { |key, val| h[key.to_sym] = val }
159
- h
160
- end
161
-
162
- # @return [Hash] The mash as a Hash with string keys.
163
- def to_hash
164
- Hash.new(default).merge(self)
165
- end
166
-
167
- # Convert a Hash into a Mash. The input Hash's default value is maintained
168
- # @return [Mash]
169
- def self.from_hash(hash)
170
- mash = Mash.new(hash)
171
- mash.default = hash.default
172
- mash
173
- end
174
-
175
- protected
176
-
177
- # @param key [Object] The key to convert.
178
- # @return [Object] The converted key. If the key was a symbol, it will be converted to a string.
179
- #
180
- # @api private
181
- def convert_key(key)
182
- key.is_a?(Symbol) ? key.to_s : key
183
- end
184
-
185
- # @param value [Object] The value to convert.
186
- #
187
- # @return [Object]
188
- # The converted value. A Hash or an Array of hashes, will be converted to
189
- # their Mash equivalents.
190
- #
191
- # @api private
192
- def convert_value(value)
193
- if value.class == Hash
194
- Mash.from_hash(value)
195
- elsif value.is_a?(Array)
196
- value.collect { |e| convert_value(e) }
197
- else
198
- value
199
- end
200
- end
201
- end
1
+ #
2
+ # Copyright:: Copyright (c) Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require "chef-utils/mash" unless defined?(ChefUtils::Mash)
19
+
20
+ # For historical reasons we inject Mash directly into the top level class namespace
21
+ Mash = ChefUtils::Mash unless defined?(Mash)
@@ -1,6 +1,6 @@
1
1
  #
2
2
  # Author:: Tim Smith (<tsmith@chef.io>)
3
- # Copyright:: Copyright 2017 Chef Software, Inc.
3
+ # Copyright:: 2017-2020 Chef Software, Inc.
4
4
  # License:: Apache License, Version 2.0
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,30 +19,86 @@ require "net/http" unless defined?(Net::HTTP)
19
19
 
20
20
  module Ohai
21
21
  module Mixin
22
+ #
23
+ # This code parses the Azure Instance Metadata API to provide details
24
+ # of the running instance.
25
+ #
26
+ # The code probes the instance metadata endpoint for
27
+ # available versions, determines the most advanced version known to
28
+ # work and executes the metadata retrieval using that version.
29
+ #
30
+ # If no compatible version is found, an empty hash is returned.
31
+ #
22
32
  module AzureMetadata
23
33
 
24
34
  AZURE_METADATA_ADDR ||= "169.254.169.254".freeze
25
- AZURE_METADATA_URL ||= "/metadata/instance?api-version=2017-08-01".freeze
26
35
 
27
- # fetch the meta content with a timeout and the required header
36
+ # it's important that the newer versions are at the end of this array so we can skip sorting it
37
+ AZURE_SUPPORTED_VERSIONS ||= %w{ 2017-04-02 2017-08-01 2017-12-01 2018-02-01 2018-04-02
38
+ 2018-10-01 2019-02-01 2019-03-11 2019-04-30 2019-06-01
39
+ 2019-06-04 2019-08-01 2019-08-15 2019-11-01 }.freeze
40
+
41
+ def best_api_version
42
+ @api_version ||= begin
43
+ logger.trace("Mixin AzureMetadata: Fetching http://#{AZURE_METADATA_ADDR}/metadata/instance to determine the latest supported metadata release")
44
+ response = http_get("/metadata/instance")
45
+ if response.code == "404"
46
+ logger.trace("Mixin AzureMetadata: Received HTTP 404 from metadata server while determining API version, assuming #{AZURE_SUPPORTED_VERSIONS.last}")
47
+ return AZURE_SUPPORTED_VERSIONS.last
48
+ elsif response.code != "400" # 400 is actually what we want
49
+ raise "Mixin AzureMetadata: Unable to determine Azure metadata version (returned #{response.code} response)"
50
+ end
51
+
52
+ # azure returns a list of the 3 latest versions it supports
53
+ versions = parse_json(response.body).fetch("newest-versions", [])
54
+ versions.sort!
55
+
56
+ until versions.empty? || AZURE_SUPPORTED_VERSIONS.include?(versions.last)
57
+ pv = versions.pop
58
+ logger.trace("Mixin AzureMetadata: Azure metadata version #{pv} is not present in the versions provided by the Azure Instance Metadata service")
59
+ end
60
+
61
+ if versions.empty?
62
+ logger.debug "Mixin AzureMetadata: The short list of supported versions provided by Azure Instance Metadata service doesn't match any known versions to Ohai. Using the latest supported release known to Ohai instead: #{AZURE_SUPPORTED_VERSIONS.last}"
63
+ return AZURE_SUPPORTED_VERSIONS.last
64
+ end
65
+
66
+ logger.trace("Mixin AzureMetadata: Latest supported Azure metadata version: #{versions.last}")
67
+ versions.last
68
+ end
69
+ end
70
+
71
+ # fetch the meta content with a timeout and the required header and a read timeout of 6s
72
+ #
73
+ # @param [String] the relative uri to fetch from the Azure Metadata Service URL
74
+ #
75
+ # @return [Net::HTTP]
28
76
  def http_get(uri)
29
77
  conn = Net::HTTP.start(AZURE_METADATA_ADDR)
30
78
  conn.read_timeout = 6
31
79
  conn.get(uri, { "Metadata" => "true" })
32
80
  end
33
81
 
34
- def fetch_metadata
35
- logger.trace("Mixin AzureMetadata: Fetching metadata from host #{AZURE_METADATA_ADDR} at #{AZURE_METADATA_URL}")
36
- response = http_get(AZURE_METADATA_URL)
82
+ # parse JSON data from a String to a Hash
83
+ #
84
+ # @param [String] response_body json as string to parse
85
+ #
86
+ # @return [Hash]
87
+ def parse_json(response_body)
88
+ data = String(response_body)
89
+ parser = FFI_Yajl::Parser.new
90
+ parser.parse(data)
91
+ rescue FFI_Yajl::ParseError
92
+ logger.warn("Mixin AzureMetadata: Metadata response is NOT valid JSON")
93
+ nil
94
+ end
95
+
96
+ def fetch_metadata(api_version = nil)
97
+ metadata_url = "/metadata/instance?api-version=#{best_api_version}"
98
+ logger.trace("Mixin AzureMetadata: Fetching metadata from host #{AZURE_METADATA_ADDR} at #{metadata_url}")
99
+ response = http_get(metadata_url)
37
100
  if response.code == "200"
38
- begin
39
- data = StringIO.new(response.body)
40
- parser = FFI_Yajl::Parser.new
41
- parser.parse(data)
42
- rescue FFI_Yajl::ParseError
43
- logger.warn("Mixin AzureMetadata: Metadata response is NOT valid JSON")
44
- nil
45
- end
101
+ parse_json(response.body)
46
102
  else
47
103
  logger.warn("Mixin AzureMetadata: Received response code #{response.code} requesting metadata")
48
104
  nil
@@ -160,7 +160,7 @@ module Ohai
160
160
  if key[-1..-1] != "/"
161
161
  retr_meta = metadata_get("#{id}#{key}", api_version)
162
162
  data = retr_meta ? retr_meta : ""
163
- json = StringIO.new(data)
163
+ json = String(data)
164
164
  parser = FFI_Yajl::Parser.new
165
165
  metadata[metadata_key(key)] = parser.parse(json)
166
166
  elsif not key.eql?("/")
@@ -39,7 +39,7 @@ module Ohai
39
39
  return nil unless response.code == "200"
40
40
 
41
41
  if json?(response.body)
42
- data = StringIO.new(response.body)
42
+ data = String(response.body)
43
43
  parser = FFI_Yajl::Parser.new
44
44
  parser.parse(data)
45
45
  elsif has_trailing_slash?(id) || (id == "")
@@ -57,7 +57,7 @@ module Ohai
57
57
  #
58
58
  # @return [Boolean] is the data JSON or not?
59
59
  def json?(data)
60
- data = StringIO.new(data)
60
+ data = String(data)
61
61
  parser = FFI_Yajl::Parser.new
62
62
  begin
63
63
  parser.parse(data)
@@ -36,10 +36,10 @@ Ohai.plugin(:C) do
36
36
  so = shell_out("/usr/bin/xcode-select -p")
37
37
  if so.exitstatus == 0
38
38
  logger.trace("Plugin C: Xcode Command Line Tools found.")
39
- return true
39
+ true
40
40
  else
41
41
  logger.trace("Plugin C: Xcode Command Line Tools not found.")
42
- return false
42
+ false
43
43
  end
44
44
  rescue Ohai::Exceptions::Exec
45
45
  logger.trace("Plugin C: xcode-select binary could not be found. Skipping data.")
@@ -364,7 +364,7 @@ Ohai.plugin(:CPU) do
364
364
  cpu["cpustates"][value] += 1
365
365
  when /core_id/
366
366
  cpu[instance]["core_id"] = value
367
- # Detect hyperthreading/multithreading
367
+ # Detect hyperthreading/multithreading
368
368
  cpucores.push(value) if cpucores.index(value).nil?
369
369
  when /family|fpu_type|model|stepping|vendor_id/
370
370
  cpu[instance][key] = value