blob: 4bd75d1dc90c654a45a77844aea25bca0ceda31d [file] [log] [blame] [view] [edit]
# Component configuration mechanisms
The [component configuration](/docs/concepts/components/configuration.md) page
introduces how components can be configured on Fuchsia, and describes different
situations that require
[component configuration][glossary.component-configuration].
This page introduces the different configuration mechanisms that Fuchsia
provides, talks about their strengths and weaknesses and provides guidance on
which mechanism to use in which situation.
## Structured configuration {#structured-configuration}
[Structured configuration][structured_config] is a modern, ergonomic, and
flexible configuration system provided by the Component Framework. Structured
configuration is integrated with many Fuchsia tools including [ffx][ffx],
[inspect][inspect], and product assembly and it should be your first choice in
most cases.
A component developer uses structured configuration by defining configuration
keys in the component's manifest, each with a name and datatype. The system
guarantees that values will be provided for all of these configuration keys when
the component is started. Libraries are auto-generated to easily read
configuration values at runtime. Components need not care what part of the
system supplied a structured configuration value and need not handle missing
configuration.
Structured configuration values can be provided through a range of different
paths, such as:
- **Package build rules**. Configuration values set by build rule are included
in the same package as the component. The configuration is fixed at build time
so can be verified during release signing.
- **Realm builder**. [Realm builder][realm_builder] integration lets tests
easily set configuration values. The two main use cases are to verify
configurable behavior and to change configuration to aid testability.
- **Product assembly**. Product assembly lets the platform define configuration
keys whose values are supplied by the product. Product integrators supply
values in their product configuration and these are built into the component
package where they can be verified during release signing.
- **Development overrides**. This [ffx tool][ffx_component_config] lets
developers change configuration at runtime on engineering builds, for example
to use pre-release features.
[RFC-0127][rfc0127] described several other ways to specify structured
configuration values, but these have not yet been built pending near-term use
cases. If your use case requires any of these features, please comment on the
tracking bug linked below for the feature:
- **Vbmeta ([https://fxbug.dev/42178359][bug.96261]**). This would let signed configuration
be modified for a release without building a new image.
- **Parent component ([https://fxbug.dev/42178351][bug.96254]**). This would let a
component specify configuration for children in a dynamic collection as it
creates those children. This requires a consistent definition of the
configuration between the two components so may only be supported between
components in the same image or package.
- **Fleet and enterprise management ([https://fxbug.dev/42055769][bug.104596])**. This
would let structured configuration be used for incremental rollouts, running
A/B experiments and enterprise policy enforcement, similar to the experiment
systems in other large platforms.
Structured configuration definition for a component is local to that component.
There is no global "configuration version" and the system does not provide
guarantees on forwards or backwards compatibility across versions of a
component — compatibility is left to the component developer. Therefore,
structured configuration is not currently suitable as a means of communication
between components that may have been built against different configuration
versions.
Structured configuration is very flexible and works in most situations, however
there are configuration problems for which structured configuration is not the
best solution:
- **Configuration values must be consistent across a large number of different components**.
Structured configuration keys are defined locally in a component's manifest.
Product assembly may be used to set consistent configuration values across a
few different components but this brings maintainability challenges and does
not scale well. If configuration values must be consistent across a large
number of different components,
[package-based configuration](#package-based-configuration) or
[service-based configuration](#service-based-configuration) are better
solutions.
- **Large configuration**. When configuration gets very large, say over several
kilobytes, the tools that structured configuration provides to set and view
configuration values become inconvenient. The implementation of structured
configuration does not prioritize efficient handling of large values.
[Package-based configuration](#package-based-configuration) is a better
solution for large configuration data.
- **Configuration that changes frequently at runtime**. A component receives its
structured configuration values as it launches, meaning a component instance
must be restarted to pick up new configuration.
[Service-based configuration](#service-based-configuration) is a better
solution for configuration that must change frequently at runtime.
- **Configuration that is set by end users**. Unlike developers, end users need
a user interface to control configuration. This user interface means that the
UI component, the component being configured, and the localization database
all need to agree on the definition of the configuration and therefore the
configuration must be defined centrally in some versioned artifact.
[Service-based configuration](#service-based-configuration) configuration is a
better solution for configuration that is controlled by end users.
## Package-based configuration {#package-based-configuration}
Package-based configuration supports configuration data that is fixed at release
time by building data files into a [package][glossary.package] and letting the
component read those files. The same package can be routed to several different
components and the configuration files can be arbitrarily large.
Package based configuration is generally less ergonomic than structured
configuration; the files must be manually opened and parsed, the component may
need to handle missing or malformed configuration, and there is no integration
with standard tooling to test, debug, or introspect configuration.
Package based configuration does not work well for the following problems:
- **Configuration needs to be altered at runtime**. Comment on the tracking bugs
above for dynamic configuration support in structured configuration and/or use
[service-based configuration](#service-based-configuration) instead.
There are three different variants of package-based configuration based on which
package is used to store the configuration:
### Global (aka "config_data") package configuration
A single global [`config_data`][config_data] package contains configuration data
for many different components. With the data for each component being added
using the "config_data" build rule. This global package was the only way to use
packaged-based configuration in CFv1 but it is inflexible and cumbersome in CFv2
since the config-data directory must be manually routed through the component
topology.
Users of config_data should migrate to either
[structured configuration](#structured-configuration) or
[domain](#domain-package-configuration)/[in-package](#in-package-configuration)
configuration, both of which provide better ergonomics and more flexibility.
### Domain package configuration {#domain-package-configuration}
The developers of the components in a domain can define their own configuration
data package and route its directories to the components they control. Unlike
global package configuration, this mechanism can be used across different build
systems and petals.
### In-package configuration {#in-package-configuration}
Configuration files may also be placed in the same package as the component they
configure. This ensures that the configuration will be distributed with the
component and does not require complex and brittle routing. However, it also
means that the configuration cannot be changed without repackaging the
component. More details are provided in the guide on
[providing data files to components][providing_data_files].
Packages contents are stored in [blobfs][blobfs], a content addressed file
system which de-duplicates blobs. This means if multiple packages include an
identical configuration blob, only one copy will be stored.
## Service-based configuration {#service-based-configuration}
Fuchsia components may be written to collect, maintain, and distribute
configuration data for a domain over FIDL. A good example is the Fuchsia
platform’s [settings service][settings_service] that maintains various user
settings such as the locale: the settings service maintains the state of these
user settings across power cycles and exposes `fuchsia.settings` FIDL protocols
that other components may use to read the current configuration data or request
a change in configuration data.
Service-based configuration can be very flexible and powerful but introducing a
server component is generally more work than the other options and incurs a
higher runtime cost. Service-based configuration should only be used when this
additional cost adds value.
The component can potentially use several different inputs to determine the
correct configuration. For example: business logic to validate and combine
client requests, settings collected from some server, or default configuration
values provided through some other mechanism such as structured configuration.
Service-based configuration works well when configuration must be shared across
a wide range of clients because the configuration is formally defined and
versioned by the FIDL interface used to deliver it. Service-based configuration
also works well when configuration potentially changes frequently.
Service-based configuration does not work well for the following problems:
- **Large Configuration**. Configuration is delivered by FIDL messages which are
limited by the size of a zircon channel write. Although a FIDL protocol could
work around this by splitting configuration into chunks or sending a VMO this
would harm the client simplicity and explicit definition that are
service-based configuration's strength.
[Packaged-based configuration](#package-based-configuration) is a better
solution when working with large configuration.
[glossary.component-configuration]: /docs/glossary/README.md#component-configuration
[glossary.package]: /docs/glossary/README.md#package
[bug.96260]: https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=96260
[bug.96261]: https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=96261
[bug.96254]: https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=96254
[bug.104596]: https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=104596
[rfc0127]: /docs/contribute/governance/rfcs/0127_structured_configuration.md
[blobfs]: /docs/concepts/filesystems/blobfs.md
[config_data]: config_data.md
[ffx]: https://fuchsia.dev/reference/tools/sdk/ffx
[inspect]: /docs/development/diagnostics/inspect/README.md
[realm_builder]: /docs/development/testing/components/realm_builder.md
[settings_service]: https://cs.opensource.google/fuchsia/fuchsia/+/main:src/settings/service/
[structured_config]: structured_config.md
[providing_data_files]: /docs/development/components/data.md
[ffx_component_config]: https://fuchsia.dev/reference/tools/sdk/ffx#ffx_component_config