Skip to content
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 joi to 17.4.0 and adapt the codebase #99899

Merged
merged 32 commits into from
May 20, 2021

Conversation

pgayvallet
Copy link
Contributor

@pgayvallet pgayvallet commented May 12, 2021

Summary

Bump joi from 13.5.2 to 17.4.0, and adapt usages, mostly in @kbn/config-schema

Fix #84624
Related to #78351

From the joi upgrade performance benchmark done here gcanti/io-ts-benchmarks#6, we should expect a +~30% perf gain for successful validations, and ~200% for unsuccessful validations.

Checklist

@pgayvallet pgayvallet force-pushed the kbn-xxx-joi-migration-of-pain branch from b85a955 to 73bd9f6 Compare May 12, 2021 17:33
@pgayvallet pgayvallet added release_note:skip Skip the PR/issue when compiling release notes Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc v7.14.0 labels May 18, 2021
Copy link
Contributor Author

@pgayvallet pgayvallet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Self-review

"joi": "^13.5.2",
"joi": "^17.4.0",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💪

Comment on lines -53 to -55
expect(() => schema.buffer().validate('abc')).toThrowErrorMatchingInlineSnapshot(
`"expected value of type [Buffer] but got [string]"`
);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

joi.binary now converts strings to buffers (using the default encoding)

