google-cloud-env 1.6.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -3
- data/README.md +15 -16
- data/lib/google/cloud/env/compute_metadata.rb +875 -0
- data/lib/google/cloud/env/compute_smbios.rb +138 -0
- data/lib/google/cloud/env/file_system.rb +125 -0
- data/lib/google/cloud/env/lazy_value.rb +1003 -0
- data/lib/google/cloud/env/variables.rb +76 -0
- data/lib/google/cloud/env/version.rb +5 -1
- data/lib/google/cloud/env.rb +197 -170
- metadata +15 -150
@@ -0,0 +1,138 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2023 Google LLC
|
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
|
+
# https://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
|
+
require "google/cloud/env/lazy_value"
|
18
|
+
|
19
|
+
module Google
|
20
|
+
module Cloud
|
21
|
+
class Env
|
22
|
+
##
|
23
|
+
# Access to the SMBIOS information needed to determine if this Ruby
|
24
|
+
# process is running on a Google compute platform.
|
25
|
+
#
|
26
|
+
# This information lives at a file system path on Linux, but in the
|
27
|
+
# Registry on Windows.
|
28
|
+
#
|
29
|
+
# You can provide an override to "mock out" the behavior of this object.
|
30
|
+
#
|
31
|
+
class ComputeSMBIOS
|
32
|
+
##
|
33
|
+
# Create an SMBIOS access object
|
34
|
+
#
|
35
|
+
def initialize
|
36
|
+
@product_name_cache = LazyValue.new { load_product_name }
|
37
|
+
@override_product_name = nil
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Read the product name. On a Google compute platform, this should
|
42
|
+
# include the word "Google".
|
43
|
+
#
|
44
|
+
# This method may read the file system (on Linux) or registry (on
|
45
|
+
# Windows) the first time it is called, but it will cache the result
|
46
|
+
# for subsequent calls.
|
47
|
+
#
|
48
|
+
# @return [String] Product name, or the empty string if not found.
|
49
|
+
#
|
50
|
+
def product_name
|
51
|
+
@override_product_name || @product_name_cache.get.first
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# The source of the product name data. Will be one of the following:
|
56
|
+
#
|
57
|
+
# * `:linux` - The data comes from the Linux SMBIOS under /sys
|
58
|
+
# * `:windows` - The data comes from the Windows Registry
|
59
|
+
# * `:error` - The data could not be obtained
|
60
|
+
# * `:override` - The data comes from an override
|
61
|
+
#
|
62
|
+
# This method may read the file system (on Linux) or registry (on
|
63
|
+
# Windows) the first time it is called, but it will cache the result
|
64
|
+
# for subsequent calls.
|
65
|
+
#
|
66
|
+
# @return [Symbol] The source
|
67
|
+
#
|
68
|
+
def product_name_source
|
69
|
+
@override_product_name ? :override : @product_name_cache.get.last
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# Determine whether the SMBIOS state suggests that we are running on a
|
74
|
+
# Google compute platform.
|
75
|
+
#
|
76
|
+
# This method may read the file system (on Linux) or registry (on
|
77
|
+
# Windows) the first time it is called, but it will cache the result
|
78
|
+
# for subsequent calls.
|
79
|
+
#
|
80
|
+
# @return [true,false]
|
81
|
+
#
|
82
|
+
def google_compute?
|
83
|
+
product_name.include? "Google"
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# The current override value for the product name, either a string
|
88
|
+
# value, or nil to disable mocking.
|
89
|
+
#
|
90
|
+
# @return [nil,String]
|
91
|
+
#
|
92
|
+
attr_accessor :override_product_name
|
93
|
+
|
94
|
+
##
|
95
|
+
# Run the given block with the product name mock modified. This is
|
96
|
+
# generally used for debugging/testing/mocking.
|
97
|
+
#
|
98
|
+
# @param override_name [nil,String]
|
99
|
+
#
|
100
|
+
def with_override_product_name override_name
|
101
|
+
old_override = @override_product_name
|
102
|
+
begin
|
103
|
+
@override_product_name = override_name
|
104
|
+
yield
|
105
|
+
ensure
|
106
|
+
@override_product_name = old_override
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
# @private The Windows registry key path
|
113
|
+
WINDOWS_KEYPATH = "SYSTEM\\HardwareConfig\\Current"
|
114
|
+
# @private The Windows registry key name
|
115
|
+
WINDOWS_KEYNAME = "SystemProductName"
|
116
|
+
# @private The Linux file path
|
117
|
+
LINUX_FILEPATH = "/sys/class/dmi/id/product_name"
|
118
|
+
|
119
|
+
private_constant :WINDOWS_KEYPATH, :WINDOWS_KEYNAME, :LINUX_FILEPATH
|
120
|
+
|
121
|
+
def load_product_name
|
122
|
+
require "win32/registry"
|
123
|
+
Win32::Registry::HKEY_LOCAL_MACHINE.open WINDOWS_KEYPATH do |reg|
|
124
|
+
return [reg[WINDOWS_KEYNAME].to_s, :windows]
|
125
|
+
end
|
126
|
+
rescue LoadError
|
127
|
+
begin
|
128
|
+
File.open LINUX_FILEPATH do |file|
|
129
|
+
return [file.readline(chomp: true), :linux]
|
130
|
+
end
|
131
|
+
rescue IOError, SystemCallError
|
132
|
+
["", :error]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2023 Google LLC
|
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
|
+
# https://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
|
+
require "google/cloud/env/lazy_value"
|
18
|
+
|
19
|
+
module Google
|
20
|
+
module Cloud
|
21
|
+
class Env
|
22
|
+
##
|
23
|
+
# Access to file system contents.
|
24
|
+
#
|
25
|
+
# This is a simple class that reads the contents of objects in the file
|
26
|
+
# system, caching data so that subsequent accesses do not need to reread
|
27
|
+
# the file system.
|
28
|
+
#
|
29
|
+
# You can also "mock" the file system by providing a hash of overrides.
|
30
|
+
# If overrides are present, actual file system access is disabled; that
|
31
|
+
# is, overrides are "all or nothing".
|
32
|
+
#
|
33
|
+
# This class does not provide any controls for data size. If you read a
|
34
|
+
# large file, its contents will stay in memory for the lifetime of the
|
35
|
+
# Ruby process.
|
36
|
+
#
|
37
|
+
class FileSystem
|
38
|
+
##
|
39
|
+
# Create a file system access object with no overrides.
|
40
|
+
#
|
41
|
+
def initialize
|
42
|
+
@overrides = nil
|
43
|
+
@cache = LazyDict.new do |path, binary|
|
44
|
+
if binary
|
45
|
+
File.binread path
|
46
|
+
else
|
47
|
+
File.read path
|
48
|
+
end
|
49
|
+
rescue IOError, SystemCallError
|
50
|
+
nil
|
51
|
+
end
|
52
|
+
# This mutex protects the overrides variable. Its setting (i.e.
|
53
|
+
# whether nil or an overrides hash) will not change within a
|
54
|
+
# synchronize block.
|
55
|
+
@mutex = Thread::Mutex.new
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# Read the given file from the file system and return its contents.
|
60
|
+
#
|
61
|
+
# @param path [String] The path to the file.
|
62
|
+
# @param binary [boolean] Whether to read in binary mode. Defaults to
|
63
|
+
# false. This must be consistent across multiple requests for the
|
64
|
+
# same path; if it is not, an error will be raised.
|
65
|
+
# @return [String] if the file exists.
|
66
|
+
# @return [nil] if the file does not exist.
|
67
|
+
#
|
68
|
+
def read path, binary: false
|
69
|
+
result = false
|
70
|
+
@mutex.synchronize do
|
71
|
+
result = @overrides[path] if @overrides
|
72
|
+
end
|
73
|
+
result = @cache.get(path, binary) if result == false
|
74
|
+
if result && binary != (result.encoding == Encoding::ASCII_8BIT)
|
75
|
+
raise IOError, "binary encoding flag mismatch"
|
76
|
+
end
|
77
|
+
result
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# The overrides hash, or nil if overrides are not present.
|
82
|
+
# The hash maps paths to contents of the file at that path.
|
83
|
+
#
|
84
|
+
# @return [Hash{String => String},nil]
|
85
|
+
#
|
86
|
+
attr_reader :overrides
|
87
|
+
|
88
|
+
##
|
89
|
+
# Set the overrides hash. You can either provide a hash of file paths
|
90
|
+
# to content, or nil to disable overrides. If overrides are present,
|
91
|
+
# actual filesystem access is disabled; overrides are "all or nothing".
|
92
|
+
#
|
93
|
+
# @param new_overrides [Hash{String => String},nil]
|
94
|
+
#
|
95
|
+
def overrides= new_overrides
|
96
|
+
@mutex.synchronize do
|
97
|
+
@overrides = new_overrides
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
##
|
102
|
+
# Run the given block with the overrides replaced with the given hash
|
103
|
+
# (or nil to disable overrides in the block). The original overrides
|
104
|
+
# setting is restored at the end of the block. This is used for
|
105
|
+
# debugging/testing/mocking.
|
106
|
+
#
|
107
|
+
# @param temp_overrides [nil,Hash{String => String}]
|
108
|
+
#
|
109
|
+
def with_overrides temp_overrides
|
110
|
+
old_overrides = @overrides
|
111
|
+
begin
|
112
|
+
@mutex.synchronize do
|
113
|
+
@overrides = temp_overrides
|
114
|
+
end
|
115
|
+
yield
|
116
|
+
ensure
|
117
|
+
@mutex.synchronize do
|
118
|
+
@overrides = old_overrides
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|