Skip to content

Commit

Permalink
add tests and pepr format
Browse files Browse the repository at this point in the history
Signed-off-by: catsby <[email protected]>
  • Loading branch information
catsby committed Dec 18, 2024
1 parent 72bd72c commit 1783349
Showing 1 changed file with 103 additions and 78 deletions.
181 changes: 103 additions & 78 deletions src/pepr/operator/controllers/network/generators/kubeNodes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,17 @@ import { beforeEach, beforeAll, describe, expect, it, jest } from "@jest/globals
import {
initAllNodesTarget,
nodeCIDRs,
// updateKubeNodesFromCreateUpdate,
// updateKubeNodesFromDelete,
updateKubeNodesFromCreateUpdate,
updateKubeNodesFromDelete,
} from "./kubeNodes";
import { K8s, kind } from "pepr";
// import { Component, setupLogger } from "../../../../logger";
import { V1NetworkPolicyList } from "@kubernetes/client-node";
import { anywhere } from "./anywhere";

type KubernetesList<T> = {
items: T[];
};

// // Mock logger if needed
// jest.mock("../../../../logger", () => ({
// Component: { OPERATOR_GENERATORS: "OPERATOR_GENERATORS" },
// setupLogger: () => ({
// info: jest.fn(),
// warn: jest.fn(),
// error: jest.fn(),
// debug: jest.fn(),
// }),
// }));

