@kui-shell/plugin-kubectl
Version:
Kubernetes visualization plugin for kubernetes
209 lines • 9.77 kB
JavaScript
/*
* Copyright 2020 The Kubernetes Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { ok } from 'assert';
import { v4 as uuid } from 'uuid';
import { Common, CLI, Keys, ReplExpect, Selectors, SidecarExpect, Util } from '@kui-shell/test';
import { createNS, allocateNS, deleteNS, deletePodByName, remotePodYaml, waitForGreen, getTerminalText, openSidecarByList, waitForTerminalText } from '@kui-shell/plugin-kubectl/tests/lib/k8s/utils';
const command = 'kubectl';
const podName = 'nginx';
const containerName = 'nginx';
// we will echo this text to this file
const ECHO_TEXT = `hello ${uuid()}`;
const ECHO_FILE_1 = '/tmp/kui-terminal-tab-test-1';
const ECHO_FILE_2 = '/tmp/kui-terminal-tab-test-2';
describe(`${command} Terminal tab ${process.env.MOCHA_RUN_TARGET || ''}`, function () {
before(Common.before(this));
after(Common.after(this));
Util.closeAllExceptFirstTab.bind(this)();
const ns = createNS();
allocateNS(this, ns);
let res;
const getPodAndOpenSidecar = () => {
it(`should get pods via ${command} then click`, () => __awaiter(this, void 0, void 0, function* () {
try {
res = yield openSidecarByList(this, `${command} get pods ${podName} -n ${ns}`, podName);
console.error('G', res.count, res.splitIndex);
}
catch (err) {
return Common.oops(this, true)(err);
}
}));
};
const switchTo = (res, mode) => __awaiter(this, void 0, void 0, function* () {
return Util.switchToTab(mode)(res);
});
/** sleep for the given number of seconds */
const sleep = (nSecs) => new Promise(resolve => setTimeout(resolve, nSecs * 1000));
/** switch to terminal tab, echo into file, and confirm echoed text */
const echoInTerminalTabAndConfirm = (ECHO_FILE) => {
it(`should echo in terminal tab ${ECHO_FILE}`, () => __awaiter(this, void 0, void 0, function* () {
try {
yield switchTo(res, 'terminal');
yield SidecarExpect.toolbarText({
type: 'info',
text: `Connected to container ${containerName}`,
exact: false
})(res);
yield sleep(5);
this.app.client.keys(`echo ${ECHO_TEXT} > ${ECHO_FILE}${Keys.ENTER}`);
this.app.client.keys(`cat ${ECHO_FILE}${Keys.ENTER}`);
waitForTerminalText.bind(this)(res, new RegExp('^' + ECHO_TEXT + '$', 'm'));
}
catch (err) {
return Common.oops(this, true)(err);
}
}));
it(`should confirm echoed text via ${command} exec`, () => __awaiter(this, void 0, void 0, function* () {
try {
yield CLI.command(`${command} exec ${podName} -c ${containerName} -n ${ns} -- cat ${ECHO_FILE}`, this.app)
.then(ReplExpect.okWithString(ECHO_TEXT))
.catch(Common.oops(this, true));
}
catch (err) {
yield Common.oops(this, true)(err);
}
}));
};
const doRetry = (toolbar) => {
it('should click retry button', () => __awaiter(this, void 0, void 0, function* () {
try {
yield this.app.client
.$(Selectors.SIDECAR_MODE_BUTTON(res.count, 'retry-streaming', res.splitIndex))
.then((_) => __awaiter(this, void 0, void 0, function* () {
yield _.waitForDisplayed();
yield _.click();
}));
yield SidecarExpect.toolbarText(toolbar)(res);
}
catch (err) {
return Common.oops(this, true)(err);
}
}));
};
/** switch to terminal tab, exit with 1, see error in toolbar and click retry button */
const exitTerminalTabAndRetry = () => {
it('should show terminal tab and exit with error', () => __awaiter(this, void 0, void 0, function* () {
try {
console.error('E1', res.count, res.splitIndex);
yield Util.switchToTab('terminal')(res);
console.error('E2');
yield SidecarExpect.toolbarText({
type: 'info',
text: `Connected to container ${containerName}`,
exact: false
})(res);
for (let idx = 0; idx < 5; idx++) {
try {
console.error('E3', idx);
yield sleep(5);
console.error('E4', idx);
yield this.app.client.keys(`exit 1${Keys.ENTER}`);
console.error('E5', idx);
yield SidecarExpect.toolbarText({ type: 'error', text: 'has closed', exact: false, timeout: 8000 })(res);
console.error('E6', idx);
break;
}
catch (err) {
if (idx === 4) {
throw err;
}
else {
console.error('Error waiting for toolbar text. Retrying');
}
}
}
}
catch (err) {
return Common.oops(this, true)(err);
}
}));
doRetry({
type: 'info',
text: `Connected to container ${containerName}`,
exact: false
});
};
// needed to force the dom renderer for webpack/browser-based tests; see ExecIntoPod
Common.setDebugMode.bind(this)();
it(`should create sample pod from URL via ${command}`, () => {
return CLI.command(`${command} create -f ${remotePodYaml} -n ${ns}`, this.app)
.then(ReplExpect.okWithCustom({ selector: Selectors.BY_NAME('nginx') }))
.then(selector => waitForGreen(this.app, selector))
.catch(Common.oops(this, true));
});
getPodAndOpenSidecar();
echoInTerminalTabAndConfirm(ECHO_FILE_1);
getPodAndOpenSidecar();
exitTerminalTabAndRetry();
echoInTerminalTabAndConfirm(ECHO_FILE_2);
const getText = getTerminalText.bind(this);
const waitForText = waitForTerminalText.bind(this);
it('should re-focus and xoff the terminal when we switch to a different sidecar tab', () => __awaiter(this, void 0, void 0, function* () {
try {
console.error('1');
yield switchTo(res, 'raw');
yield sleep(3);
console.error('2');
yield switchTo(res, 'terminal');
yield sleep(3);
console.error('3');
const elts = yield this.app.client.$$(`${Selectors.SIDECAR_TAB_CONTENT(res.count, res.splitIndex)} .xterm-rows`);
console.error('3b', elts && elts.length);
yield this.app.client.$(`${Selectors.SIDECAR_TAB_CONTENT(res.count, res.splitIndex)}`).then(_ => _.click());
yield this.app.client.keys(`while true; do echo hi; sleep 1; done${Keys.ENTER}`);
console.error('4');
yield waitForText(res, /^hi$/m);
const textBeforeSwitch = yield getText(res);
const nLinesBefore = textBeforeSwitch.split(/\n/).length;
console.error('5', nLinesBefore);
yield switchTo(res, 'raw');
yield sleep(10);
yield switchTo(res, 'terminal');
const textAfterSwitch = yield getText(res);
const nLinesAfter = textAfterSwitch.split(/\n/).length;
console.error('6', nLinesAfter);
// we slept for 10 seconds, and our while loop emits "hi" every
// second. we shouldn't have anywhere near 10 new newlines now:
ok(nLinesAfter - nLinesBefore < 5);
}
catch (err) {
yield Common.oops(this, true)(err);
}
}));
it('should properly exit the terminal', () => __awaiter(this, void 0, void 0, function* () {
try {
yield this.app.client.keys(Keys.ctrlC);
yield this.app.client.keys(`exit${Keys.ENTER}`);
yield SidecarExpect.toolbarText({ type: 'error', text: 'has closed', exact: false })(res);
}
catch (err) {
yield Common.oops(this, true)(err);
}
}));
deletePodByName(this, podName, ns);
doRetry({ type: 'error', text: 'has closed', exact: false });
deleteNS(this, ns);
});
//# sourceMappingURL=terminal-tab.js.map