Using addon wait-until for improved waiting in k8s
parent
57e6869829
commit
1b24f65522
|
|
@ -733,6 +733,7 @@ const k8s = __importStar(__webpack_require__(89679));
|
||||||
const core = __importStar(__webpack_require__(42186));
|
const core = __importStar(__webpack_require__(42186));
|
||||||
const client_node_1 = __webpack_require__(89679);
|
const client_node_1 = __webpack_require__(89679);
|
||||||
const stream_1 = __webpack_require__(92413);
|
const stream_1 = __webpack_require__(92413);
|
||||||
|
const async_wait_until_1 = __webpack_require__(41299);
|
||||||
const base64 = __webpack_require__(85848);
|
const base64 = __webpack_require__(85848);
|
||||||
const pollInterval = 20000;
|
const pollInterval = 20000;
|
||||||
class Kubernetes {
|
class Kubernetes {
|
||||||
|
|
@ -834,8 +835,13 @@ class Kubernetes {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
createPersistentVolumeClaim() {
|
getPVCPhase() {
|
||||||
var _a;
|
var _a;
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
return (_a = (yield this.kubeClient.readNamespacedPersistentVolumeClaimStatus(this.pvcName, this.namespace)).body.status) === null || _a === void 0 ? void 0 : _a.phase;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
createPersistentVolumeClaim() {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
if (this.buildParameters.kubeVolume) {
|
if (this.buildParameters.kubeVolume) {
|
||||||
core.info(this.buildParameters.kubeVolume);
|
core.info(this.buildParameters.kubeVolume);
|
||||||
|
|
@ -857,8 +863,9 @@ class Kubernetes {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const pvcResult = yield this.kubeClient.createNamespacedPersistentVolumeClaim(this.namespace, pvc);
|
yield this.kubeClient.createNamespacedPersistentVolumeClaim(this.namespace, pvc);
|
||||||
core.info(`Persistent Volume created, ${(_a = pvcResult.body.status) === null || _a === void 0 ? void 0 : _a.phase}`);
|
core.info(`Persistent Volume created, ${yield this.getPVCPhase()}`);
|
||||||
|
yield async_wait_until_1.waitUntil(() => __awaiter(this, void 0, void 0, function* () { return (yield this.getPVCPhase()) !== 'Pending'; }));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
getJobSpec(command, image) {
|
getJobSpec(command, image) {
|
||||||
|
|
@ -994,7 +1001,7 @@ class Kubernetes {
|
||||||
core.info('Creating build job');
|
core.info('Creating build job');
|
||||||
yield this.kubeClientBatch.createNamespacedJob(this.namespace, jobSpec);
|
yield this.kubeClientBatch.createNamespacedJob(this.namespace, jobSpec);
|
||||||
core.info('Job created');
|
core.info('Job created');
|
||||||
yield this.watchPersistentVolumeClaimUntilBoundToContainer();
|
// await this.watchPersistentVolumeClaimUntilBoundToContainer();
|
||||||
core.info('PVC Bound');
|
core.info('PVC Bound');
|
||||||
this.setPodNameAndContainerName(yield this.getPod());
|
this.setPodNameAndContainerName(yield this.getPod());
|
||||||
core.info('Watching pod and streaming logs');
|
core.info('Watching pod and streaming logs');
|
||||||
|
|
@ -1074,25 +1081,23 @@ class Kubernetes {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
watchUntilPodRunning() {
|
getPodStatusPhase() {
|
||||||
var _a, _b;
|
var _a, _b;
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
let ready = false;
|
return (_b = (_a = (yield this.kubeClient.readNamespacedPod(this.podName, this.namespace))) === null || _a === void 0 ? void 0 : _a.body.status) === null || _b === void 0 ? void 0 : _b.phase;
|
||||||
while (!ready) {
|
});
|
||||||
yield new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
||||||
const pod = (_a = (yield this.kubeClient.readNamespacedPod(this.podName, this.namespace))) === null || _a === void 0 ? void 0 : _a.body;
|
|
||||||
if (pod === undefined) {
|
|
||||||
throw new Error('no pod found');
|
|
||||||
}
|
}
|
||||||
const phase = (_b = pod.status) === null || _b === void 0 ? void 0 : _b.phase;
|
watchUntilPodRunning() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
yield async_wait_until_1.waitUntil(() => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
(yield this.getPodStatusPhase()) !== 'Pending';
|
||||||
|
}));
|
||||||
|
const phase = yield this.getPodStatusPhase();
|
||||||
if (phase === 'Running') {
|
if (phase === 'Running') {
|
||||||
core.info('Pod no longer pending');
|
core.info('Pod no longer pending');
|
||||||
ready = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (phase !== 'Pending') {
|
|
||||||
core.error('Kubernetes job failed');
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
core.error('Pod failed to reach running phase');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -140751,6 +140756,14 @@ function _setExports(ndebug) {
|
||||||
module.exports = _setExports(process.env.NODE_NDEBUG);
|
module.exports = _setExports(process.env.NODE_NDEBUG);
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 41299:
|
||||||
|
/***/ (function(__unused_webpack_module, exports) {
|
||||||
|
|
||||||
|
!function(e,t){ true?t(exports):0}(this,(function(e){"use strict";class t extends Error{constructor(e){super(null!=e?`Timed out after waiting for ${e} ms`:"Timed out"),Object.setPrototypeOf(this,t.prototype)}}const o=(e,t)=>new Promise(((o,n)=>{try{e.schedule(o,t)}catch(e){n(e)}})),n={schedule:(e,t)=>{let o;const n=e=>{null!=e&&clearTimeout(e),o=void 0};return o=setTimeout((()=>{n(o),e()}),t),{cancel:()=>n(o)}}},i=Number.POSITIVE_INFINITY,r=(e,r,l)=>{var u,s;const c=null!==(u="number"==typeof r?r:null==r?void 0:r.timeout)&&void 0!==u?u:5e3,d=null!==(s="number"==typeof r?l:null==r?void 0:r.intervalBetweenAttempts)&&void 0!==s?s:50;let a=!1;const f=()=>new Promise(((t,i)=>{const r=()=>{a||new Promise(((t,o)=>{try{t(e())}catch(e){o(e)}})).then((e=>{e?t(e):o(n,d).then(r).catch(i)})).catch(i)};r()})),T=c!==i?()=>o(n,c).then((()=>{throw a=!0,new t(c)})):void 0;return null!=T?Promise.race([f(),T()]):f()};e.DEFAULT_INTERVAL_BETWEEN_ATTEMPTS_IN_MS=50,e.DEFAULT_TIMEOUT_IN_MS=5e3,e.TimeoutError=t,e.WAIT_FOREVER=i,e.default=r,e.waitUntil=r,Object.defineProperty(e,"__esModule",{value:!0})}));//# sourceMappingURL=index.js.map
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 14812:
|
/***/ 14812:
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -369,6 +369,31 @@ THE SOFTWARE
|
||||||
assert-plus
|
assert-plus
|
||||||
MIT
|
MIT
|
||||||
|
|
||||||
|
async-wait-until
|
||||||
|
MIT
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2017-2021 Denis Tokarev (https://github.com/devlato)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
asynckit
|
asynckit
|
||||||
MIT
|
MIT
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
"@actions/exec": "^1.0.4",
|
"@actions/exec": "^1.0.4",
|
||||||
"@actions/github": "^2.2.0",
|
"@actions/github": "^2.2.0",
|
||||||
"@kubernetes/client-node": "^0.14.3",
|
"@kubernetes/client-node": "^0.14.3",
|
||||||
|
"async-wait-until": "^2.0.7",
|
||||||
"aws-sdk": "^2.812.0",
|
"aws-sdk": "^2.812.0",
|
||||||
"base-64": "^1.0.0",
|
"base-64": "^1.0.0",
|
||||||
"nanoid": "3.1.20",
|
"nanoid": "3.1.20",
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import { KubeConfig, Log } from '@kubernetes/client-node';
|
||||||
import { Writable } from 'stream';
|
import { Writable } from 'stream';
|
||||||
import { RemoteBuilderProviderInterface } from './remote-builder/remote-builder-provider-interface';
|
import { RemoteBuilderProviderInterface } from './remote-builder/remote-builder-provider-interface';
|
||||||
import RemoteBuilderSecret from './remote-builder/remote-builder-secret';
|
import RemoteBuilderSecret from './remote-builder/remote-builder-secret';
|
||||||
|
import { waitUntil } from 'async-wait-until';
|
||||||
|
|
||||||
const base64 = require('base-64');
|
const base64 = require('base-64');
|
||||||
|
|
||||||
const pollInterval = 20000;
|
const pollInterval = 20000;
|
||||||
|
|
@ -119,6 +121,11 @@ class Kubernetes implements RemoteBuilderProviderInterface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getPVCPhase() {
|
||||||
|
return (await this.kubeClient.readNamespacedPersistentVolumeClaimStatus(this.pvcName, this.namespace)).body.status
|
||||||
|
?.phase;
|
||||||
|
}
|
||||||
|
|
||||||
async createPersistentVolumeClaim() {
|
async createPersistentVolumeClaim() {
|
||||||
if (this.buildParameters.kubeVolume) {
|
if (this.buildParameters.kubeVolume) {
|
||||||
core.info(this.buildParameters.kubeVolume);
|
core.info(this.buildParameters.kubeVolume);
|
||||||
|
|
@ -140,8 +147,9 @@ class Kubernetes implements RemoteBuilderProviderInterface {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const pvcResult = await this.kubeClient.createNamespacedPersistentVolumeClaim(this.namespace, pvc);
|
await this.kubeClient.createNamespacedPersistentVolumeClaim(this.namespace, pvc);
|
||||||
core.info(`Persistent Volume created, ${pvcResult.body.status?.phase}`);
|
core.info(`Persistent Volume created, ${await this.getPVCPhase()}`);
|
||||||
|
await waitUntil(async () => (await this.getPVCPhase()) !== 'Pending');
|
||||||
}
|
}
|
||||||
|
|
||||||
getJobSpec(command: string[], image: string) {
|
getJobSpec(command: string[], image: string) {
|
||||||
|
|
@ -277,7 +285,7 @@ class Kubernetes implements RemoteBuilderProviderInterface {
|
||||||
core.info('Creating build job');
|
core.info('Creating build job');
|
||||||
await this.kubeClientBatch.createNamespacedJob(this.namespace, jobSpec);
|
await this.kubeClientBatch.createNamespacedJob(this.namespace, jobSpec);
|
||||||
core.info('Job created');
|
core.info('Job created');
|
||||||
await this.watchPersistentVolumeClaimUntilBoundToContainer();
|
// await this.watchPersistentVolumeClaimUntilBoundToContainer();
|
||||||
core.info('PVC Bound');
|
core.info('PVC Bound');
|
||||||
this.setPodNameAndContainerName(await this.getPod());
|
this.setPodNameAndContainerName(await this.getPod());
|
||||||
core.info('Watching pod and streaming logs');
|
core.info('Watching pod and streaming logs');
|
||||||
|
|
@ -358,24 +366,19 @@ class Kubernetes implements RemoteBuilderProviderInterface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async watchUntilPodRunning() {
|
async getPodStatusPhase() {
|
||||||
let ready = false;
|
return (await this.kubeClient.readNamespacedPod(this.podName, this.namespace))?.body.status?.phase;
|
||||||
|
|
||||||
while (!ready) {
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
||||||
const pod = (await this.kubeClient.readNamespacedPod(this.podName, this.namespace))?.body;
|
|
||||||
if (pod === undefined) {
|
|
||||||
throw new Error('no pod found');
|
|
||||||
}
|
}
|
||||||
const phase = pod.status?.phase;
|
|
||||||
|
async watchUntilPodRunning() {
|
||||||
|
await waitUntil(async () => {
|
||||||
|
(await this.getPodStatusPhase()) !== 'Pending';
|
||||||
|
});
|
||||||
|
const phase = await this.getPodStatusPhase();
|
||||||
if (phase === 'Running') {
|
if (phase === 'Running') {
|
||||||
core.info('Pod no longer pending');
|
core.info('Pod no longer pending');
|
||||||
ready = true;
|
} else {
|
||||||
return;
|
core.error('Pod failed to reach running phase');
|
||||||
}
|
|
||||||
if (phase !== 'Pending') {
|
|
||||||
core.error('Kubernetes job failed');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1211,6 +1211,11 @@ astral-regex@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
|
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
|
||||||
integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
|
integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
|
||||||
|
|
||||||
|
async-wait-until@^2.0.7:
|
||||||
|
version "2.0.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/async-wait-until/-/async-wait-until-2.0.7.tgz#ed4ccfe076850105c1de555381630b9fad882f5d"
|
||||||
|
integrity sha512-SjHxM2f5ev4o87gYppr8HmWPjOHw06Pg5KZvkSl6FMqa3TTHzDGIWCZx61XWjxO5ArPcZBuJYbAa809FNyx3QQ==
|
||||||
|
|
||||||
asynckit@^0.4.0:
|
asynckit@^0.4.0:
|
||||||
version "0.4.0"
|
version "0.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue