Skip to content

Commit

Permalink
Move EKS Discover joinToken generation to the ManualHelm dialog. (#37730
Browse files Browse the repository at this point in the history
)

* Move EKS joinToken generation to the ManualHelm dialog.

This token is used only for manul enrollment, automatic one generates token on the backend.

* Add container to manual helm dialog.

* Document join creation delay reason.

* Remove usage of msw.

* Generate command outside of manualHelmDialog.

* Fix setting join token in the manual helm dialog.

* Refactor dummyDialog.

* Use indicator component.
  • Loading branch information
AntonAM authored Feb 23, 2024
1 parent 122b5a7 commit 82e2b5f
Show file tree
Hide file tree
Showing 4 changed files with 275 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import React from 'react';
import React, { useEffect, useState } from 'react';
import { MemoryRouter } from 'react-router';
import { rest } from 'msw';
import { mswLoader } from 'msw-storybook-addon';
Expand All @@ -27,11 +27,26 @@ import { ResourceKind } from 'teleport/Discover/Shared';
import { PingTeleportProvider } from 'teleport/Discover/Shared/PingTeleportContext';
import { ContextProvider } from 'teleport';

import {
INTERNAL_RESOURCE_ID_LABEL_KEY,
JoinToken,
} from 'teleport/services/joinToken';
import { clearCachedJoinTokenResult } from 'teleport/Discover/Shared/useJoinTokenSuspender';
import {
DiscoverContextState,
DiscoverProvider,
} from 'teleport/Discover/useDiscover';
import {
IntegrationKind,
IntegrationStatusCode,
} from 'teleport/services/integrations';
import { DiscoverEventResource } from 'teleport/services/userEvent';

import { generateCmd } from 'teleport/Discover/Kubernetes/HelmChart/HelmChart';

import { ManualHelmDialog } from './ManualHelmDialog';
import { AgentWaitingDialog } from './AgentWaitingDialog';
import { EnrollmentDialog } from './EnrollmentDialog';
import { AgentWaitingDialog } from './AgentWaitingDialog';
import { ManualHelmDialog } from './ManualHelmDialog';

export default {
title: 'Teleport/Discover/Kube/EnrollEksClusters/Dialogs',
Expand Down Expand Up @@ -110,7 +125,7 @@ AgentWaitingDialogSuccess.parameters = {
},
};

