Skip to content

Commit

Permalink
[Fleet] Show snapshot version in agent upgrade modal + allow custom v…
Browse files Browse the repository at this point in the history
…alues (but not in serverless) (#165978)

Co-authored-by: Kibana Machine <[email protected]>
(cherry picked from commit 2384280)

# Conflicts:
#	x-pack/plugins/fleet/cypress/tasks/integrations.ts
  • Loading branch information
hop-dev committed Sep 12, 2023
1 parent d6385cc commit 995f75d
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 29 deletions.
1 change: 1 addition & 0 deletions config/serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ xpack.fleet.internal.fleetServerStandalone: true
xpack.fleet.internal.disableILMPolicies: true
xpack.fleet.internal.disableProxies: true
xpack.fleet.internal.activeAgentsSoftLimit: 25000
xpack.fleet.internal.onlyAllowAgentUpgradeToKnownVersions: true

# Cloud links
xpack.cloud.base_url: "https://cloud.elastic.co"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) {
'xpack.fleet.internal.activeAgentsSoftLimit (number)',
'xpack.fleet.internal.disableProxies (boolean)',
'xpack.fleet.internal.fleetServerStandalone (boolean)',
'xpack.fleet.internal.onlyAllowAgentUpgradeToKnownVersions (boolean)',
'xpack.fleet.developer.maxAgentPoliciesWithInactivityTimeout (number)',
'xpack.global_search.search_timeout (duration)',
'xpack.graph.canEditDrillDownUrls (boolean)',
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/fleet/common/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export interface FleetConfigType {
disableILMPolicies: boolean;
disableProxies: boolean;
fleetServerStandalone: boolean;
onlyAllowAgentUpgradeToKnownVersions: boolean;
activeAgentsSoftLimit?: number;
capabilities: string[];
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,8 @@ import { FormattedMessage } from '@kbn/i18n-react';

import type { EuiComboBoxOptionOption } from '@elastic/eui';

import semverCoerce from 'semver/functions/coerce';
import semverGt from 'semver/functions/gt';
import semverLt from 'semver/functions/lt';
import semverValid from 'semver/functions/valid';

import { getMinVersion } from '../../../../../../../common/services/get_min_max_version';
import type { Agent } from '../../../../types';
Expand All @@ -36,6 +34,7 @@ import {
sendPostBulkAgentUpgrade,
useStartServices,
useKibanaVersion,
useConfig,
} from '../../../../hooks';

import { sendGetAgentsAvailableVersions } from '../../../../hooks';
Expand Down Expand Up @@ -71,7 +70,8 @@ export const AgentUpgradeAgentModal: React.FunctionComponent<AgentUpgradeAgentMo
isScheduled = false,
}) => {
const { notifications } = useStartServices();
const kibanaVersion = semverCoerce(useKibanaVersion())?.version || '';
const kibanaVersion = useKibanaVersion() || '';
const config = useConfig();
const [isSubmitting, setIsSubmitting] = useState(false);
const [errors, setErrors] = useState<string | undefined>();
const [availableVersions, setVersions] = useState<string[]>([]);
Expand Down Expand Up @@ -204,23 +204,13 @@ export const AgentUpgradeAgentModal: React.FunctionComponent<AgentUpgradeAgentMo
}

const onCreateOption = (searchValue: string) => {
if (!semverValid(searchValue)) {
return;
}
const normalizedSearchValue = searchValue.trim().toLowerCase();

const agentVersionNumber = semverCoerce(searchValue);
if (
agentVersionNumber?.version &&
semverGt(kibanaVersion, agentVersionNumber?.version) &&
minVersion &&
semverGt(agentVersionNumber?.version, minVersion)
) {
const newOption = {
label: searchValue,
value: searchValue,
};
setSelectedVersion([newOption]);
}
const newOption = {
label: normalizedSearchValue,
value: normalizedSearchValue,
};
setSelectedVersion([newOption]);
};

