Class: Mongo::Server::AppMetadata::Environment Private
Relationships & Source Files | |
Namespace Children | |
Exceptions:
| |
Inherits: | Object |
Defined in: | lib/mongo/server/app_metadata/environment.rb |
Overview
Implements the logic from the handshake spec, for deducing and reporting the current environment in which the program is executing.
This includes FaaS environment checks, as well as checks for the presence of a container (Docker) and/or orchestrator (Kubernetes).
Constant Summary
-
COERCIONS =
Describes how to coerce values of the specified type.
{ string: ->(v) { String(v) }, integer: ->(v) { Integer(v) } }.freeze
-
DISCRIMINATORS =
The mapping that determines which FaaS environment is active, based on which environment variable(s) are present.
{ 'AWS_EXECUTION_ENV' => { pattern: /^AWS_Lambda_/, name: 'aws.lambda' }, 'AWS_LAMBDA_RUNTIME_API' => { name: 'aws.lambda' }, 'FUNCTIONS_WORKER_RUNTIME' => { name: 'azure.func' }, 'K_SERVICE' => { name: 'gcp.func' }, 'FUNCTION_NAME' => { name: 'gcp.func' }, 'VERCEL' => { name: 'vercel' }, }.freeze
-
DOCKERENV_PATH =
The name and location of the .dockerenv file that will signal the presence of Docker.
'/.dockerenv'
-
FIELDS =
Describes which fields are required for each FaaS environment, along with their expected types, and how they should be named in the handshake document.
{ 'aws.lambda' => { 'AWS_REGION' => { field: :region, type: :string }, 'AWS_LAMBDA_FUNCTION_MEMORY_SIZE' => { field: :memory_mb, type: :integer }, }, 'azure.func' => {}, 'gcp.func' => { 'FUNCTION_MEMORY_MB' => { field: :memory_mb, type: :integer }, 'FUNCTION_TIMEOUT_SEC' => { field: :timeout_sec, type: :integer }, 'FUNCTION_REGION' => { field: :region, type: :string }, }, 'vercel' => { 'VERCEL_REGION' => { field: :region, type: :string }, }, }.freeze
-
MAXIMUM_VALUE_LENGTH =
This value is not explicitly specified in the spec, only implied to be less than 512.
500
Class Method Summary
-
.new ⇒ Environment
constructor
Internal use only
Create a new
Environment
object, initializing it from the current ENV variables.
Instance Attribute Summary
-
#aws? ⇒ true | false
readonly
Internal use only
Queries whether the current environment is a valid AWS Lambda environment.
-
#azure? ⇒ true | false
readonly
Internal use only
Queries whether the current environment is a valid Azure environment.
- #error ⇒ String | nil rw Internal use only
-
#faas? ⇒ true | false
readonly
Internal use only
Queries whether the current environment is a valid FaaS environment.
- #fields ⇒ Hash | nil readonly Internal use only
-
#gcp? ⇒ true | false
readonly
Internal use only
Queries whether the current environment is a valid GCP environment.
- #name ⇒ String | nil readonly Internal use only
-
#present? ⇒ true | false
readonly
Internal use only
Queries whether any environment information was able to be detected.
-
#vercel? ⇒ true | false
readonly
Internal use only
Queries whether the current environment is a valid Vercel environment.
-
#docker_present? ⇒ Boolean
readonly
private
Internal use only
Checks for the existence of a .dockerenv in the root directory.
-
#error=(msg)
rw
private
Internal use only
Sets the error message to the given value and sets the name to nil.
-
#kubernetes_present? ⇒ Boolean
readonly
private
Internal use only
Checks for the presence of a non-empty KUBERNETES_SERVICE_HOST environment variable.
Instance Method Summary
-
#container ⇒ Hash | nil
Internal use only
Queries the detected container information.
-
#to_h ⇒ Hash
Internal use only
Compiles the detected environment information into a Hash.
-
#detect_container
private
Internal use only
Looks for the presence of a container.
-
#detect_environment ⇒ String | nil
private
Internal use only
Searches the DESCRIMINATORS list to see which (if any) apply to the current environment.
-
#discriminator_matches?(var) ⇒ true | false
private
Internal use only
Determines whether the named environment variable exists, and (if a pattern has been declared for that descriminator) whether the pattern matches the value of the variable.
-
#dockerenv_path
private
Internal use only
Implementing this as a method so that it can be mocked in tests, to test the presence or absence of Docker.
-
#extract_field(var, definition) ⇒ Integer | String
private
Internal use only
Extracts the named variable from the environment and validates it against its declared definition.
-
#populate_faas_fields
private
Internal use only
Extracts environment information from the current environment variables, based on the detected FaaS environment.
Instance Attribute Details
#aws? ⇒ true
| false
(readonly)
Queries whether the current environment is a valid AWS Lambda environment.
# File 'lib/mongo/server/app_metadata/environment.rb', line 157
def aws? @name == 'aws.lambda' end
#azure? ⇒ true
| false
(readonly)
Queries whether the current environment is a valid Azure environment.
# File 'lib/mongo/server/app_metadata/environment.rb', line 166
def azure? @name == 'azure.func' end
#docker_present? ⇒ Boolean
(readonly, private)
Checks for the existence of a .dockerenv in the root directory.
# File 'lib/mongo/server/app_metadata/environment.rb', line 234
def docker_present? File.exist?(dockerenv_path) end
#error ⇒ String
| nil
(rw)
These error messagess are not to be propogated to the user; they are intended only for troubleshooting and debugging.)
# File 'lib/mongo/server/app_metadata/environment.rb', line 105
attr_reader :error
#error=(msg) (rw, private)
Sets the error message to the given value and sets the name to nil.
# File 'lib/mongo/server/app_metadata/environment.rb', line 307
def error=(msg) @name = nil @error = msg end
#faas? ⇒ true
| false
(readonly)
Queries whether the current environment is a valid FaaS environment.
# File 'lib/mongo/server/app_metadata/environment.rb', line 148
def faas? @name != nil end
#fields ⇒ Hash
| nil
(readonly)
# File 'lib/mongo/server/app_metadata/environment.rb', line 98
attr_reader :fields
#gcp? ⇒ true
| false
(readonly)
Queries whether the current environment is a valid GCP environment.
# File 'lib/mongo/server/app_metadata/environment.rb', line 175
def gcp? @name == 'gcp.func' end
#kubernetes_present? ⇒ Boolean
(readonly, private)
Checks for the presence of a non-empty KUBERNETES_SERVICE_HOST environment variable.
# File 'lib/mongo/server/app_metadata/environment.rb', line 246
def kubernetes_present? !ENV['KUBERNETES_SERVICE_HOST'].to_s.empty? end
#name ⇒ String
| nil
(readonly)
# File 'lib/mongo/server/app_metadata/environment.rb', line 94
attr_reader :name
#present? ⇒ true
| false
(readonly)
Queries whether any environment information was able to be detected.
# File 'lib/mongo/server/app_metadata/environment.rb', line 140
def present? @name || fields.any? end
#vercel? ⇒ true
| false
(readonly)
Queries whether the current environment is a valid Vercel environment.
# File 'lib/mongo/server/app_metadata/environment.rb', line 184
def vercel? @name == 'vercel' end
Instance Method Details
#container ⇒ Hash
| nil
Queries the detected container information.
# File 'lib/mongo/server/app_metadata/environment.rb', line 131
def container fields[:container] end
#detect_container (private)
Looks for the presence of a container. Currently can detect Docker (by the existence of a .dockerenv file in the root directory) and Kubernetes (by the existence of the KUBERNETES_SERVICE_HOST environment variable).
# File 'lib/mongo/server/app_metadata/environment.rb', line 222
def detect_container runtime = docker_present? && 'docker' orchestrator = kubernetes_present? && 'kubernetes' return unless runtime || orchestrator fields[:container] = {} fields[:container][:runtime] = runtime if runtime fields[:container][:orchestrator] = orchestrator if orchestrator end
#detect_environment ⇒ String
| nil
(private)
Searches the DESCRIMINATORS list to see which (if any) apply to the current environment.
# File 'lib/mongo/server/app_metadata/environment.rb', line 204
def detect_environment matches = DISCRIMINATORS.keys.select { |k| discriminator_matches?(k) } names = matches.map { |m| DISCRIMINATORS[m][:name] }.uniq # From the spec: # When variables for multiple ``client.env.name`` values are present, # ``vercel`` takes precedence over ``aws.lambda``; any other # combination MUST cause ``client.env`` to be entirely omitted. return 'vercel' if names.sort == %w[ aws.lambda vercel ] raise TooManyEnvironments, names.join(', ') if names.length > 1 names.first end
#discriminator_matches?(var) ⇒ true
| false
(private)
Determines whether the named environment variable exists, and (if a pattern has been declared for that descriminator) whether the pattern matches the value of the variable.
# File 'lib/mongo/server/app_metadata/environment.rb', line 258
def discriminator_matches?(var) return false unless ENV[var] disc = DISCRIMINATORS[var] return true unless disc[:pattern] disc[:pattern].match?(ENV[var]) end
#dockerenv_path (private)
Implementing this as a method so that it can be mocked in tests, to test the presence or absence of Docker.
# File 'lib/mongo/server/app_metadata/environment.rb', line 240
def dockerenv_path DOCKERENV_PATH end
#extract_field(var, definition) ⇒ Integer
| String
(private)
Extracts the named variable from the environment and validates it against its declared definition.
# File 'lib/mongo/server/app_metadata/environment.rb', line 294
def extract_field(var, definition) raise MissingVariable, var unless ENV[var] raise ValueTooLong, var if ENV[var].length > MAXIMUM_VALUE_LENGTH COERCIONS[definition[:type]].call(ENV[var]) rescue ArgumentError raise TypeMismatch, "#{var} must be #{definition[:type]} (got #{ENV[var].inspect})" end
#populate_faas_fields (private)
Extracts environment information from the current environment variables, based on the detected FaaS environment. Populates the {@fields
} instance variable.
#to_h ⇒ Hash
Compiles the detected environment information into a Hash.