I thought it was fine (at least it didn't break anything), but if we want to forbid that, I can add our own coerce function for the binary type

.default(() => undefined, 'undefined')
.default(() => undefined)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No longer allowed to define a value description when setting a default value. We weren't using that anywhere anyway.

Comment on lines 53 to 54
"_maxListeners": undefined,
Symbol(kCapture): false,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This snapshot change is caused by a fix in the internal deep copy function joi was using. Symbols are now properly copied.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should refactor the test to assert against Stream instance?

@@ -71,14 +85,13 @@ describe('#hostname', () => {
expect(hostNameSchema.validate('www.example.com')).toBe('www.example.com');
expect(hostNameSchema.validate('3domain.local')).toBe('3domain.local');
expect(hostNameSchema.validate('hostname')).toBe('hostname');
expect(hostNameSchema.validate('2387628')).toBe('2387628');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

joi hostname validation was improved

DOMAIN_INVALID_TLDS_CHARS (last segment must start with alphanum) - https://github.com/sideway/address/blob/master/lib/domain.js#L88

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the changelog for joi 17.0.0, it appears that they also added support for non-ascii chars in hostnames: hapijs/joi#2163 😄

'[disableEmbedding.0]: expected value to equal [false]'
'[disableEmbedding]: expected value to equal [false]'
Copy link
Contributor Author

@pgayvallet pgayvallet May 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

single-type alternative, so the error message changed (see #99899 (comment))

Comment on lines -90 to -94
validate(value) {
if (value === '0') {
return 'value 0 is not a valid hostname (use "0.0.0.0" to bind to all interfaces)';
}
},
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 is now (correctly) considered as an invalid hostname by joi, so this custom validation is no longer required (and not invoked anyway if the value is 0).

We'll have to use a oneOf here when backporting to 7.x to allow 0, as the branch is still supposed to support this value.

hostname: schema.maybe(
schema.string({
validate(value) {
if (value === '0') {
return 'must not be "0" for the headless browser to correctly resolve the host';
}
},
hostname: true,
})
),
hostname: schema.maybe(schema.string({ hostname: true })),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@elastic/kibana-reporting-services 0 is now correctly considered as an invalid hostname by joi. We're loosing the custom error message as the internal validation failing is performed before calling it.

Can you confirm this is acceptable?

Comment on lines -96 to 114
const EntrySchemaDependingOnOS = schema.conditional(
const EntriesSchema = schema.conditional(
schema.siblingRef('os'),
OperatingSystem.WINDOWS,
WindowsEntrySchema,
schema.arrayOf(WindowsEntrySchema, entriesSchemaOptions),
schema.conditional(
schema.siblingRef('os'),
Copy link
Contributor Author

@pgayvallet pgayvallet May 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@elastic/security-solution joi's reference implementation is now less permissive.

You were using a reference from the schema of the type of an array to reference a sibling of the whole array's type

{
   os: schema.something(),
   entries: schema.arrayOf(schema.conditional(schema.siblingRef('os'), [...]))
}

This is no longer allowed, so I had to move the conditional to wrap the whole arrayOf type instead. (thanks for the great test coverage on this file btw)

Comment on lines +21 to 24
export const internals: JoiRoot = Joi.extend(
{
name: 'boolean',

type: 'boolean',
base: Joi.boolean(),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty much everything in the extension API changed, I will not explain all the changes in this file, but feel free to ask questions if you want info on some specific parts.

@pgayvallet pgayvallet marked this pull request as ready for review May 18, 2021 17:24
@pgayvallet pgayvallet requested review from a team as code owners May 18, 2021 17:24
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-core (Team:Core)

Copy link
Contributor

@jportner jportner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review only, security changes (src/core/server/csp/config.test.ts) LGTM.

I also had a look at the Joi changelog and the breaking changes between major versions, nothing stood out to me.

Copy link
Member

@jbudz jbudz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kbn-test changes LGTM

Copy link
Contributor

@mshustov mshustov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

}
if (options.convert && typeof value === 'string') {
if (prefs.convert && typeof value === 'string') {
Copy link
Contributor

@mshustov mshustov May 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we relying on joi defaults for convert? Maybe we shouldn't?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefs.convert defaults to true, and config-schema doesn't provide any way to change this value, so effectively this part of the condition could be removed. I thought it was better to keep it, just to kinda preserve consistency with how the underlying library is working. But maybe not.

Comment on lines 53 to 54
"_maxListeners": undefined,
Symbol(kCapture): false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should refactor the test to assert against Stream instance?

packages/kbn-config-schema/src/types/type.ts Outdated Show resolved Hide resolved
packages/kbn-config-schema/types/joi.d.ts Outdated Show resolved Hide resolved
Copy link
Contributor

@paul-tavares paul-tavares left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥

schema.siblingRef('os'),
OperatingSystem.WINDOWS,
WindowsEntrySchema,
schema.arrayOf(WindowsEntrySchema, entriesSchemaOptions),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks @pgayvallet

@dasansol92 FYI ☝️

@wylieconlon
Copy link
Contributor

@pgayvallet I tested the performance impact of this on a dashboard with dozens of panels and found that it was ~30% faster, as you said. I didn't do any code review, but that's great!

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
remoteClusters 4 - -4
Unknown metric groups

API count

id before after diff
remoteClusters 4 - -4

References to deprecated APIs

id before after diff
canvas 29 25 -4
crossClusterReplication 8 6 -2
fleet 22 20 -2
globalSearch 4 2 -2
indexManagement 12 7 -5
infra 261 149 -112
lens 67 45 -22
licensing 18 15 -3
maps 286 208 -78
ml 121 115 -6
monitoring 109 56 -53
stackAlerts 101 95 -6
total -295

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@pgayvallet pgayvallet merged commit 8fc9115 into elastic:master May 20, 2021
pgayvallet added a commit to pgayvallet/kibana that referenced this pull request May 20, 2021
* bump joi to 17.4.0, start adapting stuff

* remove custom validation rule, adapt instead

* fix error handling

* fix error handling again

* fix strings type & validation

* fix buffers and arrays

* fix bytes

* fix bytes_size type

* update conditional_type error messages in tests

* fix duration and map types

* first attempt to fix union type error messages

* revert conditional type assertions back to master state

* fix object type

* fix record type

* fix stream types

* rename test files to match sources

* fix union type tests

* temporary adapt feature/home usages of Joi

* fix lint

* adapt test assertion

* fix http config schema validation

* fix @kbn/test Config class

* fix config again

* fix reporting schema tests

* fix security solution schema

* adapt url tests

* remove useless comment

* remove space

* typo

* review comments
# Conflicts:
#	src/core/server/http/__snapshots__/http_config.test.ts.snap
pgayvallet added a commit that referenced this pull request May 20, 2021
)

* Migrate `joi` to `17.4.0` and adapt the codebase  (#99899)

* bump joi to 17.4.0, start adapting stuff

* remove custom validation rule, adapt instead

* fix error handling

* fix error handling again

* fix strings type & validation

* fix buffers and arrays

* fix bytes

* fix bytes_size type

* update conditional_type error messages in tests

* fix duration and map types

* first attempt to fix union type error messages

* revert conditional type assertions back to master state

* fix object type

* fix record type

* fix stream types

* rename test files to match sources

* fix union type tests

* temporary adapt feature/home usages of Joi

* fix lint

* adapt test assertion

* fix http config schema validation

* fix @kbn/test Config class

* fix config again

* fix reporting schema tests

* fix security solution schema

* adapt url tests

* remove useless comment

* remove space

* typo

* review comments
# Conflicts:
#	src/core/server/http/__snapshots__/http_config.test.ts.snap

* allow '0' value for server.host

* fix config def

* update snapshots
yctercero pushed a commit to yctercero/kibana that referenced this pull request May 25, 2021
* bump joi to 17.4.0, start adapting stuff

* remove custom validation rule, adapt instead

* fix error handling

* fix error handling again

* fix strings type & validation

* fix buffers and arrays

* fix bytes

* fix bytes_size type

* update conditional_type error messages in tests

* fix duration and map types

* first attempt to fix union type error messages

* revert conditional type assertions back to master state

* fix object type

* fix record type

* fix stream types

* rename test files to match sources

* fix union type tests

* temporary adapt feature/home usages of Joi

* fix lint

* adapt test assertion

* fix http config schema validation

* fix @kbn/test Config class

* fix config again

* fix reporting schema tests

* fix security solution schema

* adapt url tests

* remove useless comment

* remove space

* typo

* review comments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance release_note:skip Skip the PR/issue when compiling release notes Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc v7.14.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Upgrade Joi version or remove dependency on it
8 participants