return (
Expand Down Expand Up @@ -320,8 +310,10 @@ export const AgentUpgradeAgentModal: React.FunctionComponent<AgentUpgradeAgentMo
}
setSelectedVersion(selected);
}}
onCreateOption={onCreateOption}
customOptionText="Input the desired version"
onCreateOption={
config?.internal?.onlyAllowAgentUpgradeToKnownVersions ? undefined : onCreateOption
}
customOptionText="Use custom agent version {searchValue} (not recommended)"
/>
</EuiFormRow>
{!isSingleAgent &&
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/fleet/server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export const config: PluginConfigDescriptor = {
fleetServerStandalone: true,
disableProxies: true,
activeAgentsSoftLimit: true,
onlyAllowAgentUpgradeToKnownVersions: true,
},
},
deprecations: ({ renameFromRoot, unused, unusedFromRoot }) => [
Expand Down Expand Up @@ -176,6 +177,9 @@ export const config: PluginConfigDescriptor = {
fleetServerStandalone: schema.boolean({
defaultValue: false,
}),
onlyAllowAgentUpgradeToKnownVersions: schema.boolean({
defaultValue: false,
}),
activeAgentsSoftLimit: schema.maybe(
schema.number({
min: 0,
Expand Down
41 changes: 40 additions & 1 deletion x-pack/plugins/fleet/server/routes/agent/handlers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@ import { coreMock, httpServerMock } from '@kbn/core/server/mocks';

import { getAvailableVersionsHandler } from './handlers';

let mockKibanaVersion = '300.0.0';
let mockConfig = {};
jest.mock('../../services/app_context', () => {
const { loggerMock } = jest.requireActual('@kbn/logging-mocks');
return {
appContextService: {
getLogger: () => loggerMock.create(),
getKibanaVersion: () => '300.0.0',
getKibanaVersion: () => mockKibanaVersion,
getConfig: () => mockConfig,
},
};
});
Expand All @@ -27,6 +30,7 @@ const mockedReadFile = readFile as jest.MockedFunction<typeof readFile>;

describe('getAvailableVersionsHandler', () => {
it('should return available version and filter version < 7.17', async () => {
mockKibanaVersion = '300.0.0';
const ctx = coreMock.createCustomRequestHandlerContext(coreMock.createRequestHandlerContext());
const response = httpServerMock.createResponseFactory();

Expand All @@ -39,4 +43,39 @@ describe('getAvailableVersionsHandler', () => {
items: ['300.0.0', '8.1.0', '8.0.0', '7.17.0'],
});
});

it('should not strip -SNAPSHOT from kibana version', async () => {
mockKibanaVersion = '300.0.0-SNAPSHOT';
const ctx = coreMock.createCustomRequestHandlerContext(coreMock.createRequestHandlerContext());
const response = httpServerMock.createResponseFactory();

mockedReadFile.mockResolvedValue(`["8.1.0", "8.0.0", "7.17.0", "7.16.0"]`);

await getAvailableVersionsHandler(ctx, httpServerMock.createKibanaRequest(), response);

expect(response.ok).toBeCalled();
expect(response.ok.mock.calls[0][0]?.body).toEqual({
items: ['300.0.0-SNAPSHOT', '8.1.0', '8.0.0', '7.17.0'],
});
});

it('should not include the current version if onlyAllowAgentUpgradeToKnownVersions = true', async () => {
mockKibanaVersion = '300.0.0-SNAPSHOT';
mockConfig = {
internal: {
onlyAllowAgentUpgradeToKnownVersions: true,
},
};
const ctx = coreMock.createCustomRequestHandlerContext(coreMock.createRequestHandlerContext());
const response = httpServerMock.createResponseFactory();

mockedReadFile.mockResolvedValue(`["8.1.0", "8.0.0", "7.17.0", "7.16.0"]`);

await getAvailableVersionsHandler(ctx, httpServerMock.createKibanaRequest(), response);

expect(response.ok).toBeCalled();
expect(response.ok.mock.calls[0][0]?.body).toEqual({
items: ['8.1.0', '8.0.0', '7.17.0'],
});
});
});
17 changes: 10 additions & 7 deletions x-pack/plugins/fleet/server/routes/agent/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -366,10 +366,10 @@ function isStringArray(arr: unknown | string[]): arr is string[] {
// Read a static file generated at build time
export const getAvailableVersionsHandler: RequestHandler = async (context, request, response) => {
const AGENT_VERSION_BUILD_FILE = 'x-pack/plugins/fleet/target/agent_versions_list.json';
const config = await appContextService.getConfig();
let versionsToDisplay: string[] = [];

const kibanaVersion = appContextService.getKibanaVersion();
const kibanaVersionCoerced = semverCoerce(kibanaVersion)?.version ?? kibanaVersion;

try {
const file = await readFile(Path.join(REPO_ROOT, AGENT_VERSION_BUILD_FILE), 'utf-8');
Expand All @@ -382,13 +382,16 @@ export const getAvailableVersionsHandler: RequestHandler = async (context, reque
.map((item: any) => semverCoerce(item)?.version || '')
.filter((v: any) => semverGte(v, MINIMUM_SUPPORTED_VERSION))
.sort((a: any, b: any) => (semverGt(a, b) ? -1 : 1));
const parsedVersions = uniq(versions) as string[];
versionsToDisplay = uniq(versions) as string[];

// Add current version if not already present
const hasCurrentVersion = parsedVersions.some((v) => v === kibanaVersionCoerced);
versionsToDisplay = !hasCurrentVersion
? [kibanaVersionCoerced].concat(parsedVersions)
: parsedVersions;
if (!config?.internal?.onlyAllowAgentUpgradeToKnownVersions) {
// Add current version if not already present
const hasCurrentVersion = versionsToDisplay.some((v) => v === kibanaVersion);

versionsToDisplay = !hasCurrentVersion
? [kibanaVersion].concat(versionsToDisplay)
: versionsToDisplay;
}
const body: GetAvailableVersionsResponse = { items: versionsToDisplay };
return response.ok({ body });
} catch (error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ describe('_installPackage', () => {
disableILMPolicies: true,
disableProxies: false,
fleetServerStandalone: false,
onlyAllowAgentUpgradeToKnownVersions: false,
capabilities: [],
},
})
Expand Down Expand Up @@ -177,6 +178,7 @@ describe('_installPackage', () => {
disableProxies: false,
disableILMPolicies: false,
fleetServerStandalone: false,
onlyAllowAgentUpgradeToKnownVersions: false,
capabilities: [],
},
})
Expand Down

0 comments on commit 995f75d

Please sign in to comment.