Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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?)',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down
3 changes: 3 additions & 0 deletions x-pack/platform/plugins/shared/cloud/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export interface CloudConfigType {
project_type?: KibanaSolution;
product_tier?: KibanaProductTier;
orchestrator_target?: string;
in_trial?: boolean;
};
}

Expand Down Expand Up @@ -124,6 +125,7 @@ export class CloudPlugin implements Plugin<CloudSetup> {
// 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);
Expand Down Expand Up @@ -182,6 +184,7 @@ export class CloudPlugin implements Plugin<CloudSetup> {
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,
Expand Down
8 changes: 8 additions & 0 deletions x-pack/platform/plugins/shared/cloud/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
}

Expand Down Expand Up @@ -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;
};
}

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -80,6 +100,7 @@ describe('createCloudUsageCollector', () => {
projectType: 'security',
productTier: 'complete',
orchestratorTarget: 'canary',
organizationInTrial: undefined,
});

expect(await collector.fetch(collectorFetchContext)).toStrictEqual({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export interface CloudUsageCollectorConfig {
projectType: string | undefined;
productTier: string | undefined;
orchestratorTarget: string | undefined;
organizationInTrial: boolean | undefined;
}

interface CloudUsage {
Expand Down Expand Up @@ -47,6 +48,7 @@ export function createCloudUsageCollector(
projectType,
productTier,
orchestratorTarget,
organizationInTrial,
} = config;
const trialEndDateMs = trialEndDate ? new Date(trialEndDate).getTime() : undefined;
return usageCollection.makeUsageCollector<CloudUsage>({
Expand Down Expand Up @@ -99,7 +101,11 @@ export function createCloudUsageCollector(
isElasticStaffOwned,
organizationId,
trialEndDate,
...(trialEndDateMs ? { inTrial: Date.now() <= trialEndDateMs } : {}),
...(organizationInTrial
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: extract to a helper

Copy link
Copy Markdown
Contributor Author

@TattdCodeMonkey TattdCodeMonkey Sep 5, 2025

Choose a reason for hiding this comment

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

+1, I'd actually like to add a helper to the plugin contract as well so that date check doesn't have to be done outside of the cloud plugin either.

But I'll see about handling all of that in another PR.

? { inTrial: true }
: trialEndDateMs
? { inTrial: Date.now() <= trialEndDateMs }
: {}),
deploymentId,
projectId,
projectType,
Expand Down
2 changes: 2 additions & 0 deletions x-pack/platform/plugins/shared/cloud/server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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' }
Expand Down Expand Up @@ -133,6 +134,7 @@ export const config: PluginConfigDescriptor<CloudConfigType> = {
project_type: true,
product_tier: true,
orchestrator_target: true,
in_trial: true,
},
onboarding: {
default_solution: true,
Expand Down
6 changes: 6 additions & 0 deletions x-pack/platform/plugins/shared/cloud/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
}

Expand Down Expand Up @@ -216,6 +220,7 @@ export class CloudPlugin implements Plugin<CloudSetup, CloudStart> {
projectType,
productTier,
orchestratorTarget,
organizationInTrial: this.config.serverless?.in_trial,
});
const basePath = core.http.basePath.serverBasePath;
core.http.resources.register(
Expand Down Expand Up @@ -374,6 +379,7 @@ export class CloudPlugin implements Plugin<CloudSetup, CloudStart> {
// 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,
},
};
}
Expand Down