Documentation
¶
Overview ¶
Package liquid contains the API specification for LIQUID (the Limes Interface for Quota and Usage Interrogation and Discovery).
Limes expects OpenStack services to expose this interface either natively or through an adapter. The interface allows Limes to retrieve quota and usage data, and optionally capacity data, from the respective OpenStack service. Limes will also use the interface to set quota within the service.
Naming conventions ¶
Throughout this document:
- "LIQUID" (upper case) refers to the REST interface defined by this document.
- "A liquid" (lower case) refers to a server implementing LIQUID.
- "The liquid's service" refers to the OpenStack service that the liquid is a part of or connected to.
Each liquid provides access to one or more resources. A resource is any countable or measurable kind of entity managed by the liquid's service.
Limes discovers liquids through the Keystone service catalog. Each liquid should be registered there with a service type that has the prefix "liquid-". If a liquid uses vendor-specific APIs to interact with its service, its service type should include the vendor name.
Inside a resource: Usage, quota, capacity, overcommit ¶
All resources report a usage value for each Keystone project. This describes how much of the resource is used by objects created within the project. For example, the usage for the compute resource "cores" is the sum of all vCPUs allocated to each VM in that project.
Some resources maintain a quota value for each Keystone project. If so, the usage value must be meaningfully connected to the quota value: Provisioning of new assets shall be rejected with "quota exceeded" if and only if usage would exceed quota afterwards.
Some resources report a capacity value that applies to the entire OpenStack deployment. For example, the capacity for the compute resource "cores" would be the total amount of CPU cores available across all hypervisors.
This capacity value, as it is reported by the liquid, is also called "raw capacity". Limes may be configured to apply an "overcommit factor" to obtain an "effective capacity". For example, the compute resource "cores" is often overcommitted because most users do not put 100% load on their VMs all the time. In this case, quota and usage values are in terms of effective capacity, even though the capacity value is in terms of raw capacity.
Capacity and usage may be AZ-aware, in which case one value will be reported per availability zone (AZ). Quota is not modelled as AZ-aware since there are no OpenStack services that support AZ-aware quota at this time.
Structure ¶
LIQUID is structured as a REST-like HTTP API akin to those of the various OpenStack services. Like with any other OpenStack API, the client (i.e. Limes) authenticates to the liquid by providing its Keystone token in the HTTP header "X-Auth-Token".
Each individual endpoint is documented in a section of this docstring whose title starts with "Endpoint:". Unless noted otherwise, a liquid must implement all documented endpoints. The full URL of the endpoint is obtained by appending the subpath from the section header to the liquid's base URL from the Keystone service catalog.
The documentation for an endpoint may refer to a request body being expected or a response body being generated on success. In all such cases, the request or response body will be encoded as "Content-Type: application/json". The structure of the payload must conform to the referenced Go type.
When producing a successful response, the status code shall be 200 (OK) unless noted otherwise. When producing an error response (with a status code between 400 and 599), the liquid shall include a response body of "Content-Type: text/plain" to indicate the error.
Metrics ¶
While measuring quota, usage and capacity on behalf of Limes, liquids may obtain other metrics that may be useful to report to the OpenStack operator. LIQUID offers a facility to report metrics like this to Limes as part of the regular quota/usage and capacity reports. These metrics will be stored in the Limes database and then collectively forwarded to a metrics database like Prometheus. This delivery method is designed to ensure that liquids can be operated without their own persistent storage.
LIQUID structures metrics in the same way as the OpenMetrics format used by Prometheus:
- A "metric" is a floating-point-valued measurement with an optional set of labels. A label set is a map of string keys to string values.
- A "metric family" is a named set of metrics where the labelset of each metric must have the same keys, but a distinct set of values.
Endpoint: GET /v1/info ¶
Returns information about the OpenStack service and the resources available within it.
- On success, the response body payload must be of type ServiceInfo.
Endpoint: POST /v1/report-capacity ¶
Reports available capacity across all resources of this service.
- The request body payload must be of type ServiceCapacityRequest.
- On success, the response body payload must be of type ServiceCapacityReport.
Endpoint: POST /v1/projects/:uuid/report-usage ¶
Reports usage data (as well as applicable quotas) within a project across all resources of this service.
- The ":uuid" parameter in the request path must refer to a project ID known to Keystone.
- The request body payload must be of type ServiceUsageRequest.
- On success, the response body payload must be of type ServiceUsageReport.
Endpoint: PUT /v1/projects/:uuid/quota ¶
Updates quota within a project across all resources of this service.
- The ":uuid" parameter in the request path must refer to a project ID known to Keystone.
- The request body payload must be of type ServiceQuotaRequest.
- On success, the response body shall be empty and status 204 (No Content) shall be returned.
Index ¶
- func InAnyAZ[T any](value T) map[AvailabilityZone]*T
- type AZResourceCapacityReport
- type AZResourceUsageReport
- type AvailabilityZone
- type Metric
- type MetricFamilyInfo
- type MetricName
- type MetricType
- type OvercommitFactor
- type ResourceCapacityReport
- type ResourceDemand
- type ResourceDemandInAZ
- type ResourceInfo
- type ResourceName
- type ResourceQuotaRequest
- type ResourceUsageReport
- type ServiceCapacityReport
- type ServiceCapacityRequest
- type ServiceInfo
- type ServiceQuotaRequest
- type ServiceUsageReport
- type ServiceUsageRequest
- type Subcapacity
- type SubcapacityBuilder
- type Subresource
- type SubresourceBuilder
- type Unit
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func InAnyAZ ¶
func InAnyAZ[T any](value T) map[AvailabilityZone]*T
InAnyAZ is a convenience constructor for the PerAZ fields of ResourceCapacityReport and ResourceUsageReport. It can be used for non-AZ-aware resources. The provided report will be placed under the AvailabilityZoneAny key.
Types ¶
type AZResourceCapacityReport ¶
type AZResourceCapacityReport struct {
Capacity uint64 `json:"capacity"`
// How much of the Capacity is used, or null if no usage data is available.
//
// This should only be reported if the service has an efficient way to obtain this number from the backend.
// If you can only fill this by summing up usage across all projects, don't; Limes can already do that.
// This is intended for consistency checks and to estimate how much usage cannot be attributed to OpenStack projects.
// For example, for compute, this would allow estimating how many VMs are not managed by Nova.
Usage *uint64 `json:"usage,omitempty"`
// Only filled if the resource is able to report subcapacities in a useful way.
Subcapacities []Subcapacity `json:"subcapacities,omitempty"`
}
AZResourceCapacityReport contains capacity data for a resource in a single AZ. It appears in type ResourceCapacityReport.
type AZResourceUsageReport ¶
type AZResourceUsageReport struct {
// The amount of usage for this resource.
Usage uint64 `json:"usage"`
// The amount of physical usage for this resource.
// Only reported if this notion makes sense for the particular resource.
//
// For example, consider the Manila resource "share_capacity".
// If a project has 5 shares, each with 10 GiB size and each containing 1 GiB data, then Usage = 50 GiB and PhysicalUsage = 5 GiB.
// It is not allowed to report 5 GiB as Usage in this situation, since the 50 GiB value is used when judging whether the Quota fits.
PhysicalUsage *uint64 `json:"physicalUsage,omitempty"`
// Only filled if the resource is able to report subresources for this usage in a useful way.
Subresources []Subresource `json:"subresources,omitempty"`
}
AZResourceUsageReport contains usage data for a resource in a single project and AZ. It appears in type ResourceUsageReport.
func (AZResourceUsageReport) PrepareForBreakdownInto ¶
func (r AZResourceUsageReport) PrepareForBreakdownInto(allAZs []AvailabilityZone) map[AvailabilityZone]*AZResourceUsageReport
PrepareForBreakdownInto is a convenience constructor for the PerAZ field of ResourceUsageReport. It builds a map with zero-valued entries for all of the named AZs. Furthermore, if the provided AZ report contains nonzero usage, it is placed in the AvailabilityZoneUnknown key.
This constructor can be used when the total usage data is reported without AZ awareness. An AZ breakdown can later be added with the AddLocalizedUsage() method of ResourceUsageReport.
type AvailabilityZone ¶
type AvailabilityZone string
AvailabilityZone is the name of an availability zone. Some special values are enumerated below.
const ( // AvailabilityZoneAny marks values that are not bound to a specific AZ. AvailabilityZoneAny AvailabilityZone = "any" // AvailabilityZoneUnknown marks values that are bound to an unknown AZ. AvailabilityZoneUnknown AvailabilityZone = "unknown" )
type Metric ¶
type Metric struct {
Value float64 `json:"v"`
// This label set does not include keys to avoid redundant encoding.
// The slice must be of the same length as the LabelKeys slice in the respective MetricFamilyInfo instance in type ServiceInfo.
// Each label value is implied to belong to the label key with the same slice index.
// For example, LabelKeys = ["name","location"] and LabelValues = ["author","work"] represents the label set {name="author",location="work"}.
LabelValues []string `json:"l"`
}
Metric is a metric. This type appears in type ServiceCapacityReport. For more information, please refer to the "Metrics" section of the package documentation.
Because reports can include very large numbers of Metric instances, this type uses a compact serialization to improve efficiency.
type MetricFamilyInfo ¶
type MetricFamilyInfo struct {
// The metric type.
// The most common values are MetricTypeGauge and MetricTypeCounter.
Type MetricType `json:"type"`
// A brief description of the metric family for human consumption.
// Should be short enough to be used as a tooltip.
Help string `json:"help"`
// All labels that will be present on each metric in this family.
LabelKeys []string `json:"labelKeys"`
}
MetricFamilyInfo describes a metric family. This type appears in type ServiceInfo. For more information, please refer to the "Metrics" section of the package documentation.
type MetricName ¶
type MetricName string
MetricName is the name of a metric family. For more information, please refer to the "Metrics" section of the package documentation.
type MetricType ¶
type MetricType string
MetricType is an enum. For more information, please refer to the "Metrics" section of the package documentation.
const ( MetricTypeUnknown MetricType = "unknown" MetricTypeGauge MetricType = "gauge" MetricTypeCounter MetricType = "counter" MetricTypeStateset MetricType = "stateset" MetricTypeInfo MetricType = "info" MetricTypeHistogram MetricType = "histogram" MetricTypeGaugeHistogram MetricType = "gaugehistogram" MetricTypeSummary MetricType = "summary" )
type OvercommitFactor ¶
type OvercommitFactor float64
OvercommitFactor is the ratio between raw and effective capacity of a resource. It appears in type ResourceDemand.
In its methods, the zero value behaves as 1, meaning that no overcommit is taking place.
func (OvercommitFactor) ApplyInReverseTo ¶
func (f OvercommitFactor) ApplyInReverseTo(capacity uint64) uint64
ApplyInReverseTo turns the given effective capacity back into a raw capacity.
func (OvercommitFactor) ApplyInReverseToDemand ¶
func (f OvercommitFactor) ApplyInReverseToDemand(demand ResourceDemandInAZ) ResourceDemandInAZ
ApplyInReverseToDemand is a shorthand for calling ApplyInReverseTo() on all fields of a ResourceDemand, thus turning all values initially given in terms of effective capacity into the corresponding raw capacity.
func (OvercommitFactor) ApplyTo ¶
func (f OvercommitFactor) ApplyTo(rawCapacity uint64) uint64
ApplyTo converts a raw capacity into an effective capacity.
type ResourceCapacityReport ¶
type ResourceCapacityReport struct {
// For non-AZ-aware resources, the only entry shall be for AvailabilityZoneAny.
// Use func InAnyAZ to quickly construct a suitable structure.
//
// For AZ-aware resources, there shall be an entry for each AZ mentioned in ServiceCapacityRequest.AllAZs.
// Reports for AZ-aware resources may also include an entry for AvailabilityZoneUnknown as needed.
PerAZ map[AvailabilityZone]*AZResourceCapacityReport `json:"perAZ"`
}
ResourceCapacityReport contains capacity data for a resource. It appears in type ServiceCapacityReport.
type ResourceDemand ¶
type ResourceDemand struct {
// Demand values are provided in terms of effective capacity.
// This factor can be applied to them in reverse to obtain values in terms of raw capacity.
OvercommitFactor OvercommitFactor `json:"overcommitFactor,omitempty"`
// The actual demand values are AZ-aware.
// For non-AZ-aware resources, the only entry will be for AvailabilityZoneAny.
PerAZ map[AvailabilityZone]ResourceDemandInAZ `json:"perAZ"`
}
ResourceDemand contains demand statistics for a resource. It appears in type ServiceCapacityRequest.
This is used when a liquid needs to be able to reshuffle capacity between different resources based on actual user demand.
type ResourceDemandInAZ ¶
type ResourceDemandInAZ struct {
// Usage counts all existing usage.
Usage uint64 `json:"usage"`
// UnusedCommitments counts all commitments that are confirmed but not covered by existing usage.
UnusedCommitments uint64 `json:"unusedCommitments"`
// PendingCommitments counts all commitments that should be confirmed by now, but are not.
PendingCommitments uint64 `json:"pendingCommitments"`
}
ResourceDemandInAZ contains demand statistics for a resource in a single AZ. It appears in type ResourceDemand.
The fields are ordered in descending priority. All values are in terms of effective capacity, and are sums over all OpenStack projects.
type ResourceInfo ¶
type ResourceInfo struct {
// If omitted or empty, the resource is "countable" and any quota or usage values describe a number of objects.
// If non-empty, the resource is "measured" and quota or usage values are measured in the given unit.
// For example, the compute resource "cores" is countable, but the compute resource "ram" is measured, usually in MiB.
Unit Unit `json:"unit,omitempty"`
// Whether the liquid reports capacity for this resource on the cluster level.
HasCapacity bool `json:"hasCapacity"`
// Whether Limes needs to include demand statistics for this resource in its requests for a capacity report.
NeedsResourceDemand bool `json:"needsResourceDemand"`
// Whether the liquid reports quota for this resource on the project level.
// If false, only usage is reported on the project level.
// Limes will abstain from maintaining quota on such resources.
HasQuota bool `json:"hasQuota"`
}
ResourceInfo describes a resource that a liquid's service provides. This type appears in type ServiceInfo.
type ResourceName ¶
type ResourceName string
ResourceName identifies a resource within a service. This type is used to distinguish resource names from other types of string values in function signatures.
type ResourceQuotaRequest ¶
type ResourceQuotaRequest struct {
Quota uint64 `json:"quota"`
}
ResourceQuotaRequest contains the new quota value for a single resource. It appears in type ServiceQuotaRequest.
type ResourceUsageReport ¶
type ResourceUsageReport struct {
// If true, this project is forbidden from accessing this resource.
// This has two consequences:
// - If the resource has quota, Limes will never try to assign quota for this resource to this project.
// - If the project has no usage in this resource, Limes will hide this resource from project reports.
Forbidden bool `json:"forbidden"`
// This shall be null if and only if the resource is declared with "HasQuota = false".
// A negative value, usually -1, indicates "infinite quota" (i.e., the absence of a quota).
Quota *int64 `json:"quota,omitempty"`
// For non-AZ-aware resources, the only entry shall be for AvailabilityZoneAny.
// Use func InAnyAZ to quickly construct a suitable structure.
//
// For AZ-aware resources, there shall be an entry for each AZ mentioned in ServiceUsageRequest.AllAZs.
// Reports for AZ-aware resources may also include an entry for AvailabilityZoneUnknown as needed.
// When starting from a non-AZ-aware usage number that is later broken down with AZ-aware data, use func PrepareForBreakdownInto.
PerAZ map[AvailabilityZone]*AZResourceUsageReport `json:"perAZ"`
}
ResourceUsageReport contains usage data for a resource in a single project. It appears in type ServiceUsageReport.
func (*ResourceUsageReport) AddLocalizedUsage ¶
func (r *ResourceUsageReport) AddLocalizedUsage(az AvailabilityZone, usage uint64)
AddLocalizedUsage subtracts the given `usage from AvailabilityZoneUnknown (if any) and adds it to the given AZ instead.
This is used when breaking down a usage total reported by a non-AZ-aware API by iterating over AZ-localized objects. The hope is that the sum of usage of the AZ-localized objects matches the reported usage total. If this is the case, the entry for AvailabilityZoneUnknown will be removed entirely once it reaches zero usage.
type ServiceCapacityReport ¶
type ServiceCapacityReport struct {
// The same version number that is reported in the Version field of a GET /v1/info response.
// This is used to signal to Limes to refetch GET /v1/info after configuration changes.
InfoVersion int64 `json:"infoVersion"`
// Must contain an entry for each resource that was declared in type ServiceInfo with "HasCapacity = true".
Resources map[ResourceName]*ResourceCapacityReport `json:"resources"`
// Must contain an entry for each metric family that was declared for capacity metrics in type ServiceInfo.
Metrics map[MetricName][]Metric `json:"metrics"`
}
ServiceCapacityReport is the response payload format for POST /v1/report-capacity.
type ServiceCapacityRequest ¶
type ServiceCapacityRequest struct {
// All AZs known to Limes.
// Many liquids need this information to ensure that:
// - AZ-aware capacity is reported for all known AZs, and
// - capacity belonging to an invalid AZ is grouped into AvailabilityZoneUnknown.
// Limes provides this list here to reduce the number of places where this information needs to be maintained manually.
AllAZs []AvailabilityZone `json:"allAZs"`
// Must contain an entry for each resource that was declared in type ServiceInfo with "NeedsResourceDemand = true".
DemandByResource map[ResourceName]ResourceDemand `json:"demandByResource"`
}
ServiceCapacityRequest is the request payload format for POST /v1/report-capacity.
type ServiceInfo ¶
type ServiceInfo struct {
// This version number shall be increased whenever any part of the ServiceInfo changes.
//
// The metadata version is also reported on most other API responses.
// Limes uses this version number to discover when the metadata has changed and needs to be queried again.
//
// There is no prescribed semantics to the value of the version number, except that:
// - Changes in ServiceInfo must lead to a monotonic increase of the Version.
// - If the contents of ServiceInfo do not change, the Version too shall not change.
//
// Our recommendation is to use the UNIX timestamp of the most recent change.
// If you run multiple replicas of the liquid, take care to ensure that they agree on the Version value.
Version int64 `json:"version"`
// Info for each resource that this service provides.
Resources map[ResourceName]ResourceInfo `json:"resources"`
// Info for each metric family that is included in a response to a query for cluster capacity.
CapacityMetricFamilies map[MetricName]MetricFamilyInfo `json:"capacityMetricFamilies"`
// Info for each metric family that is included in a response to a query for project quota and usage.
UsageMetricFamilies map[MetricName]MetricFamilyInfo `json:"usageMetricFamilies"`
}
ServiceInfo is the response payload format for GET /v1/info.
type ServiceQuotaRequest ¶
type ServiceQuotaRequest struct {
Resources map[ResourceName]ResourceQuotaRequest `json:"resources"`
}
ServiceQuotaRequest is the request payload format for PUT /v1/projects/:uuid/quota.
type ServiceUsageReport ¶
type ServiceUsageReport struct {
// The same version number that is reported in the Version field of a GET /v1/info response.
// This is used to signal to Limes to refetch GET /v1/info after configuration changes.
InfoVersion int64 `json:"infoVersion"`
// Must contain an entry for each resource that was declared in type ServiceInfo.
Resources map[ResourceName]*ResourceUsageReport `json:"resources"`
// Must contain an entry for each metric family that was declared for usage metrics in type ServiceInfo.
Metrics map[MetricName][]Metric `json:"metrics"`
}
ServiceUsageReport is the response payload format for POST /v1/projects/:uuid/report-usage.
type ServiceUsageRequest ¶
type ServiceUsageRequest struct {
// All AZs known to Limes.
// Many liquids need this information to ensure that:
// - AZ-aware usage is reported for all known AZs, and
// - usage belonging to an invalid AZ is grouped into AvailabilityZoneUnknown.
// Limes provides this list here to reduce the number of places where this information needs to be maintained manually.
AllAZs []AvailabilityZone `json:"allAZs"`
}
ServiceUsageRequest is the request payload format for POST /v1/projects/:uuid/report-usage.
type Subcapacity ¶
type Subcapacity struct {
// A machine-readable unique identifier for this subcapacity, if there is one.
ID string `json:"id,omitempty"`
// A human-readable unique identifier for this subcapacity, if there is one.
Name string `json:"name,omitempty"`
// The amount of capacity in this subcapacity.
Capacity uint64 `json:"capacity"`
// How much of the Capacity is used, or null if no usage data is available.
Usage *uint64 `json:"usage,omitempty"`
// Additional resource-specific attributes.
// This must be shaped like a map[string]any, but is typed as a raw JSON message.
// Limes does not touch these attributes and will just pass them on into its users without deserializing it at all.
Attributes json.RawMessage `json:"attributes,omitempty"`
}
Subcapacity describes a distinct chunk of capacity for a resource within an AZ. It appears in type AZResourceCapacityReport.
A service will only report subcapacities for such resources where there is a useful substructure to report. For example:
- Nova can report its hypervisors as subcapacities of the "cores" and "ram" resources.
- Cinder can report its storage pools as subcapacities of the "capacity" resource.
The required fields are "Capacity" and at least one of "ID" or "Name".
There is no guarantee that the Capacity values of all subcapacities sum up to the total capacity of the resource. For example, some subcapacities may be excluded from new provisioning. The capacity calculation could then take this into account and exclude unused capacity from the total.
type SubcapacityBuilder ¶
type SubcapacityBuilder[A any] struct { ID string Name string Capacity uint64 Usage *uint64 Attributes A }
SubcapacityBuilder is a helper type for building Subcapacity values. If the Attributes in a subcapacity are collected over time, it might be more convenient to have them accessible as a structured type. Once assembly is complete, the provided methods can be used to obtain the final Subcapacity value.
func (SubcapacityBuilder[A]) Finalize ¶
func (b SubcapacityBuilder[A]) Finalize() (Subcapacity, error)
Finalize converts this SubcapacityBuilder into a Subcapacity by serializing the Attributes field to JSON. If an error is returned, it is from the json.Marshal() step.
type Subresource ¶
type Subresource struct {
// A machine-readable unique identifier for this subresource, if there is one.
ID string `json:"id,omitempty"`
// A human-readable identifier for this subresource, if there is one.
// Must be unique at least within its project.
Name string `json:"name,omitempty"`
// Must be null for counted resources (for which each subresource must be one of the things that is counted).
// Must be non-null for measured resources, and contain the subresource's size in terms of the resource's unit.
Usage *uint64 `json:"usage,omitempty"`
// Additional resource-specific attributes.
// This must be shaped like a map[string]any, but is typed as a raw JSON message.
// Limes does not touch these attributes and will just pass them on into its users without deserializing it at all.
Attributes json.RawMessage `json:"attributes,omitempty"`
}
Subresource describes a distinct chunk of usage for a resource within a project and AZ. It appears in type AZResourceUsageReport.
A service will only report subresources for such resources where there is a useful substructure to report. For example, in the Nova resource "instances", each instance is a subresource.
The required fields are "Size" (only for measured resources) and at least one of "ID" or "Name".
type SubresourceBuilder ¶
SubresourceBuilder is a helper type for building Subresource values. If the Attributes in a subresource are collected over time, it might be more convenient to have them accessible as a structured type. Once assembly is complete, the provided methods can be used to obtain the final Subresource value.
func (SubresourceBuilder[A]) Finalize ¶
func (b SubresourceBuilder[A]) Finalize() (Subresource, error)
Finalize converts this SubresourceBuilder into a Subresource by serializing the Attributes field to JSON. If an error is returned, it is from the json.Marshal() step.
type Unit ¶
type Unit string
Unit enumerates allowed values for the unit a resource's quota/usage is measured in.
const ( // UnitNone is used for countable (rather than measurable) resources. UnitNone Unit = "" // UnitBytes is exactly that. UnitBytes Unit = "B" // UnitKibibytes is exactly that. UnitKibibytes Unit = "KiB" // UnitMebibytes is exactly that. UnitMebibytes Unit = "MiB" // UnitGibibytes is exactly that. UnitGibibytes Unit = "GiB" // UnitTebibytes is exactly that. UnitTebibytes Unit = "TiB" // UnitPebibytes is exactly that. UnitPebibytes Unit = "PiB" // UnitExbibytes is exactly that. UnitExbibytes Unit = "EiB" // UnitUnspecified is used as a placeholder when the unit is not known. UnitUnspecified Unit = "UNSPECIFIED" )
func (Unit) Base ¶
Base returns the base unit of this unit. For units defined as a multiple of another unit, that unit is the base unit. Otherwise, the same unit and a multiple of 1 is returned.
func (*Unit) UnmarshalJSON ¶
UnmarshalJSON implements the json.Unmarshaler interface. This method validates that the named unit actually exists.
func (*Unit) UnmarshalYAML
deprecated
UnmarshalYAML implements the yaml.Unmarshaler interface. This method validates that the named unit actually exists.
Deprecated: This provides backwards-compatibility with existing YAML-based config file formats in Limes which will be replaced by JSON eventually.