fix(kube): action namespace, race condition, stability, dark mode #86
@ -19,7 +19,7 @@ type ActiveModal =
|
|||||||
| { type: "delete"; cm: ConfigMapInfo }
|
| { type: "delete"; cm: ConfigMapInfo }
|
||||||
| null;
|
| null;
|
||||||
|
|
||||||
export function ConfigMapList({ configmaps, clusterId, namespace, onRefresh }: ConfigMapListProps) {
|
export function ConfigMapList({ configmaps, clusterId, namespace: _namespace, onRefresh }: ConfigMapListProps) {
|
||||||
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
||||||
const [isDeleting, setIsDeleting] = useState(false);
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
const [actionError, setActionError] = useState<string | null>(null);
|
const [actionError, setActionError] = useState<string | null>(null);
|
||||||
@ -27,7 +27,7 @@ export function ConfigMapList({ configmaps, clusterId, namespace, onRefresh }: C
|
|||||||
const openEdit = async (cm: ConfigMapInfo) => {
|
const openEdit = async (cm: ConfigMapInfo) => {
|
||||||
setActionError(null);
|
setActionError(null);
|
||||||
try {
|
try {
|
||||||
const yaml = await getResourceYamlCmd(clusterId, "configmaps", namespace, cm.name);
|
const yaml = await getResourceYamlCmd(clusterId, "configmaps", cm.namespace, cm.name);
|
||||||
setActiveModal({ type: "edit", cm, yaml });
|
setActiveModal({ type: "edit", cm, yaml });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setActionError(err instanceof Error ? err.message : String(err));
|
setActionError(err instanceof Error ? err.message : String(err));
|
||||||
@ -38,7 +38,7 @@ export function ConfigMapList({ configmaps, clusterId, namespace, onRefresh }: C
|
|||||||
if (activeModal?.type !== "delete") return;
|
if (activeModal?.type !== "delete") return;
|
||||||
setIsDeleting(true);
|
setIsDeleting(true);
|
||||||
try {
|
try {
|
||||||
await deleteResourceCmd(clusterId, "configmaps", namespace, activeModal.cm.name);
|
await deleteResourceCmd(clusterId, "configmaps", activeModal.cm.namespace, activeModal.cm.name);
|
||||||
setActiveModal(null);
|
setActiveModal(null);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
} finally {
|
} finally {
|
||||||
@ -104,7 +104,7 @@ export function ConfigMapList({ configmaps, clusterId, namespace, onRefresh }: C
|
|||||||
<EditResourceModal
|
<EditResourceModal
|
||||||
isOpen
|
isOpen
|
||||||
clusterId={clusterId}
|
clusterId={clusterId}
|
||||||
namespace={namespace}
|
namespace={activeModal.cm.namespace}
|
||||||
resourceType="configmaps"
|
resourceType="configmaps"
|
||||||
resourceName={activeModal.cm.name}
|
resourceName={activeModal.cm.name}
|
||||||
initialYaml={activeModal.yaml}
|
initialYaml={activeModal.yaml}
|
||||||
|
|||||||
@ -31,12 +31,9 @@ export function CronJobList({
|
|||||||
cronJobs,
|
cronJobs,
|
||||||
clusterId,
|
clusterId,
|
||||||
_clusterId,
|
_clusterId,
|
||||||
namespace,
|
|
||||||
_namespace,
|
|
||||||
onRefresh,
|
onRefresh,
|
||||||
}: CronJobListProps) {
|
}: CronJobListProps) {
|
||||||
const cid = clusterId ?? _clusterId ?? "";
|
const cid = clusterId ?? _clusterId ?? "";
|
||||||
const ns = namespace ?? _namespace ?? "";
|
|
||||||
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
||||||
const [isDeleting, setIsDeleting] = useState(false);
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
const [actionError, setActionError] = useState<string | null>(null);
|
const [actionError, setActionError] = useState<string | null>(null);
|
||||||
@ -44,7 +41,7 @@ export function CronJobList({
|
|||||||
const openEdit = async (cj: CronJobInfo) => {
|
const openEdit = async (cj: CronJobInfo) => {
|
||||||
setActionError(null);
|
setActionError(null);
|
||||||
try {
|
try {
|
||||||
const yaml = await getResourceYamlCmd(cid, "cronjobs", ns, cj.name);
|
const yaml = await getResourceYamlCmd(cid, "cronjobs", cj.namespace, cj.name);
|
||||||
setActiveModal({ type: "edit", cj, yaml });
|
setActiveModal({ type: "edit", cj, yaml });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setActionError(err instanceof Error ? err.message : String(err));
|
setActionError(err instanceof Error ? err.message : String(err));
|
||||||
@ -54,7 +51,7 @@ export function CronJobList({
|
|||||||
const handleSuspend = async (cj: CronJobInfo) => {
|
const handleSuspend = async (cj: CronJobInfo) => {
|
||||||
setActionError(null);
|
setActionError(null);
|
||||||
try {
|
try {
|
||||||
await suspendCronjobCmd(cid, ns, cj.name);
|
await suspendCronjobCmd(cid, cj.namespace, cj.name);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setActionError(err instanceof Error ? err.message : String(err));
|
setActionError(err instanceof Error ? err.message : String(err));
|
||||||
@ -64,7 +61,7 @@ export function CronJobList({
|
|||||||
const handleResume = async (cj: CronJobInfo) => {
|
const handleResume = async (cj: CronJobInfo) => {
|
||||||
setActionError(null);
|
setActionError(null);
|
||||||
try {
|
try {
|
||||||
await resumeCronjobCmd(cid, ns, cj.name);
|
await resumeCronjobCmd(cid, cj.namespace, cj.name);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setActionError(err instanceof Error ? err.message : String(err));
|
setActionError(err instanceof Error ? err.message : String(err));
|
||||||
@ -74,7 +71,7 @@ export function CronJobList({
|
|||||||
const handleTrigger = async (cj: CronJobInfo) => {
|
const handleTrigger = async (cj: CronJobInfo) => {
|
||||||
setActionError(null);
|
setActionError(null);
|
||||||
try {
|
try {
|
||||||
await triggerCronjobCmd(cid, ns, cj.name);
|
await triggerCronjobCmd(cid, cj.namespace, cj.name);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setActionError(err instanceof Error ? err.message : String(err));
|
setActionError(err instanceof Error ? err.message : String(err));
|
||||||
@ -85,7 +82,7 @@ export function CronJobList({
|
|||||||
if (activeModal?.type !== "delete") return;
|
if (activeModal?.type !== "delete") return;
|
||||||
setIsDeleting(true);
|
setIsDeleting(true);
|
||||||
try {
|
try {
|
||||||
await deleteResourceCmd(cid, "cronjobs", ns, activeModal.cj.name);
|
await deleteResourceCmd(cid, "cronjobs", activeModal.cj.namespace, activeModal.cj.name);
|
||||||
setActiveModal(null);
|
setActiveModal(null);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
} finally {
|
} finally {
|
||||||
@ -183,7 +180,7 @@ export function CronJobList({
|
|||||||
<EditResourceModal
|
<EditResourceModal
|
||||||
isOpen
|
isOpen
|
||||||
clusterId={cid}
|
clusterId={cid}
|
||||||
namespace={ns}
|
namespace={activeModal.cj.namespace}
|
||||||
resourceType="cronjobs"
|
resourceType="cronjobs"
|
||||||
resourceName={activeModal.cj.name}
|
resourceName={activeModal.cj.name}
|
||||||
initialYaml={activeModal.yaml}
|
initialYaml={activeModal.yaml}
|
||||||
|
|||||||
@ -25,12 +25,9 @@ export function HPAList({
|
|||||||
hpas,
|
hpas,
|
||||||
clusterId,
|
clusterId,
|
||||||
_clusterId,
|
_clusterId,
|
||||||
namespace,
|
|
||||||
_namespace,
|
|
||||||
onRefresh,
|
onRefresh,
|
||||||
}: HPAListProps) {
|
}: HPAListProps) {
|
||||||
const cid = clusterId ?? _clusterId ?? "";
|
const cid = clusterId ?? _clusterId ?? "";
|
||||||
const ns = namespace ?? _namespace ?? "";
|
|
||||||
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
||||||
const [isDeleting, setIsDeleting] = useState(false);
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
const [actionError, setActionError] = useState<string | null>(null);
|
const [actionError, setActionError] = useState<string | null>(null);
|
||||||
@ -38,7 +35,7 @@ export function HPAList({
|
|||||||
const openEdit = async (hpa: HorizontalPodAutoscalerInfo) => {
|
const openEdit = async (hpa: HorizontalPodAutoscalerInfo) => {
|
||||||
setActionError(null);
|
setActionError(null);
|
||||||
try {
|
try {
|
||||||
const yaml = await getResourceYamlCmd(cid, "horizontalpodautoscalers", ns, hpa.name);
|
const yaml = await getResourceYamlCmd(cid, "horizontalpodautoscalers", hpa.namespace, hpa.name);
|
||||||
setActiveModal({ type: "edit", hpa, yaml });
|
setActiveModal({ type: "edit", hpa, yaml });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setActionError(err instanceof Error ? err.message : String(err));
|
setActionError(err instanceof Error ? err.message : String(err));
|
||||||
@ -49,7 +46,7 @@ export function HPAList({
|
|||||||
if (activeModal?.type !== "delete") return;
|
if (activeModal?.type !== "delete") return;
|
||||||
setIsDeleting(true);
|
setIsDeleting(true);
|
||||||
try {
|
try {
|
||||||
await deleteResourceCmd(cid, "horizontalpodautoscalers", ns, activeModal.hpa.name);
|
await deleteResourceCmd(cid, "horizontalpodautoscalers", activeModal.hpa.namespace, activeModal.hpa.name);
|
||||||
setActiveModal(null);
|
setActiveModal(null);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
} finally {
|
} finally {
|
||||||
@ -121,7 +118,7 @@ export function HPAList({
|
|||||||
<EditResourceModal
|
<EditResourceModal
|
||||||
isOpen
|
isOpen
|
||||||
clusterId={cid}
|
clusterId={cid}
|
||||||
namespace={ns}
|
namespace={activeModal.hpa.namespace}
|
||||||
resourceType="horizontalpodautoscalers"
|
resourceType="horizontalpodautoscalers"
|
||||||
resourceName={activeModal.hpa.name}
|
resourceName={activeModal.hpa.name}
|
||||||
initialYaml={activeModal.yaml}
|
initialYaml={activeModal.yaml}
|
||||||
|
|||||||
@ -25,12 +25,9 @@ export function IngressList({
|
|||||||
ingresses,
|
ingresses,
|
||||||
clusterId,
|
clusterId,
|
||||||
_clusterId,
|
_clusterId,
|
||||||
namespace,
|
|
||||||
_namespace,
|
|
||||||
onRefresh,
|
onRefresh,
|
||||||
}: IngressListProps) {
|
}: IngressListProps) {
|
||||||
const cid = clusterId ?? _clusterId ?? "";
|
const cid = clusterId ?? _clusterId ?? "";
|
||||||
const ns = namespace ?? _namespace ?? "";
|
|
||||||
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
||||||
const [isDeleting, setIsDeleting] = useState(false);
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
const [actionError, setActionError] = useState<string | null>(null);
|
const [actionError, setActionError] = useState<string | null>(null);
|
||||||
@ -38,7 +35,7 @@ export function IngressList({
|
|||||||
const openEdit = async (ingress: IngressInfo) => {
|
const openEdit = async (ingress: IngressInfo) => {
|
||||||
setActionError(null);
|
setActionError(null);
|
||||||
try {
|
try {
|
||||||
const yaml = await getResourceYamlCmd(cid, "ingresses", ns, ingress.name);
|
const yaml = await getResourceYamlCmd(cid, "ingresses", ingress.namespace, ingress.name);
|
||||||
setActiveModal({ type: "edit", ingress, yaml });
|
setActiveModal({ type: "edit", ingress, yaml });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setActionError(err instanceof Error ? err.message : String(err));
|
setActionError(err instanceof Error ? err.message : String(err));
|
||||||
@ -49,7 +46,7 @@ export function IngressList({
|
|||||||
if (activeModal?.type !== "delete") return;
|
if (activeModal?.type !== "delete") return;
|
||||||
setIsDeleting(true);
|
setIsDeleting(true);
|
||||||
try {
|
try {
|
||||||
await deleteResourceCmd(cid, "ingresses", ns, activeModal.ingress.name);
|
await deleteResourceCmd(cid, "ingresses", activeModal.ingress.namespace, activeModal.ingress.name);
|
||||||
setActiveModal(null);
|
setActiveModal(null);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
} finally {
|
} finally {
|
||||||
@ -119,7 +116,7 @@ export function IngressList({
|
|||||||
<EditResourceModal
|
<EditResourceModal
|
||||||
isOpen
|
isOpen
|
||||||
clusterId={cid}
|
clusterId={cid}
|
||||||
namespace={ns}
|
namespace={activeModal.ingress.namespace}
|
||||||
resourceType="ingresses"
|
resourceType="ingresses"
|
||||||
resourceName={activeModal.ingress.name}
|
resourceName={activeModal.ingress.name}
|
||||||
initialYaml={activeModal.yaml}
|
initialYaml={activeModal.yaml}
|
||||||
|
|||||||
@ -25,12 +25,9 @@ export function JobList({
|
|||||||
jobs,
|
jobs,
|
||||||
clusterId,
|
clusterId,
|
||||||
_clusterId,
|
_clusterId,
|
||||||
namespace,
|
|
||||||
_namespace,
|
|
||||||
onRefresh,
|
onRefresh,
|
||||||
}: JobListProps) {
|
}: JobListProps) {
|
||||||
const cid = clusterId ?? _clusterId ?? "";
|
const cid = clusterId ?? _clusterId ?? "";
|
||||||
const ns = namespace ?? _namespace ?? "";
|
|
||||||
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
||||||
const [isDeleting, setIsDeleting] = useState(false);
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
const [actionError, setActionError] = useState<string | null>(null);
|
const [actionError, setActionError] = useState<string | null>(null);
|
||||||
@ -38,7 +35,7 @@ export function JobList({
|
|||||||
const openEdit = async (job: JobInfo) => {
|
const openEdit = async (job: JobInfo) => {
|
||||||
setActionError(null);
|
setActionError(null);
|
||||||
try {
|
try {
|
||||||
const yaml = await getResourceYamlCmd(cid, "jobs", ns, job.name);
|
const yaml = await getResourceYamlCmd(cid, "jobs", job.namespace, job.name);
|
||||||
setActiveModal({ type: "edit", job, yaml });
|
setActiveModal({ type: "edit", job, yaml });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setActionError(err instanceof Error ? err.message : String(err));
|
setActionError(err instanceof Error ? err.message : String(err));
|
||||||
@ -49,7 +46,7 @@ export function JobList({
|
|||||||
if (activeModal?.type !== "delete") return;
|
if (activeModal?.type !== "delete") return;
|
||||||
setIsDeleting(true);
|
setIsDeleting(true);
|
||||||
try {
|
try {
|
||||||
await deleteResourceCmd(cid, "jobs", ns, activeModal.job.name);
|
await deleteResourceCmd(cid, "jobs", activeModal.job.namespace, activeModal.job.name);
|
||||||
setActiveModal(null);
|
setActiveModal(null);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
} finally {
|
} finally {
|
||||||
@ -123,7 +120,7 @@ export function JobList({
|
|||||||
<EditResourceModal
|
<EditResourceModal
|
||||||
isOpen
|
isOpen
|
||||||
clusterId={cid}
|
clusterId={cid}
|
||||||
namespace={ns}
|
namespace={activeModal.job.namespace}
|
||||||
resourceType="jobs"
|
resourceType="jobs"
|
||||||
resourceName={activeModal.job.name}
|
resourceName={activeModal.job.name}
|
||||||
initialYaml={activeModal.yaml}
|
initialYaml={activeModal.yaml}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ type ActiveModal =
|
|||||||
| { type: "delete"; lr: LimitRangeInfo }
|
| { type: "delete"; lr: LimitRangeInfo }
|
||||||
| null;
|
| null;
|
||||||
|
|
||||||
export function LimitRangeList({ limitranges, clusterId, namespace, onRefresh }: LimitRangeListProps) {
|
export function LimitRangeList({ limitranges, clusterId, namespace: _namespace, onRefresh }: LimitRangeListProps) {
|
||||||
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
||||||
const [isDeleting, setIsDeleting] = useState(false);
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
const [actionError, setActionError] = useState<string | null>(null);
|
const [actionError, setActionError] = useState<string | null>(null);
|
||||||
@ -27,7 +27,7 @@ export function LimitRangeList({ limitranges, clusterId, namespace, onRefresh }:
|
|||||||
const openEdit = async (lr: LimitRangeInfo) => {
|
const openEdit = async (lr: LimitRangeInfo) => {
|
||||||
setActionError(null);
|
setActionError(null);
|
||||||
try {
|
try {
|
||||||
const yaml = await getResourceYamlCmd(clusterId, "limitranges", namespace, lr.name);
|
const yaml = await getResourceYamlCmd(clusterId, "limitranges", lr.namespace, lr.name);
|
||||||
setActiveModal({ type: "edit", lr, yaml });
|
setActiveModal({ type: "edit", lr, yaml });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setActionError(err instanceof Error ? err.message : String(err));
|
setActionError(err instanceof Error ? err.message : String(err));
|
||||||
@ -38,7 +38,7 @@ export function LimitRangeList({ limitranges, clusterId, namespace, onRefresh }:
|
|||||||
if (activeModal?.type !== "delete") return;
|
if (activeModal?.type !== "delete") return;
|
||||||
setIsDeleting(true);
|
setIsDeleting(true);
|
||||||
try {
|
try {
|
||||||
await deleteResourceCmd(clusterId, "limitranges", namespace, activeModal.lr.name);
|
await deleteResourceCmd(clusterId, "limitranges", activeModal.lr.namespace, activeModal.lr.name);
|
||||||
setActiveModal(null);
|
setActiveModal(null);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
} finally {
|
} finally {
|
||||||
@ -104,7 +104,7 @@ export function LimitRangeList({ limitranges, clusterId, namespace, onRefresh }:
|
|||||||
<EditResourceModal
|
<EditResourceModal
|
||||||
isOpen
|
isOpen
|
||||||
clusterId={clusterId}
|
clusterId={clusterId}
|
||||||
namespace={namespace}
|
namespace={activeModal.lr.namespace}
|
||||||
resourceType="limitranges"
|
resourceType="limitranges"
|
||||||
resourceName={activeModal.lr.name}
|
resourceName={activeModal.lr.name}
|
||||||
initialYaml={activeModal.yaml}
|
initialYaml={activeModal.yaml}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ type ActiveModal =
|
|||||||
| { type: "delete"; np: NetworkPolicyInfo }
|
| { type: "delete"; np: NetworkPolicyInfo }
|
||||||
| null;
|
| null;
|
||||||
|
|
||||||
export function NetworkPolicyList({ networkpolicies, clusterId, namespace, onRefresh }: NetworkPolicyListProps) {
|
export function NetworkPolicyList({ networkpolicies, clusterId, namespace: _namespace, onRefresh }: NetworkPolicyListProps) {
|
||||||
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
||||||
const [isDeleting, setIsDeleting] = useState(false);
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
const [actionError, setActionError] = useState<string | null>(null);
|
const [actionError, setActionError] = useState<string | null>(null);
|
||||||
@ -27,7 +27,7 @@ export function NetworkPolicyList({ networkpolicies, clusterId, namespace, onRef
|
|||||||
const openEdit = async (np: NetworkPolicyInfo) => {
|
const openEdit = async (np: NetworkPolicyInfo) => {
|
||||||
setActionError(null);
|
setActionError(null);
|
||||||
try {
|
try {
|
||||||
const yaml = await getResourceYamlCmd(clusterId, "networkpolicies", namespace, np.name);
|
const yaml = await getResourceYamlCmd(clusterId, "networkpolicies", np.namespace, np.name);
|
||||||
setActiveModal({ type: "edit", np, yaml });
|
setActiveModal({ type: "edit", np, yaml });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setActionError(err instanceof Error ? err.message : String(err));
|
setActionError(err instanceof Error ? err.message : String(err));
|
||||||
@ -38,7 +38,7 @@ export function NetworkPolicyList({ networkpolicies, clusterId, namespace, onRef
|
|||||||
if (activeModal?.type !== "delete") return;
|
if (activeModal?.type !== "delete") return;
|
||||||
setIsDeleting(true);
|
setIsDeleting(true);
|
||||||
try {
|
try {
|
||||||
await deleteResourceCmd(clusterId, "networkpolicies", namespace, activeModal.np.name);
|
await deleteResourceCmd(clusterId, "networkpolicies", activeModal.np.namespace, activeModal.np.name);
|
||||||
setActiveModal(null);
|
setActiveModal(null);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
} finally {
|
} finally {
|
||||||
@ -106,7 +106,7 @@ export function NetworkPolicyList({ networkpolicies, clusterId, namespace, onRef
|
|||||||
<EditResourceModal
|
<EditResourceModal
|
||||||
isOpen
|
isOpen
|
||||||
clusterId={clusterId}
|
clusterId={clusterId}
|
||||||
namespace={namespace}
|
namespace={activeModal.np.namespace}
|
||||||
resourceType="networkpolicies"
|
resourceType="networkpolicies"
|
||||||
resourceName={activeModal.np.name}
|
resourceName={activeModal.np.name}
|
||||||
initialYaml={activeModal.yaml}
|
initialYaml={activeModal.yaml}
|
||||||
|
|||||||
@ -25,12 +25,9 @@ export function PVCList({
|
|||||||
pvcs,
|
pvcs,
|
||||||
clusterId,
|
clusterId,
|
||||||
_clusterId,
|
_clusterId,
|
||||||
namespace,
|
|
||||||
_namespace,
|
|
||||||
onRefresh,
|
onRefresh,
|
||||||
}: PVCListProps) {
|
}: PVCListProps) {
|
||||||
const cid = clusterId ?? _clusterId ?? "";
|
const cid = clusterId ?? _clusterId ?? "";
|
||||||
const ns = namespace ?? _namespace ?? "";
|
|
||||||
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
||||||
const [isDeleting, setIsDeleting] = useState(false);
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
const [actionError, setActionError] = useState<string | null>(null);
|
const [actionError, setActionError] = useState<string | null>(null);
|
||||||
@ -38,7 +35,7 @@ export function PVCList({
|
|||||||
const openEdit = async (pvc: PersistentVolumeClaimInfo) => {
|
const openEdit = async (pvc: PersistentVolumeClaimInfo) => {
|
||||||
setActionError(null);
|
setActionError(null);
|
||||||
try {
|
try {
|
||||||
const yaml = await getResourceYamlCmd(cid, "persistentvolumeclaims", ns, pvc.name);
|
const yaml = await getResourceYamlCmd(cid, "persistentvolumeclaims", pvc.namespace, pvc.name);
|
||||||
setActiveModal({ type: "edit", pvc, yaml });
|
setActiveModal({ type: "edit", pvc, yaml });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setActionError(err instanceof Error ? err.message : String(err));
|
setActionError(err instanceof Error ? err.message : String(err));
|
||||||
@ -49,7 +46,7 @@ export function PVCList({
|
|||||||
if (activeModal?.type !== "delete") return;
|
if (activeModal?.type !== "delete") return;
|
||||||
setIsDeleting(true);
|
setIsDeleting(true);
|
||||||
try {
|
try {
|
||||||
await deleteResourceCmd(cid, "persistentvolumeclaims", ns, activeModal.pvc.name);
|
await deleteResourceCmd(cid, "persistentvolumeclaims", activeModal.pvc.namespace, activeModal.pvc.name);
|
||||||
setActiveModal(null);
|
setActiveModal(null);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
} finally {
|
} finally {
|
||||||
@ -121,7 +118,7 @@ export function PVCList({
|
|||||||
<EditResourceModal
|
<EditResourceModal
|
||||||
isOpen
|
isOpen
|
||||||
clusterId={cid}
|
clusterId={cid}
|
||||||
namespace={ns}
|
namespace={activeModal.pvc.namespace}
|
||||||
resourceType="persistentvolumeclaims"
|
resourceType="persistentvolumeclaims"
|
||||||
resourceName={activeModal.pvc.name}
|
resourceName={activeModal.pvc.name}
|
||||||
initialYaml={activeModal.yaml}
|
initialYaml={activeModal.yaml}
|
||||||
|
|||||||
@ -31,12 +31,9 @@ export function ReplicaSetList({
|
|||||||
replicaSets,
|
replicaSets,
|
||||||
clusterId,
|
clusterId,
|
||||||
_clusterId,
|
_clusterId,
|
||||||
namespace,
|
|
||||||
_namespace,
|
|
||||||
onRefresh,
|
onRefresh,
|
||||||
}: ReplicaSetListProps) {
|
}: ReplicaSetListProps) {
|
||||||
const cid = clusterId ?? _clusterId ?? "";
|
const cid = clusterId ?? _clusterId ?? "";
|
||||||
const ns = namespace ?? _namespace ?? "";
|
|
||||||
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
||||||
const [isActing, setIsActing] = useState(false);
|
const [isActing, setIsActing] = useState(false);
|
||||||
const [actionError, setActionError] = useState<string | null>(null);
|
const [actionError, setActionError] = useState<string | null>(null);
|
||||||
@ -44,7 +41,7 @@ export function ReplicaSetList({
|
|||||||
const openEdit = async (rs: ReplicaSetInfo) => {
|
const openEdit = async (rs: ReplicaSetInfo) => {
|
||||||
setActionError(null);
|
setActionError(null);
|
||||||
try {
|
try {
|
||||||
const yaml = await getResourceYamlCmd(cid, "replicasets", ns, rs.name);
|
const yaml = await getResourceYamlCmd(cid, "replicasets", rs.namespace, rs.name);
|
||||||
setActiveModal({ type: "edit", rs, yaml });
|
setActiveModal({ type: "edit", rs, yaml });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setActionError(err instanceof Error ? err.message : String(err));
|
setActionError(err instanceof Error ? err.message : String(err));
|
||||||
@ -55,7 +52,7 @@ export function ReplicaSetList({
|
|||||||
if (activeModal?.type !== "delete") return;
|
if (activeModal?.type !== "delete") return;
|
||||||
setIsActing(true);
|
setIsActing(true);
|
||||||
try {
|
try {
|
||||||
await deleteResourceCmd(cid, "replicasets", ns, activeModal.rs.name);
|
await deleteResourceCmd(cid, "replicasets", activeModal.rs.namespace, activeModal.rs.name);
|
||||||
setActiveModal(null);
|
setActiveModal(null);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
} finally {
|
} finally {
|
||||||
@ -138,7 +135,7 @@ export function ReplicaSetList({
|
|||||||
resourceName={activeModal.rs.name}
|
resourceName={activeModal.rs.name}
|
||||||
currentReplicas={activeModal.rs.replicas}
|
currentReplicas={activeModal.rs.replicas}
|
||||||
onScale={(replicas) =>
|
onScale={(replicas) =>
|
||||||
scaleReplicasetCmd(cid, ns, activeModal.rs.name, replicas).then(() => {
|
scaleReplicasetCmd(cid, activeModal.rs.namespace, activeModal.rs.name, replicas).then(() => {
|
||||||
setActiveModal(null);
|
setActiveModal(null);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
})
|
})
|
||||||
@ -150,7 +147,7 @@ export function ReplicaSetList({
|
|||||||
<EditResourceModal
|
<EditResourceModal
|
||||||
isOpen
|
isOpen
|
||||||
clusterId={cid}
|
clusterId={cid}
|
||||||
namespace={ns}
|
namespace={activeModal.rs.namespace}
|
||||||
resourceType="replicasets"
|
resourceType="replicasets"
|
||||||
resourceName={activeModal.rs.name}
|
resourceName={activeModal.rs.name}
|
||||||
initialYaml={activeModal.yaml}
|
initialYaml={activeModal.yaml}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ type ActiveModal =
|
|||||||
| { type: "delete"; rq: ResourceQuotaInfo }
|
| { type: "delete"; rq: ResourceQuotaInfo }
|
||||||
| null;
|
| null;
|
||||||
|
|
||||||
export function ResourceQuotaList({ resourcequotas, clusterId, namespace, onRefresh }: ResourceQuotaListProps) {
|
export function ResourceQuotaList({ resourcequotas, clusterId, namespace: _namespace, onRefresh }: ResourceQuotaListProps) {
|
||||||
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
||||||
const [isDeleting, setIsDeleting] = useState(false);
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
const [actionError, setActionError] = useState<string | null>(null);
|
const [actionError, setActionError] = useState<string | null>(null);
|
||||||
@ -27,7 +27,7 @@ export function ResourceQuotaList({ resourcequotas, clusterId, namespace, onRefr
|
|||||||
const openEdit = async (rq: ResourceQuotaInfo) => {
|
const openEdit = async (rq: ResourceQuotaInfo) => {
|
||||||
setActionError(null);
|
setActionError(null);
|
||||||
try {
|
try {
|
||||||
const yaml = await getResourceYamlCmd(clusterId, "resourcequotas", namespace, rq.name);
|
const yaml = await getResourceYamlCmd(clusterId, "resourcequotas", rq.namespace, rq.name);
|
||||||
setActiveModal({ type: "edit", rq, yaml });
|
setActiveModal({ type: "edit", rq, yaml });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setActionError(err instanceof Error ? err.message : String(err));
|
setActionError(err instanceof Error ? err.message : String(err));
|
||||||
@ -38,7 +38,7 @@ export function ResourceQuotaList({ resourcequotas, clusterId, namespace, onRefr
|
|||||||
if (activeModal?.type !== "delete") return;
|
if (activeModal?.type !== "delete") return;
|
||||||
setIsDeleting(true);
|
setIsDeleting(true);
|
||||||
try {
|
try {
|
||||||
await deleteResourceCmd(clusterId, "resourcequotas", namespace, activeModal.rq.name);
|
await deleteResourceCmd(clusterId, "resourcequotas", activeModal.rq.namespace, activeModal.rq.name);
|
||||||
setActiveModal(null);
|
setActiveModal(null);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
} finally {
|
} finally {
|
||||||
@ -110,7 +110,7 @@ export function ResourceQuotaList({ resourcequotas, clusterId, namespace, onRefr
|
|||||||
<EditResourceModal
|
<EditResourceModal
|
||||||
isOpen
|
isOpen
|
||||||
clusterId={clusterId}
|
clusterId={clusterId}
|
||||||
namespace={namespace}
|
namespace={activeModal.rq.namespace}
|
||||||
resourceType="resourcequotas"
|
resourceType="resourcequotas"
|
||||||
resourceName={activeModal.rq.name}
|
resourceName={activeModal.rq.name}
|
||||||
initialYaml={activeModal.yaml}
|
initialYaml={activeModal.yaml}
|
||||||
|
|||||||
@ -25,12 +25,9 @@ export function RoleBindingList({
|
|||||||
roleBindings,
|
roleBindings,
|
||||||
clusterId,
|
clusterId,
|
||||||
_clusterId,
|
_clusterId,
|
||||||
namespace,
|
|
||||||
_namespace,
|
|
||||||
onRefresh,
|
onRefresh,
|
||||||
}: RoleBindingListProps) {
|
}: RoleBindingListProps) {
|
||||||
const cid = clusterId ?? _clusterId ?? "";
|
const cid = clusterId ?? _clusterId ?? "";
|
||||||
const ns = namespace ?? _namespace ?? "";
|
|
||||||
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
||||||
const [isDeleting, setIsDeleting] = useState(false);
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
const [actionError, setActionError] = useState<string | null>(null);
|
const [actionError, setActionError] = useState<string | null>(null);
|
||||||
@ -38,7 +35,7 @@ export function RoleBindingList({
|
|||||||
const openEdit = async (rb: RoleBindingInfo) => {
|
const openEdit = async (rb: RoleBindingInfo) => {
|
||||||
setActionError(null);
|
setActionError(null);
|
||||||
try {
|
try {
|
||||||
const yaml = await getResourceYamlCmd(cid, "rolebindings", ns, rb.name);
|
const yaml = await getResourceYamlCmd(cid, "rolebindings", rb.namespace, rb.name);
|
||||||
setActiveModal({ type: "edit", rb, yaml });
|
setActiveModal({ type: "edit", rb, yaml });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setActionError(err instanceof Error ? err.message : String(err));
|
setActionError(err instanceof Error ? err.message : String(err));
|
||||||
@ -49,7 +46,7 @@ export function RoleBindingList({
|
|||||||
if (activeModal?.type !== "delete") return;
|
if (activeModal?.type !== "delete") return;
|
||||||
setIsDeleting(true);
|
setIsDeleting(true);
|
||||||
try {
|
try {
|
||||||
await deleteResourceCmd(cid, "rolebindings", ns, activeModal.rb.name);
|
await deleteResourceCmd(cid, "rolebindings", activeModal.rb.namespace, activeModal.rb.name);
|
||||||
setActiveModal(null);
|
setActiveModal(null);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
} finally {
|
} finally {
|
||||||
@ -115,7 +112,7 @@ export function RoleBindingList({
|
|||||||
<EditResourceModal
|
<EditResourceModal
|
||||||
isOpen
|
isOpen
|
||||||
clusterId={cid}
|
clusterId={cid}
|
||||||
namespace={ns}
|
namespace={activeModal.rb.namespace}
|
||||||
resourceType="rolebindings"
|
resourceType="rolebindings"
|
||||||
resourceName={activeModal.rb.name}
|
resourceName={activeModal.rb.name}
|
||||||
initialYaml={activeModal.yaml}
|
initialYaml={activeModal.yaml}
|
||||||
|
|||||||
@ -25,12 +25,9 @@ export function RoleList({
|
|||||||
roles,
|
roles,
|
||||||
clusterId,
|
clusterId,
|
||||||
_clusterId,
|
_clusterId,
|
||||||
namespace,
|
|
||||||
_namespace,
|
|
||||||
onRefresh,
|
onRefresh,
|
||||||
}: RoleListProps) {
|
}: RoleListProps) {
|
||||||
const cid = clusterId ?? _clusterId ?? "";
|
const cid = clusterId ?? _clusterId ?? "";
|
||||||
const ns = namespace ?? _namespace ?? "";
|
|
||||||
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
||||||
const [isDeleting, setIsDeleting] = useState(false);
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
const [actionError, setActionError] = useState<string | null>(null);
|
const [actionError, setActionError] = useState<string | null>(null);
|
||||||
@ -38,7 +35,7 @@ export function RoleList({
|
|||||||
const openEdit = async (role: RoleInfo) => {
|
const openEdit = async (role: RoleInfo) => {
|
||||||
setActionError(null);
|
setActionError(null);
|
||||||
try {
|
try {
|
||||||
const yaml = await getResourceYamlCmd(cid, "roles", ns, role.name);
|
const yaml = await getResourceYamlCmd(cid, "roles", role.namespace, role.name);
|
||||||
setActiveModal({ type: "edit", role, yaml });
|
setActiveModal({ type: "edit", role, yaml });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setActionError(err instanceof Error ? err.message : String(err));
|
setActionError(err instanceof Error ? err.message : String(err));
|
||||||
@ -49,7 +46,7 @@ export function RoleList({
|
|||||||
if (activeModal?.type !== "delete") return;
|
if (activeModal?.type !== "delete") return;
|
||||||
setIsDeleting(true);
|
setIsDeleting(true);
|
||||||
try {
|
try {
|
||||||
await deleteResourceCmd(cid, "roles", ns, activeModal.role.name);
|
await deleteResourceCmd(cid, "roles", activeModal.role.namespace, activeModal.role.name);
|
||||||
setActiveModal(null);
|
setActiveModal(null);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
} finally {
|
} finally {
|
||||||
@ -113,7 +110,7 @@ export function RoleList({
|
|||||||
<EditResourceModal
|
<EditResourceModal
|
||||||
isOpen
|
isOpen
|
||||||
clusterId={cid}
|
clusterId={cid}
|
||||||
namespace={ns}
|
namespace={activeModal.role.namespace}
|
||||||
resourceType="roles"
|
resourceType="roles"
|
||||||
resourceName={activeModal.role.name}
|
resourceName={activeModal.role.name}
|
||||||
initialYaml={activeModal.yaml}
|
initialYaml={activeModal.yaml}
|
||||||
|
|||||||
@ -25,12 +25,9 @@ export function SecretList({
|
|||||||
secrets,
|
secrets,
|
||||||
clusterId,
|
clusterId,
|
||||||
_clusterId,
|
_clusterId,
|
||||||
namespace,
|
|
||||||
_namespace,
|
|
||||||
onRefresh,
|
onRefresh,
|
||||||
}: SecretListProps) {
|
}: SecretListProps) {
|
||||||
const cid = clusterId ?? _clusterId ?? "";
|
const cid = clusterId ?? _clusterId ?? "";
|
||||||
const ns = namespace ?? _namespace ?? "";
|
|
||||||
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
||||||
const [isDeleting, setIsDeleting] = useState(false);
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
const [actionError, setActionError] = useState<string | null>(null);
|
const [actionError, setActionError] = useState<string | null>(null);
|
||||||
@ -38,7 +35,7 @@ export function SecretList({
|
|||||||
const openEdit = async (secret: SecretInfo) => {
|
const openEdit = async (secret: SecretInfo) => {
|
||||||
setActionError(null);
|
setActionError(null);
|
||||||
try {
|
try {
|
||||||
const yaml = await getResourceYamlCmd(cid, "secrets", ns, secret.name);
|
const yaml = await getResourceYamlCmd(cid, "secrets", secret.namespace, secret.name);
|
||||||
setActiveModal({ type: "edit", secret, yaml });
|
setActiveModal({ type: "edit", secret, yaml });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setActionError(err instanceof Error ? err.message : String(err));
|
setActionError(err instanceof Error ? err.message : String(err));
|
||||||
@ -49,7 +46,7 @@ export function SecretList({
|
|||||||
if (activeModal?.type !== "delete") return;
|
if (activeModal?.type !== "delete") return;
|
||||||
setIsDeleting(true);
|
setIsDeleting(true);
|
||||||
try {
|
try {
|
||||||
await deleteResourceCmd(cid, "secrets", ns, activeModal.secret.name);
|
await deleteResourceCmd(cid, "secrets", activeModal.secret.namespace, activeModal.secret.name);
|
||||||
setActiveModal(null);
|
setActiveModal(null);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
} finally {
|
} finally {
|
||||||
@ -117,7 +114,7 @@ export function SecretList({
|
|||||||
<EditResourceModal
|
<EditResourceModal
|
||||||
isOpen
|
isOpen
|
||||||
clusterId={cid}
|
clusterId={cid}
|
||||||
namespace={ns}
|
namespace={activeModal.secret.namespace}
|
||||||
resourceType="secrets"
|
resourceType="secrets"
|
||||||
resourceName={activeModal.secret.name}
|
resourceName={activeModal.secret.name}
|
||||||
initialYaml={activeModal.yaml}
|
initialYaml={activeModal.yaml}
|
||||||
|
|||||||
@ -25,12 +25,9 @@ export function ServiceAccountList({
|
|||||||
serviceAccounts,
|
serviceAccounts,
|
||||||
clusterId,
|
clusterId,
|
||||||
_clusterId,
|
_clusterId,
|
||||||
namespace,
|
|
||||||
_namespace,
|
|
||||||
onRefresh,
|
onRefresh,
|
||||||
}: ServiceAccountListProps) {
|
}: ServiceAccountListProps) {
|
||||||
const cid = clusterId ?? _clusterId ?? "";
|
const cid = clusterId ?? _clusterId ?? "";
|
||||||
const ns = namespace ?? _namespace ?? "";
|
|
||||||
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
||||||
const [isDeleting, setIsDeleting] = useState(false);
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
const [actionError, setActionError] = useState<string | null>(null);
|
const [actionError, setActionError] = useState<string | null>(null);
|
||||||
@ -38,7 +35,7 @@ export function ServiceAccountList({
|
|||||||
const openEdit = async (sa: ServiceAccountInfo) => {
|
const openEdit = async (sa: ServiceAccountInfo) => {
|
||||||
setActionError(null);
|
setActionError(null);
|
||||||
try {
|
try {
|
||||||
const yaml = await getResourceYamlCmd(cid, "serviceaccounts", ns, sa.name);
|
const yaml = await getResourceYamlCmd(cid, "serviceaccounts", sa.namespace, sa.name);
|
||||||
setActiveModal({ type: "edit", sa, yaml });
|
setActiveModal({ type: "edit", sa, yaml });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setActionError(err instanceof Error ? err.message : String(err));
|
setActionError(err instanceof Error ? err.message : String(err));
|
||||||
@ -49,7 +46,7 @@ export function ServiceAccountList({
|
|||||||
if (activeModal?.type !== "delete") return;
|
if (activeModal?.type !== "delete") return;
|
||||||
setIsDeleting(true);
|
setIsDeleting(true);
|
||||||
try {
|
try {
|
||||||
await deleteResourceCmd(cid, "serviceaccounts", ns, activeModal.sa.name);
|
await deleteResourceCmd(cid, "serviceaccounts", activeModal.sa.namespace, activeModal.sa.name);
|
||||||
setActiveModal(null);
|
setActiveModal(null);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
} finally {
|
} finally {
|
||||||
@ -115,7 +112,7 @@ export function ServiceAccountList({
|
|||||||
<EditResourceModal
|
<EditResourceModal
|
||||||
isOpen
|
isOpen
|
||||||
clusterId={cid}
|
clusterId={cid}
|
||||||
namespace={ns}
|
namespace={activeModal.sa.namespace}
|
||||||
resourceType="serviceaccounts"
|
resourceType="serviceaccounts"
|
||||||
resourceName={activeModal.sa.name}
|
resourceName={activeModal.sa.name}
|
||||||
initialYaml={activeModal.yaml}
|
initialYaml={activeModal.yaml}
|
||||||
|
|||||||
@ -20,7 +20,7 @@ type ActiveModal =
|
|||||||
| { type: "delete"; svc: ServiceInfo }
|
| { type: "delete"; svc: ServiceInfo }
|
||||||
| null;
|
| null;
|
||||||
|
|
||||||
export function ServiceList({ services, clusterId, namespace, onRefresh }: ServiceListProps) {
|
export function ServiceList({ services, clusterId, namespace: _namespace, onRefresh }: ServiceListProps) {
|
||||||
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
const [activeModal, setActiveModal] = useState<ActiveModal>(null);
|
||||||
const [isDeleting, setIsDeleting] = useState(false);
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
const [actionError, setActionError] = useState<string | null>(null);
|
const [actionError, setActionError] = useState<string | null>(null);
|
||||||
@ -43,7 +43,7 @@ export function ServiceList({ services, clusterId, namespace, onRefresh }: Servi
|
|||||||
const openEdit = async (svc: ServiceInfo) => {
|
const openEdit = async (svc: ServiceInfo) => {
|
||||||
setActionError(null);
|
setActionError(null);
|
||||||
try {
|
try {
|
||||||
const yaml = await getResourceYamlCmd(clusterId, "services", namespace, svc.name);
|
const yaml = await getResourceYamlCmd(clusterId, "services", svc.namespace, svc.name);
|
||||||
setActiveModal({ type: "edit", svc, yaml });
|
setActiveModal({ type: "edit", svc, yaml });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setActionError(err instanceof Error ? err.message : String(err));
|
setActionError(err instanceof Error ? err.message : String(err));
|
||||||
@ -54,7 +54,7 @@ export function ServiceList({ services, clusterId, namespace, onRefresh }: Servi
|
|||||||
if (activeModal?.type !== "delete") return;
|
if (activeModal?.type !== "delete") return;
|
||||||
setIsDeleting(true);
|
setIsDeleting(true);
|
||||||
try {
|
try {
|
||||||
await deleteResourceCmd(clusterId, "services", namespace, activeModal.svc.name);
|
await deleteResourceCmd(clusterId, "services", activeModal.svc.namespace, activeModal.svc.name);
|
||||||
setActiveModal(null);
|
setActiveModal(null);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
} finally {
|
} finally {
|
||||||
@ -140,7 +140,7 @@ export function ServiceList({ services, clusterId, namespace, onRefresh }: Servi
|
|||||||
<EditResourceModal
|
<EditResourceModal
|
||||||
isOpen
|
isOpen
|
||||||
clusterId={clusterId}
|
clusterId={clusterId}
|
||||||
namespace={namespace}
|
namespace={activeModal.svc.namespace}
|
||||||
resourceType="services"
|
resourceType="services"
|
||||||
resourceName={activeModal.svc.name}
|
resourceName={activeModal.svc.name}
|
||||||
initialYaml={activeModal.yaml}
|
initialYaml={activeModal.yaml}
|
||||||
|
|||||||
663
tests/unit/NamespaceActionFix.test.tsx
Normal file
663
tests/unit/NamespaceActionFix.test.tsx
Normal file
@ -0,0 +1,663 @@
|
|||||||
|
/**
|
||||||
|
* TDD tests: action IPC calls in network/config/storage/access-control list
|
||||||
|
* components must use the item's own .namespace, never the filter prop (which
|
||||||
|
* can be "all" when the user is viewing all namespaces).
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||||
|
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
|
||||||
|
import { invoke } from "@tauri-apps/api/core";
|
||||||
|
|
||||||
|
import { ServiceList } from "@/components/Kubernetes/ServiceList";
|
||||||
|
import { IngressList } from "@/components/Kubernetes/IngressList";
|
||||||
|
import { ConfigMapList } from "@/components/Kubernetes/ConfigMapList";
|
||||||
|
import { SecretList } from "@/components/Kubernetes/SecretList";
|
||||||
|
import { HPAList } from "@/components/Kubernetes/HPAList";
|
||||||
|
import { PVCList } from "@/components/Kubernetes/PVCList";
|
||||||
|
import { ServiceAccountList } from "@/components/Kubernetes/ServiceAccountList";
|
||||||
|
import { RoleList } from "@/components/Kubernetes/RoleList";
|
||||||
|
import { RoleBindingList } from "@/components/Kubernetes/RoleBindingList";
|
||||||
|
import { NetworkPolicyList } from "@/components/Kubernetes/NetworkPolicyList";
|
||||||
|
import { ResourceQuotaList } from "@/components/Kubernetes/ResourceQuotaList";
|
||||||
|
import { LimitRangeList } from "@/components/Kubernetes/LimitRangeList";
|
||||||
|
|
||||||
|
import type {
|
||||||
|
ServiceInfo,
|
||||||
|
IngressInfo,
|
||||||
|
ConfigMapInfo,
|
||||||
|
SecretInfo,
|
||||||
|
HorizontalPodAutoscalerInfo,
|
||||||
|
PersistentVolumeClaimInfo,
|
||||||
|
ServiceAccountInfo,
|
||||||
|
RoleInfo,
|
||||||
|
RoleBindingInfo,
|
||||||
|
NetworkPolicyInfo,
|
||||||
|
ResourceQuotaInfo,
|
||||||
|
LimitRangeInfo,
|
||||||
|
} from "@/lib/tauriCommands";
|
||||||
|
|
||||||
|
type MockedInvoke = typeof invoke & {
|
||||||
|
mockResolvedValue: (v: unknown) => void;
|
||||||
|
mockImplementation: (fn: (cmd: string, args?: unknown) => Promise<unknown>) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockInvoke = invoke as MockedInvoke;
|
||||||
|
|
||||||
|
// ─── helpers ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/** Open the action menu for the first row whose name cell matches `name`. */
|
||||||
|
function openActionMenu(name: string) {
|
||||||
|
const cell = screen.getByText(name);
|
||||||
|
const row = cell.closest("tr")!;
|
||||||
|
const btn = row.querySelector("button")!;
|
||||||
|
fireEvent.click(btn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Click the first menu item that contains `label`. */
|
||||||
|
function clickMenuItem(label: string) {
|
||||||
|
const item = screen.getByText(label);
|
||||||
|
fireEvent.click(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── ServiceList ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
describe("ServiceList – action IPC uses item.namespace", () => {
|
||||||
|
const svc: ServiceInfo = {
|
||||||
|
name: "my-svc",
|
||||||
|
namespace: "production",
|
||||||
|
type: "ClusterIP",
|
||||||
|
cluster_ip: "10.0.0.1",
|
||||||
|
ports: [],
|
||||||
|
age: "1d",
|
||||||
|
selector: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => vi.clearAllMocks());
|
||||||
|
|
||||||
|
it("getResourceYamlCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue("yaml: content");
|
||||||
|
render(
|
||||||
|
<ServiceList services={[svc]} clusterId="c1" namespace="all" />
|
||||||
|
);
|
||||||
|
openActionMenu("my-svc");
|
||||||
|
clickMenuItem("Edit");
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("get_resource_yaml", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "services",
|
||||||
|
namespace: "production",
|
||||||
|
resourceName: "my-svc",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("deleteResourceCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue(undefined);
|
||||||
|
render(
|
||||||
|
<ServiceList services={[svc]} clusterId="c1" namespace="all" onRefresh={() => {}} />
|
||||||
|
);
|
||||||
|
openActionMenu("my-svc");
|
||||||
|
clickMenuItem("Delete");
|
||||||
|
const confirmBtn = await screen.findByRole("button", { name: /confirm|delete/i });
|
||||||
|
fireEvent.click(confirmBtn);
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("delete_resource", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "services",
|
||||||
|
namespace: "production",
|
||||||
|
resourceName: "my-svc",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ─── IngressList ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
describe("IngressList – action IPC uses item.namespace", () => {
|
||||||
|
const ing: IngressInfo = {
|
||||||
|
name: "my-ingress",
|
||||||
|
namespace: "staging",
|
||||||
|
host: "example.com",
|
||||||
|
addresses: [],
|
||||||
|
age: "2d",
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => vi.clearAllMocks());
|
||||||
|
|
||||||
|
it("getResourceYamlCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue("yaml: content");
|
||||||
|
render(
|
||||||
|
<IngressList ingresses={[ing]} clusterId="c1" namespace="all" />
|
||||||
|
);
|
||||||
|
openActionMenu("my-ingress");
|
||||||
|
clickMenuItem("Edit");
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("get_resource_yaml", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "ingresses",
|
||||||
|
namespace: "staging",
|
||||||
|
resourceName: "my-ingress",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("deleteResourceCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue(undefined);
|
||||||
|
render(
|
||||||
|
<IngressList ingresses={[ing]} clusterId="c1" namespace="all" onRefresh={() => {}} />
|
||||||
|
);
|
||||||
|
openActionMenu("my-ingress");
|
||||||
|
clickMenuItem("Delete");
|
||||||
|
const confirmBtn = await screen.findByRole("button", { name: /confirm|delete/i });
|
||||||
|
fireEvent.click(confirmBtn);
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("delete_resource", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "ingresses",
|
||||||
|
namespace: "staging",
|
||||||
|
resourceName: "my-ingress",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ─── ConfigMapList ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
describe("ConfigMapList – action IPC uses item.namespace", () => {
|
||||||
|
const cm: ConfigMapInfo = {
|
||||||
|
name: "app-config",
|
||||||
|
namespace: "kube-system",
|
||||||
|
data_keys: 3,
|
||||||
|
age: "10d",
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => vi.clearAllMocks());
|
||||||
|
|
||||||
|
it("getResourceYamlCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue("yaml: content");
|
||||||
|
render(
|
||||||
|
<ConfigMapList configmaps={[cm]} clusterId="c1" namespace="all" />
|
||||||
|
);
|
||||||
|
openActionMenu("app-config");
|
||||||
|
clickMenuItem("Edit");
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("get_resource_yaml", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "configmaps",
|
||||||
|
namespace: "kube-system",
|
||||||
|
resourceName: "app-config",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("deleteResourceCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue(undefined);
|
||||||
|
render(
|
||||||
|
<ConfigMapList configmaps={[cm]} clusterId="c1" namespace="all" onRefresh={() => {}} />
|
||||||
|
);
|
||||||
|
openActionMenu("app-config");
|
||||||
|
clickMenuItem("Delete");
|
||||||
|
const confirmBtn = await screen.findByRole("button", { name: /confirm|delete/i });
|
||||||
|
fireEvent.click(confirmBtn);
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("delete_resource", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "configmaps",
|
||||||
|
namespace: "kube-system",
|
||||||
|
resourceName: "app-config",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ─── SecretList ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
describe("SecretList – action IPC uses item.namespace", () => {
|
||||||
|
const secret: SecretInfo = {
|
||||||
|
name: "db-creds",
|
||||||
|
namespace: "production",
|
||||||
|
type: "Opaque",
|
||||||
|
data_keys: 2,
|
||||||
|
age: "5d",
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => vi.clearAllMocks());
|
||||||
|
|
||||||
|
it("getResourceYamlCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue("yaml: content");
|
||||||
|
render(
|
||||||
|
<SecretList secrets={[secret]} clusterId="c1" namespace="all" />
|
||||||
|
);
|
||||||
|
openActionMenu("db-creds");
|
||||||
|
clickMenuItem("Edit");
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("get_resource_yaml", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "secrets",
|
||||||
|
namespace: "production",
|
||||||
|
resourceName: "db-creds",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("deleteResourceCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue(undefined);
|
||||||
|
render(
|
||||||
|
<SecretList secrets={[secret]} clusterId="c1" namespace="all" onRefresh={() => {}} />
|
||||||
|
);
|
||||||
|
openActionMenu("db-creds");
|
||||||
|
clickMenuItem("Delete");
|
||||||
|
const confirmBtn = await screen.findByRole("button", { name: /confirm|delete/i });
|
||||||
|
fireEvent.click(confirmBtn);
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("delete_resource", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "secrets",
|
||||||
|
namespace: "production",
|
||||||
|
resourceName: "db-creds",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ─── HPAList ──────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
describe("HPAList – action IPC uses item.namespace", () => {
|
||||||
|
const hpa: HorizontalPodAutoscalerInfo = {
|
||||||
|
name: "web-hpa",
|
||||||
|
namespace: "default",
|
||||||
|
min_replicas: 1,
|
||||||
|
max_replicas: 10,
|
||||||
|
current_replicas: 3,
|
||||||
|
desired_replicas: 3,
|
||||||
|
age: "7d",
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => vi.clearAllMocks());
|
||||||
|
|
||||||
|
it("getResourceYamlCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue("yaml: content");
|
||||||
|
render(
|
||||||
|
<HPAList hpas={[hpa]} clusterId="c1" namespace="all" />
|
||||||
|
);
|
||||||
|
openActionMenu("web-hpa");
|
||||||
|
clickMenuItem("Edit");
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("get_resource_yaml", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "horizontalpodautoscalers",
|
||||||
|
namespace: "default",
|
||||||
|
resourceName: "web-hpa",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("deleteResourceCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue(undefined);
|
||||||
|
render(
|
||||||
|
<HPAList hpas={[hpa]} clusterId="c1" namespace="all" onRefresh={() => {}} />
|
||||||
|
);
|
||||||
|
openActionMenu("web-hpa");
|
||||||
|
clickMenuItem("Delete");
|
||||||
|
const confirmBtn = await screen.findByRole("button", { name: /confirm|delete/i });
|
||||||
|
fireEvent.click(confirmBtn);
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("delete_resource", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "horizontalpodautoscalers",
|
||||||
|
namespace: "default",
|
||||||
|
resourceName: "web-hpa",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ─── PVCList ──────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
describe("PVCList – action IPC uses item.namespace", () => {
|
||||||
|
const pvc: PersistentVolumeClaimInfo = {
|
||||||
|
name: "data-pvc",
|
||||||
|
namespace: "staging",
|
||||||
|
status: "Bound",
|
||||||
|
volume: "pv-001",
|
||||||
|
capacity: "10Gi",
|
||||||
|
access_modes: ["ReadWriteOnce"],
|
||||||
|
age: "3d",
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => vi.clearAllMocks());
|
||||||
|
|
||||||
|
it("getResourceYamlCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue("yaml: content");
|
||||||
|
render(
|
||||||
|
<PVCList pvcs={[pvc]} clusterId="c1" namespace="all" />
|
||||||
|
);
|
||||||
|
openActionMenu("data-pvc");
|
||||||
|
clickMenuItem("Edit");
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("get_resource_yaml", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "persistentvolumeclaims",
|
||||||
|
namespace: "staging",
|
||||||
|
resourceName: "data-pvc",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("deleteResourceCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue(undefined);
|
||||||
|
render(
|
||||||
|
<PVCList pvcs={[pvc]} clusterId="c1" namespace="all" onRefresh={() => {}} />
|
||||||
|
);
|
||||||
|
openActionMenu("data-pvc");
|
||||||
|
clickMenuItem("Delete");
|
||||||
|
const confirmBtn = await screen.findByRole("button", { name: /confirm|delete/i });
|
||||||
|
fireEvent.click(confirmBtn);
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("delete_resource", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "persistentvolumeclaims",
|
||||||
|
namespace: "staging",
|
||||||
|
resourceName: "data-pvc",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ─── ServiceAccountList ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
describe("ServiceAccountList – action IPC uses item.namespace", () => {
|
||||||
|
const sa: ServiceAccountInfo = {
|
||||||
|
name: "app-sa",
|
||||||
|
namespace: "production",
|
||||||
|
secrets: 1,
|
||||||
|
age: "30d",
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => vi.clearAllMocks());
|
||||||
|
|
||||||
|
it("getResourceYamlCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue("yaml: content");
|
||||||
|
render(
|
||||||
|
<ServiceAccountList serviceAccounts={[sa]} clusterId="c1" namespace="all" />
|
||||||
|
);
|
||||||
|
openActionMenu("app-sa");
|
||||||
|
clickMenuItem("Edit");
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("get_resource_yaml", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "serviceaccounts",
|
||||||
|
namespace: "production",
|
||||||
|
resourceName: "app-sa",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("deleteResourceCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue(undefined);
|
||||||
|
render(
|
||||||
|
<ServiceAccountList serviceAccounts={[sa]} clusterId="c1" namespace="all" onRefresh={() => {}} />
|
||||||
|
);
|
||||||
|
openActionMenu("app-sa");
|
||||||
|
clickMenuItem("Delete");
|
||||||
|
const confirmBtn = await screen.findByRole("button", { name: /confirm|delete/i });
|
||||||
|
fireEvent.click(confirmBtn);
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("delete_resource", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "serviceaccounts",
|
||||||
|
namespace: "production",
|
||||||
|
resourceName: "app-sa",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ─── RoleList ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
describe("RoleList – action IPC uses item.namespace", () => {
|
||||||
|
const role: RoleInfo = {
|
||||||
|
name: "pod-reader",
|
||||||
|
namespace: "default",
|
||||||
|
age: "14d",
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => vi.clearAllMocks());
|
||||||
|
|
||||||
|
it("getResourceYamlCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue("yaml: content");
|
||||||
|
render(
|
||||||
|
<RoleList roles={[role]} clusterId="c1" namespace="all" />
|
||||||
|
);
|
||||||
|
openActionMenu("pod-reader");
|
||||||
|
clickMenuItem("Edit");
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("get_resource_yaml", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "roles",
|
||||||
|
namespace: "default",
|
||||||
|
resourceName: "pod-reader",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("deleteResourceCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue(undefined);
|
||||||
|
render(
|
||||||
|
<RoleList roles={[role]} clusterId="c1" namespace="all" onRefresh={() => {}} />
|
||||||
|
);
|
||||||
|
openActionMenu("pod-reader");
|
||||||
|
clickMenuItem("Delete");
|
||||||
|
const confirmBtn = await screen.findByRole("button", { name: /confirm|delete/i });
|
||||||
|
fireEvent.click(confirmBtn);
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("delete_resource", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "roles",
|
||||||
|
namespace: "default",
|
||||||
|
resourceName: "pod-reader",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ─── RoleBindingList ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
describe("RoleBindingList – action IPC uses item.namespace", () => {
|
||||||
|
const rb: RoleBindingInfo = {
|
||||||
|
name: "pod-reader-binding",
|
||||||
|
namespace: "default",
|
||||||
|
role: "pod-reader",
|
||||||
|
age: "10d",
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => vi.clearAllMocks());
|
||||||
|
|
||||||
|
it("getResourceYamlCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue("yaml: content");
|
||||||
|
render(
|
||||||
|
<RoleBindingList roleBindings={[rb]} clusterId="c1" namespace="all" />
|
||||||
|
);
|
||||||
|
openActionMenu("pod-reader-binding");
|
||||||
|
clickMenuItem("Edit");
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("get_resource_yaml", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "rolebindings",
|
||||||
|
namespace: "default",
|
||||||
|
resourceName: "pod-reader-binding",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("deleteResourceCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue(undefined);
|
||||||
|
render(
|
||||||
|
<RoleBindingList roleBindings={[rb]} clusterId="c1" namespace="all" onRefresh={() => {}} />
|
||||||
|
);
|
||||||
|
openActionMenu("pod-reader-binding");
|
||||||
|
clickMenuItem("Delete");
|
||||||
|
const confirmBtn = await screen.findByRole("button", { name: /confirm|delete/i });
|
||||||
|
fireEvent.click(confirmBtn);
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("delete_resource", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "rolebindings",
|
||||||
|
namespace: "default",
|
||||||
|
resourceName: "pod-reader-binding",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ─── NetworkPolicyList ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
describe("NetworkPolicyList – action IPC uses item.namespace", () => {
|
||||||
|
const np: NetworkPolicyInfo = {
|
||||||
|
name: "deny-all",
|
||||||
|
namespace: "production",
|
||||||
|
pod_selector: "{}",
|
||||||
|
policy_types: ["Ingress"],
|
||||||
|
age: "3d",
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => vi.clearAllMocks());
|
||||||
|
|
||||||
|
it("getResourceYamlCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue("yaml: content");
|
||||||
|
render(
|
||||||
|
<NetworkPolicyList networkpolicies={[np]} clusterId="c1" namespace="all" />
|
||||||
|
);
|
||||||
|
openActionMenu("deny-all");
|
||||||
|
clickMenuItem("Edit");
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("get_resource_yaml", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "networkpolicies",
|
||||||
|
namespace: "production",
|
||||||
|
resourceName: "deny-all",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("deleteResourceCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue(undefined);
|
||||||
|
render(
|
||||||
|
<NetworkPolicyList networkpolicies={[np]} clusterId="c1" namespace="all" onRefresh={() => {}} />
|
||||||
|
);
|
||||||
|
openActionMenu("deny-all");
|
||||||
|
clickMenuItem("Delete");
|
||||||
|
const confirmBtn = await screen.findByRole("button", { name: /confirm|delete/i });
|
||||||
|
fireEvent.click(confirmBtn);
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("delete_resource", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "networkpolicies",
|
||||||
|
namespace: "production",
|
||||||
|
resourceName: "deny-all",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ─── ResourceQuotaList ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
describe("ResourceQuotaList – action IPC uses item.namespace", () => {
|
||||||
|
const rq: ResourceQuotaInfo = {
|
||||||
|
name: "compute-resources",
|
||||||
|
namespace: "default",
|
||||||
|
request_cpu: "4",
|
||||||
|
request_memory: "8Gi",
|
||||||
|
limit_cpu: "8",
|
||||||
|
limit_memory: "16Gi",
|
||||||
|
age: "7d",
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => vi.clearAllMocks());
|
||||||
|
|
||||||
|
it("getResourceYamlCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue("yaml: content");
|
||||||
|
render(
|
||||||
|
<ResourceQuotaList resourcequotas={[rq]} clusterId="c1" namespace="all" />
|
||||||
|
);
|
||||||
|
openActionMenu("compute-resources");
|
||||||
|
clickMenuItem("Edit");
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("get_resource_yaml", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "resourcequotas",
|
||||||
|
namespace: "default",
|
||||||
|
resourceName: "compute-resources",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("deleteResourceCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue(undefined);
|
||||||
|
render(
|
||||||
|
<ResourceQuotaList resourcequotas={[rq]} clusterId="c1" namespace="all" onRefresh={() => {}} />
|
||||||
|
);
|
||||||
|
openActionMenu("compute-resources");
|
||||||
|
clickMenuItem("Delete");
|
||||||
|
const confirmBtn = await screen.findByRole("button", { name: /confirm|delete/i });
|
||||||
|
fireEvent.click(confirmBtn);
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("delete_resource", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "resourcequotas",
|
||||||
|
namespace: "default",
|
||||||
|
resourceName: "compute-resources",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ─── LimitRangeList ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
describe("LimitRangeList – action IPC uses item.namespace", () => {
|
||||||
|
const lr: LimitRangeInfo = {
|
||||||
|
name: "cpu-mem-limits",
|
||||||
|
namespace: "default",
|
||||||
|
limit_count: 3,
|
||||||
|
age: "14d",
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => vi.clearAllMocks());
|
||||||
|
|
||||||
|
it("getResourceYamlCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue("yaml: content");
|
||||||
|
render(
|
||||||
|
<LimitRangeList limitranges={[lr]} clusterId="c1" namespace="all" />
|
||||||
|
);
|
||||||
|
openActionMenu("cpu-mem-limits");
|
||||||
|
clickMenuItem("Edit");
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("get_resource_yaml", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "limitranges",
|
||||||
|
namespace: "default",
|
||||||
|
resourceName: "cpu-mem-limits",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("deleteResourceCmd receives item.namespace, not filter prop 'all'", async () => {
|
||||||
|
mockInvoke.mockResolvedValue(undefined);
|
||||||
|
render(
|
||||||
|
<LimitRangeList limitranges={[lr]} clusterId="c1" namespace="all" onRefresh={() => {}} />
|
||||||
|
);
|
||||||
|
openActionMenu("cpu-mem-limits");
|
||||||
|
clickMenuItem("Delete");
|
||||||
|
const confirmBtn = await screen.findByRole("button", { name: /confirm|delete/i });
|
||||||
|
fireEvent.click(confirmBtn);
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(mockInvoke).toHaveBeenCalledWith("delete_resource", {
|
||||||
|
clusterId: "c1",
|
||||||
|
resourceType: "limitranges",
|
||||||
|
namespace: "default",
|
||||||
|
resourceName: "cpu-mem-limits",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue
Block a user