const helmCommand = generateCmd({
const helmCommandProps = {
namespace: 'teleport-agent',
clusterName: 'EKS1',
proxyAddr: 'teleport-proxy.example.com:1234',
Expand All @@ -126,15 +141,98 @@ const helmCommand = generateCmd({
{ name: 'region', value: 'us-east-1' },
{ name: 'account-id', value: '1234567789012' },
],
});
};

export const ManualHelmDialogStory = () => (
<MemoryRouter initialEntries={[{ state: { discover: {} } }]}>
<ManualHelmDialog
command={helmCommand}
confirmedCommands={() => {}}
cancel={() => {}}
/>
</MemoryRouter>
);
export const ManualHelmDialogStory = () => {
const discoverCtx: DiscoverContextState = {
agentMeta: {
resourceName: 'kube-name',
agentMatcherLabels: [],
kube: {
kind: 'kube_cluster',
name: '',
labels: [],
},
awsIntegration: {
kind: IntegrationKind.AwsOidc,
name: 'test-oidc',
resourceType: 'integration',
spec: {
roleArn: 'arn:aws:iam::123456789012:role/test-role-arn',
},
statusCode: IntegrationStatusCode.Running,
},
},
currentStep: 0,
nextStep: () => null,
prevStep: () => null,
onSelectResource: () => null,
resourceSpec: {
name: 'Eks',
kind: ResourceKind.Kubernetes,
icon: 'Eks',
keywords: '',
event: DiscoverEventResource.KubernetesEks,
},
exitFlow: () => null,
viewConfig: null,
indexedViews: [],
setResourceSpec: () => null,
updateAgentMeta: () => null,
emitErrorEvent: () => null,
emitEvent: () => null,
eventState: null,
};

useEffect(() => {
return () => {
clearCachedJoinTokenResult([
ResourceKind.Kubernetes,
ResourceKind.Application,
ResourceKind.Discovery,
]);
};
}, []);

const [, setToken] = useState<JoinToken>();

return (
<MemoryRouter
initialEntries={[
{ pathname: cfg.routes.discover, state: { entity: 'eks' } },
]}
>
<ContextProvider ctx={createTeleportContext()}>
<DiscoverProvider mockCtx={discoverCtx}>
<ManualHelmDialog
setJoinTokenAndGetCommand={token => {
// Emulate real usage of ManualHelmDialog where setJoinTokenAndGetCommand updates the
// state of a parent.
setToken(token);
return generateCmd(helmCommandProps);
}}
confirmedCommands={() => {}}
cancel={() => {}}
/>
</DiscoverProvider>
</ContextProvider>
</MemoryRouter>
);
};
ManualHelmDialogStory.storyName = 'ManualHelmDialog';
ManualHelmDialogStory.parameters = {
msw: {
handlers: [
rest.post(cfg.api.joinTokenPath, (req, res, ctx) => {
return res(
ctx.json({
id: 'token-id',
suggestedLabels: [
{ name: INTERNAL_RESOURCE_ID_LABEL_KEY, value: 'resource-id' },
],
})
);
}),
],
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import React, { useState } from 'react';
import React, { useState, useCallback } from 'react';
import { Box, ButtonSecondary, ButtonText, Text, Toggle } from 'design';
import styled from 'styled-components';
import { FetchStatus } from 'design/DataTable/types';
Expand All @@ -39,14 +39,15 @@ import { isIamPermError } from 'teleport/Discover/Shared/Aws/error';
import { AgentStepProps } from 'teleport/Discover/types';
import useTeleport from 'teleport/useTeleport';

import { useJoinTokenSuspender } from 'teleport/Discover/Shared/useJoinTokenSuspender';
import { generateCmd } from 'teleport/Discover/Kubernetes/HelmChart/HelmChart';
import { Kube } from 'teleport/services/kube';

import { Header, ResourceKind } from '../../Shared';
import { JoinToken } from 'teleport/services/joinToken';

import { Header } from '../../Shared';

import { ClustersList } from './EksClustersList';
import { ManualHelmDialog } from './ManualHelmDialog';
import ManualHelmDialog from './ManualHelmDialog';
import { EnrollmentDialog } from './EnrollmentDialog';
import { AgentWaitingDialog } from './AgentWaitingDialog';

Expand Down Expand Up @@ -97,14 +98,11 @@ export function EnrollEksCluster(props: AgentStepProps) {
useState(false);
const [isManualHelmDialogShown, setIsManualHelmDialogShown] = useState(false);
const [waitingResourceId, setWaitingResourceId] = useState('');
// join token will be set only if user opens ManualHelmDialog,
// we delay it to avoid premature admin action MFA confirmation request.
const [joinToken, setJoinToken] = useState<JoinToken>(null);
const ctx = useTeleport();

const { joinToken } = useJoinTokenSuspender([
ResourceKind.Kubernetes,
ResourceKind.Application,
ResourceKind.Discovery,
]);

function fetchClustersWithNewRegion(region: Regions) {
setSelectedRegion(region);
// Clear table when fetching with new region.
Expand Down Expand Up @@ -205,8 +203,6 @@ export function EnrollEksCluster(props: AgentStepProps) {
{
region: selectedRegion,
enableAppDiscovery: isAppDiscoveryEnabled,
joinToken: joinToken.id,
resourceId: joinToken.internalResourceId,
clusterNames: [selectedCluster.name],
}
);
Expand Down Expand Up @@ -262,23 +258,34 @@ export function EnrollEksCluster(props: AgentStepProps) {
!selectedCluster ||
enrollmentState.status !== 'notStarted';

let command = '';
if (selectedCluster) {
command = generateCmd({
namespace: 'teleport-agent',
clusterName: selectedCluster.name,
proxyAddr: ctx.storeUser.state.cluster.publicURL,
tokenId: joinToken.id,
clusterVersion: ctx.storeUser.state.cluster.authVersion,
resourceId: joinToken.internalResourceId,
isEnterprise: ctx.isEnterprise,
isCloud: ctx.isCloud,
automaticUpgradesEnabled: ctx.automaticUpgradesEnabled,
automaticUpgradesTargetVersion: ctx.automaticUpgradesTargetVersion,
joinLabels: [...selectedCluster.labels, ...selectedCluster.joinLabels],
disableAppDiscovery: !isAppDiscoveryEnabled,
});
}
const setJoinTokenAndGetCommand = useCallback(
(token: JoinToken) => {
setJoinToken(token);
return generateCmd({
namespace: 'teleport-agent',
clusterName: selectedCluster.name,
proxyAddr: ctx.storeUser.state.cluster.publicURL,
clusterVersion: ctx.storeUser.state.cluster.authVersion,
tokenId: token.id,
resourceId: token.internalResourceId,
isEnterprise: ctx.isEnterprise,
isCloud: ctx.isCloud,
automaticUpgradesEnabled: ctx.automaticUpgradesEnabled,
automaticUpgradesTargetVersion: ctx.automaticUpgradesTargetVersion,
joinLabels: [...selectedCluster.labels, ...selectedCluster.joinLabels],
disableAppDiscovery: !isAppDiscoveryEnabled,
});
},
[
ctx.automaticUpgradesEnabled,
ctx.automaticUpgradesTargetVersion,
ctx.isCloud,
ctx.isEnterprise,
ctx.storeUser.state.cluster,
isAppDiscoveryEnabled,
selectedCluster,
]
);

return (
<Box maxWidth="1000px">
Expand Down Expand Up @@ -366,7 +373,7 @@ export function EnrollEksCluster(props: AgentStepProps) {
)}
{isManualHelmDialogShown && (
<ManualHelmDialog
command={command}
setJoinTokenAndGetCommand={setJoinTokenAndGetCommand}
cancel={() => setIsManualHelmDialogShown(false)}
confirmedCommands={() => {
setEnrollmentState({ status: 'awaitingAgent' });
Expand All @@ -377,7 +384,7 @@ export function EnrollEksCluster(props: AgentStepProps) {
)}
{isAgentWaitingDialogShown && (
<AgentWaitingDialog
joinResourceId={waitingResourceId || joinToken.internalResourceId}
joinResourceId={waitingResourceId || joinToken?.internalResourceId}
status={enrollmentState.status}
clusterName={selectedCluster.name}
updateWaitingResult={(result: Kube) => {
Expand Down
Loading

0 comments on commit 82e2b5f

Please sign in to comment.