class Mongo::Server::AppMetadata::Environment
Implements the logic from the handshake spec, for deducing and reporting the current FaaS environment in which the program is executing.
@api private
Constants
- COERCIONS
Describes how to coerce values of the specified type.
- DISCRIMINATORS
The mapping that determines which FaaS environment is active, based on which environment variable(s) are present.
- 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.
- MAXIMUM_VALUE_LENGTH
This value is not explicitly specified in the spec, only implied to be less than 512.
Attributes
@return [ String | nil ] the error message explaining why a valid
FaaS environment was not detected, or nil if no error occurred.
@note These error messagess are not to be propogated to the
user; they are intended only for troubleshooting and debugging.)
@return [ Hash | nil ] the fields describing the detected FaaS
environment.
@return [ String | nil ] the name of the FaaS environment that was
detected, or nil if no valid FaaS environment was detected.
Public Class Methods
Create a new AppMetadata::Environment
object, initializing it from the current ENV variables. If no FaaS environment is detected, or if the environment contains invalid or contradictory state, it will be initialized with {{name}} set to {{nil}}.
# File lib/mongo/server/app_metadata/environment.rb, line 104 def initialize @error = nil @name = detect_environment populate_fields rescue TooManyEnvironments => e self.error = "too many environments detected: #{e.message}" rescue MissingVariable => e self.error = "missing environment variable: #{e.message}" rescue TypeMismatch => e self.error = e.message rescue ValueTooLong => e self.error = "value for #{e.message} is too long" end
Public Instance Methods
Queries whether the current environment is a valid AWS Lambda environment.
@return [ true | false ] whether the environment is a AWS Lambda
environment or not.
# File lib/mongo/server/app_metadata/environment.rb, line 131 def aws? @name == 'aws.lambda' end
Queries whether the current environment is a valid Azure environment.
@return [ true | false ] whether the environment is a Azure
environment or not.
# File lib/mongo/server/app_metadata/environment.rb, line 140 def azure? @name == 'azure.func' end
Queries whether the current environment is a valid FaaS environment.
@return [ true | false ] whether the environment is a FaaS
environment or not.
# File lib/mongo/server/app_metadata/environment.rb, line 122 def faas? @name != nil end
Queries whether the current environment is a valid GCP environment.
@return [ true | false ] whether the environment is a GCP
environment or not.
# File lib/mongo/server/app_metadata/environment.rb, line 149 def gcp? @name == 'gcp.func' end
Compiles the detected environment information into a Hash. It will always include a {{name}} key, but may include other keys as well, depending on the detected FaaS environment. (See the handshake spec for details.)
@return [ Hash ] the detected environment information.
# File lib/mongo/server/app_metadata/environment.rb, line 168 def to_h fields.merge(name: name) end
Queries whether the current environment is a valid Vercel environment.
@return [ true | false ] whether the environment is a Vercel
environment or not.
# File lib/mongo/server/app_metadata/environment.rb, line 158 def vercel? @name == 'vercel' end
Private Instance Methods
Searches the DESCRIMINATORS list to see which (if any) apply to the current environment.
@return [ String | nil ] the name of the detected FaaS provider.
@raise [ TooManyEnvironments
] if the environment contains
discriminating variables for more than one FaaS provider.
# File lib/mongo/server/app_metadata/environment.rb, line 181 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
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.
@param [ String ] var the name of the environment variable
@return [ true | false ] if the variable describes the current
environment or not.
# File lib/mongo/server/app_metadata/environment.rb, line 203 def discriminator_matches?(var) return false unless ENV[var] disc = DISCRIMINATORS[var] return true unless disc[:pattern] disc[:pattern].match?(ENV[var]) end
Sets the error message to the given value and sets the name to nil.
@param [ String ] msg The error message to store.
# File lib/mongo/server/app_metadata/environment.rb, line 252 def error=(msg) @name = nil @error = msg end
Extracts the named variable from the environment and validates it against its declared definition.
@param [ String ] var The name of the environment variable to look
for.
@param [ Hash ] definition The definition of the field that applies
to the named variable.
@return [ Integer | String ] the validated and coerced value of the
given environment variable.
@raise [ MissingVariable
] if the environment does not include a
variable required by the current FaaS provider.
@raise [ ValueTooLong
] if a required variable is too long. @raise [ TypeMismatch
] if a required variable cannot be coerced to
the expected type.
# File lib/mongo/server/app_metadata/environment.rb, line 239 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
Extracts environment information from the current environment variables, based on the detected FaaS environment. Populates the {{@fields}} instance variable.
# File lib/mongo/server/app_metadata/environment.rb, line 215 def populate_fields return unless name @fields = FIELDS[name].each_with_object({}) do |(var, defn), fields| fields[defn[:field]] = extract_field(var, defn) end end