Skip to content
This repository has been archived by the owner on Jun 6, 2024. It is now read-only.

Concatenate SSH command for user #4250

Merged
merged 11 commits into from
Mar 10, 2020
Merged
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -218,40 +218,76 @@ export default class TaskRoleContainerList extends React.Component {
);
}

showSshInfo(id) {
showSshInfo(hasUserSsh, id, containerPorts, containerIp) {
const { sshInfo } = this.context;
abuccts marked this conversation as resolved.
Show resolved Hide resolved
const containerSshInfo =
sshInfo && sshInfo.containers.find(x => x.id === id);
if (!containerSshInfo) {
const res = [];
res.push('This job does not contain SSH info.');
res.push(
'Please note that if your docker image does not have openssh-server and curl packages, SSH will not be enabled.\n',
);
res.push(
'Solution 1: Use one of the recommended docker images on the submission page.',
);
res.push(
'Solution 2: Use your own image, but enable SSH for it. Please follow the instructions on https://aka.ms/AA5u4sq to do such work.',
);
this.setState({
monacoProps: { value: res.join('\n') },
monacoTitle: `SSH to ${id}`,
});
if (config.launcherType !== 'k8s') {
if (!containerSshInfo) {
const res = [];
res.push('This job does not contain SSH info.');
res.push(
'Please note that if your docker image does not have openssh-server and curl packages, SSH will not be enabled.\n',
);
res.push(
'Solution 1: Use one of the recommended docker images on the submission page.',
);
res.push(
'Solution 2: Use your own image, but enable SSH for it. Please follow the instructions on https://aka.ms/AA5u4sq to do such work.',
);
this.setState({
monacoProps: { value: res.join('\n') },
monacoTitle: `SSH to ${id}`,
});
} else {
const res = [];
res.push('# Step 1. Open a Bash shell terminal.');
res.push('# Step 2: Download the private key:');
res.push(
`wget '${sshInfo.keyPair.privateKeyDirectDownloadLink}' -O ${sshInfo.keyPair.privateKeyFileName}`,
);
res.push('# Step 3: Set correct permission for the key file:');
res.push(`chmod 600 ${sshInfo.keyPair.privateKeyFileName}`);
res.push('# Step 4: Connect to the container:');
res.push(
`ssh -i ${sshInfo.keyPair.privateKeyFileName} -p ${containerSshInfo.sshPort} root@${containerSshInfo.sshIp}`,
);
res.push('');
this.setState({
monacoProps: {
value: res.join('\n'),
options: {
wordWrap: 'off',
readOnly: true,
},
},
monacoTitle: `SSH to ${id}`,
});
}
} else {
const res = [];
res.push('# Step 1. Open a Bash shell terminal.');
res.push('# Step 2: Download the private key:');
res.push(
`wget '${sshInfo.keyPair.privateKeyDirectDownloadLink}' -O ${sshInfo.keyPair.privateKeyFileName}`,
);
res.push('# Step 3: Set correct permission for the key file:');
res.push(`chmod 600 ${sshInfo.keyPair.privateKeyFileName}`);
res.push('# Step 4: Connect to the container:');
res.push(
`ssh -i ${sshInfo.keyPair.privateKeyFileName} -p ${containerSshInfo.sshPort} root@${containerSshInfo.sshIp}`,
);
res.push('');
if (hasUserSsh) {
res.push(
'You can connect to this container by one of the following commands if SSH is set up properly: \n',
);
res.push(`1. Use your default SSH private key:\n`);
res.push(`ssh -p ${containerPorts.ssh} root@${containerIp}\n`);
abuccts marked this conversation as resolved.
Show resolved Hide resolved
res.push(`2. Use a pre-downloaded SSH private key:\n`);
abuccts marked this conversation as resolved.
Show resolved Hide resolved
res.push(
`On Windows:\nssh -p ${containerPorts.ssh} -i <your-private-key-file-path> root@${containerIp}\n`,
);
res.push(
`On Unix-like System:\nchmod 400 <your-private-key-file-path> && ssh -p ${containerPorts.ssh} -i <your-private-key-file-path> root@${containerIp}\n\n`,
);
res.push(
`If you are using a different username in your docker, please change "root" to your pre-defined username.`,
);
} else {
res.push('This job does not contain SSH info.');
res.push(
'If you want to use SSH, please enable it in the "Tools -> SSH" Section on the Job Submission Page.',
);
}
this.setState({
monacoProps: {
value: res.join('\n'),
Expand Down Expand Up @@ -446,21 +482,47 @@ export default class TaskRoleContainerList extends React.Component {
className={c(t.h100, t.flex, t.justifyStart, t.itemsCenter, t.ml1)}
>
<div className={c(t.flex)} style={{ height: 40 }}>
{config.launcherType !== 'k8s' && (
<CommandBarButton
className={c(FontClassNames.mediumPlus)}
styles={{
root: { backgroundColor: 'transparent' },
rootDisabled: { backgroundColor: 'transparent' },
}}
iconProps={{ iconName: 'CommandPrompt' }}
text='View SSH Info'
onClick={() => this.showSshInfo(item.containerId)}
disabled={
isNil(item.containerId) || item.taskState !== 'RUNNING'
<CommandBarButton
className={c(FontClassNames.mediumPlus)}
styles={{
root: { backgroundColor: 'transparent' },
rootDisabled: { backgroundColor: 'transparent' },
}}
iconProps={{ iconName: 'CommandPrompt' }}
text='View SSH Info'
onClick={() => {
let hasUserSsh = false;
const jobConfig = this.context.jobConfig;
if (
'extras' in jobConfig &&
'com.microsoft.pai.runtimeplugin' in jobConfig.extras
) {
for (const pluginSetting of jobConfig.extras[
'com.microsoft.pai.runtimeplugin'
]) {
if (pluginSetting.plugin === 'ssh') {
if (
'parameters' in pluginSetting &&
'userssh' in pluginSetting.parameters &&
!isEmpty(pluginSetting.parameters.userssh)
) {
hasUserSsh = true;
break;
}
}
}
abuccts marked this conversation as resolved.
Show resolved Hide resolved
}
/>
)}
this.showSshInfo(
hasUserSsh,
item.containerId,
item.containerPorts,
item.containerIp,
);
}}
disabled={
isNil(item.containerId) || item.taskState !== 'RUNNING'
}
/>
<CommandBarButton
className={FontClassNames.mediumPlus}
styles={{
Expand Down