Skip to content

Commit

Permalink
Merge branch 'master' into issue-61100
Browse files Browse the repository at this point in the history
  • Loading branch information
mshustov committed May 17, 2021
2 parents 49fc22f + e30c7a4 commit 2bf8351
Show file tree
Hide file tree
Showing 35 changed files with 542 additions and 161 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ The version in which this object type is being converted to a multi-namespace ty
<b>Signature:</b>

```typescript
convertToMultiNamespaceTypeVersion?: string;
readonly convertToMultiNamespaceTypeVersion?: string;
```
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ logger instance to be used by the migration handler
<b>Signature:</b>

```typescript
log: SavedObjectsMigrationLogger;
readonly log: SavedObjectsMigrationLogger;
```
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ The migration version that this migration function is defined for
<b>Signature:</b>

```typescript
migrationVersion: string;
readonly migrationVersion: string;
```
Original file line number Diff line number Diff line change
Expand Up @@ -661,13 +661,14 @@ function wrapWithTry(
migrationFn: SavedObjectMigrationFn,
log: Logger
) {
const context = Object.freeze({
log: new MigrationLogger(log),
migrationVersion: version,
convertToMultiNamespaceTypeVersion: type.convertToMultiNamespaceTypeVersion,
});

return function tryTransformDoc(doc: SavedObjectUnsanitizedDoc) {
try {
const context = {
log: new MigrationLogger(log),
migrationVersion: version,
convertToMultiNamespaceTypeVersion: type.convertToMultiNamespaceTypeVersion,
};
const result = migrationFn(doc, context);

// A basic sanity check to help migration authors detect basic errors
Expand Down
6 changes: 3 additions & 3 deletions src/core/server/saved_objects/migrations/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@ export interface SavedObjectMigrationContext {
/**
* logger instance to be used by the migration handler
*/
log: SavedObjectsMigrationLogger;
readonly log: SavedObjectsMigrationLogger;
/**
* The migration version that this migration function is defined for
*/
migrationVersion: string;
readonly migrationVersion: string;
/**
* The version in which this object type is being converted to a multi-namespace type
*/
convertToMultiNamespaceTypeVersion?: string;
readonly convertToMultiNamespaceTypeVersion?: string;
}

/**
Expand Down
25 changes: 25 additions & 0 deletions src/core/server/saved_objects/migrationsv2/model.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,31 @@ describe('migrations v2 model', () => {
});

describe('model transitions from', () => {
it('transition returns new state', () => {
const initState: State = {
...baseState,
controlState: 'INIT',
currentAlias: '.kibana',
versionAlias: '.kibana_7.11.0',
versionIndex: '.kibana_7.11.0_001',
};

const res: ResponseType<'INIT'> = Either.right({
'.kibana_7.11.0_001': {
aliases: {
'.kibana': {},
'.kibana_7.11.0': {},
},
mappings: {
properties: {},
},
settings: {},
},
});
const newState = model(initState, res);
expect(newState).not.toBe(initState);
});

describe('INIT', () => {
const initState: State = {
...baseState,
Expand Down
4 changes: 2 additions & 2 deletions src/core/server/saved_objects/migrationsv2/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import { gt, valid } from 'semver';
import * as Either from 'fp-ts/lib/Either';
import * as Option from 'fp-ts/lib/Option';
import { cloneDeep } from 'lodash';

import { AliasAction, FetchIndexResponse, isLeftTypeof, RetryableEsClientError } from './actions';
import { AllActionStates, InitState, State } from './types';
import { IndexMapping } from '../mappings';
Expand Down Expand Up @@ -187,7 +187,7 @@ export const model = (currentState: State, resW: ResponseType<AllActionStates>):
// control state using:
// `const res = resW as ResponseType<typeof stateP.controlState>;`

let stateP: State = cloneDeep(currentState);
let stateP: State = currentState;

// Handle retryable_es_client_errors. Other left values need to be handled
// by the control state specific code below.
Expand Down
5 changes: 3 additions & 2 deletions src/core/server/saved_objects/migrationsv2/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ export interface LegacyDeleteState extends LegacyBaseState {
readonly controlState: 'LEGACY_DELETE';
}

export type State =
export type State = Readonly<
| FatalState
| InitState
| DoneState
Expand Down Expand Up @@ -411,7 +411,8 @@ export type State =
| LegacySetWriteBlockState
| LegacyReindexState
| LegacyReindexWaitForTaskState
| LegacyDeleteState;
| LegacyDeleteState
>;

export type AllControlStates = State['controlState'];
/**
Expand Down
6 changes: 3 additions & 3 deletions src/core/server/server.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2152,9 +2152,9 @@ export interface SavedObjectExportBaseOptions {

// @public
export interface SavedObjectMigrationContext {
convertToMultiNamespaceTypeVersion?: string;
log: SavedObjectsMigrationLogger;
migrationVersion: string;
readonly convertToMultiNamespaceTypeVersion?: string;
readonly log: SavedObjectsMigrationLogger;
readonly migrationVersion: string;
}

// @public
Expand Down
5 changes: 2 additions & 3 deletions src/plugins/dashboard/common/saved_dashboard_references.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import semverSatisfies from 'semver/functions/satisfies';
import Semver from 'semver';
import { SavedObjectAttributes, SavedObjectReference } from '../../../core/types';
import { DashboardContainerStateWithType, DashboardPanelState } from './types';
import { EmbeddablePersistableStateService } from '../../embeddable/common/types';
Expand All @@ -24,7 +23,7 @@ export interface SavedObjectAttributesAndReferences {
}

const isPre730Panel = (panel: Record<string, string>): boolean => {
return 'version' in panel ? semverSatisfies(panel.version, '<7.3') : true;
return 'version' in panel ? Semver.gt('7.3.0', panel.version) : true;
};

function dashboardAttributesToState(
Expand Down
1 change: 0 additions & 1 deletion test/functional/apps/visualize/_visualize_listing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
describe('search', function () {
before(async function () {
// create one new viz
await PageObjects.visualize.gotoVisualizationLandingPage();
await PageObjects.visualize.navigateToNewVisualization();
await PageObjects.visualize.clickMarkdownWidget();
await PageObjects.visEditor.setMarkdownTxt('HELLO');
Expand Down
6 changes: 1 addition & 5 deletions test/functional/page_objects/common_page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo
return currentUrl;
});

await retry.try(async () => {
await retry.tryForTime(defaultFindTimeout, async () => {
await this.sleep(501);
const currentUrl = await browser.getCurrentUrl();
log.debug('in navigateTo url = ' + currentUrl);
Expand All @@ -266,10 +266,6 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo
throw new Error('URL changed, waiting for it to settle');
}
});
if (appName === 'status_page') return;
if (await testSubjects.exists('statusPageContainer')) {
throw new Error('Navigation ended up at the status page.');
}
});
}

Expand Down
4 changes: 2 additions & 2 deletions test/functional/page_objects/visualize_page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,14 @@ export function VisualizePageProvider({ getService, getPageObjects }: FtrProvide
}

public async navigateToNewVisualization() {
await common.navigateToApp('visualize');
await this.gotoVisualizationLandingPage();
await header.waitUntilLoadingHasFinished();
await this.clickNewVisualization();
await this.waitForGroupsSelectPage();
}

public async navigateToNewAggBasedVisualization() {
await common.navigateToApp('visualize');
await this.gotoVisualizationLandingPage();
await header.waitUntilLoadingHasFinished();
await this.clickNewVisualization();
await this.clickAggBasedVisualizations();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ const getWrapper: (name?: WorkpadNames) => ReactWrapper = (name = 'hello') => {
return mount(<App {...{ stage, workpad }} />);
};

describe('<App />', () => {
// FLAKY: https://github.com/elastic/kibana/issues/95899
describe.skip('<App />', () => {
test('App renders properly', () => {
expect(getWrapper().html()).toMatchSnapshot();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import React, { useCallback, useState } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import {
EuiButton,
EuiCheckbox,
Expand All @@ -24,7 +24,15 @@ import {
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';

import { sendPutSettings, useLink, useStartServices } from '../../../hooks';
import {
sendGetAgents,
sendGetOneAgentPolicy,
sendPutSettings,
useLink,
useStartServices,
} from '../../../hooks';
import type { PackagePolicy } from '../../../types';
import { FLEET_SERVER_PACKAGE } from '../../../constants';

interface Props {
onClose: () => void;
Expand All @@ -37,6 +45,56 @@ export const FleetServerUpgradeModal: React.FunctionComponent<Props> = ({ onClos
const isCloud = !!cloud?.cloudId;

const [checked, setChecked] = useState(false);
const [isAgentsAndPoliciesLoaded, setAgentsAndPoliciesLoaded] = useState(false);

// Check if an other agent than the fleet server is already enrolled
useEffect(() => {
async function check() {
try {
const agentPoliciesAlreadyChecked: { [k: string]: boolean } = {};

const res = await sendGetAgents({
page: 1,
perPage: 10,
showInactive: false,
});

if (res.error) {
throw res.error;
}

for (const agent of res.data?.list ?? []) {
if (!agent.policy_id || agentPoliciesAlreadyChecked[agent.policy_id]) {
continue;
}

agentPoliciesAlreadyChecked[agent.policy_id] = true;
const policyRes = await sendGetOneAgentPolicy(agent.policy_id);
const hasFleetServer =
(policyRes.data?.item.package_policies as PackagePolicy[]).some((p: PackagePolicy) => {
return p.package?.name === FLEET_SERVER_PACKAGE;
}) ?? false;
if (!hasFleetServer) {
await sendPutSettings({
has_seen_fleet_migration_notice: true,
});
onClose();
return;
}
}
setAgentsAndPoliciesLoaded(true);
} catch (err) {
notifications.toasts.addError(err, {
title: i18n.translate('xpack.fleet.fleetServerUpgradeModal.errorLoadingAgents', {
defaultMessage: `Error loading agents`,
}),
});
}
}

check();
}, [notifications.toasts, onClose]);

const onChange = useCallback(async () => {
try {
setChecked(!checked);
Expand All @@ -52,18 +110,23 @@ export const FleetServerUpgradeModal: React.FunctionComponent<Props> = ({ onClos
}
}, [checked, setChecked, notifications]);

if (!isAgentsAndPoliciesLoaded) {
return null;
}

return (
<EuiModal onClose={onClose}>
<EuiModalHeader>
<EuiModalHeaderTitle>
<FormattedMessage
id="xpack.fleet.fleetServerUpgradeModal.modalTitle"
defaultMessage="This version of Fleet requires a Fleet Server"
defaultMessage="Enroll your agents into Fleet Server"
/>
</EuiModalHeaderTitle>
</EuiModalHeader>
<EuiModalBody>
<EuiImage
size="fullWidth"
src={getAssetsPath('./announcement.jpg')}
alt={i18n.translate('xpack.fleet.fleetServerUpgradeModal.announcementImageAlt', {
defaultMessage: 'Fleet Server upgrade announcement',
Expand All @@ -74,7 +137,7 @@ export const FleetServerUpgradeModal: React.FunctionComponent<Props> = ({ onClos
{isCloud ? (
<FormattedMessage
id="xpack.fleet.fleetServerUpgradeModal.cloudDescriptionMessage"
defaultMessage="Fleet Server is now available and it provides improved scalability and security. If you already had APM on Elastic Cloud, we've upgraded it to APM & Fleet. {existingAgentsMessage} To continue using Fleet, you must install a Fleet Server and the new version of Elastic Agent on each host. Learn more in our {link}."
defaultMessage="Fleet Server is now available and it provides improved scalability and security. If you already had an APM instance on Elastic Cloud, we've upgraded it to APM & Fleet. If not, you can add one to your deployment for free. {existingAgentsMessage} To continue using Fleet, you must use Fleet Server and install the new version of Elastic Agent on each host."
values={{
existingAgentsMessage: (
<strong>
Expand All @@ -84,17 +147,6 @@ export const FleetServerUpgradeModal: React.FunctionComponent<Props> = ({ onClos
/>
</strong>
),
link: (
<EuiLink
href="https://www.elastic.co/guide/en/fleet/current/upgrade-elastic-agent.html"
external={true}
>
<FormattedMessage
id="xpack.fleet.fleetServerUpgradeModal.fleetServerMigrationGuide"
defaultMessage="Fleet Server migration guide"
/>
</EuiLink>
),
}}
/>
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { invalidateAPIKeys } from '../api_keys';
import { settingsService } from '..';

export async function runFleetServerMigration() {
await settingsService.settingsSetup(getInternalUserSOClient());
await Promise.all([migrateEnrollmentApiKeys(), migrateAgentPolicies(), migrateAgents()]);
}

Expand Down
Loading

0 comments on commit 2bf8351

Please sign in to comment.