jest.mock("pepr", () => {
const originalModule = jest.requireActual("pepr") as object;
return {
Expand Down Expand Up @@ -61,6 +51,30 @@ describe("kubeNodes module", () => {
],
};

const mockNetworkPolicyList: V1NetworkPolicyList = {
apiVersion: "networking.k8s.io/v1",
kind: "NetworkPolicyList",
items: [
{
apiVersion: "networking.k8s.io/v1",
kind: "NetworkPolicy",
metadata: {
name: "example-policy",
namespace: "default",
},
spec: {
podSelector: {}, // required field
policyTypes: ["Egress"], // or ["Ingress"], or both
egress: [
{
to: [{ ipBlock: { cidr: "0.0.0.0/0" } }], // an IP we don't want
},
],
},
},
],
};

const mockK8sGetNodes = jest.fn<() => Promise<KubernetesList<kind.Node>>>();
const mockGetNetworkPolicies = jest.fn<() => Promise<KubernetesList<kind.NetworkPolicy>>>();
const mockApply = jest.fn();
Expand All @@ -77,13 +91,6 @@ describe("kubeNodes module", () => {

beforeEach(() => {
jest.clearAllMocks();
(K8s as jest.Mock).mockImplementation(() => ({
Get: mockK8sGetNodes,
WithLabel: jest.fn(() => ({
Get: mockGetNetworkPolicies,
})),
Apply: mockApply,
}));
});

describe("initAllNodesTarget", () => {
Expand All @@ -100,74 +107,92 @@ describe("kubeNodes module", () => {
]),
);
});

// it("should handle errors and default to anywhere if no nodes", async () => {
// mockK8sGetNodes.mockRejectedValueOnce(new Error("Network Error"));
// await initAllNodesTarget();
// const cidrs = nodeCIDRs();
// // Expect fallback to anywhere
// expect(cidrs).toEqual([{ ipBlock: { cidr: "0.0.0.0/0" } }]);
// });
});

describe("nodeCIDRs", () => {
it("should return CIDRs for currently known nodes", async () => {
mockK8sGetNodes.mockResolvedValue(mockNodeList);
it("should return anywhere if no nodes known", async () => {
mockK8sGetNodes.mockResolvedValue({ items: [] });
await initAllNodesTarget();
const cidrs = nodeCIDRs();
expect(cidrs).toHaveLength(2);
// expect it to match "anywhere"
expect(cidrs).toEqual([anywhere]);
});
});

describe("updateKubeNodesFromCreateUpdate", () => {
it("should add a node IP if node is ready", async () => {
mockK8sGetNodes.mockResolvedValueOnce({ items: [] });
mockGetNetworkPolicies.mockResolvedValue(mockNetworkPolicyList);
await initAllNodesTarget(); // start empty
await updateKubeNodesFromCreateUpdate(mockNodeList.items[0]);
let cidrs = nodeCIDRs();
expect(cidrs).toHaveLength(1);
expect(cidrs[0].ipBlock?.cidr).toBe("10.0.0.1/32");
expect(mockApply).toHaveBeenCalled();

await updateKubeNodesFromCreateUpdate(mockNodeList.items[1]);
cidrs = nodeCIDRs();
expect(cidrs).toHaveLength(2);
expect(cidrs[1].ipBlock?.cidr).toBe("10.0.0.2/32");
expect(mockApply).toHaveBeenCalled();
});

it("should return anywhere if no nodes known", async () => {
mockK8sGetNodes.mockResolvedValue({ items: [] });
await initAllNodesTarget();
it("should not add a node IP if node not ready", async () => {
const notReadyNode = {
metadata: { name: "node3" },
status: {
addresses: [{ type: "InternalIP", address: "10.0.0.3" }],
conditions: [{ type: "Ready", status: "False" }],
},
};
mockK8sGetNodes.mockResolvedValueOnce({ items: [] });
await initAllNodesTarget(); // start empty
await updateKubeNodesFromCreateUpdate(notReadyNode);
const cidrs = nodeCIDRs();
expect(cidrs).toEqual([{ ipBlock: { cidr: "0.0.0.0/0" } }]);
expect(cidrs).toEqual([anywhere]);
expect(mockApply).toHaveBeenCalled(); // Still called to update polices even if empty
});

it("should remove a node that's no longer ready", async () => {
mockK8sGetNodes.mockResolvedValue(mockNodeList);
await initAllNodesTarget();
let cidrs = nodeCIDRs();
// Should have two IPs from mockNodeList
expect(cidrs).toHaveLength(2);
expect(cidrs).toEqual(
expect.arrayContaining([
{ ipBlock: { cidr: "10.0.0.1/32" } },
{ ipBlock: { cidr: "10.0.0.2/32" } },
]),
);

const notReadyNode = {
metadata: { name: "node2" },
status: {
addresses: [{ type: "InternalIP", address: "10.0.0.1" }],
conditions: [{ type: "Ready", status: "False" }],
},
};
await updateKubeNodesFromCreateUpdate(notReadyNode);
cidrs = nodeCIDRs();
expect(cidrs).toHaveLength(1);
expect(cidrs).toEqual(expect.arrayContaining([{ ipBlock: { cidr: "10.0.0.2/32" } }]));
expect(mockApply).toHaveBeenCalled(); // Still called to update polices even if empty
});
});

// describe("updateKubeNodesFromCreateUpdate", () => {
// it("should add a node IP if node is ready", async () => {
// mockK8sGet.mockResolvedValueOnce({ items: [] });
// await initAllNodesTarget(); // start empty
// await updateKubeNodesFromCreateUpdate(mockNodeList.items[0]);
// const cidrs = nodeCIDRs();
// expect(cidrs).toHaveLength(1);
// expect(cidrs[0].ipBlock?.cidr).toBe("10.0.0.1/32");
// expect(mockK8sApply).toHaveBeenCalled();
// });

// it("should not add a node IP if node not ready", async () => {
// const notReadyNode = {
// metadata: { name: "node3" },
// status: {
// addresses: [{ type: "InternalIP", address: "10.0.0.3" }],
// conditions: [{ type: "Ready", status: "False" }],
// },
// };
// mockK8sGet.mockResolvedValueOnce({ items: [] });
// await initAllNodesTarget(); // start empty
// await updateKubeNodesFromCreateUpdate(notReadyNode);
// const cidrs = nodeCIDRs();
// expect(cidrs).toEqual([{ ipBlock: { cidr: "0.0.0.0/0" } }]); // no change
// expect(mockK8sApply).toHaveBeenCalled(); // Still called to update polices even if empty
// });
// });

// describe("updateKubeNodesFromDelete", () => {
// it("should remove the node IP from nodeSet", async () => {
// mockK8sGet.mockResolvedValueOnce(mockNodeList);
// await initAllNodesTarget();
// const cidrsBeforeDelete = nodeCIDRs();
// expect(cidrsBeforeDelete).toHaveLength(2);

// await updateKubeNodesFromDelete(mockNodeList.items[0]);
// const cidrsAfterDelete = nodeCIDRs();
// expect(cidrsAfterDelete).toHaveLength(1);
// expect(cidrsAfterDelete[0].ipBlock?.cidr).toBe("10.0.0.2/32");
// expect(mockK8sApply).toHaveBeenCalled();
// });
// });
describe("updateKubeNodesFromDelete", () => {
it("should remove the node IP from nodeSet", async () => {
mockK8sGetNodes.mockResolvedValueOnce(mockNodeList);
await initAllNodesTarget();
const cidrsBeforeDelete = nodeCIDRs();
expect(cidrsBeforeDelete).toHaveLength(2);

await updateKubeNodesFromDelete(mockNodeList.items[0]);
const cidrsAfterDelete = nodeCIDRs();
expect(cidrsAfterDelete).toHaveLength(1);
expect(cidrsAfterDelete[0].ipBlock?.cidr).toBe("10.0.0.2/32");
expect(mockApply).toHaveBeenCalled();
});
});
});

0 comments on commit 1783349

Please sign in to comment.