-
Notifications
You must be signed in to change notification settings - Fork 126
RunConfig
as architectural boundary proposal
#2096
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2096 +/- ##
==========================================
- Coverage 48.33% 48.31% -0.02%
==========================================
Files 238 238
Lines 30034 30034
==========================================
- Hits 14518 14512 -6
- Misses 14418 14423 +5
- Partials 1098 1099 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
This change contains a design doc describing an architectural boundary at `RunConfig` level. Aim of this design doc is * listing the current responsibilities of `RunConfig` and related code (e.g. `Runner`) * propose a new split of responsibilities and a clear golang API for it * clarify what responsibilities should be moved in the respective user interfaces, e.g. CLI or Operator
b7dca4b
to
fb9c334
Compare
@claude please review this architectural proposal |
Claude finished @JAORMX's task —— View job Architectural Proposal ReviewI've reviewed the Overall AssessmentThis is a well-structured and necessary proposal that addresses real architectural concerns in ToolHive. The separation of concerns between Strengths
Areas for Improvement1. Implementation Guidance MissingThe proposal describes what should change but lacks how to achieve it. Consider adding:
2. Concrete Examples of ViolationsThe proposal would benefit from specific examples of current violations: Current problematic fields in
These should be called out explicitly as fields that violate the proposed boundary. 3. Validation Responsibility UnclearLine 75 mentions "basic validation" as a Suggested clarification:
4. Serialization Format Not SpecifiedLine 75 mentions serialization but doesn't specify:
5. Missing Discussion of
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An open question I'd like to discuss tomorrow is: Should we have information about the secret provider that's used and a key to retrieve the secret at runtime? This would make it easier to share configurations.
* **ToolHive Operator**, which is used in both Kubernetes and OpenShift | ||
* **ToolHive UI**, which internally uses APIs exposed by `thv serve` | ||
|
||
These interfaces differ in their execution environment and "quality of life" features that one might implement. For example, one obvious difference is the way configuration is accessed: CLI must both accept CLI options and read files on file system, while the Kubernetes Operator requires all parameters to be fully specified in the main CRD or into "linked" ones (e.g. `MCPToolConfig`). Another one is in config reload semantics, which must implemented in an ad-hoc fashion for CLI, while Kubernetes handles it as part of the life cycle of resources. Yet another example is the location of runtime configuration and state. The Kubernetes Operator relies on both being stored "inside the cluster", while the CLI and UI must both rely on file system, yet the configuration might be semantically equivalent. A final useful use case is exporting `RunConfig` so that the same workload can be "moved" to a different place or shipped as configuration. A similar use case is that implemented by the `thv restart` command, which fetches the serialized version of a run config to restart the workload when necessary. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's worth noting that in the UI/API case - the preference has been to specify the payload ("literal" as this doc uses) of the configuration instead of a path. This allows the payload to be constructed by a UI form.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: there's general agreement on the fact that HTTP API must not contain references to local files.
Action Item: this is a bit outside of the RunConfig
design doc, but we should document it regardless.
@@ -0,0 +1,81 @@ | |||
# `RunConfig` as Architectural Boundary |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
General comment worth noting: There are a bunch of fields in the run config right now which are only needed for backwards compatibility. We should clean those up as part of stabilization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: we have a VersionSchema
field in the RunConfig
struct, we should leverage that.
Action Item: list fields that are either no longer used or not desired anymore.
|
||
Consequences of changes to configuration parameters must be managed outside the `RunConfig` code. For example, configuration reload for the CLI must be managed within CLI commands, and not within the `Runner` or `RunConfig`. That said, `Runner`s can implement behaviors specific to their execution environment, but they must not rely on references to the "outside world" being stored in the `RunConfig`. | ||
|
||
Types exposed by `RunConfig` package should not be used for externally facing formats like HTTP API if not for trivial cases. In case diverging becomes necessary, said types won't be modified (to avoid breaking changes) and CLI/Operator must expose their own type that is then mapped to the `RunConfig` equivalent. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: is it worth mentioning that a decorator can be used here? Not sure if we want to mention specific terms right now, but it may help somewhat keep custom types following a certain pattern
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Action Item: I need to rephrase this mentioning "API contracts", this should clarify what I meant.
|
||
**RunConfig** data structure and routines will be responsible for holding configuration parameters, basic validation, and serialization, but not storage. Simply put, the package should accept bytes and readers, and return bytes, similarly to how `encoding/json` works. | ||
|
||
**CLI** and **Operator** will be responsible for mapping their respective representation of configuration parameters to the representation allowed by `RunConfig`. Specifically, no file-based representation of configuration parameters is allowed in the `RunConfig` struct. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: could we have a simple diagram here of the types? Picture paints a thousand words in that sense
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Action Item: list users of RunConfig
structs and how they represent information that ends up in the run config.
@JAORMX currently, |
* permission profile (literal or file-based) | ||
* OIDC configuration parameters | ||
* authorization config (literal or file-based) | ||
* audit config (literal or file-based) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of these are deprecated.
|
||
We propose the following split in responsibilities | ||
|
||
**RunConfig** data structure and routines will be responsible for holding configuration parameters, basic validation, and serialization, but not storage. Simply put, the package should accept bytes and readers, and return bytes, similarly to how `encoding/json` works. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: currently, validation for middleware configs is done late in the process and should be done at least where it's currently done as well as when instantiating a RunConfig
.
Action Item: document here where validation is implemented and where validation routines should be invoked.
This change contains a design doc describing an architectural boundary at
RunConfig
level. Aim of this design doc isRunConfig
and related code (e.g.Runner
)