This repository was archived by the owner on Nov 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9
WIP rfc: unified-configuration #523
Open
siddhantk232
wants to merge
7
commits into
fastn-stack:main
Choose a base branch
from
siddhantk232:rfc/unified-config
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 4 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
dfff9b3
WIP rfc: unified-configuration
siddhantk232 1409668
correct use of ds.code and note
siddhantk232 5fcd2fd
mention cli args as a way to configure + fix typos
siddhantk232 b4780c9
add configuring of deps + other sections
siddhantk232 80d924e
use kebab-case in ftd
siddhantk232 fa79f7c
remove special config types and impose restriction
siddhantk232 8d5119d
fix syntax of fastn.env
siddhantk232 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,312 @@ | ||
-- import: fastn.com/rfcs/lib | ||
-- import: fastn-community.github.io/bling/note | ||
|
||
-- lib.rfc: RFC: Unified Configuration | ||
id: unified-config | ||
status: proposal | ||
|
||
A configuration system streamlining complex settings for processors, fastn | ||
packages. It introduces: | ||
|
||
- Special Configuration types in the `fastn` namespace. | ||
- A virtual module for configuration access in userland. | ||
- Package level configuration. | ||
|
||
-- lib.motivation: | ||
|
||
Currently, `fastn` supports configuration through [environment | ||
variables](/env/), cli arguments, and in some way, through the `FASTN.ftd` | ||
file. Environment variables are good to change the behaviour of the cli or to | ||
pass secret information but it's not ideal for defining complex configuration | ||
for a framework like `fastn` which provides various configurable features like | ||
[processors](/processor/-/backend/), oauth authentication and, apps. | ||
|
||
This RFC proposes a way of dealing with configuration that is centralized and | ||
leverages the existing ability of the `fastn` cli to read environment | ||
variables. | ||
|
||
-- end: lib.motivation | ||
|
||
|
||
-- lib.detailed-design: | ||
|
||
-- ds.h2: Configuration types in `fastn.*` | ||
|
||
This contains all special configuration types defined by the fastn framework. | ||
|
||
Any configuration required by the framework will be present as a type under the | ||
`fastn` namespace. | ||
|
||
For example, `db-conn` that represents database connection information is a type | ||
under `fastn` which can be used to create variables like: | ||
|
||
-- ds.code: variable in `FASTN.ftd` of `my-package` | ||
lang: ftd | ||
|
||
\-- import: fastn | ||
|
||
\-- fastn.package: my-package | ||
|
||
\-- fastn.db-conn my-db: | ||
db_host: <some_ip> | ||
siddhantk232 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
db_user: user | ||
db_password: config.DB_PASSWORD ;; this is an environment variable | ||
db_name: user_db | ||
|
||
-- ds.markdown: | ||
|
||
A corresponding struct for `db-conn` on rust side would look like: | ||
|
||
-- ds.code: `db-conn` in rust | ||
lang: rust | ||
|
||
struct DatabaseConnInfo { | ||
db_host: String, | ||
db_user: String, | ||
db_password: String, | ||
db_name: String, | ||
} | ||
|
||
-- ds.markdown: | ||
|
||
The `fastn` namespace will also allow access to environment variables using | ||
`fast.env` function. | ||
|
||
-- ds.code: A variable that reads environment variable using `fastn.env()` | ||
lang: ftd | ||
|
||
\-- import: fastn | ||
|
||
\-- fastn.package: my-package | ||
|
||
\-- fastn.db-conn my-db: | ||
db_host: <some_ip> | ||
db_user: user | ||
db_password: fastn.env(DB_PASSWORD) \;; suggested syntax | ||
db_name: user_db | ||
|
||
-- note.note: `fastn.env()` | ||
|
||
It is a foreign function. A default value can be provided in case `DB_PASSWORD` doesn't exist: `fastn.env(DB_PASSWORD, default=admin)`. | ||
|
||
-- ds.markdown: | ||
|
||
- Some special variable names may be defined in `FASTN.ftd` file that are | ||
required by the framework. Example: The implementation of [`pg` | ||
processor](/sql/) may require the user of this processor to define a variable | ||
name `db` in their package's `FASTN.ftd` file. | ||
|
||
- Variables created using types from `fastn.*` (as well as primitive types) | ||
are normal variables that can be defined in any `.ftd` file. | ||
|
||
The virtual module (`<pkg-name>/-/config`) will handle access of variables | ||
defined in `FASTN.ftd`. | ||
|
||
-- ds.h2: `<pkg-name>/-/config` - A virtual module to assist configuration access. | ||
|
||
Add a virtual module (`<pkg-name>/-/config`) similar to existing | ||
[assets](https://fastn.com/assets) module. | ||
|
||
This module will allow access to variables defined in `FASTN.ftd` file. | ||
|
||
-- ds.code: Example | ||
lang: ftd | ||
|
||
\-- import: my-package/-/config \;; This is new! | ||
|
||
\-- import: fastn/processors as pr | ||
|
||
\-- person list people: | ||
$processor$: pr.pg | ||
use: $config.my-db \;; defined in my-package's FASTN.ftd | ||
|
||
SELECT * FROM users; | ||
|
||
-- ds.h2: Configuring dependencies and apps | ||
|
||
`FASTN.ftd` file will be central to the whole configuration system. Users can | ||
modify the behaviour of a dependency by passing variables when they're added. | ||
Example: | ||
|
||
-- ds.code: `FASTN.ftd` of test-todos | ||
lang: ftd | ||
|
||
\-- import: fastn | ||
|
||
\-- fastn.package: test-todos | ||
|
||
\;; fastn.app works in similar way | ||
\-- fastn.dependency: amitu.com/todos | ||
max-todo-per-page: 30 | ||
|
||
-- end: ds.code | ||
|
||
-- ds.markdown: | ||
|
||
The above snippet is configuring `amitu.com/todos` by modifying variables that | ||
are in its `FASTN.ftd` file. | ||
|
||
The `FASTN.ftd` of `amitu.com/todos` will look like this: | ||
|
||
-- ds.code: FASTN.ftd of amitu.com/todos | ||
lang: ftd | ||
|
||
\-- import: fastn | ||
|
||
\-- fastn.package: amitu.com/todos | ||
|
||
\-- integer max-todo-per-page: 10 \;; becomes 30 when used by test-todos | ||
|
||
\-- string sample-title: TODO App \;; this was not modified by test-todos so this stays intact | ||
|
||
-- end: ds.code | ||
|
||
-- ds.markdown: | ||
|
||
- While adding dependency, users can modify any variable defined in the | ||
`FASTN.ftd` file of the said dependency. | ||
|
||
- Any extra header value passed to `fastn.dependency` will result in an error. | ||
|
||
-- ds.h2: Optional vs. Required dependency configuration | ||
|
||
A package can create variables in `FASTN.ftd` in different ways which will | ||
dictate if they're required or optional. See the example below: | ||
|
||
-- ds.code: `FASTN.ftd` of `amitu.com/todos` | ||
lang: ftd | ||
|
||
\-- import: fastn | ||
|
||
\-- fastn.package: amitu.com/todos | ||
db: $my-db-for-dev \;; this value for db is available only when it's not used as a dependency | ||
|
||
\-- fastn.db-conn db: \;; this has no value so this will be required | ||
|
||
\-- integer max-todos: 30 \;; this has a default value so this is optional | ||
|
||
-- ds.markdown: | ||
|
||
- `db` must be defined when the package is being used, and fastn.package is one | ||
such usage! This allows for easy testing, say if I am building | ||
amitu.com/todos, I do not have to create a test app, and I can work directly | ||
in amitu.com/todos package, and my test values would be passed there. | ||
|
||
- `max-todos` is defined with a value so this doesn't have to be passed as a | ||
header when using `amitu.com/todos` as a dependency. | ||
|
||
-- ds.code: Example use of `amitu.com/todos` in `my-website` | ||
lang: ftd | ||
|
||
\-- import: fastn | ||
|
||
\-- fastn.package: my-website | ||
|
||
\-- fastn.dependency: amitu.com/todos | ||
db: $my-db \;; this is required otherwise an error will be thrown | ||
\;; max-todos is optional so we ignore this | ||
|
||
|
||
-- ds.h3: Q. Why do we allow defining config variables outside of `FASTN.ftd`? | ||
siddhantk232 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
<start of answer> | ||
|
||
Configurations are meant to modify the behaviour of the framework or an | ||
external fastn package. Even though this change in behaviour or modification in | ||
configuration of a package should happen in `FASTN.ftd` file, we should give | ||
users option to define configuration that are scoped for a single use. | ||
|
||
Consider the following example that uses the [`pg` processor](/sql/): | ||
|
||
-- ds.code: `sample.ftd` | ||
lang: ftd | ||
|
||
\-- import: fastn/processors as pr | ||
\-- import: fastn/config | ||
|
||
\-- config.db-conn temp: | ||
db_host: <some_ip> | ||
db_user: user | ||
db_password: config.DB_PASSWORD ;; this is an environment variable | ||
db_name: user_db | ||
|
||
\-- person list people: | ||
$processor$: pr.pg | ||
use: $temp | ||
|
||
SELECT * FROM users; | ||
|
||
|
||
-- note.note: Side note | ||
|
||
If the use of pg processor doesn't specify database connections information | ||
through the `use` header, the implementation of `pg` can choose to look for a | ||
default variable (say `db`) in `FASTN.ftd`. Looking into arbitrary `.ftd` file | ||
is not supported. Any rust implementation will only be able to access variables | ||
defined in `FASTN.ftd` for configuration stuff. | ||
|
||
|
||
-- ds.markdown: | ||
|
||
In summary, a processor like `pg` would say: "Pass connection information | ||
through the `use` header or it'll pick `db` variable of type `config.db-conn` | ||
from your `FASTN.ftd` file. | ||
|
||
<end of answer> | ||
|
||
|
||
-- end: lib.detailed-design | ||
|
||
|
||
-- lib.alternatives: | ||
|
||
Another way is to stick with how fastn currently reads environment variables. | ||
It's good because it keeps secret info safe in source files. But there are some | ||
downsides: | ||
|
||
- We still need a way to share settings between packages (like dependencies and | ||
apps). | ||
|
||
- People don't have a straightforward system to make their packages adjustable | ||
by the outside world. | ||
|
||
-- end: lib.alternatives | ||
|
||
|
||
-- lib.teaching-notes: | ||
|
||
- At a minimum, framework features might require users to define a variable | ||
in their FASTN.ftd file, and this process is quite straightforward to | ||
explain. | ||
|
||
- Likewise, when incorporating dependencies into FASTN.ftd, it's preferable for | ||
the documentation of the dependency to document all potential configurations. | ||
|
||
- Power users and library authors can choose to dive deep in the docs and | ||
explore how they can use the `<pkg-name>/-/config` virtual module to access | ||
variables defined in their package's `FASTN.ftd`. | ||
|
||
-- end: lib.teaching-notes | ||
|
||
-- lib.unresolved-questions: | ||
|
||
This RFC doesn't address the security concerns around this feature. Some points to consider here: | ||
|
||
- Environment variables accessed using `fastn.env()` could be leaked in client code. Example: | ||
|
||
-- ds.code: Client can print environment variables | ||
lang: ftd | ||
|
||
\-- import: fastn | ||
|
||
\-- ftd.text: $fastn.env(DB_PASSWORD) ;; this is bad | ||
|
||
-- ds.markdown: | ||
|
||
- We need some way to limit access of environment variables. | ||
|
||
|
||
-- end: lib.unresolved-questions | ||
|
||
-- end: lib.rfc | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.