[Spaces] Add defaultSolution to spaces config (#218360)

## Summary

This PR adds new config option `defaultSolution`
(`xpack.spaces.defaultSolution`) which lets you specify a default
solution, similar to the way cloud plugin does it.

Addresses: #213144
This commit is contained in:
Krzysztof Kowalczyk 2025-04-16 19:22:10 +02:00 committed by GitHub
parent a7796cd0d0
commit 31f0f211d9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 42 additions and 3 deletions

View file

@ -96,4 +96,12 @@ describe('config schema', () => {
)
).toThrow();
});
it('should not throw error if defaultSolution uses valid value', () => {
expect(() => ConfigSchema.validate({ defaultSolution: 'es' })).not.toThrow();
});
it('should throw error if defaultSolution uses invalid value', () => {
expect(() => ConfigSchema.validate({ defaultSolution: 'test' })).toThrow();
});
});

View file

@ -10,6 +10,13 @@ import type { Observable } from 'rxjs';
import type { TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema } from '@kbn/config-schema';
import type { PluginInitializerContext } from '@kbn/core/server';
import type { SolutionId } from '@kbn/core-chrome-browser';
const solutions = ['es', 'oblt', 'security'] as const;
const solutionSchemaLiterals = [...solutions].map((s) => schema.literal(s)) as [
ReturnType<typeof schema.literal<Exclude<SolutionId, 'chat'>>>
];
export const ConfigSchema = schema.object({
enabled: schema.conditional(
@ -54,6 +61,7 @@ export const ConfigSchema = schema.object({
defaultValue: true,
}),
}),
defaultSolution: schema.maybe(schema.oneOf(solutionSchemaLiterals)),
});
export function createConfig$(context: PluginInitializerContext) {

View file

@ -82,7 +82,7 @@ describe('Spaces plugin', () => {
expect(usageCollection.getCollectorByType('spaces')).toBeDefined();
});
it('can setup space with default solution', async () => {
it('can setup space with default solution for cloud', async () => {
const initializerContext = coreMock.createPluginInitializerContext({ maxSpaces: 1000 });
const core = coreMock.createSetup() as CoreSetup<PluginsStart>;
const features = featuresPluginMock.createSetup();
@ -100,6 +100,23 @@ describe('Spaces plugin', () => {
expect.objectContaining({ solution: 'security' })
);
});
it('can setup space with default solution for onprem', async () => {
const initializerContext = coreMock.createPluginInitializerContext({
maxSpaces: 1000,
defaultSolution: 'oblt',
});
const core = coreMock.createSetup() as CoreSetup<PluginsStart>;
const features = featuresPluginMock.createSetup();
const licensing = licensingMock.createSetup();
const plugin = new SpacesPlugin(initializerContext);
plugin.setup(core, { features, licensing });
expect(createDefaultSpace).toHaveBeenCalledWith(
expect.objectContaining({ solution: 'oblt' })
);
});
});
describe('#start', () => {

View file

@ -6,7 +6,7 @@
*/
import type { Observable } from 'rxjs';
import { map } from 'rxjs';
import { map, take } from 'rxjs';
import type { CloudSetup } from '@kbn/cloud-plugin/server';
import type {
@ -155,6 +155,12 @@ export class SpacesPlugin
const { license } = this.spacesLicenseService.setup({ license$: plugins.licensing.license$ });
let defaultSolution;
this.config$.pipe(take(1)).subscribe((config) => {
defaultSolution = config.defaultSolution;
});
this.defaultSpaceService = new DefaultSpaceService();
this.defaultSpaceService.setup({
coreStatus: core.status,
@ -162,7 +168,7 @@ export class SpacesPlugin
license$: plugins.licensing.license$,
spacesLicense: license,
logger: this.log,
solution: plugins.cloud?.onboarding?.defaultSolution,
solution: plugins.cloud?.onboarding?.defaultSolution || defaultSolution,
});
initSpacesViewsRoutes({