-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
Migrate instance uuid logic to new platform #52060
Conversation
💔 Build Failed
|
Waiting for #51478 to be merged (need |
a35888f
to
6964d1e
Compare
This comment has been minimized.
This comment has been minimized.
export type KibanaConfig = LegacyConfig; | ||
// lot of legacy code was assuming this type only had these two methods | ||
export type KibanaConfig = Pick<LegacyConfig, 'get' | 'has'>; |
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.
Added set
method in LegacyConfig
to set the uuid in it for legacy compatibility. However a LOT of code in legacy made the assumption that KibanaConfig
only had get
and has
.
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.
I'm surprised having set
would break anything?
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.
Lots of TS errors, mostly (but not only) in test code, similars to:
Type '() => { get<T>(key: string): any; has(key: string): boolean; }' is not assignable to type '() => LegacyConfig'.
Property 'set' is missing in type '{ get<T>(key: string): any; has(key: string): boolean; }' but required in type 'LegacyConfig'
As set
isn't used in legacy anyway, It felt like is was more pragmatic to restrict the type than to adapt something like 25 usages in multiple solutions code.
src/core/server/http/http_config.ts
Outdated
@@ -91,6 +91,7 @@ export const config = { | |||
) | |||
), | |||
}), | |||
uuid: schema.maybe(schema.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.
I don't like having to add this here, as the server
config namespace is now more like only the http
config, However the current property is server.uuid
, so I don't really see another way.
We could deprecates/rename that once the config deprecation PR lands if we want to.
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.
Can you add a note to the config refactoring issue just so we don't forget?
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.
In the legacy config, we validated this as a valid guid. Can we add that validation here as well? Should be able to specify a custom validate
option to schema.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.
Oh good catch, totally forgot about that
src/core/server/uuid/uuid_service.ts
Outdated
// propagate the instance uuid to the legacy config, as it was the legacy way to access it. | ||
legacyPlugins.pluginExtendedConfig.set('server.uuid', this.uuid); |
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.
The legacy way to access the instance uuid was via the config... the legacy mixin was writing it during server init.
I tried to migrates the legacy usages of config.get('server.uuid')
, however some calls are very deeply nested in places where the server, and therefor the NP API, is not accessible. So to preserve retro-compatibility, I was kinda forced to do that.
Tell me if we think this is not acceptable and if I should migrate all calls instead.
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.
Would it be possible to move this code into the LegacyService instead? That way we can more easily delete legacy code without having to modify this as well.
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.
Done. The legacy service tests mocks requirements are growing though. It was harder than expected to move the legacy config set test here.
src/core/server/uuid/uuid_service.ts
Outdated
|
||
public async setup({ legacyPlugins }: SetupDeps) { | ||
this.uuid = await manageInstanceUuid(this.configService); | ||
this.log.info(`Kibana instance UUID: ${this.uuid}`); |
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.
The legacy was logging different (but very similar) messages depending on where the uuid was read from. I think we don't really care, and that the only important info is the actual UUID, so I simplified. Please tell me if I'm wrong.
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.
I'm not sure if we necessarily care, but seeing how this does affect startup and some critical functions (task_manager) maybe it would be good to retain some insight. That said, I think downgrading the detailed messages to debug would be fine.
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.
Ok, adapted to use the exact same messages we had in legacy, and used debug instead of info
💚 Build Succeeded |
Pinging @elastic/kibana-platform (Team:Platform) |
src/core/server/uuid/uuid_service.ts
Outdated
// propagate the instance uuid to the legacy config, as it was the legacy way to access it. | ||
legacyPlugins.pluginExtendedConfig.set('server.uuid', this.uuid); |
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.
Would it be possible to move this code into the LegacyService instead? That way we can more easily delete legacy code without having to modify this as well.
src/core/server/uuid/manage_uuid.ts
Outdated
configService | ||
.atPath<PathConfigType>('path') | ||
.pipe(take(1)) | ||
.toPromise(), | ||
configService | ||
.atPath<HttpConfigType>('server') | ||
.pipe(take(1)) | ||
.toPromise(), | ||
]); |
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: use config.path
from the original modules rather than hardcoded strings.
src/core/server/uuid/manage_uuid.ts
Outdated
|
||
const uuidFilePath = join(pathConfig.data, FILE_NAME); | ||
|
||
const uuidFromFile = await readUUIDFromFile(uuidFilePath); |
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.
super nit: can we capitalize all these UUID names with the same convention used elsewhere: readUuidFromFile
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.
Thanks. I'm more of a UUID
person myself, so I had to rename all theses after asking about our conventions. Missed some, will fix that.
src/core/server/uuid/manage_uuid.ts
Outdated
const readFile = promisify(fs.readFile); | ||
const writeFile = promisify(fs.writeFile); | ||
|
||
export async function manageInstanceUuid(configService: IConfigService): Promise<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.
export async function manageInstanceUuid(configService: IConfigService): Promise<string> { | |
export async function resolveInstanceUuid(configService: IConfigService): Promise<string> { |
seems more descriptive than manage
?
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.
Probably better. Wasn't that inspired with the name. Changed.
export type KibanaConfig = LegacyConfig; | ||
// lot of legacy code was assuming this type only had these two methods | ||
export type KibanaConfig = Pick<LegacyConfig, 'get' | 'has'>; |
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.
I'm surprised having set
would break anything?
src/core/server/uuid/uuid_service.ts
Outdated
|
||
public async setup({ legacyPlugins }: SetupDeps) { | ||
this.uuid = await manageInstanceUuid(this.configService); | ||
this.log.info(`Kibana instance UUID: ${this.uuid}`); |
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.
I'm not sure if we necessarily care, but seeing how this does affect startup and some critical functions (task_manager) maybe it would be good to retain some insight. That said, I think downgrading the detailed messages to debug would be fine.
src/core/server/http/http_config.ts
Outdated
@@ -91,6 +91,7 @@ export const config = { | |||
) | |||
), | |||
}), | |||
uuid: schema.maybe(schema.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.
Can you add a note to the config refactoring issue just so we don't forget?
src/core/server/uuid/resolve_uuid.ts
Outdated
// non-existent uuid file is ok, we will create it. | ||
return undefined; | ||
} | ||
throw e; |
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 possible that we get a EACCESS
error here and in writeUuidToFile
we might also get EISDIR
. I think it would be worth catching these errors and throwing a more useful error to users, maybe something like:
Unable to write Kibana UUID file, please check the uuid.server configuration value in kibana.yml and ensure Kibana has sufficient permissions to read / write to this file.
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.
I think it would also be worth testing these error conditions
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.
Explicit error message is indeed better.
await expect( | ||
resolveInstanceUuid(configService, logger) | ||
).rejects.toThrowErrorMatchingInlineSnapshot( | ||
`"Unable to write Kibana UUID file, please check the uuid.server configurationvalue in kibana.yml and ensure Kibana has sufficient permissions to read / write to this file. Error was: undefined"` |
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.
"Error was: undefined" doesn't seem right.
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.
Damn. thanks you. That's the actual main reason why I hate snapshot testing. That makes developer lazy and leads to that kind of errors.
💚 Build SucceededHistory
To update your PR or re-run it, just comment with: |
* move and migrate uuid code to new platform * create and wire uuid service * handle legacy compatibility * update generated docs * add `set` to LegacyConfig interface * Fix types * fix config access * respect naming conventions for uuid * remove hardcoded config paths * rename manageInstanceUuid to resolveInstanceUuid * moves legacy config uuid set from uuid to legacy service * log specific message depending on how uuid was resolved * resolve merge conflicts * use fs.promises * add forgotten @public in uuid contract * add explicit errors and tests * ensure uuid is valid in configuration * fix read/write tests
* move and migrate uuid code to new platform * create and wire uuid service * handle legacy compatibility * update generated docs * add `set` to LegacyConfig interface * Fix types * fix config access * respect naming conventions for uuid * remove hardcoded config paths * rename manageInstanceUuid to resolveInstanceUuid * moves legacy config uuid set from uuid to legacy service * log specific message depending on how uuid was resolved * resolve merge conflicts * use fs.promises * add forgotten @public in uuid contract * add explicit errors and tests * ensure uuid is valid in configuration * fix read/write tests
Summary
Fix #48956
Migrate the code that was managing the instance uuid and writing it to file (formerly in
src/legacy/core_plugins/kibana/server/lib/manage_uuid.js
) to new platform.As the only public API exposed from this feature is a constant-like, I tried to expose it to plugins via the
PluginInitializerContext
(something likepluginInitializerContext.instanceUuid
). However the pluginsPluginInitializerContext
is created during plugin discovery, which is done before configuration validation. As we decided in #49378 that no config access should be performed before config validation, and as the uuid logic relies on reading the config, I had to fallback to a more classic service approach (core.uuid
)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 appropriately- [ ] This includes a feature addition or change that requires a release note and was labeled appropriately