@controlplane/cli
Version:
Control Plane Corporation CLI
182 lines • 7.73 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.K8sWorkloadHandler = void 0;
const pod_template_1 = require("../processors/pod-template");
const helper_1 = require("../../util/helper");
class K8sWorkloadHandler {
constructor(filePath, k8sWorkload, mapper) {
this.filePath = filePath;
this.k8sWorkload = k8sWorkload;
this.mapper = mapper;
this.workload = {
kind: 'workload',
name: k8sWorkload.metadata.name,
spec: {
type: 'serverless',
containers: [],
defaultOptions: {
autoscaling: {
minScale: 1,
maxScale: 1,
},
capacityAI: false,
},
},
};
}
/*** Public Methods ***/
handle() {
var _a;
// Validate K8s workload
this.validate();
// Process labels as tags
if ((_a = this.k8sWorkload.spec.template.metadata) === null || _a === void 0 ? void 0 : _a.labels) {
this.workload.tags = this.k8sWorkload.spec.template.metadata.labels;
}
if (!this.workload.tags || Object.keys(this.workload.tags).length == 0) {
this.workload.tags = this.k8sWorkload.metadata.labels;
}
// Handle suspend
if (this.k8sWorkload.spec.paused) {
this.workload.spec.defaultOptions.suspend = true;
}
// Process template property
const templateProcessor = new pod_template_1.K8sPodTemplateProcessor(this.filePath, 'spec.template', this.k8sWorkload, this.workload, this.k8sWorkload.spec.template, this.mapper);
templateProcessor.process();
// Process autoscaling
this.processAutoscaling();
// Process rollout options
this.processRolloutOptions();
// Determine Workload Type
this.determineWorkloadType();
return this.workload;
}
/*** Private Methods ***/
processAutoscaling() {
// Process replicas first
if (this.k8sWorkload.spec.replicas) {
this.workload.spec.defaultOptions.autoscaling.minScale = this.k8sWorkload.spec.replicas;
this.workload.spec.defaultOptions.autoscaling.maxScale = this.k8sWorkload.spec.replicas;
}
// Override the value set previously with HPA if it is specified
this.processHpa();
}
processHpa() {
if (!this.mapper.k8sWorkloadNameToHpa[this.k8sWorkload.metadata.name]) {
return;
}
const hpa = this.mapper.k8sWorkloadNameToHpa[this.workload.name];
// Handle min and max scales
if (hpa.spec.minReplicas) {
this.workload.spec.defaultOptions.autoscaling.minScale = hpa.spec.minReplicas;
}
if (hpa.spec.maxReplicas) {
this.workload.spec.defaultOptions.autoscaling.maxScale = hpa.spec.maxReplicas;
}
// Handle scale to zero delay
if (hpa.spec.behavior && hpa.spec.behavior.scaleDown && hpa.spec.behavior.scaleDown.stabilizationWindowSeconds) {
this.workload.spec.defaultOptions.autoscaling.scaleToZeroDelay = hpa.spec.behavior.scaleDown.stabilizationWindowSeconds;
}
// Handle CPU Utilization target value
if (hpa.spec.metrics) {
for (const metric of hpa.spec.metrics) {
if (metric.containerResource &&
metric.containerResource.name.toLowerCase() === 'cpu' &&
metric.containerResource.target.type.toLowerCase() === 'utilization') {
// Take the first target value found
this.workload.spec.defaultOptions.autoscaling.target = metric.containerResource.target.averageUtilization;
break;
}
}
}
}
processRolloutOptions() {
if (!this.k8sWorkload.spec.minReadySeconds &&
!this.k8sWorkload.spec.podManagementPolicy &&
!this.k8sWorkload.spec.strategy &&
!this.k8sWorkload.spec.updateStrategy) {
return;
}
const rolloutOptions = {
minReadySeconds: this.k8sWorkload.spec.minReadySeconds || 0,
maxUnavailableReplicas: '1',
maxSurgeReplicas: '25%',
scalingPolicy: 'OrderedReady',
};
// Update strategy
if (this.k8sWorkload.spec.strategy && this.k8sWorkload.spec.strategy.rollingUpdate) {
// Set max surge replicas
if (this.k8sWorkload.spec.strategy.rollingUpdate.maxSurge) {
rolloutOptions.maxSurgeReplicas = this.k8sWorkload.spec.strategy.rollingUpdate.maxSurge.toString();
}
// Set max unavailable replicas
if (this.k8sWorkload.spec.strategy.rollingUpdate.maxUnavailable) {
rolloutOptions.maxUnavailableReplicas = this.k8sWorkload.spec.strategy.rollingUpdate.maxUnavailable.toString();
}
}
if (this.k8sWorkload.spec.updateStrategy && this.k8sWorkload.spec.updateStrategy.rollingUpdate) {
// Set max unavailable replicas
if (this.k8sWorkload.spec.updateStrategy.rollingUpdate.maxUnavailable) {
rolloutOptions.maxUnavailableReplicas = this.k8sWorkload.spec.updateStrategy.rollingUpdate.maxUnavailable.toString();
}
}
// Update scaling policy
if (this.k8sWorkload.spec.podManagementPolicy) {
rolloutOptions.scalingPolicy = this.k8sWorkload.spec.podManagementPolicy;
}
this.workload.spec.rolloutOptions = rolloutOptions;
}
determineWorkloadType() {
// Check if workload type is 'standard' and/or 'stateful'
let isStandard = false;
let isStateful = false;
// Iterate over each container
for (const container of this.workload.spec.containers) {
// Check if the container is mounting a volume set as a volume
if (container.volumes) {
for (const volume of container.volumes) {
if (volume.uri.includes('cpln://volumeset')) {
isStateful = true;
break;
}
}
}
// Check if the container has many or no ports exposed
if (!container.ports || container.ports.length == 0 || container.ports.length > 1) {
isStandard = true;
break;
}
// Check if liveness or readiness probes has grpc used
if (container.livenessProbe && container.livenessProbe.grpc) {
isStandard = true;
break;
}
if (container.readinessProbe && container.readinessProbe.grpc) {
isStandard = true;
break;
}
}
// Check if workload has rollout options
if (this.workload.spec.rolloutOptions) {
isStandard = true;
}
if (isStandard) {
this.workload.spec.type = 'standard';
}
// Type 'stateful' is stronger than type 'standard'
if (isStateful) {
this.workload.spec.type = 'stateful';
}
}
// Validators //
validate() {
if (!this.k8sWorkload.spec) {
(0, helper_1.ensurePropertyPresence)('spec', this.filePath, this.k8sWorkload);
}
if (!this.k8sWorkload.spec.template) {
(0, helper_1.ensurePropertyPresence)('spec.template', this.filePath, this.k8sWorkload);
}
}
}
exports.K8sWorkloadHandler = K8sWorkloadHandler;
//# sourceMappingURL=workload.js.map