mirror of
https://github.com/Azure/k8s-deploy.git
synced 2026-06-24 21:50:00 +08:00
360 lines
10 KiB
TypeScript
360 lines
10 KiB
TypeScript
import { getKubectlPath, Kubectl } from "./kubectl";
|
|
import * as exec from "@actions/exec";
|
|
import * as io from "@actions/io";
|
|
import * as core from "@actions/core";
|
|
import * as toolCache from "@actions/tool-cache";
|
|
import { config } from "process";
|
|
|
|
describe("Kubectl path", () => {
|
|
const version = "1.1";
|
|
const path = "path";
|
|
|
|
it("gets the kubectl path", async () => {
|
|
jest.spyOn(core, "getInput").mockImplementationOnce(() => undefined);
|
|
jest.spyOn(io, "which").mockImplementationOnce(async () => path);
|
|
|
|
expect(await getKubectlPath()).toBe(path);
|
|
});
|
|
|
|
it("gets the kubectl path with version", async () => {
|
|
jest.spyOn(core, "getInput").mockImplementationOnce(() => version);
|
|
jest.spyOn(toolCache, "find").mockImplementationOnce(() => path);
|
|
|
|
expect(await getKubectlPath()).toBe(path);
|
|
});
|
|
|
|
it("throws if kubectl not found", async () => {
|
|
// without version
|
|
jest.spyOn(io, "which").mockImplementationOnce(async () => undefined);
|
|
await expect(() => getKubectlPath()).rejects.toThrow();
|
|
|
|
// with verision
|
|
jest.spyOn(core, "getInput").mockImplementationOnce(() => undefined);
|
|
jest.spyOn(io, "which").mockImplementationOnce(async () => undefined);
|
|
await expect(() => getKubectlPath()).rejects.toThrow();
|
|
});
|
|
});
|
|
|
|
const kubectlPath = "kubectlPath";
|
|
const testNamespace = "testNamespace";
|
|
const defaultNamespace = "default";
|
|
describe("Kubectl class", () => {
|
|
|
|
describe("default namespace behavior", () => {
|
|
const kubectl = new Kubectl(kubectlPath, defaultNamespace);
|
|
const execReturn = { exitCode: 0, stdout: "Output", stderr: "" };
|
|
|
|
beforeEach(() => {
|
|
jest.spyOn(exec, "getExecOutput").mockImplementation(async () => {
|
|
return execReturn;
|
|
});
|
|
});
|
|
|
|
describe("omits default namespace from commands", () => {
|
|
it("executes a command without appending --namespace arg", async () => {
|
|
// no args
|
|
const command = "command";
|
|
expect(await kubectl.executeCommand(command)).toBe(execReturn);
|
|
expect(exec.getExecOutput).toBeCalledWith(
|
|
kubectlPath,
|
|
[command],
|
|
{ silent: false }
|
|
);
|
|
});
|
|
});
|
|
});
|
|
|
|
|
|
describe("with a success exec return in testNamespace", () => {
|
|
const kubectl = new Kubectl(kubectlPath, testNamespace);
|
|
const execReturn = { exitCode: 0, stdout: "Output", stderr: "" };
|
|
|
|
beforeEach(() => {
|
|
jest.spyOn(exec, "getExecOutput").mockImplementation(async () => {
|
|
return execReturn;
|
|
});
|
|
});
|
|
|
|
it("applies a configuration with a single config path", async () => {
|
|
const configPaths = "configPaths";
|
|
const result = await kubectl.apply(configPaths);
|
|
expect(result).toBe(execReturn);
|
|
expect(exec.getExecOutput).toBeCalledWith(
|
|
kubectlPath,
|
|
["apply", "-f", configPaths, "--namespace", testNamespace],
|
|
{ silent: false }
|
|
);
|
|
});
|
|
|
|
it("applies a configuration with multiple config paths", async () => {
|
|
const configPaths = ["configPath1", "configPath2", "configPath3"];
|
|
const result = await kubectl.apply(configPaths);
|
|
expect(result).toBe(execReturn);
|
|
expect(exec.getExecOutput).toBeCalledWith(
|
|
kubectlPath,
|
|
[
|
|
"apply",
|
|
"-f",
|
|
configPaths[0] + "," + configPaths[1] + "," + configPaths[2],
|
|
"--namespace",
|
|
testNamespace,
|
|
],
|
|
{ silent: false }
|
|
);
|
|
});
|
|
|
|
it("applies a configuration with force when specified", async () => {
|
|
const configPaths = ["configPath1", "configPath2", "configPath3"];
|
|
const result = await kubectl.apply(configPaths, true);
|
|
expect(result).toBe(execReturn);
|
|
expect(exec.getExecOutput).toBeCalledWith(
|
|
kubectlPath,
|
|
[
|
|
"apply",
|
|
"-f",
|
|
configPaths[0] + "," + configPaths[1] + "," + configPaths[2],
|
|
"--force",
|
|
"--namespace",
|
|
testNamespace,
|
|
],
|
|
{ silent: false }
|
|
);
|
|
});
|
|
|
|
it("describes a resource", async () => {
|
|
const resourceType = "type";
|
|
const resourceName = "name";
|
|
const result = await kubectl.describe(resourceType, resourceName);
|
|
expect(result).toBe(execReturn);
|
|
expect(exec.getExecOutput).toBeCalledWith(
|
|
kubectlPath,
|
|
["describe", resourceType, resourceName, "--namespace", testNamespace],
|
|
{ silent: false }
|
|
);
|
|
});
|
|
|
|
it("describes a resource silently", async () => {
|
|
const resourceType = "type";
|
|
const resourceName = "name";
|
|
const result = await kubectl.describe(resourceType, resourceName, true);
|
|
expect(result).toBe(execReturn);
|
|
expect(exec.getExecOutput).toBeCalledWith(
|
|
kubectlPath,
|
|
["describe", resourceType, resourceName, "--namespace", testNamespace],
|
|
{ silent: true }
|
|
);
|
|
});
|
|
|
|
it("annotates resource", async () => {
|
|
const resourceType = "type";
|
|
const resourceName = "name";
|
|
const annotation = "annotation";
|
|
const result = await kubectl.annotate(
|
|
resourceType,
|
|
resourceName,
|
|
annotation
|
|
);
|
|
expect(result).toBe(execReturn);
|
|
expect(exec.getExecOutput).toBeCalledWith(
|
|
kubectlPath,
|
|
[
|
|
"annotate",
|
|
resourceType,
|
|
resourceName,
|
|
annotation,
|
|
"--overwrite",
|
|
"--namespace",
|
|
testNamespace,
|
|
],
|
|
{ silent: false }
|
|
);
|
|
});
|
|
|
|
it("annotates files with single file", async () => {
|
|
const file = "file";
|
|
const annotation = "annotation";
|
|
const result = await kubectl.annotateFiles(file, annotation);
|
|
expect(result).toBe(execReturn);
|
|
expect(exec.getExecOutput).toBeCalledWith(
|
|
kubectlPath,
|
|
[
|
|
"annotate",
|
|
"-f",
|
|
file,
|
|
annotation,
|
|
"--overwrite",
|
|
"--namespace",
|
|
testNamespace,
|
|
],
|
|
{ silent: false }
|
|
);
|
|
});
|
|
|
|
it("annotates files with mulitple files", async () => {
|
|
const files = ["file1", "file2", "file3"];
|
|
const annotation = "annotation";
|
|
const result = await kubectl.annotateFiles(files, annotation);
|
|
expect(result).toBe(execReturn);
|
|
expect(exec.getExecOutput).toBeCalledWith(
|
|
kubectlPath,
|
|
[
|
|
"annotate",
|
|
"-f",
|
|
files.join(","),
|
|
annotation,
|
|
"--overwrite",
|
|
"--namespace",
|
|
testNamespace,
|
|
],
|
|
{ silent: false }
|
|
);
|
|
});
|
|
|
|
it("labels files with single file", async () => {
|
|
const file = "file";
|
|
const labels = ["label1", "label2"];
|
|
const result = await kubectl.labelFiles(file, labels);
|
|
expect(result).toBe(execReturn);
|
|
expect(exec.getExecOutput).toBeCalledWith(
|
|
kubectlPath,
|
|
[
|
|
"label",
|
|
"-f",
|
|
file,
|
|
...labels,
|
|
"--overwrite",
|
|
"--namespace",
|
|
testNamespace,
|
|
],
|
|
{ silent: false }
|
|
);
|
|
});
|
|
|
|
it("labels files with multiple files", async () => {
|
|
const files = ["file1", "file2", "file3"];
|
|
const labels = ["label1", "label2"];
|
|
const result = await kubectl.labelFiles(files, labels);
|
|
expect(result).toBe(execReturn);
|
|
expect(exec.getExecOutput).toBeCalledWith(
|
|
kubectlPath,
|
|
[
|
|
"label",
|
|
"-f",
|
|
files.join(","),
|
|
...labels,
|
|
"--overwrite",
|
|
"--namespace",
|
|
testNamespace,
|
|
],
|
|
{ silent: false }
|
|
);
|
|
});
|
|
|
|
it("gets all pods", async () => {
|
|
expect(await kubectl.getAllPods()).toBe(execReturn);
|
|
expect(exec.getExecOutput).toBeCalledWith(
|
|
kubectlPath,
|
|
["get", "pods", "-o", "json", "--namespace", testNamespace],
|
|
{ silent: true }
|
|
);
|
|
});
|
|
|
|
it("checks rollout status", async () => {
|
|
const resourceType = "type";
|
|
const name = "name";
|
|
expect(await kubectl.checkRolloutStatus(resourceType, name)).toBe(
|
|
execReturn
|
|
);
|
|
expect(exec.getExecOutput).toBeCalledWith(
|
|
kubectlPath,
|
|
[
|
|
"rollout",
|
|
"status",
|
|
`${resourceType}/${name}`,
|
|
"--namespace",
|
|
testNamespace,
|
|
],
|
|
{ silent: false }
|
|
);
|
|
});
|
|
|
|
it("gets resource", async () => {
|
|
const resourceType = "type";
|
|
const name = "name";
|
|
expect(await kubectl.getResource(resourceType, name)).toBe(execReturn);
|
|
expect(exec.getExecOutput).toBeCalledWith(
|
|
kubectlPath,
|
|
[
|
|
"get",
|
|
`${resourceType}/${name}`,
|
|
"-o",
|
|
"json",
|
|
"--namespace",
|
|
testNamespace,
|
|
],
|
|
{ silent: false }
|
|
);
|
|
});
|
|
|
|
it("executes a command", async () => {
|
|
// no args
|
|
const command = "command";
|
|
expect(await kubectl.executeCommand(command)).toBe(execReturn);
|
|
expect(exec.getExecOutput).toBeCalledWith(
|
|
kubectlPath,
|
|
[command, "--namespace", testNamespace],
|
|
{ silent: false }
|
|
);
|
|
|
|
// with args
|
|
const args = "args";
|
|
expect(await kubectl.executeCommand(command, args)).toBe(execReturn);
|
|
expect(exec.getExecOutput).toBeCalledWith(
|
|
kubectlPath,
|
|
[command, args, "--namespace", testNamespace],
|
|
{ silent: false }
|
|
);
|
|
});
|
|
|
|
it("deletes with single argument", async () => {
|
|
const arg = "argument";
|
|
expect(await kubectl.delete(arg)).toBe(execReturn);
|
|
expect(exec.getExecOutput).toBeCalledWith(
|
|
kubectlPath,
|
|
["delete", arg, "--namespace", testNamespace],
|
|
{ silent: false }
|
|
);
|
|
});
|
|
|
|
it("deletes with multiple arguments", async () => {
|
|
const args = ["argument1", "argument2", "argument3"];
|
|
expect(await kubectl.delete(args)).toBe(execReturn);
|
|
expect(exec.getExecOutput).toBeCalledWith(
|
|
kubectlPath,
|
|
["delete", ...args, "--namespace", testNamespace],
|
|
{ silent: false }
|
|
);
|
|
});
|
|
});
|
|
|
|
it("gets new replica sets", async () => {
|
|
const kubectl = new Kubectl(kubectlPath, testNamespace);
|
|
|
|
const newReplicaSetName = "newreplicaset";
|
|
const name = "name";
|
|
const describeReturn = {
|
|
exitCode: 0,
|
|
stdout: newReplicaSetName + name + " " + "extra",
|
|
stderr: "",
|
|
};
|
|
|
|
jest.spyOn(exec, "getExecOutput").mockImplementationOnce(async () => {
|
|
return describeReturn;
|
|
});
|
|
|
|
const deployment = "deployment";
|
|
const result = await kubectl.getNewReplicaSet(deployment);
|
|
expect(result).toBe(name);
|
|
});
|
|
});
|