Skip to content

Commit 2565084

Browse files
[Remote clusters] Add cloud-specific logic to remote clusters (#61639)
1 parent 47184fb commit 2565084

File tree

20 files changed

+276
-28
lines changed

20 files changed

+276
-28
lines changed

x-pack/plugins/remote_clusters/common/lib/cluster_serialization.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,40 @@ describe('cluster_serialization', () => {
112112
},
113113
'localhost:9300'
114114
)
115+
).toEqual({
116+
name: 'test_cluster',
117+
proxyAddress: 'localhost:9300',
118+
mode: 'proxy',
119+
hasDeprecatedProxySetting: true,
120+
isConnected: true,
121+
connectedNodesCount: 1,
122+
maxConnectionsPerCluster: 3,
123+
initialConnectTimeout: '30s',
124+
skipUnavailable: false,
125+
transportPingSchedule: '-1',
126+
transportCompress: false,
127+
});
128+
});
129+
130+
it('should deserialize a cluster that contains a deprecated proxy address and is in cloud', () => {
131+
expect(
132+
deserializeCluster(
133+
'test_cluster',
134+
{
135+
seeds: ['localhost:9300'],
136+
connected: true,
137+
num_nodes_connected: 1,
138+
max_connections_per_cluster: 3,
139+
initial_connect_timeout: '30s',
140+
skip_unavailable: false,
141+
transport: {
142+
ping_schedule: '-1',
143+
compress: false,
144+
},
145+
},
146+
'localhost:9300',
147+
true
148+
)
115149
).toEqual({
116150
name: 'test_cluster',
117151
proxyAddress: 'localhost:9300',

x-pack/plugins/remote_clusters/common/lib/cluster_serialization.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ export interface ClusterSettingsPayloadEs {
6868
export function deserializeCluster(
6969
name: string,
7070
esClusterObject: ClusterInfoEs,
71-
deprecatedProxyAddress?: string | undefined
71+
deprecatedProxyAddress?: string | undefined,
72+
isCloudEnabled?: boolean | undefined
7273
): Cluster {
7374
if (!name || !esClusterObject || typeof esClusterObject !== 'object') {
7475
throw new Error('Unable to deserialize cluster');
@@ -117,7 +118,7 @@ export function deserializeCluster(
117118
// If a user has a remote cluster with the deprecated proxy setting,
118119
// we transform the data to support the new implementation and also flag the deprecation
119120
if (deprecatedProxyAddress) {
120-
// Create server name (address, without port), since field doesn't exist in deprecated implementation
121+
// Cloud-specific logic: Create default server name, since field doesn't exist in deprecated implementation
121122
const defaultServerName = deprecatedProxyAddress.split(':')[0];
122123

123124
deserializedClusterObject = {
@@ -126,7 +127,7 @@ export function deserializeCluster(
126127
seeds: undefined,
127128
hasDeprecatedProxySetting: true,
128129
mode: PROXY_MODE,
129-
serverName: defaultServerName,
130+
serverName: isCloudEnabled ? defaultServerName : undefined,
130131
};
131132
}
132133

x-pack/plugins/remote_clusters/kibana.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"indexManagement"
1212
],
1313
"optionalPlugins": [
14-
"usageCollection"
14+
"usageCollection",
15+
"cloud"
1516
],
1617
"server": true,
1718
"ui": true
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
import React, { createContext } from 'react';
7+
8+
export interface Context {
9+
isCloudEnabled: boolean;
10+
}
11+
12+
export const AppContext = createContext<Context>({} as any);
13+
14+
export const AppContextProvider = ({
15+
children,
16+
context,
17+
}: {
18+
children: React.ReactNode;
19+
context: Context;
20+
}) => {
21+
return <AppContext.Provider value={context}>{children}</AppContext.Provider>;
22+
};

x-pack/plugins/remote_clusters/public/application/index.d.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,8 @@ import { RegisterManagementAppArgs, I18nStart } from '../types';
88

99
export declare const renderApp: (
1010
elem: HTMLElement | null,
11-
I18nContext: I18nStart['Context']
11+
I18nContext: I18nStart['Context'],
12+
appDependencies: {
13+
isCloudEnabled?: boolean;
14+
}
1215
) => ReturnType<RegisterManagementAppArgs['mount']>;

x-pack/plugins/remote_clusters/public/application/index.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,17 @@ import { Provider } from 'react-redux';
1111

1212
import { App } from './app';
1313
import { remoteClustersStore } from './store';
14+
import { AppContextProvider } from './app_context';
1415

15-
export const renderApp = (elem, I18nContext) => {
16+
export const renderApp = (elem, I18nContext, appDependencies) => {
1617
render(
1718
<I18nContext>
1819
<Provider store={remoteClustersStore}>
19-
<HashRouter>
20-
<App />
21-
</HashRouter>
20+
<AppContextProvider context={appDependencies}>
21+
<HashRouter>
22+
<App />
23+
</HashRouter>
24+
</AppContextProvider>
2225
</Provider>
2326
</I18nContext>,
2427
elem

x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap

Lines changed: 11 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.js

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,22 @@ import {
4242

4343
import { RequestFlyout } from './request_flyout';
4444

45-
import { validateName, validateSeeds, validateProxy, validateSeed } from './validators';
45+
import {
46+
validateName,
47+
validateSeeds,
48+
validateProxy,
49+
validateSeed,
50+
validateServerName,
51+
} from './validators';
4652

4753
import { SNIFF_MODE, PROXY_MODE } from '../../../../../common/constants';
4854

55+
import { AppContext } from '../../../app_context';
56+
4957
const defaultFields = {
5058
name: '',
5159
seeds: [],
5260
skipUnavailable: false,
53-
mode: SNIFF_MODE,
5461
nodeConnections: 3,
5562
proxyAddress: '',
5663
proxySocketConnections: 18,
@@ -75,11 +82,17 @@ export class RemoteClusterForm extends Component {
7582
disabledFields: {},
7683
};
7784

78-
constructor(props) {
79-
super(props);
85+
static contextType = AppContext;
86+
87+
constructor(props, context) {
88+
super(props, context);
8089

8190
const { fields, disabledFields } = props;
82-
const fieldsState = merge({}, defaultFields, fields);
91+
const { isCloudEnabled } = context;
92+
93+
// Connection mode should default to "proxy" in cloud
94+
const defaultMode = isCloudEnabled ? PROXY_MODE : SNIFF_MODE;
95+
const fieldsState = merge({}, { ...defaultFields, mode: defaultMode }, fields);
8396

8497
this.generateId = htmlIdGenerator();
8598
this.state = {
@@ -100,12 +113,15 @@ export class RemoteClusterForm extends Component {
100113
};
101114

102115
getFieldsErrors(fields, seedInput = '') {
103-
const { name, seeds, mode, proxyAddress } = fields;
116+
const { name, seeds, mode, proxyAddress, serverName } = fields;
117+
const { isCloudEnabled } = this.context;
104118

105119
return {
106120
name: validateName(name),
107121
seeds: mode === SNIFF_MODE ? validateSeeds(seeds, seedInput) : null,
108122
proxyAddress: mode === PROXY_MODE ? validateProxy(proxyAddress) : null,
123+
// server name is only required in cloud when proxy mode is enabled
124+
serverName: isCloudEnabled && mode === PROXY_MODE ? validateServerName(serverName) : null,
109125
};
110126
}
111127

@@ -349,9 +365,11 @@ export class RemoteClusterForm extends Component {
349365
const {
350366
areErrorsVisible,
351367
fields: { proxyAddress, proxySocketConnections, serverName },
352-
fieldsErrors: { proxyAddress: errorProxyAddress },
368+
fieldsErrors: { proxyAddress: errorProxyAddress, serverName: errorServerName },
353369
} = this.state;
354370

371+
const { isCloudEnabled } = this.context;
372+
355373
return (
356374
<>
357375
<EuiFormRow
@@ -413,11 +431,20 @@ export class RemoteClusterForm extends Component {
413431
</EuiFormRow>
414432
<EuiFormRow
415433
data-test-subj="remoteClusterFormServerNameFormRow"
434+
isInvalid={Boolean(areErrorsVisible && errorServerName)}
435+
error={errorServerName}
416436
label={
417-
<FormattedMessage
418-
id="xpack.remoteClusters.remoteClusterForm.fieldServerNameLabel"
419-
defaultMessage="Server name (optional)"
420-
/>
437+
isCloudEnabled ? (
438+
<FormattedMessage
439+
id="xpack.remoteClusters.remoteClusterForm.fieldServerNameRequiredLabel"
440+
defaultMessage="Server name"
441+
/>
442+
) : (
443+
<FormattedMessage
444+
id="xpack.remoteClusters.remoteClusterForm.fieldServerNameOptionalLabel"
445+
defaultMessage="Server name (optional)"
446+
/>
447+
)
421448
}
422449
helpText={
423450
<FormattedMessage
@@ -440,6 +467,7 @@ export class RemoteClusterForm extends Component {
440467
<EuiFieldText
441468
value={serverName}
442469
onChange={e => this.onFieldsChange({ serverName: e.target.value })}
470+
isInvalid={Boolean(areErrorsVisible && errorServerName)}
443471
fullWidth
444472
/>
445473
</EuiFormRow>
@@ -452,6 +480,8 @@ export class RemoteClusterForm extends Component {
452480
fields: { mode },
453481
} = this.state;
454482

483+
const { isCloudEnabled } = this.context;
484+
455485
return (
456486
<EuiDescribedFormGroup
457487
title={
@@ -485,6 +515,21 @@ export class RemoteClusterForm extends Component {
485515
}
486516
/>
487517
</EuiFormRow>
518+
{isCloudEnabled && mode === PROXY_MODE ? (
519+
<>
520+
<EuiSpacer size="s" />
521+
<EuiCallOut
522+
title={
523+
<FormattedMessage
524+
id="xpack.remoteClusters.cloudClusterInformationTitle"
525+
defaultMessage="You can find the proxy address and server name of your cluster in the Security section of your deployment."
526+
/>
527+
}
528+
iconType="pin"
529+
size="s"
530+
/>
531+
</>
532+
) : null}
488533
</>
489534
}
490535
fullWidth

x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ export { validateName } from './validate_name';
88
export { validateProxy } from './validate_proxy';
99
export { validateSeeds } from './validate_seeds';
1010
export { validateSeed } from './validate_seed';
11+
export { validateServerName } from './validate_server_name';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import React from 'react';
8+
import { FormattedMessage } from '@kbn/i18n/react';
9+
10+
export function validateServerName(serverName) {
11+
if (!serverName || !serverName.trim()) {
12+
return (
13+
<FormattedMessage
14+
id="xpack.remoteClusters.form.errors.serverNameMissing"
15+
defaultMessage="A server name is required."
16+
/>
17+
);
18+
}
19+
20+
return null;
21+
}

0 commit comments

Comments
 (0)