-
Notifications
You must be signed in to change notification settings - Fork 8.2k
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
Make core
responsible for reading and merging of config files. Simplify legacy config adapter.
#21956
Make core
responsible for reading and merging of config files. Simplify legacy config adapter.
#21956
Conversation
583fcf7
to
7843504
Compare
7843504
to
66a3d7d
Compare
core
responsible for reading and merging of config files. Simplify legacy config adapter.core
responsible for reading and merging of config files. Simplify legacy config adapter.
66a3d7d
to
5454031
Compare
This comment has been minimized.
This comment has been minimized.
5454031
to
320b45b
Compare
This comment has been minimized.
This comment has been minimized.
…lify legacy config adapter.
320b45b
to
51fb213
Compare
💚 Build Succeeded |
* in extreme cases when there is no other better way, e.g. bridging with the | ||
* "legacy" systems that consume and process config in a different way. | ||
*/ | ||
toRaw(): Record<string, any>; |
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.
constructor(readonly configFile: string) { | ||
constructor( | ||
readonly configFiles: ReadonlyArray<string>, | ||
configAdapter: (rawValue: Record<string, any>) => RawConfig = rawValue => |
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: I need this "middleware" to be able to apply cli/keystore overrides to config before it will be published to any subscriber.
throw new Error(`some config paths are not handled: ${JSON.stringify(unhandledConfigPaths)}`); | ||
// We don't throw here since unhandled paths are verified by the "legacy" | ||
// Kibana right now, but this will eventually change. | ||
this.log.trace( |
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: still left trace
here, just as a reminder... I'm not sure what to do with that yet. Currently core uses keys defined in the "legacy" schema, so "legacy" Kibana won't complain about unused keys. But once we start using some config keys in the core exclusively and don't define them in the legacy schema then we'll need to expose something like core.getAppliedConfigKeys()
so that "legacy" Kibana doesn't mark these keys as unused/unknown (or just filter out core-only settings from config we send to the "legacy" kibana, that would be even easier).
This one is ready for review @spalger :) Thanks! |
Alright, I'll take a look today (was out Friday) |
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.
Code looks good, and things run nicely, haven't dug too deep into the tests, but spot checked and things look good. I'm struggling a bit with the naming, as noted in the comments, but I suspect these are more situations where things will make more sense once we get the rest of the big PR in...
}); | ||
} | ||
|
||
function merge(target: any, value: any, key: string = '') { |
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.
feels like key
should just be optional, not default to an empty string.
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.
Yes, was too lazy to write else if (key !== undefined) {
to make lodash.set
type signature happy :) But agree, will change that.
readonly configFiles: ReadonlyArray<string>, | ||
configAdapter: (rawValue: Record<string, any>) => RawConfig = rawValue => | ||
new ObjectToRawConfigAdapter(rawValue) | ||
) { | ||
this.config$ = this.rawConfigFromFile$.pipe( | ||
filter(rawConfig => rawConfig !== notRead), |
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.
Could this filtering be avoided by using a ReplaySubject(1)
instead of a BehaviorSubject(notRead)
?
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.
Absolutely! We also we'll need to review all other places in the server core where observables are used - kbn/observable
didn't have a lot of useful operators/factories that we have now.
import { RawConfig } from './raw_config'; | ||
|
||
/** | ||
* Allows plain javascript object to behave like `RawConfig` instance. | ||
* @internal | ||
*/ | ||
export class ObjectToRawConfigAdapter implements RawConfig { | ||
constructor(private readonly rawValue: { [key: string]: any }) {} | ||
constructor(protected readonly rawValue: Record<string, any>) {} |
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.
Looks like this can stay private
.
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.
Yep, thanks! Was experimenting with something and likely forgot to revert
|
||
import { ConfigPath } from './config_service'; | ||
import { ConfigPath } from './'; | ||
import { RawConfig } from './raw_config'; | ||
|
||
/** | ||
* Allows plain javascript object to behave like `RawConfig` instance. | ||
* @internal | ||
*/ | ||
export class ObjectToRawConfigAdapter implements RawConfig { |
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.
What is the ObjectTo...
part of this name supposed to represent?
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.
Well, I'm bad at naming 🙁
At some point we had "adapter" for the legacy config (src/server/config/config.js
) to be able to use it everywhere where RawConfig
was expected, so it was called LegacyConfigToRawConfigAdapter
(like in Number.toString()
or just NumberToString
🙂 ):
LegacyConfig (src/server/config/config.js)
+ ----> (to)
+ RawConfig (src/core/server/config/raw_config.ts)
But for the non-legacy world we have a plain JavaScript object (or just Object
) instead, that was parsed from yaml config file, so it was called ObjectToRawConfigAdapter
(probably PlainObjectTo...
would have been better):
Record<string, any> (Object)
+ ----> (to)
+ RawConfig (src/core/server/config/raw_config.ts)
We got rid of dependency on the legacy config now and can work with underlying raw config object, but we still need some transformation before core can use it (e.g. logging config format is different), so to bridge it with the legacy world I created LegacyObjectToRawConfigAdapter
, Legacy
part is just to stress that we do something there to support legacy world, and ObjectToRawConfigAdapter
part as explained above.
If it sounds really confusing we can definitely rename this at any point, just let me know what name would sound better?
constructor(readonly configFile: string) { | ||
constructor( | ||
readonly configFiles: ReadonlyArray<string>, | ||
configAdapter: (rawValue: Record<string, any>) => RawConfig = rawValue => |
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.
Feels like this is mapping the rawConfig
to a config instance, which is why the input observable is called rawConfigFromFile$
and the result observable is config$
, but the name configAdapter
doesn't seem to communicate that, and the fact that it's supposed to return a RawConfig
is even more confusing IMO.
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.
Agree, it's a way to confusing now. Let's leave raw
to real "raw" plain JavaScript config object parsed from yaml and rename RawConfig
to just Config
(and remove raw
from names of adapters as well). I was previously concerned about RawConfig.toRaw
, and having Config.toRaw
makes me feel a bit better :)
…Script raw config and `Config` class instance.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
💚 Build Succeeded |
6.x/6.5: dc04be0 |
This PR switches "legacy" Kibana to read and merge config files via
core
functionality. This will be done only bycore
once we merge #22190.I've also simplified legacy config adapter and removed support for
__newPlatform
config node, if we need something like this in the future we'll add it back, but since new platform is in master already I don't see any reason to keep this unused functionality.Blocked by #21885Unblocks #19994