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

[Fleet] Show snapshot version in agent upgrade modal + allow custom values (but not in serverless) #165978

Merged
merged 10 commits into from
Sep 11, 2023
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 @@ -237,6 +237,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
4 changes: 2 additions & 2 deletions x-pack/plugins/fleet/cypress/tasks/integrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ export function scrollToIntegration(selector: string) {
return cy.window().then(async (win) => {
let found = false;
let i = 0;
while (!found && i < 10) {
win.scroll(0, i++ * 500);
while (!found && i < 20) {
win.scroll(0, i++ * 250);
await new Promise((resolve) => setTimeout(resolve, 200));
if (win.document.querySelector(`[data-test-subj="${selector}"]`)) {
found = true;
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 () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you just specify that this happens when not in serverless? it's going to be easier for future changes.

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