1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

allow to scale replication controllers

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2023-02-15 15:43:53 +02:00
parent 1d08dd8300
commit 7f6a46b987
3 changed files with 122 additions and 7 deletions

View File

@ -6,7 +6,7 @@
import type { DerivedKubeApiOptions, KubeApiDependencies } from "../kube-api";
import { KubeApi } from "../kube-api";
import type {
BaseKubeObjectCondition,
BaseKubeObjectCondition, KubeObjectMetadata,
KubeObjectStatus,
NamespaceScopedMetadata,
} from "../kube-object";
@ -25,7 +25,7 @@ export class ReplicationControllerApi extends KubeApi<ReplicationController> {
return `${this.formatUrlForNotListing(params)}/scale`;
}
getScale(params: { namespace: string; name: string }) {
getScale(params: { namespace: string; name: string }): Promise<Scale> {
return this.request.get(this.getScaleApiUrl(params));
}
@ -37,9 +37,25 @@ export class ReplicationControllerApi extends KubeApi<ReplicationController> {
replicas,
},
},
}, {
headers: {
"content-type": "application/strategic-merge-patch+json",
},
});
}
}
export interface Scale {
apiVersion: "autoscaling/v1";
kind: "Scale";
metadata: KubeObjectMetadata;
spec: {
replicas: number;
};
status: {
replicas: number;
selector: string;
};
}
export interface ReplicationControllerSpec {
@ -115,8 +131,8 @@ export class ReplicationController extends KubeObject<
return this.status?.replicas;
}
getDesiredReplicas(): number | undefined {
return this.spec?.replicas;
getDesiredReplicas(): number {
return this.spec?.replicas ?? 0;
}
getAvailableReplicas(): number | undefined {

View File

@ -4,4 +4,10 @@
*/
.ReplicationControllerDetails {
.desiredReplicas {
display: flex;
gap: calc(var(--margin) * 2);
align-items: center;
}
}

View File

@ -5,6 +5,7 @@
import styles from "./replicationcontroller-details.module.scss";
import React from "react";
import { makeObservable, observable } from "mobx";
import { observer } from "mobx-react";
import { withInjectables } from "@ogre-tools/injectable-react";
import { DrawerItem, DrawerTitle } from "../drawer";
@ -12,17 +13,106 @@ import { Badge } from "../badge";
import type { KubeObjectDetailsProps } from "../kube-object-details";
import type { ReplicationControllerStore } from "./replicationcontroller-store";
import replicationControllerStoreInjectable from "./replicationcontroller-store.injectable";
import type { ReplicationController } from "../../../common/k8s-api/endpoints";
import type {
ReplicationController,
ReplicationControllerApi,
} from "../../../common/k8s-api/endpoints";
import replicationControllerApiInjectable
from "../../../common/k8s-api/endpoints/replication-controller.api.injectable";
import { Button } from "../button";
import { Input } from "../input";
import showErrorNotificationInjectable from "../notifications/show-error-notification.injectable";
import type { ShowNotification } from "../notifications";
import hideDetailsInjectable from "../kube-detail-params/hide-details.injectable";
export interface ReplicationControllerDetailsProps extends KubeObjectDetailsProps<ReplicationController> {
}
interface Dependencies {
store: ReplicationControllerStore;
api: ReplicationControllerApi;
showNotificationError: ShowNotification;
hideDetails(): void;
}
@observer
class NonInjectedReplicationControllerDetails extends React.Component<ReplicationControllerDetailsProps & Dependencies> {
class NonInjectedReplicationControllerDetails<Props extends ReplicationControllerDetailsProps & Dependencies> extends React.Component<Props> {
@observable showScaleDialog = false;
constructor(props: Props) {
super(props);
makeObservable(this);
}
inputRef = React.createRef<Input>();
scale(replicas: number) {
const { object: resource, api } = this.props;
return api.scale({
name: resource.getName(),
namespace: resource.getNs(),
}, replicas);
}
renderReplicasAndScaleDialog() {
const { object: resource, showNotificationError, hideDetails } = this.props;
if (this.showScaleDialog) {
return (
<div className={styles.desiredReplicas}>
<Input
type="number"
min={1}
max={100}
defaultValue={resource.getDesiredReplicas().toString()}
ref={this.inputRef}
/>
<Button
accent
label="Cancel"
onClick={() => this.showScaleDialog = false}
/>
<Button
primary
label="Scale"
onClick={async () => {
const inputComponent = this.inputRef.current;
const newScaleVal = Number(inputComponent?.getValue());
if (isNaN(newScaleVal)) return;
try {
await this.scale(newScaleVal);
this.showScaleDialog = false;
hideDetails();
} catch (err) {
showNotificationError(String(err));
}
}}
/>
</div>
);
}
return (
<div className={styles.desiredReplicas}>
<div>
{resource.getDesiredReplicas()}
</div>
<Button
primary
label="Scale"
onClick={() => {
this.showScaleDialog = true;
requestAnimationFrame(() => this.inputRef.current?.focus());
}}
/>
</div>
);
}
render() {
const { object: resource } = this.props;
@ -32,7 +122,7 @@ class NonInjectedReplicationControllerDetails extends React.Component<Replicatio
Spec
</DrawerTitle>
<DrawerItem name="Desired Replicas">
{resource.getDesiredReplicas()}
{this.renderReplicasAndScaleDialog()}
</DrawerItem>
<DrawerItem name="Selectors" labelsOnly>
{
@ -67,5 +157,8 @@ export const ReplicationControllerDetails = withInjectables<Dependencies, Replic
getProps: (di, props) => ({
...props,
store: di.inject(replicationControllerStoreInjectable),
api: di.inject(replicationControllerApiInjectable),
showNotificationError: di.inject(showErrorNotificationInjectable),
hideDetails: di.inject(hideDetailsInjectable),
}),
});