Skip to content

Commit

Permalink
CNV-30327: Add identity flag to ssh command
Browse files Browse the repository at this point in the history
Signed-off-by: Aviv Turgeman <[email protected]>
  • Loading branch information
avivtur committed Jun 29, 2023
1 parent e4262a2 commit 6ca220b
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 47 deletions.
1 change: 1 addition & 0 deletions locales/en/plugin__kubevirt-plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,7 @@
"SSH key name": "SSH key name",
"SSH over LoadBalancer": "SSH over LoadBalancer",
"SSH over NodePort": "SSH over NodePort",
"SSH secret not configured": "SSH secret not configured",
"SSH service type": "SSH service type",
"SSH using virtctl": "SSH using virtctl",
"Start": "Start",
Expand Down
10 changes: 1 addition & 9 deletions src/utils/components/SSHAccess/SSHAccess.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import * as React from 'react';

import { IoK8sApiCoreV1Service } from '@kubevirt-ui/kubevirt-api/kubernetes';
import { V1VirtualMachine, V1VirtualMachineInstance } from '@kubevirt-ui/kubevirt-api/kubevirt';
import { getCloudInitCredentials } from '@kubevirt-utils/resources/vmi';
import { DescriptionList } from '@patternfly/react-core';

import ConsoleOverVirtctl from './components/ConsoleOverVirtctl';
Expand All @@ -16,16 +15,9 @@ type SSHAccessProps = {
};

