Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[teraslice] add typescript types to KubernetesV2 backend #3812

Merged
merged 30 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
9cdaca4
rename resource folders to not be plural
busma13 Oct 30, 2024
8810387
add types to k8s v2
busma13 Oct 30, 2024
af9d638
add types to tests for k8s v2
busma13 Oct 30, 2024
41a1dae
remove commented out code, fix import formatting
busma13 Oct 30, 2024
7eb3e10
revert _getClusterState to previous syntax
busma13 Oct 30, 2024
c6d50e2
replace instanceof checks
busma13 Oct 30, 2024
f38613d
refactor post and list functions
busma13 Oct 30, 2024
033d56d
remove unneeded check
busma13 Oct 30, 2024
4aea696
handle undefined k8sConfig fields
busma13 Oct 31, 2024
5e45e0e
pass required parameters to tests
busma13 Oct 31, 2024
c5fa86c
refactor delete fn
busma13 Oct 31, 2024
3743334
remove retryable
busma13 Oct 31, 2024
dc4b90d
make resourceTypes plural
busma13 Nov 1, 2024
993d605
extend K8sResource class
busma13 Nov 1, 2024
c46ad38
fix jsdoc comments
busma13 Nov 1, 2024
827aab6
removed unused imports
busma13 Nov 1, 2024
383b68e
missed a resourceType rename in test
busma13 Nov 1, 2024
7cfc9c1
accidentally removed undefined checks in makeTemplate
busma13 Nov 1, 2024
fe4f2b0
fix tests
busma13 Nov 2, 2024
6cadcd5
extend k8s resources to TS resources that have required fields
busma13 Nov 6, 2024
73a00e3
release: (minor) [email protected]
busma13 Nov 6, 2024
2e13500
make kubernetes_api_poll_delay mandatory in teraslice Config type
busma13 Nov 6, 2024
d27ce69
remove unneeded undefined checks, typos
busma13 Nov 6, 2024
39425b5
missed an unneeded check
busma13 Nov 6, 2024
cd572d3
merge resource template into instance of resource class. Update imports
busma13 Nov 6, 2024
370df23
reformat imports
busma13 Nov 6, 2024
3787911
k8s-v2-spec update resource creation. env can't be required - not ret…
busma13 Nov 6, 2024
60ca244
remove comment
busma13 Nov 7, 2024
f709489
remove defaults from teraslice Config type
busma13 Nov 7, 2024
b4d02b5
bump: (minor) @terascope/[email protected], @terascope/[email protected]
busma13 Nov 7, 2024
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "teraslice-workspace",
"displayName": "Teraslice",
"version": "2.6.4",
"version": "2.7.0",
"private": true,
"homepage": "https://github.com/terascope/teraslice",
"bugs": {
Expand Down
1 change: 1 addition & 0 deletions packages/job-components/src/test-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ export class TestContext implements i.Context {
analytics: 'yearly',
state: 'montly',
},
kubernetes_api_poll_delay: 1000,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the only kubernetes config or are there other ones as well?

master_hostname: 'localhost',
master: false,
name: testName,
Expand Down
2 changes: 1 addition & 1 deletion packages/teraslice/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "teraslice",
"displayName": "Teraslice",
"version": "2.6.4",
"version": "2.7.0",
"description": "Distributed computing platform for processing JSON data",
"homepage": "https://github.com/terascope/teraslice#readme",
"bugs": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ export class KubernetesClusterBackend {
this.logger,
null,
kubernetesNamespace,
// @ts-expect-error
context.sysconfig.teraslice.kubernetes_api_poll_delay,
context.sysconfig.teraslice.shutdown_timeout
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import {
cloneDeep, pRetry, Logger
} from '@terascope/utils';
import type { Context, ExecutionConfig } from '@terascope/job-components';
import * as K8sClient from '@kubernetes/client-node';
import { makeLogger } from '../../../../../workers/helpers/terafoundation.js';
import { K8sResource } from './k8sResource.js';
import { gen } from './k8sState.js';
import { K8s } from './k8s.js';
import { getRetryConfig } from './utils.js';
import { StopExecutionOptions } from '../../../interfaces.js';
import { ResourceType } from './interfaces.js';
import { K8sJobResource } from './k8sJobResource.js';
import { K8sServiceResource } from './k8sServiceResource.js';
import { K8sDeploymentResource } from './k8sDeploymentResource.js';

/*
Execution Life Cycle for _status
Expand Down Expand Up @@ -42,7 +44,6 @@ export class KubernetesClusterBackendV2 {
this.logger,
null,
kubernetesNamespace,
// @ts-expect-error
context.sysconfig.teraslice.kubernetes_api_poll_delay,
context.sysconfig.teraslice.shutdown_timeout
);
Expand All @@ -65,11 +66,11 @@ export class KubernetesClusterBackendV2 {
* app.kubernetes.io/name=teraslice
* app.kubernetes.io/instance=${clusterNameLabel}
* @constructor
* @return {Promise} [description]
* @return {Promise} void
*/
private async _getClusterState() {
return this.k8s.list(`app.kubernetes.io/name=teraslice,app.kubernetes.io/instance=${this.clusterNameLabel}`, 'pods')
.then((k8sPods) => gen(k8sPods, this.clusterState))
.then((tsPodList) => gen(tsPodList, this.clusterState))
.catch((err) => {
// TODO: We might need to do more here. I think it's OK to just
// log though. This only gets used to show slicer info through
Expand Down Expand Up @@ -106,49 +107,51 @@ export class KubernetesClusterBackendV2 {

execution.slicer_port = 45680;

const exJobResource = new K8sResource(
'jobs',
'execution_controller',
const exJobResource = new K8sJobResource(
this.context.sysconfig.teraslice,
execution,
this.logger
);

const exJob = exJobResource.resource;

this.logger.debug(exJob, 'execution allocating slicer');

const jobResult = await this.k8s.post(exJob, 'job') as K8sClient.V1Job;
const jobResult = await this.k8s.post(exJob);

// I need to add these here to create the ex service resource
// @ts-expect-error
execution.k8sName = jobResult.metadata.name;
// @ts-expect-error
execution.k8sUid = jobResult.metadata.uid;
if (!jobResult.metadata.uid) {
throw new Error('Required field uid missing from jobResult.metadata');
}

const exServiceResource = new K8sResource(
'services',
'execution_controller',
const exServiceResource = new K8sServiceResource(
this.context.sysconfig.teraslice,
execution,
this.logger
this.logger,
// Needed to create the deployment and service resource ownerReferences
jobResult.metadata.name,
jobResult.metadata.uid
);

const exService = exServiceResource.resource;

const serviceResult = await this.k8s.post(exService, 'service') as K8sClient.V1Service;
const serviceResult = await this.k8s.post(exService);

this.logger.debug(jobResult, 'k8s slicer job submitted');

if (!jobResult.spec.selector?.matchLabels) {
throw new Error('Required field matchLabels missing from jobResult.spec.selector');
}

let controllerLabel: string;
if (jobResult.spec?.selector?.matchLabels?.['controller-uid'] !== undefined) {
if (jobResult.spec.selector.matchLabels['controller-uid'] !== undefined) {
/// If running on kubernetes < v1.27.0
controllerLabel = 'controller-uid';
} else {
/// If running on kubernetes v1.27.0 or later
controllerLabel = 'batch.kubernetes.io/controller-uid';
}

const controllerUid = jobResult.spec?.selector?.matchLabels?.[controllerLabel];
const controllerUid = jobResult.spec.selector.matchLabels[controllerLabel];

const pod = await this.k8s.waitForSelectedPod(
`${controllerLabel}=${controllerUid}`,
Expand All @@ -161,7 +164,7 @@ export class KubernetesClusterBackendV2 {
const error = new Error('pod.status.podIP must be defined');
return Promise.reject(error);
}
const exServiceName = serviceResult.metadata?.name;
const exServiceName = serviceResult.metadata.name;
const exServiceHostName = `${exServiceName}.${this.k8s.defaultNamespace}`;
this.logger.debug(`Slicer is using host name: ${exServiceHostName}`);

Expand All @@ -183,12 +186,8 @@ export class KubernetesClusterBackendV2 {
// instead.
const selector = `app.kubernetes.io/component=execution_controller,teraslice.terascope.io/jobId=${execution.job_id}`;
const jobs = await pRetry(
() => this.k8s.nonEmptyList(selector, 'jobs'), getRetryConfig()
() => this.k8s.nonEmptyJobList(selector), getRetryConfig()
);
// @ts-expect-error
execution.k8sName = jobs.items[0].metadata.name;
// @ts-expect-error
execution.k8sUid = jobs.items[0].metadata.uid;

/// Wait for ex readiness probe to return 'Ready'
await this.k8s.waitForSelectedPod(
Expand All @@ -198,19 +197,23 @@ export class KubernetesClusterBackendV2 {
this.context.sysconfig.teraslice.slicer_timeout
);

const kr = new K8sResource(
'deployments',
'worker',
if (!jobs.items[0].metadata.uid) {
throw new Error('Required field uid missing from kubernetes job metadata');
}

const kr = new K8sDeploymentResource(
this.context.sysconfig.teraslice,
execution,
this.logger
this.logger,
jobs.items[0].metadata.name,
jobs.items[0].metadata.uid
);

const workerDeployment = kr.resource;

this.logger.debug(`workerDeployment:\n\n${JSON.stringify(workerDeployment, null, 2)}`);

return this.k8s.post(workerDeployment, 'deployment')
return this.k8s.post(workerDeployment)
.then((result) => this.logger.debug(`k8s worker deployment submitted: ${JSON.stringify(result)}`))
.catch((err) => {
const error = new TSError(err, {
Expand Down Expand Up @@ -260,12 +263,13 @@ export class KubernetesClusterBackendV2 {
/**
* Returns a list of all k8s resources associated with a job ID
* @param {string} jobId The job ID of the job to list associated resources
* @returns {Array<K8sClient.V1PodList | K8sClient.V1DeploymentList | K8sClient.V1ServiceList
* | K8sClient.V1JobList | K8sClient.V1ReplicaSetList>}
* @returns {Array<TSPod[] | TSDeployment[] | TSService[]
* | TSJob[] | TSReplicaSet[]>}
*/
async listResourcesForJobId(jobId: string) {
const resources = [];
const resourceTypes = ['pods', 'deployments', 'services', 'jobs', 'replicasets'];
const resourceTypes: ResourceType[] = ['pods', 'deployments', 'services', 'jobs', 'replicasets'];

for (const type of resourceTypes) {
const list = await this.k8s.list(`teraslice.terascope.io/jobId=${jobId}`, type);
if (list.items.length > 0) {
Expand Down
Loading
Loading