diff --git a/src/platform/test/plugin_functional/test_suites/core_plugins/rendering.ts b/src/platform/test/plugin_functional/test_suites/core_plugins/rendering.ts index 65b360c73d7d3..04f0d91e7299b 100644 --- a/src/platform/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/src/platform/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -259,6 +259,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'xpack.cloud.serverless.project_type (observability?|security?|search?|chat?)', 'xpack.cloud.serverless.product_tier (never|complete?|essentials?|search_ai_lake?|logs_essentials?)', 'xpack.cloud.serverless.orchestrator_target (string?)', + 'xpack.cloud.serverless.in_trial (boolean?)', 'xpack.cloud.onboarding.default_solution (string?)', 'xpack.contentConnectors.ui.enabled (boolean?)', 'xpack.discoverEnhanced.actions.exploreDataInChart.enabled (boolean?)', diff --git a/x-pack/platform/plugins/private/cloud_integrations/cloud_experiments/common/metadata_service/initialize_metadata.ts b/x-pack/platform/plugins/private/cloud_integrations/cloud_experiments/common/metadata_service/initialize_metadata.ts index ee3a0f8f313c5..7a716157f8636 100644 --- a/x-pack/platform/plugins/private/cloud_integrations/cloud_experiments/common/metadata_service/initialize_metadata.ts +++ b/x-pack/platform/plugins/private/cloud_integrations/cloud_experiments/common/metadata_service/initialize_metadata.ts @@ -46,6 +46,7 @@ export function initializeMetadata({ organizationKey: cloud.organizationId, trial_end_date: cloud.trialEndDate, is_elastic_staff: cloud.isElasticStaffOwned, + in_trial: cloud.serverless?.organizationInTrial, }); // Update the client's contexts when we get any updates in the metadata. diff --git a/x-pack/platform/plugins/private/cloud_integrations/cloud_experiments/common/metadata_service/metadata_service.test.ts b/x-pack/platform/plugins/private/cloud_integrations/cloud_experiments/common/metadata_service/metadata_service.test.ts index 196c8be7a77ce..21e61b77bc223 100644 --- a/x-pack/platform/plugins/private/cloud_integrations/cloud_experiments/common/metadata_service/metadata_service.test.ts +++ b/x-pack/platform/plugins/private/cloud_integrations/cloud_experiments/common/metadata_service/metadata_service.test.ts @@ -104,6 +104,20 @@ describe('MetadataService', () => { }); }) ); + + test('accepts inTrial from cloud serverless config', async () => { + metadataService.setup({ + ...initialMetadata, + in_trial: true, + }); + await expect(firstValueFrom(metadataService.userMetadata$)).resolves.toStrictEqual({ + ...multiContextFormat, + organization: { + ...multiContextFormat.organization, + in_trial: true, + }, + }); + }); }); describe('start', () => { diff --git a/x-pack/platform/plugins/shared/cloud/public/plugin.tsx b/x-pack/platform/plugins/shared/cloud/public/plugin.tsx index a526036d8781d..08803466715af 100644 --- a/x-pack/platform/plugins/shared/cloud/public/plugin.tsx +++ b/x-pack/platform/plugins/shared/cloud/public/plugin.tsx @@ -47,6 +47,7 @@ export interface CloudConfigType { project_type?: KibanaSolution; product_tier?: KibanaProductTier; orchestrator_target?: string; + in_trial?: boolean; }; } @@ -124,6 +125,7 @@ export class CloudPlugin implements Plugin { // It is exposed for informational purposes (telemetry and feature flags). Do not use it for feature-gating. // Use `core.pricing` when checking if a feature is available for the current product tier. productTier: this.config.serverless?.product_tier, + organizationInTrial: this.config.serverless?.in_trial, }, registerCloudService: (contextProvider) => { this.contextProviders.push(contextProvider); @@ -182,6 +184,7 @@ export class CloudPlugin implements Plugin { projectId: this.config.serverless?.project_id, projectName: this.config.serverless?.project_name, projectType: this.config.serverless?.project_type, + organizationInTrial: this.config.serverless?.in_trial, }, performanceUrl, usersAndRolesUrl, diff --git a/x-pack/platform/plugins/shared/cloud/public/types.ts b/x-pack/platform/plugins/shared/cloud/public/types.ts index 258b05047cda7..174167cc4ca56 100644 --- a/x-pack/platform/plugins/shared/cloud/public/types.ts +++ b/x-pack/platform/plugins/shared/cloud/public/types.ts @@ -90,6 +90,10 @@ export interface CloudStart { * Will always be present if `isServerlessEnabled` is `true` */ projectType?: KibanaSolution; + /** + * Whether the serverless project belongs to an organization currently in trial. + */ + organizationInTrial?: boolean; }; } @@ -231,6 +235,10 @@ export interface CloudSetup { * Will always be present if `isServerlessEnabled` is `true` */ orchestratorTarget?: string; + /** + * Whether the serverless project belongs to an organization currently in trial. + */ + organizationInTrial?: boolean; }; } diff --git a/x-pack/platform/plugins/shared/cloud/server/__snapshots__/plugin.test.ts.snap b/x-pack/platform/plugins/shared/cloud/server/__snapshots__/plugin.test.ts.snap index ebb26e3e9ef1b..37f6178469e71 100644 --- a/x-pack/platform/plugins/shared/cloud/server/__snapshots__/plugin.test.ts.snap +++ b/x-pack/platform/plugins/shared/cloud/server/__snapshots__/plugin.test.ts.snap @@ -25,6 +25,7 @@ Object { "projectsUrl": "https://cloud.elastic.co/projects/", "serverless": Object { "orchestratorTarget": undefined, + "organizationInTrial": undefined, "productTier": undefined, "projectId": undefined, "projectName": undefined, diff --git a/x-pack/platform/plugins/shared/cloud/server/collectors/cloud_usage_collector.test.ts b/x-pack/platform/plugins/shared/cloud/server/collectors/cloud_usage_collector.test.ts index 4305cb7c2492e..2489b3d47db97 100644 --- a/x-pack/platform/plugins/shared/cloud/server/collectors/cloud_usage_collector.test.ts +++ b/x-pack/platform/plugins/shared/cloud/server/collectors/cloud_usage_collector.test.ts @@ -69,6 +69,26 @@ describe('createCloudUsageCollector', () => { }); }); + it('return inTrial true if inTrial is provided', async () => { + const collector = createCloudUsageCollector(usageCollection, { + isCloudEnabled: true, + organizationInTrial: true, + } as CloudUsageCollectorConfig); + + expect(await collector.fetch(collectorFetchContext)).toStrictEqual({ + isCloudEnabled: true, + isElasticStaffOwned: undefined, + organizationId: undefined, + trialEndDate: undefined, + inTrial: true, + deploymentId: undefined, + projectId: undefined, + projectType: undefined, + productTier: undefined, + orchestratorTarget: undefined, + }); + }); + it('pass-through properties are copied as expected', async () => { const collector = createCloudUsageCollector(usageCollection, { isCloudEnabled: true, @@ -80,6 +100,7 @@ describe('createCloudUsageCollector', () => { projectType: 'security', productTier: 'complete', orchestratorTarget: 'canary', + organizationInTrial: undefined, }); expect(await collector.fetch(collectorFetchContext)).toStrictEqual({ diff --git a/x-pack/platform/plugins/shared/cloud/server/collectors/cloud_usage_collector.ts b/x-pack/platform/plugins/shared/cloud/server/collectors/cloud_usage_collector.ts index 18ab9a0ef9bbf..c4c45ee831ba9 100644 --- a/x-pack/platform/plugins/shared/cloud/server/collectors/cloud_usage_collector.ts +++ b/x-pack/platform/plugins/shared/cloud/server/collectors/cloud_usage_collector.ts @@ -18,6 +18,7 @@ export interface CloudUsageCollectorConfig { projectType: string | undefined; productTier: string | undefined; orchestratorTarget: string | undefined; + organizationInTrial: boolean | undefined; } interface CloudUsage { @@ -47,6 +48,7 @@ export function createCloudUsageCollector( projectType, productTier, orchestratorTarget, + organizationInTrial, } = config; const trialEndDateMs = trialEndDate ? new Date(trialEndDate).getTime() : undefined; return usageCollection.makeUsageCollector({ @@ -99,7 +101,11 @@ export function createCloudUsageCollector( isElasticStaffOwned, organizationId, trialEndDate, - ...(trialEndDateMs ? { inTrial: Date.now() <= trialEndDateMs } : {}), + ...(organizationInTrial + ? { inTrial: true } + : trialEndDateMs + ? { inTrial: Date.now() <= trialEndDateMs } + : {}), deploymentId, projectId, projectType, diff --git a/x-pack/platform/plugins/shared/cloud/server/config.ts b/x-pack/platform/plugins/shared/cloud/server/config.ts index 493bdbd911134..b7d476f5ab448 100644 --- a/x-pack/platform/plugins/shared/cloud/server/config.ts +++ b/x-pack/platform/plugins/shared/cloud/server/config.ts @@ -101,6 +101,7 @@ const configSchema = schema.object({ ), product_tier: schema.maybe(createProductTiersSchema()), orchestrator_target: schema.maybe(schema.string()), + in_trial: schema.maybe(schema.boolean()), }, // avoid future chicken-and-egg situation with the component populating the config { unknowns: 'ignore' } @@ -133,6 +134,7 @@ export const config: PluginConfigDescriptor = { project_type: true, product_tier: true, orchestrator_target: true, + in_trial: true, }, onboarding: { default_solution: true, diff --git a/x-pack/platform/plugins/shared/cloud/server/plugin.ts b/x-pack/platform/plugins/shared/cloud/server/plugin.ts index 17b1b8e55ecf9..73bae13e445a0 100644 --- a/x-pack/platform/plugins/shared/cloud/server/plugin.ts +++ b/x-pack/platform/plugins/shared/cloud/server/plugin.ts @@ -161,6 +161,10 @@ export interface CloudSetup { * Will always be present if `isServerlessEnabled` is `true` */ orchestratorTarget?: string; + /** + * Whether the serverless project belongs to an organization currently in trial. + */ + organizationInTrial?: boolean; }; } @@ -216,6 +220,7 @@ export class CloudPlugin implements Plugin { projectType, productTier, orchestratorTarget, + organizationInTrial: this.config.serverless?.in_trial, }); const basePath = core.http.basePath.serverBasePath; core.http.resources.register( @@ -374,6 +379,7 @@ export class CloudPlugin implements Plugin { // It is exposed for informational purposes (telemetry and feature flags). Do not use it for feature-gating. // Use `core.pricing` when checking if a feature is available for the current product tier. productTier, + organizationInTrial: this.config.serverless?.in_trial, }, }; }