const SSHAccess: React.FC<SSHAccessProps> = ({ sshService, sshServiceLoaded, vm, vmi }) => {
const userData = getCloudInitCredentials(vm);
const userName = userData?.users?.[0]?.name;

return (
<DescriptionList>
<ConsoleOverVirtctl
userName={userName}
vmName={vm?.metadata?.name}
vmNamespace={vm?.metadata?.namespace}
/>
<ConsoleOverVirtctl vm={vm} />
<SSHCommand sshService={sshService} sshServiceLoaded={sshServiceLoaded} vm={vm} vmi={vmi} />
</DescriptionList>
);
Expand Down
28 changes: 8 additions & 20 deletions src/utils/components/SSHAccess/components/ConsoleOverVirtctl.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,23 @@
import * as React from 'react';
import React, { FC } from 'react';

import { t } from '@kubevirt-utils/hooks/useKubevirtTranslation';
import { V1VirtualMachine } from '@kubevirt-ui/kubevirt-api/kubevirt';
import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation';
import {
ClipboardCopy,
DescriptionListDescription,
DescriptionListGroup,
DescriptionListTerm,
Popover,
} from '@patternfly/react-core';
import { HelpIcon } from '@patternfly/react-icons';

import { getConsoleVirtctlCommand } from '../utils';
import VirtctlSSHCommandClipboardCopy from './VirtctlSSHCommandClipboardCopy';

type ConsoleOverVirtctlProps = {
userName?: string;
vmName: string;
vmNamespace: string;
vm: V1VirtualMachine;
};

const ConsoleOverVirtctl: React.FC<ConsoleOverVirtctlProps> = ({
userName,
vmName,
vmNamespace,
}) => {
const ConsoleOverVirtctl: FC<ConsoleOverVirtctlProps> = ({ vm }) => {
const { t } = useKubevirtTranslation();
return (
<DescriptionListGroup>
<DescriptionListTerm className="pf-u-font-size-xs">
Expand All @@ -39,14 +34,7 @@ const ConsoleOverVirtctl: React.FC<ConsoleOverVirtctlProps> = ({
</DescriptionListTerm>

<DescriptionListDescription className="sshcommand-body">
<ClipboardCopy
clickTip={t('Copied')}
data-test="ssh-over-virtctl"
hoverTip={t('Copy to clipboard')}
isReadOnly
>
{getConsoleVirtctlCommand(userName, vmName, vmNamespace)}
</ClipboardCopy>
<VirtctlSSHCommandClipboardCopy vm={vm} />
</DescriptionListDescription>
</DescriptionListGroup>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, { FC } from 'react';

import { V1VirtualMachine } from '@kubevirt-ui/kubevirt-api/kubevirt';
import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation';
import { getVMSSHSecretName } from '@kubevirt-utils/resources/vm';
import { isEmpty } from '@kubevirt-utils/utils/utils';
import { ClipboardCopy, HelperText, HelperTextItem } from '@patternfly/react-core';

import { exampleIdentityFilePath } from '../constants';
import { getConsoleVirtctlCommand } from '../utils';

type VirtctlSSHCommandClipboardCopyProps = {
vm: V1VirtualMachine;
};

const VirtctlSSHCommandClipboardCopy: FC<VirtctlSSHCommandClipboardCopyProps> = ({ vm }) => {
const { t } = useKubevirtTranslation();

if (isEmpty(getVMSSHSecretName(vm))) {
return <div className="pf-u-font-size-xs">{t('SSH secret not configured')}</div>;
}

return (
<>
<ClipboardCopy
clickTip={t('Copied')}
data-test="ssh-over-virtctl"
hoverTip={t('Copy to clipboard')}
>
{getConsoleVirtctlCommand(vm)}
</ClipboardCopy>
<HelperText className="pf-u-mt-sm">
<HelperTextItem variant="indeterminate">
{t('Example: ')}
{getConsoleVirtctlCommand(vm, exampleIdentityFilePath)}
</HelperTextItem>
</HelperText>
</>
);
};

export default VirtctlSSHCommandClipboardCopy;
2 changes: 2 additions & 0 deletions src/utils/components/SSHAccess/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ export enum SERVICE_TYPES {
}

export const METALLB_GROUP = 'metallb.io';

export const exampleIdentityFilePath = '--identity-file=/home/jdoe/.ssh/id_rsa';
18 changes: 14 additions & 4 deletions src/utils/components/SSHAccess/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ import VirtualMachineInstanceModel from '@kubevirt-ui/kubevirt-api/console/model
import VirtualMachineModel from '@kubevirt-ui/kubevirt-api/console/models/VirtualMachineModel';
import { IoK8sApiCoreV1Service } from '@kubevirt-ui/kubevirt-api/kubernetes';
import { V1VirtualMachine, V1VirtualMachineInstance } from '@kubevirt-ui/kubevirt-api/kubevirt';
import { ensurePath, getRandomChars } from '@kubevirt-utils/utils/utils';
import { getCloudInitCredentials } from '@kubevirt-utils/resources/vmi';
import { ensurePath, getRandomChars, isEmpty } from '@kubevirt-utils/utils/utils';
import {
k8sCreate,
k8sDelete,
K8sResourceCommon,
k8sUpdate,
} from '@openshift-console/dynamic-plugin-sdk';

import { buildOwnerReference } from './../../resources/shared';
import { buildOwnerReference, getName, getNamespace } from './../../resources/shared';
import { PORT, SERVICE_TYPES, SSH_PORT, VMI_LABEL_AS_SSH_SERVICE_SELECTOR } from './constants';

const buildSSHServiceFromVM = (vm: V1VirtualMachine, type: SERVICE_TYPES, sshLabel: string) => ({
Expand Down Expand Up @@ -106,5 +107,14 @@ export const createSSHService = async (
});
};

export const getConsoleVirtctlCommand = (userName: string, vmName: string, vmNamespace?: string) =>
`virtctl ${vmNamespace ? `-n ${vmNamespace}` : ''} ssh ${userName}@${vmName}`;
export const getConsoleVirtctlCommand = (vm: V1VirtualMachine, identityFlag?: string) => {
const [vmName, vmNamespace, userName] = [
getName(vm),
getNamespace(vm),
getCloudInitCredentials(vm)?.users?.[0]?.name,
];

return `virtctl -n ${vmNamespace} ssh ${userName}@${vmName} ${
!isEmpty(identityFlag) ? identityFlag : '--identity-file=<path_to_sshkey>'
}`;
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { LabelsModal } from '@kubevirt-utils/components/LabelsModal/LabelsModal'
import { ModalComponent } from '@kubevirt-utils/components/ModalProvider/ModalProvider';
import { t } from '@kubevirt-utils/hooks/useKubevirtTranslation';
import { asAccessReview } from '@kubevirt-utils/resources/shared';
import { getVMSSHSecretName } from '@kubevirt-utils/resources/vm';
import { isEmpty } from '@kubevirt-utils/utils/utils';
import { Action, k8sPatch } from '@openshift-console/dynamic-plugin-sdk';
import { CopyIcon } from '@patternfly/react-icons';

Expand Down Expand Up @@ -78,6 +80,7 @@ export const VirtualMachineActionFactory = {
accessReview: asAccessReview(VirtualMachineModel, vm, 'patch'),
cta: () => command && navigator.clipboard.writeText(command),
description: t('SSH using virtctl'),
disabled: isEmpty(getVMSSHSecretName(vm)),
icon: <CopyIcon />,
id: 'vm-action-copy-ssh',
label: t('Copy SSH command'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
import { useModal } from '@kubevirt-utils/components/ModalProvider/ModalProvider';
import { getConsoleVirtctlCommand } from '@kubevirt-utils/components/SSHAccess/utils';
import { VirtualMachineModelRef } from '@kubevirt-utils/models';
import { getCloudInitCredentials } from '@kubevirt-utils/resources/vmi';
import { vmimStatuses } from '@kubevirt-utils/resources/vmim/statuses';
import { Action, useK8sModel } from '@openshift-console/dynamic-plugin-sdk';

Expand All @@ -26,12 +25,8 @@ const useVirtualMachineActionsProvider: UseVirtualMachineActionsProvider = (
isSingleNodeCluster,
) => {
const { createModal } = useModal();
const userName = getCloudInitCredentials(vm)?.users?.[0]?.name;
const virtctlCommand = getConsoleVirtctlCommand(
userName,
vm?.metadata?.name,
vm?.metadata?.namespace,
);

const virtctlCommand = getConsoleVirtctlCommand(vm);

const [, inFlight] = useK8sModel(VirtualMachineModelRef);
const actions: Action[] = React.useMemo(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { printableVMStatus } from 'src/views/virtualmachines/utils';
import { V1VirtualMachine } from '@kubevirt-ui/kubevirt-api/kubevirt';
import { getConsoleVirtctlCommand } from '@kubevirt-utils/components/SSHAccess/utils';
import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation';
import { getCloudInitCredentials } from '@kubevirt-utils/resources/vmi';
import { getVMSSHSecretName } from '@kubevirt-utils/resources/vm';
import { isEmpty } from '@kubevirt-utils/utils/utils';
import { CardTitle, Dropdown, DropdownItem, KebabToggle } from '@patternfly/react-core';
import { CopyIcon } from '@patternfly/react-icons';

Expand All @@ -21,12 +22,7 @@ const VirtualMachinesOverviewTabDetailsTitle: FC<VirtualMachinesOverviewTabDetai
}) => {
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const { t } = useKubevirtTranslation();
const userName = getCloudInitCredentials(vm)?.users?.[0]?.name;
const virtctlCommand = getConsoleVirtctlCommand(
userName,
vm?.metadata?.name,
vm?.metadata?.namespace,
);
const virtctlCommand = getConsoleVirtctlCommand(vm);

const isMachinePaused = vm?.status?.printableStatus === printableVMStatus.Paused;
const isMachineStopped = vm?.status?.printableStatus === printableVMStatus.Stopped;
Expand All @@ -38,6 +34,7 @@ const VirtualMachinesOverviewTabDetailsTitle: FC<VirtualMachinesOverviewTabDetai
dropdownItems={[
<DropdownItem
description={t('SSH using virtctl')}
isDisabled={isEmpty(getVMSSHSecretName(vm))}
key="copy"
onClick={() => virtctlCommand && navigator.clipboard.writeText(virtctlCommand)}
>
Expand Down

0 comments on commit 6ca220b

Please sign in to comment.