UNPKG

@kui-shell/plugin-kubectl

Version:

Kubernetes visualization plugin for kubernetes

209 lines 9.77 kB
/* * 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