Implements config deprecation in New Platform#52251
Implements config deprecation in New Platform#52251pgayvallet merged 33 commits intoelastic:masterfrom
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
98bcb38 to
31a9c38
Compare
This comment has been minimized.
This comment has been minimized.
💚 Build Succeeded |
|
Pinging @elastic/kibana-platform (Team:Platform) |
| deprecations: ({ rename, unused, renameFromRoot }) => [ | ||
| rename('securityKey', 'secret'), | ||
| renameFromRoot('oldtestbed.uiProp', 'testbed.uiProp'), | ||
| unused('deprecatedProperty'), | ||
| ], |
There was a problem hiding this comment.
Added an example in testbed. Not sure if I should keep it.
There was a problem hiding this comment.
we could add something similar to the integration tests in LP https://github.com/restrry/kibana/blob/55604f711f2b06ca58235c1aabc45f5281e13642/src/legacy/server/config/__tests__/deprecation_warnings.js#L28
although it tests only logging part
There was a problem hiding this comment.
Do we want a similar approach to what LP does, by actually spawning a real kibana process? Could not find a NP equivalent to legacy const RUN_KBN_SERVER_STARTUP = require.resolve('./fixtures/run_kbn_server_startup'); ? Seems like more than what we call integration_test in NP?
There was a problem hiding this comment.
run_kbn_server_startup uses test_utils under the hood. So do we in the integrations tests.
https://github.com/restrry/kibana/blob/55604f711f2b06ca58235c1aabc45f5281e13642/src/core/server/http/integration_tests/core_services.test.ts#L23
so yes, I think we can adopt the same approach
There was a problem hiding this comment.
Thanks, missed that.
|
Overall this is looking great. Haven't dug deep into the implementation yet, but the interface and design looks pretty good to me.
Just so I understand correctly: As-is in this PR right now, New Platform plugins and Legacy plugins will be reading different configs because the NP deprecations are not applied to the config that legacy reads. However, the legacy deprecations are applied to the config that NP reads. Correct? If so, are we sure there's a need to apply NP deprecations to the config that LP reads? It seems that if an LP plugin wants to read a renamed config key, it'd be fine if we told them they still need to implement the deprecation in the LP too. |
That is correct.
I don't know if there is a functional need. To be honest I'm not even sure we really should do it. However what I meant what more about technical cleanup: ATM, legacy deprecations are applied to the legacy config (a good thing) but in the legacy world (which is the issue), therefor blocking me from actually remove all the legacy config deprecation system. Now that legacy deprecation can be adapted to NP one, we could apply the adapted legacy deprecations (and maybe the NP ones) to LP config in NP (probably in the legacy service), which would allow us to get rid of the legacy code now without waiting for post 8.0. But we can also decide that this is not necessary and just keep this legacy code until we actually unplug legacy. WDYT? |
| const dataPathDeprecation: ConfigDeprecation = (settings, fromPath, log) => { | ||
| if (has(process.env, 'DATA_PATH')) { | ||
| log( | ||
| `Environment variable "DATA_PATH" will be removed. It has been replaced with kibana.yml setting "path.data"` |
There was a problem hiding this comment.
shouldn't we remove core deprecations from the legacy now?
There was a problem hiding this comment.
Good question, and I'm not sure of the answer to be honest.
There is one deprecation I did not migrate yet from src/legacy/server/config/transform_deprecations.js, the one regarding CSP rules. in legacy, the csp config is located at csp. In #52161, It seems we moved it to server.csp, so I was not sure what to do about it.
But I could at least remove all the others from legacy I think
There was a problem hiding this comment.
Actually I migrated the csp deprecations. Btw the logic inside it looks like more like actual validation that deprecation, we might want to move it to config validation at some point.
That was the last thing blocking, I should be able to suppress src/legacy/server/config/transform_deprecations.js and it's usages now.
There was a problem hiding this comment.
b9e0c6c removes the legacy core deprecations.
| expect(logs.warn).toMatchInlineSnapshot(` | ||
| Array [ | ||
| Array [ | ||
| "\\"optimize.lazy\\" is deprecated and has been replaced by \\"optimize.watch\\"", |
There was a problem hiding this comment.
a disadvantage of such testing is lack of context testing. (config.deprecation)
There was a problem hiding this comment.
I agree. However I think I would prefer to improve the logger mock to allow to filter by context than actually use child_process.spawn is possible, as we may also want it in unit test (and I already do in this PR for the added test in src/core/server/server.test.ts). However this is a big change and I would prefer to do it in a separate PR.
But WDYT?
There was a problem hiding this comment.
In theory we could leverage new config format for NP logging #41956 to filter logs by context and write them into inMemoryAppender. That would require minimal boilerplate code.
There was a problem hiding this comment.
BufferAppender you mean?
- It is a reserved appender that can't be set via configuration file
- It will still requires some mocking or trick to access the appender logs, as it's not exposed currently
There was a problem hiding this comment.
I didn't mean the concrete implementation. We can implement a custom appender for testing purposes only.
There was a problem hiding this comment.
The code in src/core/server/logging/appenders/appenders.ts make me think that this would mean ship test-only code, as there is currently no way to register custom appenders (and I don't think we planned/want that?), so we would still relies on some mocking mechanism (to mock Appenders.create for example), so not sure of the added value in comparison to put this logging into the logger mock?
But I think testing tools in integration tests (aka when using kbnTestServer) is a discussion on it's own.
There was a problem hiding this comment.
and I don't think we planned/want that?
I have no clue to what extent we want to support log4j2 configuration. It was just an idea of testing the whole logging pipeline (including filtering & appenders).
👍 |
| * under the License. | ||
| */ | ||
|
|
||
| import _, { has, get } from 'lodash'; |
There was a problem hiding this comment.
| import _, { has, get } from 'lodash'; | |
| import { has, get } from 'lodash'; |
| return new ClusterManager( | ||
| opts, | ||
| Config.withDefaultSchema(transformDeprecations(settings)), | ||
| Config.withDefaultSchema(settings), |
There was a problem hiding this comment.
Not sure if it works as expected. As I understand settings is expected to be POJO here. But we pass LegacyConfig https://github.com/elastic/kibana/pull/52251/files#diff-748376502c51ed8bfc271f4a6c4c26d3R251
Shouldn't we wrap in getLegacyRawConfig or pass this.settings in legacy_service ?
There was a problem hiding this comment.
I think you are right. However the PR did not change the arguments we were invoking ClusterManager.create with. So I guess this has always been broken?
The fix is (well, should be) easy
require('../../../cli/cluster/cluster_manager').create(
this.coreContext.env.cliArgs,
-- config,
++ config.get(),
await basePathProxy$.toPromise()
);However the legacy service tests are a mess, and are not properly mocking with correct object types (the config in test is actually a Record and not a LegacyConfig ). Already had to fix that in #52060, so would be easier to fix in a separate PR once it lands.
Will open a ticket for that if it's alright with you
There was a problem hiding this comment.
yeah, not a blocker for the current work.
| [uiSettingsConfig.path, uiSettingsConfig.schema], | ||
| ]; | ||
|
|
||
| this.configService.addDeprecationProvider(rootConfigPath, coreDeprecationProvider); |
There was a problem hiding this comment.
shouldn't we rename setupConfigSchemas ? for example setupCoreConfig.
💚 Build SucceededHistory
To update your PR or re-run it, just comment with: |
* implements 'rename' and 'unset' deprecations * introduce usage of ConfigDeprecationProvider * adapt RawConfigService to only returns unmodified raw config * apply deprecations when accessing config * register legacy plugin deprecation in new platform * implements ConfigService#validate * add exemple config deprecation usage in testbed * documentation * export public config deprecation types * fix new test due to rebase * name ConfigDeprecationFactory * update generated doc * add tests for unset and move it to src/core/utils * add tests for renameFromRoot and unusedFromRoot * cast paths as any as get expects a fixed-length string array * use specific logger for deprecations * add additional test on renameFromRoot * update migration guide * migrate core deprecations to NP * add integration test * use same log context as legacy * remove old deprecation warnings integration tests, now covered in NP * migrates csp deprecation to NP * removes deprecationWarningMixin from legacy * remove legacy core deprecations * remove unused import * rename setupConfigSchemas to setupCoreConfig * update generated doc
* implements 'rename' and 'unset' deprecations * introduce usage of ConfigDeprecationProvider * adapt RawConfigService to only returns unmodified raw config * apply deprecations when accessing config * register legacy plugin deprecation in new platform * implements ConfigService#validate * add exemple config deprecation usage in testbed * documentation * export public config deprecation types * fix new test due to rebase * name ConfigDeprecationFactory * update generated doc * add tests for unset and move it to src/core/utils * add tests for renameFromRoot and unusedFromRoot * cast paths as any as get expects a fixed-length string array * use specific logger for deprecations * add additional test on renameFromRoot * update migration guide * migrate core deprecations to NP * add integration test * use same log context as legacy * remove old deprecation warnings integration tests, now covered in NP * migrates csp deprecation to NP * removes deprecationWarningMixin from legacy * remove legacy core deprecations * remove unused import * rename setupConfigSchemas to setupCoreConfig * update generated doc
Summary
Fix #40255
Implement configuration deprecation management in new platform.
coreandpluginscan now register deprecations to be used to mutates the raw configuration (by renaming or removing deprecated properties)Actual implementation
The legacy config deprecation system was chaotic in the sense that deprecations were actually applied in different points (and time) in the code. However, the underneath implementation and API was pretty clever and NP implementation is strongly inspired by it.
core can now register deprecation providers using
configService.addDeprecationProvider. Plugins can register the same providers when declaring their configuration using theirPluginConfigDescriptorBy default, deprecations can only access a plugin's configuration schema, meaning that
rename('someOldKey', 'someNewKey'),will actually renamemyplugin.someOldKeytomyplugin.someNewKey. However due to legacy and edge case requirements, we also expose APIs to access the whole config (renameFromRootandunusedFromRoot)Deprecations are not limited to
renameandunused(even if they cover 99% of the needs) and any custom implementation ofConfigDeprecationcan be returned by a provider.RawConfigServiceandConfigServicechangesTo properly manage and apply deprecations to the configuration values, I had to change these two services responsibilities a little. Now the
RawConfigServicereturns the configuration values in a raw,Record<string, any>format instead of returning an actualConfigobject. This allows to move all configuration data manipulation logic in a single place (the config service). This is probably more coherent regarding what we could expect of aRaw[..]-type service anyway.The most important change regarding
ConfigServiceis in the schema validation timing: because of some edge cases of deprecations, it's no longer possible to validates a plugin's schema when registering it. Practical exemple is a property that would have been migrated from one plugin to another (and we got some of these in the legacy deprecations, such asrename('xpack.telemetry.enabled', 'telemetry.enabled'),). For this reason, global config validation is now done at a single point of time, just after plugins discovery.Legacy deprecations in new platform
As legacy and new deprecation system are pretty close, I was able to create an adapter from legacy deprecations to new ones. the
LegacyServicenow collect every legacy plugin's deprecation providers, adapt them, and register them in the new platform. That way, the NP configuration is properly aware of legacy deprecations and expose up to date values.What remains to be done
Totally removes the legacy deprecation systemUPDATE after discussion, this will be done after NP plugin migration, and is out of the scope of this PR
We are so close and yet so far. This impacts
LegacyServiceand legacy code the most. Currently, the legacy service creates aLegacyConfigfrom the raw config's value, and callsfindPluginSpecswith it. The config then enter in the legacy world/code, where discovered legacy plugins mutates the legacy configuration with both their schema, their value and their deprecations. This mutated legacy config is then considered the source of truth when we instanciate the legacy kibana server.To be able to totally suppress the legacy deprecation system, we will need to remove the part where the deprecation are applied from legacy
findPluginSpecs, get the non-migrated config back in legacyService, and then apply the new platform deprecation to it. However, all this code is strongly coupled atm, not typed (js, no ts), and lack test coverage, so I will need to be extremely careful with that part, and think that we might want to do it in a separate PR.Checklist
Use
strikethroughsto remove checklist items you don't feel are applicable to this PR.- [ ] This was checked for cross-browser compatibility, including a check against IE11- [ ] Any text added follows EUI's writing guidelines, uses sentence case text and includes i18n support- [ ] This was checked for keyboard-only and screenreader accessibilityFor maintainers
- [ ] This was checked for breaking API changes and was labeled appropriatelyDev Docs
New platform plugin's configuration now supports deprecation. Use the
deprecationskey of a plugin's config descriptor to register them.