/** * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { IAffinity } from "../workload-kube-object"; import { WorkloadKubeObject } from "../workload-kube-object"; import { autoBind } from "../../utils"; import { KubeApi } from "../kube-api"; import { metricsApi } from "./metrics.api"; import type { IPodMetrics } from "./pods.api"; import type { KubeJsonApiData } from "../kube-json-api"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import type { LabelSelector } from "../kube-object"; export class StatefulSetApi extends KubeApi { protected getScaleApiUrl(params: { namespace: string; name: string }) { return `${this.getUrl(params)}/scale`; } getReplicas(params: { namespace: string; name: string }): Promise { return this.request .get(this.getScaleApiUrl(params)) .then(({ status }: any) => status?.replicas); } scale(params: { namespace: string; name: string }, replicas: number) { return this.request.patch(this.getScaleApiUrl(params), { data: { spec: { replicas, }, }, }, { headers: { "content-type": "application/merge-patch+json", }, }); } } export function getMetricsForStatefulSets(statefulSets: StatefulSet[], namespace: string, selector = ""): Promise { const podSelector = statefulSets.map(statefulset => `${statefulset.getName()}-[[:digit:]]+`).join("|"); const opts = { category: "pods", pods: podSelector, namespace, selector }; return metricsApi.getMetrics({ cpuUsage: opts, memoryUsage: opts, fsUsage: opts, fsWrites: opts, fsReads: opts, networkReceive: opts, networkTransmit: opts, }, { namespace, }); } export class StatefulSet extends WorkloadKubeObject { static kind = "StatefulSet"; static namespaced = true; static apiBase = "/apis/apps/v1/statefulsets"; constructor(data: KubeJsonApiData) { super(data); autoBind(this); } declare spec: { serviceName: string; replicas: number; selector: LabelSelector; template: { metadata: { labels: { app: string; }; }; spec: { containers: null | { name: string; image: string; ports: { containerPort: number; name: string; }[]; volumeMounts: { name: string; mountPath: string; }[]; }[]; affinity?: IAffinity; nodeSelector?: { [selector: string]: string; }; tolerations: { key: string; operator: string; effect: string; tolerationSeconds: number; }[]; }; }; volumeClaimTemplates: { metadata: { name: string; }; spec: { accessModes: string[]; resources: { requests: { storage: string; }; }; }; }[]; }; declare status: { observedGeneration: number; replicas: number; currentReplicas: number; readyReplicas: number; currentRevision: string; updateRevision: string; collisionCount: number; }; getReplicas() { return this.spec.replicas || 0; } getImages() { const containers = this.spec.template?.spec?.containers ?? []; return containers.map(container => container.image); } } let statefulSetApi: StatefulSetApi; if (isClusterPageContext()) { statefulSetApi = new StatefulSetApi({ objectConstructor: StatefulSet, }); } export { statefulSetApi, };